mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-05 23:41:44 +00:00
de7520418b
Compile the Bonsai Viewer as part of the Linux and Windows binary builds, and ship the Autodesk connector alongside the viewer executable. Qt6 dependencies: - The viewer links Qt6::Svg for runtime icon tinting. Svg is a separate base-Qt archive, so aqt now installs "qtbase qtsvg" (plus icu on Linux) rather than qtbase alone, on both Linux and Windows. - Qt6::CorePrivate is exposed differently across Qt versions: Qt 6.8 ships the target inside Qt6Core, while Qt 6.10 provides it only as a separate CorePrivate config package. The viewer CMakeLists requests it via OPTIONAL_COMPONENTS so it resolves on both. - When cross-compiling Windows ARM64, windeployqt runs from the host x64 Qt, so qtsvg is installed into the host Qt as well. Windows build: - build-all-win.py passed -DBUILD_IFCVIEWER, a flag since renamed to BUILD_BONSAIVIEWER, so the Windows build compiled no viewer at all. It now passes -DBUILD_BONSAIVIEWER. - The Autodesk connector is bundled under connectors/ next to BonsaiViewer.exe in the packaged archive, mirroring the Linux builds. - The Windows workflow builds the connector (PyInstaller) before the main build so it is available to bundle. Connector bundling: - The Linux rocky workflows build the connector and bundle it into the BonsaiViewer archive; the Windows build now does the same. Generated with the assistance of an AI coding tool. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
236 lines
9.3 KiB
YAML
236 lines
9.3 KiB
YAML
name: Build IfcOpenShell Linux
|
|
|
|
on:
|
|
workflow_dispatch:
|
|
|
|
jobs:
|
|
build_ifcopenshell:
|
|
runs-on: ubuntu-22.04
|
|
container: rockylinux:9
|
|
|
|
steps:
|
|
- name: Install Dependencies
|
|
run: |
|
|
dnf update -y
|
|
dnf install -y epel-release
|
|
dnf install -y gcc gcc-c++ git autoconf automake bison make zip cmake python3 python3-pip \
|
|
bzip2 patch mesa-libGL-devel libffi-devel fontconfig-devel \
|
|
sqlite-devel bzip2-devel zlib-devel openssl-devel xz-devel \
|
|
readline-devel ncurses-devel libffi-devel libuuid-devel git-lfs \
|
|
findutils xz byacc patchelf libxkbcommon-devel \
|
|
python3.11 python3.11-pip python3.11-tkinter
|
|
python3 -m pip install typing_extensions aqtinstall
|
|
git config --global --add safe.directory '*'
|
|
python3.11 -c "import tkinter; print('Tk', tkinter.TkVersion)"
|
|
|
|
- name: Install aws cli
|
|
run: |
|
|
curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
|
|
unzip awscliv2.zip
|
|
./aws/install
|
|
rm -rf awscliv2.zip aws
|
|
aws --version
|
|
|
|
- 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: rockylinux9-x64
|
|
lfs: true
|
|
token: ${{ secrets.BUILD_REPO_TOKEN }}
|
|
|
|
- name: Unpack Dependencies
|
|
run: |
|
|
cd build
|
|
python3 ../nix/cache_dependencies.py unpack
|
|
|
|
- name: ccache
|
|
uses: hendrikmuhs/ccache-action@v1.2.22
|
|
with:
|
|
key: ubuntu-22.04-${{ runner.arch }}-rockylinux9
|
|
|
|
- name: Run Build Script
|
|
shell: bash
|
|
run: |
|
|
set -o pipefail
|
|
CXXFLAGS="-O3" CFLAGS="-O3 ${DARWIN_C_SOURCE}" ADD_COMMIT_SHA=1 BUILD_CFG=Release BUILD_BONSAIVIEWER=ON python3 ./nix/build-all.py -v --diskcleanup 2>&1 | tee build.log
|
|
|
|
- name: Upload Build Logs
|
|
if: always()
|
|
uses: actions/upload-artifact@v7
|
|
with:
|
|
name: build-logs-rocky
|
|
path: |
|
|
build.log
|
|
build/*/*/logs/*.log
|
|
retention-days: 30
|
|
|
|
- name: Pack Dependencies
|
|
run: |
|
|
cd build
|
|
python3 ../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
|
|
shell: bash
|
|
run: |
|
|
VERSION=v`cat VERSION`
|
|
python3.11 -m pip install "src/bonsaiviewer-autodesk[build]"
|
|
python3.11 src/bonsaiviewer-autodesk/packaging/build.py
|
|
autodesk_connector_dir="$PWD/src/bonsaiviewer-autodesk/dist/autodesk"
|
|
test -d "$autodesk_connector_dir"
|
|
|
|
cd ./build/`uname`/*/install/ifcopenshell
|
|
mkdir -p ~/output
|
|
install_root="$PWD"
|
|
QT6_VERSION="${QT6_VERSION:-6.8.3}"
|
|
|
|
if [ -z "${QT_DIR:-}" ]; then
|
|
for qt_candidate in "$(dirname "$install_root")"/qt6-${QT6_VERSION}-*/${QT6_VERSION}/*; do
|
|
if [ -d "$qt_candidate/lib" ]; then
|
|
QT_DIR="$qt_candidate"
|
|
break
|
|
fi
|
|
done
|
|
fi
|
|
|
|
ensure_soname_links() {
|
|
dest="$1"
|
|
find "$dest" -maxdepth 1 -type f -name "*.so*" | while IFS= read -r shared_object; do
|
|
soname=$(readelf -d "$shared_object" 2>/dev/null | sed -n 's/.*(SONAME).*Shared library: \[\(.*\)\].*/\1/p' | head -n 1)
|
|
[ -n "$soname" ] || continue
|
|
[ -e "$dest/$soname" ] && continue
|
|
ln -s "$(basename "$shared_object")" "$dest/$soname"
|
|
done
|
|
}
|
|
|
|
stage_runtime_payload() {
|
|
dest="$1"
|
|
while IFS= read -r runtime_file; do
|
|
cp -P "$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 -o -type l \) \( -name "*.so" -o -name "*.so.*" -o -name "*.dylib" -o -name "*.dll" \)
|
|
done
|
|
)
|
|
ensure_soname_links "$dest"
|
|
}
|
|
|
|
stage_qt_runtime_payload() {
|
|
exe_path="$1"
|
|
dest="$2"
|
|
[ -n "${QT_DIR:-}" ] && [ -d "$QT_DIR/lib" ] || return 0
|
|
|
|
if ! LD_LIBRARY_PATH="$QT_DIR/lib:${LD_LIBRARY_PATH:-}" ldd "$exe_path" 2>/dev/null | grep -q "libQt6"; then
|
|
return 0
|
|
fi
|
|
|
|
find "$QT_DIR/lib" -maxdepth 1 \( -type f -o -type l \) -name "*.so*" -exec cp -P {} "$dest/" \;
|
|
ensure_soname_links "$dest"
|
|
|
|
if [ -d "$QT_DIR/plugins" ]; then
|
|
pushd "$QT_DIR/plugins" > /dev/null
|
|
find . \( -type f -o -type l \) -name "*.so*" | while IFS= read -r plugin_file; do
|
|
mkdir -p "$dest/plugins/$(dirname "$plugin_file")"
|
|
cp -P "$plugin_file" "$dest/plugins/$plugin_file"
|
|
done
|
|
popd > /dev/null
|
|
if [ -d "$dest/plugins" ]; then
|
|
find "$dest/plugins" -type f -name "*.so*" -exec patchelf --set-rpath '$ORIGIN/../..:$ORIGIN' {} \;
|
|
fi
|
|
fi
|
|
|
|
find "$dest" -maxdepth 1 -type f -name "*.so*" -exec patchelf --set-rpath '$ORIGIN' {} \;
|
|
|
|
printf "[Paths]\nPrefix = .\n" > "$dest/qt.conf"
|
|
}
|
|
|
|
check_runtime_dependencies() {
|
|
package_dir="$1"
|
|
missing=0
|
|
while IFS= read -r binary_file; do
|
|
readelf -h "$binary_file" >/dev/null 2>&1 || continue
|
|
if ! env -u LD_LIBRARY_PATH ldd "$binary_file" > "$package_dir/.ldd.out" 2>&1; then
|
|
echo "ldd failed for $binary_file"
|
|
cat "$package_dir/.ldd.out"
|
|
missing=1
|
|
continue
|
|
fi
|
|
if grep -q "not found" "$package_dir/.ldd.out"; then
|
|
echo "Missing runtime dependencies for $binary_file"
|
|
grep "not found" "$package_dir/.ldd.out"
|
|
missing=1
|
|
fi
|
|
done < <(find "$package_dir" -type f \( -perm /111 -o -name "*.so" -o -name "*.so.*" \))
|
|
rm -f "$package_dir/.ldd.out"
|
|
if [ "$missing" -ne 0 ]; then
|
|
echo "Runtime dependency check found issues; continuing packaging."
|
|
fi
|
|
return 0
|
|
}
|
|
|
|
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
|
|
zip -y -r -qq ifcopenshell-${py_version_major}-${VERSION}-${GITHUB_SHA:0:7}-linux64.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/"
|
|
patchelf --set-rpath '$ORIGIN' "$package_dir/$exe"
|
|
stage_runtime_payload "$package_dir"
|
|
stage_qt_runtime_payload "$exe_path" "$package_dir"
|
|
if [ "$exe" = "BonsaiViewer" ]; then
|
|
mkdir -p "$package_dir/connectors"
|
|
cp -a "$autodesk_connector_dir" "$package_dir/connectors/"
|
|
fi
|
|
check_runtime_dependencies "$package_dir"
|
|
pushd "$package_dir" > /dev/null
|
|
zip -y -qq -r "$HOME/output/${exe}-${VERSION}-${GITHUB_SHA:0:7}-linux64.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
|