ソフトウェア開発」カテゴリーアーカイブ

Whisper.cppがビルドできない

音声の文字起こしは色々あるとは思いますが、ローカルで実行しようと考えた場合に選択肢として上がるのはWhisper.cppではないでしょうか

https://github.com/ggml-org/whisper.cpp

環境としては、様々な環境で動作可能な形なので手元のWindowsで実行しようとしているのですがうまくいきません・・・。

Quick start にある下記コマンドがエラーになってしまうんですよね。

cmake -B build
CMake Deprecation Warning at CMakeLists.txt:1 (cmake_minimum_required):
  Compatibility with CMake < 3.10 will be removed from a future version of
  CMake.

  Update the VERSION argument <min> value.  Or, use the <min>...<max> syntax
  to tell CMake that the project requires at least <min> but has been updated
  to work with policies introduced by <max> or earlier.


-- The C compiler identification is MSVC 19.43.34810.0
-- The CXX compiler identification is MSVC 19.43.34810.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - failed
-- Check for working C compiler: C:/Program Files (x86)/Microsoft Visual Studio/2022/BuildTools/VC/Tools/MSVC/14.43.34808/bin/Hostx64/x64/cl.exe
-- Check for working C compiler: C:/Program Files (x86)/Microsoft Visual Studio/2022/BuildTools/VC/Tools/MSVC/14.43.34808/bin/Hostx64/x64/cl.exe - broken
CMake Error at C:/Program Files/CMake/share/cmake-4.0/Modules/CMakeTestCCompiler.cmake:67 (message):
  The C compiler

    "C:/Program Files (x86)/Microsoft Visual Studio/2022/BuildTools/VC/Tools/MSVC/14.43.34808/bin/Hostx64/x64/cl.exe"

  is not able to compile a simple test program.

  It fails with the following output:

    Change Dir: 'C:/Dev/whisper.cpp/build/CMakeFiles/CMakeScratch/TryCompile-eelwlp'

    Run Build Command(s): "C:/Program Files/CMake/bin/cmake.exe" -E env VERBOSE=1 nmake -f Makefile /nologo cmTC_a73a9\fast
        "C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\VC\Tools\MSVC\14.43.34808\bin\Hostx64\x64\nmake.exe"  -f CMakeFiles\cmTC_a73a9.dir\build.make /nologo -L                  CMakeFiles\cmTC_a73a9.dir\build
    Building C object CMakeFiles/cmTC_a73a9.dir/testCCompiler.c.obj
        "C:\Program Files\CMake\bin\cmake.exe" -E cmake_cl_compile_depends --dep-file=CMakeFiles\cmTC_a73a9.dir\testCCompiler.c.obj.d --working-dir=C:\Dev\whisper.cpp\build\CMakeFiles\CMakeScratch\TryCompile-eelwlp --filter-prefix="メモ: インクルード ファイル:  " -- C:\PROGRA~2\MICROS~3\2022\BUILDT~1\VC\Tools\MSVC\1443~1.348\bin\Hostx64\x64\cl.exe @C:\Users\krote\AppData\Local\Temp\nmDA0F.tmp
    testCCompiler.c
    Linking C executable cmTC_a73a9.exe
        "C:\Program Files\CMake\bin\cmake.exe" -E vs_link_exe --msvc-ver=1943 --intdir=CMakeFiles\cmTC_a73a9.dir --rc=rc --mt=CMAKE_MT-NOTFOUND --manifests -- C:\PROGRA~2\MICROS~3\2022\BUILDT~1\VC\Tools\MSVC\1443~1.348\bin\Hostx64\x64\link.exe /nologo @CMakeFiles\cmTC_a73a9.dir\objects1.rsp @C:\Users\krote\AppData\Local\Temp\nmDA8D.tmp
    Visual Studio Incremental Link with embedded manifests
    Create CMakeFiles\cmTC_a73a9.dir/manifest.rc
    Create empty: CMakeFiles\cmTC_a73a9.dir/embed.manifest
    RC Pass 1:
    rc /fo CMakeFiles\cmTC_a73a9.dir/manifest.res CMakeFiles\cmTC_a73a9.dir/manifest.rc
    RC Pass 1: command "rc /fo CMakeFiles\cmTC_a73a9.dir/manifest.res CMakeFiles\cmTC_a73a9.dir/manifest.rc" failed (exit code 0) with the following output:
    no such file or directoryNMAKE : fatal error U1077: '"C:\Program Files\CMake\bin\cmake.exe" -E vs_link_exe --msvc-ver=1943 --intdir=CMakeFiles\cmTC_a73a9.dir --rc=rc --mt=CMAKE_MT-NOTFOUND --manifests -- C:\PROGRA~2\MICROS~3\2022\BUILDT~1\VC\Tools\MSVC\1443~1.348\bin\Hostx64\x64\link.exe /nologo @CMakeFiles\cmTC_a73a9.dir\objects1.rsp @C:\Users\krote\AppData\Local\Temp\nmDA8D.tmp' : リターン コード '0xffffffff'
    Stop.
    NMAKE : fatal error U1077: '"C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\VC\Tools\MSVC\14.43.34808\bin\Hostx64\x64\nmake.exe"  -f CMakeFiles\cmTC_a73a9.dir\build.make /nologo -L                  CMakeFiles\cmTC_a73a9.dir\build' : リターン コード '0x2'
    Stop.

エラーメッセージからは”C:\Program Files\CMake\bin\cmake.exe”が存在しないようにも見えますが、ファイルとしてはいるんですよね。

うーん、なんだかんだ言って、プログラミングよりもこういう環境構築のほうが時間かかるし、精神力をごっそり持っていかれますね。。

Claude codeを少し使ってみた感想

先日セットアップしたClaude code。
個人開発プロジェクトとして作っている、Electronアプリで色々とプロンプトを試しています。
面白いです

自分でコードして、ビルドしてみたら失敗して、調整して、、、って繰り返すのを見ていると、いや、本当人間っぽいなと思ってしまいます。

ただ、コーディングスピードは流石に早く、それなりのボリュームを持った作業をさせると、一度に大量のコードが書かれるために、正直これを読んでいたらこういうツールを使っている意味が薄くなりそうだなと思いました。

動かしてみてうまくいかなければ、それはコードを確認するのではなくプロンプトで指示を投げるような形でしょうか。
そういう意味で、変なデグレードをなくすためにテストコードを書かせながら進めることが大事になりそうです。

一方で、何かしらトラブルが有るたびにプロンプトで指示を与えるということが本当に正しいやり方なんだっけ?と思うと必ずしもそうではなく、コードを読まないといけないシーンはそれなりにあるはず。
そう考えると、コーディングなどに対する理解は必要で。。。いや、それすらプロンプトでAIによるコードの解説を受けながら問題を特定するようになるのだろうか・・・?
うーん、そのほうが現実的なのかもしれない。

誰がどの程度使うことになるのか?

そう考えると、若手に使わせたほうがチームの生産性は上がるかもしれないが一方で学ぶ機会を失うことにもなりかねない懸念はあります。

また、全員が使うのか・・・?協力会社さんがいる場合は・・・?

使ったほうが生産性やスピードが上る可能性は高い一方で、使いこなせないとひたすらプロンプトを打ち続けることになり課金額がそれなりに行くことが考えられます。

もちろん、人件費のほうが高いケースが多いとは思いますが、必要最低限なプロンプトで最大の結果を得るような評価基準が将来のエンジニア評価で用いられる可能性もありそうです。

手でコードを書くという行為と、AIにコード生成させるという行為。
ケースによって違うとは思いますが、このあたりのバランスは試行錯誤を通じて作り上げていく必要があるのかもしれません。

useEffect, useCallback, useMemoに関しての使い分け

Claudeに課金をしたので、先日より取り組んでいるElectron製のアプリをちまちまと助けを借りながらいじっているのですが、

まずは、提示された内容を元に書き写すような形で進めています。

その中で、AIあるあると言えばあるある何でしょうけれど、生成されるコードがコロコロ変わる問題にぶち当たっています。

結局のところ、目的を達成する上でプログラミングの書き方としては複数のやり方があって、その背景をAIに伝えない限りはどの手法が適切なのかはわからず、その生成されるコードが変わるわけですね。

言葉で言ってしまえば、そりゃそうなんだけど、なかなかのストレスです。
完全に任せるわけではない、AIサポートの開発における難しさを感じますね。。。

こういうものを見ていると、結局コードに関しての知識は必要になりそうだな、という気がしてきます。

というわけで、今回は自分の学習記録として、useEffectとuseCallback。そして調べているうちに出てきたuseMemoに関して書いてみようと思います。

useEffect – 副作用の管理

特徴

  • コンポーネントのレンダリング後に実行される
  • DOM操作、データフェッチング、購読、タイマーなどの副作用を扱う
  • クリーンアップ関数を返すことで、コンポーネントのアンマウント時や依存配列の値が変わる前に実行される処理を定義できる

使用例

import React, { useState, useEffect } from 'react';

function UserProfile({ userId }) {
  const [user, setUser] = useState(null);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    // 副作用: APIからデータをフェッチ
    setLoading(true);

    // userIdが変わるたびに新しいユーザーデータを取得
    fetch(`https://api.example.com/users/${userId}`)
      .then(response => response.json())
      .then(data => {
        setUser(data);
        setLoading(false);
      });

    // クリーンアップ関数
    return () => {
      // コンポーネントのアンマウント時やuserIdが変わる前に実行
      console.log('User profile cleanup');
    };
  }, [userId]); // 依存配列: userIdが変わったときだけ実行

  if (loading) return <div>Loading...</div>;
  return (
    <div>
      <h1>{user.name}</h1>
      <p>{user.email}</p>
    </div>
  );
}

いつ使うべきか

  • 外部データの取得
  • イベントリスナーの設定と解除
  • DOM要素の直接操作
  • タイマーの設定とクリア
  • 外部サービスへの購読と解除

useCallback – 関数のメモ化

特徴

  • 関数をメモ化し、不要な再生成を防ぐ
  • 依存配列の値が変わるまで、同じ関数インスタンスを保持する
  • 子コンポーネントに渡す関数のパフォーマンス最適化に役立つ

使用例

import React, { useState, useCallback } from 'react';

// 子コンポーネント(React.memoでメモ化)
const ExpensiveList = React.memo(({ items, onItemClick }) => {
  console.log('ExpensiveList rendered');
  return (
    <ul>
      {items.map(item => (
        <li key={item.id} onClick={() => onItemClick(item.id)}>
          {item.name}
        </li>
      ))}
    </ul>
  );
});

function ItemManager() {
  const [items, setItems] = useState([
    { id: 1, name: '項目1' },
    { id: 2, name: '項目2' },
  ]);

  const [count, setCount] = useState(0);

  // useCallbackを使用して関数をメモ化
  const handleItemClick = useCallback((id) => {
    console.log(`Item ${id} clicked`);
  }, []); // 空の依存配列: 関数は再作成されない

  return (
    <div>
      <h1>アイテム管理</h1>
      <ExpensiveList items={items} onItemClick={handleItemClick} />
      <div>
        <p>カウント: {count}</p>
        <button onClick={() => setCount(count + 1)}>
          カウント増加
        </button>
      </div>
    </div>
  );
}

いつ使うべきか

  • `React.memo`でラップされた子コンポーネントに関数を渡す場合
  • `useEffect`の依存配列に関数を含める場合
  • イベントハンドラーが複雑で、不要な再作成を避けたい場合
  • 関数が他のフックの依存関係になっている場合

useMemo – 値のメモ化

特徴

  • 計算結果をメモ化し、不要な再計算を防ぐ
  • 依存配列の値が変わるまで、前回の計算結果を再利用する
  • 計算コストが高い処理の最適化に特に役立つ

使用例

import React, { useState, useMemo } from 'react';

function ExpensiveCalculation({ numbers }) {
  const [count, setCount] = useState(0);

  // 計算コストが高い処理をuseMemoでメモ化
  const sumResult = useMemo(() => {
    console.log('Heavy calculation running...');
    // 重い計算の例
    return numbers.reduce((total, num) => {
      // 人為的に処理を重くする
      for (let i = 0; i < 1000000; i++) {}
      return total + num;
    }, 0);
  }, [numbers]); // 依存配列: numbersが変わった時だけ再計算

  return (
    <div>
      <h2>計算結果: {sumResult}</h2>
      <p>カウント: {count}</p>
      <button onClick={() => setCount(count + 1)}>
        カウント増加(計算には影響しない)
      </button>
    </div>
  );
}

function App() {
  const [numbers, setNumbers] = useState([1, 2, 3, 4, 5]);
  return (
    <div>
      <ExpensiveCalculation numbers={numbers} />
      <button onClick={() => setNumbers([...numbers, numbers.length + 1])}>
        数字を追加
      </button>
    </div>
  );
}

いつ使うべきか

  • 計算コストが高い処理の結果をキャッシュしたい場合
  • レンダリングごとに再生成したくないオブジェクトがある場合
  • 大きな配列やオブジェクトの変換や加工を行う場合
  • コンポーネントの再レンダリングが頻繁に発生する場合

まとめ

結局のところ、どこまでキャッシュさせることが可能な内容何だっけ?ってところなんでしょうね。

計算コストが高くても、再レンダリングが頻繁に発生しようとも、表示内容が再計算必要なものであればuseEffectにするしかないんだろうし。。。くらいに覚えておくことにします!

Tailwindcssの適用にてんやわんや

Electronのプロジェクト構成として、Next.jsをフロントエンドに選択。
CSSとしてはTailwindcssを適用しようとしていたのですが、見様見真似でやっているものの、動いているコードを見る限り正常にTailwidがあたっているように見えない。

ということで、もう一度インストールから見直してみることに。

$ npm install -D tailwindcss autoprefixer postcss

インストール自体は上記コマンドで問題なくインストールできているようです。
これに、初期化するコマンドが必要となるのですが

$ npx tailwindcss init -p
npm error could not determine executable to run
npm error A complete log of this run can be found in: /XXXXX

というようにエラーが出ていることがわかりました。

おかしい。。。Claudeに聞いてみてもセットアップの仕方は上記コマンドで問題ないはずなのですが、、、と調べてみるとどうやらtailwindcssのv4系ではセットアップ方法が変わったようで、上記のコマンドはv3系のもののよう。

そんなわけで、一旦インストールするtailwindcssをv3系にしてみます

$ npm install -D tailwindcss@3.4.17 autoprefixer postcss
$ npx tailwindcss init -p

上記でエラーが解消されました。

v4系のセットアップは、ViteかPostCSSなどによってやり方が変わっているよう。

もう、頭から引っかかりまくっているので大変です。。。
やっぱりフロントエンドは中途半端に手を出すときっついです。

Electron + Next.js + TypeScript

Electronを利用してのアプリケーション開発で、いくつかの選択肢が存在するけれど、どうせならNext.jsやTypeScriptを使ってみたいと思っていた。

いくつか探したところ、ちょうどいいサンプルがあったのでそれをベースにアプリを作ることにする

Electron with Typescript application example
https://github.com/vercel/next.js/tree/canary/examples/with-electron-typescript

利用の方法はReadmeにかかれているが、下記のような形(プロジェクト名をelectron-exampleにした場合
npx, yarn , pnpmそれぞれ書かれている

npx create-next-app --example with-electron-typescript electron-example
yarn create next-app --example with-electron-typescript electron-example
pnpm create next-app --example with-electron-typescript electron-example

これで作られるフォルダ構成としてはざっくりこんな感じ

npm run devを実行してみると

起動した。

ハマったこと

Electron超初心者のわたしがハマったこととしては、、build後のフォルダ構成が下記のように増えたことだった。

今振り返って考えてみると、これはTypeScriptをコンパイルしてできたファイルになるので、それらは管理対象外なんですよね。

チュートリアルやQiitaを見ながらいじっていたので、main/index.jsやそれをコピーしてmain/main.js等としたりしていたので全然動きませんでした。

それらを考えるとコンパイルによって自動生成されるコードはGithubの対象外にするべきなので、gitignoreは下記を追加しています

/.next/
/out/
main
dist
renderer/.next
renderer/out

修正してもビルドしたらもとに戻ったり、思ったものが表示されなかったりと、余計な時間を使ってしまいましたが、ようやくスタートできそう

デザインシステム構築の実践イベントに参加してきた

3月7日に表参道スパイラルホールで開催されたFigmaJapan社主催のイベント「スケーラブルなデザインシステム構築の実践」というイベントに縁があって参加してきました

https://designsystem102.splashthat.com/TW

デザインシステム。
フロントエンドの世界を主戦場としているわけではないのですが、言葉自体は把握していて、主には mozaic.fm というPodcastでよく話に上がっているので気になっていました。

デザインが特に意識されるのはToCの分野が多い認識でToBに関してはあまり必要性が認識されていない事が多い。
前職でもよくあったのが、画面にできるだけ情報を詰め込むような形。

結局これは、もともと使っていた画面や紙がそれだけの情報量を一目で見ることができ、それを用いた業務にユーザが最適化していることに起因していると思う。
画面を分割したりスクロールやタブが発生すると業務効率が落ちるというクレームが入る。

ただ、その流れは確実に変わってきていると思っていて、それは何よりもユーザがスマホやタブレット端末を日常使いするようになり、デザイン要素を取り込んだアプリケーションに慣れてきたという側面が強いのではないかと思っている。

そんなわけで、これからアプリケーション開発を行っていくうえでデザインシステムの構築みたいなものというのは、どういうシーンで必要で強みになり、どういうシーンでは逆に不要となるのだろうか?というのが自分の中での問いになった。

そんなモヤモヤしながらもしっかりと学習していない中でたまたまFigmaJapan社の方とメールする機会あり、本イベントを紹介いただいたのでホイホイと参加してみた。

こちらのイベントは後ほどYoutubeへ公開されるということなので、興味がある方はFigmaJapanさんの公式Xを追っていると出てくると思う。

実践編ということだけあって、登壇されたYahoo!社もHonda社も少し規模が違いすぎる感覚だった。
そもそも、自社プロダクトを持っているわけでもない立ち位置での話なので、デザインシステムの構築をお手伝いする立場?請負でそれを適用する??
そもそもデザインシステムを作ったこともないのに??

自分の立ち位置にツッコミどころ満載である。

うーん、面白そうで大事そうではあるけれど、やはりちゃんと理解して腹落ちするところから進めないとダメだろうな、、、ということでこちらのYoutubeを一旦見ておこう。
そのうえで公開されるであろう今回のイベントを見返してみたいと思う。

Electronを触り始めた

ちょっと秘匿性の高いデータを取り扱うアプリケーションを作りたくなって、そう考えるとWebアプリは面倒かもな?と。

かといってAccessで作るのも手軽なんだけど芸がないな~と思ってElectronに手を出してみた

https://www.electronjs.org/ja

概要レベルは知っていたけれど、実際にコードを見て改めて面白いな、と思った

スタンドアロンのアプリケーションとなるのだから、いわゆるフロントエンドとバックエンドが一つになっているんだけど、ElectronはそれをWebの技術を使って実装している。

つまりは、一つのアプリケーションにNode.jsで作られたバックエンドであるメインプロセスと、Web技術。ReactやViewなどが利用可能なレンダラープロセスが明確に分離されて存在している。

そして、それらをpreload.jsでつなぎ合わせている。

通常httpなどでそれらをつなぐことになる部分はipcが唯一の通信手段として存在している。。と。

面白い仕組みだ。

悩ましいな、と思うのはいわゆるAIを用いたコーディングスタイルを考えるとこのあたりの仕組みの理解をすっ飛ばしてものができてしまうんですよね。
結果論で言えばそれで問題なくものが作られる世界であればそれはそれで効率のいい話ではあるんだけど、、、

とりあえず、最近ろくにフロントエンドに携わっていないのでNext.jsとかどこまでできるんだろう?という不安はあるものの、やれる範囲まで頑張ってみようかと思っています

Fly.io のAppを削除する

Obsidian の Self-hosted LiveSync をFly.ioで作ろうとしたものの、App作成スクリプトの使い方を誤っていたようで、作り直す必要が生じてしまった。

基本的にFly.ioはCLIからの操作になるのだが、削除自体はDashboardからできるようだった

ログインすると、登録されているAppが表示されている。
Obsidian用に1GBのDBが構築されているのがわかる

Appを選択して、左下の「Settings」を選択する

「Delete app」を選択すれば削除ができる。

アプリケーションの削除が設定ページにあるという発送に思いつかず、結構探し回ってしまった。

これで削除が完了して、余計なインスタンスを維持する必要もなくなって安心。安心。

Garminが充電できなくなった

早いよ。早いよダニー

購入してまだ一月も経っていないのに、Garminが充電できなくなってしまった。
正確に言うと、一瞬充電中のマークはつくけれどすぐに消えてしまうような感じ。
すごい接触不良臭い。

接触不良だと仮定して、充電ケーブル側の問題なのか、時計側の問題なのかの二択になるはず。
と、充電ケーブルを見てみると・・・

ちょっと分かりづらいかもしれないですが、一番手前のピンが他のピンと比べて短い用に見える。なんか変。

もともとの状態がわからないので確証はないけれど、これじゃないかな?とネットで調べてみると。。。

GARMIN(ガーミン)充電できないときにやるべき3つのこと【解決策】
https://cediablog.com/garmin_battery_checkpoint

上記ブログでまさに同じような状態になっている写真が。
これは確定ではないだろうか。

保証期間内なので公式の修理に出してもいいんだけど、修理に出すにはあれこれ手順が必要そうな気がする。
その間、Garminと離れ離れになるのは耐えられない(恋人気分)

というわけで、Amazonで充電ケーブルをポチった

2枚 L字型 ガーミン 充電ケーブルGarmin Watch用充電器 USB C充電ケーブル

公式の充電ケーブルは、Garminに差し込むと浮いてしまうのだけど、このケーブルはL字型になっているので充電中の姿勢が安心感がある。

というか、公式のケーブルでピンが折れてしまったりするのは充電中に変な負荷がかかってしまうのが原因なのではないだろうか?
そんなことまで思えてしまう。

なにはともあれ、バッテリーが切れるギリギリセーフなタイミングでケーブルが届いたので、電源オフになることなく充電することが出来ました。

さて、公式のケーブルに文句をいうか悩むところですね。。。
すでに原因の特定と回避策を実施してしまった手前、別にいいかなという気もする。
でも、せっかくなので公式の反応を見てみてもいいかもしれない。
お金かかってしまっているわけだし。

でも、時計側を送ってくれとか言われたら涙目になりそう

Watch Face を作ってみたい

Garmin の Watch face はConnectIQアプリで入手することができるのですが、有料のものが多いのと、ちょっとごちゃごちゃしすぎる感じがします。

かといって、文字盤を自作することができるとして用意されているFaceItは項目数的にしょぼい。

であれば、自作することが出来ないだろうか?と思って調べてみるとVSCodeで開発環境を作ることができるということだったので、まずは開発環境を整えてみた

前提

VSCodeインストール済み
Javaインストール済み

公式の環境作成に関するページはこちら
https://developer.garmin.com/connect-iq/connect-iq-basics/getting-started/

SDKインストール

SDK取得のページからSDK Managerをダウンロード。起動する。
基本的にポチポチと進めていくことでSDKをインストールすることが出来た。
バージョンに関しては、執筆時点では 7.4.3が最新のようなのでこちらをCurrentとする

無事にインストールが済んだら、続いてVSCodeに拡張を追加していく

VCSCodeへのインストールと設定

VSCodeのExtensionとして「Monkey C」を検索、インストールする。
その後、VSCodeを再起動してコマンドパレット(Ctrl+Shift+P)から「Generating a developer Key」を選択。適当なフォルダを選択してKeyを出力する。

その後、Monkey C : New Projectを選択します

プロジェクト名を適当に入力。
WatchFaceなので安直にface1とかにしてみました

続いて、なんのプロジェクトかを選択します。
ここではWatch Faceですが、その他の選択肢が若干気になりますね。。。

テンプレートとしては、Settingもできたほうがいいと考えて「Simple with Settings」を選択します。

対応するAPIレベルを選択します。
APIレベルに関しては、どの機種がどのレベルを対応しているかの一覧が公式にあるので、必要に応じて選ぶことになります。

得に今回は複数の機種での用途を考えないので自分が持っている265が5.0.0だったのでそれを選択してみました

どの製品を対象とするのかを選択します。
このあたりはシミュレーターやストアへの公開時設定に影響を及ぼしそうです

無事、プロジェクトを作ることが出来ました。

Run and Debugをそのまま押下すると。。

無事にシミュレータも起動させることが出来ました!

ちょっと遊んでみたいと思います!