本文を読み飛ばす

LSPにclangdを使ってPocketSDRのソースを読む

動機

VSCodeでPocketSDRのコードを読んでいる。 MSのC/C++拡張 (cpptools) は変数や関数のジャンプがやたらと遅い。 そこで、clangdを使うことにした。

手順

makefileの変更

makefileに直に書かれている make$(MAKE) に変更する。 サブモジュールのライブラリのmakefileも。

compile_commands.json の生成

PATHに C:msys64mingw64bin がある状態で、PowerShellやcmdで mingw32-make > build.log 2>&1 でmakefileを実行する。 (makeのログにあるパスがcygpathを経由せず、素のWindowsのパスとして出力されるようにする) 念のため -j は付けず、 make clean して実行するのが良いかもしれない (考えればわかる)。

compiledb --parse build.log --full-pathcompile_commands.json を生成する。

この際、コンパイラのフルパスはPATHで最初に解決されたものになることに注意。 実際に使ったコンパイラと一致しているか確認。

VSCodeのclasgd拡張で読み込み

settings.json--query-driver を指定する。 compiledbが出力するコンパイラのフルパスではgccやg++の拡張子が .EXE と大文字になることがある。 --query-driver に書いたパスが小文字だと検出されない(?)ようで、いろいろ考えるのが面倒だったためワイルドカードを用いた。 もしかしたら勘違いかもしれない。 また、余計なものが入る可能性があるため、地道に列挙しても良い。

"clangd.arguments": [
    "--query-driver=C:\\msys64\\mingw64\\bin\\g*",
    "--clang-tidy",
    "--log=verbose"
],

clangdが mingw64/bin をPATHに持つ環境で起動するようにする。 色々と方法はあるが、ここではGoでラッパーを書いてそれを呼び出すようにした (Goは未経験だがAIに頼んだらGoで出してきた) 。 なお、実行ファイルでないとエラーが出る。

ラッパーのスクリプト

package main

import (
    "os"
    "os/exec"
    "strings"
)

func main() {
    clangd := `C:\Program Files\LLVM\bin\clangd.exe`
    path := os.Getenv("PATH")
    add := `C:\msys64\mingw64\bin`
    if !strings.Contains(strings.ToLower(`;`+path+`;`), `;`+strings.ToLower(add)+`;`) {
        path = add + `;` + path
    }
    cmd := exec.Command(clangd, os.Args[1:]...)
    cmd.Env = append(os.Environ(), "PATH="+path)
    cmd.Stdin, cmd.Stdout, cmd.Stderr = os.Stdin, os.Stdout, os.Stderr
    if err := cmd.Run(); err != nil {
        os.Exit(1)
    }
}

コンパイルコマンド

mkdir clangd_env
cd clangd_env
# コードを書いたら
go mod init example.com/claangd_env
go build -o clangd_env.exe clangd_env.go

settings.json

"clangd.path": "${workspaceFolder}/clangd_env/clangd_env.exe",

.clangd を書く。 必須なのは CompilationDatabase で、 compile_commands.json があるディレクトリを指定する。

CompileFlags:
  CompilationDatabase: PocketSDR/lib/build
  # BuiltinHeaders: QueryDriver
Index:
  Background: Build
Completion:
  HeaderInsertion: IWYU

補遺

各手順の理由は大部分を省略。 かなりclangd, clangd拡張, gccに (今回、筆者にとって) 都合の悪い仕様があったため、余裕があるとき [いつ?] に追加する。

感想

非常に大変だった。 ここまでたどり着くまでに10時間くらいかかってしまった。


そういえば、みちびき5号機が来月打ち上げられるそう。 成功を祈ります。

Pythonでビット演算(コード生成)した

精説GPSの問題を解くためにC/Aコードを生成した

精説GPSの解答 の第2章でC/Aコード生成の問題がある。 このビット演算をPythonでやってみた。

Cと違い、メモリを操作しているというより、もっと高いレイヤにある抽象的なデータを操作している感覚がある (あくまで感覚、実際にどうなっているかは知らない (マサカリが飛んできそう) )。 実際はどのように計算が行われているのかを知らないと、計算効率の悪いコードを書いてしまいそう。 実装の詳細を少しは調べるべき。

今回はPythonの組み込みの整数型を使ったが、NumPyを使うとよりCに近い書き方になる。 書き方というか、CのラッパーだからCを書いているのと同等。

書いたコードはgistで貼り付けようと考えたが、面倒になったのでリポジトリのURLを貼った。

コードのAI生成チェッカー

https://code-detector.ai/

入力したコードがAIによって生成されたか、人間によって書かれたかを判定するツール (SNSで知った)。 似たようなツールはほかにもあるが、会員登録やインストールが不要で、 クリップボードからペーストして使うような簡潔なものは少し調べた限りではほかには見つからなかった。

試しに手元のコードをいくつか入力してみた。 - すべて自分で書いたコード: 0% written by AI - すべてAI生成のコード: 100% - 前半・後半分けて半分のみAIに書かせたコード: 前半は100%, 後半0% - 混在: 50% のような感じになった (少し端折ってはいる)。 よくできている。

卒業研究, このサイト

研究がなかなか進んでいない。 11月に中間発表があるため、10月中に成果をまとめる必要がある。 どうなることやら。

日報のような感覚で、毎日 nikola new_post してみようか。 書く内容を作ろうと作業が少しは進む気がする。

Nikolaのフォーマッターはあるらしいが、面倒で導入していない。 ソースが結構乱れている。

NikolaでMathJax

NikolaでMathJaxを使った記録。

やったこと

  • MathJax v4 の導入

  • プラグイン "units" の導入

結論

  1. math_helper.tmpl/templates/ にコピーする。

  2. math_helper.tmpl

    <script src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/MathJax.js?config=TeX-AMS-MML_HTMLorMML" integrity="sha512-yxTB34XQUKlyuz73upeDrZ91/tbZW/YAURVWL3s+09bEWdmORQzUZwSKyBIRxSeHuSwh1aOKEffn2/D65kwyYg==" crossorigin="anonymous"></script>
    % if mathjax_config:
    ${mathjax_config}
    % else:
    <script type="text/x-mathjax-config">
    MathJax.Hub.Config({tex2jax: {inlineMath: [['$latex ','$'], ['\\(','\\)']]}});
    </script>
    % endif
    

    % if mathjax_config:
        ${mathjax_config}
    % else:
    <script>
    window.MathJax = {
      options: { processHtmlClass: 'math' },
      loader: {
        paths: {
          tex: 'https://cdn.jsdelivr.net/npm/mathjax@4.0.0/input/tex/extensions'
        },
        load: ['[tex]/units']
      },
      tex: {
        packages: { '[+]': ['units'] },
        inlineMath: [['$', '$'], ['\\(', '\\)']],
        displayMath: [['\\[', '\\]'], ['$$', '$$']],
        units: { loose: false, ugly: false }
      },
    # startup: {
    #   ready: () => {
    #     MathJax.startup.defaultReady();
    #     MathJax.typesetPromise();
    #   }
    # }
    };
    </script>
    % endif
    <script defer src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/4.0.0/tex-mml-chtml.min.js"
            integrity="sha512-yxTB34XQUKlyuz73upeDrZ91/tbZW/YAURVWL3s+09bEWdmORQzUZwSKyBIRxSeHuSwh1aOKEffn2/D65kwyYg=="
            crossorigin="anonymous"></script>
    

    に置換

メモ

  • units は MathJax v4 以降対応 (らしい。未検証)

  • cdnjsではMathJaxの /extensions が提供されていない模様。

    よって、 tex: 'https://cdn.jsdelivr.net/npm/mathjax@4.0.0/input/tex/extensions' を指定し、jsdelivrから読む。

  • startupはおそらく不要、コメントアウトしている。

  • require は読み込む必要があるか不明(標準で使えるかをドキュメントで確認すれば良いが、していない。


これにたどり着くのに4時間くらいかかってしまった。

ChatGPTに聞きつつやってみたが、ChatGPTはまだまだ完全ではない。 今回はChatGPTに聞かなければ解決しなかっただろうが、 ChatGPTの回答が生成されるのを待つためにかなり時間を溶かした。 自分の技術力を上げることが必要。


それと、PCのスペックが低すぎて作業が滞った。

まず、CPU (i5-8250U) が弱い。 ベンチマークスコアはN100と同等。 AtomやCeleronで開発をするようなもので、無理があろう。

(補足)

PassMark では、 N100/150/200, 8250U: 5372/5464/4723, 5806 となっている。 かろうじて8250Uがトップ。

N100はi5-8xxx相当の性能があるため、軽い事務作業は快適に行えるだろう。 良い時代になった。)

(余談)

Celeronが強かった時代もあったね。

メモリも足りない。 タスクマネージャーでメモリのタブを確認すると、 "コミット済み" が だいたい 30-40/60-70 GB になっている。

研究で使うソフトウェアがまともに動かなくて困る。 (これはハードウェア以外にも原因がありそうだが) MATLABでSDRを実行すると、このPCで実行した時のみ捕捉が正常に行われない。 PocketSDRは10信号くらいを超えるとまともに操作を受け付けなくなる。

新しいマシンがほしい。切実に。

GNSSで使われる番号についての記事を追加した

GNSSで使われる番号について少し整理した。

動機は、PocketSDRのコマンドライン( pocket_trk などの引数 -prn )で指定する番号はどこでどのように定義されているのか確認しておきたくなったから。 入力できる番号や・入力した番号がどのように処理されるかはソースを見るべきではあるが、 そもそも、それらの番号はGNSSの仕様書・技術文書でどのように定義されているのか気になった。 また、PRN以外にも衛星に振られている番号について整理できていなかったため、確認したかった。


衛星や信号に割り振られる番号にはいくつもの種類(概念)があり。複雑。

PRNにしても、「拡散コードを特定するための番号」にあたる概念にもいくつもの種類がある。 大抵は各衛星に対して1つの番号が与えられるが、QZSSは信号ごとに与えられる(198以外?)。 どうしてこうなった。

そういえば 高須先生の 2025-03-02 の備考録 でもQZSSで使われる番号について「複雑すぎ」と言及されていた。


結局、あまり整理できず、複雑だということが確認できただけのような。 とはいえ、必要な範囲はある程度わかったので中断。

誰かがまとめてくれていないかな。 こんなことを気にしているのは自分のような初心者だけか?

サイト開設

MkDocsで作っていたサイトをNikolaで作り直した。 ついでにサブドメインを memorandom から www に変更した。