Skip to content

Commit 80fd474

Browse files
committed
Merge #19240: build: macOS toolchain simplification and bump
adf543d darwin: pass mlinker-version so that clang enables new features (Cory Fields) 2418f73 macos: Bump to xcode 11.3.1 and 10.15 SDK (Cory Fields) 5c2c835 depends: bump MacOS toolchain (Cory Fields) 85b5e42 contrib: macdeploy: Remove historical extraction notes (Carl Dong) 351beb5 contrib: macdeploy: Use apple-sdk-tools instead of xar+pbzx (Carl Dong) fbcfcf6 native_cctools: Don't use libc++ from pinned clang (Carl Dong) 3381e4a Adapt rest of tooling to new SDK naming scheme (Carl Dong) b3394ab contrib: macdeploy: Correctly generate macOS SDK (Carl Dong) Pull request description: This PR achieves 3 main things: 1. It simplifies the macOS SDK generation by putting the logic inside a (semi-)portable python3 script `gen-sdk` 2. It transitions us to using `libc++` headers extracted from the `Xcode.app`, which is more correct as those headers better match the `.tbd` library stubs we use from the `MacOSX.sdk` (located under the same `Xcode.app`). Previously, we used `libc++` headers copied from our downloaded, pinned clang (see `native_cctools.mk`). 3. It bumps the macOS toolchain in a way that fulfills all of the following constraints: 1. The new SDK should support compiling with C++17 (our current one doesn't) 2. The new toolchain should not change our minimum supported macOS version (`-mmacosx-version-min`) 3. The new toolchain should expect to use a version of `cctools` that is supported by https://github.com/tpoechtrager/cctools-port For the constraints in (3), you can reference [this chart](https://en.wikipedia.org/wiki/Xcode#Xcode_7.0_-_11.x_(since_Free_On-Device_Development)) to see that the newest toolchain we can use with our `cctools-port` is `11.3.1`, and the rest of the constraints were tested with local builds. #### But [the other Wikipedia chart](https://en.wikipedia.org/wiki/Xcode#Xcode_11.x_(since_SwiftUI_framework)) says that the "min macOS to run" for Xcode 11.3.1 is 10.14.4, doesn't that violate constraint (ii)? This confused me at first too, but the "min macOS to run" is for the Xcode.app App itself. The SDK still supports 10.12, as evident in a few plist files and as proven through local builds. #### Why bundle all of this together in a single PR? We need (1) and (2) together, because if we don't, manually adding the `libc++` headers and writing that out in a `README.md` is going to result in a lot of user error, so it's great to have these together to be more correct and also make it easier on the user at the same time. We need (3) together with everything else because bumping (or in the case of (1), renaming) the SDK requires some human coordination and may break some builds. And since it's not that complicated a change, it makes sense to do it together with the rest. ACKs for top commit: theuni: ACK adf543d. fanquake: ACK adf543d - I'll take a look at the linker issue. Tree-SHA512: 3813b69ebfe9610bee14100f26296fb5438d9bf0dd184ea55e6c38f5ebd94f7c171d98b150fc9e52fde626533f347f7ec51a2b72b79859d946284f578c1084a3
2 parents e3fa3c7 + adf543d commit 80fd474

File tree

8 files changed

+146
-57
lines changed

8 files changed

+146
-57
lines changed

ci/test/00_setup_env_mac.sh

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ export LC_ALL=C.UTF-8
99
export CONTAINER_NAME=ci_macos_cross
1010
export HOST=x86_64-apple-darwin16
1111
export PACKAGES="cmake imagemagick libcap-dev librsvg2-bin libz-dev libbz2-dev libtiff-tools python3-dev python3-setuptools"
12-
export OSX_SDK=10.14
12+
export XCODE_VERSION=11.3.1
13+
export XCODE_BUILD_ID=11C505
1314
export RUN_UNIT_TESTS=false
1415
export RUN_FUNCTIONAL_TESTS=false
1516
export GOAL="deploy"

ci/test/05_before_script.sh

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,14 @@ fi
1515

1616
DOCKER_EXEC mkdir -p ${DEPENDS_DIR}/SDKs ${DEPENDS_DIR}/sdk-sources
1717

18-
if [ -n "$OSX_SDK" ] && [ ! -f ${DEPENDS_DIR}/sdk-sources/MacOSX${OSX_SDK}.sdk.tar.gz ]; then
19-
curl --location --fail $SDK_URL/MacOSX${OSX_SDK}.sdk.tar.gz -o ${DEPENDS_DIR}/sdk-sources/MacOSX${OSX_SDK}.sdk.tar.gz
18+
OSX_SDK_BASENAME="Xcode-${XCODE_VERSION}-${XCODE_BUILD_ID}-extracted-SDK-with-libcxx-headers.tar.gz"
19+
OSX_SDK_PATH="${DEPENDS_DIR}/sdk-sources/${OSX_SDK_BASENAME}"
20+
21+
if [ -n "$XCODE_VERSION" ] && [ ! -f "$OSX_SDK_PATH" ]; then
22+
curl --location --fail "${SDK_URL}/${OSX_SDK_BASENAME}" -o "$OSX_SDK_PATH"
2023
fi
21-
if [ -n "$OSX_SDK" ] && [ -f ${DEPENDS_DIR}/sdk-sources/MacOSX${OSX_SDK}.sdk.tar.gz ]; then
22-
DOCKER_EXEC tar -C ${DEPENDS_DIR}/SDKs -xf ${DEPENDS_DIR}/sdk-sources/MacOSX${OSX_SDK}.sdk.tar.gz
24+
if [ -n "$XCODE_VERSION" ] && [ -f "$OSX_SDK_PATH" ]; then
25+
DOCKER_EXEC tar -C "${DEPENDS_DIR}/SDKs" -xf "$OSX_SDK_PATH"
2326
fi
2427
if [[ $HOST = *-mingw32 ]]; then
2528
DOCKER_EXEC update-alternatives --set $HOST-g++ \$\(which $HOST-g++-posix\)

contrib/gitian-build.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,7 @@ def main():
209209
args.macos = 'm' in args.os
210210

211211
# Disable for MacOS if no SDK found
212-
if args.macos and not os.path.isfile('gitian-builder/inputs/MacOSX10.14.sdk.tar.gz'):
212+
if args.macos and not os.path.isfile('gitian-builder/inputs/Xcode-11.3.1-11C505-extracted-SDK-with-libcxx-headers.tar.gz'):
213213
print('Cannot build for MacOS, SDK does not exist. Will build for other OSes')
214214
args.macos = False
215215

contrib/gitian-descriptors/gitian-osx.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ remotes:
3232
- "url": "https://github.com/bitcoin/bitcoin.git"
3333
"dir": "bitcoin"
3434
files:
35-
- "MacOSX10.14.sdk.tar.gz"
35+
- "Xcode-11.3.1-11C505-extracted-SDK-with-libcxx-headers.tar.gz"
3636
script: |
3737
set -e -o pipefail
3838
@@ -90,7 +90,7 @@ script: |
9090
BASEPREFIX="${PWD}/depends"
9191
9292
mkdir -p ${BASEPREFIX}/SDKs
93-
tar -C ${BASEPREFIX}/SDKs -xf ${BUILD_DIR}/MacOSX10.14.sdk.tar.gz
93+
tar -C ${BASEPREFIX}/SDKs -xf ${BUILD_DIR}/Xcode-11.3.1-11C505-extracted-SDK-with-libcxx-headers.tar.gz
9494
9595
# Build dependencies for each host
9696
for i in $HOSTS; do

contrib/macdeploy/README.md

Lines changed: 27 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -14,55 +14,44 @@ When complete, it will have produced `Bitcoin-Qt.dmg`.
1414

1515
## SDK Extraction
1616

17-
Our current macOS SDK (`macOSX10.14.sdk`) can be extracted from
18-
[Xcode_10.2.1.xip](https://download.developer.apple.com/Developer_Tools/Xcode_10.2.1/Xcode_10.2.1.xip).
17+
### Step 1: Obtaining `Xcode.app`
18+
19+
Our current macOS SDK
20+
(`Xcode-11.3.1-11C505-extracted-SDK-with-libcxx-headers.tar.gz`) can be
21+
extracted from
22+
[Xcode_11.3.1.xip](https://download.developer.apple.com/Developer_Tools/Xcode_11.3.1/Xcode_11.3.1.xip).
1923
An Apple ID is needed to download this.
2024

21-
`Xcode.app` is packaged in a `.xip` archive.
22-
This makes the SDK less-trivial to extract on non-macOS machines.
23-
One approach (tested on Debian Buster) is outlined below:
25+
After Xcode version 7.x, Apple started shipping the `Xcode.app` in a `.xip`
26+
archive. This makes the SDK less-trivial to extract on non-macOS machines. One
27+
approach (tested on Debian Buster) is outlined below:
2428

2529
```bash
30+
# Install/clone tools needed for extracting Xcode.app
31+
apt install cpio
32+
git clone https://github.com/bitcoin-core/apple-sdk-tools.git
2633

27-
apt install clang cpio git liblzma-dev libxml2-dev libssl-dev make
28-
29-
git clone https://github.com/tpoechtrager/xar
30-
pushd xar/xar
31-
./configure
32-
make
33-
make install
34-
popd
35-
36-
git clone https://github.com/NiklasRosenstein/pbzx
37-
pushd pbzx
38-
clang -llzma -lxar pbzx.c -o pbzx -Wl,-rpath=/usr/local/lib
39-
popd
40-
41-
xar -xf Xcode_10.2.1.xip -C .
42-
43-
./pbzx/pbzx -n Content | cpio -i
44-
45-
find Xcode.app -type d -name MacOSX.sdk -exec sh -c 'tar --transform="s/MacOSX.sdk/MacOSX10.14.sdk/" -c -C$(dirname {}) MacOSX.sdk/ | gzip -9n > MacOSX10.14.sdk.tar.gz' \;
34+
# Unpack Xcode_11.3.1.xip and place the resulting Xcode.app in your current
35+
# working directory
36+
python3 apple-sdk-tools/extract_xcode.py -f Xcode_11.3.1.xip | cpio -d -i
4637
```
4738

48-
on macOS the process is more straightforward:
39+
On macOS the process is more straightforward:
4940

5041
```bash
51-
xip -x Xcode_10.2.1.xip
52-
tar -s "/MacOSX.sdk/MacOSX10.14.sdk/" -C Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/ -czf MacOSX10.14.sdk.tar.gz MacOSX.sdk
42+
xip -x Xcode_11.3.1.xip
5343
```
5444

55-
Our previously used macOS SDK (`MacOSX10.11.sdk`) can be extracted from
56-
[Xcode 7.3.1 dmg](https://developer.apple.com/devcenter/download.action?path=/Developer_Tools/Xcode_7.3.1/Xcode_7.3.1.dmg).
57-
The script [`extract-osx-sdk.sh`](./extract-osx-sdk.sh) automates this. First
58-
ensure the DMG file is in the current directory, and then run the script. You
59-
may wish to delete the `intermediate 5.hfs` file and `MacOSX10.11.sdk` (the
60-
directory) when you've confirmed the extraction succeeded.
45+
### Step 2: Generating `Xcode-11.3.1-11C505-extracted-SDK-with-libcxx-headers.tar.gz` from `Xcode.app`
46+
47+
To generate `Xcode-11.3.1-11C505-extracted-SDK-with-libcxx-headers.tar.gz`, run
48+
the script [`gen-sdk`](./gen-sdk) with the path to `Xcode.app` (extracted in the
49+
previous stage) as the first argument.
6150

6251
```bash
63-
apt-get install p7zip-full sleuthkit
64-
contrib/macdeploy/extract-osx-sdk.sh
65-
rm -rf 5.hfs MacOSX10.11.sdk
52+
# Generate a Xcode-11.3.1-11C505-extracted-SDK-with-libcxx-headers.tar.gz from
53+
# the supplied Xcode.app
54+
./contrib/macdeploy/gen-sdk '/path/to/Xcode.app'
6655
```
6756

6857
## Deterministic macOS DMG Notes
@@ -91,13 +80,13 @@ and its `libLTO.so` rather than those from `llvmgcc`, as it was originally done
9180

9281
To complicate things further, all builds must target an Apple SDK. These SDKs are free to
9382
download, but not redistributable. To obtain it, register for an Apple Developer Account,
94-
then download [Xcode 10.2.1](https://download.developer.apple.com/Developer_Tools/Xcode_10.2.1/Xcode_10.2.1.xip).
83+
then download [Xcode_11.3.1](https://download.developer.apple.com/Developer_Tools/Xcode_11.3.1/Xcode_11.3.1.xip).
9584

9685
This file is many gigabytes in size, but most (but not all) of what we need is
9786
contained only in a single directory:
9887

9988
```bash
100-
Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.14.sdk
89+
Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk
10190
```
10291

10392
See the SDK Extraction notes above for how to obtain it.

contrib/macdeploy/gen-sdk

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
#!/usr/bin/env python3
2+
import argparse
3+
import plistlib
4+
import pathlib
5+
import sys
6+
import tarfile
7+
import gzip
8+
import os
9+
import contextlib
10+
11+
@contextlib.contextmanager
12+
def cd(path):
13+
"""Context manager that restores PWD even if an exception was raised."""
14+
old_pwd = os.getcwd()
15+
os.chdir(str(path))
16+
try:
17+
yield
18+
finally:
19+
os.chdir(old_pwd)
20+
21+
def run():
22+
parser = argparse.ArgumentParser(
23+
description=__doc__, formatter_class=argparse.RawTextHelpFormatter)
24+
25+
parser.add_argument('xcode_app', metavar='XCODEAPP', nargs=1)
26+
parser.add_argument("-o", metavar='OUTSDKTGZ', nargs=1, dest='out_sdktgz', required=False)
27+
28+
args = parser.parse_args()
29+
30+
xcode_app = pathlib.Path(args.xcode_app[0]).resolve()
31+
assert xcode_app.is_dir(), "The supplied Xcode.app path '{}' either does not exist or is not a directory".format(xcode_app)
32+
33+
xcode_app_plist = xcode_app.joinpath("Contents/version.plist")
34+
with xcode_app_plist.open('rb') as fp:
35+
pl = plistlib.load(fp)
36+
xcode_version = pl['CFBundleShortVersionString']
37+
xcode_build_id = pl['ProductBuildVersion']
38+
print("Found Xcode (version: {xcode_version}, build id: {xcode_build_id})".format(xcode_version=xcode_version, xcode_build_id=xcode_build_id))
39+
40+
sdk_dir = xcode_app.joinpath("Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk")
41+
sdk_plist = sdk_dir.joinpath("System/Library/CoreServices/SystemVersion.plist")
42+
with sdk_plist.open('rb') as fp:
43+
pl = plistlib.load(fp)
44+
sdk_version = pl['ProductVersion']
45+
sdk_build_id = pl['ProductBuildVersion']
46+
print("Found MacOSX SDK (version: {sdk_version}, build id: {sdk_build_id})".format(sdk_version=sdk_version, sdk_build_id=sdk_build_id))
47+
48+
out_name = "Xcode-{xcode_version}-{xcode_build_id}-extracted-SDK-with-libcxx-headers".format(xcode_version=xcode_version, xcode_build_id=xcode_build_id)
49+
50+
xcode_libcxx_dir = xcode_app.joinpath("Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1")
51+
assert xcode_libcxx_dir.is_dir()
52+
53+
if args.out_sdktgz:
54+
out_sdktgz_path = pathlib.Path(args.out_sdktgz_path)
55+
else:
56+
# Construct our own out_sdktgz if not specified on the command line
57+
out_sdktgz_path = pathlib.Path("./{}.tar.gz".format(out_name))
58+
59+
def tarfp_add_with_base_change(tarfp, dir_to_add, alt_base_dir):
60+
"""Add all files in dir_to_add to tarfp, but prepent MEMBERPREFIX to the files'
61+
names
62+
63+
e.g. if the only file under /root/bazdir is /root/bazdir/qux, invoking:
64+
65+
tarfp_add_with_base_change(tarfp, "foo/bar", "/root/bazdir")
66+
67+
would result in the following members being added to tarfp:
68+
69+
foo/bar/ -> corresponding to /root/bazdir
70+
foo/bar/qux -> corresponding to /root/bazdir/qux
71+
72+
"""
73+
def change_tarinfo_base(tarinfo):
74+
if tarinfo.name and tarinfo.name.startswith("./"):
75+
tarinfo.name = str(pathlib.Path(alt_base_dir, tarinfo.name))
76+
if tarinfo.linkname and tarinfo.linkname.startswith("./"):
77+
tarinfo.linkname = str(pathlib.Path(alt_base_dir, tarinfo.linkname))
78+
return tarinfo
79+
with cd(dir_to_add):
80+
tarfp.add(".", recursive=True, filter=change_tarinfo_base)
81+
82+
print("Creating output .tar.gz file...")
83+
with out_sdktgz_path.open("wb") as fp:
84+
with gzip.GzipFile(fileobj=fp, compresslevel=9, mtime=0) as gzf:
85+
with tarfile.open(mode="w", fileobj=gzf) as tarfp:
86+
print("Adding MacOSX SDK {} files...".format(sdk_version))
87+
tarfp_add_with_base_change(tarfp, sdk_dir, out_name)
88+
print("Adding libc++ headers...")
89+
tarfp_add_with_base_change(tarfp, xcode_libcxx_dir, "{}/usr/include/c++/v1".format(out_name))
90+
print("Done! Find the resulting gzipped tarball at:")
91+
print(out_sdktgz_path.resolve())
92+
93+
if __name__ == '__main__':
94+
run()

depends/hosts/darwin.mk

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
11
OSX_MIN_VERSION=10.12
2-
OSX_SDK_VERSION=10.14
3-
OSX_SDK=$(SDK_PATH)/MacOSX$(OSX_SDK_VERSION).sdk
4-
darwin_CC=clang -target $(host) -mmacosx-version-min=$(OSX_MIN_VERSION) --sysroot $(OSX_SDK)
5-
darwin_CXX=clang++ -target $(host) -mmacosx-version-min=$(OSX_MIN_VERSION) --sysroot $(OSX_SDK) -stdlib=libc++
2+
OSX_SDK_VERSION=10.15.1
3+
XCODE_VERSION=11.3.1
4+
XCODE_BUILD_ID=11C505
5+
LD64_VERSION=530
6+
7+
OSX_SDK=$(SDK_PATH)/Xcode-$(XCODE_VERSION)-$(XCODE_BUILD_ID)-extracted-SDK-with-libcxx-headers
8+
darwin_CC=clang -target $(host) -mmacosx-version-min=$(OSX_MIN_VERSION) --sysroot $(OSX_SDK) -mlinker-version=$(LD64_VERSION)
9+
darwin_CXX=clang++ -target $(host) -mmacosx-version-min=$(OSX_MIN_VERSION) --sysroot $(OSX_SDK) -stdlib=libc++ -mlinker-version=$(LD64_VERSION)
610

711
darwin_CFLAGS=-pipe
812
darwin_CXXFLAGS=$(darwin_CFLAGS)

depends/packages/native_cctools.mk

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
package=native_cctools
2-
$(package)_version=3764b223c011574971ee3ae09ce968ba5dc2f00f
2+
$(package)_version=4da2f3b485bcf4cef526f30c0b8c0bcda99cdbb4
33
$(package)_download_path=https://github.com/tpoechtrager/cctools-port/archive
44
$(package)_file_name=$($(package)_version).tar.gz
5-
$(package)_sha256_hash=3e35907bf376269a844df08e03cbb43e345c88125374f2228e03724b5f9a2a04
5+
$(package)_sha256_hash=a2d491c0981cef72fee2b833598f20f42a6c44a7614a61c439bda93d56446fec
66
$(package)_build_subdir=cctools
7-
$(package)_clang_version=6.0.1
7+
$(package)_clang_version=8.0.0
88
$(package)_clang_download_path=https://releases.llvm.org/$($(package)_clang_version)
99
$(package)_clang_download_file=clang+llvm-$($(package)_clang_version)-x86_64-linux-gnu-ubuntu-14.04.tar.xz
1010
$(package)_clang_file_name=clang-llvm-$($(package)_clang_version)-x86_64-linux-gnu-ubuntu-14.04.tar.xz
11-
$(package)_clang_sha256_hash=fa5416553ca94a8c071a27134c094a5fb736fe1bd0ecc5ef2d9bc02754e1bef0
11+
$(package)_clang_sha256_hash=9ef854b71949f825362a119bf2597f744836cb571131ae6b721cd102ffea8cd0
1212

1313
$(package)_libtapi_version=3efb201881e7a76a21e0554906cf306432539cef
1414
$(package)_libtapi_download_path=https://github.com/tpoechtrager/apple-libtapi/archive
@@ -72,7 +72,5 @@ define $(package)_stage_cmds
7272
cp -P bin/clang++ $($(package)_staging_prefix_dir)/bin/ &&\
7373
cp lib/libLTO.so $($(package)_staging_prefix_dir)/lib/ && \
7474
cp -rf lib/clang/$($(package)_clang_version)/include/* $($(package)_staging_prefix_dir)/lib/clang/$($(package)_clang_version)/include/ && \
75-
cp bin/llvm-dsymutil $($(package)_staging_prefix_dir)/bin/$(host)-dsymutil && \
76-
if `test -d include/c++/`; then cp -rf include/c++/ $($(package)_staging_prefix_dir)/include/; fi && \
77-
if `test -d lib/c++/`; then cp -rf lib/c++/ $($(package)_staging_prefix_dir)/lib/; fi
75+
cp bin/dsymutil $($(package)_staging_prefix_dir)/bin/$(host)-dsymutil
7876
endef

0 commit comments

Comments
 (0)