Skip to content

Commit 196188e

Browse files
authored
ARM Mac open-source and packaged build (#677)
This enables cross-compiling for arm64 Mac. This changes the default Xcode version to 12.2, as Xcode 11 doesn't support arm64, and 12.0 fails with vcpkg. It'll still build with 11.7 in the expanded matrix and omit arm64. Unit tests are built, but not run, on arm64. (They can't be run until GitHub has hosted ARM Mac runners, or we add our own.) This PR adds a --arch option to the testapp builder but does not yet build for arm64 in the integration_tests workflow. For packaged builds, we now build LLVM binutils on Mac, in addition to GNU binutils. LLVM binutils are required for the merge_libraries step on Mac, as GNU binutils does not support outputting ARM64 Mach-O files properly. (We still need GNU binutils on Mac for c++filt). Because LLVM binutils can take a long time to build, we cache it.
1 parent 84c4e2a commit 196188e

File tree

14 files changed

+812
-89
lines changed

14 files changed

+812
-89
lines changed

.github/workflows/cpp-packaging.yml

Lines changed: 58 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,11 @@ env:
3232
demumbleVer: "1.1.0"
3333
# Use SHA256 for hashing files.
3434
hashCommand: "sha256sum"
35-
# Xcode version 12 is the version we build the SDK with.
35+
# Xcode version 12.2 is the version we build the SDK with.
3636
# Our MacOS runners will use the version in /Applications/Xcode_${xcodeVersion}.app
37-
xcodeVersion: "12"
37+
xcodeVersion: "12.2"
38+
# LLVM version with ARM MachO support has no version number yet.
39+
llvmVer: "5f187f0afaad33013ba03454c4749d99b1362534"
3840

3941
jobs:
4042
log_inputs:
@@ -91,7 +93,7 @@ jobs:
9193
if: runner.os == 'macOS'
9294
run: sudo xcode-select -s /Applications/Xcode_${{ env.xcodeVersion }}.app/Contents/Developer
9395

94-
- name: fetch and build binutils
96+
- name: Fetch and build binutils
9597
run: |
9698
set +e
9799
# Retry up to 10 times because Curl has a tendency to timeout on
@@ -105,13 +107,46 @@ jobs:
105107
106108
tar -xf binutils.tar.xz
107109
mv ./binutils-${{ matrix.binutils_version }} ./binutils-src
110+
mkdir /tmp/binutils-output
108111
cd binutils-src
109-
./configure --enable-targets=all --prefix=/tmp/binutils
110-
make
112+
./configure --enable-targets=all --prefix=/tmp/binutils-output
113+
make -j2
111114
make install
112115
cd -
113116
mkdir -p packaging-tools
114-
cp -af /tmp/binutils/bin/* packaging-tools
117+
cp -af /tmp/binutils-output/bin/* packaging-tools
118+
119+
- name: Cache LLVM (Mac only)
120+
if: matrix.tools_platform == 'darwin'
121+
id: cache_llvm
122+
uses: actions/cache@v2
123+
with:
124+
path: llvm-src/llvm/build/bin
125+
key: llvm-bin-${{matrix.tools_platform}}-${{env.xcodeVersion}}-${{env.llvmVer}}
126+
127+
- name: Fetch LLVM source (Mac only)
128+
# Only fetch LLVM if we don't already have binaries from the cache.
129+
if: ${{ matrix.tools_platform == 'darwin' && !steps.cache_llvm.outputs.cache-hit }}
130+
uses: actions/[email protected]
131+
with:
132+
repository: llvm/llvm-project
133+
path: llvm-src
134+
ref: ${{ env.llvmVer }}
135+
136+
- name: Build LLVM (Mac only)
137+
# Only build LLVM if we don't already have binaries from the cache.
138+
if: ${{ matrix.tools_platform == 'darwin' && !steps.cache_llvm.outputs.cache-hit }}
139+
run: |
140+
mkdir llvm-src/llvm/build
141+
cd llvm-src/llvm/build
142+
cmake -DLLVM_ENABLE_PROJECTS=clang -DCMAKE_BUILD_TYPE=Release ..
143+
cmake --build . -j 3 --target llvm-objcopy --target llvm-nm --target llvm-ar
144+
145+
- name: Package LLVM output (Mac only)
146+
if: matrix.tools_platform == 'darwin'
147+
run: |
148+
mkdir -p packaging-tools
149+
cp -af llvm-src/llvm/build/bin/* packaging-tools
115150
116151
- name: fetch demumble
117152
uses: actions/[email protected]
@@ -127,7 +162,7 @@ jobs:
127162
cmake --build .
128163
python demumble_test.py
129164
cd -
130-
mkdir -p packaging-tools-
165+
mkdir -p packaging-tools
131166
cp -af demumble-src/demumble packaging-tools
132167
133168
- name: archive tools
@@ -254,7 +289,7 @@ jobs:
254289
matrix:
255290
os: [windows-latest, ubuntu-latest, macos-latest]
256291
build_type: ["Release", "Debug"]
257-
architecture: ["x64", "x86"]
292+
architecture: ["x64", "x86", "arm64"]
258293
msvc_runtime: ["static", "dynamic"]
259294
linux_abi: ["legacy", "c++11"]
260295
python_version: [3.7]
@@ -292,6 +327,10 @@ jobs:
292327
msvc_runtime: "dynamic"
293328
- os: ubuntu-latest
294329
build_type: "Debug"
330+
- os: ubuntu-latest
331+
architecture: "arm64"
332+
- os: windows-latest
333+
architecture: "arm64"
295334

296335
steps:
297336
- name: setup Xcode version (macos)
@@ -308,6 +347,10 @@ jobs:
308347
echo "VCPKG_RESPONSE_FILE=external/vcpkg_${{ matrix.vcpkg_triplet }}_response_file.txt" >> $GITHUB_ENV
309348
echo "MATRIX_UNIQUE_NAME=${{ matrix.os }}-${{ matrix.build_type }}-${{ matrix.architecture }}-${{ matrix.python_version }}-${{ matrix.msvc_runtime }}-${{ matrix.linux_abi }}" >> $GITHUB_ENV
310349
echo "SDK_NAME=${{ matrix.sdk_platform }}-${{ matrix.architecture }}-${{ matrix.build_type }}-${{ matrix.msvc_runtime }}-${{ matrix.linux_abi }}" >> $GITHUB_ENV
350+
if [[ '${{ matrix.sdk_platform }}' == 'darwin' ]]; then
351+
# If Mac, also hash vcpkg cache on Xcode version.
352+
echo "VCPKG_EXTRA_HASH=-xcode${{env.xcodeVersion}}" >> $GITHUB_ENV
353+
fi
311354
312355
- name: Add msbuild to PATH (windows)
313356
if: startsWith(matrix.os, 'windows')
@@ -318,7 +361,7 @@ jobs:
318361
uses: actions/cache@v2
319362
with:
320363
path: external/vcpkg/installed
321-
key: dev-vcpkg-${{ matrix.architecture }}-${{ matrix.vcpkg_triplet_suffix }}-${{ matrix.msvc_runtime }}-${{ matrix.linux_abi }}-${{ hashFiles(format('{0}', env.VCPKG_RESPONSE_FILE)) }}-${{ hashFiles('.git/modules/external/vcpkg/HEAD') }}
364+
key: dev-vcpkg-${{ matrix.architecture }}-${{ matrix.vcpkg_triplet_suffix }}-${{ matrix.msvc_runtime }}-${{ matrix.linux_abi }}-${{ hashFiles(format('{0}', env.VCPKG_RESPONSE_FILE)) }}-${{ hashFiles('.git/modules/external/vcpkg/HEAD') }}${{env.VCPKG_EXTRA_HASH}}
322365

323366
- name: Cache ccache files
324367
if: startsWith(matrix.os, 'ubuntu') || startsWith(matrix.os, 'macos')
@@ -503,15 +546,15 @@ jobs:
503546
variant=$(sdk-src/build_scripts/desktop/get_variant.sh "${pkg}")
504547
additional_flags=(${verbose_flag})
505548
# Several build targets require explicitly-set binutils format to be passed
506-
# to package.sh (and thus, to merge_libraries).
507-
if [[ "${{ matrix.sdk_platform }}" == "darwin" && "${variant}" == "arm64" ]]; then
508-
# MacOS ARM
509-
additional_flags+=(-f mach-o-arm64)
549+
# to package.sh (and thus, to merge_libraries), or use LLVM binutils.
550+
if [[ "${{ matrix.sdk_platform }}" == "darwin" ]]; then
551+
# MacOS: use LLVM binutils for both X64 and ARM64
552+
additional_flags+=(-L)
510553
elif [[ "${{ matrix.sdk_platform }}" == "windows" && "${variant}" == *"/x64/"* ]]; then
511-
# Windows x64
554+
# Windows x64: force input and output target format
512555
additional_flags+=(-f pe-x86-64,pe-bigobj-x86-64)
513556
elif [[ "${{ matrix.sdk_platform }}" == "windows" && "${variant}" == *"/x86/"* ]]; then
514-
# Windows x86
557+
# Windows x86: force input and output target format
515558
additional_flags+=(-f pe-i386,pe-bigobj-i386)
516559
fi
517560
sdk-src/build_scripts/desktop/package.sh -b ${pkg} -o firebase-cpp-sdk-${{ matrix.sdk_platform }}${{ matrix.suffix }}-package -p ${{ matrix.sdk_platform }} -t bin -d ${variant} -P python3 -j ${additional_flags[*]}

.github/workflows/desktop.yml

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,14 @@ jobs:
7676
xcode_version: "12.4"
7777
- os: windows-latest
7878
xcode_version: "12.4"
79+
# arm64 is only for macos
80+
- os: ubuntu-latest
81+
architecture: "arm64"
82+
- os: windows-latest
83+
architecture: "arm64"
84+
# arm64 can't be built on Xcode 11
85+
- xcode_version: "11.7"
86+
architecture: "arm64"
7987
steps:
8088
- name: Setup Xcode version (macos)
8189
if: runner.os == 'macOS'
@@ -114,21 +122,25 @@ jobs:
114122
echo "VCPKG_SUFFIX: ${{env.VCPKG_SUFFIX}}"
115123
echo "VCPKG_RESPONSE_FILE=external/vcpkg_custom_data/response_files/${{ matrix.architecture }}-${{ env.VCPKG_SUFFIX }}.txt" >> $GITHUB_ENV
116124
echo "MATRIX_UNIQUE_NAME=${{ matrix.os }}-${{ matrix.build_type }}-${{ matrix.architecture }}-${{ matrix.msvc_runtime }}" >> $GITHUB_ENV
125+
if [[ '${{ matrix.sdk_platform }}' == 'darwin' ]]; then
126+
# If Mac, also hash vcpkg cache on Xcode version.
127+
echo "VCPKG_EXTRA_HASH=-xcode${{matrix.xcode_version}}" >> $GITHUB_ENV
128+
fi
117129
118130
- name: Cache vcpkg C++ dependencies
119131
id: cache_vcpkg
120132
uses: actions/cache@v2
121133
with:
122134
path: external/vcpkg/installed
123-
key: dev-vcpkg-${{ matrix.architecture }}-${{ env.VCPKG_SUFFIX }}-${{ matrix.msvc_runtime }}-${{ hashFiles(format('{0}', env.VCPKG_RESPONSE_FILE)) }}-${{ hashFiles('.git/modules/external/vcpkg/HEAD') }}
135+
key: dev-vcpkg-${{ matrix.architecture }}-${{ env.VCPKG_SUFFIX }}-${{ matrix.msvc_runtime }}-${{ hashFiles(format('{0}', env.VCPKG_RESPONSE_FILE)) }}-${{ hashFiles('.git/modules/external/vcpkg/HEAD') }}${{ env.VCPKG_EXTRA_HASH }}
124136

125137
- name: Cache ccache files
126138
if: startsWith(matrix.os, 'ubuntu') || startsWith(matrix.os, 'macos')
127139
id: cache_ccache
128140
uses: actions/cache@v2
129141
with:
130142
path: ccache_dir
131-
key: dev-test-ccache-${{ env.MATRIX_UNIQUE_NAME }}
143+
key: dev-test-ccache-${{ env.MATRIX_UNIQUE_NAME }}${{ env.VCPKG_EXTRA_HASH }}
132144

133145
- name: Setup python
134146
uses: actions/setup-python@v2
@@ -193,7 +205,7 @@ jobs:
193205
194206
- name: Run unit tests (windows & macos)
195207
# TODO: Enable tests for x86 once they are all working
196-
if: (startsWith(matrix.os, 'windows') || startsWith(matrix.os, 'macos')) && matrix.architecture != 'x86'
208+
if: (startsWith(matrix.os, 'windows') || startsWith(matrix.os, 'macos')) && matrix.architecture != 'x86' && matrix.architecture != 'arm64'
197209
env:
198210
LANG: en_US
199211
run: |

CMakeLists.txt

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,15 @@ else()
136136
set(DESKTOP OFF)
137137
endif()
138138

139+
# For OSX, if the architectures we are building for do not match the current
140+
# host, treat it as cross-compiling.
141+
if(DESKTOP AND APPLE)
142+
if(NOT "${CMAKE_OSX_ARCHITECTURES}" MATCHES "${CMAKE_HOST_SYSTEM_PROCESSOR}")
143+
message("Cross-compiling ENABLED")
144+
set(CMAKE_CROSSCOMPILING ON CACHE BOOL "" FORCE)
145+
endif()
146+
endif()
147+
139148
if(DESKTOP AND NOT MSVC AND NOT APPLE)
140149
# Linux-specific option.
141150
if (FIREBASE_LINUX_USE_CXX11_ABI)
@@ -305,6 +314,12 @@ endif()
305314

306315
# Include Firestore's external build early to resolve conflicts on packages.
307316
if(FIRESTORE_USE_EXTERNAL_CMAKE_BUILD)
317+
if(APPLE)
318+
# On Apple, set GRPC_BAZEL_BUILD to fix an issue with __thread.
319+
# Setting this define makes gRPC use pthread's thread-local storage
320+
# instead of GCC's.
321+
add_definitions(-DGRPC_BAZEL_BUILD=1)
322+
endif()
308323
set(FIRESTORE_BINARY_DIR ${FIRESTORE_SOURCE_DIR}-build)
309324

310325
if(FIREBASE_CPP_BUILD_TESTS OR FIREBASE_CPP_BUILD_STUB_TESTS)
@@ -329,7 +344,7 @@ set(FLATBUFFERS_FLATHASH OFF CACHE BOOL "")
329344
set(LEVELDB_BUILD_TESTS OFF CACHE BOOL "")
330345

331346
# Disable building flatc if cross compiling
332-
if(IOS OR ANDROID)
347+
if(IOS OR ANDROID OR CMAKE_CROSSCOMPILING)
333348
set(FLATBUFFERS_BUILD_FLATC OFF CACHE BOOL "")
334349
endif()
335350

@@ -367,6 +382,14 @@ if(DESKTOP)
367382
set(CMAKE_USE_LIBSSH2 OFF)
368383
set(HTTP_ONLY ON)
369384
set(BUILD_TESTING OFF)
385+
if(APPLE AND CMAKE_CROSSCOMPILING AND NOT CMAKE_TOOLCHAIN_FILE)
386+
# curl's CMake file checks for CMAKE_TOOLCHAIN_FILE rather than checking
387+
# CMAKE_CROSSCOMPILING when determining whether we are cross-compiling.
388+
# So if CMAKE_CROSSCOMPILING is set and we don't have a CMAKE_TOOLCHAIN_FILE,
389+
# just add a null one now so curl is happy. This only happens on Mac when
390+
# building for arm64/x86_64 on the opposite machine.
391+
set(CMAKE_TOOLCHAIN_FILE /dev/null)
392+
endif()
370393
add_external_library(curl)
371394

372395
add_external_library(libuv)
@@ -402,13 +425,15 @@ if(DESKTOP)
402425
${UWEBSOCKETS_SOURCE_DIR}/src/WebSocket.cpp)
403426
if(MSVC)
404427
set(websockets_additional_defines
428+
${websockets_additional_defines}
405429
-DWIN32_LEAN_AND_MEAN # Ensure that windows doesn't include winsock.h by
406430
# default, as it can cause issues when libraries try
407431
# to include winsock2.h later on in the process.
408432
-DUSE_LIBUV=1
409433
)
410434
elseif(APPLE)
411435
set(websockets_additional_defines
436+
${websockets_additional_defines}
412437
-DUSE_LIBUV=1
413438
)
414439
endif()
@@ -440,7 +465,7 @@ if(DESKTOP)
440465
if(FIRESTORE_USE_EXTERNAL_CMAKE_BUILD)
441466
# The Firestore build includes protobuf and nanopb already
442467
list(APPEND CMAKE_MODULE_PATH ${NANOPB_SOURCE_DIR}/extra)
443-
find_package(Nanopb REQUIRED)
468+
find_package(Nanopb)
444469

445470
set(PROTOBUF_FOUND ON)
446471
else()
@@ -462,7 +487,7 @@ if(DESKTOP)
462487
endif()
463488
endif()
464489

465-
if(DESKTOP)
490+
if(DESKTOP AND NOT CMAKE_CROSSCOMPILING)
466491
# Desktop platforms do not need to declare this dependency, as they will build
467492
# flatc correctly when needed.
468493
set(FIREBASE_FLATBUFFERS_DEPENDENCIES "")

build_scripts/desktop/finish_darwin.sh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ done
5555
# means that the lipo step has already occurred.
5656
if [[ ! -d "${packagepath}/libs/${os}/universal" ]]; then
5757
echo "Repackaging libraries using Mac libtool..."
58-
for arch in "${architectures[*]}"; do
58+
for arch in ${architectures[*]}; do
5959
for lib in "${packagepath}/libs/${os}/${arch}"/*.a; do
6060
pushd $(dirname ${lib}) > /dev/null
6161
libname=$(basename "${lib}")
@@ -89,7 +89,7 @@ fi
8989
echo "Creating frameworks..."
9090
rm -rf "${packagepath}/frameworks/${os}"
9191
mkdir -p "${packagepath}/frameworks/${os}"
92-
for arch in universal "${architectures[*]}"; do
92+
for arch in universal ${architectures[*]}; do
9393
for f in "${packagepath}/libs/${os}/${arch}/"*.a; do
9494
library=$f
9595
framework=$(basename "${library}" | sed 's|^lib||' | sed 's|\.a$||')

build_scripts/desktop/package.sh

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ options:
1818
-f, binutils format default: [auto-detect]
1919
-j, run merge_libraries jobs in parallel
2020
-v, enable verbose mode
21+
-L, use LLVM binutils
2122
example:
2223
build_scripts/desktop/package.sh -b firebase-cpp-sdk-linux -p linux -o package_out -v x86 -j"
2324
}
@@ -35,6 +36,7 @@ built_sdk_tarfile=
3536
binutils_format=
3637
temp_dir=
3738
run_in_parallel=0
39+
use_llvm_binutils=0
3840

3941
. "${root_dir}/build_scripts/packaging.conf"
4042

@@ -48,7 +50,7 @@ abspath(){
4850
fi
4951
}
5052

51-
while getopts "f:b:o:p:d:m:P:t:hjv" opt; do
53+
while getopts "f:b:o:p:d:m:P:t:hjLv" opt; do
5254
case $opt in
5355
f)
5456
binutils_format=$OPTARG
@@ -73,6 +75,9 @@ while getopts "f:b:o:p:d:m:P:t:hjv" opt; do
7375
v)
7476
verbose=1
7577
;;
78+
L)
79+
use_llvm_binutils=1
80+
;;
7681
d)
7782
variant=$OPTARG
7883
;;
@@ -228,13 +233,19 @@ readonly -a rename_namespaces=(flatbuffers flexbuffers reflection ZLib bssl uWS
228233
readonly rename_string=f_b_
229234

230235
readonly demangle_cmds=${tools_path}/c++filt,${tools_path}/demumble
231-
readonly binutils_objcopy=${tools_path}/objcopy
232-
if [[ -x ${tools_path}/nm-new ]] ; then
233-
readonly binutils_nm=${tools_path}/nm-new
234-
else
235-
readonly binutils_nm=${tools_path}/nm
236+
if [[ ${use_llvm_binutils} -eq 1 ]]; then
237+
readonly binutils_objcopy=${tools_path}/llvm-objcopy
238+
readonly binutils_nm=${tools_path}/llvm-nm
239+
readonly binutils_ar=${tools_path}/llvm-ar
240+
else
241+
readonly binutils_objcopy=${tools_path}/objcopy
242+
if [[ -x ${tools_path}/nm-new ]] ; then
243+
readonly binutils_nm=${tools_path}/nm-new
244+
else
245+
readonly binutils_nm=${tools_path}/nm
246+
fi
247+
readonly binutils_ar=${tools_path}/ar
236248
fi
237-
readonly binutils_ar=${tools_path}/ar
238249

239250
cache_file=/tmp/merge_libraries_cache.$$
240251
# Clean up cache file after script is finished.
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
protobuf
2+
zlib
3+
--triplet
4+
arm64-osx

0 commit comments

Comments
 (0)