5 months ago

Integrating Swift Macros with Xcodeproj native blocks

Swift Macros were introduced by Apple as a feature bundled within Swift Packages. This approach enhances shareability—a notable limitation of XcodeProj elements like targets. However, it also tightens the reliance on seamless integration between Xcode and the Swift Package Manager (SPM), which, from my experience and that of others, can be less than ideal in large projects with numerous dependencies. In fact, some developers are shifting towards Tuist’s methodology, reminiscent of CocoaPods, where projects are immediately ready for compilation upon opening.

Given the suboptimal experience offered by Apple’s ecosystem, which precludes optimization opportunities, Tuist employs SPM to resolve packages before mapping them onto Xcodeproj elements. While generally effective, this approach has encountered occasional setbacks, which developers can rectify by tweaking the build settings of the generated targets. Yet, it has not supported Swift Macros since their announcement.

Interestingly, developers managing Xcode rules for Bazel quickly devised a method to accommodate Swift Macros using compiler flags. Inspired by this, could Tuist adopt a similar strategy by utilizing targets, dependencies, and build settings? After some investigation, the answer is affirmative. Here’s the blueprint:

The macro’s representative target must be a macOS command-line target, encompassing the macro’s source code. A secondary, dependent target is required, hosting the public macro definition for import by other targets.

Targets wishing to leverage the macro should:

This setup is contingent upon the secondary target and the dependent targets producing their outputs in the same directory. If that’s not the case, SWIFT_INCLUDE_PATHS will be necessary to make the module available to the dependent targets.

With this mechanism uncovered, the next step is to integrate it into Tuist’s Swift-based DSL and combine it with our binary caching feature. This integration will enable developers to concentrate on targets dependent on macros without the overhead of compiling the macros themselves.

About Pedro Piñera

I created XcodeProj and Tuist, and co-founded Tuist Cloud. My work is trusted by companies like Adidas, American Express, and Etsy. I enjoy building delightful tools for developers and open-source communities.