Re-examining meaning of global options in cross-compilation contexts

Re-examining meaning of global options in cross-compilation contexts

Since the host/target split is new for SwiftPM I think it's a good time to re-visit meaning and structure of affected command options such as --sdk , --toolchain , --triple and various -X options. This post is also inspired by plugins: Global compiler flags should not be used for plugin dependencies by euanh · Pull Request #7549 · apple/swift-package-manager · GitHub (authored by euanh), which was aimed at fixing a case hit when attempting to cross compile.

First regarding terminology - I use "host" and "target" platforms because that's the terminology that has been agreed upon during the review of the cross-compilation sdk proposal. In particular the following sentence from the acceptance announcement:

We elected to use host and target when specifying cross compilation and host, build and target when using Canadian Cross.

Cross compilation complicates the existing options - a module can now be built for both the host and the target depending on the context, completely transparently to the user. For example, a target could have a macro dependency which would mean that it has to be built for the host. Some other non-macro/plugin module could depend on that target at the same time, so it would then have to be built for the target platform as well. Note that plugins, macros, and test targets that directly depend on macros, are always built for the host.

Let’s start with -X options. Currently only Swift language options support host/target separation by means of -Xbuild-tools-swiftc prefix although how that actually behaves is not well-documented at the moment. Currently -Xswiftc applies to all builds and -Xbuild-tools-swiftc applies to manifest, plugins, but not macros. At the same time, such capability doesn't exist at all for cc , cxx, and linker flags.

--sdk/--toolchain options were originally added as an early form of cross-compilation and were hidden from the help output. When switching to swift-argument-parser, that was no longer the case (no hidden was added), but they still have no documentation. Both only apply to target.

--triple applies to the target only and can be useful in cross-compiling scenarios where a separate SDK/toolchain isn’t needed.

I’d like to propose leaving --sdk/--toolchain as is for now (and perhaps deprecating for --swift-sdk in the future), --triple being renamed to --target-triple (deprecating --triple), and renaming the other options through either:

  1. -X{cc, cxx, swiftc, linker} are applicable to all contexts
    1. -Xhost-{cc, cxx, swiftc, linker} , only applicable to host platform related builds (including macros) and override -X options.
    2. -Xtarget-{cc, cxx, swiftc, linker}, only applicable to target platform related builds (not macros) and override -X options.
  2. -X{cc, cxx, swiftc, linker} are applicable only to target context (not macros)
    1. -Xhost-{cc, cxx, swiftc, linker} could be used to specify host specific values if required (including macros).
    2. Optional: Deprecate -X and --triple in favor of verbose -Xtarget-{cc, cxx, swiftc, linker}.

With my preference being towards option 1, since it seems like the most intuitive and backward compatible approach.

Please share your thoughts!

6 Likes

option 1 absolutely! this would be so so so so helpful for embedded swift

1 Like

I really like option 1) for how understandable it is. The host and target prefixing makes a lot of sense and is pretty intuitive.

In general I like the hierarchy it introduces in "what is affected", and option 2 is somewhat fuzzy still tbh, I'm pretty sure I'd forget that -X (in option 2) does NOT affect host context, it seems to me like "it obviously should" and then I'd have to remember it doesn't :sweat_smile: