Is there a way to print the Swift AST for an Xcode project?

It’s pretty straightforward to print the AST for a Swift package — just add -dump-ast when compiling. It’s not that easy for an Xcode project. When I add the same flag to the build settings “other flags” it shows up in the monstrous swiftc command, but when I copy the command and run it in terminal, no AST is output.

How do I do this?

Update

Now that the question is answered, I've udpated the below to reflect the final version of the command that outputs the AST. If anyone's interested in background as to what inspired the initially removed command options you'll find it here: SO post.

/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swiftc \
    -module-name TicTacToe \
    -Onone \
    -enforce-exclusivity\=checked @/Users/me/Library/Developer/Xcode/DerivedData/TicTacToe-ffbvdaamivfgttffncgscwiarzbu/Build/Intermediates.noindex/TicTacToe.build/Debug-iphoneos/TicTacToe.build/Objects-normal/arm64/TicTacToe.SwiftFileList \
    -DDEBUG \
    -dump-ast \
    -enable-bare-slash-regex \
    -enable-experimental-feature DebugDescriptionMacro \
    -sdk /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS18.2.sdk \
    -target arm64-apple-ios16.0 \
    -g \
    -module-cache-path /Users/me/Library/Developer/Xcode/DerivedData/ModuleCache.noindex \
    -Xfrontend \
    -serialize-debugging-options \
    -enable-testing \
    -index-store-path /Users/me/Library/Developer/Xcode/DerivedData/TicTacToe-ffbvdaamivfgttffncgscwiarzbu/Index.noindex/DataStore \
    -enable-experimental-feature OpaqueTypeErasure \
    -Xcc -D_LIBCPP_HARDENING_MODE\=_LIBCPP_HARDENING_MODE_DEBUG \
    -swift-version 5 \
    -I /Users/me/Library/Developer/Xcode/DerivedData/TicTacToe-ffbvdaamivfgttffncgscwiarzbu/Build/Products/Debug-iphoneos \
    -F /Users/me/Library/Developer/Xcode/DerivedData/TicTacToe-ffbvdaamivfgttffncgscwiarzbu/Build/Products/Debug-iphoneos \
#   -c \
    -j8 \
    -enable-batch-mode \
#   -incremental \
    -Xcc -ivfsstatcache \
    -Xcc /Users/me/Library/Developer/Xcode/DerivedData/SDKStatCaches.noindex/iphoneos18.2-22C146-d5b9239ec3bf5b3adbecdf21472871e3.sdkstatcache \
#   -output-file-map /Users/me/Library/Developer/Xcode/DerivedData/TicTacToe-ffbvdaamivfgttffncgscwiarzbu/Build/Intermediates.noindex/TicTacToe.build/Debug-iphoneos/TicTacToe.build/Objects-normal/arm64/TicTacToe-OutputFileMap.json \
    -use-frontend-parseable-output \
    -save-temps \
    -no-color-diagnostics \
    -serialize-diagnostics \
#   -emit-dependencies \
#   -emit-module \
#   -emit-module-path /Users/me/Library/Developer/Xcode/DerivedData/TicTacToe-ffbvdaamivfgttffncgscwiarzbu/Build/Intermediates.noindex/TicTacToe.build/Debug-iphoneos/TicTacToe.build/Objects-normal/arm64/TicTacToe.swiftmodule \
    -validate-clang-modules-once \
    -clang-build-session-file /Users/me/Library/Developer/Xcode/DerivedData/ModuleCache.noindex/Session.modulevalidation \
    -Xcc -I/Users/me/Library/Developer/Xcode/DerivedData/TicTacToe-ffbvdaamivfgttffncgscwiarzbu/Build/Intermediates.noindex/TicTacToe.build/Debug-iphoneos/TicTacToe.build/swift-overrides.hmap \
#   -emit-const-values \
    -Xfrontend \
    -const-gather-protocols-file \
    -Xfrontend /Users/me/Library/Developer/Xcode/DerivedData/TicTacToe-ffbvdaamivfgttffncgscwiarzbu/Build/Intermediates.noindex/TicTacToe.build/Debug-iphoneos/TicTacToe.build/Objects-normal/arm64/TicTacToe_const_extract_protocols.json \
    -Xcc -iquote -Xcc /Users/me/Library/Developer/Xcode/DerivedData/TicTacToe-ffbvdaamivfgttffncgscwiarzbu/Build/Intermediates.noindex/TicTacToe.build/Debug-iphoneos/TicTacToe.build/TicTacToe-generated-files.hmap \
    -Xcc -I/Users/me/Library/Developer/Xcode/DerivedData/TicTacToe-ffbvdaamivfgttffncgscwiarzbu/Build/Intermediates.noindex/TicTacToe.build/Debug-iphoneos/TicTacToe.build/TicTacToe-own-target-headers.hmap \
    -Xcc -I/Users/me/Library/Developer/Xcode/DerivedData/TicTacToe-ffbvdaamivfgttffncgscwiarzbu/Build/Intermediates.noindex/TicTacToe.build/Debug-iphoneos/TicTacToe.build/TicTacToe-all-target-headers.hmap \
    -Xcc -iquote -Xcc /Users/me/Library/Developer/Xcode/DerivedData/TicTacToe-ffbvdaamivfgttffncgscwiarzbu/Build/Intermediates.noindex/TicTacToe.build/Debug-iphoneos/TicTacToe.build/TicTacToe-project-headers.hmap \
    -Xcc -I/Users/me/Library/Developer/Xcode/DerivedData/TicTacToe-ffbvdaamivfgttffncgscwiarzbu/Build/Products/Debug-iphoneos/include \
    -Xcc -I/Users/me/Library/Developer/Xcode/DerivedData/TicTacToe-ffbvdaamivfgttffncgscwiarzbu/Build/Intermediates.noindex/TicTacToe.build/Debug-iphoneos/TicTacToe.build/DerivedSources-normal/arm64 \
    -Xcc -I/Users/me/Library/Developer/Xcode/DerivedData/TicTacToe-ffbvdaamivfgttffncgscwiarzbu/Build/Intermediates.noindex/TicTacToe.build/Debug-iphoneos/TicTacToe.build/DerivedSources/arm64 \
    -Xcc -I/Users/me/Library/Developer/Xcode/DerivedData/TicTacToe-ffbvdaamivfgttffncgscwiarzbu/Build/Intermediates.noindex/TicTacToe.build/Debug-iphoneos/TicTacToe.build/DerivedSources \
    -Xcc -DDEBUG\=1 \
#   -emit-objc-header \
#   -emit-objc-header-path /Users/me/Library/Developer/Xcode/DerivedData/TicTacToe-ffbvdaamivfgttffncgscwiarzbu/Build/Intermediates.noindex/TicTacToe.build/Debug-iphoneos/TicTacToe.build/Objects-normal/arm64/TicTacToe-Swift.h \
    -working-directory /Users/me/Downloads/BuildingACustomPeerToPeerProtocol/TicTacToe \
    -experimental-emit-module-separately \
    -disable-cmo

For background, here was the original error(s) I faced when I ran an immature version of the above command:

<unknown>:0: error: this mode does not support emitting reference dependency files
<unknown>:0: error: this mode does not support emitting reference dependency files
<unknown>:0: error: this mode does not support emitting reference dependency files
<unknown>:0: error: this mode does not support emitting reference dependency files
<unknown>:0: error: this mode does not support emitting reference dependency files
<unknown>:0: error: this mode does not support emitting reference dependency files
<unknown>:0: error: this mode does not support emitting reference dependency files
<unknown>:0: error: this mode does not support emitting reference dependency files

without seeing your exact command, a possible explanation is the flag order. the frontend output emission flags only respect the last entry, so if you have something like this:

swiftc -dump-ast -emit-object

it will emit the compiled object file, but if you swap the order to

swiftc -emit-object -dump-ast

it will dump the AST

Updated the question with the command I'm using. I've removed multiple "emit" options from the command. I've also tried with adding the -dump-ast flag last in the command, but still no AST :(

Try removing -output-file-map and possibly -use-frontend-parseable-output.

1 Like

you're the best man thanks! -incremental required -output-file-map, so i removed that too. Then it was complaining about not being able to emit constants in the current configuration, so I also removed -emit-const-values — that's when it started working!

I'm curious how this works when the project contains both objc and swift code, but I'll post another question then if I hit that and run into trouble then.

Also, if you want to remove all output other than the AST, then also remove the -use-frontend-parseable-output flag above as well.

1 Like