Support for prebuilt Swift-Syntax

Is there a plan to support prebuilt Swift-Syntax when using Tuist dependencies without Tuist cache? Is this even feasible with current Tuist implementation?

Some resources for the reference

1 Like

Hey!

This is certainly a need, but not a strong priority of the Tuist team right as teams using Tuist can already benefit from prebuilt macros by using the binary cache. We understand the prebuilt version from Xcode would result in a slightly better experience than what we have right now as explained here. We would definitely still like to support this in the future, but there’s currently no timeline. As always, contributions are more than welcome :wink:

Right. I is more like suggestion idea of possible implementation. But it could work like that (I’m not sure if it is feasable change form the Tuist Architectures standpoint).

Currently, when we have an external dependency of SPM, all transitive dependencies are re-mapped to the frameworks.

So, for example, if someone has dependency on swift-syntax, there’ll be a project, with all the targets of the swift-syntax.

	•	SwiftBasicFormat.framework
	•	SwiftCompilerPlugin.framework
	•	SwiftCompilerPluginMessageHandling.framework
	•	SwiftDiagnostics.framework
	•	SwiftOperators.framework
	•	SwiftParser.framework
	•	SwiftParserDiagnostics.framework
	•	SwiftSyntax.framework
	•	SwiftSyntax509.framework
	•	SwiftSyntax510.framework
	•	SwiftSyntax600.framework
	•	SwiftSyntax601.framework
	•	SwiftSyntaxBuilder.framework
	•	SwiftSyntaxMacroExpansion.framework
	•	SwiftSyntaxMacros.framework
	•	_SwiftSyntaxCShims.framework

The idea here is to:

Allow developer to leave package dependencies as-is for the extenal depencies.

So, for example, if I have a depedncy A, which depends on swift-syntax, I could opt-in, to prevent tuist from creating project for swift-syntax.

This would create swift package reference in the A. project

And, basically will leave resolance of the package to the Xcode/xcodebuild.

swift syntax is one of the cases, though. but having this option (at least as experimental) would drastically reduce the amount of time, needed for building external depedencies, dependent on the swift-syntax.

@marekfort Will this pass review, or does it completely break how Tuist is supposed to work?

I mean, is there even a possibility that this solution could be merged?

This is something Tuist can certainly support. Perhaps with a setting in PackageSettings:

#if TUIST
let packageSettings = PackageSettings(
  packagePreBuilts: .all 
  // Or individual opt-in: ["foo", "bar"]
)
#endif

This will require setting the right build settings in those targets such that the SwiftSyntax modules can be looked up (cc @core to get their thoughts). Would you be interested in giving it a shot?

I don’t think this is the right way to approach the XcodeProj-based installation. One of the benefits of the XcodeProj-based installation is that everything is resolved at the generation time and leaving the resolution to Xcode would break that. Additionally, you’d resolve swift-syntax twice – once during tuist install and once when you open Xcode.

Instead, we can integrate the prebuilts directly. To get prebuilds, we can modify the swift package resolve command to swift package --enable-experimental-prebuilts resolve. Once you do that, you’ll get paths to the prebuilts in the .build/workspace-state.json which is the file we use when mapping the package info to our Tuist definitions. Here’s an example of how swift-syntax is referenced in that file when running the mentioned command against our app_with_composable_architecture fixture:

    "prebuilts" : [
      {
        "cModules" : [

        ],
        "checkoutPath" : "/Users/marekfort/Developer/tuist/cli/Fixtures/app_with_composable_architecture/Tuist/.build/checkouts/swift-syntax",
        "identity" : "swift-syntax",
        "includePath" : [
          "Sources/_SwiftSyntaxCShims/include",
          "Sources/_SwiftLibraryPluginProviderCShims/include"
        ],
        "libraryName" : "MacroSupport",
        "path" : "/Users/marekfort/Developer/tuist/cli/Fixtures/app_with_composable_architecture/Tuist/.build/prebuilts/swift-syntax/600.0.1/swiftlang-6.2.0.19.9-MacroSupport-macos_aarch64",
        "products" : [
          "swift-syntaxPackageTests",
          "SwiftBasicFormat",
          "SwiftCompilerPlugin",
          "SwiftDiagnostics",
          "SwiftIDEUtils",
          "SwiftOperators",
          "SwiftParser",
          "SwiftParserDiagnostics",
          "SwiftRefactor",
          "SwiftSyntax",
          "SwiftSyntaxBuilder",
          "SwiftSyntaxMacros",
          "SwiftSyntaxMacroExpansion",
          "SwiftSyntaxMacrosTestSupport",
          "SwiftSyntaxMacrosGenericTestSupport",
          "_SwiftCompilerPluginMessageHandling",
          "_SwiftLibraryPluginProvider"
        ],
        "version" : "600.0.1"
      }
    ]

We can take this information and integrate these prebuilts directly without having to depend on the vanilla Xcode <> SwiftPM integration.

If we do it like that, then this shouldn’t be configurable in PackageSettings (and it shouldn’t be configurable on a per-product basis), instead, you would specify that in Tuist.swift. We already support using arbitrary swift package arguments, so this would require no changes in ProjectDescription: Config.InstallOptions · Project Description · References · Tuist

In other words, we need to add support for integrating the packages referred to in .build/workspace-state.json’s prebuilts field.

This part I was not aware of. I created an issue. @PaulTaykalo would you like to take a stab at implementing it?