Antimony: exploring alternative build systems

The llbuild build engine can build ninja manifests in addition to its native format, but ninja can't build llbuild's manifests.

1 Like

Just generating a build.ninja file for ninja to build would exclude the performance opportunities of dynamic tasks and tighter integration with the compilers, that SwiftBuild allows and features like "explicitly built modules" are built on.

2 Likes

Perhaps this isn't the right thread but I've started here so I'll continue. The current evolution of Xcode's build system seems to be on the path to obfuscation where other toolmakers are not permitted to peer inside. I've downloaded Xcode 16.3 and it no longer even bothers to log the specific compiler command used to build swift files. Aside from wrecking my pet project (which I guess I'd be more annoyed about if I didn't already have a replacement in the works) the direction in general seems unfortunate, centralising peoples' experience of developing iOS on a very complex monolith that they have absolutely no agency over when there is a problem (even if it is now all Open Source). The result is the search for alternatives in organisations large enough to build their own such as Bazel and Buck. This is why I suggested using a simple build.ninja file as a well documented interface between the IDE and the act of building to keep things open for other IDEs and tools like Cursor and VSCode. Why re-invent the wheel?

2 Likes

They're still there; the "Planning Swift module $MODULE_NAME" step contains the full driver invocation command line, which is what corresponds to the top-level command that a human being would run to compile the module (and what build systems like Bazel and Ninja would use).

It does look like Xcode 16.3 does indeed hide the command lines specifically for the frontend child processes spawned by the driver, but that's not really any different than how the driver works if you run it by hand: it doesn't show you the swift-frontend invocations unless you add -v to your command.

If you're doing something that depends on the frontend invocation command lines specifically, you should definitely file a feedback asking if there could be a setting to show them. (I don't know if there is one; I didn't look that deeply.)

4 Likes

I think @dabrahams and @johnno1962 nail the sentiment shared by a lot of folks using SwiftPM right now. It’s precisely what fuels the constant, furious search for solutions that supplement or outright replace SwiftPM (to the detriment of the SwiftPM effort).

Certainly part of the value of contributing Xcode's build system to the Swift project was to give the Open Source community more agency over being able to introspect and debug the build process.

Anyone would be able to integrate swift-build into Cursor or VSCode (and we are doing so indirectly via Swift Package Manager, as detailed in Evolving SwiftPM Builds with Swift Build) if they so wished.

Could you clarify what you believe is still missing?

What is missing for me at the moment is a way to recover the individual swift-frontend invocations as one was able to do from the .xcactivity logs until Xcode 16.3. Could a there be a build setting to opt into the legacy logging behaviour? I use this in the InjectionIII project as I believe build systems are struggling to scale and the focus should be on incremental builds, ideally injected directly into the running program using a dynamic library. I need to be able to re-compile individual swift files as quickly as possible.

I see. Activity logs are handled by Xcode, which isn't part of the Swift project or the swift-build build system engine. In cases where specific Xcode UX outside the purview of the Swift project is involved, please direct those requests to feedbackassistant.apple.com.

That said, the lines are sometimes blurry in terms of how data and build log information in swift-build gets surfaced to IDEs (such as Xcode). If you wanted a build setting to opt into more logging, or even some alternate design to extract more data from the build process, that would definitely be something appropriate to propose and discuss on a swift-build issue, or on the forums category.

1 Like

But… surely the underlying tool must be sending this information to Xcode in some form so it can be logged? You don’t do the work of producing these commands on both sides of the boundary do you?

Yes, Swift Build's public API provides information like the command line display string (see swift-build/Sources/SwiftBuild/ConsoleCommands/SWBServiceConsoleBuildCommandProtocol.swift at 6d5df10fc68848abac0f6cad1c4579ddb23ed7a7 · swiftlang/swift-build · GitHub) to clients such as Xcode.

There are also various user defaults which you can find in swift-build/Sources/SWBUtil/UserDefaults.swift at main · swiftlang/swift-build · GitHub which provide additional logging detail when toggled.

I've raised FB16626699. I've also explored "other" ways of intercepting the swift-frontend commands/arguments would prefer to be able to continue parsing the logs for the information I need. This is kind-of relevant to this thread as a build.ninja file would have been an alternative to provide this information.

and so... Xcode 16.3 shipped with this regression of not logging swift compilations any more.

Does Add a build setting for xcode's EnableDebugActivityLogs by owenv · Pull Request #234 · swiftlang/swift-build · GitHub help you?

2 Likes

Hi Boris, thank you so much, that flag EMIT_FRONTEND_COMMAND_LINES does indeed bring the previous behaviour back with Xcode 16.3 so InjectionIII lives to ride another day. Log parsing in some ways isn't the best solution for what I'm trying to do but at least it doesn't require users to alter their development environment.

Or, if you want Xcode 16.2 behaviour back globally the secret sauce seems to be:

defaults write com.apple.dt.Xcode EnableDebugActivityLogs 1

Though I've just had a strange side-effect from enabling this form of logging all the time.

1 Like