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

せっかくCMakeベースのプロジェクトで compile_commands.json
を運用するのを整えたので、msbuildプロジェクトでもやりたい。
binlogを使うべきかどうかはめっちゃ悩ましいな。。マクロを展開してXMLにしたりはmsbuild単体でもできるが、パースが面倒というのがあんまり変わらない。

簡単なテストコードを書く
#ifdef
で2パターンのexecutableをビルドするテストを書いてみた。
CMakeはターゲット毎にvcxprojを作るので、vcxprojがどのdefineをしているのかを、ログから抽出したい。

ログの取得
普通にソリューションファイルを生成して(Visual Studio command prompt上なら、デフォルトで最新のVisual Studioソリューションがgeneratorとして選ばれる)、 /bl
オプション入りでビルドを行う。
msbuild /bl drawtest.sln
生成された msbuild.binlog
を https://msbuildlog.com/ に掛けると、ログの内容をビジュアライズできる。
jsonに変換
とりあえず前作ったツールに掛ける。
確かに、 drawtest.c
は2回コンパイルされていて、ここで言うところの ProjectContextId
か ProjectInstanceId
がどこに由来するのか調べられれば良さそうだ。
ダンプ対象のイベントを追加してみるのが良いかな。

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なのでやっぱりフラットにした。
Structured log内の Project
から id
を引き、これをbinlogのProjectContextId
と合わせる方向にしてみる。(この点はChatGPTは全く理解が間違っていた。)

BuiltProjectOutputGroupKeyOutput
をダンプする
ProjectEvaluationFinishedEventArgs
経由で取れるっちゃ取れるんだけど、もっと良い方法があるような気がしてならない。。