Skip to content

Commit 68554ec

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 <[email protected]> Co-authored-by: Alexander Smarus <[email protected]> Co-authored-by: Danielle <[email protected]>
1 parent 9facbd4 commit 68554ec

File tree

1 file changed

+103
-0
lines changed

1 file changed

+103
-0
lines changed

docs/CrossCompilationModel.md

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

0 commit comments

Comments
 (0)