mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-05 23:41:44 +00:00
b0ef47819f
# Why this exists
The bonsai macOS CI (`build_osx.yml`, arm64) currently fails the
`IfcOpenShell-Python` smoke test with:
ImportError: dlopen(.../_ifcopenshell_wrapper.cpython-311-darwin.so,
0x0002):
Library not loaded: @rpath/ifcopenshell.document.rdb.dylib
Reason: tried: '$ORIGIN/ifcopenshell.document.rdb.dylib'
(no such file)
`_ifcopenshell_wrapper.cpython-311-darwin.so` has a hard `LC_LOAD_DYLIB`
of `@rpath/ifcopenshell.document.rdb.dylib` and its only `LC_RPATH` is
`$ORIGIN` (= `site-packages/ifcopenshell/`). The plug-in dylib is not
present at that path on macOS, so the wrapper fails to load and the
build smoke test (`build-all.py: compile_python_wrapper`) errors out.
BonsaiViewer.app builds, installs, and macdeployqt-deploys cleanly
before this point — the failure is downstream and unrelated to wgpu,
BonsaiViewer, or anything else on this branch.
# Where the regression came from
Two commits on the branch line that became `ifcviewer-wgpu`:
b599ee10 "More work on isolating into plug-ins" (2026-04-18, Thomas Krijnen)
b022ca7e7 "Some plug-in work" (2026-04-21, Thomas Krijnen)
`b599ee10` added a hard link dep:
target_link_libraries(ifcopenshell_wrapper PRIVATE document_serializer_rdb)
which bakes `@rpath/ifcopenshell.document.rdb.dylib` into the wrapper's
`LC_LOAD_DYLIB`. `b022ca7e7` added a `if(CREATE_BUNDLE) ...
install(TARGETS ${_ifcopenshell_python_runtime_targets}
LIBRARY DESTINATION "${python_package_dir}/ifcopenshell" ...)` block
that was *intended* to satisfy that link dep by copying plug-ins next
to the wrapper. On macOS arm64 the install rule does not actually
deposit `ifcopenshell.document.rdb.dylib` into
`site-packages/ifcopenshell/`, so the runtime dlopen fails.
# Why 227d85d worked
`227d85d` (2026-05-15) is on the `v0.8.0` line, not on the
`datamodel-v1.0 -> ifcviewer -> ifcviewer-wgpu` line. The merge-base
of `227d85d` and `ifcviewer-wgpu` is `e6258ab4` (2026-04-13). Both
b599ee10 and b022ca7e7 live on the wgpu side of that fork and are not
ancestors of `227d85d`:
$ git merge-base --is-ancestor b599ee10 227d85d
[exit 1 — NOT an ancestor]
$ git merge-base --is-ancestor b599ee10 v0.8.0
[exit 1 — NOT an ancestor]
So the macOS Python wheel built fine on `v0.8.0` because that branch
never had the plug-in refactor; it has been broken on our branch line
since 2026-04-21. Nobody noticed because nobody had been firing
`build_osx.yml` against this branch line until this week's bonsai CI
work.
# What this commit does
Adds an `IFCOS_BUILD_PYTHON_WRAPPER` env var to `nix/build-all.py`.
Defaulting to `on` preserves existing behaviour everywhere; setting
it to `off` (or `0`/`false`/`no`) drops `IfcOpenShell-Python` from
the target set so `build-all.py` skips the wrapper build + smoke
test entirely.
`build_osx.yml` sets `IFCOS_BUILD_PYTHON_WRAPPER=off` so the bonsai
macOS CI can complete and upload `BonsaiViewer.app` while the plug-in
install rule is broken.
# What Thomas should do
Once the install rule in `src/ifcwrap/CMakeLists.txt` (the
`if(CREATE_BUNDLE) ... install(TARGETS ${_ifcopenshell_python_runtime_targets}
LIBRARY DESTINATION "${python_package_dir}/ifcopenshell" ...)` block,
added in b022ca7e7) is fixed to actually drop
`ifcopenshell.document.rdb.dylib` next to the wrapper in
site-packages on macOS — this commit can be reverted in its entirety:
the env-gate in `build-all.py` AND the `IFCOS_BUILD_PYTHON_WRAPPER=off`
in `build_osx.yml`. The bonsai macOS workflow will then build the
Python wrapper too.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
184 lines
7.0 KiB
YAML
184 lines
7.0 KiB
YAML
name: Build IfcOpenShell OSX
|
|
|
|
on:
|
|
workflow_dispatch:
|
|
|
|
jobs:
|
|
build_ifcopenshell:
|
|
runs-on: ${{ matrix.runner }}
|
|
strategy:
|
|
fail-fast: false
|
|
matrix:
|
|
include:
|
|
# x64 (Intel cross-compile) dropped while wgpu Qt is required:
|
|
# the runner is arm64 so `brew --prefix qt` returns the arm64
|
|
# prefix; we'd need a separate x86_64 Qt install under
|
|
# /usr/local to cross-build BonsaiViewer. Revisit if Intel-Mac
|
|
# demand resurfaces.
|
|
- os: macos
|
|
runner: macos-14
|
|
arch: arm64
|
|
oldarch: m1
|
|
|
|
steps:
|
|
- name: Checkout Repository
|
|
uses: actions/checkout@v6
|
|
with:
|
|
submodules: recursive
|
|
|
|
- name: Checkout Build Repository
|
|
uses: actions/checkout@v6
|
|
with:
|
|
repository: IfcOpenShell/build-outputs
|
|
path: ./build
|
|
ref: ${{ matrix.os }}-${{ matrix.arch }}
|
|
lfs: true
|
|
token: ${{ secrets.BUILD_REPO_TOKEN }}
|
|
|
|
- name: Install Dependencies
|
|
run: |
|
|
brew update
|
|
# preinstalled: xz, cmake
|
|
brew install git bison autoconf automake libffi findutils
|
|
# qt brings in Qt6 + Svg; nix/build-all.py honours pre-set
|
|
# QT_DIR so BonsaiViewer doesn't try to aqtinstall (which is
|
|
# Linux-only).
|
|
brew install qt
|
|
echo "$(brew --prefix findutils)/libexec/gnubin" >> $GITHUB_PATH
|
|
# Mac is using bison 2.5 by default, but we need 3.5+ for swig.
|
|
echo "$(brew --prefix bison)/bin" >> $GITHUB_PATH
|
|
|
|
- name: Install aws cli
|
|
run: |
|
|
python -m pip install awscli
|
|
|
|
- name: Unpack Dependencies
|
|
run: |
|
|
cd build
|
|
python ../nix/cache_dependencies.py unpack
|
|
|
|
- name: ccache
|
|
uses: hendrikmuhs/ccache-action@v1.2.22
|
|
with:
|
|
key: mac-${{ matrix.arch }}
|
|
|
|
- name: Run Build Script
|
|
shell: bash
|
|
run: |
|
|
if [ "${{ matrix.os }}" == "macos" ]; then
|
|
DARWIN_C_SOURCE=-D_DARWIN_C_SOURCE
|
|
fi
|
|
if [ "${{ matrix.arch }}" == "x64" ]; then
|
|
arch -x86_64 /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
|
|
MAC_INTEL=-mac-cross-compile-intel
|
|
# We don't use gmpcxx, but it comes preinstalled on macos runner as arm64 bottle
|
|
# and CGAL detects it and breaks cross compilation.
|
|
brew uninstall --ignore-dependencies gmp
|
|
# Otherwise Python will fallback to use arm64 `pkg-config`,
|
|
# will pick up arm64 libraries ('zstd' in particular),
|
|
# and break the build.
|
|
/usr/local/bin/brew install pkg-config
|
|
# Required by Python.
|
|
/usr/local/bin/brew install gettext openssl
|
|
fi
|
|
set -o pipefail
|
|
export QT_DIR="$(brew --prefix qt)"
|
|
# IFCOS_BUILD_PYTHON_WRAPPER=off skips IfcOpenShell-Python on
|
|
# macOS until the plug-in refactor's CREATE_BUNDLE install rule
|
|
# actually drops ifcopenshell.document.rdb.dylib into
|
|
# site-packages/ifcopenshell/ (see the commit that added this
|
|
# gate for the full history + the rocksdb/macdeployqt write-up).
|
|
CXXFLAGS="-O3" CFLAGS="-O3 ${DARWIN_C_SOURCE}" ADD_COMMIT_SHA=1 BUILD_CFG=Release \
|
|
BUILD_BONSAIVIEWER=ON QT_DIR="${QT_DIR}" \
|
|
IFCOS_BUILD_PYTHON_WRAPPER=off \
|
|
python3 ./nix/build-all.py -v --diskcleanup ${MAC_INTEL} \
|
|
| tee build.log
|
|
|
|
- name: Upload Build Logs
|
|
if: always()
|
|
uses: actions/upload-artifact@v7
|
|
with:
|
|
name: build-logs-osx-${{ matrix.arch }}
|
|
path: |
|
|
build.log
|
|
build/*/*/*/logs/*.log
|
|
build/*/*/*/build/ifcopenshell/**/CMakeCache.txt
|
|
retention-days: 30
|
|
|
|
- name: Pack Dependencies
|
|
run: |
|
|
cd build
|
|
python ../nix/cache_dependencies.py pack
|
|
|
|
- name: Commit and Push Changes to Build Repository
|
|
run: |
|
|
cd build
|
|
git config user.name "IfcOpenBot"
|
|
git config user.email "ifcopenbot@ifcopenshell.org"
|
|
git add "$(find . -maxdepth 4 -name install)/*.tar.gz"
|
|
git commit -m "Update build artifacts [skip ci]" || echo "No changes to commit"
|
|
git push || true
|
|
|
|
- name: Package .zip archives
|
|
run: |
|
|
VERSION=v`cat VERSION`
|
|
cd ./build/`uname`/*/10.15/install/ifcopenshell
|
|
mkdir -p ~/output
|
|
install_root="$PWD"
|
|
|
|
stage_runtime_payload() {
|
|
dest="$1"
|
|
while IFS= read -r runtime_file; do
|
|
cp -L "$runtime_file" "$dest/"
|
|
done < <(
|
|
for runtime_dir in "$install_root/bin" "$install_root/lib" "$install_root/lib64"; do
|
|
[ -d "$runtime_dir" ] || continue
|
|
find "$runtime_dir" -type f \( -name "*.so" -o -name "*.so.*" -o -name "*.dylib" -o -name "*.dll" \)
|
|
done
|
|
)
|
|
}
|
|
|
|
ls -d python-* | while read py_version; do
|
|
postfix=`echo ${py_version: -1} | sed s/[0-9]//`
|
|
numbers=`echo $py_version | grep -oE '[0-9]+\.[0-9]+' | tr -d '.'`
|
|
py_version_major=python-${numbers}$postfix
|
|
pushd . > /dev/null
|
|
cd $py_version
|
|
if [ ! -d ifcopenshell ]; then
|
|
mkdir ../ifcopenshell_
|
|
mv * ../ifcopenshell_
|
|
mv ../ifcopenshell_ ifcopenshell
|
|
fi
|
|
[ -d ifcopenshell/__pycache__ ] && rm -rf ifcopenshell/__pycache__
|
|
find ifcopenshell -name "*.pyc" -delete
|
|
stage_runtime_payload ifcopenshell
|
|
zip -r -qq ifcopenshell-${py_version_major}-${VERSION}-${GITHUB_SHA:0:7}-macos${{ matrix.oldarch }}64.zip ifcopenshell
|
|
mv *.zip ~/output
|
|
popd > /dev/null
|
|
done
|
|
|
|
rm -f "$install_root"/bin/*.zip
|
|
find "$install_root/bin" -maxdepth 1 -type f -perm /111 ! -name "*.zip" ! -name "*.so" ! -name "*.so.*" ! -name "*.dylib" ! -name "*.dll" | while read exe_path; do
|
|
exe=`basename "$exe_path"`
|
|
package_dir="$install_root/.package-${exe}"
|
|
rm -rf "$package_dir"
|
|
mkdir -p "$package_dir"
|
|
cp "$exe_path" "$package_dir/"
|
|
stage_runtime_payload "$package_dir"
|
|
pushd "$package_dir" > /dev/null
|
|
zip -qq -r "$HOME/output/${exe}-${VERSION}-${GITHUB_SHA:0:7}-macos${{ matrix.oldarch }}64.zip" .
|
|
popd > /dev/null
|
|
rm -rf "$package_dir"
|
|
done
|
|
|
|
- name: Configure AWS credentials
|
|
uses: aws-actions/configure-aws-credentials@v6
|
|
with:
|
|
aws-access-key-id: ${{ secrets.AWS_UPLOAD_ACCESS_KEY_ID }}
|
|
aws-secret-access-key: ${{ secrets.AWS_UPLOAD_SECRET_ACCESS_KEY }}
|
|
aws-region: us-east-1
|
|
|
|
- name: Upload .zip archives to S3
|
|
run: |
|
|
aws s3 cp ~/output s3://ifcopenshell-builds/ --recursive
|