|
1 | | -Skip Linux-only linkopts when generating macOS Swift toolchain linker inputs. |
| 1 | +Emit macOS-appropriate linkopts when generating macOS Swift toolchain |
| 2 | +linker inputs. |
2 | 3 |
|
3 | 4 | rules_swift 4.0.0-rc4's standalone toolchain extension registers a |
4 | | -`swift_toolchain(...)` for macOS whose implicit linker inputs are produced by |
5 | | -`_swift_unix_linkopts_cc_info`. That function unconditionally emits |
6 | | -Linux/ELF-only flags -- `swiftrt.o`, `-lstdc++`, `-lrt`, `-ldl`, |
7 | | -`-static-libgcc` -- plus a Linux-shaped runtime path |
8 | | -(`{arch}/swiftrt.o` with `arch = "aarch64"`, but the macOS toolchain lays |
9 | | -out `usr/lib/swift/macos/` without `swiftrt.o` at all and uses `arm64` for |
10 | | -Apple Silicon). |
| 5 | +`swift_toolchain(...)` for macOS whose implicit linker inputs are produced |
| 6 | +by `_swift_unix_linkopts_cc_info`. That function has two problems on macOS: |
11 | 7 |
|
12 | | -On macOS the Apple linker handles Swift runtime initialization automatically |
13 | | -via `LC_LINKER_OPTION` autolinking and `__DATA,__mod_init_func`, so |
14 | | -`swiftrt.o` is neither present nor needed. The other flags are also |
15 | | -Linux-specific. The only linkopts that carry over are the toolchain library |
16 | | -search path and rpath so downstream binaries can locate |
17 | | -`libswiftCore.dylib` etc. |
| 8 | +1. It unconditionally emits Linux/ELF-only flags -- `swiftrt.o`, |
| 9 | + `-lstdc++`, `-lrt`, `-ldl`, `-static-libgcc` -- plus a Linux-shaped |
| 10 | + runtime path (`{arch}/swiftrt.o` with `arch = "aarch64"`, but the |
| 11 | + macOS toolchain lays out `usr/lib/swift/macosx/` without `swiftrt.o` |
| 12 | + at all and uses `arm64` for Apple Silicon). |
18 | 13 |
|
19 | | -Without this patch, linking any `swift_library`-dependent Rust binary (e.g. |
20 | | -`//unified/swift-syntax-rs:swift-syntax-parse`) on macOS fails with: |
| 14 | +2. It builds the Swift runtime library path as |
| 15 | + `{toolchain_root}/lib/swift/{os}` using the `os` value passed in from |
| 16 | + `_swift_toolchain_impl`, which is `"macos"` (the Bazel |
| 17 | + `@platforms//os:macos` name). But a Swift.org macOS toolchain -- the |
| 18 | + one rules_swift materializes via `swift_tools`' `additional_inputs = |
| 19 | + glob(["usr/lib/swift/**", ...])` -- actually stores its libraries |
| 20 | + under `usr/lib/swift/`**`macosx`**`/` (Apple's SDK name), not |
| 21 | + `usr/lib/swift/macos/`. `-L .../usr/lib/swift/macos` therefore points |
| 22 | + at a non-existent directory, so `libswiftCompatibility56.a`, |
| 23 | + `libswiftCompatibilityConcurrency.a`, |
| 24 | + `libswiftCompatibilityPacks.a` (auto-linked via `LC_LINKER_OPTION` |
| 25 | + records in swiftc-emitted `.o` files) can't be resolved, and their |
| 26 | + symbols end up undefined. |
| 27 | + |
| 28 | +On macOS the Apple linker handles Swift runtime initialization |
| 29 | +automatically via `LC_LINKER_OPTION` autolinking and |
| 30 | +`__DATA,__mod_init_func`, so `swiftrt.o` is neither present nor needed. |
| 31 | +The Linux-specific system libraries (`-lrt`, `-ldl`, `-lstdc++`, |
| 32 | +`-static-libgcc`) also don't exist. The only linkopts that carry over |
| 33 | +are the toolchain library search path and rpath -- rewritten to point |
| 34 | +at `macosx` -- so downstream binaries can locate `libswiftCore.dylib` |
| 35 | +and the compatibility static archives. |
| 36 | + |
| 37 | +Without this patch, linking any `swift_library`-dependent Rust binary |
| 38 | +(e.g. `//unified/swift-syntax-rs:swift-syntax-parse`) on macOS fails |
| 39 | +with either: |
21 | 40 |
|
22 | 41 | clang: error: no such file or directory: |
23 | 42 | 'external/rules_swift+.../usr/lib/swift/macos/aarch64/swiftrt.o' |
24 | 43 |
|
25 | | -This should be fixed upstream: rules_swift's standalone toolchain extension |
26 | | -needs a macOS-aware `_swift_unix_linkopts_cc_info`. Until then, we patch the |
27 | | -module locally so macOS consumers can build. |
| 44 | +(problem 1, pre-patch), or: |
| 45 | + |
| 46 | + ld: warning: search path |
| 47 | + 'external/rules_swift+.../usr/lib/swift/macos' not found |
| 48 | + ld: warning: Could not find or use auto-linked library |
| 49 | + 'swiftCompatibility56': library 'swiftCompatibility56' not found |
| 50 | + Undefined symbols for architecture arm64: ... |
| 51 | + ld: symbol(s) not found for architecture arm64 |
| 52 | + |
| 53 | +(problem 2, if only problem 1 is fixed). |
| 54 | + |
| 55 | +This should be fixed upstream: rules_swift's standalone toolchain |
| 56 | +extension needs a macOS-aware `_swift_unix_linkopts_cc_info`. Until |
| 57 | +then, we patch the module locally so macOS consumers can build. |
28 | 58 |
|
29 | 59 | --- a/swift/toolchains/swift_toolchain.bzl |
30 | 60 | +++ b/swift/toolchains/swift_toolchain.bzl |
31 | | -@@ -411,25 +411,38 @@ |
| 61 | +@@ -411,25 +411,48 @@ |
32 | 62 | toolchain_root = toolchain_root, |
33 | 63 | ) |
34 | 64 |
|
@@ -57,9 +87,19 @@ module locally so macOS consumers can build. |
57 | 87 | + # __DATA,__mod_init_func; swiftrt.o is neither present in the |
58 | 88 | + # toolchain layout nor needed. The Linux-specific system libraries |
59 | 89 | + # (-lrt, -ldl, -lstdc++, -static-libgcc) also don't exist here. |
| 90 | ++ # |
| 91 | ++ # Also, a Swift.org macOS toolchain stores its libraries under |
| 92 | ++ # `usr/lib/swift/macosx/` (Apple's SDK name), not the Bazel |
| 93 | ++ # `os = "macos"` name that `_swift_toolchain_impl` passes in. Rewrite |
| 94 | ++ # `platform_lib_dir` to point at `macosx` so `-L` and `-Wl,-rpath` |
| 95 | ++ # resolve to a real directory (and thus `libswiftCompatibility*.a`, |
| 96 | ++ # `libswiftCore.dylib`, etc. can be found by the linker). |
| 97 | ++ macos_platform_lib_dir = "{toolchain_root}/lib/swift/macosx".format( |
| 98 | ++ toolchain_root = toolchain_root, |
| 99 | ++ ) |
60 | 100 | + linkopts = [ |
61 | | -+ "-L{}".format(platform_lib_dir), |
62 | | -+ "-Wl,-rpath,{}".format(platform_lib_dir), |
| 101 | ++ "-L{}".format(macos_platform_lib_dir), |
| 102 | ++ "-Wl,-rpath,{}".format(macos_platform_lib_dir), |
63 | 103 | + ] + [ |
64 | 104 | + "-Wl,-rpath,{}".format(rpath) |
65 | 105 | + for rpath in additional_rpaths |
|
0 commit comments