Skip to content

Commit 3e6aa17

Browse files
compnerdetcwildelxbndrendocrimes
committed
Create CrossCompilationModel.md
Add some documentation to describe the proposed model for cross-compilation, associated flags, and the reasoning for the structure. This should allow us to have a reference for the design allowing us to evolve the model. Co-authored-by: Evan Wilde <ewilde@apple.com> Co-authored-by: Alexander Smarus <bender@readdle.com> Co-authored-by: Danielle <dani@builds.terrible.systems>
1 parent 9facbd4 commit 3e6aa17

File tree

1 file changed

+104
-0
lines changed

1 file changed

+104
-0
lines changed

docs/CrossCompilationModel.md

+104
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
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

Comments
 (0)