Don't try to build dynamic libraries if the SDK only supports
static linking. Also, *do* build static libraries if the SDK
only supports static linking.
rdar://123503191
The dispatch that's built into concurrency on Linux and Windows is built
with clang, but there's no dependency edge. Usually this isn't noticed
because concurrency and most the things it depends on also depend on
clang directly, but occasionally ninja will choose the dispatch build
before building other dependencies, which then fails because there's no
clang.
As of CMake 3.25, there are now global variables `LINUX=1`, `ANDROID=1`,
etc. These conflict with expressions that used these names as unquoted
strings in positions where CMake accepts 'variable|string', for example:
- `if(sdk STREQUAL LINUX)` would fail, because `LINUX` is now defined and
expands to 1, where it would previously coerce to a string.
- `if(${sdk} STREQUAL "LINUX")` would fail if `sdk=LINUX`, because the
left-hand side expands twice.
In this patch, I looked for a number of patterns to fix up, sometimes a
little defensively:
- Quoted right-hand side of `STREQUAL` where I was confident it was
intended to be a string literal.
- Removed manual variable expansion on left-hand side of `STREQUAL`,
`MATCHES` and `IN_LIST` where I was confident it was unintended.
Fixes#65028.
We would previously use `clang-cl` without the explicit path which could
find an alternative `clang-cl` instance. This manifested as a failure
to build libdispatch as part of the compiler when cross-compiling x64 to
arm64.
Convert the NDK path to allow the native path to be used when
configuring the Swift runtime but use the CMake spelling when
performing the inner configure.
When building on Windows i686 with a toolchain build for Windows x64, we
would try to build libdispatch for i686 as x86_64. This obviously would
be incorrect. Explicitly pass the target triple for the sub-builds. We
can do this unconditionally since we always use `clang-cl` builds. This
allows us to build the SDK only components for Windows i686 from a 64bit
build.
We have two directories for Swift libraries,
* `SWIFT_SDK_<platform>_LIB_SUBDIR`, a.k.a., the SDK subdir,
a.k.a., `swift-<platform>-<arch>/lib/swift/<platform>`, and
* `SWIFTLIB_SINGLE_SUBDIR`,
a.k.a., `swift-<platform>-<arch>/lib/swift/<platform>/<arch>`.
Through the Swift build, libraries are emitted to both
`.../lib/swift/<platform>` and `.../lib/swift/<platform>/<arch>`.
However, when building toolchains, only `.../lib/swift/<platform>/` is
populated with libraries.
None of this normally isn't a problem; the Swift libraries do not have
inherent interdependencies. This however changes with Concurrency:
Concurrency has an implicit dependency on libdispatch.
When Swift is built, we have two copies of `libswift_Concurrency.so`:
one in `.../lib/swift/<platform>` and one in
`.../lib/swift/<platform>/<arch>`. Prior to this commit, we
unconditionally copy `libdispatch.so` and `libBlocksRuntime.so` to only
_one_ place -- that is, `.../lib/swift/<platform>/<arch>`.
swiftc emits binaries on ELF systems with an rpath of
`.../lib/swift/<platform>`. These binaries implicitly import
Concurrency, so they link against `libswift_Concurrency.so` (whether
they use Concurrency features or not). The library's `$ORIGIN` is
searched to find `libdispatch.so`.
Now, nothing breaks on Linux because there the loader, when given an
rpath, searches both `.../lib/swift/<platform>` and
`.../lib/swift/<platform>/<arch>` even though the rpath only specifies
one directory..
However, on other platforms, only the given rpath is searched.
`libdispatch.so` does not reside next to `libswift_Concurrency.so`
because it has been copied to `.../lib/swift/<platform>/<arch>`; not in
the rpath.
There are a few ways to solve this: change the way rpaths are
configured, only emit libraries into one place, copy `libdispatch.so`
only to the path matching the rpath, or copy `libdispatch.so` wherever
`libswift_Concurrency.so` is copied,
Because the toolchain file layout is different to the file layout when
only Swift is built, hacking the rpath is brittle. Presumably, the
reason why we have a `libswift_Concurrency.so` residing in two places is
to support builds where multiple architectures are supported in the one
build directory, so we cannot just copy `libdispatch.so` _only_ to
`.../lib/swift/<platform>`.
Ultimately, We need to ensure that every instance where
`libswift_Concurrency.so` can be used has `libdispatch.so` residing next
to it, which we do here.
Note that this implicit dependency resolution would not happen unless we
added a `-ldispatch` flag to make this all work, but other platforms are
instaed using `$ORIGIN` to get the search to work properly, so we also
do this for OpenBSD in this commit.
The newest VS2019 release updates CMake to 3.20, which picks up
`llvm-mt` as a preferred manifest tool. However, we do not build
`llvm-mt` with libxml2 support currently, which prevents the use of the
just built manifest tool for building libdispatch. Explicitly opt into
using the MSVC manifest-tool.
For cross-compiling Android one can simply provide
CMAKE_ANDROID_ARCH_ABI and the right CMAKE_SYSTEM_PROCESSOR will be
chosen by CMake. Since the SDK arch names are not the expected ones by the Android NDK,
it is better not to use them. The change should keep sending the
CMAKE_SYSTEM_PROCESSOR for SDKs that are not ANDROID, while skipping it
for the ANDROID SDKs.
* [Concurrency] Fix Android C libdispatch build
We need to pass CMAKE_ANDROID_NDK and CMAKE_ANDROID_ARCH_ABI to the
build.
* Set proper ANDROID_ARCH_ABI
* Add -DCMAKE_ANDROID_API to C libdispatch build
* Fix compiler config for Android