XcodeでIncremental Buildが走った際に、具体的にどのファイルがCompileされたか表示する方法のメモです。

諸事情により、XcodeでIncremental Buildが走った際、具体的にどのファイルがCompileされたか知る必要があり、Xcode上で見れるBuild Logから読み取ろうにも諸々省略されていて読み取れず。。。 何か良い方法はないかなと模索していたところ、 @kateinoigakukunさんが SWIFT_EXEC にwrapperかませるとよいかもとのことだったので、雑にscriptねじ込んで表示させてみました。

swiftcの出力は(微妙に惜しい)JSON形式になっており、ちょっと修正を加えてやれば普通のJSON Textとして扱えます。具体的にはこのような感じになってます。

15002
{
  "kind": "began",
  "name": "compile",
  "command": "\/Applications\/Xcode-11.4.app\/Contents\/Developer\/Toolchains\/XcodeDefault.xctoolchain\/usr\/bin\/swift -frontend -c -primary-file \/path\/to\/project\/\/sample-project\/sample-project\/View\/MainViewController.swift ..............................",
  "command_arguments": [
    "-frontend",
    "-c",
    "-primary-file",
    "\/path\/to\/project\/sample-project\/sampel-project\/View\/MainViewController.swift",
    .
    .
  ],
  .
  .
}
123
.
.

この出力を若干修正してJSON Textとして読めるようにしつつ、実際にcompileされたファイルを表示するためのshell scriptとRubyコードが次です。超雑です。もっと良い書き方あればGistのコメントで教えて下さい🙏

require "json"
json_data = File.open("output.json") do |file|
JSON.load(file)
end
changed_files = json_data
.select { |block|
block["kind"] == "began" and block["name"] == "compile"
}
.map { |block|
args = block["command_arguments"]
idx = args.index("-primary-file")
args[idx+1]
}
puts changed_files
#!/bin/sh
SWIFTC="swiftc"
SED="gsed"
RUBY="ruby"
RUBY_FIND_COMPILED_FILES="find_compiled_files.rb"
LOG_OUTPUT_FILE="output.txt"
LOG_JSON_FILE="output.json"
echo "Compiled files:"
$SWIFTC $@ 1>$LOG_OUTPUT_FILE 2>&1
grep -E -v '^[0-9]+$' $LOG_OUTPUT_FILE | $SED -e 's/^}$/},/' -e '1s/{/[{/' -e '$s/},/}]/' > $LOG_JSON_FILE
$RUBY $RUBY_FIND_COMPILED_FILES
rm $LOG_OUTPUT_FILE $LOG_JSON_FILE

このshell scriptとRubyコードを適当なところにおき、SWIFT_EXECというUser-Defined Build settingsを追加し、その値として先のshell scriptへのパスを設定します。

あとはBuildさせればこんな感じでBuild Logに表示されます。(Compile Swift source filesの行を展開させてやる必要があります)

Compiled files:
/path/to/project/sample-project/sample-projectView/MainViewController.swift

何かファイルを変更した後にIncremental Buildするケースでは問題なく動きます(多分)。ただ、Xcodeの仕様上、ファイルに変更が一切ない場合は直近のBuild Logが使い回されてしまい、実際にCompileはされていないのにCompileされたという表示がなされるので注意です。