|
| 1 | + |
| 2 | +# Cross-Compilation Model |
| 3 | + |
| 4 | +## Components |
| 5 | + |
| 6 | +When compiling Swift code, the compiler will consult three different sources of |
| 7 | +inputs outside of the user provided code. |
| 8 | + |
| 9 | +1. Compiler Resources |
| 10 | +2. System (C/C++) Headers |
| 11 | +3. Platform Swift Modules (SDK Overlay) |
| 12 | + |
| 13 | +These pieces compose in a particular manner to build a system image to build |
| 14 | +code against. |
| 15 | + |
| 16 | +The compiler resources are content shipped with the toolchain and are tied to |
| 17 | +that specific version and build of the compiler. In the case of the Swift |
| 18 | +compiler, this includes the Swift shims. Whilst this is a compiler resource, the |
| 19 | +packaging may not necessarily be part of the toolchain due to interdependencies. |
| 20 | +Some of this content is required to process the system headers themselves (e.g. |
| 21 | +clang's builtin resource headers). |
| 22 | + |
| 23 | +The C/C++ system headers (and libraries) are what is traditionally called the |
| 24 | +Unix "sysroot". On most Unix systems, this is the set of headers that are |
| 25 | +associated with the system library set which normally may be found in |
| 26 | +`/usr/include`. On Darwin, this is the SDK which is shipped to the user, while |
| 27 | +on Windows, this is called the Windows SDK, which is a separate installable |
| 28 | +component. |
| 29 | + |
| 30 | +The platform Swift modules provided by the SDK overlay overlays the sysroot or |
| 31 | +(C/C++) SDK. It contains the libraries and overlays that provide the core |
| 32 | +language runtime and expose system libraries to Swift code in an ergonomic |
| 33 | +manner. This may be in the form of API Notes, module maps, wrapper types, or |
| 34 | +Swift `extension`s, or entire libraries. This code may or may not be fully |
| 35 | +inlined into the client code and thus be part of the platform ABI. |
| 36 | + |
| 37 | +## Flags |
| 38 | + |
| 39 | +The compiler resources are controlled via the driver flag `-resource-dir`. |
| 40 | +This allows the driver to select the correct location in most cases while |
| 41 | +allowing the developer control to override the value if required. |
| 42 | +Normally, you should not need to set this flag as the location of these files is intrinsic to the compiler. |
| 43 | + |
| 44 | +The system headers are more interesting. Since this is C/C++ content, this is |
| 45 | +actually consumed through the clang importer rather than the Swift compiler. The |
| 46 | +Swift toolchain uses clang as the C/C++ compiler on all platforms as it is |
| 47 | +embedded to generate inline foreign function interface (FFI) to enable seamless |
| 48 | +C/C++ bridging to Swift. The flag used by clang is derived from the GCC |
| 49 | +toolchain, and is spelt `--sysroot`. The compiler driver is responsible for |
| 50 | +identifying the structure of the sysroot. When cross-compiling, there isn't a |
| 51 | +consistent location for these files, so the driver must expose an argument to |
| 52 | +specify where to find these files. |
| 53 | + |
| 54 | +Currently, we do not have a good way to isolate the SDK overlay from the |
| 55 | +remainder of the required content. On Darwin platforms, this content is shipped |
| 56 | +as part of the SDK. As a result the singular `-sdk` flag allows control over the |
| 57 | +platform SDK and SDK overlay. Windows uses a split model as the Windows SDK is |
| 58 | +split into multiple components and can be controlled individually (i.e. UCRT |
| 59 | +version, SDK version, VCRuntime version). The `-sdk` flag is used to specify the |
| 60 | +location of the SDK overlay which is applied to the system SDK. By default, the |
| 61 | +environment variable `SDKROOT` is used to seed the value of `-sdk`, though the |
| 62 | +user may specify the value explicitly. Other platforms do not currently have a |
| 63 | +flag to control this location and the toolchain defaults to a set of relative |
| 64 | +paths to locate the content. This prevents cross-compilation as the included |
| 65 | +content would be for a single platform. |
| 66 | + |
| 67 | +> [!NOTE] |
| 68 | +> `-resource-dir` historically influenced the driver's search for the SDK content, locating the standard library relative to the resource directory. This behaviour is considered deprecated but remains for compatibility. The `-sdk` parameter is given precedence and is the preferred mechanism for controlling the behaviour of the driver to locate the SDK content. |
| 69 | +
|
| 70 | +## Solution |
| 71 | + |
| 72 | +Generalising the above structure and sharing the common sharing gives way to the |
| 73 | +following set of flags for cross-compilation: |
| 74 | + |
| 75 | +1. `-target`: specifies the triple for the host |
| 76 | +2. `-sysroot`: specifies the (C/C++) sysroot for the host platform content |
| 77 | +3. `-sdk`: specifies the Swift SDK overlay for the host |
| 78 | + |
| 79 | +The values for these may be defaulted by the driver on a per-platform basis. |
| 80 | + |
| 81 | +The `-sysroot` flag identifies the location for the C/C++ headers and libraries required for compilation. This is primarily used by non-Darwin, non-Windows hosts as Darwin has its own SDK concept that allows for co-installation and Windows uses a different model which merges multiple locations in memory. |
| 82 | + |
| 83 | +The `-sdk` flag identifies the location of the "Swift SDK overlay", which provides the necessary content for Swift compilation (including binary swiftmodules). This includes the standard library and the core libraries (dispatch, Foundation, and possibly XCTest - Windows isolates XCTest from the rest of the SDK). The Swift shims are also provided by this location as they are a dependency for properly processing the Swift core library. |
| 84 | + |
| 85 | +## Compatibility |
| 86 | + |
| 87 | +In order to retain compatibility with older toolchain releases which did not include support for the `-sysroot` flag, the driver shall default the value to the value provided to `-sdk`. This allows us to transition between the existing toolchains which expected a single root containing all the necessary components. |
| 88 | +This allows the driver to make the most appropriate choice for the host that is |
| 89 | +being compiled for without loss of generality. A platform may opt to ignore one |
| 90 | +or more of these flags (e.g. Windows does not use `-sysroot` as the system |
| 91 | +headers are not organised like the traditional unix layout). |
0 commit comments