From 6ed0c112076c522276fa47dea552e047d11a349c Mon Sep 17 00:00:00 2001 From: Siarhei Fedartsou Date: Thu, 15 Sep 2022 15:20:33 +0200 Subject: [PATCH] Configure cross-compilation for Apple Silicon --- .github/workflows/osrm-backend.yml | 88 +++++++++++++++++++++++++----- CHANGELOG.md | 1 + CMakeLists.txt | 15 ++++- scripts/ci/node_package.sh | 48 ++++++++-------- 4 files changed, 113 insertions(+), 39 deletions(-) diff --git a/.github/workflows/osrm-backend.yml b/.github/workflows/osrm-backend.yml index 5264bfaff69..000d9d1930a 100644 --- a/.github/workflows/osrm-backend.yml +++ b/.github/workflows/osrm-backend.yml @@ -234,7 +234,7 @@ jobs: CCOMPILER: gcc-7 CXXCOMPILER: g++-7 - - name: conan-osx-release-node-12 + - name: conan-macos-x64-release-node-12 build_node_package: true continue-on-error: false node: 12 @@ -247,7 +247,7 @@ jobs: ENABLE_ASSERTIONS: ON ENABLE_CONAN: ON - - name: conan-osx-release-node-14 + - name: conan-macos-x64-release-node-14 build_node_package: true continue-on-error: false node: 14 @@ -260,7 +260,7 @@ jobs: ENABLE_ASSERTIONS: ON ENABLE_CONAN: ON - - name: conan-osx-release-node-16 + - name: conan-macos-x64-release-node-16 build_node_package: true continue-on-error: false node: 16 @@ -273,6 +273,20 @@ jobs: ENABLE_ASSERTIONS: ON ENABLE_CONAN: ON + - name: conan-macos-arm64-release-node-16 + build_node_package: true + continue-on-error: false + node: 16 + runs-on: macos-11 + BUILD_TOOLS: ON + BUILD_TYPE: Release + CCOMPILER: clang + CXXCOMPILER: clang++ + CUCUMBER_TIMEOUT: 60000 + ENABLE_ASSERTIONS: ON + ENABLE_CONAN: ON + ENABLE_APPLE_SILICON: ON + - name: gcc-7-release-shared continue-on-error: false node: 12 @@ -356,7 +370,19 @@ jobs: ENABLE_CONAN: ON NODE_PACKAGE_TESTS_ONLY: ON - - name: conan-osx-release-node-latest + - name: conan-macos-x64-release-node-latest + build_node_package: true + continue-on-error: true + node: latest + runs-on: macos-11 + BUILD_TYPE: Release + CCOMPILER: clang + CXXCOMPILER: clang++ + CUCUMBER_TIMEOUT: 60000 + ENABLE_ASSERTIONS: ON + ENABLE_CONAN: ON + + - name: conan-macos-arm64-release-node-latest build_node_package: true continue-on-error: true node: latest @@ -367,6 +393,7 @@ jobs: CUCUMBER_TIMEOUT: 60000 ENABLE_ASSERTIONS: ON ENABLE_CONAN: ON + ENABLE_APPLE_SILICON: ON - name: node-latest-conan-linux-release build_node_package: true @@ -392,7 +419,7 @@ jobs: ENABLE_CONAN: ON NODE_PACKAGE_TESTS_ONLY: ON - - name: conan-osx-release-node-lts + - name: conan-macos-x64-release-node-lts build_node_package: true continue-on-error: true node: "lts/*" @@ -403,6 +430,19 @@ jobs: CUCUMBER_TIMEOUT: 60000 ENABLE_ASSERTIONS: ON ENABLE_CONAN: ON + + - name: conan-macos-arm64-release-node-lts + build_node_package: true + continue-on-error: true + node: "lts/*" + runs-on: macos-11 + BUILD_TYPE: Release + CCOMPILER: clang + CXXCOMPILER: clang++ + CUCUMBER_TIMEOUT: 60000 + ENABLE_ASSERTIONS: ON + ENABLE_CONAN: ON + ENABLE_APPLE_SILICON: ON - name: node-lts-conan-linux-release build_node_package: true @@ -447,6 +487,7 @@ jobs: ENABLE_CONAN: ${{ matrix.ENABLE_CONAN }} ENABLE_SANITIZER: ${{ matrix.ENABLE_SANITIZER }} NODE_PACKAGE_TESTS_ONLY: ${{ matrix.NODE_PACKAGE_TESTS_ONLY }} + ENABLE_APPLE_SILICON: ${{ matrix.ENABLE_APPLE_SILICON }} TARGET_ARCH: ${{ matrix.TARGET_ARCH }} OSRM_CONNECTION_RETRIES: ${{ matrix.OSRM_CONNECTION_RETRIES }} OSRM_CONNECTION_EXP_BACKOFF_COEF: ${{ matrix.OSRM_CONNECTION_EXP_BACKOFF_COEF }} @@ -475,9 +516,9 @@ jobs: uses: actions/cache@v2 with: path: ~/.conan - key: v4-conan-${{ matrix.name }}-${{ github.sha }} + key: v6-conan-${{ matrix.name }}-${{ github.sha }} restore-keys: | - v4-conan-${{ matrix.name }}- + v6-conan-${{ matrix.name }}- - name: Enable test cache uses: actions/cache@v2 with: @@ -583,6 +624,16 @@ jobs: echo "Using ${JOBS} jobs" pushd ${OSRM_BUILD_DIR} + # handle Apple Silicon cross compilation + if [[ "${ENABLE_APPLE_SILICON}" == "ON" ]]; then + ARCH=arm64 + TARGET="${ARCH}-apple-darwin" + CFLAGS="$CFLAGS --target=$TARGET" + CXXFLAGS="$CXXFLAGS --target=$TARGET" + APPLE_SILICON_FLAGS=(-DCMAKE_C_COMPILER_TARGET="$TARGET" -DCMAKE_CXX_COMPILER_TARGET="$TARGET" -DCMAKE_SYSTEM_PROCESSOR="${ARCH}" -DCMAKE_SYSTEM_NAME="Darwin" -DCMAKE_C_FLAGS="$CFLAGS" -DCMAKE_CXX_FLAGS="$CXXFLAGS") + else + APPLE_SILICON_FLAGS=() + fi cmake .. -DCMAKE_BUILD_TYPE=${BUILD_TYPE} \ -DENABLE_CONAN=${ENABLE_CONAN:-OFF} \ -DENABLE_ASSERTIONS=${ENABLE_ASSERTIONS:-OFF} \ @@ -594,10 +645,11 @@ jobs: -DBUILD_TOOLS=${BUILD_TOOLS:-OFF} \ -DENABLE_CCACHE=ON \ -DCMAKE_INSTALL_PREFIX=${OSRM_INSTALL_DIR} \ - -DENABLE_GLIBC_WORKAROUND=${ENABLE_GLIBC_WORKAROUND:-OFF} + -DENABLE_GLIBC_WORKAROUND=${ENABLE_GLIBC_WORKAROUND:-OFF} \ + "${APPLE_SILICON_FLAGS[@]}" make --jobs=${JOBS} - if [[ "${NODE_PACKAGE_TESTS_ONLY}" != "ON" ]]; then + if [[ "${NODE_PACKAGE_TESTS_ONLY}" != "ON" && "${ENABLE_APPLE_SILICON}" != "ON" ]]; then make tests --jobs=${JOBS} make benchmarks --jobs=${JOBS} ccache -s @@ -609,7 +661,7 @@ jobs: fi popd - name: Build example - if: ${{ matrix.NODE_PACKAGE_TESTS_ONLY != 'ON' }} + if: ${{ matrix.NODE_PACKAGE_TESTS_ONLY != 'ON' && matrix.ENABLE_APPLE_SILICON != 'ON' }} run: | mkdir example/build && pushd example/build cmake .. -DCMAKE_BUILD_TYPE=${BUILD_TYPE} @@ -617,7 +669,7 @@ jobs: popd - name: Run all tests - if: ${{ matrix.NODE_PACKAGE_TESTS_ONLY != 'ON' }} + if: ${{ matrix.NODE_PACKAGE_TESTS_ONLY != 'ON' && matrix.ENABLE_APPLE_SILICON != 'ON' }} run: | make -C test/data benchmark @@ -634,7 +686,7 @@ jobs: popd npm test - name: Run Node package tests only - if: ${{ matrix.NODE_PACKAGE_TESTS_ONLY == 'ON' }} + if: ${{ matrix.NODE_PACKAGE_TESTS_ONLY == 'ON' && matrix.ENABLE_APPLE_SILICON != 'ON' }} run: | npm run nodejs-tests - name: Upload test logs @@ -659,9 +711,17 @@ jobs: name: codecov-osrm-backend fail_ci_if_error: true verbose: true - + - name: Check Apple Silicon binary + if: ${{ matrix.ENABLE_APPLE_SILICON == 'ON' }} + run: | + ARCH=$(file ./lib/binding/node_osrm.node | awk '{printf $NF}') + if [[ "$ARCH" != "arm64" ]]; then + file ./lib/binding/node_osrm.node + >&2 echo "Wrong architecture!" + exit 1 + fi - name: Build Node package - if: ${{ matrix.build_node_package && env.PUBLISH == 'On' }} + if: ${{ matrix.build_node_package }} run: ./scripts/ci/node_package.sh - name: Publish Node package if: ${{ matrix.build_node_package && env.PUBLISH == 'On' }} diff --git a/CHANGELOG.md b/CHANGELOG.md index 8b6f8bb7a20..324f83757de 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,7 @@ - FIXED: Bug in bicycle profile that caused exceptions if there is a highway=bicycle in the data. [#6296](https://github.com/Project-OSRM/osrm-backend/pull/6296) - FIXED: Internal refactoring of identifier types used in data facade [#6044](https://github.com/Project-OSRM/osrm-backend/pull/6044) - Build: + - ADDED: Configure cross-compilation for Apple Silicon. [#6360](https://github.com/Project-OSRM/osrm-backend/pull/6360) - CHANGED: Use apt-get to install Clang on CI. [#6345](https://github.com/Project-OSRM/osrm-backend/pull/6345) - CHANGED: Fix TBB in case of Conan + NodeJS build. [#6333](https://github.com/Project-OSRM/osrm-backend/pull/6333) - CHANGED: Migrate to modern TBB version. [#6300](https://github.com/Project-OSRM/osrm-backend/pull/6300) diff --git a/CMakeLists.txt b/CMakeLists.txt index 46acc13d9b1..db0149e1fde 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -61,6 +61,15 @@ if (POLICY CMP0074) endif() project(OSRM C CXX) +# add @loader_path/$ORIGIN to rpath to make binaries relocatable +if (APPLE) + set(CMAKE_BUILD_RPATH "@loader_path") +else() + set(CMAKE_BUILD_RPATH "\$ORIGIN") + # https://stackoverflow.com/questions/6324131/rpath-origin-not-having-desired-effect + set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,-z,origin") +endif() + include(JSONParser) file(READ "package.json" packagejsonraw) sbeParseJson(packagejson packagejsonraw) @@ -185,7 +194,7 @@ if(ENABLE_GOLD_LINKER) execute_process(COMMAND ${CMAKE_C_COMPILER} -fuse-ld=gold -Wl,--version ERROR_QUIET OUTPUT_VARIABLE LD_VERSION) if("${LD_VERSION}" MATCHES "GNU gold") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fuse-ld=gold -Wl,--disable-new-dtags") - set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fuse-ld=gold -Wl,--disable-new-dtags") + set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -fuse-ld=gold -Wl,--disable-new-dtags") set(OSRM_LDFLAGS "${OSRM_LDFLAGS} -fuse-ld=gold -Wl,--disable-new-dtags") message(STATUS "Using GNU gold as linker.") @@ -489,11 +498,15 @@ if(ENABLE_CONAN) NO_OUTPUT_DIRS OPTIONS boost:filesystem_version=3 # https://stackoverflow.com/questions/73392648/error-with-boost-filesystem-version-in-cmake onetbb:shared=${TBB_SHARED} + boost:without_stacktrace=True # Apple Silicon cross-compilation fails without it BUILD missing ) # explicitly say Conan to use x86 dependencies if build for x86 platforms (https://github.com/conan-io/cmake-conan/issues/141) if(NOT CMAKE_SIZEOF_VOID_P EQUAL 8) conan_cmake_run("${CONAN_ARGS};ARCH;x86") + # cross-compilation for Apple Silicon + elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL "arm64" AND CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL "x86_64") + conan_cmake_run("${CONAN_ARGS};ARCH;armv8") else() conan_cmake_run("${CONAN_ARGS}") endif() diff --git a/scripts/ci/node_package.sh b/scripts/ci/node_package.sh index fd62c8adb7e..8df7c50e059 100755 --- a/scripts/ci/node_package.sh +++ b/scripts/ci/node_package.sh @@ -7,31 +7,31 @@ echo "node version is:" which node node -v -if [[ ${PUBLISH} == 'On' ]]; then - echo "PUBLISH is set to '${PUBLISH}', publishing!" - NPM_FLAGS='' - if [[ ${BUILD_TYPE} == "Debug" ]]; then - NPM_FLAGS='--debug' - fi +NPM_FLAGS='' +if [[ ${BUILD_TYPE} == "Debug" ]]; then + NPM_FLAGS='--debug' +fi + +# append --target_arch in order to handle cross-compilation for Apple Silicon +if [[ "$ENABLE_APPLE_SILICON" == "ON" ]]; then + NPM_FLAGS="${NPM_FLAGS} --target_arch=arm64" +fi - echo "dumping binary meta..." - ./node_modules/.bin/node-pre-gyp reveal $NPM_FLAGS +echo "dumping binary meta..." +./node_modules/.bin/node-pre-gyp reveal $NPM_FLAGS - # enforce that binary has proper ORIGIN flags so that - # it can portably find libtbb.so in the same directory - if [[ $(uname -s) == 'Linux' ]]; then - readelf -d ./lib/binding/node_osrm.node > readelf-output.txt - if grep -q 'Flags: ORIGIN' readelf-output.txt; then - echo "Found ORIGIN flag in readelf output" - cat readelf-output.txt - else - echo "*** Error: Could not found ORIGIN flag in readelf output" - cat readelf-output.txt - exit 1 - fi +# enforce that binary has proper ORIGIN flags so that +# it can portably find libtbb.so in the same directory +if [[ $(uname -s) == 'Linux' ]]; then + readelf -d ./lib/binding/node_osrm.node > readelf-output.txt + if grep -q 'Flags: ORIGIN' readelf-output.txt; then + echo "Found ORIGIN flag in readelf output" + cat readelf-output.txt + else + echo "*** Error: Could not found ORIGIN flag in readelf output" + cat readelf-output.txt + exit 1 fi - - ./node_modules/.bin/node-pre-gyp package testpackage $NPM_FLAGS -else - echo "PUBLISH is set to '${PUBLISH}', skipping." fi + +./node_modules/.bin/node-pre-gyp package testpackage $NPM_FLAGS