I've been doing some work on analyzing Swift projects using their ASTs, and I would like to know if it is possible to generate it somehow when building a Swift project with Xcode.
Right now, I am able to print the AST on the terminal when running the swiftc -dump-ast
command for single files and simple projects. However, it becomes harder when using it for more complex projects.
For this reason, I'd like to use xcode. I already tried to pass the -dump-ast
flag to the compiler in Build Settings > Swift Compiler - Custom Flags > Other Swift Flags. The flag was indeed passed to the compiler (the output does report calling swiftc with the -dump-ast flag when building). I tried to build the project both with xcode and through the xcodebuild
command below, but neither dumped the ast.
xcodebuild -target 'CompilingTest.xcodeproj' -scheme 'CompilingTest' -
configuration "Debug" -sdk iphoneos -arch "armv7"
CONFIGURATION_BUILD_DIR="TestBuild" ONLY_ACTIVE_ARCH=NO
Now, I'm reasoning that either Xcode's build process redirects swiftc's output to some file, or it silences it somehow. Any thoughts?
Any help would be greatly appreciated.
Dumping the AST of your app is not possible to do from only changing
Xcode build settings. The main reason for this is that Xcode is making a
lot of decisions about compiler flags to pass to swiftc
which
are not all compatible with dumping the AST and you cannot stop Xcode from
doing this.
But it is possible to do outside of Xcode with Xcode's help (or in
Xcode using my script mentioned below). To do this you'll need to
capture the swiftc
command Xcode runs for your project, and then
change it a bit to dump the AST.
First, build your project, then go to the Report Navigator in Xcode (the
last tab in the Navigator pane on the left). From here either save your
entire build log with the save button across the top, or copy the
swiftc
command directly from Xcode. You're looking for the command
called "Compile Swift Sources" for your app target (NOTE: this only
contains the compile command for the one target, if you want the AST for
multiple targets you'll need to perform these steps multiple times). If
you can't find this step, you may need to clean your project and compile
again (or look at an older build log).
After you've copied the entire swiftc
command from Xcode, you'll need
to head to the command line and change the command a bit. Here's what
you'll need to do:
-emit-dependencies
-emit-module -emit-module-path FILEPATH
-emit-objc-header -emit-objc-header-path FILEPATH
-c
(right before -jN
and the list of files)-parseable-output
-dump-ast
> output.ast 2>&1
to your shell commandWhy these?
-c
is an alias of -emit-object
.swiftc
from outputting other information about this
command. If you plan to parse the output of this AST command from
another program instead of redirecting the output in the shell you
might want to leave this option in (you end up getting JSON with it).-print-ast
which prints a more
class-dump
style output vs
the more verbose, classical parsable AST output of -dump-ast
.output.ast
to whatever file you want. You'll need 2>&1
because the
AST is dumped to stderr instead of stdout. The order also matters
here.Also note that Xcode's build log escapes spaces but not other characters
that shells may not like. For example if you have &
in any of your
folder / directory paths, you'll have to escape that manually.
If all of this sounds like too much work, I threw together a script to do this processing for you and you can set it up in Xcode. You can find it on GitHub.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With