Skip to content

Commit a4a173e

Browse files
siticssheorey
andauthored
Add macOS arm64 CI runner, fix macOS arm64 builds, fused multi-platform viewer app and python wheels (#6695)
* Test macOS arm64 runner * Use matrix to run jobs for both Intel and Apple SIlicon * cleanup workflow, try to fix libomp related issue * Fuse x64 and arm64 wheels, fix wheel naming & unit tests * embree 4.3.1: fix macOS arm64 compile * Add prebuilt arm64 filament binaries * Fuse viewer app * Documentation CI fix by adding lxml[html_clean] to requirements. * Fix for uploading linux CUDA artifacts to github name clash --------- Co-authored-by: Sameer Sheorey <sameer.sheorey@intel.com>
1 parent 1562468 commit a4a173e

File tree

15 files changed

+373
-78
lines changed

15 files changed

+373
-78
lines changed

.github/workflows/macos.yml

Lines changed: 182 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,13 @@ env:
2626

2727
jobs:
2828
MacOS:
29-
runs-on: macos-12
29+
runs-on: ${{ matrix.os }}
3030
strategy:
3131
fail-fast: false
3232
matrix:
33+
# macos-12 is Intel runner, macos-14 is Apple Silicon
34+
# https://github.com/actions/runner-images
35+
os: [macos-12, macos-14]
3336
CONFIG: [ON, OFF]
3437
env:
3538
BUILD_SHARED_LIBS: ${{ matrix.CONFIG }}
@@ -47,26 +50,49 @@ jobs:
4750
path: ~/.ccache
4851
# We include the commit sha in the cache key, as new cache entries are
4952
# only created if there is no existing entry for the key yet.
50-
key: ${{ runner.os }}-ccache-${{ github.sha }}
53+
key: ${{ runner.os }}-${{ runner.arch }}-ccache-${{ github.sha }}
5154
# Restore any ccache cache entry, if none for
52-
# ${{ runner.os }}-ccache-${{ github.sha }} exists.
55+
# ${{ runner.os }}-${{ runner.arch }}-ccache-${{ github.sha }} exists.
5356
# Common prefix will be used so that ccache can be used across commits.
5457
restore-keys: |
55-
${{ runner.os }}-ccache
58+
${{ runner.os }}-${{ runner.arch }}-ccache
59+
5660
- name: Set up Python version
5761
uses: actions/setup-python@v5
5862
with:
59-
python-version: 3.8
63+
python-version: '3.11'
64+
6065
- name: Install dependencies
6166
run: |
6267
brew install ccache pkg-config
63-
# Install libomp 11.1.0 from old brew bottle for catalina (10.15).
64-
# Directly installing the Ruby formula will install for the current OS
68+
69+
if [[ ${{ runner.arch}} == "ARM64" ]]; then
70+
# Fix gfortran not found issue
71+
ln -s $(which gfortran-13) /usr/local/bin/gfortran
72+
73+
# Default macos-14 image Xcode (version 15.0.1) linker causes build issues.
74+
# Newer Xcode versions work, but embree recommends Apple clang <= 14 on
75+
# arm64 to avoid possible "EXEC_BAD_INSTRUCTION" runtime exceptions:
76+
# https://github.com/embree/embree/releases/tag/v4.3.1
77+
sudo xcode-select -switch /Applications/Xcode_14.3.1.app
78+
fi
79+
80+
# Install libomp 11.1.0 from old brew bottle for x64 catalina (10.15)
81+
# / arm64 big sur (11.0). Directly installing the Ruby formula will
82+
# install for the current OS.
6583
# https://github.com/microsoft/LightGBM/issues/4229
66-
brew unlink libomp
67-
curl -L -H "Authorization: Bearer QQ==" -o libomp-11.1.0.catalina.bottle.tar.gz \
68-
https://ghcr.io/v2/homebrew/core/libomp/blobs/sha256:45a5aa653bd45bd5ff5858580b1a4670c4b5a51ea29d68d45a53f72f56010e05
69-
brew install -f libomp-11.1.0.catalina.bottle.tar.gz
84+
if [[ ${{ runner.arch}} == "X64" ]]; then
85+
brew unlink libomp
86+
# x64 catalina (10.15) bottle
87+
export LIBOMP_BOTTLE_HASH=45a5aa653bd45bd5ff5858580b1a4670c4b5a51ea29d68d45a53f72f56010e05
88+
else # ARM64
89+
# arm64 big_sur (11.0) bottle
90+
export LIBOMP_BOTTLE_HASH=f87f7841eb8b72650fa771af39642361aec371ea1a1f94f081ecc0e8168a0e75
91+
fi
92+
curl -L -H "Authorization: Bearer QQ==" -o libomp-11.1.0.bottle.tar.gz \
93+
https://ghcr.io/v2/homebrew/core/libomp/blobs/sha256:$LIBOMP_BOTTLE_HASH
94+
brew install -f libomp-11.1.0.bottle.tar.gz
95+
7096
ccache -M 2G # See .github/workflows/readme.md for ccache strategy.
7197
- name: Config and build
7298
run: |
@@ -82,7 +108,7 @@ jobs:
82108
pushd build
83109
make -j${NPROC} Open3DViewer
84110
pushd bin
85-
zip -rv open3d-app-macosx-10_15.zip Open3D.app
111+
zip -rv open3d-app-macosx-10_15-${{ runner.arch}}.zip Open3D.app
86112
ccache -s
87113
88114
- name: Upload package
@@ -116,21 +142,58 @@ jobs:
116142
uses: actions/upload-artifact@v4
117143
if: ${{ env.BUILD_SHARED_LIBS == 'OFF' }}
118144
with:
119-
name: open3d-app-macosx-10_15
120-
path: build/bin/open3d-app-macosx-10_15.zip
145+
name: open3d-app-macosx-10_15-${{ runner.arch}}
146+
path: build/bin/open3d-app-macosx-10_15-${{ runner.arch}}.zip
147+
if-no-files-found: error
148+
149+
fuse-viewer:
150+
name: Fuse x64 and ARM64 viewer app
151+
runs-on: [macos-12]
152+
needs: [MacOS]
153+
steps:
154+
- name: Download viewer apps
155+
uses: actions/download-artifact@v4
156+
with:
157+
pattern: open3d-app-macosx-10_15-*
158+
merge-multiple: true
159+
160+
- name: Fuse x64 and arm64 viewer apps
161+
run: |
162+
unzip open3d-app-macosx-10_15-X64.zip -d x64
163+
unzip open3d-app-macosx-10_15-ARM64.zip -d arm64
164+
for i in arm64/Open3D.app/Contents/MacOS/*; do
165+
filepath=Open3D.app/Contents/MacOS/$(basename $i)
166+
lipo -create arm64/${filepath} x64/${filepath} -output arm64/${filepath}
167+
done
168+
mv arm64/Open3D.app Open3D.app
169+
zip -rv open3d-app-macosx-10_15-universal2.zip Open3D.app
170+
171+
- name: Upload Open3D viewer app
172+
uses: actions/upload-artifact@v4
173+
with:
174+
name: open3d-app-macosx-10_15-universal2
175+
path: open3d-app-macosx-10_15-universal2.zip
121176
if-no-files-found: error
122177

123178
build-wheel:
124179
name: Build wheel
125-
runs-on: macos-12
180+
runs-on: ${{ matrix.os }}
126181
strategy:
127182
fail-fast: false
128183
# https://github.yungao-tech.community/t/how-to-conditionally-include-exclude-items-in-matrix-eg-based-on-branch/16853/6
129184
matrix:
185+
# macos-12 is Intel runner, macos-14 is Apple Silicon
186+
# https://github.com/actions/runner-images
187+
os: [macos-12, macos-14]
130188
python_version: ['3.8', '3.9', '3.10', '3.11']
131189
is_main:
132190
- ${{ github.ref == 'refs/heads/main' }}
133191
exclude:
192+
# TODO: remove macos-14 excludes when https://github.com/actions/setup-python/issues/808 is fixed
193+
- os: macos-14
194+
python_version: '3.8'
195+
- os: macos-14
196+
python_version: '3.9'
134197
- is_main: false
135198
python_version: '3.8'
136199
- is_main: false
@@ -158,12 +221,12 @@ jobs:
158221
path: ~/.ccache
159222
# We include the commit sha in the cache key, as new cache entries are
160223
# only created if there is no existing entry for the key yet.
161-
key: ${{ runner.os }}-ccache-${{ github.sha }}
224+
key: ${{ runner.os }}-${{ runner.arch }}-ccache-${{ github.sha }}
162225
# Restore any ccache cache entry, if none for
163-
# ${{ runner.os }}-ccache-${{ github.sha }} exists.
226+
# ${{ runner.os }}-${{ runner.arch }}-ccache-${{ github.sha }} exists.
164227
# Common prefix will be used so that ccache can be used across commits.
165228
restore-keys: |
166-
${{ runner.os }}-ccache
229+
${{ runner.os }}-${{ runner.arch }}-ccache
167230
168231
- name: Set up Python
169232
uses: actions/setup-python@v5
@@ -180,12 +243,26 @@ jobs:
180243
cmake --version
181244
source util/ci_utils.sh
182245
install_python_dependencies
246+
247+
# Fix macos-14 arm64 runner image issues, see comments in MacOS job.
248+
if [[ ${{ runner.arch}} == "ARM64" ]]; then
249+
ln -s $(which gfortran-13) /usr/local/bin/gfortran
250+
sudo xcode-select -switch /Applications/Xcode_14.3.1.app
251+
fi
252+
183253
# Install libomp 11.1.0. See comment above.
254+
if [[ ${{ runner.arch}} == "X64" ]]; then
255+
brew unlink libomp
256+
# x64 catalina (10.15) bottle
257+
export LIBOMP_BOTTLE_HASH=45a5aa653bd45bd5ff5858580b1a4670c4b5a51ea29d68d45a53f72f56010e05
258+
else # ARM64
259+
# arm64 big_sur (11.0) bottle
260+
export LIBOMP_BOTTLE_HASH=f87f7841eb8b72650fa771af39642361aec371ea1a1f94f081ecc0e8168a0e75
261+
fi
262+
curl -L -H "Authorization: Bearer QQ==" -o libomp-11.1.0.bottle.tar.gz \
263+
https://ghcr.io/v2/homebrew/core/libomp/blobs/sha256:$LIBOMP_BOTTLE_HASH
264+
brew install -f libomp-11.1.0.bottle.tar.gz
184265
brew install ccache
185-
brew unlink libomp
186-
curl -L -H "Authorization: Bearer QQ==" -o libomp-11.1.0.catalina.bottle.tar.gz \
187-
https://ghcr.io/v2/homebrew/core/libomp/blobs/sha256:45a5aa653bd45bd5ff5858580b1a4670c4b5a51ea29d68d45a53f72f56010e05
188-
brew install -f libomp-11.1.0.catalina.bottle.tar.gz
189266
ccache -M 2G # See .github/workflows/readme.md for ccache strategy.
190267
191268
- name: Config and build wheel
@@ -227,17 +304,97 @@ jobs:
227304
gsutil cp build/lib/python_package/pip_package/${{ env.PIP_PKG_NAME }} gs://open3d-releases/python-wheels/
228305
echo "Download pip package at: https://storage.googleapis.com/open3d-releases/python-wheels/${{ env.PIP_PKG_NAME }}"
229306
307+
fuse-wheel:
308+
name: Fuse universal2 wheel
309+
runs-on: [macos-12]
310+
needs: [build-wheel]
311+
strategy:
312+
fail-fast: false
313+
# https://github.yungao-tech.community/t/how-to-conditionally-include-exclude-items-in-matrix-eg-based-on-branch/16853/6
314+
matrix:
315+
python_version: ['3.10', '3.11']
316+
is_main:
317+
- ${{ github.ref == 'refs/heads/main' }}
318+
exclude:
319+
- is_main: false
320+
python_version: '3.10'
321+
steps:
322+
- name: Set up Python
323+
uses: actions/setup-python@v5
324+
with:
325+
python-version: ${{ matrix.python_version }}
326+
- name: Download X64 wheels
327+
uses: actions/download-artifact@v4
328+
with:
329+
pattern: open3d-*macosx*_x86_64.whl
330+
path: x64_wheels
331+
merge-multiple: true
332+
- name: Download ARM64 wheels
333+
uses: actions/download-artifact@v4
334+
with:
335+
pattern: open3d-*macosx*_arm64.whl
336+
path: arm64_wheels
337+
merge-multiple: true
338+
- name: Fuse x64 and ARM64 wheels
339+
env:
340+
python_version: ${{ matrix.python_version }}
341+
run: |
342+
PYTAG="-cp$(echo ${{ env.python_version }} | tr -d '.')"
343+
mkdir universal_wheels
344+
345+
pip install delocate
346+
delocate-fuse -v x64_wheels/open3d-*${PYTAG}*.whl arm64_wheels/open3d-*${PYTAG}*.whl
347+
348+
# Normalize file name as delocate-fuse doesn't update it
349+
OLD_WHL_NAME=$(basename x64_wheels/open3d-*${PYTAG}*.whl)
350+
NEW_WHL_NAME=${OLD_WHL_NAME/x86_64/universal2}
351+
mv x64_wheels/${OLD_WHL_NAME} universal_wheels/${NEW_WHL_NAME}
352+
353+
echo "PIP_PKG_NAME=$NEW_WHL_NAME" >> $GITHUB_ENV
354+
- name: Upload merged wheels
355+
uses: actions/upload-artifact@v4
356+
with:
357+
name: ${{ env.PIP_PKG_NAME }}
358+
path: universal_wheels/${{ env.PIP_PKG_NAME }}
359+
if-no-files-found: error
360+
361+
- name: GCloud CLI auth
362+
if: ${{ github.ref == 'refs/heads/main' }}
363+
uses: 'google-github-actions/auth@v2'
364+
with:
365+
project_id: ${{ secrets.GCE_PROJECT }}
366+
credentials_json: '${{ secrets.GCE_SA_KEY_GPU_CI }}'
367+
- name: GCloud CLI setup
368+
if: ${{ github.ref == 'refs/heads/main' }}
369+
uses: google-github-actions/setup-gcloud@v2
370+
with:
371+
version: ${{ env.GCE_CLI_GHA_VERSION }}
372+
project_id: ${{ secrets.GCE_PROJECT }}
373+
374+
- name: Upload wheel to GCS bucket
375+
if: ${{ github.ref == 'refs/heads/main' }}
376+
env:
377+
python_version: ${{ matrix.python_version }}
378+
run: |
379+
gsutil cp universal_wheels/${{ env.PIP_PKG_NAME }} gs://open3d-releases/python-wheels/
380+
echo "Download pip package at: https://storage.googleapis.com/open3d-releases/python-wheels/${{ env.PIP_PKG_NAME }}"
381+
230382
test-wheel:
231383
name: Test wheel
232-
runs-on: macos-12
384+
runs-on: ${{ matrix.os }}
233385
needs: [build-wheel]
234386
strategy:
235387
fail-fast: false
236388
matrix:
389+
os: [macos-12, macos-14]
237390
python_version: ['3.8', '3.9', '3.10', '3.11']
238391
is_main:
239392
- ${{ github.ref == 'refs/heads/main' }}
240393
exclude:
394+
- os: macos-14
395+
python_version: '3.8'
396+
- os: macos-14
397+
python_version: '3.9'
241398
- is_main: false
242399
python_version: '3.8'
243400
- is_main: false
@@ -273,7 +430,7 @@ jobs:
273430
python -V
274431
source util/ci_utils.sh
275432
pi_tag=$(python -c "import sys; print(f'cp{sys.version_info.major}{sys.version_info.minor}')")
276-
test_wheel open3d*-"$pi_tag"-*.whl
433+
test_wheel open3d*-"$pi_tag"-*_$(uname -m).whl
277434
278435
- name: Run Python unit tests (benchmarks)
279436
run: |
@@ -286,7 +443,7 @@ jobs:
286443
# no need to run on macOS
287444
runs-on: ubuntu-latest
288445
if: ${{ github.ref == 'refs/heads/main' }}
289-
needs: [build-wheel, MacOS]
446+
needs: [fuse-wheel, MacOS]
290447
steps:
291448
- name: GCloud CLI auth
292449
uses: 'google-github-actions/auth@v2'

.github/workflows/ubuntu-cuda.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ jobs:
152152
if: ${{ env.BUILD_PACKAGE == 'true' }}
153153
uses: actions/upload-artifact@v4
154154
with:
155-
name: open3d-devel-linux-x86_64-cuda-${CI_CONFIG}
155+
name: open3d-devel-linux-x86_64-cuda-${{ matrix.CI_CONFIG }}
156156
path: open3d-devel-linux*.tar.xz
157157
if-no-files-found: error
158158

3rdparty/embree/embree.cmake

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,11 @@ include(ExternalProject)
88
# select ISAs
99
if(APPLE)
1010
if(APPLE_AARCH64)
11-
# Turn off ISA optimizations for Apple ARM64 for now.
12-
set(ISA_ARGS -DEMBREE_ISA_AVX=OFF
13-
-DEMBREE_ISA_AVX2=OFF
14-
-DEMBREE_ISA_AVX512=OFF
15-
-DEMBREE_ISA_SSE2=OFF
16-
-DEMBREE_ISA_SSE42=OFF
11+
set(ISA_ARGS -DEMBREE_ISA_NEON=OFF
12+
-DEMBREE_ISA_NEON2X=ON
1713
)
14+
set(ISA_LIBS embree_avx2)
15+
set(ISA_BUILD_BYPRODUCTS "<INSTALL_DIR>/${Open3D_INSTALL_LIB_DIR}/${CMAKE_STATIC_LIBRARY_PREFIX}embree_avx2${CMAKE_STATIC_LIBRARY_SUFFIX}")
1816
else()
1917
# With AppleClang we can select only 1 ISA.
2018
set(ISA_ARGS -DEMBREE_ISA_AVX=OFF

3rdparty/filament/filament_build.cmake

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,5 +72,6 @@ ExternalProject_Add(
7272
-DFILAMENT_SUPPORTS_VULKAN=OFF
7373
-DFILAMENT_SKIP_SAMPLES=ON
7474
-DFILAMENT_OPENGL_HANDLE_ARENA_SIZE_IN_MB=20 # to support many small entities
75+
-DSPIRV_WERROR=OFF
7576
BUILD_BYPRODUCTS ${lib_byproducts}
7677
)

3rdparty/filament/filament_download.cmake

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,17 @@ else()
2626
string(APPEND lib_dir /x86_64/md)
2727
endif()
2828
elseif(APPLE)
29-
set(FILAMENT_URL https://github.com/google/filament/releases/download/v1.9.19/filament-v1.9.19-mac.tgz)
30-
set(FILAMENT_SHA256 2765d0ce60647fc17d1880c4618cf7d6b5343d8be4dad87978c3917d9c723b4e)
31-
string(APPEND lib_dir /x86_64)
29+
if (APPLE_AARCH64)
30+
set(FILAMENT_URL https://github.com/isl-org/open3d_downloads/releases/download/filament/filament-v1.9.19-macos_arm64.tgz)
31+
set(FILAMENT_SHA256 3422bdff451d90144fbb69e625d8dcaeaf3222dc2c28879536067937955bc362)
32+
string(APPEND lib_dir /arm64)
33+
# Our arm64 builds use FILAMENT_SUPPORTS_VULKAN=OFF
34+
list(REMOVE_ITEM filament_LIBRARIES bluevk)
35+
else()
36+
set(FILAMENT_URL https://github.com/google/filament/releases/download/v1.9.19/filament-v1.9.19-mac.tgz)
37+
set(FILAMENT_SHA256 2765d0ce60647fc17d1880c4618cf7d6b5343d8be4dad87978c3917d9c723b4e)
38+
string(APPEND lib_dir /x86_64)
39+
endif()
3240
else() # Linux: Check glibc version and use open3d filament binary if new (Ubuntu 20.04 and similar)
3341
execute_process(COMMAND ldd --version OUTPUT_VARIABLE ldd_version)
3442
string(REGEX MATCH "([0-9]+\.)+[0-9]+" glibc_version ${ldd_version})
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
From beb4c44debc8336de991c983274cad841eb5c323 Mon Sep 17 00:00:00 2001
2+
From: Pavol Rusnak <pavol@rusnak.io>
3+
Date: Sun, 20 Jun 2021 12:26:58 +0200
4+
Subject: [PATCH] Fix build on macOS arm64
5+
6+
---
7+
src/proc/color-formats-converter.cpp | 2 +-
8+
1 file changed, 1 insertion(+), 1 deletion(-)
9+
10+
diff --git a/src/proc/color-formats-converter.cpp b/src/proc/color-formats-converter.cpp
11+
index 564a23d9c4..6c6c8c97d8 100644
12+
--- a/src/proc/color-formats-converter.cpp
13+
+++ b/src/proc/color-formats-converter.cpp
14+
@@ -18,7 +18,7 @@
15+
#include <tmmintrin.h> // For SSSE3 intrinsics
16+
#endif
17+
18+
-#if defined (ANDROID) || (defined (__linux__) && !defined (__x86_64__))
19+
+#if defined (ANDROID) || (defined (__linux__) && !defined (__x86_64__)) || (defined (__APPLE__) && !defined (__x86_64__))
20+
21+
bool has_avx() { return false; }
22+

3rdparty/librealsense/librealsense.cmake

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ ExternalProject_Add(
1717
COMMAND ${GIT_EXECUTABLE} init
1818
COMMAND ${GIT_EXECUTABLE} apply --ignore-space-change --ignore-whitespace
1919
${CMAKE_CURRENT_LIST_DIR}/fix-cudacrt.patch
20+
# Patch for macOS ARM64 support for versions < 2.50.0
21+
COMMAND ${GIT_EXECUTABLE} apply --ignore-space-change --ignore-whitespace
22+
${CMAKE_CURRENT_LIST_DIR}/fix-macos-arm64.patch
2023
CMAKE_ARGS
2124
-DCMAKE_INSTALL_PREFIX=<INSTALL_DIR>
2225
-DBUILD_SHARED_LIBS=OFF

0 commit comments

Comments
 (0)