Skip to content

Commit ab66d12

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 ab66d12

File tree

1 file changed

+91
-0
lines changed

1 file changed

+91
-0
lines changed

docs/CrossCompilationModel.md

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

Comments
 (0)