|
| 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 (Platform SDK) |
| 11 | +3. Platform Swift Modules (Swift SDK) |
| 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 included in the unified SDK which is shipped |
| 27 | +to the user, while on Windows, this is called the Windows SDK, which is a |
| 28 | +separate installable component. For simplicity, we will refer to this as the |
| 29 | +Platform SDK universally. |
| 30 | + |
| 31 | +The Swift SDK 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. In some |
| 36 | +distributions, the Swift SDK and Platform SDK are combined where the system C, |
| 37 | +C++, and Swift libraries are shipped together, such as the SDKs for the Apple |
| 38 | +platforms. |
| 39 | + |
| 40 | +## Flags |
| 41 | + |
| 42 | +The compiler resources are controlled via the driver flag `-resource-dir`. This |
| 43 | +allows the driver to select the correct location in most cases while allowing |
| 44 | +the developer control to override the value if required. Normally, you should |
| 45 | +not need to set this flag as the location of these files is intrinsic to the |
| 46 | +compiler. |
| 47 | + |
| 48 | +The Platform SDK contains C/C++ content which is actually consumed through the |
| 49 | +clang importer rather than the Swift compiler. The Swift toolchain uses clang as |
| 50 | +the C/C++ compiler on all platforms as it is embedded to generate inline foreign |
| 51 | +function interface (FFI) to enable seamless C/C++ bridging to Swift. The flag |
| 52 | +used by clang is derived from the GCC toolchain, and is spelt `--sysroot`. The |
| 53 | +compiler driver is responsible for identifying the structure of the sysroot. |
| 54 | +When cross-compiling, there isn't a consistent location for these files, so the |
| 55 | +driver must expose an argument to specify where to find these files. |
| 56 | + |
| 57 | +On Darwin platforms, the Platform SDK and Swift SDK are shipped combined into a |
| 58 | +single SDK. As a result the singular `-sdk` flag allows control over the |
| 59 | +Platform SDK and Swift SDK. Windows uses a split model as the Windows SDK is |
| 60 | +split into multiple components and can be controlled individually (i.e. UCRT |
| 61 | +version, SDK version, VCRuntime version). The `-sdk` flag is used to specify the |
| 62 | +location of the Swift SDK which is merged with the Platform SDK. By default, the |
| 63 | +environment variable `SDKROOT` is used to seed the value of `-sdk`, though the |
| 64 | +user may specify the value explicitly. Other platforms do not currently have a |
| 65 | +flag to control this location and the toolchain defaults to a set of relative |
| 66 | +paths to locate the content. This prevents cross-compilation as the included |
| 67 | +content would be for a single platform. |
| 68 | + |
| 69 | +> [!NOTE] |
| 70 | +> `-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. |
| 71 | +
|
| 72 | +## Solution |
| 73 | + |
| 74 | +Generalising the above structure and sharing the common sharing gives way to the |
| 75 | +following set of flags for cross-compilation: |
| 76 | + |
| 77 | +1. `-target`: specifies the triple for the host |
| 78 | +2. `-sysroot`: specifies the Platform SDK for the host platform content |
| 79 | +3. `-sdk`: specifies the Swift SDK for the host |
| 80 | + |
| 81 | +The values for these may be defaulted by the driver on a per-platform basis. |
| 82 | + |
| 83 | +The `-sysroot` flag identifies the location for the C/C++ headers and libraries |
| 84 | +required for compilation. This is primarily used by non-Darwin, non-Windows |
| 85 | +hosts as Darwin has its own SDK concept that allows for co-installation and |
| 86 | +Windows uses a different model which merges multiple locations in memory. |
| 87 | + |
| 88 | +The `-sdk` flag identifies the location of the Swift SDK, which provides the |
| 89 | +necessary content for Swift compilation (including binary swiftmodules). This |
| 90 | +includes the standard library and the core libraries (dispatch, Foundation, and |
| 91 | +possibly XCTest - Windows isolates XCTest from the rest of the SDK). The Swift |
| 92 | +shims are also provided by this location as they are a dependency for properly |
| 93 | +processing the Swift core library. |
| 94 | + |
| 95 | +## Compatibility |
| 96 | + |
| 97 | +In order to retain compatibility with older toolchain releases which did not |
| 98 | +include support for the `-sysroot` flag, the driver shall default the value to |
| 99 | +the value provided to `-sdk`. This allows us to transition between the existing |
| 100 | +toolchains which expected a single root containing all the necessary components. |
| 101 | +This allows the driver to make the most appropriate choice for the host that is |
| 102 | +being compiled for without loss of generality. A platform may opt to ignore one |
| 103 | +or more of these flags (e.g. Windows does not use `-sysroot` as the system |
| 104 | +headers are not organised like the traditional unix layout). |
0 commit comments