Open5

Reposoup: msbuildのログからターゲットを列挙したい

okuokuokuoku

せっかくCMakeベースのプロジェクトで compile_commands.json を運用するのを整えたので、msbuildプロジェクトでもやりたい。

https://zenn.dev/okuoku/scraps/4652e7bed8a0bb

binlogを使うべきかどうかはめっちゃ悩ましいな。。マクロを展開してXMLにしたりはmsbuild単体でもできるが、パースが面倒というのがあんまり変わらない。

okuokuokuoku

簡単なテストコードを書く

#ifdef で2パターンのexecutableをビルドするテストを書いてみた。

https://github.com/okuoku/sdl3_multiproctest/blob/e2594d3129ebf700568a30146d9fa44f3c99c715/drawtest.c#L36-L37

https://github.com/okuoku/sdl3_multiproctest/blob/e2594d3129ebf700568a30146d9fa44f3c99c715/drawtest.c#L50-L51

CMakeはターゲット毎にvcxprojを作るので、vcxprojがどのdefineをしているのかを、ログから抽出したい。

okuokuokuoku

ログの取得

普通にソリューションファイルを生成して(Visual Studio command prompt上なら、デフォルトで最新のVisual Studioソリューションがgeneratorとして選ばれる)、 /bl オプション入りでビルドを行う。

msbuild /bl drawtest.sln

生成された msbuild.binloghttps://msbuildlog.com/ に掛けると、ログの内容をビジュアライズできる。

jsonに変換

とりあえず前作ったツールに掛ける。

https://zenn.dev/okuoku/scraps/5cb30908986936

確かに、 drawtest.c は2回コンパイルされていて、ここで言うところの ProjectContextIdProjectInstanceId がどこに由来するのか調べられれば良さそうだ。

ダンプ対象のイベントを追加してみるのが良いかな。

okuokuokuoku

Recursiveにやる

ChatGPTは以下のようにrecursiveにやることを提案してきた。まぁそっちの方がログを羅列するより出力が読みやすいかな。

using Microsoft.Build.Logging.StructuredLogger;
var build = BinaryLog.ReadBuild("yourlog.binlog");

foreach (var project in build.FindChildrenRecursive<Project>())
{
    Console.WriteLine($"Project: {project.Name}, Path: {project.SourceFilePath}");

    foreach (var target in project.FindChildrenRecursive<Target>())
    {
        Console.WriteLine($"  Target: {target.Name}");
    }
}

...ちょっとoverkillなのでやっぱりフラットにした。

https://github.com/okuoku/binlogdump/commit/4537cbb026b3f58131d8f4a77bf0d508b6d9dc89

Structured log内の Project から id を引き、これをbinlogのProjectContextId と合わせる方向にしてみる。(この点はChatGPTは全く理解が間違っていた。)