Merge remote-tracking branch 'origin/v0.8.0' into datamodel-v1.0

This commit is contained in:
Thomas Krijnen
2026-04-18 20:15:28 +02:00
1655 changed files with 105534 additions and 46934 deletions
+12
View File
@@ -0,0 +1,12 @@
# yaml-language-server: $schema=https://raw.githubusercontent.com/BlankSpruce/gersemi/0.24.0/gersemi/configuration.schema.json
# Gersemi doesn't support autodetection of macros/functions from other files or from the current one
# and requires to explicitly list directories/cmake files that define them.
definitions: ["./cmake", "./src"]
disable_formatting: false
extensions: []
indent: 4
line_length: 120
list_expansion: favour-inlining
unsafe: false
warn_about_unknown_commands: true
+4
View File
@@ -6,3 +6,7 @@ updates:
directory: "/" directory: "/"
schedule: schedule:
interval: "weekly" interval: "weekly"
- package-ecosystem: "pip"
directory: "/"
schedule:
interval: "weekly"
@@ -0,0 +1,41 @@
from __future__ import annotations
import json
import os
import sys
from typing import TypedDict
import github_action_utils as gha_utils
class Entry(TypedDict):
location: Location
class Location(TypedDict):
path: str
lines: Lines
class Lines(TypedDict):
begin: int
end: int
json_data: list[Entry] = json.load(sys.stdin)
if os.getenv("RUNNER_DEBUG"):
print("Debug: Black formatting JSON data:")
print(json.dumps(json_data, indent=2))
for change in json_data:
location = change["location"]
path = location["path"]
lines = location["lines"]
gha_utils.error(
f"Black formatting issue in {path}",
title="Black Format Issue",
file=path,
line=lines["begin"],
end_line=lines["end"],
)
+10 -10
View File
@@ -21,12 +21,12 @@ jobs:
steps: steps:
- name: Checkout Repository - name: Checkout Repository
uses: actions/checkout@v5 uses: actions/checkout@v6
with: with:
submodules: recursive submodules: recursive
- name: Checkout Build Repository - name: Checkout Build Repository
uses: actions/checkout@v5 uses: actions/checkout@v6
with: with:
repository: IfcOpenShell/build-outputs repository: IfcOpenShell/build-outputs
path: ./build path: ./build
@@ -40,6 +40,8 @@ jobs:
# preinstalled: xz, cmake # preinstalled: xz, cmake
brew install git bison autoconf automake libffi findutils brew install git bison autoconf automake libffi findutils
echo "$(brew --prefix findutils)/libexec/gnubin" >> $GITHUB_PATH 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 - name: Install aws cli
run: | run: |
@@ -47,11 +49,11 @@ jobs:
- name: Unpack Dependencies - name: Unpack Dependencies
run: | run: |
install_root=$(find ./build -maxdepth 4 -type d -name install 2>/dev/null | head -n 1 || true) cd build
[ -n "$install_root" ] && find "$install_root" -type f -name 'cache-*.tar.gz' -maxdepth 1 -exec tar -xzf {} -C "$install_root" \; || true python ../nix/cache_dependencies.py unpack
- name: ccache - name: ccache
uses: hendrikmuhs/ccache-action@v1.2 uses: hendrikmuhs/ccache-action@v1.2.22
with: with:
key: mac-${{ matrix.arch }} key: mac-${{ matrix.arch }}
@@ -81,7 +83,7 @@ jobs:
- name: Upload Build Logs - name: Upload Build Logs
if: always() if: always()
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@v7
with: with:
name: build-logs-osx-${{ matrix.arch }} name: build-logs-osx-${{ matrix.arch }}
path: | path: |
@@ -93,9 +95,7 @@ jobs:
- name: Pack Dependencies - name: Pack Dependencies
run: | run: |
cd build cd build
for install_dir in $(find $(find . -maxdepth 4 -name install) -mindepth 1 -maxdepth 1 -type d); do python ../nix/cache_dependencies.py pack
test -f $(dirname "$install_dir")/cache-$(basename "$install_dir").tar.gz || tar -czf $(dirname "$install_dir")/cache-$(basename "$install_dir").tar.gz -C $(dirname "$install_dir") $(basename "$install_dir");
done
- name: Commit and Push Changes to Build Repository - name: Commit and Push Changes to Build Repository
run: | run: |
@@ -161,7 +161,7 @@ jobs:
mv "$install_root"/bin/*.zip ~/output mv "$install_root"/bin/*.zip ~/output
- name: Configure AWS credentials - name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v5 uses: aws-actions/configure-aws-credentials@v6
with: with:
aws-access-key-id: ${{ secrets.AWS_UPLOAD_ACCESS_KEY_ID }} aws-access-key-id: ${{ secrets.AWS_UPLOAD_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_UPLOAD_SECRET_ACCESS_KEY }} aws-secret-access-key: ${{ secrets.AWS_UPLOAD_SECRET_ACCESS_KEY }}
+7 -7
View File
@@ -9,13 +9,13 @@ jobs:
steps: steps:
- name: Checkout Repository - name: Checkout Repository
uses: actions/checkout@v5 uses: actions/checkout@v6
with: with:
submodules: recursive submodules: recursive
path: IfcOpenShell path: IfcOpenShell
- name: Checkout Build Repository - name: Checkout Build Repository
uses: actions/checkout@v5 uses: actions/checkout@v6
with: with:
repository: IfcOpenShell/build-outputs repository: IfcOpenShell/build-outputs
path: ifcopenshell_build path: ifcopenshell_build
@@ -26,10 +26,10 @@ jobs:
- name: Unpack Dependencies - name: Unpack Dependencies
run: | run: |
cd ifcopenshell_build cd ifcopenshell_build
python ../IfcOpenShell/pyodide/cache_dependencies.py unpack python ../IfcOpenShell/nix/cache_dependencies.py unpack
- name: ccache - name: ccache
uses: hendrikmuhs/ccache-action@v1.2 uses: hendrikmuhs/ccache-action@v1.2.22
with: with:
key: ubuntu-22.04-${{ runner.arch }} key: ubuntu-22.04-${{ runner.arch }}
@@ -42,7 +42,7 @@ jobs:
- name: Upload Build Logs - name: Upload Build Logs
if: always() if: always()
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@v7
with: with:
name: build-logs-pyodide name: build-logs-pyodide
path: | path: |
@@ -65,7 +65,7 @@ jobs:
- name: Pack Dependencies - name: Pack Dependencies
run: | run: |
cd ifcopenshell_build cd ifcopenshell_build
python ../IfcOpenShell/pyodide/cache_dependencies.py pack python ../IfcOpenShell/nix/cache_dependencies.py pack
- name: Commit and Push Changes to Build Repository - name: Commit and Push Changes to Build Repository
run: | run: |
@@ -77,7 +77,7 @@ jobs:
git push || echo "Push failed" git push || echo "Push failed"
- name: Configure AWS credentials - name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v5 uses: aws-actions/configure-aws-credentials@v6
with: with:
aws-access-key-id: ${{ secrets.AWS_UPLOAD_ACCESS_KEY_ID }} aws-access-key-id: ${{ secrets.AWS_UPLOAD_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_UPLOAD_SECRET_ACCESS_KEY }} aws-secret-access-key: ${{ secrets.AWS_UPLOAD_SECRET_ACCESS_KEY }}
+13 -16
View File
@@ -6,13 +6,13 @@ on:
jobs: jobs:
build_ifcopenshell: build_ifcopenshell:
runs-on: ubuntu-22.04 runs-on: ubuntu-22.04
container: rockylinux:8 container: rockylinux:9
steps: steps:
- name: Install Dependencies - name: Install Dependencies
run: | run: |
yum update -y dnf update -y
yum install -y gcc gcc-c++ git autoconf automake bison make zip cmake python3 \ 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 \ bzip2 patch mesa-libGL-devel libffi-devel fontconfig-devel \
sqlite-devel bzip2-devel zlib-devel openssl-devel xz-devel \ sqlite-devel bzip2-devel zlib-devel openssl-devel xz-devel \
readline-devel ncurses-devel libffi-devel libuuid-devel git-lfs \ readline-devel ncurses-devel libffi-devel libuuid-devel git-lfs \
@@ -29,29 +29,28 @@ jobs:
aws --version aws --version
- name: Checkout Repository - name: Checkout Repository
uses: actions/checkout@v5 uses: actions/checkout@v6
with: with:
submodules: recursive submodules: recursive
- name: Checkout Build Repository - name: Checkout Build Repository
uses: actions/checkout@v5 uses: actions/checkout@v6
with: with:
repository: IfcOpenShell/build-outputs repository: IfcOpenShell/build-outputs
path: ./build path: ./build
ref: rockylinux8-x64 ref: rockylinux9-x64
lfs: true lfs: true
token: ${{ secrets.BUILD_REPO_TOKEN }} token: ${{ secrets.BUILD_REPO_TOKEN }}
- name: Unpack Dependencies - name: Unpack Dependencies
run: | run: |
install_root=$(find ./build -maxdepth 4 -type d -name install 2>/dev/null | head -n 1 || true) cd build
[ -n "$install_root" ] && find "$install_root" -type f -name 'cache-*.tar.gz' -maxdepth 1 -exec tar -xzf {} -C "$install_root" \; || true python3 ../nix/cache_dependencies.py unpack
- name: ccache - name: ccache
# TODO: Use tag after 1.2.20 releases. uses: hendrikmuhs/ccache-action@v1.2.22
uses: hendrikmuhs/ccache-action@5ebbd400eff9e74630f759d94ddd7b6c26299639
with: with:
key: ubuntu-22.04-${{ runner.arch }}-rockylinux8 key: ubuntu-22.04-${{ runner.arch }}-rockylinux9
- name: Run Build Script - name: Run Build Script
shell: bash shell: bash
@@ -61,7 +60,7 @@ jobs:
- name: Upload Build Logs - name: Upload Build Logs
if: always() if: always()
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@v7
with: with:
name: build-logs-rocky name: build-logs-rocky
path: | path: |
@@ -72,9 +71,7 @@ jobs:
- name: Pack Dependencies - name: Pack Dependencies
run: | run: |
cd build cd build
for install_dir in $(find $(find . -maxdepth 4 -name install) -mindepth 1 -maxdepth 1 -type d); do python3 ../nix/cache_dependencies.py pack
test -f $(dirname "$install_dir")/cache-$(basename "$install_dir").tar.gz || tar -czf $(dirname "$install_dir")/cache-$(basename "$install_dir").tar.gz -C $(dirname "$install_dir") $(basename "$install_dir");
done
- name: Commit and Push Changes to Build Repository - name: Commit and Push Changes to Build Repository
run: | run: |
@@ -140,7 +137,7 @@ jobs:
mv "$install_root"/bin/*.zip ~/output mv "$install_root"/bin/*.zip ~/output
- name: Configure AWS credentials - name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v5 uses: aws-actions/configure-aws-credentials@v6
with: with:
aws-access-key-id: ${{ secrets.AWS_UPLOAD_ACCESS_KEY_ID }} aws-access-key-id: ${{ secrets.AWS_UPLOAD_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_UPLOAD_SECRET_ACCESS_KEY }} aws-secret-access-key: ${{ secrets.AWS_UPLOAD_SECRET_ACCESS_KEY }}
+13 -16
View File
@@ -6,13 +6,13 @@ on:
jobs: jobs:
build_ifcopenshell: build_ifcopenshell:
runs-on: ubuntu-22.04-arm runs-on: ubuntu-22.04-arm
container: arm64v8/rockylinux:8 container: arm64v8/rockylinux:9
steps: steps:
- name: Install Dependencies - name: Install Dependencies
run: | run: |
yum update -y dnf update -y
yum install -y gcc gcc-c++ git autoconf automake bison make zip cmake python3 \ 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 \ bzip2 patch mesa-libGL-devel libffi-devel fontconfig-devel \
sqlite-devel bzip2-devel zlib-devel openssl-devel xz-devel \ sqlite-devel bzip2-devel zlib-devel openssl-devel xz-devel \
readline-devel ncurses-devel libffi-devel libuuid-devel git-lfs \ readline-devel ncurses-devel libffi-devel libuuid-devel git-lfs \
@@ -29,29 +29,28 @@ jobs:
aws --version aws --version
- name: Checkout Repository - name: Checkout Repository
uses: actions/checkout@v5 uses: actions/checkout@v6
with: with:
submodules: recursive submodules: recursive
- name: Checkout Build Repository - name: Checkout Build Repository
uses: actions/checkout@v5 uses: actions/checkout@v6
with: with:
repository: IfcOpenShell/build-outputs repository: IfcOpenShell/build-outputs
path: ./build path: ./build
ref: rockylinux8-arm64 ref: rockylinux9-arm64
lfs: true lfs: true
token: ${{ secrets.BUILD_REPO_TOKEN }} token: ${{ secrets.BUILD_REPO_TOKEN }}
- name: Unpack Dependencies - name: Unpack Dependencies
run: | run: |
install_root=$(find ./build -maxdepth 4 -type d -name install 2>/dev/null | head -n 1 || true) cd build
[ -n "$install_root" ] && find "$install_root" -type f -name 'cache-*.tar.gz' -maxdepth 1 -exec tar -xzf {} -C "$install_root" \; || true python3 ../nix/cache_dependencies.py unpack
- name: ccache - name: ccache
# TODO: Use tag after 1.2.20 releases. uses: hendrikmuhs/ccache-action@v1.2.22
uses: hendrikmuhs/ccache-action@5ebbd400eff9e74630f759d94ddd7b6c26299639
with: with:
key: ubuntu-22.04-${{ runner.arch }}-rockylinux8 key: ubuntu-22.04-${{ runner.arch }}-rockylinux9
- name: Run Build Script - name: Run Build Script
shell: bash shell: bash
@@ -61,7 +60,7 @@ jobs:
- name: Upload Build Logs - name: Upload Build Logs
if: always() if: always()
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@v7
with: with:
name: build-logs-rocky-arm64 name: build-logs-rocky-arm64
path: | path: |
@@ -72,9 +71,7 @@ jobs:
- name: Pack Dependencies - name: Pack Dependencies
run: | run: |
cd build cd build
for install_dir in $(find $(find . -maxdepth 4 -name install) -mindepth 1 -maxdepth 1 -type d); do python3 ../nix/cache_dependencies.py pack
test -f $(dirname "$install_dir")/cache-$(basename "$install_dir").tar.gz || tar -czf $(dirname "$install_dir")/cache-$(basename "$install_dir").tar.gz -C $(dirname "$install_dir") $(basename "$install_dir");
done
- name: Commit and Push Changes to Build Repository - name: Commit and Push Changes to Build Repository
run: | run: |
@@ -140,7 +137,7 @@ jobs:
mv "$install_root"/bin/*.zip ~/output mv "$install_root"/bin/*.zip ~/output
- name: Configure AWS credentials - name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v5 uses: aws-actions/configure-aws-credentials@v6
with: with:
aws-access-key-id: ${{ secrets.AWS_UPLOAD_ACCESS_KEY_ID }} aws-access-key-id: ${{ secrets.AWS_UPLOAD_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_UPLOAD_SECRET_ACCESS_KEY }} aws-secret-access-key: ${{ secrets.AWS_UPLOAD_SECRET_ACCESS_KEY }}
+31 -14
View File
@@ -5,23 +5,38 @@ on:
jobs: jobs:
build_ifcopenshell: build_ifcopenshell:
runs-on: windows-2022
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
arch: ['x64'] include:
- arch: x64
runs_on: windows-2022
deps_dir: _deps-vs2022-x64-installed
vcvars: '"C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat"'
build_branch: windows-x64
zip_suffix: win64
- arch: ARM64
runs_on: windows-11-arm
deps_dir: _deps-vs2022-ARM64-installed
vcvars: '"C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsarm64.bat"'
build_branch: windows-arm64
zip_suffix: win-arm64
runs-on: ${{ matrix.runs_on }}
steps: steps:
- name: Checkout Repository - name: Checkout Repository
uses: actions/checkout@v5 uses: actions/checkout@v6
with: with:
submodules: recursive submodules: recursive
- name: Checkout Build Repository - name: Checkout Build Repository
uses: actions/checkout@v5 uses: actions/checkout@v6
with: with:
repository: IfcOpenShell/build-outputs repository: IfcOpenShell/build-outputs
path: _deps-vs2022-x64-installed path: ${{ matrix.deps_dir }}
ref: windows-${{ matrix.arch }} ref: ${{ matrix.build_branch }}
lfs: true lfs: true
token: ${{ secrets.BUILD_REPO_TOKEN }} token: ${{ secrets.BUILD_REPO_TOKEN }}
@@ -31,14 +46,13 @@ jobs:
- name: Unpack Dependencies - name: Unpack Dependencies
run: | run: |
cd _deps-vs2022-x64-installed cd ${{ matrix.deps_dir }}
Get-ChildItem -Path . -Filter 'cache-*.zip' | ForEach-Object { Get-ChildItem -Path . -Filter 'cache-*.zip' | ForEach-Object {
7z x $_.FullName 7z x $_.FullName
} }
- name: ccache - name: ccache
# TODO: Use tag after 1.2.20 releases. uses: hendrikmuhs/ccache-action@v1.2.22
uses: hendrikmuhs/ccache-action@5ebbd400eff9e74630f759d94ddd7b6c26299639
with: with:
key: win-${{ matrix.arch }} key: win-${{ matrix.arch }}
# Windows ccache needs ~1GB # Windows ccache needs ~1GB
@@ -47,8 +61,10 @@ jobs:
- name: Run Build Script And Pack .zip Archives - name: Run Build Script And Pack .zip Archives
shell: cmd shell: cmd
env:
TARGET_ARCH: ${{ matrix.arch }} # lets the Python script know which arch to target (optional override)
run: | run: |
call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat" call ${{ matrix.vcvars }}
cd win cd win
python build-all-win.py python build-all-win.py
@@ -112,7 +128,7 @@ jobs:
- name: Pack Dependencies - name: Pack Dependencies
run: | run: |
cd _deps-vs2022-x64-installed cd ${{ matrix.deps_dir }}
Get-ChildItem -Path . -Directory | ForEach-Object { Get-ChildItem -Path . -Directory | ForEach-Object {
$cacheFile = "cache-$($_.Name).zip" $cacheFile = "cache-$($_.Name).zip"
echo $cacheFile echo $cacheFile
@@ -123,15 +139,16 @@ jobs:
- name: Commit and Push Changes to Build Repository - name: Commit and Push Changes to Build Repository
run: | run: |
cd _deps-vs2022-x64-installed cd ${{ matrix.deps_dir }}
git config user.name "IfcOpenBot" git config user.name "IfcOpenBot"
git config user.email "ifcopenbot@ifcopenshell.org" git config user.email "ifcopenbot@ifcopenshell.org"
git checkout -B ${{ matrix.build_branch }}
git add *.zip git add *.zip
git commit -m "Update build artifacts [skip ci]" || echo "No changes to commit" git commit -m "Update build artifacts [skip ci]" || echo "No changes to commit"
git push || echo "Push failed" git push --set-upstream origin ${{ matrix.build_branch }} || echo "Push failed"
- name: Configure AWS Credentials - name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v5 uses: aws-actions/configure-aws-credentials@v6
with: with:
aws-access-key-id: ${{ secrets.AWS_UPLOAD_ACCESS_KEY_ID }} aws-access-key-id: ${{ secrets.AWS_UPLOAD_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_UPLOAD_SECRET_ACCESS_KEY }} aws-secret-access-key: ${{ secrets.AWS_UPLOAD_SECRET_ACCESS_KEY }}
+2 -2
View File
@@ -1,9 +1,9 @@
import os
import pathlib import pathlib
import shutil import shutil
import zipfile
import requests import requests
import zipfile
import os
# To test this locally, set these environment variables # To test this locally, set these environment variables
REPO_OWNER = os.environ.get("REPO_OWNER", "IfcOpenShell/IfcOpenShell") REPO_OWNER = os.environ.get("REPO_OWNER", "IfcOpenShell/IfcOpenShell")
+1 -1
View File
@@ -19,7 +19,7 @@ jobs:
strategy: strategy:
fail-fast: false fail-fast: false
steps: steps:
- uses: actions/checkout@v5 # https://github.com/actions/checkout - uses: actions/checkout@v6 # https://github.com/actions/checkout
- uses: actions/setup-python@v6 # https://github.com/actions/setup-python - uses: actions/setup-python@v6 # https://github.com/actions/setup-python
with: with:
python-version: '3.11' # Version range or exact version of a Python version to use, using SemVer's version range syntax python-version: '3.11' # Version range or exact version of a Python version to use, using SemVer's version range syntax
@@ -1,68 +0,0 @@
name: ci-black-formatting
on:
push:
pull_request:
jobs:
lint-formatting:
runs-on: ubuntu-latest
steps:
- name: Action - checkout repository
uses: actions/checkout@v5
- name: Action - install python
uses: actions/setup-python@v6
with:
python-version: "3.9"
- name: Action - install python
uses: actions/setup-python@v6
with:
python-version: "3.11"
- name: Install dependencies
run: |
curl -LsSf https://astral.sh/uv/install.sh | sh
uv tool install ruff
uv tool install black
uv tool install poethepoet
# black doesn't catch all syntax errors, so we check them explicitly.
- name: Check syntax errors
id: syntax-errors
run: |
ERROR=0
python3.9 -W error -m compileall -q src/ifcopenshell-python || ERROR=1
python3.11 -W error -m compileall -q src/bonsai || ERROR=1
exit $ERROR
continue-on-error: true
- name: Black formatter
id: black
run: |
black --diff --check .
continue-on-error: true
- name: Ruff check
id: ruff
run: |
ERROR=0
poe ruff-main || ERROR=1
poe ruff-old || ERROR=1
exit $ERROR
continue-on-error: true
- name: Final check
run: |
ERROR=0
if [ "${{ steps.syntax-errors.outcome }}" != "success" ]; then
echo "::error::Syntax errors check failed, see 'syntax-errors' step for the details." && ERROR=1
fi
if [ "${{ steps.black.outcome }}" != "success" ]; then
echo "::error::Black formatting check failed, see 'black' step for the details." && ERROR=1
fi
if [ "${{ steps.ruff.outcome }}" != "success" ]; then
echo "::error::Ruff check failed, see 'ruff' step for the details." && ERROR=1
fi
exit $ERROR
+1 -1
View File
@@ -34,7 +34,7 @@ jobs:
strategy: strategy:
fail-fast: false fail-fast: false
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@v6
with: with:
fetch-tags: true fetch-tags: true
fetch-depth: 0 fetch-depth: 0
+20 -15
View File
@@ -24,9 +24,15 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
if: | if: |
github.repository == 'IfcOpenShell/IfcOpenShell' github.repository == 'IfcOpenShell/IfcOpenShell'
outputs:
timestamp: ${{ steps.timestamp.outputs.timestamp }}
steps: steps:
- name: Set env - name: Get current timestamp
run: echo ok go id: timestamp
# Include hours and minutes to release tag
# to avoid possibility of unstable repo's index.json
# pointing to the new file when index.json itself wasn't yet updated.
run: echo "timestamp=$(date +'%y%m%d%H%M')" >> $GITHUB_OUTPUT
build: build:
needs: activate needs: activate
@@ -35,7 +41,7 @@ jobs:
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
pyver: [py311, py312] pyver: [py311, py312, py313]
config: config:
- { - {
name: "Windows Build", name: "Windows Build",
@@ -53,8 +59,13 @@ jobs:
name: "MacOS ARM Build", name: "MacOS ARM Build",
short_name: macosm1, short_name: macosm1,
} }
exclude:
# Python 3.13 is needed for Blender 5.1+ and Blender dropped Intel Mac support in 5.0.
- pyver: py313
config:
short_name: macos
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@v6
- uses: actions/setup-python@v6 # https://github.com/actions/setup-python - uses: actions/setup-python@v6 # https://github.com/actions/setup-python
with: with:
architecture: 'x64' # optional x64 or x86. Defaults to x64 if not specified architecture: 'x64' # optional x64 or x86. Defaults to x64 if not specified
@@ -62,12 +73,6 @@ jobs:
- name: Get current version - name: Get current version
id: version id: version
run: echo "version=$(cat VERSION)" >> $GITHUB_OUTPUT run: echo "version=$(cat VERSION)" >> $GITHUB_OUTPUT
- name: Get current date
id: date
# Include hours and minutes to release tag
# to avoid possibility of unstable repo's index.json
# pointing to the new file when index.json itself wasn't yet updated.
run: echo "date=$(date +'%y%m%d%H%M')" >> $GITHUB_OUTPUT
- name: Compile - name: Compile
run: | run: |
cd src/bonsai && make dist PLATFORM=${{ matrix.config.short_name }} PYVERSION=${{ matrix.pyver }} cd src/bonsai && make dist PLATFORM=${{ matrix.config.short_name }} PYVERSION=${{ matrix.pyver }}
@@ -83,8 +88,8 @@ jobs:
repo_token: ${{ secrets.GITHUB_TOKEN }} repo_token: ${{ secrets.GITHUB_TOKEN }}
file: ${{ steps.find_zip.outputs.filepath }} file: ${{ steps.find_zip.outputs.filepath }}
asset_name: ${{ steps.find_zip.outputs.filename }} asset_name: ${{ steps.find_zip.outputs.filename }}
release_name: "bonsai-${{steps.version.outputs.version}}-alpha${{steps.date.outputs.date}} (unstable)" release_name: "bonsai-${{steps.version.outputs.version}}-alpha${{ needs.activate.outputs.timestamp }} (unstable)"
tag: "bonsai-${{steps.version.outputs.version}}-alpha${{steps.date.outputs.date}}" tag: "bonsai-${{steps.version.outputs.version}}-alpha${{ needs.activate.outputs.timestamp }}"
overwrite: true overwrite: true
body: "See README in https://github.com/IfcOpenShell/bonsai_unstable_repo/ on how to setup autoupdates for daily Bonsai builds." body: "See README in https://github.com/IfcOpenShell/bonsai_unstable_repo/ on how to setup autoupdates for daily Bonsai builds."
@@ -93,7 +98,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout bonsai_unstable_repo repository - name: Checkout bonsai_unstable_repo repository
uses: actions/checkout@v5 uses: actions/checkout@v6
with: with:
repository: IfcOpenShell/bonsai_unstable_repo repository: IfcOpenShell/bonsai_unstable_repo
token: ${{ secrets.IFCOPENBOT_TOKEN }} token: ${{ secrets.IFCOPENBOT_TOKEN }}
@@ -104,7 +109,7 @@ jobs:
# Ensure Bonsai and ifcsverchok enable/disable works before uploading to extensions repo. # Ensure Bonsai and ifcsverchok enable/disable works before uploading to extensions repo.
# Download Blender. # Download Blender.
wget -q -O blender.tar.xz https://download.blender.org/release/Blender4.5/blender-4.5.0-linux-x64.tar.xz wget -q -O blender.tar.xz https://download.blender.org/release/Blender5.1/blender-5.1.0-linux-x64.tar.xz
tar -xf blender.tar.xz tar -xf blender.tar.xz
# Setup Blender. # Setup Blender.
@@ -117,7 +122,7 @@ jobs:
pip install -r requirements.txt pip install -r requirements.txt
python setup_extensions_repo.py --last-tag python setup_extensions_repo.py --last-tag
cd .. cd ..
bonsai_zip="$(pwd)/$(ls bonsai_unstable_repo/bonsai_py311*-linux-x64.zip)" bonsai_zip="$(pwd)/$(ls bonsai_unstable_repo/bonsai_py313*-linux-x64.zip)"
# Install Bonsai. # Install Bonsai.
blender --command extension install-file -r user_default -e $bonsai_zip blender --command extension install-file -r user_default -e $bonsai_zip
+7 -2
View File
@@ -24,7 +24,7 @@ jobs:
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
pyver: [py311, py312] pyver: [py311, py312, py313]
config: config:
- { - {
name: "Windows Build", name: "Windows Build",
@@ -42,8 +42,13 @@ jobs:
name: "MacOS ARM Build", name: "MacOS ARM Build",
short_name: macosm1, short_name: macosm1,
} }
exclude:
# Python 3.13 is needed for Blender 5.1+ and Blender dropped Intel Mac support in 5.0.
- pyver: py313
config:
short_name: macos
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@v6
- uses: actions/setup-python@v6 # https://github.com/actions/setup-python - uses: actions/setup-python@v6 # https://github.com/actions/setup-python
with: with:
architecture: 'x64' # optional x64 or x86. Defaults to x64 if not specified architecture: 'x64' # optional x64 or x86. Defaults to x64 if not specified
+1 -1
View File
@@ -18,7 +18,7 @@ jobs:
strategy: strategy:
fail-fast: false fail-fast: false
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@v6
- uses: actions/setup-python@v6 # https://github.com/actions/setup-python - uses: actions/setup-python@v6 # https://github.com/actions/setup-python
with: with:
python-version: '3.11' # Version range or exact version of a Python version to use, using SemVer's version range syntax python-version: '3.11' # Version range or exact version of a Python version to use, using SemVer's version range syntax
+1 -1
View File
@@ -18,7 +18,7 @@ jobs:
strategy: strategy:
fail-fast: false fail-fast: false
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@v6
- uses: actions/setup-python@v6 # https://github.com/actions/setup-python - uses: actions/setup-python@v6 # https://github.com/actions/setup-python
with: with:
python-version: '3.11' # Version range or exact version of a Python version to use, using SemVer's version range syntax python-version: '3.11' # Version range or exact version of a Python version to use, using SemVer's version range syntax
+1 -1
View File
@@ -18,7 +18,7 @@ jobs:
strategy: strategy:
fail-fast: false fail-fast: false
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@v6
- uses: actions/setup-python@v6 # https://github.com/actions/setup-python - uses: actions/setup-python@v6 # https://github.com/actions/setup-python
with: with:
python-version: '3.11' # Version range or exact version of a Python version to use, using SemVer's version range syntax python-version: '3.11' # Version range or exact version of a Python version to use, using SemVer's version range syntax
+1 -1
View File
@@ -18,7 +18,7 @@ jobs:
strategy: strategy:
fail-fast: false fail-fast: false
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@v6
- uses: actions/setup-python@v6 # https://github.com/actions/setup-python - uses: actions/setup-python@v6 # https://github.com/actions/setup-python
with: with:
python-version: '3.11' # Version range or exact version of a Python version to use, using SemVer's version range syntax python-version: '3.11' # Version range or exact version of a Python version to use, using SemVer's version range syntax
+1 -1
View File
@@ -18,7 +18,7 @@ jobs:
strategy: strategy:
fail-fast: false fail-fast: false
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@v6
- uses: actions/setup-python@v6 # https://github.com/actions/setup-python - uses: actions/setup-python@v6 # https://github.com/actions/setup-python
with: with:
python-version: '3.11' # Version range or exact version of a Python version to use, using SemVer's version range syntax python-version: '3.11' # Version range or exact version of a Python version to use, using SemVer's version range syntax
+1 -1
View File
@@ -37,7 +37,7 @@ jobs:
short_name: macosm164 short_name: macosm164
} }
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@v6
- uses: actions/setup-python@v6 # https://github.com/actions/setup-python - uses: actions/setup-python@v6 # https://github.com/actions/setup-python
with: with:
python-version: '3.11' # Version range or exact version of a Python version to use, using SemVer's version range syntax python-version: '3.11' # Version range or exact version of a Python version to use, using SemVer's version range syntax
+1 -1
View File
@@ -18,7 +18,7 @@ jobs:
strategy: strategy:
fail-fast: false fail-fast: false
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@v6
- uses: actions/setup-python@v6 # https://github.com/actions/setup-python - uses: actions/setup-python@v6 # https://github.com/actions/setup-python
with: with:
python-version: '3.11' # Version range or exact version of a Python version to use, using SemVer's version range syntax python-version: '3.11' # Version range or exact version of a Python version to use, using SemVer's version range syntax
+1 -1
View File
@@ -18,7 +18,7 @@ jobs:
strategy: strategy:
fail-fast: false fail-fast: false
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@v6
- uses: actions/setup-python@v6 # https://github.com/actions/setup-python - uses: actions/setup-python@v6 # https://github.com/actions/setup-python
with: with:
python-version: '3.11' # Version range or exact version of a Python version to use, using SemVer's version range syntax python-version: '3.11' # Version range or exact version of a Python version to use, using SemVer's version range syntax
+35
View File
@@ -0,0 +1,35 @@
name: ci-ifcedit-pypi
on:
workflow_dispatch:
jobs:
activate:
runs-on: ubuntu-latest
if: |
github.repository == 'IfcOpenShell/IfcOpenShell'
steps:
- name: Set env
run: echo ok go
build:
needs: activate
runs-on: ubuntu-latest
strategy:
fail-fast: false
steps:
- uses: actions/checkout@v6
- uses: actions/setup-python@v6
with:
python-version: '3.11'
- name: Compile
run: |
pip install build
cd src/ifcedit &&
make dist IS_STABLE=TRUE
- name: Publish a Python distribution to PyPI
uses: pypa/gh-action-pypi-publish@release/v1
with:
user: __token__
password: ${{ secrets.PYPI_API_TOKEN }}
packages_dir: src/ifcedit/dist
+1 -1
View File
@@ -18,7 +18,7 @@ jobs:
strategy: strategy:
fail-fast: false fail-fast: false
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@v6
- uses: actions/setup-python@v6 # https://github.com/actions/setup-python - uses: actions/setup-python@v6 # https://github.com/actions/setup-python
with: with:
python-version: '3.11' # Version range or exact version of a Python version to use, using SemVer's version range syntax python-version: '3.11' # Version range or exact version of a Python version to use, using SemVer's version range syntax
+36
View File
@@ -0,0 +1,36 @@
name: ci-ifcmcp-pypi
on:
workflow_dispatch:
jobs:
activate:
runs-on: ubuntu-latest
if: |
github.repository == 'IfcOpenShell/IfcOpenShell'
steps:
- name: Set env
run: echo ok go
build:
needs: activate
runs-on: ubuntu-latest
strategy:
fail-fast: false
steps:
- uses: actions/checkout@v6
- uses: actions/setup-python@v6
with:
python-version: '3.11'
- name: Compile
run: |
pip install build
cd src/ifcmcp &&
make dist IS_STABLE=TRUE
- name: Publish a Python distribution to PyPI
uses: pypa/gh-action-pypi-publish@release/v1
with:
user: __token__
password: ${{ secrets.PYPI_API_TOKEN }}
packages_dir: src/ifcmcp/dist
verbose: true
@@ -24,7 +24,7 @@ jobs:
if: | if: |
github.repository == 'IfcOpenShell/IfcOpenShell' github.repository == 'IfcOpenShell/IfcOpenShell'
steps: steps:
- uses: mamba-org/setup-micromamba@v2 # https://github.com/mamba-org/setup-micromamba - uses: mamba-org/setup-micromamba@v3 # https://github.com/mamba-org/setup-micromamba
with: with:
environment-name: test-env environment-name: test-env
create-args: >- create-args: >-
@@ -21,7 +21,7 @@ jobs:
date: ${{ steps.date.outputs.date }} date: ${{ steps.date.outputs.date }}
verdate: ${{ steps.verdate.outputs.verdate }} verdate: ${{ steps.verdate.outputs.verdate }}
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@v6
- name: Set env - name: Set env
run: echo ok go run: echo ok go
@@ -54,8 +54,7 @@ jobs:
platform: [ platform: [
{ name: win, distver: windows-latest, pkg_dir: 'win-64' }, { name: win, distver: windows-latest, pkg_dir: 'win-64' },
{ name: linux, distver: ubuntu-latest, pkg_dir: 'linux-64' }, { name: linux, distver: ubuntu-latest, pkg_dir: 'linux-64' },
{ name: macOS-arm, distver: macos-latest, pkg_dir: 'osx-arm64' }, { name: macOS-arm, distver: macos-latest, pkg_dir: 'osx-arm64' }
{ name: macOS-x86, distver: macos-13, pkg_dir: 'osx-64' }
] ]
steps: steps:
- name: Set Swap Space - name: Set Swap Space
@@ -76,7 +75,7 @@ jobs:
echo "ARTIFACTS_DIR=/home/runner/work/artifacts" >> $GITHUB_ENV echo "ARTIFACTS_DIR=/home/runner/work/artifacts" >> $GITHUB_ENV
fi fi
- uses: actions/checkout@v5 - uses: actions/checkout@v6
with: with:
submodules: recursive submodules: recursive
@@ -85,7 +84,7 @@ jobs:
run: | run: |
curl -L https://github.com/phracker/MacOSX-SDKs/releases/download/11.3/MacOSX10.13.sdk.tar.xz | tar -xvJf - -C /Users/runner/work/ curl -L https://github.com/phracker/MacOSX-SDKs/releases/download/11.3/MacOSX10.13.sdk.tar.xz | tar -xvJf - -C /Users/runner/work/
- uses: mamba-org/setup-micromamba@v2 # https://github.com/mamba-org/setup-micromamba - uses: mamba-org/setup-micromamba@v3 # https://github.com/mamba-org/setup-micromamba
with: with:
environment-name: test-env environment-name: test-env
create-args: >- create-args: >-
+9 -12
View File
@@ -21,7 +21,7 @@ jobs:
runs-on: ubuntu-22.04 runs-on: ubuntu-22.04
needs: activate needs: activate
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@v6
with: with:
submodules: recursive submodules: recursive
@@ -35,16 +35,13 @@ jobs:
- -
name: ccache name: ccache
uses: hendrikmuhs/ccache-action@v1.2 uses: hendrikmuhs/ccache-action@v1.2.22
- -
name: Build ifcopenshell name: Build ifcopenshell
run: | run: |
mkdir build && cd build mkdir build && cd build
cmake \ cmake \
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
-DCMAKE_CXX_STANDARD=17 \
-DCMAKE_INSTALL_PREFIX=$PWD/install/ \ -DCMAKE_INSTALL_PREFIX=$PWD/install/ \
-DCMAKE_BUILD_TYPE=Release \ -DCMAKE_BUILD_TYPE=Release \
-DCMAKE_PREFIX_PATH=/usr \ -DCMAKE_PREFIX_PATH=/usr \
@@ -76,7 +73,7 @@ jobs:
make package make package
working-directory: build working-directory: build
- name: Upload - name: Upload
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@v7
with: with:
# Artifact name # Artifact name
name: ifcos-artifacts name: ifcos-artifacts
@@ -89,31 +86,31 @@ jobs:
name: Docker Build, Tag, Push name: Docker Build, Tag, Push
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@v6
with: with:
lfs: true lfs: true
- name: Download - name: Download
uses: actions/download-artifact@v6.0.0 uses: actions/download-artifact@v8.0.1
with: with:
# Artifact name # Artifact name
name: ifcos-artifacts name: ifcos-artifacts
path: artifacts/ path: artifacts/
- -
name: Set up QEMU name: Set up QEMU
uses: docker/setup-qemu-action@v3 uses: docker/setup-qemu-action@v4
- -
name: Set up Docker Buildx name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3 uses: docker/setup-buildx-action@v4
- -
name: Login to Dockerhub name: Login to Dockerhub
uses: docker/login-action@v3 uses: docker/login-action@v4
with: with:
username: aecgeeks username: aecgeeks
password: ${{ secrets.DOCKER_HUB_TOKEN }} password: ${{ secrets.DOCKER_HUB_TOKEN }}
- -
name: Build container image name: Build container image
uses: docker/build-push-action@v6 uses: docker/build-push-action@v7
with: with:
context: artifacts context: artifacts
repository: aecgeeks/ifcopenshell repository: aecgeeks/ifcopenshell
@@ -24,7 +24,7 @@ jobs:
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
pyver: [py39, py310, py311, py312, py313, py314] pyver: [py310, py311, py312, py313, py314]
config: config:
- { - {
name: "Windows 64bit", name: "Windows 64bit",
@@ -47,7 +47,7 @@ jobs:
short_name: macosm164 short_name: macosm164
} }
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@v6
with: with:
submodules: recursive submodules: recursive
- uses: actions/setup-python@v6 # https://github.com/actions/setup-python - uses: actions/setup-python@v6 # https://github.com/actions/setup-python
+2 -2
View File
@@ -19,7 +19,7 @@ jobs:
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
pyver: [py39, py310, py311, py312, py313, py314] pyver: [py310, py311, py312, py313, py314]
config: config:
- { - {
name: "Windows 64bit", name: "Windows 64bit",
@@ -38,7 +38,7 @@ jobs:
short_name: macosm164 short_name: macosm164
} }
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@v6
with: with:
submodules: recursive submodules: recursive
- uses: actions/setup-python@v6 # https://github.com/actions/setup-python - uses: actions/setup-python@v6 # https://github.com/actions/setup-python
+1 -1
View File
@@ -18,7 +18,7 @@ jobs:
strategy: strategy:
fail-fast: false fail-fast: false
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@v6
- uses: actions/setup-python@v6 # https://github.com/actions/setup-python - uses: actions/setup-python@v6 # https://github.com/actions/setup-python
with: with:
python-version: '3.11' # Version range or exact version of a Python version to use, using SemVer's version range syntax python-version: '3.11' # Version range or exact version of a Python version to use, using SemVer's version range syntax
+35
View File
@@ -0,0 +1,35 @@
name: ci-ifcquery-pypi
on:
workflow_dispatch:
jobs:
activate:
runs-on: ubuntu-latest
if: |
github.repository == 'IfcOpenShell/IfcOpenShell'
steps:
- name: Set env
run: echo ok go
build:
needs: activate
runs-on: ubuntu-latest
strategy:
fail-fast: false
steps:
- uses: actions/checkout@v6
- uses: actions/setup-python@v6
with:
python-version: '3.11'
- name: Compile
run: |
pip install build
cd src/ifcquery &&
make dist IS_STABLE=TRUE
- name: Publish a Python distribution to PyPI
uses: pypa/gh-action-pypi-publish@release/v1
with:
user: __token__
password: ${{ secrets.PYPI_API_TOKEN }}
packages_dir: src/ifcquery/dist
+1 -1
View File
@@ -25,7 +25,7 @@ jobs:
strategy: strategy:
fail-fast: false fail-fast: false
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@v6
- uses: actions/setup-python@v6 # https://github.com/actions/setup-python - uses: actions/setup-python@v6 # https://github.com/actions/setup-python
with: with:
architecture: 'x64' # optional x64 or x86. Defaults to x64 if not specified architecture: 'x64' # optional x64 or x86. Defaults to x64 if not specified
+1 -1
View File
@@ -19,7 +19,7 @@ jobs:
strategy: strategy:
fail-fast: false fail-fast: false
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@v6
- uses: actions/setup-python@v6 # https://github.com/actions/setup-python - uses: actions/setup-python@v6 # https://github.com/actions/setup-python
with: with:
architecture: 'x64' # optional x64 or x86. Defaults to x64 if not specified architecture: 'x64' # optional x64 or x86. Defaults to x64 if not specified
+2 -2
View File
@@ -10,9 +10,9 @@ jobs:
publish_website: publish_website:
runs-on: ubuntu-22.04 runs-on: ubuntu-22.04
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@v6
- name: Checkout ifctester_org_static_html - name: Checkout ifctester_org_static_html
uses: actions/checkout@v5 uses: actions/checkout@v6
with: with:
repository: IfcOpenShell/ifctester_org_static_html repository: IfcOpenShell/ifctester_org_static_html
token: ${{ secrets.IFCOPENBOT_TOKEN }} token: ${{ secrets.IFCOPENBOT_TOKEN }}
+1 -1
View File
@@ -18,7 +18,7 @@ jobs:
strategy: strategy:
fail-fast: false fail-fast: false
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@v6
- uses: actions/setup-python@v6 # https://github.com/actions/setup-python - uses: actions/setup-python@v6 # https://github.com/actions/setup-python
with: with:
python-version: '3.11' # Version range or exact version of a Python version to use, using SemVer's version range syntax python-version: '3.11' # Version range or exact version of a Python version to use, using SemVer's version range syntax
+119
View File
@@ -0,0 +1,119 @@
name: ci-lint
on:
push:
pull_request:
jobs:
lint-formatting:
runs-on: ubuntu-latest
env:
MIN_IOS_PY_VERSION: "3.10"
MIN_BLENDER_PY_VERSION: "3.11"
steps:
- name: Action - checkout repository
uses: actions/checkout@v6
- name: Action - install python
uses: actions/setup-python@v6
with:
python-version: ${{ env.MIN_IOS_PY_VERSION }}
- name: Action - install python
uses: actions/setup-python@v6
with:
python-version: ${{ env.MIN_BLENDER_PY_VERSION }}
- name: Install dependencies
run: |
curl -LsSf https://astral.sh/uv/install.sh | sh
uv tool install ruff
uv tool install black
uv tool install poethepoet
uv tool install ty
# black doesn't catch all syntax errors, so we check them explicitly.
- name: Check syntax errors
id: syntax-errors
run: |
ERROR=0
# Using 2 Python versions - one minimum required for IfcOpenShell
# and other that's used by Blender currently.
python${{ env.MIN_IOS_PY_VERSION }} -W error -m compileall -q src/ifcopenshell-python || ERROR=1
python${{ env.MIN_BLENDER_PY_VERSION }} -W error -m compileall -q src/bonsai || ERROR=1
exit $ERROR
continue-on-error: true
- name: Black formatter
id: black
uses: psf/black@stable
continue-on-error: true
# Same check as above, but just for creating github annotations.
- name: Black formatter annotations
id: black-annotations
run: |
uv tool install black-codeclimate
pip install github_action_utils
black --diff --check . | black-codeclimate | python .github/workflows/black_to_github_annotations.py
continue-on-error: true
- name: ty check
id: ty
run: |
poe ty-venv
poe ty
continue-on-error: true
- name: Ruff check
id: ruff
run: |
# Ensure execution continues, since we need to cache the output.
set +e
ERROR=0
# Keep colored output inside action logs, strip it from color codes for summary.
uv tool install ansi2txt
# `ruff` disables color output in CI by default.
export FORCE_COLOR="1"
run_check() {
local out
out="$("$@" 2>&1)"
local exit_code=$?
if [ "$exit_code" -ne 0 ]; then
ERROR=1
fi
# Rerun just for GitHub annotations.
"$@" --output-format=github || true
echo "$out"
echo "\`\`\`python" >> $GITHUB_STEP_SUMMARY
echo "$out" | ansi2txt >> $GITHUB_STEP_SUMMARY
echo "\`\`\`" >> $GITHUB_STEP_SUMMARY
}
run_check poe ruff-main
run_check poe ruff-old
exit $ERROR
continue-on-error: true
- name: Final check
run: |
ERROR=0
if [ "${{ steps.syntax-errors.outcome }}" != "success" ]; then
echo "::error::Syntax errors check failed, see 'syntax-errors' step for the details." && ERROR=1
fi
if [ "${{ steps.black.outcome }}" != "success" ]; then
echo "::error::Black formatting check failed, see Summary or 'black' step for the details." && ERROR=1
fi
if [ "${{ steps.ruff.outcome }}" != "success" ]; then
echo "::error::Ruff check failed, see Summary or 'ruff' step for the details." && ERROR=1
fi
if [ "${{ steps.ty.outcome }}" != "success" ]; then
echo "::error::ty check failed, see 'ty check' step for the details." && ERROR=1
fi
exit $ERROR
@@ -0,0 +1,46 @@
name: Release Pyodide WASM Wheel
on:
workflow_dispatch:
jobs:
build-and-push:
runs-on: ubuntu-latest
steps:
- name: Checkout IfcOpenShell
uses: actions/checkout@v6
- name: Install uv
uses: astral-sh/setup-uv@v7
- name: Build wheel
working-directory: pyodide
run: uv run pack_wheel.py --build
- name: Find wheel
id: wheel
run: |
WHEEL=$(ls pyodide/dist/ifcopenshell-*.whl)
echo "path=$WHEEL" >> $GITHUB_OUTPUT
echo "name=$(basename $WHEEL)" >> $GITHUB_OUTPUT
- name: Checkout wasm-wheels
uses: actions/checkout@v6
with:
repository: IfcOpenShell/wasm-wheels
path: wasm-wheels
token: ${{ secrets.BUILD_REPO_TOKEN }}
- name: Commit and push wheel to wasm-wheels
run: |
WHEEL_NAME="${{ steps.wheel.outputs.name }}"
cp "${{ steps.wheel.outputs.path }}" "wasm-wheels/$WHEEL_NAME"
cd wasm-wheels
git config user.name "IfcOpenBot"
git config user.email "ifcopenbot@ifcopenshell.org"
git add "$WHEEL_NAME"
git commit -m "Add $WHEEL_NAME"
VERSION=$(cat ../VERSION)
git tag "v${VERSION}"
git push origin main
git push origin "v${VERSION}"
+73 -13
View File
@@ -34,8 +34,12 @@ jobs:
compile-and-test: compile-and-test:
runs-on: ubuntu-22.04 runs-on: ubuntu-22.04
needs: activate needs: activate
env:
# Colored output for cmake.
CLICOLOR_FORCE: "1"
CMAKE_COLOR_DIAGNOSTICS: "ON"
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@v6
with: with:
submodules: recursive submodules: recursive
@@ -49,12 +53,16 @@ jobs:
python -m pip install --upgrade pip python -m pip install --upgrade pip
pip install xmlschema xsdata numpy lxml pytest isodate lark networkx tabulate python-dateutil shapely pip install xmlschema xsdata numpy lxml pytest isodate lark networkx tabulate python-dateutil shapely
pip install src/bcf --no-deps pip install src/bcf --no-deps
pip install git+https://github.com/zdhoward/aud
pip install pytest-xdist==3.8.0 pip install pytest-xdist==3.8.0
- name: Install C++ dependencies - name: Install C++ dependencies
run: | run: |
sudo apt update sudo apt update
# `occt-misc` is only needed for 22.04, since it has cmake configs.
# In 24.04+, the needed files were moved `libocct-foundation-dev` and `occt-misc` can be removed.
# Other libs in `OCCT_CMAKE_DEPS` are needed only for cmake config to work properly, they're not used directly.
OCCT_CMAKE_DEPS="occt-misc libocct-draw-dev tcl-dev tk-dev libxi-dev"
sudo apt-get install --no-install-recommends \ sudo apt-get install --no-install-recommends \
git cmake gcc g++ \ git cmake gcc g++ \
libboost-date-time-dev \ libboost-date-time-dev \
@@ -67,13 +75,11 @@ jobs:
libpcre3-dev libxml2-dev \ libpcre3-dev libxml2-dev \
libtbb-dev nlohmann-json3-dev \ libtbb-dev nlohmann-json3-dev \
libocct-foundation-dev libocct-modeling-algorithms-dev libocct-modeling-data-dev libocct-ocaf-dev libocct-visualization-dev libocct-data-exchange-dev \ libocct-foundation-dev libocct-modeling-algorithms-dev libocct-modeling-data-dev libocct-ocaf-dev libocct-visualization-dev libocct-data-exchange-dev \
${OCCT_CMAKE_DEPS} \
libhdf5-dev libcgal-dev libeigen3-dev libhdf5-dev libcgal-dev libeigen3-dev
- name: ccache - name: ccache
# TODO: temporarily pointing to 1.2.19 to get notified by dependabot when 1.2.20 is released uses: hendrikmuhs/ccache-action@v1.2.22
# to update hardcoded references to commits in some other workflows.
# Then we can switch back to 1.2 in all actions.
uses: hendrikmuhs/ccache-action@v1.2.19
with: with:
key: ubuntu-22.04-${{ runner.arch }} key: ubuntu-22.04-${{ runner.arch }}
@@ -118,6 +124,31 @@ jobs:
-DCMAKE_CXX_FLAGS_INIT="-fPIC" -DCMAKE_CXX_FLAGS_INIT="-fPIC"
sudo make -j$(nproc) install sudo make -j$(nproc) install
# We need zstd and libxml2 just for cmake config files to test the examples build.
# zslibzstd-dev has cmake config only on Ubuntu 24.04+.
- name : Build zstd
run: |
git clone https://github.com/facebook/zstd --depth 1 --branch v1.5.7
cd zstd
# `build` already exists.
mkdir build_ && cd build_
cmake ../build/cmake -DCMAKE_BUILD_TYPE=Release \
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache
sudo cmake --build . --target install -j $(nproc)
# libxml2-dev doesn't have cmake configs even on Ubuntu 24.04+.
- name: Build libxml2
run: |
git clone https://gitlab.gnome.org/GNOME/libxml2.git --branch v2.13.8 --depth 1
cd libxml2
mkdir build && cd build
cmake .. \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache
sudo cmake --build . --target install -j $(nproc)
# Ubuntu has `swig` package, but we build it to match the version we use in the main build. # Ubuntu has `swig` package, but we build it to match the version we use in the main build.
# To avoid failing tests when checking stub generation. # To avoid failing tests when checking stub generation.
- name: build swig - name: build swig
@@ -125,9 +156,8 @@ jobs:
# Remove default swig to avoid conflicts. # Remove default swig to avoid conflicts.
sudo apt remove --purge swig swig4.0 sudo apt remove --purge swig swig4.0
sudo apt-get install -y libpcre2-dev bison sudo apt-get install -y libpcre2-dev bison
git clone https://github.com/swig/swig git clone https://github.com/swig/swig --branch v4.1.0 --depth 1
cd swig cd swig
git checkout v4.1.0
mkdir build && cd build mkdir build && cd build
cmake .. \ cmake .. \
-DCMAKE_BUILD_TYPE=Release \ -DCMAKE_BUILD_TYPE=Release \
@@ -141,21 +171,17 @@ jobs:
echo ${{ env.pythonLocation }} echo ${{ env.pythonLocation }}
mkdir build && cd build mkdir build && cd build
# Ubuntu 22.04's libocct-foundation-dev package doesn't have Config.cmake, so we provide OCC paths directly.
# In later versions of Ubuntu, this can be simplified and the OCC paths can be removed.
cmake \ cmake \
-DCMAKE_CXX_STANDARD=17 \
-DCMAKE_BUILD_TYPE=Release \ -DCMAKE_BUILD_TYPE=Release \
-DCMAKE_PREFIX_PATH=/usr \ -DCMAKE_PREFIX_PATH=/usr \
-DCMAKE_SYSTEM_PREFIX_PATH=/usr \ -DCMAKE_SYSTEM_PREFIX_PATH=/usr \
-DOCC_INCLUDE_DIR=/usr/include/opencascade \
-DOCC_LIBRARY_DIR=/usr/lib/x86_64-linux-gnu \
-DPYTHON_EXECUTABLE:FILEPATH=${{ env.pythonLocation }}/bin/python \ -DPYTHON_EXECUTABLE:FILEPATH=${{ env.pythonLocation }}/bin/python \
-DPYTHON_INCLUDE_DIR:PATH=${{ env.pythonLocation }}/include/python3.11 \ -DPYTHON_INCLUDE_DIR:PATH=${{ env.pythonLocation }}/include/python3.11 \
-DUSE_MMAP=On \ -DUSE_MMAP=On \
"-DSCHEMA_VERSIONS=2x3;4;4x3_add2" \ "-DSCHEMA_VERSIONS=2x3;4;4x3_add2" \
-DGLTF_SUPPORT=On \ -DGLTF_SUPPORT=On \
-DWITH_ROCKSDB=On \ -DWITH_ROCKSDB=On \
-DBUILD_EXAMPLES=ON \
../cmake ../cmake
sudo make -j $(nproc) sudo make -j $(nproc)
sudo make install sudo make install
@@ -178,6 +204,39 @@ jobs:
run: | run: |
IfcConvert test/input/acad2010_walls.ifc test/input/acad2010_walls.obj IfcConvert test/input/acad2010_walls.ifc test/input/acad2010_walls.obj
- name: Build standalone examples to test cmake package
run: |
set -x
cd src/examples
mkdir build && cd build
cmake .. -DCMAKE_BUILD_TYPE=Release \
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache
cmake --build .
./arbitrary_open_profile_def && test -f arbitrary_open_profile_def.ifc
./composite_profile_def && test -f composite_profile_def.ifc
./csg_primitive && test -f csg_primitive.ifc
./ellipse_pies && test -f ellipse_pies.ifc
./faces && test -f faces.ifc
./ifc_curve_rebar && test -f ifc_curve_rebar.ifc
./profiles
test -f IfcUShapeProfileDef.ifc
test -f IfcTShapeProfileDef.ifc
test -f IfcZShapeProfileDef.ifc
test -f IfcEllipseProfileDef.ifc
test -f IfcIShapeProfileDef.ifc
test -f IfcLShapeProfileDef.ifc
test -f IfcCShapeProfileDef.ifc
test -f IfcCircleProfileDef.ifc
test -f IfcRectangleProfileDef.ifc
test -f IfcTrapeziumProfileDef.ifc
./IfcParseExamples "../IfcParseExamples_test.ifc"
./IfcOpenHouse && test -f IfcOpenHouse.ifc
./IfcAdvancedHouse && test -f IfcAdvancedHouse.ifc
./IfcAlignment && test -f IfcAlignment.ifc
./IfcSimplifiedAlignment && test -f IfcSimplifiedAlignment.ifc
./triangulated_faceset && test -f triangulated_faceset.ifc
- name: Test ifcopenshell-python - name: Test ifcopenshell-python
run: | run: |
cd test cd test
@@ -195,6 +254,7 @@ jobs:
cd ../ifcpatch && make test || ERROR=1 cd ../ifcpatch && make test || ERROR=1
pip install -e ../ifctester --no-deps pip install -e ../ifctester --no-deps
cd ../ifctester && make test || ERROR=1 cd ../ifctester && make test || ERROR=1
make build-ids-docs || ERROR=1
# Run mathutils related tests at the end to ensure no other code is relying on mathutils. # Run mathutils related tests at the end to ensure no other code is relying on mathutils.
cd ../ifcopenshell-python cd ../ifcopenshell-python
pip install mathutils pip install mathutils
@@ -11,7 +11,7 @@ jobs:
steps: steps:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@v5 uses: actions/checkout@v6
- name: Set up Python - name: Set up Python
uses: actions/setup-python@v6 uses: actions/setup-python@v6
-36
View File
@@ -1,36 +0,0 @@
name: Build and Deploy Stable Documentation
on:
workflow_dispatch: # Manual trigger
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v5
- name: Set up Python
uses: actions/setup-python@v6
with:
python-version: '3.x'
- name: Install dependencies
run: |
cd src/bonsai/docs
pip install -r requirements.txt # Run pip install from the docs directory
- name: Build documentation
run: |
cd src/bonsai/docs
make html
- name: Deploy to GitHub Pages (Stable)
uses: peaceiris/actions-gh-pages@v4
with:
deploy_key: ${{ secrets.ACTIONS_DEPLOY_KEY }}
external_repository: IfcOpenShell/bonsaibim_org_docs
publish_branch: main
cname: docs.bonsaibim.org
publish_dir: src/bonsai/docs/_build/html
+65
View File
@@ -0,0 +1,65 @@
name: Deploy AI chat App to static page repo
permissions:
id-token: write
pages: write
on:
push:
paths:
- 'src/ifcchat/**'
- '.github/workflows/publish-aichat-app.yaml'
branches:
- v0.8.0
workflow_dispatch:
jobs:
activate:
runs-on: ubuntu-latest
if: |
github.repository == 'IfcOpenShell/IfcOpenShell'
steps:
- name: Set env
run: echo ok go
build:
needs: activate
runs-on: ubuntu-latest
steps:
- name: Checkout (recursive)
uses: actions/checkout@v6
with:
submodules: recursive
fetch-depth: 0
- name: Checkout intermediate Pages repo
uses: actions/checkout@v6
with:
repository: IfcOpenShell/aichat_ifcopenshell_org_static_html
ref: gh-pages
path: output
token: ${{ secrets.WEBSITE_PUBLISH }}
- name: Sync demo app into target subfolder
run: |
rsync -av --delete --exclude='.git/' src/ifcchat/ output/
- name: Setup Python
uses: actions/setup-python@v6
with:
python-version: "3.x"
- name: Download wheels
working-directory: output/
run: |
pip download ifcquery==0.8.5 ifcopenshell-mcp==0.8.5 ifcedit==0.8.5 lark==1.3.1 isodate==0.7.2 --no-deps -d ./dist
- name: Commit and push if changed
working-directory: output
run: |
git config --global user.name 'IfcOpenBot'
git config --global user.email 'IfcOpenBot@users.noreply.github.com'
git add .
if git diff --cached --quiet; then
echo "No changes to commit"
exit 0
fi
git commit -m "$(git log --oneline -1)"
git push origin gh-pages
+25 -18
View File
@@ -1,4 +1,4 @@
name: Deploy Pyodide Demo App to GitHub Pages name: Deploy Pyodide Demo App to static page repo
permissions: permissions:
id-token: write id-token: write
@@ -11,6 +11,7 @@ on:
- '.github/workflows/publish-pyodide-demo-app.yml' - '.github/workflows/publish-pyodide-demo-app.yml'
branches: branches:
- v0.8.0 - v0.8.0
workflow_dispatch:
jobs: jobs:
activate: activate:
@@ -26,25 +27,31 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout (recursive) - name: Checkout (recursive)
uses: actions/checkout@v5 uses: actions/checkout@v6
with: with:
submodules: recursive submodules: recursive
fetch-depth: 0 fetch-depth: 0
- name: Setup Pages - name: Checkout intermediate Pages repo
uses: actions/configure-pages@v5 uses: actions/checkout@v6
- name: Upload static files as artifact
id: deployment
uses: actions/upload-pages-artifact@v4
with: with:
path: src/pyodide/demo-app/ repository: IfcOpenShell/wasm_ifcopenshell_org_static_html
ref: gh-pages
path: output
token: ${{ secrets.WEBSITE_PUBLISH }}
- name: Sync demo app into target subfolder
run: |
rsync -av --delete --exclude='.git/' src/pyodide/demo-app/ output/
- name: Commit and push if changed
working-directory: output
run: |
git config --global user.name 'IfcOpenBot'
git config --global user.email 'IfcOpenBot@users.noreply.github.com'
deploy: git add .
environment: if git diff --cached --quiet; then
name: github-pages echo "No changes to commit"
url: ${{ steps.deployment.outputs.page_url }} exit 0
runs-on: ubuntu-latest fi
needs: build
steps: git commit -m "$(git log --oneline -1)"
- name: Deploy to GitHub Pages git push origin gh-pages
id: deployment
uses: actions/deploy-pages@v4
+1 -2
View File
@@ -17,7 +17,7 @@ jobs:
runs-on: ubuntu-22.04 runs-on: ubuntu-22.04
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v5 uses: actions/checkout@v6
with: with:
submodules: recursive submodules: recursive
- name: Install C++ dependencies - name: Install C++ dependencies
@@ -46,7 +46,6 @@ jobs:
mkdir build && cd build mkdir build && cd build
cmake \ cmake \
-DCMAKE_INSTALL_PREFIX=$PWD/install/ \ -DCMAKE_INSTALL_PREFIX=$PWD/install/ \
-DCMAKE_CXX_STANDARD=17 \
-DCMAKE_BUILD_TYPE=Release \ -DCMAKE_BUILD_TYPE=Release \
-DCMAKE_PREFIX_PATH=/usr \ -DCMAKE_PREFIX_PATH=/usr \
-DCMAKE_SYSTEM_PREFIX_PATH=/usr \ -DCMAKE_SYSTEM_PREFIX_PATH=/usr \
+19 -1
View File
@@ -4,6 +4,9 @@
/_deps-vs*-x*-installed/ /_deps-vs*-x*-installed/
/_installed-vs*-x*/ /_installed-vs*-x*/
/build/ /build/
/src/examples/build/
# ifctester docs output
/src/ifctester/test/build/
# output directories # output directories
/cmake/out/ /cmake/out/
@@ -11,6 +14,7 @@
/src/ifcmax/out/ /src/ifcmax/out/
/src/ifcwrap/out/ /src/ifcwrap/out/
/src/qtviewer/out/ /src/qtviewer/out/
/src/ifctester/webapp/public/pyodide/
/win/BuildDepsCache*.txt /win/BuildDepsCache*.txt
@@ -21,6 +25,8 @@ venv
# Visual Studio Code files # Visual Studio Code files
.vscode .vscode
!.vscode/launch.json
!.vscode/tasks.json
.vs .vs
# PyCharm files # PyCharm files
@@ -77,8 +83,14 @@ src/ifcopenshell-python/test/build
# bonsai i18n # bonsai i18n
src/bonsai/bonsai/translations.py src/bonsai/bonsai/translations.py
# bonsai test temp files # bonsai external dependencies (cloned for just ty checks)
src/bonsai/external_dependencies/
# bonsai test temp/cache files
src/bonsai/test/files/temp src/bonsai/test/files/temp
src/bonsai/test/files/*.cache.blend
src/bonsai/test/files/*.cache.json
src/bonsai/test/files/*.cache.sqlite
# bonsai data # bonsai data
src/bonsai/bonsai/bim/data/build/ src/bonsai/bonsai/bim/data/build/
@@ -110,3 +122,9 @@ dev_environment.bat
src/ifcopenshell-python/ifcopenshell/express/*.exp src/ifcopenshell-python/ifcopenshell/express/*.exp
src/ifcopenshell-python/ifcopenshell/express/*.exp.cache.dat src/ifcopenshell-python/ifcopenshell/express/*.exp.cache.dat
# temp files from AI coding tools
*.claude
*.py.tmp*
*.json.tmp*
+24
View File
@@ -0,0 +1,24 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "Python Debugger: Remote Attach",
"type": "debugpy",
"request": "attach",
"connect": {
"host": "localhost",
"port": 5678
},
"pathMappings": [
{
"localRoot": "${config:bonsai.localRoot}",
"remoteRoot": "${config:bonsai.remoteRoot}"
}
]
}
]
}
+53
View File
@@ -0,0 +1,53 @@
{
// See https://go.microsoft.com/fwlink/?LinkId=733558
// for the documentation about the tasks.json format
"version": "2.0.0",
"tasks": [
{
"label": "Configure bonsai/vscode development environment",
"type": "shell",
"command": "${input:blenderPath}",
"args": [
"--background",
"--python", "${workspaceFolder}/src/bonsai/scripts/dev_environment_vscode_config.py"
],
"problemMatcher": []
},
{
"label": "Launch blender with debugpy",
"type": "shell",
"command": "blender",
"options": {
"cwd": "${config:bonsai.blenderPath}"
},
"args": [
"--python-expr",
"import debugpy; debugpy.listen(5678)"
],
"problemMatcher": []
},
{
"label": "Install debugpy in Blender",
"type": "shell",
"command": "blender",
"options": {
"cwd": "${config:bonsai.blenderPath}"
},
"args": [
"--background",
"--python-expr",
"import os, sys, subprocess; path=os.path.abspath(sys.executable); subprocess.call([path, '-m', 'ensurepip']); subprocess.call([path, '-m', 'pip', 'install', '--upgrade', 'debugpy'])"
],
"problemMatcher": []
}
],
"inputs": [
{
"id": "blenderPath",
"type": "promptString",
"description": "Enter the path to the blender executable",
"default": "blender"
}
]
}
+153
View File
@@ -0,0 +1,153 @@
<!-- This file was generated with the assistance of an AI coding tool. -->
# AGENTS.md
Guidelines for AI coding agents contributing to IfcOpenShell. This file is
intended to be read by all AI agents regardless of platform (Claude Code,
Copilot, Cursor, etc.) in addition to any tool-specific configuration files.
Human contributors using AI tools should also read this document carefully,
as they are responsible for ensuring their contributions comply with these
guidelines.
## Project Overview
IfcOpenShell is an open source library for working with Industry Foundation
Classes (IFC). It provides C++ and Python APIs, geometry processing, and an
ecosystem of tools including IfcConvert and the Bonsai Blender add-on.
## Licensing
All contributions must be compatible with the project's licensing:
- **Library code** (everything except Bonsai): **LGPL-3.0-or-later**
- **Bonsai** (`src/bonsai/`): **GPL-3.0-or-later**
There is no Contributor License Agreement (CLA). By submitting a pull request,
you agree that your contribution is licensed under the applicable license above.
## Indicating AI-Generated Code
Contributors must clearly indicate when code has been generated or
substantially written by an AI tool.
### Commits
Commits that modify existing code must include a note in the **body** of the
commit message (not the subject line) indicating that the change was
AI-generated. For example:
```
Fix off-by-one error in element iteration
The loop termination condition was incorrect when processing
IfcRelAggregates relationships.
Generated with the assistance of an AI coding tool.
```
### New Files
New files that are AI-generated must include a comment near the top of the
file indicating this. Use the appropriate comment syntax for the language:
```python
# This file was generated with the assistance of an AI coding tool.
```
```cpp
// This file was generated with the assistance of an AI coding tool.
```
### Pull Requests
Pull requests containing AI-generated code must indicate in the PR description
which parts of the contribution are AI-generated. If the entire PR is
AI-generated, state that clearly. If only specific commits or files are
AI-generated, identify them.
## Pull Request Guidelines
### Scope and Size
- Each pull request should address a **single issue or feature**.
- Do not mix unrelated changes (e.g., bug fixes with refactoring or style
changes) in the same PR.
- Large pull requests should be broken down into **multiple small, standalone
commits** that are each easy to review independently. Rewrite commit history
for this purpose if necessary.
- PRs that are minimal, focused solutions to a specific problem are much more
likely to be accepted.
### What to Avoid
- **Over-engineering**: Do not add features, abstractions, or configurability
beyond what is needed to solve the immediate problem.
- **Scope creep**: Do not make changes to files or code that are not directly
related to the task at hand.
- **Unnecessary additions**: Do not add docstrings, comments, type annotations,
or error handling to code you did not otherwise need to change.
- **Cosmetic changes**: Do not reformat, rename, or reorganize code that is
unrelated to your change.
## Commit Messages
- The **subject line** must be **50 characters or less**.
- Use the **imperative mood** (e.g., "Fix crash in geometry kernel", not
"Fixed crash" or "Fixes crash").
- A commit message can be a single line if the purpose is obvious from the
subject alone.
- Otherwise, add a blank line after the subject followed by a short explanation
of a few lines in the body.
## Code Style
### Python
- **Line length**: 120 characters
- **Formatter**: black
- **Linter**: ruff
- Configuration is in `pyproject.toml`
### C++
- **Standard**: C++17 minimum
- **Formatter**: clang-format (configuration in `.clang-format`)
- **Linter**: clang-tidy (configuration in `.clang-tidy`)
Run linters and formatters **before submitting** your pull request. Do not rely
on CI to catch formatting issues.
## Testing
- Pull requests with test coverage are **much more likely to be merged**.
- If tests are appropriate and feasible for your change, they should be
included.
- Tests are not required for every change (e.g., documentation-only changes),
but the expectation is that testable code changes come with tests.
- Python tests use **pytest** and are located in `test/` or `tests/` directories
within each package under `src/`.
- Run the existing test suite for the package you modified before submitting.
## Architecture Quick Reference
### Directory Structure
- `src/ifcparse/` — C++ IFC file parsing
- `src/ifcgeom/` — C++ geometry processing (OpenCASCADE and CGAL kernels)
- `src/serializers/` — Output format serializers (glTF, Collada, SVG, etc.)
- `src/ifcwrap/` — SWIG Python bindings
- `src/ifcconvert/` — CLI conversion tool
- `src/ifcopenshell-python/` — Python API (`ifcopenshell` package)
- `src/bonsai/` — Blender add-on (GPL-3.0-or-later)
- `src/ifctester/` — IDS model auditing
- `src/ifcpatch/` — IFC file manipulation scripts
- `src/ifcdiff/` — IFC model comparison
- `src/ifcclash/` — Clash detection
- `src/ifccsv/` — Schedule import/export
### IFC Schema Versions
The library supports IFC2x3 TC1, IFC4 Add2 TC1, IFC4x1, IFC4x2, and
IFC4x3 Add2. Schema-specific code is compiled conditionally. Be aware of
which schema versions your change affects.
+5 -2
View File
@@ -50,11 +50,14 @@ Contents
| [ifcconvert](https://docs.ifcopenshell.org/ifcconvert.html) | CLI app to convert IFC to many other formats | LGPL-3.0-or-later\* | [![Official](https://img.shields.io/badge/IfcOpenShell.org-Download-70ba35)](https://docs.ifcopenshell.org/ifcconvert/installation.html) [![GitHub](https://img.shields.io/github/v/release/ifcopenshell/ifcopenshell?filter=ifcconvert-*&label=GitHub&color=f6f8fa)](https://github.com/IfcOpenShell/IfcOpenShell/releases?q=ifcconvert&expanded=true) | [ifcconvert](https://docs.ifcopenshell.org/ifcconvert.html) | CLI app to convert IFC to many other formats | LGPL-3.0-or-later\* | [![Official](https://img.shields.io/badge/IfcOpenShell.org-Download-70ba35)](https://docs.ifcopenshell.org/ifcconvert/installation.html) [![GitHub](https://img.shields.io/github/v/release/ifcopenshell/ifcopenshell?filter=ifcconvert-*&label=GitHub&color=f6f8fa)](https://github.com/IfcOpenShell/IfcOpenShell/releases?q=ifcconvert&expanded=true)
| [ifccsv](https://docs.ifcopenshell.org/ifccsv.html) | Library and CLI app to export and import schedules from IFC | LGPL-3.0-or-later | [![PyPI](https://img.shields.io/pypi/v/ifccsv?label=PyPI&color=006dad)](https://pypi.org/project/ifccsv/) | | [ifccsv](https://docs.ifcopenshell.org/ifccsv.html) | Library and CLI app to export and import schedules from IFC | LGPL-3.0-or-later | [![PyPI](https://img.shields.io/pypi/v/ifccsv?label=PyPI&color=006dad)](https://pypi.org/project/ifccsv/) |
| [ifcdiff](https://docs.ifcopenshell.org/ifcdiff.html) | Compare changes between IFC models | LGPL-3.0-or-later | [![PyPI](https://img.shields.io/pypi/v/ifcdiff?label=PyPI&color=006dad)](https://pypi.org/project/ifcdiff/) | | [ifcdiff](https://docs.ifcopenshell.org/ifcdiff.html) | Compare changes between IFC models | LGPL-3.0-or-later | [![PyPI](https://img.shields.io/pypi/v/ifcdiff?label=PyPI&color=006dad)](https://pypi.org/project/ifcdiff/) |
| [ifcedit](https://docs.ifcopenshell.org/ifcedit.html) | CLI wrapper for ifcopenshell.api IFC model mutation functions | LGPL-3.0-or-later | [![PyPI](https://img.shields.io/pypi/v/ifcedit?label=PyPI&color=006dad)](https://pypi.org/project/ifcedit/) |
| [ifcfm](https://docs.ifcopenshell.org/ifcfm.html) | Extract IFC data for FM handover requirements | LGPL-3.0-or-later | [![PyPI](https://img.shields.io/pypi/v/ifcfm?label=PyPI&color=006dad)](https://pypi.org/project/ifcfm/) | | [ifcfm](https://docs.ifcopenshell.org/ifcfm.html) | Extract IFC data for FM handover requirements | LGPL-3.0-or-later | [![PyPI](https://img.shields.io/pypi/v/ifcfm?label=PyPI&color=006dad)](https://pypi.org/project/ifcfm/) |
| [ifcmax](https://docs.ifcopenshell.org/ifcmax.html) | Historic extension for IFC support in 3DS Max | LGPL-3.0-or-later\* | [![Official](https://img.shields.io/badge/IfcOpenShell.org-Download-70ba35)](https://docs.ifcopenshell.org/ifcmax.html) | [ifcmax](https://docs.ifcopenshell.org/ifcmax.html) | Historic extension for IFC support in 3DS Max | LGPL-3.0-or-later\* | [![Official](https://img.shields.io/badge/IfcOpenShell.org-Download-70ba35)](https://docs.ifcopenshell.org/ifcmax.html)
| [ifcopenshell-python](https://docs.ifcopenshell.org/ifcopenshell-python.html) | Python library for IFC manipulation | LGPL-3.0-or-later\* | [![Official](https://img.shields.io/badge/IfcOpenShell.org-Download-70ba35)](https://docs.ifcopenshell.org/ifcopenshell-python/installation.html) [![GitHub](https://img.shields.io/github/v/release/ifcopenshell/ifcopenshell?filter=ifcopenshell-python-*&label=GitHub&color=f6f8fa)](https://github.com/IfcOpenShell/IfcOpenShell/releases?q=ifcopenshell-python&expanded=true) [![PyPI](https://img.shields.io/pypi/v/ifcopenshell?label=PyPI&color=006dad)](https://pypi.org/project/ifcopenshell/) [![Anaconda](https://img.shields.io/conda/vn/conda-forge/ifcopenshell?label=Anaconda&color=43b02a)](https://anaconda.org/conda-forge/ifcopenshell) [![Anaconda](https://img.shields.io/conda/vn/ifcopenshell/ifcopenshell?label=Anaconda-Unstable&color=43b02a)](https://anaconda.org/ifcopenshell/ifcopenshell) [![Docker](https://img.shields.io/docker/pulls/aecgeeks/ifcopenshell?label=Docker&color=1D63ED)](https://hub.docker.com/r/aecgeeks/ifcopenshell) [![AUR](https://img.shields.io/aur/version/ifcopenshell?label=AUR&color=1793d1)](https://aur.archlinux.org/packages/ifcopenshell) [![AUR Unstable](https://img.shields.io/aur/version/ifcopenshell-git?label=AUR-Unstable&color=1793d1)](https://aur.archlinux.org/packages/ifcopenshell-git) [Pyodide WASM Wheels](https://github.com/IfcOpenShell/wasm-wheels#pyodide-test-wheels) | | [ifcmcp](https://docs.ifcopenshell.org/ifcmcp.html) | MCP server for querying and editing IFC building models | LGPL-3.0-or-later | [![PyPI](https://img.shields.io/pypi/v/ifcopenshell-mcp?label=PyPI&color=006dad)](https://pypi.org/project/ifcopenshell-mcp/) |
| [ifcopenshell-python](https://docs.ifcopenshell.org/ifcopenshell-python.html) | Python library for IFC manipulation | LGPL-3.0-or-later\* | [![Official](https://img.shields.io/badge/IfcOpenShell.org-Download-70ba35)](https://docs.ifcopenshell.org/ifcopenshell-python/installation.html) [![GitHub](https://img.shields.io/github/v/release/ifcopenshell/ifcopenshell?filter=ifcopenshell-python-*&label=GitHub&color=f6f8fa)](https://github.com/IfcOpenShell/IfcOpenShell/releases?q=ifcopenshell-python&expanded=true) [![PyPI](https://img.shields.io/pypi/v/ifcopenshell?label=PyPI&color=006dad)](https://pypi.org/project/ifcopenshell/) [![Anaconda](https://img.shields.io/conda/vn/conda-forge/ifcopenshell?label=Anaconda&color=43b02a)](https://anaconda.org/conda-forge/ifcopenshell) [![Anaconda](https://img.shields.io/conda/vn/ifcopenshell/ifcopenshell?label=Anaconda-Unstable&color=43b02a)](https://anaconda.org/ifcopenshell/ifcopenshell) [![Docker](https://img.shields.io/docker/pulls/aecgeeks/ifcopenshell?label=Docker&color=1D63ED)](https://hub.docker.com/r/aecgeeks/ifcopenshell) [![AUR](https://img.shields.io/aur/version/ifcopenshell?label=AUR&color=1793d1)](https://aur.archlinux.org/packages/ifcopenshell) [![AUR Unstable](https://img.shields.io/aur/version/ifcopenshell-git?label=AUR-Unstable&color=1793d1)](https://aur.archlinux.org/packages/ifcopenshell-git) [![Pyodide WASM Wheels tag](https://img.shields.io/github/v/tag/ifcopenshell/wasm-wheels?sort=semver&label=pyodide-wasm-wheels)](https://github.com/IfcOpenShell/wasm-wheels) |
| [ifcpatch](https://docs.ifcopenshell.org/ifcpatch.html) | Utility to run pre-packaged scripts to manipulate IFCs | LGPL-3.0-or-later | [![PyPI](https://img.shields.io/pypi/v/ifcpatch?label=PyPI&color=006dad)](https://pypi.org/project/ifcpatch/) | | [ifcpatch](https://docs.ifcopenshell.org/ifcpatch.html) | Utility to run pre-packaged scripts to manipulate IFCs | LGPL-3.0-or-later | [![PyPI](https://img.shields.io/pypi/v/ifcpatch?label=PyPI&color=006dad)](https://pypi.org/project/ifcpatch/) |
| [ifcsverchok](https://docs.ifcopenshell.org/ifcsverchok.html) | Blender Add-on for visual node programming with IFC | GPL-3.0-or-later | [![GitHub Unstable](https://img.shields.io/github/v/release/ifcopenshell/ifcopenshell?filter=ifcsverchok-*.*.*.*&label=GitHub-Unstable&color=f6f8fa)](https://github.com/IfcOpenShell/IfcOpenShell/releases?q=ifcsverchok&expanded=true) | [ifcquery](https://docs.ifcopenshell.org/ifcquery.html) | CLI tool for querying and inspecting IFC building models | LGPL-3.0-or-later | [![PyPI](https://img.shields.io/pypi/v/ifcquery?label=PyPI&color=006dad)](https://pypi.org/project/ifcquery/) |
| [ifcsverchok](https://docs.ifcopenshell.org/ifcsverchok.html) | Blender Add-on for visual node programming with IFC | GPL-3.0-or-later | [![GitHub](https://img.shields.io/github/v/release/ifcopenshell/ifcopenshell?filter=ifcsverchok-*.*.*&label=GitHub&color=f6f8fa)](https://github.com/IfcOpenShell/IfcOpenShell/releases?q=ifcsverchok&expanded=true)
| [ifctester](https://docs.ifcopenshell.org/ifctester.html) | Library, CLI and webapp for IDS model auditing | LGPL-3.0-or-later | [![PyPI](https://img.shields.io/pypi/v/ifctester?label=PyPI&color=006dad)](https://pypi.org/project/ifctester/) | | [ifctester](https://docs.ifcopenshell.org/ifctester.html) | Library, CLI and webapp for IDS model auditing | LGPL-3.0-or-later | [![PyPI](https://img.shields.io/pypi/v/ifctester?label=PyPI&color=006dad)](https://pypi.org/project/ifctester/) |
The IfcOpenShell C++ codebase is split into multiple interal libraries: The IfcOpenShell C++ codebase is split into multiple interal libraries:
+1 -1
View File
@@ -1 +1 @@
0.8.5 0.8.6
+1 -1
View File
@@ -1,6 +1,6 @@
import boto3
import ifcopenshell import ifcopenshell
import ifcopenshell.util.element import ifcopenshell.util.element
import boto3
s3 = boto3.client('s3') s3 = boto3.client('s3')
+22 -12
View File
@@ -13,13 +13,15 @@ import hashlib
import os import os
import pathlib import pathlib
import re import re
from urllib import request import subprocess
from github import Github
from typing import NoReturn from typing import NoReturn
from urllib import request
from github import Github
def get_repo_tag_names() -> list[str]: def get_repo_tag_names() -> list[str]:
git_return = os.popen("git tag -l").read() git_return = subprocess.check_output("git tag -l", text=True)
tag_names = [tag_name for tag_name in git_return.split("\n") if tag_name] tag_names = [tag_name for tag_name in git_return.split("\n") if tag_name]
print(f"{len(tag_names)} tag_names found in repo") print(f"{len(tag_names)} tag_names found in repo")
return tag_names return tag_names
@@ -77,6 +79,10 @@ def get_release_zip(tag: str) -> tuple[str, str]:
raise Exception(f"Couldn't find the release matching '{python_version}' and '{TARGET_OS}' in tag '{tag}'.") raise Exception(f"Couldn't find the release matching '{python_version}' and '{TARGET_OS}' in tag '{tag}'.")
def run(command: str) -> None:
subprocess.check_output(command)
start = datetime.datetime.now() start = datetime.datetime.now()
URL_CHOCO_PACKAGE = "https://community.chocolatey.org/packages/blender" URL_CHOCO_PACKAGE = "https://community.chocolatey.org/packages/blender"
@@ -96,7 +102,7 @@ should_release = False
target_release_tag = "" target_release_tag = ""
TARGET_OS = "windows-x64" TARGET_OS = "windows-x64"
git_status = os.popen("git status").read() git_status = subprocess.check_output("git status", text=True)
print(git_status) print(git_status)
for tag_name in get_repo_tag_names(): for tag_name in get_repo_tag_names():
@@ -146,7 +152,7 @@ blenderbim_build_version = target_release_tag.replace("blenderbim-", "")
# url_blenderbim_py3x_win_zip # url_blenderbim_py3x_win_zip
release_zip_file_name, url_blenderbim_py3x_win_zip = get_release_zip(target_release_tag) release_zip_file_name, url_blenderbim_py3x_win_zip = get_release_zip(target_release_tag)
os.popen(f"wget {url_blenderbim_py3x_win_zip} --no-verbose").read() subprocess.check_call(f"wget {url_blenderbim_py3x_win_zip} --no-verbose")
# sha256sum_blenderbim_py310_win_zip # sha256sum_blenderbim_py310_win_zip
sha256sum_blenderbim_py3x_win_zip = get_file_sha256_hash(release_zip_file_name) sha256sum_blenderbim_py3x_win_zip = get_file_sha256_hash(release_zip_file_name)
@@ -200,13 +206,13 @@ print("[INFO] inserting dynamic chocolatey package parameters successful")
print("\n_____ build choco.exe with mono") print("\n_____ build choco.exe with mono")
choco_version = "1.1.0" choco_version = "1.1.0"
os.popen(f"wget https://github.com/chocolatey/choco/archive/refs/tags/{choco_version}.tar.gz --quiet").read() run(f"wget https://github.com/chocolatey/choco/archive/refs/tags/{choco_version}.tar.gz --quiet")
os.popen(f"tar -xzf {choco_version}.tar.gz").read() run(f"tar -xzf {choco_version}.tar.gz")
print("choco tar unpack successful") print("choco tar unpack successful")
os.chdir("choco-1.1.0") os.chdir("choco-1.1.0")
os.popen("./build.sh").read() run("./build.sh")
os.popen("cp -r build_output/chocolatey /opt/chocolatey").read() run("cp -r build_output/chocolatey /opt/chocolatey")
os.chdir(BLENDERBIM_DIR) os.chdir(BLENDERBIM_DIR)
if pathlib.Path("/opt/chocolatey/choco.exe").exists(): if pathlib.Path("/opt/chocolatey/choco.exe").exists():
@@ -214,11 +220,15 @@ if pathlib.Path("/opt/chocolatey/choco.exe").exists():
print("\n_____ build choco pack") print("\n_____ build choco pack")
os.popen("mono /opt/chocolatey/choco.exe pack --allow-unofficial").read() run("mono /opt/chocolatey/choco.exe pack --allow-unofficial")
os.popen('mono /opt/chocolatey/choco.exe setapikey --key="{choco_token}" --source="https://push.chocolatey.org/" --allow-unofficial').read() run(
'mono /opt/chocolatey/choco.exe setapikey --key="{choco_token}" --source="https://push.chocolatey.org/" --allow-unofficial'
)
print("\n_____ build choco push") print("\n_____ build choco push")
os.popen('mono /opt/chocolatey/choco.exe push --source="https://push.chocolatey.org/" --key="$CHOCO_TOKEN" --allow-unofficial --verbose').read() run(
'mono /opt/chocolatey/choco.exe push --source="https://push.chocolatey.org/" --key="$CHOCO_TOKEN" --allow-unofficial --verbose'
)
print(f"choco push of version: {target_release_tag} successful!") print(f"choco push of version: {target_release_tag} successful!")
print(f"it took: {datetime.datetime.now() - start}") print(f"it took: {datetime.datetime.now() - start}")
@@ -1,6 +1,5 @@
import bpy import bpy
bpy.ops.preferences.addon_disable(module='blenderbim') bpy.ops.preferences.addon_disable(module='blenderbim')
bpy.ops.wm.save_userpref() bpy.ops.wm.save_userpref()
@@ -1,6 +1,5 @@
import bpy import bpy
bpy.ops.preferences.addon_enable(module='blenderbim') bpy.ops.preferences.addon_enable(module='blenderbim')
bpy.ops.wm.save_userpref() bpy.ops.wm.save_userpref()
+32 -6
View File
@@ -9,10 +9,14 @@
# If input variables are not specified, try to find HDF5 config. # If input variables are not specified, try to find HDF5 config.
# Input variables could also be provided as environment variables. # Input variables could also be provided as environment variables.
# #
# Output variables: # Output targets:
# - `CGAL_INCLUDE_DIR` # - `IFCOPENSHELL_CGAL`
# #
if(TARGET IFCOPENSHELL_CGAL)
return()
endif()
UNIFY_ENVVARS_AND_CACHE(CGAL_INCLUDE_DIR) UNIFY_ENVVARS_AND_CACHE(CGAL_INCLUDE_DIR)
UNIFY_ENVVARS_AND_CACHE(CGAL_LIBRARY_DIR) UNIFY_ENVVARS_AND_CACHE(CGAL_LIBRARY_DIR)
UNIFY_ENVVARS_AND_CACHE(GMP_INCLUDE_DIR) UNIFY_ENVVARS_AND_CACHE(GMP_INCLUDE_DIR)
@@ -20,7 +24,21 @@ UNIFY_ENVVARS_AND_CACHE(GMP_LIBRARY_DIR)
UNIFY_ENVVARS_AND_CACHE(MPFR_INCLUDE_DIR) UNIFY_ENVVARS_AND_CACHE(MPFR_INCLUDE_DIR)
UNIFY_ENVVARS_AND_CACHE(MPFR_LIBRARY_DIR) UNIFY_ENVVARS_AND_CACHE(MPFR_LIBRARY_DIR)
if(NOT CGAL_INCLUDE_DIR) if(CGAL_INCLUDE_DIR)
find_library(libGMP NAMES gmp mpir PATHS ${GMP_LIBRARY_DIR} NO_DEFAULT_PATH)
find_library(libMPFR NAMES mpfr PATHS ${MPFR_LIBRARY_DIR} NO_DEFAULT_PATH)
if(NOT libGMP)
message(FATAL_ERROR "Unable to find GMP library files, aborting")
endif()
if(NOT libMPFR)
message(FATAL_ERROR "Unable to find MPFR library files, aborting")
endif()
add_library(CGAL::CGAL INTERFACE IMPORTED)
target_include_directories(CGAL::CGAL INTERFACE "${CGAL_INCLUDE_DIR}")
target_include_directories(CGAL::CGAL INTERFACE "${GMP_INCLUDE_DIR}" "${MPFR_INCLUDE_DIR}")
target_link_libraries(CGAL::CGAL INTERFACE "${libMPFR}" "${libGMP}")
else()
# CGAL is not respecting default Boost_USE_STATIC_LIBS value # CGAL is not respecting default Boost_USE_STATIC_LIBS value
# and sometiems it's getting in the way. # and sometiems it's getting in the way.
if(NOT DEFINED Boost_USE_STATIC_LIBS) if(NOT DEFINED Boost_USE_STATIC_LIBS)
@@ -28,8 +46,11 @@ if(NOT CGAL_INCLUDE_DIR)
else() else()
set(CGAL_Boost_USE_STATIC_LIBS "${Boost_USE_STATIC_LIBS}") set(CGAL_Boost_USE_STATIC_LIBS "${Boost_USE_STATIC_LIBS}")
endif() endif()
find_package(CGAL CONFIG REQUIRED) # Annoyingly this is producing CMP0167 boost warnings, because it's unsetting cmake policies
if(NOT CGAL_DIR) # and using FindBoost module. But there's nothing we can do about it,
# since everything happens in the scope of CGAL config. I guess it's be resolved in CGAL 6.1.0.
find_package(CGAL CONFIG)
if(NOT CGAL_FOUND)
message( message(
FATAL_ERROR FATAL_ERROR
"CGAL_SUPPORT enabled, but CGAL_INCLUDE_DIR wasn't provided and CGAL package couldn't be found." "CGAL_SUPPORT enabled, but CGAL_INCLUDE_DIR wasn't provided and CGAL package couldn't be found."
@@ -38,5 +59,10 @@ if(NOT CGAL_INCLUDE_DIR)
message(STATUS "CGAL: found config at '${CGAL_DIR}'.") message(STATUS "CGAL: found config at '${CGAL_DIR}'.")
endif() endif()
add_definitions(-DIFOPSH_WITH_CGAL) # Adding another `IFCOPENSHELL_CGAL` target, because we want to add compile definitions to it,
# but in `CGALconfig.cmake` `CGAL::CGAL` is an alias, so you can't add properties to it.
add_library(IFCOPENSHELL_CGAL INTERFACE)
target_link_libraries(IFCOPENSHELL_CGAL INTERFACE CGAL::CGAL)
target_compile_definitions(IFCOPENSHELL_CGAL INTERFACE IFOPSH_WITH_CGAL)
set(SWIG_DEFINES ${SWIG_DEFINES} -DIFOPSH_WITH_CGAL) set(SWIG_DEFINES ${SWIG_DEFINES} -DIFOPSH_WITH_CGAL)
install(TARGETS IFCOPENSHELL_CGAL EXPORT ${IFCOPENSHELL_EXPORT_TARGETS})
+4 -4
View File
@@ -19,13 +19,13 @@ UNIFY_ENVVARS_AND_CACHE(HDF5_LIBRARIES)
# To avoid cyclic calls to this file # To avoid cyclic calls to this file
list(REMOVE_ITEM CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}) list(REMOVE_ITEM CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR})
if("${HDF5_INCLUDE_DIR}" STREQUAL "") if(NOT HDF5_INCLUDE_DIR)
message(STATUS "No HDF5 include directory specified") message(STATUS "No HDF5 include directory specified")
else() else()
set(HDF5_INCLUDE_DIR "${HDF5_INCLUDE_DIR}" CACHE FILEPATH "HDF5 header files") set(HDF5_INCLUDE_DIR "${HDF5_INCLUDE_DIR}" CACHE FILEPATH "HDF5 header files")
endif() endif()
if("${HDF5_LIBRARY_DIR}" STREQUAL "") if(NOT HDF5_LIBRARY_DIR)
message(STATUS "No HDF5 library directory specified") message(STATUS "No HDF5 library directory specified")
else() else()
set(HDF5_LIBRARY_DIR "${HDF5_LIBRARY_DIR}" CACHE FILEPATH "HDF5 library files") set(HDF5_LIBRARY_DIR "${HDF5_LIBRARY_DIR}" CACHE FILEPATH "HDF5 library files")
@@ -35,7 +35,7 @@ if(HDF5_LIBRARY_DIR)
# result of the HDF5 ctest package # result of the HDF5 ctest package
# Find zlib using cmake find_library. How should this be implemented? # Find zlib using cmake find_library. How should this be implemented?
# FIND_LIBRARY(NAMES z libz libz_debug PATHS ... NO_DEFAULT_PATH) # FIND_LIBRARY(NAMES z libz libz_debug PATHS ... NO_DEFAULT_PATH)
if("$ENV{CONDA_BUILD}" STREQUAL "") if(NOT DEFINED ENV{CONDA_BUILD})
# result of the HDF5 ctest package # result of the HDF5 ctest package
if(WIN32) if(WIN32)
set(zlib_post lib) set(zlib_post lib)
@@ -55,7 +55,6 @@ if(HDF5_LIBRARY_DIR)
"${HDF5_LIBRARY_DIR}/libsz${debug_postfix}.${lib_ext}" "${HDF5_LIBRARY_DIR}/libsz${debug_postfix}.${lib_ext}"
"${HDF5_LIBRARY_DIR}/libaec${debug_postfix}.${lib_ext}" "${HDF5_LIBRARY_DIR}/libaec${debug_postfix}.${lib_ext}"
) )
else() else()
message(STATUS "Packaging hdf5 and zlib for conda distribution") message(STATUS "Packaging hdf5 and zlib for conda distribution")
@@ -86,6 +85,7 @@ endif()
if(NOT HDF5_INCLUDE_DIR OR NOT HDF5_LIBRARY_DIR) if(NOT HDF5_INCLUDE_DIR OR NOT HDF5_LIBRARY_DIR)
# First try to find it as a config. # First try to find it as a config.
find_package(HDF5 CONFIG) find_package(HDF5 CONFIG)
mark_as_advanced(HDF5_DIR)
if(HDF5_DIR) if(HDF5_DIR)
message(STATUS "HDF5: found config at '${HDF5_DIR}'.") message(STATUS "HDF5: found config at '${HDF5_DIR}'.")
set(HDF5_LIBRARIES hdf5_cpp-static) set(HDF5_LIBRARIES hdf5_cpp-static)
+15 -17
View File
@@ -5,9 +5,8 @@
# If input variables are not specified, try to find LibXml2 config. # If input variables are not specified, try to find LibXml2 config.
# Input variables could also be provided as environment variables. # Input variables could also be provided as environment variables.
# #
# Output variables: # Output targets:
# - `LIBXML2_INCLUDE_DIR` # - `LibXml2::LibXml2`
# - `LIBXML2_LIBRARIES`
# #
# To avoid cyclic calls to this file # To avoid cyclic calls to this file
@@ -27,22 +26,21 @@ if((NOT LIBXML2_INCLUDE_DIR AND NOT LIBXML2_LIBRARIES))
else() else()
message(STATUS "Found LibXml2 config: ${LibXml2_DIR}") message(STATUS "Found LibXml2 config: ${LibXml2_DIR}")
endif() endif()
if(TARGET LibXml2::LibXml2)
# Config mode already gives us the target
set(LIBXML2_LIBRARIES LibXml2::LibXml2)
get_target_property(LIBXML2_INCLUDE_DIR LibXml2::LibXml2 INTERFACE_INCLUDE_DIRECTORIES)
else()
# Module mode (Ubuntu)
set(LIBXML2_LIBRARIES ${LibXml2_LIBRARIES})
set(LIBXML2_INCLUDE_DIR ${LibXml2_INCLUDE_DIRS})
endif()
else() else()
find_package(LibXml2 REQUIRED) find_package(LibXml2 REQUIRED)
endif() if(MSVC)
# Unset `IMPORTED_LOCATION` and set it manually.
if(MSVC AND NOT LibXml2_DIR) set_property(TARGET LibXml2::LibXml2 PROPERTY IMPORTED_LOCATION)
add_debug_variants(LIBXML2_LIBRARIES "${LIBXML2_LIBRARIES}" d) get_release_variant(LIBXML2_RELEASE_LIB "${LIBXML2_LIBRARIES}" "d")
get_debug_variant(LIBXML2_DEBUG_LIB "${LIBXML2_LIBRARIES}" "d")
set_target_properties(
LibXml2::LibXml2
PROPERTIES
IMPORTED_CONFIGURATIONS "Release;Debug"
IMPORTED_LOCATION_RELEASE "${LIBXML2_RELEASE_LIB}"
IMPORTED_LOCATION_DEBUG "${LIBXML2_DEBUG_LIB}"
)
endif()
endif() endif()
# Restore module path. # Restore module path.
+70 -23
View File
@@ -22,7 +22,6 @@ if(OCC_LIBRARY_DIR)
message(STATUS "Looking for Open CASCADE library files in: ${OCC_LIBRARY_DIR}") message(STATUS "Looking for Open CASCADE library files in: ${OCC_LIBRARY_DIR}")
endif() endif()
if(NOT OCC_INCLUDE_DIR AND NOT OCC_LIBRARY_DIR) if(NOT OCC_INCLUDE_DIR AND NOT OCC_LIBRARY_DIR)
# OCE is not supported for find_package, because it's using a different name (`oce`) # OCE is not supported for find_package, because it's using a different name (`oce`)
# and also has an odd directory structure (install/lib/oce-0.18/*.cmake). # and also has an odd directory structure (install/lib/oce-0.18/*.cmake).
@@ -33,9 +32,33 @@ if(NOT OCC_INCLUDE_DIR AND NOT OCC_LIBRARY_DIR)
# OpenCASCADE may be built with VTK support. Try to find VTK first to avoid # OpenCASCADE may be built with VTK support. Try to find VTK first to avoid
# CMake errors when OpenCASCADE's config references VTK targets. # CMake errors when OpenCASCADE's config references VTK targets.
find_package(VTK QUIET) find_package(VTK QUIET)
mark_as_advanced(VTK_DIR)
find_package(OpenCASCADE CONFIG REQUIRED) find_package(OpenCASCADE CONFIG REQUIRED)
mark_as_advanced(OpenCASCADE_DIR)
message(STATUS "Found OpenCASCADE config: ${OpenCASCADE_DIR}") message(STATUS "Found OpenCASCADE config: ${OpenCASCADE_DIR}")
if(OpenCASCADE_VERSION VERSION_LESS "7.7.0")
# cmake configs < 7.7.0 were not adding include directories to targets automatically.
set_target_properties(TKernel PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${OpenCASCADE_INCLUDE_DIR}")
endif()
if(
OpenCASCADE_VERSION VERSION_LESS "7.9.0"
AND CMAKE_VERSION GREATER_EQUAL "3.24"
AND CMAKE_CXX_COMPILER_ID STREQUAL "GNU"
)
# Before 7.9.0 targets in OCCT cmake configs are not linked to each other
# leading to missing symbols on Unix. Link them as a single group as a workaround.
# Only needed for gcc, because other compilers (e.g. Apple Clang, MSVC) do rescan automatically.
set(OpenCASCADE_LIBRARIES "$<LINK_GROUP:RESCAN,${OpenCASCADE_LIBRARIES}>")
endif()
if(OpenCASCADE_VERSION VERSION_LESS "7.9.0" AND WIN32)
# Bug in OCCT cmake configs < 7.9.0 - missing linked library.
list(APPEND OpenCASCADE_LIBRARIES WSOCK32.lib)
endif()
return() return()
endif() endif()
@@ -47,17 +70,11 @@ if(OCC_INCLUDE_DIR AND OCC_LIBRARY_DIR)
"and OCC_LIBRARY_DIR ('${OCC_LIBRARY_DIR}')." "and OCC_LIBRARY_DIR ('${OCC_LIBRARY_DIR}')."
) )
# Parse OCC_VERSION_STRING. # Parse OCC_VERSION_STRING.
file(STRINGS ${OCC_INCLUDE_DIR}/Standard_Version.hxx OCC_MAJOR file(STRINGS ${OCC_INCLUDE_DIR}/Standard_Version.hxx OCC_MAJOR REGEX "#define OCC_VERSION_MAJOR.*")
REGEX "#define OCC_VERSION_MAJOR.*"
)
string(REGEX MATCH "[0-9]+" OCC_MAJOR ${OCC_MAJOR}) string(REGEX MATCH "[0-9]+" OCC_MAJOR ${OCC_MAJOR})
file(STRINGS ${OCC_INCLUDE_DIR}/Standard_Version.hxx OCC_MINOR file(STRINGS ${OCC_INCLUDE_DIR}/Standard_Version.hxx OCC_MINOR REGEX "#define OCC_VERSION_MINOR.*")
REGEX "#define OCC_VERSION_MINOR.*"
)
string(REGEX MATCH "[0-9]+" OCC_MINOR ${OCC_MINOR}) string(REGEX MATCH "[0-9]+" OCC_MINOR ${OCC_MINOR})
file(STRINGS ${OCC_INCLUDE_DIR}/Standard_Version.hxx OCC_MAINT file(STRINGS ${OCC_INCLUDE_DIR}/Standard_Version.hxx OCC_MAINT REGEX "#define OCC_VERSION_MAINTENANCE.*")
REGEX "#define OCC_VERSION_MAINTENANCE.*"
)
string(REGEX MATCH "[0-9]+" OCC_MAINT ${OCC_MAINT}) string(REGEX MATCH "[0-9]+" OCC_MAINT ${OCC_MAINT})
set(OCC_VERSION_STRING "${OCC_MAJOR}.${OCC_MINOR}.${OCC_MAINT}") set(OCC_VERSION_STRING "${OCC_MAJOR}.${OCC_MINOR}.${OCC_MAINT}")
else() else()
@@ -71,17 +88,37 @@ else()
) )
endif() endif()
set( set(OpenCASCADE_LIBRARIES
OpenCASCADE_LIBRARIES TKernel
TKernel TKMath TKBRep TKGeomBase TKGeomAlgo TKG3d TKG2d TKShHealing TKTopAlgo TKMesh TKPrim TKBool TKBO TKMath
TKFillet TKXSBase TKOffset TKHLR TKBRep
TKGeomBase
TKGeomAlgo
TKG3d
TKG2d
TKShHealing
TKTopAlgo
TKMesh
TKPrim
TKBool
TKBO
TKFillet
TKXSBase
TKOffset
TKHLR
# @todo investigate the exact conditions when this is necessary # @todo investigate the exact conditions when this is necessary
TKBin TKBin
) )
if(OCC_VERSION_STRING VERSION_LESS 7.8.0) if(OCC_VERSION_STRING VERSION_LESS 7.8.0)
list(APPEND OpenCASCADE_LIBRARIES TKIGES TKSTEPBase TKSTEPAttr TKSTEP209 TKSTEP) list(
APPEND OpenCASCADE_LIBRARIES
TKIGES
TKSTEPBase
TKSTEPAttr
TKSTEP209
TKSTEP
)
else(OCC_VERSION_STRING VERSION_LESS 7.8.0) else(OCC_VERSION_STRING VERSION_LESS 7.8.0)
list(APPEND OpenCASCADE_LIBRARIES TKDESTEP TKDEIGES) list(APPEND OpenCASCADE_LIBRARIES TKDESTEP TKDEIGES)
endif(OCC_VERSION_STRING VERSION_LESS 7.8.0) endif(OCC_VERSION_STRING VERSION_LESS 7.8.0)
@@ -91,10 +128,7 @@ find_library(libTKernel NAMES TKernel TKerneld PATHS ${OCC_LIBRARY_DIR} NO_DEFAU
if(libTKernel) if(libTKernel)
message(STATUS "Required Open Cascade Library files found") message(STATUS "Required Open Cascade Library files found")
else() else()
message( message(FATAL_ERROR "Unable to find Open Cascade library files in OCC_LIBRARY_DIR ('${OCC_LIBRARY_DIR}'), aborting")
FATAL_ERROR
"Unable to find Open Cascade library files in OCC_LIBRARY_DIR ('${OCC_LIBRARY_DIR}'), aborting"
)
endif() endif()
if(MSVC) if(MSVC)
@@ -123,9 +157,21 @@ if(OCCT_STATIC)
# OpenCASCADE_LIBRARIES repeated N times below in order to fix cyclic dependencies # OpenCASCADE_LIBRARIES repeated N times below in order to fix cyclic dependencies
# tfk: --start-group ... --end-group didn't work on the apple linker when last tested # tfk: --start-group ... --end-group didn't work on the apple linker when last tested
if(APPLE) if(APPLE)
set(OpenCASCADE_LIBRARIES ${OpenCASCADE_LIBRARIES} ${OpenCASCADE_LIBRARIES} ${OpenCASCADE_LIBRARIES} ${OpenCASCADE_LIBRARIES} ${OpenCASCADE_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT}) set(OpenCASCADE_LIBRARIES
${OpenCASCADE_LIBRARIES}
${OpenCASCADE_LIBRARIES}
${OpenCASCADE_LIBRARIES}
${OpenCASCADE_LIBRARIES}
${OpenCASCADE_LIBRARIES}
${CMAKE_THREAD_LIBS_INIT}
)
else() else()
set(OpenCASCADE_LIBRARIES -Wl,--start-group ${OpenCASCADE_LIBRARIES} -Wl,--end-group ${CMAKE_THREAD_LIBS_INIT}) set(OpenCASCADE_LIBRARIES
-Wl,--start-group
${OpenCASCADE_LIBRARIES}
-Wl,--end-group
${CMAKE_THREAD_LIBS_INIT}
)
endif() endif()
endif() endif()
@@ -137,8 +183,9 @@ if(OCCT_STATIC)
endif() endif()
endif() endif()
add_library(OpenCASCADE_INTERFACE INTERFACE IMPORTED) add_library(OpenCASCADE_INTERFACE INTERFACE)
target_include_directories(OpenCASCADE_INTERFACE INTERFACE "${OCC_INCLUDE_DIR}") target_include_directories(OpenCASCADE_INTERFACE INTERFACE "${OCC_INCLUDE_DIR}")
target_link_libraries(OpenCASCADE_INTERFACE INTERFACE ${OpenCASCADE_LIBRARIES}) target_link_libraries(OpenCASCADE_INTERFACE INTERFACE ${OpenCASCADE_LIBRARIES})
target_link_directories(OpenCASCADE_INTERFACE INTERFACE "${OCC_LIBRARY_DIR}") target_link_directories(OpenCASCADE_INTERFACE INTERFACE "${OCC_LIBRARY_DIR}")
set(OpenCASCADE_LIBRARIES OpenCASCADE_INTERFACE) set(OpenCASCADE_LIBRARIES OpenCASCADE_INTERFACE)
install(TARGETS OpenCASCADE_INTERFACE EXPORT ${IFCOPENSHELL_EXPORT_TARGETS})
+40 -13
View File
@@ -1,4 +1,3 @@
# #
# Input variables: # Input variables:
# - `OPENCOLLADA_INCLUDE_DIR` # - `OPENCOLLADA_INCLUDE_DIR`
@@ -21,6 +20,7 @@ if(NOT OPENCOLLADA_INCLUDE_DIR AND NOT OPENCOLLADA_LIBRARY_DIR)
# If package is found, automatically sets # If package is found, automatically sets
# OPENCOLLADA_INCLUDE_DIRS and OPENCOLLADA_LIBRARIES (list of targets, not paths). # OPENCOLLADA_INCLUDE_DIRS and OPENCOLLADA_LIBRARIES (list of targets, not paths).
find_package(OpenCOLLADA CONFIG) find_package(OpenCOLLADA CONFIG)
mark_as_advanced(OpenCOLLADA_DIR)
if(OpenCOLLADA_DIR) if(OpenCOLLADA_DIR)
message(STATUS "Found OpenCOLLADA: '${OpenCOLLADA_DIR}'.") message(STATUS "Found OpenCOLLADA: '${OpenCOLLADA_DIR}'.")
set(OPENCOLLADA_FOUND TRUE) set(OPENCOLLADA_FOUND TRUE)
@@ -40,23 +40,37 @@ if(NOT OpenCOLLADA_DIR)
if("${OPENCOLLADA_LIBRARY_DIR}" STREQUAL "") if("${OPENCOLLADA_LIBRARY_DIR}" STREQUAL "")
message(STATUS "No OpenCOLLADA library directory specified") message(STATUS "No OpenCOLLADA library directory specified")
find_library(OPENCOLLADA_FRAMEWORK_LIB NAMES OpenCOLLADAFramework find_library(
PATHS /usr/lib64/opencollada /usr/lib/opencollada /usr/lib64 /usr/lib /usr/local/lib64 /usr/local/lib) OPENCOLLADA_FRAMEWORK_LIB
NAMES OpenCOLLADAFramework
PATHS /usr/lib64/opencollada /usr/lib/opencollada /usr/lib64 /usr/lib /usr/local/lib64 /usr/local/lib
)
get_filename_component(OPENCOLLADA_LIBRARY_DIR ${OPENCOLLADA_FRAMEWORK_LIB} PATH) get_filename_component(OPENCOLLADA_LIBRARY_DIR ${OPENCOLLADA_FRAMEWORK_LIB} PATH)
endif() endif()
find_library(OpenCOLLADAFramework NAMES OpenCOLLADAFramework OpenCOLLADAFrameworkd PATHS ${OPENCOLLADA_LIBRARY_DIR} NO_DEFAULT_PATH) find_library(
OpenCOLLADAFramework
NAMES OpenCOLLADAFramework OpenCOLLADAFrameworkd
PATHS ${OPENCOLLADA_LIBRARY_DIR}
NO_DEFAULT_PATH
)
if(OpenCOLLADAFramework) if(OpenCOLLADAFramework)
message(STATUS "OpenCOLLADA library files found") message(STATUS "OpenCOLLADA library files found")
else() else()
message(FATAL_ERROR "COLLADA_SUPPORT enabled, but unable to find OpenCOLLADA libraries. " message(
"Disable COLLADA_SUPPORT or fix OpenCOLLADA paths to proceed.") FATAL_ERROR
"COLLADA_SUPPORT enabled, but unable to find OpenCOLLADA libraries. "
"Disable COLLADA_SUPPORT or fix OpenCOLLADA paths to proceed."
)
endif() endif()
set(OPENCOLLADA_LIBRARY_DIR "${OPENCOLLADA_LIBRARY_DIR}" CACHE FILEPATH "OpenCOLLADA library files") set(OPENCOLLADA_LIBRARY_DIR "${OPENCOLLADA_LIBRARY_DIR}" CACHE FILEPATH "OpenCOLLADA library files")
set(OPENCOLLADA_INCLUDE_DIRS "${OPENCOLLADA_INCLUDE_DIR}/COLLADABaseUtils" "${OPENCOLLADA_INCLUDE_DIR}/COLLADAStreamWriter") set(OPENCOLLADA_INCLUDE_DIRS
"${OPENCOLLADA_INCLUDE_DIR}/COLLADABaseUtils"
"${OPENCOLLADA_INCLUDE_DIR}/COLLADAStreamWriter"
)
find_file(COLLADASWStreamWriter_h "COLLADASWStreamWriter.h" ${OPENCOLLADA_INCLUDE_DIRS}) find_file(COLLADASWStreamWriter_h "COLLADASWStreamWriter.h" ${OPENCOLLADA_INCLUDE_DIRS})
@@ -65,8 +79,15 @@ if(NOT OpenCOLLADA_DIR)
set(OPENCOLLADA_FOUND TRUE) set(OPENCOLLADA_FOUND TRUE)
set(OPENCOLLADA_LIBRARY_NAMES set(OPENCOLLADA_LIBRARY_NAMES
GeneratedSaxParser MathMLSolver OpenCOLLADABaseUtils OpenCOLLADAFramework OpenCOLLADASaxFrameworkLoader GeneratedSaxParser
OpenCOLLADAStreamWriter UTF buffer ftoa MathMLSolver
OpenCOLLADABaseUtils
OpenCOLLADAFramework
OpenCOLLADASaxFrameworkLoader
OpenCOLLADAStreamWriter
UTF
buffer
ftoa
) )
# Use the found OpenCOLLADAFramework as a template for all other OpenCOLLADA libraries # Use the found OpenCOLLADAFramework as a template for all other OpenCOLLADA libraries
@@ -99,16 +120,22 @@ if(NOT OpenCOLLADA_DIR)
list(APPEND OPENCOLLADA_LIBRARIES "${pcre_library}") list(APPEND OPENCOLLADA_LIBRARIES "${pcre_library}")
endif() endif()
else() else()
message(FATAL_ERROR "COLLADA_SUPPORT enabled, but unable to find PCRE. " message(
"Disable COLLADA_SUPPORT or fix PCRE_LIBRARY_DIR path to proceed.") FATAL_ERROR
"COLLADA_SUPPORT enabled, but unable to find PCRE. "
"Disable COLLADA_SUPPORT or fix PCRE_LIBRARY_DIR path to proceed."
)
endif() endif()
if(MSVC) if(MSVC)
add_debug_variants(OPENCOLLADA_LIBRARIES "${OPENCOLLADA_LIBRARIES}" d) add_debug_variants(OPENCOLLADA_LIBRARIES "${OPENCOLLADA_LIBRARIES}" d)
endif() endif()
else() else()
message(FATAL_ERROR "COLLADA_SUPPORT enabled, but unable to find OpenCOLLADA headers. " message(
"Disable COLLADA_SUPPORT or fix OpenCOLLADA paths to proceed.") FATAL_ERROR
"COLLADA_SUPPORT enabled, but unable to find OpenCOLLADA headers. "
"Disable COLLADA_SUPPORT or fix OpenCOLLADA paths to proceed."
)
endif() endif()
endif(NOT OpenCOLLADA_DIR) endif(NOT OpenCOLLADA_DIR)
+56
View File
@@ -0,0 +1,56 @@
#
# Input variables:
# - `PROJ_INCLUDE_DIR`
# - `PROJ_LIBRARIES`
# If input variables are not specified, try to find PROJ config.
# Input variables could also be provided as environment variables.
#
# Output targets:
# - `PROJ::proj`
#
# To avoid cyclic calls to this file
list(REMOVE_ITEM CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR})
UNIFY_ENVVARS_AND_CACHE(PROJ_INCLUDE_DIR)
UNIFY_ENVVARS_AND_CACHE(PROJ_LIBRARIES)
if((NOT PROJ_INCLUDE_DIR AND NOT PROJ_LIBRARIES))
find_package(PROJ QUIET CONFIG)
if(NOT PROJ_FOUND)
find_path(PROJ_INCLUDE_DIR proj.h PATHS /usr/include/proj REQUIRED)
if(PROJ_INCLUDE_DIR)
message(STATUS "Found PROJ include files in: ${PROJ_INCLUDE_DIR}")
else()
message(FATAL_ERROR "Unable to find PROJ include directory, specify PROJ_INCLUDE_DIR manually.")
endif()
find_library(PROJ_LIBRARY NAMES proj PATHS /usr/lib/x86_64-linux-gnu)
if(PROJ_LIBRARY)
message(STATUS "PROJ libraries ${PROJ_LIBRARY} found in: ${PROJ_LIBRARY_DIR}")
set(PROJ_LIBRARIES ${PROJ_LIBRARY})
else()
message(FATAL_ERROR "Unable to find PROJ libraries in: ${PROJ_LIBRARY_DIR}")
endif()
add_library(PROJ::proj INTERFACE IMPORTED)
target_include_directories(PROJ::proj INTERFACE "${PROJ_INCLUDE_DIR}")
target_link_libraries(PROJ::proj INTERFACE ${PROJ_LIBRARIES})
target_link_directories(PROJ::proj INTERFACE "${PROJ_LIBRARY}")
endif()
else()
find_library(PROJ_LIBRARY NAMES proj PATHS ${PROJ_LIBRARY_DIR})
if(PROJ_LIBRARY)
message(STATUS "PROJ libraries ${PROJ_LIBRARY} found in: ${PROJ_LIBRARY_DIR}")
set(PROJ_LIBRARIES ${PROJ_LIBRARY})
else()
message(FATAL_ERROR "Unable to find PROJ libraries in: ${PROJ_LIBRARY_DIR}")
endif()
set(PROJ_INCLUDE_DIR ${PROJ_INCLUDE_DIR} CACHE FILEPATH "PROJ header files")
message(STATUS "Looking for PROJ include files in: ${PROJ_INCLUDE_DIR}")
include_directories(${PROJ_INCLUDE_DIR})
endif()
list(PREPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR})
+56 -24
View File
@@ -2,23 +2,33 @@
# Input variables: # Input variables:
# - `USD_INCLUDE_DIR` # - `USD_INCLUDE_DIR`
# - `USD_LIBRARY_DIR` # - `USD_LIBRARY_DIR`
# - `TBB_INCLUDE_DIR`
# - `TBB_LIBRARY_DIR`
# Input variables could also be provided as environment variables. # Input variables could also be provided as environment variables.
# TODO: Try to find USD config if varibales are not provided. # If `USD_INCLUDE_DIR` and `USD_LIBRARY_DIR` are not provided,
# TODO: does usd have a config file? # try to find USD by locating its config file.
# #
# Output variables: # Output targets:
# - `USD_LIBRARIES` # - `pxr::USD`
UNIFY_ENVVARS_AND_CACHE(USD_INCLUDE_DIR) UNIFY_ENVVARS_AND_CACHE(USD_INCLUDE_DIR)
UNIFY_ENVVARS_AND_CACHE(USD_LIBRARY_DIR) UNIFY_ENVVARS_AND_CACHE(USD_LIBRARY_DIR)
UNIFY_ENVVARS_AND_CACHE(TBB_INCLUDE_DIR)
UNIFY_ENVVARS_AND_CACHE(TBB_LIBRARY_DIR)
if("${USD_INCLUDE_DIR}" STREQUAL "") if(NOT USD_LIBRARY_DIR AND NOT USD_INCLUDE_DIR)
find_path(USD_INCLUDE_DIR pxr.h find_package(pxr CONFIG)
PATHS if(pxr_FOUND)
/usr/include/pxr add_library(pxr::USD INTERFACE IMPORTED)
/usr/local/include/pxr target_link_libraries(pxr::USD INTERFACE ${PXR_LIBRARIES})
REQUIRED include(FindPackageHandleStandardArgs)
) find_package_handle_standard_args(USD REQUIRED_VARS pxr_DIR)
return()
endif()
endif()
if(NOT USD_INCLUDE_DIR)
find_path(USD_INCLUDE_DIR pxr.h PATHS /usr/include/pxr /usr/local/include/pxr REQUIRED)
if(USD_INCLUDE_DIR) if(USD_INCLUDE_DIR)
message(STATUS "Found USD include files in: ${USD_INCLUDE_DIR}") message(STATUS "Found USD include files in: ${USD_INCLUDE_DIR}")
else() else()
@@ -30,19 +40,28 @@ else()
endif() endif()
set(USD_LIBRARIES set(USD_LIBRARIES
usd_usd usd_usd
usd_usdGeom usd_usdGeom
usd_usdShade usd_usdShade
usd_usdLux usd_usdLux
usd_vt usd_vt
usd_sdf usd_sdf
usd_tf usd_tf
usd_gf usd_gf
) usd_kind
usd_pcp
usd_arch
usd_ar
usd_plug
usd_js
usd_sdr
usd_work
usd_trace
usd_ndr
usd_ts
)
find_library(USD_LIBRARY find_library(USD_LIBRARY NAMES ${USD_LIBRARIES} PATHS ${USD_LIBRARY_DIR})
NAMES ${USD_LIBRARIES}
PATHS ${USD_LIBRARY_DIR})
if(USD_LIBRARY) if(USD_LIBRARY)
message(STATUS "USD libraries ${USD_LIBRARIES} found in: ${USD_LIBRARY_DIR}") message(STATUS "USD libraries ${USD_LIBRARIES} found in: ${USD_LIBRARY_DIR}")
link_directories(${USD_LIBRARY_DIR}) link_directories(${USD_LIBRARY_DIR})
@@ -50,5 +69,18 @@ else()
message(FATAL_ERROR "Unable to find USD libraries in: ${USD_LIBRARY_DIR}") message(FATAL_ERROR "Unable to find USD libraries in: ${USD_LIBRARY_DIR}")
endif() endif()
add_definitions(-DWITH_USD) add_library(pxr::USD INTERFACE IMPORTED)
target_link_directories(pxr::USD INTERFACE ${USD_LIBRARY_DIR} ${TBB_LIBRARY_DIR})
target_include_directories(pxr::USD INTERFACE ${USD_INCLUDE_DIR} ${TBB_INCLUDE_DIR})
# We don't link TBB libraries - on Windows they're provided using `pragma(lib)`.
# On Unix there's no `pragma(lib)`, so in theory it will break.
target_link_libraries(pxr::USD INTERFACE ${USD_LIBRARIES})
if(MSVC)
target_link_libraries(pxr::USD INTERFACE debug DbgHelp.lib)
endif()
target_compile_definitions(pxr::USD INTERFACE PXR_STATIC WITH_USD)
set(SWIG_DEFINES ${SWIG_DEFINES} -DWITH_USD) set(SWIG_DEFINES ${SWIG_DEFINES} -DWITH_USD)
+30
View File
@@ -0,0 +1,30 @@
#
# Input variables:
# - `JSON_INCLUDE_DIR`
# If input variables are not specified, try to find nlohmann_json config.
# Input variables could also be provided as environment variables.
#
# Output targets:
# - `nlohmann_json::nlohmann_json`
UNIFY_ENVVARS_AND_CACHE(JSON_INCLUDE_DIR)
if(NOT JSON_INCLUDE_DIR)
find_package(nlohmann_json CONFIG)
mark_as_advanced(nlohmann_json)
if(nlohmann_json_DIR)
return()
endif()
endif()
find_path(json_header_path "nlohmann/json.hpp" HINTS "${JSON_INCLUDE_DIR}")
mark_as_advanced(json_header_path)
if(json_header_path)
message(STATUS "JSON for Modern C++ header file found in '${json_header_path}'.")
add_library(nlohmann_json::nlohmann_json INTERFACE IMPORTED)
target_include_directories(nlohmann_json::nlohmann_json INTERFACE ${json_header_path})
return()
endif()
message(FATAL_ERROR "Unable to find JSON for Modern C++ header file / package, aborting")
+63
View File
@@ -0,0 +1,63 @@
@PACKAGE_INIT@
# Variable to inspect installed schema versions.
set(IFCOPENSHELL_SCHEMA_VERSIONS @SCHEMA_VERSIONS@)
set(IFCOPENSHELL_WITH_OPENCASCADE @WITH_OPENCASCADE@)
set(IFCOPENSHELL_WITH_CGAL @WITH_CGAL@)
set(IFCOPENSHELL_IFCXML @IFCXML_SUPPORT@)
set(IFCOPENSHELL_WITH_ROCKSDB @WITH_ROCKSDB@)
include(CMakeFindDependencyMacro)
set(Boost_USE_STATIC_LIBS ON)
set(Boost_USE_STATIC_RUNTIME OFF)
set(Boost_USE_MULTITHREADED ON)
set(Boost_COMPONENTS
system
program_options
regex
thread
date_time
iostreams
)
find_dependency(Boost CONFIG COMPONENTS ${Boost_COMPONENTS})
find_dependency(Eigen3 CONFIG)
if(IFCOPENSHELL_WITH_ROCKSDB)
find_dependency(zstd CONFIG)
# Temporaily mess with CMAKE_FIND_PACKAGE_PREFER_CONFIG to help RocksDB
# find it's zstd dependency on Windows.
# Only do it on Windows, otherwise it might create problems as
# findzstd and zstd-config target names do not match.
# https://github.com/facebook/rocksdb/pull/13975
if(WIN32)
set(TEMP CMAKE_FIND_PACKAGE_PREFER_CONFIG)
set(CMAKE_FIND_PACKAGE_PREFER_CONFIG TRUE)
endif()
find_dependency(RocksDB CONFIG)
if(WIN32)
set(CMAKE_FIND_PACKAGE_PREFER_CONFIG ${TEMP})
endif()
endif()
if(IFCOPENSHELL_IFCXML)
find_dependency(LibXml2 CONFIG)
endif()
if(IFCOPENSHELL_WITH_CGAL)
find_dependency(CGAL CONFIG)
endif()
if(IFCOPENSHELL_WITH_OPENCASCADE)
find_dependency(OpenCASCADE CONFIG)
if(OpenCASCADE_VERSION VERSION_LESS "7.7.0")
# cmake configs < 7.7.0 were not adding include directories to targets automatically.
set_target_properties(TKernel PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${OpenCASCADE_INCLUDE_DIR}")
endif()
endif()
include("${CMAKE_CURRENT_LIST_DIR}/@CONFIG_TARGETS_FILENAME@")
check_required_components("@PROJECT_NAME@")
+6 -13
View File
@@ -25,19 +25,12 @@ file(READ "@CMAKE_BINARY_DIR@/install_manifest.txt" files)
string(REGEX REPLACE "\n" ";" files "${files}") string(REGEX REPLACE "\n" ";" files "${files}")
foreach(file ${files}) foreach(file ${files})
message(STATUS "Uninstalling $ENV{DESTDIR}${file}") set(filepath "$ENV{DESTDIR}${file}")
message(STATUS "Uninstalling ${filepath}")
if(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}") if(IS_SYMLINK "${filepath}" OR EXISTS "${filepath}")
exec_program( file(REMOVE "${filepath}")
"@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\"" else(NOT EXISTS "${filepath}")
OUTPUT_VARIABLE rm_out message(STATUS "File ${filepath} does not exist.")
RETURN_VALUE rm_retval
)
if(NOT "${rm_retval}" STREQUAL 0)
message(FATAL_ERROR "Problem when removing $ENV{DESTDIR}${file}")
endif()
else(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}")
message(STATUS "File $ENV{DESTDIR}${file} does not exist.")
endif() endif()
endforeach() endforeach()
+22
View File
@@ -0,0 +1,22 @@
set(CONFIG_PACKAGE_LOCATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}")
set(CONFIG_NAMESPACE "${PROJECT_NAME}")
set(CONFIG_TARGETS_FILENAME ${PROJECT_NAME}Targets.cmake)
set(CONFIG_VERSION_OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake")
set(CONFIG_PACKAGE_INPUT "${PROJECT_SOURCE_DIR}/${PROJECT_NAME}Config.cmake.in")
set(CONFIG_PACKAGE_OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake")
# Allow linking against build directory.
export(EXPORT ${IFCOPENSHELL_EXPORT_TARGETS} FILE ${CONFIG_TARGETS_FILENAME} NAMESPACE ${CONFIG_NAMESPACE}::)
install(EXPORT ${IFCOPENSHELL_EXPORT_TARGETS} NAMESPACE ${CONFIG_NAMESPACE}:: DESTINATION "${CONFIG_PACKAGE_LOCATION}")
include(CMakePackageConfigHelpers)
write_basic_package_version_file(${CONFIG_VERSION_OUTPUT} COMPATIBILITY ExactVersion)
configure_package_config_file(
${CONFIG_PACKAGE_INPUT}
${CONFIG_PACKAGE_OUTPUT}
INSTALL_DESTINATION ${CONFIG_PACKAGE_LOCATION}
)
install(FILES "${CONFIG_PACKAGE_OUTPUT}" "${CONFIG_VERSION_OUTPUT}" DESTINATION ${CONFIG_PACKAGE_LOCATION})
+26 -1
View File
@@ -19,8 +19,9 @@
# Create a cache entry if absent for environment variables # Create a cache entry if absent for environment variables
macro(UNIFY_ENVVARS_AND_CACHE VAR) macro(UNIFY_ENVVARS_AND_CACHE VAR)
if((NOT DEFINED ${VAR}) AND(NOT "$ENV{${VAR}}" STREQUAL "")) if(NOT DEFINED ${VAR} AND DEFINED ENV{${VAR}} AND NOT ENV{${VAR}} STREQUAL "")
set(${VAR} "$ENV{${VAR}}" CACHE STRING "${VAR}" FORCE) set(${VAR} "$ENV{${VAR}}" CACHE STRING "${VAR}" FORCE)
mark_as_advanced(${VAR})
endif() endif()
endmacro() endmacro()
@@ -113,6 +114,30 @@ function(add_debug_variants NAME LIBRARIES POSTFIX)
set(${NAME} ${LIBRARIES} PARENT_SCOPE) set(${NAME} ${LIBRARIES} PARENT_SCOPE)
endfunction() endfunction()
# E.g.
# - `get_release_variant(MYLIB "mylibd.lib" "d")` -> `MYLIB = "mylib.lib"`
# - `get_release_variant(MYLIB "mylib.lib" "d")` -> `MYLIB = "mylib.lib"`
function(get_release_variant NAME LIBRARY POSTFIX)
set(RELEASE_SUFFIX ".lib")
set(DEBUG_SUFFIX "${POSTFIX}${RELEASE_SUFFIX}")
if("${LIBRARY}" MATCHES "${DEBUG_SUFFIX}$")
string(REPLACE "${DEBUG_SUFFIX}" "${RELEASE_SUFFIX}" LIBRARY ${LIBRARY})
endif()
set(${NAME} "${LIBRARY}" PARENT_SCOPE)
endfunction()
# E.g.
# - `get_debug_variant(MYLIB "mylib.lib" "d")` -> `MYLIB = "mylibd.lib"`
# - `get_debug_variant(MYLIB "mylibd.lib" "d")` -> `MYLIB = "mylibd.lib"`
function(get_debug_variant NAME LIBRARY POSTFIX)
set(RELEASE_SUFFIX ".lib")
set(DEBUG_SUFFIX "${POSTFIX}${RELEASE_SUFFIX}")
if(NOT "${LIBRARY}" MATCHES "${DEBUG_SUFFIX}$" AND "${LIBRARY}" MATCHES "${RELEASE_SUFFIX}$")
string(REPLACE "${RELEASE_SUFFIX}" "${DEBUG_SUFFIX}" LIBRARY ${LIBRARY})
endif()
set(${NAME} "${LIBRARY}" PARENT_SCOPE)
endfunction()
function(files_for_ifc_version IFC_VERSION RESULT_NAME) function(files_for_ifc_version IFC_VERSION RESULT_NAME)
set(IFC_PARSE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../src/ifcparse) set(IFC_PARSE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../src/ifcparse)
set(${RESULT_NAME} set(${RESULT_NAME}
+2 -3
View File
@@ -9,7 +9,6 @@ set LIBXML2="%LIBRARY_PREFIX%/lib/libxml2.lib"
cmake -G "Ninja" ^ cmake -G "Ninja" ^
-D SCHEMA_VERSIONS="2x3;4;4x1;4x3_add2" ^ -D SCHEMA_VERSIONS="2x3;4;4x1;4x3_add2" ^
-D CMAKE_BUILD_TYPE:STRING=Release ^ -D CMAKE_BUILD_TYPE:STRING=Release ^
-D CMAKE_CXX_STANDARD=17 ^
-D CMAKE_INSTALL_PREFIX:FILEPATH="%LIBRARY_PREFIX%" ^ -D CMAKE_INSTALL_PREFIX:FILEPATH="%LIBRARY_PREFIX%" ^
-D CMAKE_PREFIX_PATH:FILEPATH="%LIBRARY_PREFIX%" ^ -D CMAKE_PREFIX_PATH:FILEPATH="%LIBRARY_PREFIX%" ^
-D CMAKE_SYSTEM_PREFIX_PATH:FILEPATH="%LIBRARY_PREFIX%" ^ -D CMAKE_SYSTEM_PREFIX_PATH:FILEPATH="%LIBRARY_PREFIX%" ^
@@ -43,7 +42,7 @@ cmake -G "Ninja" ^
-D Boost_INCLUDE_DIR:FILEPATH="%LIBRARY_PREFIX%\include" ^ -D Boost_INCLUDE_DIR:FILEPATH="%LIBRARY_PREFIX%\include" ^
-D Boost_USE_STATIC_LIBS:BOOL=OFF ^ -D Boost_USE_STATIC_LIBS:BOOL=OFF ^
../cmake ../cmake
if errorlevel 1 exit 1 if errorlevel 1 exit 1
ninja install -j 1 ninja install -j 1
@@ -52,4 +51,4 @@ if errorlevel 1 exit 1
python %RECIPE_DIR%/update_version_init.py %PKG_VERSION% %SP_DIR%/ifcopenshell/__init__.py python %RECIPE_DIR%/update_version_init.py %PKG_VERSION% %SP_DIR%/ifcopenshell/__init__.py
if errorlevel 1 exit 1 if errorlevel 1 exit 1
-1
View File
@@ -16,7 +16,6 @@ cmake ${CMAKE_ARGS} -G Ninja \
-DSCHEMA_VERSIONS="2x3;4;4x1;4x3_add2" \ -DSCHEMA_VERSIONS="2x3;4;4x1;4x3_add2" \
-DCMAKE_BUILD_TYPE=Release \ -DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX=$PREFIX \ -DCMAKE_INSTALL_PREFIX=$PREFIX \
-DCMAKE_CXX_STANDARD=17 \
${CMAKE_PLATFORM_FLAGS[@]} \ ${CMAKE_PLATFORM_FLAGS[@]} \
-DCMAKE_PREFIX_PATH=$PREFIX \ -DCMAKE_PREFIX_PATH=$PREFIX \
-DCMAKE_SYSTEM_PREFIX_PATH=$PREFIX \ -DCMAKE_SYSTEM_PREFIX_PATH=$PREFIX \
+2 -1
View File
@@ -1,7 +1,8 @@
import re
import argparse import argparse
import re
from pathlib import Path from pathlib import Path
def update_version(file_path: str, version: str) -> None: def update_version(file_path: str, version: str) -> None:
"""Update the version string in the given __init__.py file.""" """Update the version string in the given __init__.py file."""
file_path = Path(file_path) file_path = Path(file_path)
+1
View File
@@ -1,4 +1,5 @@
import textwrap import textwrap
# The `extensions` list should already be in here from `sphinx-quickstart` # The `extensions` list should already be in here from `sphinx-quickstart`
extensions = [ extensions = [
# there may be others here already, e.g. 'sphinx.ext.mathjax' # there may be others here already, e.g. 'sphinx.ext.mathjax'
+19 -24
View File
@@ -1,14 +1,10 @@
#Look for an executable called sphinx-build #Look for an executable called sphinx-build
find_program(SPHINX_EXECUTABLE find_program(SPHINX_EXECUTABLE NAMES sphinx-build DOC "Path to sphinx-build executable")
NAMES sphinx-build
DOC "Path to sphinx-build executable")
include(FindPackageHandleStandardArgs) include(FindPackageHandleStandardArgs)
#Handle standard arguments to find_package like REQUIRED and QUIET #Handle standard arguments to find_package like REQUIRED and QUIET
find_package_handle_standard_args(Sphinx find_package_handle_standard_args(Sphinx "Failed to find sphinx-build executable" SPHINX_EXECUTABLE)
"Failed to find sphinx-build executable"
SPHINX_EXECUTABLE)
find_package(Doxygen REQUIRED) find_package(Doxygen REQUIRED)
#find_package(Sphinx REQUIRED) #find_package(Sphinx REQUIRED)
@@ -16,25 +12,24 @@ find_package(Doxygen REQUIRED)
set(SPHINX_SOURCE ${CMAKE_CURRENT_SOURCE_DIR}) set(SPHINX_SOURCE ${CMAKE_CURRENT_SOURCE_DIR})
set(SPHINX_BUILD ${CMAKE_CURRENT_BINARY_DIR}/docs/sphinx) set(SPHINX_BUILD ${CMAKE_CURRENT_BINARY_DIR}/docs/sphinx)
MESSAGE(STATUS "SPHINX BUILD ${CMAKE_CURRENT_BINARY_DIR}") message(STATUS "SPHINX BUILD ${CMAKE_CURRENT_BINARY_DIR}")
file(MAKE_DIRECTORY ./output/doxygen) file(MAKE_DIRECTORY ./output/doxygen)
if (DOXYGEN_FOUND) if(DOXYGEN_FOUND)
add_custom_target(
Sphinx
ALL
COMMAND ${SPHINX_EXECUTABLE} -v -T -b html ${SPHINX_SOURCE} ${CMAKE_CURRENT_SOURCE_DIR}/output
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/output
COMMENT "Generating documentation with Sphinx"
)
add_custom_target(Sphinx ALL # add_custom_target(ifcopenshell_python_docs ALL
COMMAND # COMMAND make html
${SPHINX_EXECUTABLE} -v -T -b html # WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/../src/ifcblenderexport/docs
${SPHINX_SOURCE} ${CMAKE_CURRENT_SOURCE_DIR}/output # OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/../src/ifcblenderexport/docs
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/output # COMMENT "Generating documentation with Sphinx")
COMMENT "Generating documentation with Sphinx") else(DOXYGEN_FOUND)
message("Doxygen need to be installed to generate the doxygen documentation")
# add_custom_target(ifcopenshell_python_docs ALL endif(DOXYGEN_FOUND)
# COMMAND make html
# WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/../src/ifcblenderexport/docs
# OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/../src/ifcblenderexport/docs
# COMMENT "Generating documentation with Sphinx")
else (DOXYGEN_FOUND)
message("Doxygen need to be installed to generate the doxygen documentation")
endif (DOXYGEN_FOUND)
+2 -2
View File
@@ -1,10 +1,10 @@
# This program requires doxygen, sphinx, breathe and exhale. # This program requires doxygen, sphinx, breathe and exhale.
import multiprocessing
import os import os
import sys
import shutil import shutil
import subprocess import subprocess
import multiprocessing import sys
# some extra check to see if we can find sphinx in pypy bin dir # some extra check to see if we can find sphinx in pypy bin dir
sphinx_build = os.path.join(os.path.dirname(sys.executable), 'sphinx-build') sphinx_build = os.path.join(os.path.dirname(sys.executable), 'sphinx-build')
+87 -110
View File
@@ -56,8 +56,6 @@ Used environment variables:
`SIDE_MODULE_CFLAGS`, `SIDE_MODULE_LDFLAGS`. `SIDE_MODULE_CFLAGS`, `SIDE_MODULE_LDFLAGS`.
Allows to build wasm without pyodide build environment, which can be useful for debugging build issues. Allows to build wasm without pyodide build environment, which can be useful for debugging build issues.
Example value: 'pyodide/cpython/installs/python-3.13.2' Example value: 'pyodide/cpython/installs/python-3.13.2'
- ``WASM_TOOLCHAIN_FILE`` - path to emscripten toolchain file from pyodide ('Emscripten.cmake')
needed only if ``WASM_PYTHON_PATH`` is provided.
- ``ADD_COMMIT_SHA`` - if defined with any non-empty value then - ``ADD_COMMIT_SHA`` - if defined with any non-empty value then
`ADD_COMMIT_SHA` and `VERSION_OVERRIDE` will be set to `ON` while configuring IfcOpenShell `ADD_COMMIT_SHA` and `VERSION_OVERRIDE` will be set to `ON` while configuring IfcOpenShell
@@ -77,59 +75,63 @@ Used environment variables:
# # # #
# for python37 to install correctly additionally: # # for python37 to install correctly additionally: #
# * libffi(-dev[el]) # # * libffi(-dev[el]) #
# for Python build we also needs ssl # # for Python build we also needs ssl and zlib #
# (since we do `pip install numpy` at the end) # # (since we do `pip install numpy` at the end) #
# * libssl-dev # # * libssl-dev #
# # # #
# on debian 7.8 these can be obtained with: # # on debian 7.8 these can be obtained with: #
# $ apt-get install git gcc g++ autoconf bison bzip2 cmake # # $ apt-get install git gcc g++ autoconf bison bzip2 cmake #
# mesa-common-dev libffi-dev libfontconfig1-dev # # mesa-common-dev libffi-dev libfontconfig1-dev #
# libssl-dev xz # # libssl-dev xz zlib1g-dev #
# # # #
# on ubuntu 14.04: # # on ubuntu 14.04: #
# $ apt-get install git gcc g++ autoconf bison make cmake # # $ apt-get install git gcc g++ autoconf bison make cmake #
# mesa-common-dev libffi-dev libfontconfig1-dev # # mesa-common-dev libffi-dev libfontconfig1-dev #
# libssl-dev xz-utils # # libssl-dev xz-utils zlib1g-dev #
# # # #
# on OS X El Capitan with homebrew: # # on OS X El Capitan with homebrew: #
# $ brew install git bison autoconf automake libffi cmake # # $ brew install git bison autoconf automake libffi cmake #
# $ # `bison` shipped with Mac is too old for swig build, #
# $ # so we use `brew`. #
# $ export PATH=$(brew --prefix bison)/bin:$PATH #
# # # #
# on RHEL-related distros: # # on RHEL-related distros: #
# $ yum install git gcc gcc-c++ autoconf bison make cmake # # $ dnf install git gcc gcc-c++ autoconf bison make cmake #
# mesa-libGL-devel libffi-devel fontconfig-devel bzip2 # # mesa-libGL-devel libffi-devel fontconfig-devel bzip2 #
# automake patch byacc xz # # automake patch byacc xz zlib-devel openssl-devel #
""" """
import logging
import os
import re
import sys
import glob import glob
import subprocess as sp import logging
import shutil
import tarfile
import multiprocessing import multiprocessing
import os
import platform import platform
import threading import re
import sysconfig import shutil
from datetime import datetime
# @todo temporary for expired mpfr.org certificate on 2023-04-08 # @todo temporary for expired mpfr.org certificate on 2023-04-08
import ssl import ssl
import subprocess as sp
import sys
import sysconfig
import tarfile
import threading
from datetime import datetime
ssl._create_default_https_context = ssl._create_unverified_context ssl._create_default_https_context = ssl._create_unverified_context
import time import time
from urllib.request import urlretrieve
from collections.abc import Generator, Sequence from collections.abc import Generator, Sequence
from pathlib import Path from pathlib import Path
from urllib.request import urlretrieve
try: try:
from typing import Union, Literal from typing import Literal, Union
except: except:
# python 3.6 compatibility for rocky 8 # python 3.6 compatibility for rocky 8
from typing import Union from typing import Union
from typing_extensions import Literal from typing_extensions import Literal
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@@ -141,16 +143,15 @@ PROJECT_NAME = "IfcOpenShell"
USE_CURRENT_PYTHON_VERSION = os.getenv("USE_CURRENT_PYTHON_VERSION") USE_CURRENT_PYTHON_VERSION = os.getenv("USE_CURRENT_PYTHON_VERSION")
ADD_COMMIT_SHA = os.getenv("ADD_COMMIT_SHA") ADD_COMMIT_SHA = os.getenv("ADD_COMMIT_SHA")
PYTHON_VERSIONS = ["3.9.11", "3.10.3", "3.11.8", "3.12.1", "3.13.6", "3.14.0"] PYTHON_VERSIONS = ["3.10.3", "3.11.8", "3.12.1", "3.13.6", "3.14.0"]
JSON_VERSION = "3.11.3" JSON_VERSION = "3.11.3"
OCE_VERSION = "0.18.3" OCE_VERSION = "0.18.3"
OCCT_VERSION = "7.8.1" OCCT_VERSION = "7.8.1"
BOOST_VERSION = "1.86.0" BOOST_VERSION = "1.86.0"
EIGEN_VERSION = "3.4.0" EIGEN_VERSION = "3.4.0"
PCRE_VERSION = "8.41" PCRE_VERSION = "8.41"
PCRE2_VERSION = "10.32"
LIBXML2_VERSION = "2.13.8" LIBXML2_VERSION = "2.13.8"
SWIG_VERSION = "4.1.0" SWIG_VERSION = "4.2.1"
OPENCOLLADA_VERSION = "v1.6.68" OPENCOLLADA_VERSION = "v1.6.68"
HDF5_VERSION = "1.13.1" HDF5_VERSION = "1.13.1"
@@ -247,15 +248,8 @@ if WASM:
# https://github.com/pyodide/pyodide-build/pull/249 # https://github.com/pyodide/pyodide-build/pull/249
WASM_CMAKE_IS_USING_INIT_VARS = get_pyodide_build_version() >= (99, 0, 0) WASM_CMAKE_IS_USING_INIT_VARS = get_pyodide_build_version() >= (99, 0, 0)
# pyodide provide empty `CXXFLAGS`, leading to issues using C++ files compiled with `-fexceptions` # 0.31 is required for SIDE_MODULE_CXXFLAGS to be provided.
# which is used by OCCT. assert get_pyodide_build_version() >= (0, 31)
# https://github.com/pyodide/pyodide-build/issues/251
side_module_cxx_flags = os.environ.get("SIDE_MODULE_CXXFLAGS", "")
if side_module_cxx_flags.strip():
print("SIDE_MODULE_CXXFLAGS are already passed from pyodide build ('{side_module_cxx_flags}').")
print("Maybe it's time to stop overriding them in the script?")
os.environ["SIDE_MODULE_CXXFLAGS"] = os.environ["SIDE_MODULE_CFLAGS"]
# Set defaults for missing empty environment variables # Set defaults for missing empty environment variables
@@ -295,6 +289,7 @@ DEPS_DIR = os.getenv("DEPS_DIR", DEFAULT_DEPS_DIR)
if not os.path.exists(DEPS_DIR): if not os.path.exists(DEPS_DIR):
os.makedirs(DEPS_DIR) os.makedirs(DEPS_DIR)
INSTALL_DIR = Path(DEPS_DIR) / "install"
BUILD_CFG = os.getenv("BUILD_CFG", "RelWithDebInfo") BUILD_CFG = os.getenv("BUILD_CFG", "RelWithDebInfo")
@@ -320,24 +315,18 @@ cecho(f"* Build Directory = {BUILD_DIR}", MAGENTA)
cecho(f"* Dependency Directory = {DEPS_DIR}", MAGENTA) cecho(f"* Dependency Directory = {DEPS_DIR}", MAGENTA)
cecho(f" - The directory where {PROJECT_NAME} dependencies are installed.") cecho(f" - The directory where {PROJECT_NAME} dependencies are installed.")
cecho(f"* Build Config Type = {BUILD_CFG}", MAGENTA) cecho(f"* Build Config Type = {BUILD_CFG}", MAGENTA)
cecho( cecho(""" - The used build configuration type for the dependencies.
""" - The used build configuration type for the dependencies. Defaults to RelWithDebInfo if not specified.""")
Defaults to RelWithDebInfo if not specified."""
)
if BUILD_CFG == "MinSizeRel": if BUILD_CFG == "MinSizeRel":
cecho(" WARNING: MinSizeRel build can suffer from a significant performance loss.", RED) cecho(" WARNING: MinSizeRel build can suffer from a significant performance loss.", RED)
cecho(f"* IFCOS_NUM_BUILD_PROCS = {IFCOS_NUM_BUILD_PROCS}", MAGENTA) cecho(f"* IFCOS_NUM_BUILD_PROCS = {IFCOS_NUM_BUILD_PROCS}", MAGENTA)
cecho( cecho(""" - How many compiler processes may be run in parallel.
""" - How many compiler processes may be run in parallel. """)
"""
)
cecho(f" * IFCOS_SCHEMAS = '{os.environ.get('IFCOS_SCHEMAS')}'", MAGENTA) cecho(f" * IFCOS_SCHEMAS = '{os.environ.get('IFCOS_SCHEMAS')}'", MAGENTA)
cecho( cecho(""" - IFC Schemas to compile. If not provided, fallback to default provided in cmake.
""" - IFC Schemas to compile. If not provided, fallback to default provided in cmake. """)
"""
)
dependency_tree: "dict[str, tuple[str, ...]]" = { dependency_tree: "dict[str, tuple[str, ...]]" = {
"IfcParse": ("boost", "libxml2", "hdf5", "rocksdb"), "IfcParse": ("boost", "libxml2", "hdf5", "rocksdb"),
@@ -346,18 +335,16 @@ dependency_tree: "dict[str, tuple[str, ...]]" = {
"OpenCOLLADA": ("libxml2", "pcre"), "OpenCOLLADA": ("libxml2", "pcre"),
"IfcGeomServer": ("IfcGeom",), "IfcGeomServer": ("IfcGeom",),
"IfcOpenShell-Python": ("python", "swig", "IfcGeom"), "IfcOpenShell-Python": ("python", "swig", "IfcGeom"),
"swig": ("pcre2",), "swig": (),
"boost": (), "boost": (),
"libxml2": (), "libxml2": (),
"python": (), "python": (),
"occ": ("freetype",), "occ": (),
"pcre": (), "pcre": (),
"pcre2": (),
"json": (), "json": (),
"hdf5": (), "hdf5": (),
"cgal": (), "cgal": (),
"eigen": (), "eigen": (),
"freetype": (),
"rocksdb": ("zstd",), "rocksdb": ("zstd",),
"zstd": (), "zstd": (),
# 'usd': ('boost', 'oneTBB') # 'usd': ('boost', 'oneTBB')
@@ -407,8 +394,6 @@ if any(f.startswith("py-") for f in flags):
if any(f.startswith("occt-") for f in flags): if any(f.startswith("occt-") for f in flags):
OCCT_VERSION = next(f.split("-", 1)[1] for f in flags if f.startswith("occt-")) OCCT_VERSION = next(f.split("-", 1)[1] for f in flags if f.startswith("occt-"))
print(OCCT_VERSION)
if explicit_targets: if explicit_targets:
targets = {dep for target in explicit_targets for dep in gather_dependencies(target)} targets = {dep for target in explicit_targets for dep in gather_dependencies(target)}
else: else:
@@ -422,7 +407,6 @@ if WASM:
"opencollada", "opencollada",
"swig", "swig",
"pcre", "pcre",
"pcre2",
"IfcGeom", "IfcGeom",
"IfcConvert", "IfcConvert",
"IfcGeomServer", "IfcGeomServer",
@@ -437,13 +421,16 @@ print("Building:", *sorted(targets, key=lambda t: len(list(gather_dependencies(t
# Check that required tools are in PATH # Check that required tools are in PATH
yacc = "yacc" # Used during swig building process, installed with `bison` on Debian / `byacc` on Red Hat. yacc = "yacc" # Used during swig building process, installed with `bison` on Debian / `byacc` on Red Hat.
bison = "bison"
missing_commands: "list[str]" = [] missing_commands: "list[str]" = []
required_commands = [git, bunzip2, tar, cc, cplusplus, autoconf, automake, make, "patch", "cmake", yacc, xz] required_commands = [git, bunzip2, tar, cc, cplusplus, autoconf, automake, make, "patch", "cmake", yacc, xz, bison]
if "wasm" in flags: if "wasm" in flags:
# Skip swig build for WASM. # Skip swig build for WASM.
required_commands.append("swig") required_commands.append("swig")
required_commands.append("pyodide") required_commands.append("pyodide")
required_commands.remove(yacc) required_commands.remove(yacc)
required_commands.remove(bison)
for cmd in required_commands: for cmd in required_commands:
if shutil.which(cmd) is None: if shutil.which(cmd) is None:
@@ -502,7 +489,7 @@ def run(cmds: "Sequence[str]", cwd: "Union[str, None]" = None, can_fail: bool =
collector.append(line) collector.append(line)
pipe.close() pipe.close()
logger.debug(f"running command {' '.join(cmds)} in directory {cwd}") logger.debug(f"running command `{' '.join(cmds)}` in directory '{cwd}'")
stdout: list[str] = [] stdout: list[str] = []
stderr: list[str] = [] stderr: list[str] = []
@@ -548,14 +535,14 @@ BOOST_LOCATION = f"https://github.com/boostorg/boost/releases/download/boost-{BO
# Helper functions # Helper functions
def run_autoconf(arg1: str, configure_args: "list[str]", cwd: str) -> None: def run_autoconf(dependency_name: str, configure_args: "list[str]", cwd: str) -> None:
configure_path = os.path.realpath(os.path.join(cwd, "..", "configure")) configure_path = os.path.realpath(os.path.join(cwd, "..", "configure"))
if not os.path.exists(configure_path): if not os.path.exists(configure_path):
run( run(
[bash, "./autogen.sh"], cwd=os.path.realpath(os.path.join(cwd, "..")) [bash, "./autogen.sh"], cwd=os.path.realpath(os.path.join(cwd, ".."))
) # only run autogen.sh in the directory it is located and use cwd to achieve that in order to not mess up things ) # only run autogen.sh in the directory it is located and use cwd to achieve that in order to not mess up things
# Using `sh` over `bash` fixes issues with building swig # Using `sh` over `bash` fixes issues with building swig
prefix = os.path.realpath(f"{DEPS_DIR}/install/{arg1}") prefix = os.path.realpath(f"{DEPS_DIR}/install/{dependency_name}")
wasm = [] wasm = []
if "wasm" in flags: if "wasm" in flags:
@@ -934,53 +921,34 @@ if "pcre" in targets:
restore_env("CC", OLD_CC) restore_env("CC", OLD_CC)
restore_env("CXX", OLD_CXX) restore_env("CXX", OLD_CXX)
if "pcre2" in targets:
build_dependency(
name=f"pcre2-{PCRE2_VERSION}",
mode="autoconf",
build_tool_args=[DISABLE_FLAG],
download_url=f"https://downloads.sourceforge.net/project/pcre/pcre2/{PCRE2_VERSION}/",
download_name=f"pcre2-{PCRE2_VERSION}.tar.bz2",
)
if "swig" in targets: if "swig" in targets:
dependency_name = f"swig-{SWIG_VERSION}"
build_dependency( build_dependency(
name=f"swig-{SWIG_VERSION}", name=dependency_name,
mode="autoconf", mode="cmake",
build_tool_args=["--disable-ccache", f"--with-pcre2-prefix={DEPS_DIR}/install/pcre2-{PCRE2_VERSION}"], build_tool_args=[
"-DWITH_PCRE=OFF",
f"-DCMAKE_INSTALL_PREFIX={DEPS_DIR}/install/{dependency_name}",
],
download_url="https://github.com/swig/swig.git", download_url="https://github.com/swig/swig.git",
download_name="swig", download_name="swig",
download_tool=download_tool_git, download_tool=download_tool_git,
revision=f"v{SWIG_VERSION}", revision=f"v{SWIG_VERSION}",
) )
if "freetype" in targets:
build_dependency(
name=f"freetype",
mode="cmake",
build_tool_args=[f"-DCMAKE_INSTALL_PREFIX={DEPS_DIR}/install/freetype"],
download_url="https://github.com/freetype/freetype",
download_name="freetype2",
download_tool=download_tool_git,
revision="VER-2-14-0",
)
if USE_OCCT and "occ" in targets: if USE_OCCT and "occ" in targets:
patches = [] occt_args: "list[str]" = []
patches: "list[str]" = []
if OCCT_VERSION < "7.4": if OCCT_VERSION < "7.4":
patches.append("./patches/occt/enable-exception-handling.patch") patches.append("./patches/occt/enable-exception-handling.patch")
if OCCT_VERSION == "7.7.1": # Skip ExpToCasExe as we don't need it and it requires additional dependencies.
# Before 7.7.2 ExpToCasExe is part of DataExchange, DETools doesn't exist yet.
# Since we do need DataExchange (used for IgesSerializer), we use a patch to skip only ExpToCasExe.
if "7.7.2" > OCCT_VERSION >= "7.7":
patches.append("./patches/occt/no_ExpToCasExe.patch") patches.append("./patches/occt/no_ExpToCasExe.patch")
elif OCCT_VERSION >= "7.7.2":
if OCCT_VERSION == "7.7.2": occt_args.append("-DBUILD_MODULE_DETools=OFF")
patches.append("./patches/occt/no_ExpToCasExe_7_7_2.patch")
if OCCT_VERSION == "7.8.1":
patches.append("./patches/occt/no_ExpToCasExe_7_8_1.patch")
if OCCT_VERSION == "7.9.1":
patches.append("./patches/occt/no_ExpToCasExe_7_9_1.patch")
if "wasm" in flags: if "wasm" in flags:
patches.append("./patches/occt/no_em_js.patch") patches.append("./patches/occt/no_em_js.patch")
@@ -999,9 +967,9 @@ if USE_OCCT and "occ" in targets:
f"-DUSE_FREETYPE=OFF", f"-DUSE_FREETYPE=OFF",
f"-DUSE_OPENGL=OFF", f"-DUSE_OPENGL=OFF",
f"-DUSE_GLES2=OFF", f"-DUSE_GLES2=OFF",
f"-D3RDPARTY_FREETYPE_DIR={DEPS_DIR}/install/freetype",
f"-DCMAKE_POLICY_VERSION_MINIMUM=3.5", f"-DCMAKE_POLICY_VERSION_MINIMUM=3.5",
*MAC_CROSS_COMPILE_INTEL_ARGS, *MAC_CROSS_COMPILE_INTEL_ARGS,
*occt_args,
], ],
download_url="https://github.com/Open-Cascade-SAS/OCCT", download_url="https://github.com/Open-Cascade-SAS/OCCT",
download_name="occt", download_name="occt",
@@ -1117,23 +1085,28 @@ if "python" in targets and not USE_CURRENT_PYTHON_VERSION and "wasm" not in flag
PYTHON_CONFIGURE_ARGS.extend(["--with-universal-archs=intel-64", "--enable-universalsdk"]) PYTHON_CONFIGURE_ARGS.extend(["--with-universal-archs=intel-64", "--enable-universalsdk"])
for PYTHON_VERSION in PYTHON_VERSIONS: for PYTHON_VERSION in PYTHON_VERSIONS:
# Don't fail silently on missing Python dependencies (e.g. openssl or zlib),
# because later ifcopenshell-python build will fail too but in a more confusing way.
build_dependency(
f"python-{PYTHON_VERSION}",
"autoconf",
PYTHON_CONFIGURE_ARGS,
f"http://www.python.org/ftp/python/{PYTHON_VERSION}/",
f"Python-{PYTHON_VERSION}.tgz",
)
python_install = INSTALL_DIR / f"python-{PYTHON_VERSION}"
python_bin = python_install / "bin" / "python3"
# `_ssl` module is present -> we will be able to install `numpy` later
# to verify IfcOpenShell installation
try: try:
build_dependency( run([str(python_bin), "-c", "import _ssl"])
f"python-{PYTHON_VERSION}", except RuntimeError:
"autoconf", print(
PYTHON_CONFIGURE_ARGS, "ERROR: Python was built without SSL support (_ssl module is missing). "
f"http://www.python.org/ftp/python/{PYTHON_VERSION}/", f"To fix this: remove the installed Python at {python_install}; "
f"Python-{PYTHON_VERSION}.tgz", "install OpenSSL development libraries and re-run."
) )
except RuntimeError as e: raise
# Sometimes setting up modules such as pip/lzma can cause
# the python installer script to return a non zero exit
# code where actually the headers and dynamic libraries
# are installed correctly. This is all we need so we catch
# the exception and only reraise if a partially successful
# install is not detected.
if not os.path.exists(os.path.join(DEPS_DIR, "install", f"python-{PYTHON_VERSION}")):
raise e
if MAC_CROSS_COMPILE_INTEL: if MAC_CROSS_COMPILE_INTEL:
assert original_path assert original_path
@@ -1193,6 +1166,8 @@ if "cgal" in targets:
# Disable assembly, otherwise `emcc -c conftest.s` will crash due to assembly mismatch. # Disable assembly, otherwise `emcc -c conftest.s` will crash due to assembly mismatch.
gmp_args.extend(("--disable-assembly", "--enable-cxx")) gmp_args.extend(("--disable-assembly", "--enable-cxx"))
mpfr_args.extend(("--host", "none")) mpfr_args.extend(("--host", "none"))
elif "x86" in arch:
gmp_args.append("--enable-fat") # See issues #7458 #7556
OLD_CC = None OLD_CC = None
if MAC_CROSS_COMPILE_INTEL: if MAC_CROSS_COMPILE_INTEL:
@@ -1334,7 +1309,6 @@ os.makedirs(executables_dir, exist_ok=True)
cmake_args = [ cmake_args = [
"-DCMAKE_CXX_STANDARD=17",
"-DUSE_MMAP=OFF", "-DUSE_MMAP=OFF",
"-DBUILD_EXAMPLES=OFF", "-DBUILD_EXAMPLES=OFF",
"-DBUILD_SHARED_LIBS=" + OFF_ON[not BUILD_STATIC], "-DBUILD_SHARED_LIBS=" + OFF_ON[not BUILD_STATIC],
@@ -1409,11 +1383,11 @@ else:
cmake_args.append("-DHDF5_SUPPORT=Off") cmake_args.append("-DHDF5_SUPPORT=Off")
if "usd" in targets: if "usd" in targets:
cmake_args.extend( cmake_args.append("-DUSD_SUPPORT=ON")
cmake_args_prefix_path.extend(
[ [
f"-DUSD_SUPPORT=" "On", f"{DEPS_DIR}/install/tbb-{TBB_VERSION}",
f"-DUSD_INCLUDE_DIR={DEPS_DIR}/install/usd-{USD_VERSION}/include", f"{DEPS_DIR}/install/usd-{USD_VERSION}",
f"-DUSD_LIBRARY_DIR={DEPS_DIR}/install/usd-{USD_VERSION}/lib",
] ]
) )
@@ -1550,13 +1524,16 @@ if "IfcOpenShell-Python" in targets:
) )
# Copy setup.py where pyodide build system expects it. # Copy setup.py where pyodide build system expects it.
shutil.copy(REPO_PATH / "pyodide" / "setup.py", REPO_PATH) shutil.copy(REPO_PATH / "pyodide" / "setup.py", REPO_PATH)
# Empty pyproject so it's contents won't affect the resulting wheel
# otherwise the wheel will use version and dependencies from toml, not setup.py.
(REPO_PATH / "pyproject.toml").write_text("")
elif USE_CURRENT_PYTHON_VERSION: elif USE_CURRENT_PYTHON_VERSION:
python_info = sysconfig.get_paths() python_info = sysconfig.get_paths()
compile_python_wrapper(platform.python_version(), python_info["include"], sys.executable) compile_python_wrapper(platform.python_version(), python_info["include"], sys.executable)
else: else:
for python_version in PYTHON_VERSIONS: for python_version in PYTHON_VERSIONS:
python_path = Path(DEPS_DIR) / "install" / f"python-{python_version}" python_path = INSTALL_DIR / f"python-{python_version}"
module_dir = compile_python_wrapper(python_version, python_path=python_path) module_dir = compile_python_wrapper(python_version, python_path=python_path)
assert module_dir assert module_dir
# Not sure why, but added after reading this in the logs # Not sure why, but added after reading this in the logs
@@ -5,36 +5,51 @@ This script is finding common install directory and either
packs each folder into a tar.gz archive, if it wasn't packed before, packs each folder into a tar.gz archive, if it wasn't packed before,
or unpacks existing archives. or unpacks existing archives.
Expected to be executed from 'build' directory (e.g. that might contain 'Linux/x86_64/install').
Usage: python cache_dependencies.py [pack|unpack] Usage: python cache_dependencies.py [pack|unpack]
""" """
import tarfile import platform
import subprocess
import sys import sys
import tarfile
from pathlib import Path from pathlib import Path
from typing import Literal from typing import Literal
CACHE_PREFIX = "cache-" CACHE_PREFIX = "cache-"
def get_install_dir() -> Path: def get_install_dir() -> Path:
for data in Path.cwd().glob("*/*/install"): if platform.system() == "Darwin":
pattern = "Darwin/*/*/install"
else:
pattern = "*/*/install"
for data in Path.cwd().glob(pattern):
return data return data
raise Exception("No install dir found") raise Exception("No install dir found")
def run(cmd: str) -> None:
print(f"Running command: `{cmd}`")
subprocess.check_call(cmd, shell=True)
def pack_dependencies(install_dir: Path) -> None: def pack_dependencies(install_dir: Path) -> None:
# Process each install_dir # Process each install_dir
for dependency_path in install_dir.iterdir(): for dependency_path in install_dir.iterdir():
if not dependency_path.is_dir(): if not dependency_path.is_dir():
continue continue
dependency_name = dependency_path.name dependency_name = dependency_path.name
# Skip ifcopenshell - it's a build output, not a dependency to reuse across builds.
if dependency_name == "ifcopenshell":
continue
tar_path = install_dir / f"{CACHE_PREFIX}{dependency_name}.tar.gz" tar_path = install_dir / f"{CACHE_PREFIX}{dependency_name}.tar.gz"
if tar_path.exists(): if tar_path.exists():
print(f"Skipping existing cache: '{tar_path}'") print(f"Skipping existing cache: '{tar_path}'")
else: else:
with tarfile.open(tar_path, "w:gz") as tar: # Python's `tarfile` is 10x slower than `tar` cli, so we use `tar`.
tar.add(dependency_path, arcname=dependency_path.name) run(f'tar -czf "{tar_path}" -C "{install_dir}" "{dependency_name}"')
print(f"Created cache: '{tar_path}'") print(f"Created cache: '{tar_path}'")
+9 -13
View File
@@ -1,13 +1,9 @@
diff --git a/CMakeLists.txt b/CMakeLists.txt --- a/adm/MODULES
index fd17283f77..6cecf9dad3 100644 +++ b/adm/MODULES
--- a/CMakeLists.txt @@ -3,5 +3,5 @@ ModelingData TKG2d TKG3d TKGeomBase TKBRep
+++ b/CMakeLists.txt ModelingAlgorithms TKGeomAlgo TKTopAlgo TKPrim TKBO TKBool TKHLR TKFillet TKOffset TKFeat TKMesh TKXMesh TKShHealing
@@ -826,6 +826,8 @@ if (EMSCRIPTEN) Visualization TKService TKV3d TKOpenGl TKOpenGles TKMeshVS TKIVtk TKD3DHost
list (REMOVE_ITEM BUILD_TOOLKITS ExpToCasExe) ApplicationFramework TKCDF TKLCAF TKCAF TKBinL TKXmlL TKBin TKXml TKStdL TKStd TKTObj TKBinTObj TKXmlTObj TKVCAF
endif() -DataExchange TKXDE TKXSBase TKSTEPBase TKSTEPAttr TKSTEP209 TKSTEP TKIGES TKXCAF TKXDEIGES TKXDESTEP TKSTL TKVRML TKXmlXCAF TKBinXCAF TKRWMesh TKXDECascade TKExpress ExpToCasExe
+DataExchange TKXDE TKXSBase TKSTEPBase TKSTEPAttr TKSTEP209 TKSTEP TKIGES TKXCAF TKXDEIGES TKXDESTEP TKSTL TKVRML TKXmlXCAF TKBinXCAF TKRWMesh TKXDECascade TKExpress
+list (REMOVE_ITEM BUILD_TOOLKITS ExpToCasExe) Draw TKDraw TKTopTest TKOpenGlTest TKOpenGlesTest TKD3DHostTest TKViewerTest TKXSDRAW TKDCAF TKXDEDRAW TKTObjDRAW TKQADraw TKIVtkDraw DRAWEXE
+
# bison
if (BUILD_YACCLEX)
OCCT_INCLUDE_CMAKE_FILE ("adm/cmake/bison")
@@ -1,13 +0,0 @@
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 1bacca1a48..11f931ad39 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -820,6 +820,8 @@ else()
OCCT_CHECK_AND_UNSET ("3RDPARTY_DOT_EXECUTABLE")
endif()
+list (REMOVE_ITEM BUILD_TOOLKITS ExpToCasExe)
+
# bison
if (BUILD_YACCLEX)
OCCT_INCLUDE_CMAKE_FILE ("adm/cmake/bison")
@@ -1,13 +0,0 @@
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 86905287dc..9d0bce984c 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -828,6 +828,8 @@ else()
OCCT_CHECK_AND_UNSET ("3RDPARTY_DOT_EXECUTABLE")
endif()
+list (REMOVE_ITEM BUILD_TOOLKITS ExpToCasExe)
+
# bison
if (BUILD_YACCLEX)
OCCT_INCLUDE_CMAKE_FILE ("adm/cmake/bison")
@@ -1,13 +0,0 @@
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 34300d41ad..09b2e0d45f 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -721,6 +721,8 @@ else()
OCCT_CHECK_AND_UNSET ("3RDPARTY_DOT_EXECUTABLE")
endif()
+list (REMOVE_ITEM BUILD_TOOLKITS ExpToCasExe)
+
# bison
if (BUILD_YACCLEX)
list (APPEND OCCT_3RDPARTY_CMAKE_LIST "adm/cmake/bison")
+7 -9
View File
@@ -1,9 +1,12 @@
#!/usr/bin/bash #!/usr/bin/bash
set -ex set -ex
# Script is assuming that it will be possible to execute it multiple times
# therefore we're clearing venv each time and ignoring existing 'emsdk' folder.
# Install uv. # Install uv.
curl -LsSf https://astral.sh/uv/install.sh | sh curl -LsSf https://astral.sh/uv/install.sh | sh
uv venv --python 3.13 uv venv --python 3.13 --clear
source .venv/bin/activate source .venv/bin/activate
# Install pyodide cross build environment. # Install pyodide cross build environment.
@@ -11,16 +14,11 @@ source .venv/bin/activate
uv pip install pyodide-build uv pip install pyodide-build
# `uv run` is required, so xbuildenv would skip using `pip`. # `uv run` is required, so xbuildenv would skip using `pip`.
uv run pyodide xbuildenv install uv run pyodide xbuildenv install
uv run pyodide xbuildenv install-emscripten
# Emscripten doesn't come with xbuildenv. EMSDK_ROOT=$(pyodide config get emscripten_dir)
git clone https://github.com/emscripten-core/emsdk source ${EMSDK_ROOT}/emsdk_env.sh
pushd emsdk
PYODIDE_EMSCRIPTEN_VERSION=$(pyodide config get emscripten_version)
./emsdk install ${PYODIDE_EMSCRIPTEN_VERSION}
./emsdk activate ${PYODIDE_EMSCRIPTEN_VERSION}
source emsdk_env.sh
which emcc which emcc
popd
mkdir -p packages/ifcopenshell mkdir -p packages/ifcopenshell
VERSION=`cat IfcOpenShell/VERSION` VERSION=`cat IfcOpenShell/VERSION`
+232
View File
@@ -0,0 +1,232 @@
#
# /// script
# # Latest Pyodide build env versions are listed here:
# # https://pyodide.github.io/pyodide/api/pyodide-cross-build-environments.json
# # https://github.com/pyodide/pyodide-build/blob/main/pyodide_build/xbuildenv_releases.py
# requires-python = "==3.13.2"
# dependencies = [
# "requests",
# "setuptools",
# ]
# ///
"""
Pack an IfcOpenShell WASM wheel using Pyodide build system.
Usage:
uv run make_wheel.py # Show this help
uv run make_wheel.py --build # Build wheel
uv run make_wheel.py --clean # Clean build artifacts and exit
"""
import argparse
import os
import re
import shutil
import subprocess
import time
import zipfile
from pathlib import Path
from urllib.parse import quote
import requests
# Get repo root (parent of this script's parent directory)
REPO_ROOT = Path(__file__).parent.parent
PYODIDE_DIR = REPO_ROOT / "pyodide"
BUILD_DIR = PYODIDE_DIR / "build"
# Hardcoded path (Windows packing workaround with --dev flag)
PYODIDE_BUILD = Path(r"L:\Projects\Github\pyodide-build")
# Wheel platform tag (from PYODIDE_EMSCRIPTEN_VERSION in pyodide-build/Makefile.envs)
WHEEL_PLATFORM_TAG = "emscripten_4_0_9_wasm32"
# Location where ifcopenshell will be extracted
IFCOPENSHELL_DIR = PYODIDE_DIR / "ifcopenshell"
class WheelBuilder:
@staticmethod
def extract_ifcopenshell_from_git(dst: Path) -> None:
"""Extract ifcopenshell directory from git repo into destination."""
Tools.rmrf(dst)
print(f"Extracting ifcopenshell from git to {dst}...")
# Use git ls-files piped to git checkout-index to avoid copying
# untracked or ignored files from the actual repo.
ls_proc = subprocess.Popen(
["git", "ls-files", "-z", "src/ifcopenshell-python/ifcopenshell"],
cwd=REPO_ROOT,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
)
checkout_proc = subprocess.Popen(
["git", "checkout-index", "-z", "--prefix", "pyodide/", "--stdin"],
cwd=REPO_ROOT,
stdin=ls_proc.stdout,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
)
assert ls_proc.stdout is not None
ls_proc.stdout.close()
checkout_proc.communicate()
if checkout_proc.returncode != 0:
assert checkout_proc.stderr is not None
raise RuntimeError(f"Failed to extract: {checkout_proc.stderr.decode()}")
# Move src/ifcopenshell-python/ifcopenshell to ifcopenshell.
temp_src = PYODIDE_DIR / "src" / "ifcopenshell-python" / "ifcopenshell"
shutil.move(temp_src, dst)
# Clean up temporary src directory.
Tools.rmrf(PYODIDE_DIR / "src")
print("✓ Extracted ifcopenshell from git")
@staticmethod
def get_wheel_url(makefile_path: Path) -> str:
"""Get S3 wheel URL based on BINARY_VERSION and BUILD_COMMIT from Makefile."""
def parse_makefile_vars() -> dict[str, str]:
content = makefile_path.read_text()
vars: dict[str, str] = {}
for match in re.finditer(r"^(BINARY_VERSION|BUILD_COMMIT):=(.+)$", content, re.MULTILINE):
vars[match.group(1)] = match.group(2).strip()
return vars
vars: dict[str, str] = parse_makefile_vars()
binary_version = vars["BINARY_VERSION"]
build_commit = vars["BUILD_COMMIT"]
filename = f"ifcopenshell-{binary_version}+{build_commit}-cp313-cp313-pyodide_2025_0_wasm32.whl"
encoded_filename = quote(filename, safe="")
return f"https://s3.amazonaws.com/ifcopenshell-builds/{encoded_filename}"
@staticmethod
def download_and_extract_so(url: str, build_dir: Path) -> tuple[Path, Path]:
"""Download wheel from URL and extract .so and .py files."""
py_wrapper_filename = "ifcopenshell_wrapper.py"
build_dir.mkdir(parents=True, exist_ok=True)
wheel_path = build_dir / url.rsplit("/", 1)[-1]
if wheel_path.exists():
print(f"Using cached wheel: {wheel_path}")
else:
print(f"Downloading {url}...")
response = requests.get(url)
response.raise_for_status()
wheel_path.write_bytes(response.content)
print("Extracting _ifcopenshell_wrapper files...")
with zipfile.ZipFile(wheel_path) as zf:
so_files = [f for f in zf.namelist() if f.endswith(".so")]
py_files = [f for f in zf.namelist() if f.endswith(py_wrapper_filename)]
assert so_files, "No .so file found in wheel"
assert py_files, f"No {py_wrapper_filename} file found in wheel"
so_file = so_files[0]
so_dst = build_dir / Path(so_file).name
so_dst.write_bytes(zf.read(so_file))
py_file = py_files[0]
py_dst = build_dir / Path(py_file).name
py_dst.write_bytes(zf.read(py_file))
return so_dst, py_dst
class Tools:
@staticmethod
def run(
cmd: list[str],
cwd: Path | None = None,
) -> None:
print(f"$ {' '.join(cmd)}")
subprocess.check_call(cmd, cwd=cwd)
@staticmethod
def create_symlink(dst: Path, src: Path) -> None:
Tools.rmrf(dst)
dst.symlink_to(src)
@staticmethod
def rmrf(path: Path) -> None:
if path.exists() or path.is_symlink():
if path.is_dir() and not path.is_symlink():
shutil.rmtree(path)
else:
path.unlink()
def clean() -> None:
"""Remove build artifacts."""
paths_to_remove = (
BUILD_DIR,
PYODIDE_DIR / ".pyodide_build",
PYODIDE_DIR / "dist",
PYODIDE_DIR / "ifcopenshell.egg-info",
PYODIDE_DIR / "src",
IFCOPENSHELL_DIR,
)
for path in paths_to_remove:
if path.exists() or path.is_symlink():
print(f"Removing {path}...")
Tools.rmrf(path)
print("✓ Clean complete")
def main() -> None:
parser = argparse.ArgumentParser(description=__doc__, add_help=False)
parser.add_argument("--build", action="store_true", help="Build the wheel")
parser.add_argument("--clean", action="store_true", help="Clean build folder")
parser.add_argument(
"--dev",
action="store_true",
help="Use editable pyodide-build from hardcoded path (Windows packing workaround)",
)
args = parser.parse_args()
if not args.build and not args.clean:
print(__doc__)
return
if args.clean:
clean()
return
start_time = time.time()
WheelBuilder.extract_ifcopenshell_from_git(IFCOPENSHELL_DIR)
print("Downloading and extracting _ifcopenshell_wrapper files...")
makefile = REPO_ROOT / "src" / "ifcopenshell-python" / "Makefile"
wheel_url = WheelBuilder.get_wheel_url(makefile)
so_file, py_file = WheelBuilder.download_and_extract_so(wheel_url, BUILD_DIR)
Tools.create_symlink(IFCOPENSHELL_DIR / Path(so_file).name, so_file)
Tools.create_symlink(IFCOPENSHELL_DIR / Path(py_file).name, py_file)
print("Installing pyodide-build...")
if args.dev:
Tools.run(["uv", "pip", "install", "-e", str(PYODIDE_BUILD)])
else:
Tools.run(["uv", "pip", "install", "pyodide-build"])
print("Building with pyodide...")
# Use --no-isolation due to pyodide-build Windows support issues:
# symlink_unisolated_packages fails with missing `_sysconfigdata_$(CPYTHON_ABI_FLAGS)_emscripten_wasm32-emscripten.py`.
# Hardcode platform name since pyodide doesn't yet support overriding wheel tags on Windows.
#
# Use `LEGACY_PLATFORM` since pyodide 0.34.1 introduced new tag for wheels `pyemscripten`,
# which doesn't work with pyodide itself yet - https://github.com/pyodide/pyodide/issues/6177.
os.environ["USE_LEGACY_PLATFORM"] = "1"
Tools.run(["pyodide", "build", f"-C--build-option=--plat-name={WHEEL_PLATFORM_TAG}"])
elapsed = time.time() - start_time
print(f"\n✓ Done! ({elapsed:.1f}s)")
if __name__ == "__main__":
main()
+39 -1
View File
@@ -2,12 +2,16 @@
# because `tool.setuptools.ext-modules` is still experimental in pyproject.toml # because `tool.setuptools.ext-modules` is still experimental in pyproject.toml
# and we need it to get the wheel suffix right. # and we need it to get the wheel suffix right.
import os import os
import sys
from pathlib import Path from pathlib import Path
import tomllib import tomllib
from setuptools import Extension, find_packages, setup from setuptools import Extension, find_packages, setup
from setuptools.command.build_ext import build_ext
REPO_FOLDER = Path(__file__).parent # Detect repo folder: if setup.py is in pyodide folder, go to parent
SETUP_DIR = Path(__file__).parent
REPO_FOLDER = SETUP_DIR.parent if SETUP_DIR.name == "pyodide" else SETUP_DIR
def get_version() -> str: def get_version() -> str:
@@ -25,6 +29,39 @@ def get_dependencies() -> list[str]:
return dependencies return dependencies
class UnixBuildExt(build_ext):
"""Customize ``build_ext`` to support packing on Windows."""
def finalize_options(self):
from distutils import sysconfig
super().finalize_options()
if sys.platform == "win32":
self.compiler = "unix"
# Configure sysconfig for Windows builds
# CCSHARED is the only variable that's not customizable with env vars.
# Basically avoiding this:
# File ".venv\Lib\site-packages\setuptools\_distutils\sysconfig.py", line 366, in customize_compiler
# compiler_so=cc_cmd + ' ' + ccshared,
# ~~~~~~~~~~~~~^~~~~~~~~~
# TypeError: can only concatenate str (not "NoneType") to str
sysconfig.get_config_vars() # Initialize config cache
if sysconfig._config_vars.get("CCSHARED") is None:
sysconfig._config_vars["CCSHARED"] = "-fPIC"
# Override compiler type before it's instantiated
# Set Emscripten compiler environment variables
os.environ["CC"] = "emcc"
os.environ["CXX"] = "em++"
os.environ["CFLAGS"] = ""
os.environ["CXXFLAGS"] = ""
os.environ["LDSHARED"] = "emcc -shared"
os.environ["AR"] = "emar"
os.environ["ARFLAGS"] = "rcs"
os.environ["SETUPTOOLS_EXT_SUFFIX"] = ".cpython-313-wasm32-emscripten.so"
setup( setup(
name="ifcopenshell", name="ifcopenshell",
version=get_version(), version=get_version(),
@@ -44,4 +81,5 @@ setup(
}, },
# Has to provide extension to get the correct wheel suffix. # Has to provide extension to get the correct wheel suffix.
ext_modules=[Extension("ifcopenshell._ifcopenshell_wrapper", sources=[])], ext_modules=[Extension("ifcopenshell._ifcopenshell_wrapper", sources=[])],
cmdclass={"build_ext": UnixBuildExt},
) )
-1
View File
@@ -1,6 +1,5 @@
from pathlib import Path from pathlib import Path
WHEEL_FILENAME = next( WHEEL_FILENAME = next(
p.name for p in (Path.cwd() / "pyodide").iterdir() if p.name.startswith("ifcopenshell-") and p.suffix == ".whl" p.name for p in (Path.cwd() / "pyodide").iterdir() if p.name.startswith("ifcopenshell-") and p.suffix == ".whl"
) )
+197 -1
View File
@@ -1,3 +1,14 @@
[project]
name = "IfcOpenShell"
version = "0.0.0"
dependencies = [
"black==26.3.1",
"ruff==0.15.9",
"poethepoet",
"ty==0.0.29",
"gersemi==0.26.1",
]
[tool.black] [tool.black]
line-length = 120 line-length = 120
include = ''' include = '''
@@ -5,7 +16,8 @@ include = '''
|nix/.*.pyi?$ |nix/.*.pyi?$
''' '''
extend-exclude = ''' extend-exclude = '''
src/ifcopenshell-python/ifcopenshell/express/* src/ifcopenshell-python/ifcopenshell/express/rules/*
|src/ifcopenshell-python/ifcopenshell/express/express_parser.py
|src/ifcopenshell-python/ifcopenshell/mvd/* |src/ifcopenshell-python/ifcopenshell/mvd/*
|src/ifcopenshell-python/ifcopenshell/simple_spf/* |src/ifcopenshell-python/ifcopenshell/simple_spf/*
|src/ifc2ca/templates/* |src/ifc2ca/templates/*
@@ -17,6 +29,15 @@ extend-exclude = '''
reportInvalidTypeForm = false reportInvalidTypeForm = false
disableBytesTypePromotions = true disableBytesTypePromotions = true
reportUnnecessaryTypeIgnoreComment = true reportUnnecessaryTypeIgnoreComment = true
reportRedeclaration = false
# Ignore warnings from bpy stubs missing actual source files.
reportMissingModuleSource = false
# Pylance doesn't respect gitignore, so we have to exclude files manually here
# to avoid VS Code slowing down.
# https://github.com/microsoft/pylance-release/issues/5169
exclude = [
"_deps",
]
# Define here general ruff settings, # Define here general ruff settings,
# then they will be inherited by projects' .toml files. # then they will be inherited by projects' .toml files.
@@ -47,6 +68,7 @@ select = [
"UP", # pyupgrade "UP", # pyupgrade
"RUF015", # next() > list_comprehension[0] "RUF015", # next() > list_comprehension[0]
"RUF022", # sort __all__ "RUF022", # sort __all__
"I", # import sorting
] ]
ignore = [ ignore = [
"FA100", # Conflicts with Blender using annotations for props definitions. "FA100", # Conflicts with Blender using annotations for props definitions.
@@ -60,6 +82,137 @@ ignore = [
"UP032", # Replace .format with f-string "UP032", # Replace .format with f-string
] ]
[tool.ty.rules]
all = "ignore"
# Structural rules (no deep type inference needed, easier to adapt).
abstract-method-in-final-class = "error"
ambiguous-protocol-member = "error"
conflicting-declarations = "error"
conflicting-metaclass = "error"
cyclic-class-definition = "error"
cyclic-type-alias-definition = "error"
dataclass-field-order = "error"
duplicate-base = "error"
duplicate-kw-only = "error"
empty-body = "error"
escape-character-in-forward-annotation = "error"
final-on-non-method = "error"
final-without-value = "error"
ignore-comment-unknown-rule = "error"
implicit-concatenated-string-type-annotation = "error"
inconsistent-mro = "error"
ineffective-final = "error"
instance-layout-conflict = "error"
invalid-dataclass = "error"
invalid-dataclass-override = "error"
invalid-enum-member-annotation = "error"
invalid-explicit-override = "error"
invalid-frozen-dataclass-subclass = "error"
invalid-generic-class = "error"
invalid-generic-enum = "error"
invalid-ignore-comment = "error"
invalid-legacy-positional-parameter = "error"
invalid-legacy-type-variable = "error"
invalid-named-tuple = "error"
invalid-newtype = "error"
invalid-overload = "error"
invalid-paramspec = "error"
invalid-protocol = "error"
invalid-syntax-in-forward-annotation = "error"
invalid-total-ordering = "error"
invalid-type-alias-type = "error"
invalid-type-checking-constant = "error"
invalid-type-guard-definition = "error"
invalid-type-variable-bound = "error"
invalid-type-variable-constraints = "error"
invalid-typed-dict-header = "error"
invalid-typed-dict-statement = "error"
override-of-final-method = "error"
override-of-final-variable = "error"
possibly-missing-import = "error"
possibly-missing-submodule = "error"
# Has false positives due to ty walrus operator bug.
# possibly-unresolved-reference = "error"
raw-string-type-annotation = "error"
redundant-final-classvar = "error"
shadowed-type-variable = "error"
subclass-of-final-class = "error"
super-call-in-named-tuple-method = "error"
unavailable-implicit-super-arguments = "error"
unbound-type-variable = "error"
undefined-reveal = "error"
unresolved-global = "error"
unresolved-import = "error"
unresolved-reference = "error"
unused-ignore-comment = "error"
unused-type-ignore-comment = "error"
useless-overload-body = "error"
# Non-structural rules:
deprecated = "error"
zero-stepsize-in-slice = "error"
possibly-missing-implicit-call = "error"
unused-awaitable = "error"
# Function argument rules:
# Conflicts with `ifcopenshell.api.geometry.add_representation` type of callables we have, confusing them with a module.
# call-non-callable = "error"
conflicting-argument-forms = "error"
# Too many false positives.
# invalid-argument-type = "error"
missing-argument = "error"
parameter-already-assigned = "error"
positional-only-parameter-as-kwarg = "error"
too-many-positional-arguments = "error"
unknown-argument = "error"
# Has a lot of warnings due to current ty walrus operator issues.
# index-out-of-bounds = "error"
# unresolved-attribute = "error"
[tool.ty.environment]
extra-paths = [
"src/bonsai/external_dependencies",
"src/bcf",
"src/bsdd",
"src/bonsai",
"src/ifc4d",
"src/ifc5d",
"src/ifccityjson",
"src/ifcclash",
"src/ifccsv",
"src/ifcdiff",
"src/ifcfm",
"src/ifcopenshell-python",
"src/ifcpatch",
"src/ifctester",
]
[tool.ty.src]
exclude = [
# External dependencies cloned for type checking only.
"src/bonsai/external_dependencies",
# Submodules.
"src/ifcopenshell-python/ifcopenshell/express",
"src/ifcopenshell-python/ifcopenshell/mvd",
"src/ifcopenshell-python/ifcopenshell/simple_spf",
"src/svgfill/3rdparty",
# Has special dependencies.
"src/ifcopenshell-python/ifcopenshell/geom/app.py",
"src/ifcopenshell-python/ifcopenshell/geom/code_editor_pane.py",
"src/ifcopenshell-python/ifcopenshell/util/doc.py",
"src/ifcopenshell-python/ifcopenshell/util/generate_pset_templates.py",
"src/ifcopenshell-python/ifcopenshell/util/ifc4x3dev_scrape_data_for_docs.py",
# Too esoteric.
"src/ifcopenshell-python/ifcopenshell/ifcopenshell_wrapper.py",
"src/ifc2ca/templates",
# Too dev.
"src/bcf/setup.py",
"src/bsdd/yml_to_classes.py",
# Deprecated.
"src/ifc2ca/_deprecated",
]
[tool.poe.tasks] [tool.poe.tasks]
ruff-main = "ruff check --extend-exclude nix/build-all.py" ruff-main = "ruff check --extend-exclude nix/build-all.py"
@@ -69,4 +222,47 @@ ruff.sequence = ["ruff-main", "ruff-old"]
black = "black ." black = "black ."
ty.sequence = ["ty-bonsai", "ty-ios"]
ty.help = "Run ty type checker. Requires ty-venv to be set up first."
ty-bonsai = "ty check src/bonsai --python=src/bonsai/.venv"
ty-venv.sequence = ["bonsai-deps", "ty-venv-bonsai", "ty-venv-ios"]
ty-venv-bonsai.sequence = [
{cmd = "uv venv src/bonsai/.venv --python=3.11 --allow-existing"},
{cmd = "uv pip install -r src/bonsai/type-check-requirements.txt --python=src/bonsai/.venv"},
]
ty-venv-ios.sequence = [
{cmd = "uv venv src/ifcopenshell-python/.venv --python=3.10 --allow-existing"},
{cmd = "uv pip install -r src/ifcopenshell-python/type-check-requirements.txt --python=src/ifcopenshell-python/.venv"},
]
format.sequence = ["black", "ruff-main", "ruff-old"] format.sequence = ["black", "ruff-main", "ruff-old"]
cmake-format = "gersemi . --in-place"
[tool.poe.tasks.ty-ios]
# --ignore unresolved-reference: walrus operator false positives in ty.
cmd = """
ty check
src/bcf
src/bsdd
src/ifc2ca
src/ifc4d
src/ifc5d
src/ifccityjson
src/ifcclash
src/ifccsv
src/ifcdiff
src/ifcfm
src/ifcopenshell-python
src/ifcpatch
src/ifctester
--python=src/ifcopenshell-python/.venv
--ignore unresolved-reference
"""
[tool.poe.tasks.bonsai-deps]
help = "Clone or update Bonsai external dependencies."
cmd = "python src/bonsai/scripts/bonsai_deps.py"
+3 -2
View File
@@ -1,7 +1,8 @@
from dataclasses import fields
from typing import NamedTuple, Union
import bcf.v2.model.extensions import bcf.v2.model.extensions
import bcf.v3.model.extensions import bcf.v3.model.extensions
from typing import NamedTuple, Union
from dataclasses import fields
class AttributeData(NamedTuple): class AttributeData(NamedTuple):
+2 -1
View File
@@ -1,6 +1,7 @@
from typing import Union
import bcf.v2.model import bcf.v2.model
import bcf.v3.model import bcf.v3.model
from typing import Union
BimSnippet = Union[bcf.v2.model.BimSnippet, bcf.v3.model.BimSnippet] BimSnippet = Union[bcf.v2.model.BimSnippet, bcf.v3.model.BimSnippet]
BitMap = Union[bcf.v2.model.VisualizationInfoBitmap, bcf.v3.model.Bitmap] BitMap = Union[bcf.v2.model.VisualizationInfoBitmap, bcf.v3.model.Bitmap]
+6 -4
View File
@@ -1,14 +1,16 @@
import tempfile import tempfile
from pathlib import Path
from typing import Optional, Union
from typing_extensions import assert_never
import bcf.agnostic.model as mdl
import bcf.v2.bcfxml import bcf.v2.bcfxml
import bcf.v2.model import bcf.v2.model
import bcf.v2.topic import bcf.v2.topic
import bcf.v3.bcfxml import bcf.v3.bcfxml
import bcf.v3.model import bcf.v3.model
import bcf.v3.topic import bcf.v3.topic
import bcf.agnostic.model as mdl
from pathlib import Path
from typing import Union, Optional
from typing_extensions import assert_never
TopicHandler = Union[bcf.v2.topic.TopicHandler, bcf.v3.topic.TopicHandler] TopicHandler = Union[bcf.v2.topic.TopicHandler, bcf.v3.topic.TopicHandler]
+3 -2
View File
@@ -1,5 +1,6 @@
import bcf.v2.visinfo
import bcf.v3.visinfo
from typing import Union from typing import Union
import bcf.v2.visinfo
import bcf.v3.visinfo
VisualizationInfoHandler = Union[bcf.v2.visinfo.VisualizationInfoHandler, bcf.v3.visinfo.VisualizationInfoHandler] VisualizationInfoHandler = Union[bcf.v2.visinfo.VisualizationInfoHandler, bcf.v3.visinfo.VisualizationInfoHandler]
-1
View File
@@ -29,7 +29,6 @@ from bcf.v3.bcfxml import BcfXml as BcfXml3
from bcf.v3.model import Version as Version3 from bcf.v3.model import Version as Version3
from bcf.xml_parser import AbstractXmlParserSerializer, XmlParserSerializer from bcf.xml_parser import AbstractXmlParserSerializer, XmlParserSerializer
BcfXml = Union[BcfXml2, BcfXml3] BcfXml = Union[BcfXml2, BcfXml3]
+2 -1
View File
@@ -7,6 +7,7 @@ original idea from https://stackoverflow.com/a/19722365/1307905
""" """
from __future__ import annotations from __future__ import annotations
import zipfile import zipfile
from io import BytesIO from io import BytesIO
from os import PathLike from os import PathLike
@@ -26,7 +27,7 @@ class InMemoryZipFile:
self._file_name: Optional[str | Path] = str(file_name) if hasattr(file_name, "_from_parts") else file_name self._file_name: Optional[str | Path] = str(file_name) if hasattr(file_name, "_from_parts") else file_name
self.in_memory_data = BytesIO() self.in_memory_data = BytesIO()
# Create the in-memory zipfile # Create the in-memory zipfile
self.in_memory_zip = zipfile.ZipFile(self.in_memory_data, "w", compression, False) self.in_memory_zip = zipfile.ZipFile(self.in_memory_data, "w", compression, True)
self.in_memory_zip.debug = debug self.in_memory_zip.debug = debug
def writestr(self, filename_in_zip: str | zipfile.ZipInfo, file_contents: bytes | str) -> None: def writestr(self, filename_in_zip: str | zipfile.ZipInfo, file_contents: bytes | str) -> None:
+1
View File
@@ -1,6 +1,7 @@
"""BCF XML V2 handler.""" """BCF XML V2 handler."""
from __future__ import annotations from __future__ import annotations
import uuid import uuid
import warnings import warnings
import zipfile import zipfile
+9 -13
View File
@@ -14,15 +14,11 @@
# Currently extensions support for v2 is only read-only. # Currently extensions support for v2 is only read-only.
import sys from dataclasses import dataclass, field
from dataclasses import dataclass, field, fields
from typing import Optional from typing import Optional
DATACLASS_KWARGS = {} if sys.version_info < (3, 10) else {"slots": True, "kw_only": True} @dataclass(slots=True, kw_only=True)
@dataclass(**DATACLASS_KWARGS)
class ExtensionsPriorities: class ExtensionsPriorities:
class Meta: class Meta:
global_type = False global_type = False
@@ -39,7 +35,7 @@ class ExtensionsPriorities:
) )
@dataclass(**DATACLASS_KWARGS) @dataclass(slots=True, kw_only=True)
class ExtensionsSnippetTypes: class ExtensionsSnippetTypes:
class Meta: class Meta:
global_type = False global_type = False
@@ -56,7 +52,7 @@ class ExtensionsSnippetTypes:
) )
@dataclass(**DATACLASS_KWARGS) @dataclass(slots=True, kw_only=True)
class ExtensionsStages: class ExtensionsStages:
class Meta: class Meta:
global_type = False global_type = False
@@ -73,7 +69,7 @@ class ExtensionsStages:
) )
@dataclass(**DATACLASS_KWARGS) @dataclass(slots=True, kw_only=True)
class ExtensionsTopicLabels: class ExtensionsTopicLabels:
class Meta: class Meta:
global_type = False global_type = False
@@ -90,7 +86,7 @@ class ExtensionsTopicLabels:
) )
@dataclass(**DATACLASS_KWARGS) @dataclass(slots=True, kw_only=True)
class ExtensionsTopicStatuses: class ExtensionsTopicStatuses:
class Meta: class Meta:
global_type = False global_type = False
@@ -107,7 +103,7 @@ class ExtensionsTopicStatuses:
) )
@dataclass(**DATACLASS_KWARGS) @dataclass(slots=True, kw_only=True)
class ExtensionsTopicTypes: class ExtensionsTopicTypes:
class Meta: class Meta:
global_type = False global_type = False
@@ -124,7 +120,7 @@ class ExtensionsTopicTypes:
) )
@dataclass(**DATACLASS_KWARGS) @dataclass(slots=True, kw_only=True)
class ExtensionsUsers: class ExtensionsUsers:
class Meta: class Meta:
global_type = False global_type = False
@@ -141,7 +137,7 @@ class ExtensionsUsers:
) )
@dataclass(**DATACLASS_KWARGS) @dataclass(slots=True, kw_only=True)
class Extensions: class Extensions:
topic_types: Optional[ExtensionsTopicTypes] = field( topic_types: Optional[ExtensionsTopicTypes] = field(
default=None, default=None,
+10 -13
View File
@@ -1,13 +1,10 @@
import sys
from dataclasses import dataclass, field from dataclasses import dataclass, field
from typing import Optional from typing import Optional
from xsdata.models.datatype import XmlDateTime from xsdata.models.datatype import XmlDateTime
DATACLASS_KWARGS = {} if sys.version_info < (3, 10) else {"slots": True, "kw_only": True}
@dataclass(slots=True, kw_only=True)
@dataclass(**DATACLASS_KWARGS)
class BimSnippet: class BimSnippet:
reference: str = field( reference: str = field(
metadata={ metadata={
@@ -41,7 +38,7 @@ class BimSnippet:
) )
@dataclass(**DATACLASS_KWARGS) @dataclass(slots=True, kw_only=True)
class CommentViewpoint: class CommentViewpoint:
class Meta: class Meta:
global_type = False global_type = False
@@ -56,7 +53,7 @@ class CommentViewpoint:
) )
@dataclass(**DATACLASS_KWARGS) @dataclass(slots=True, kw_only=True)
class HeaderFile: class HeaderFile:
class Meta: class Meta:
global_type = False global_type = False
@@ -112,7 +109,7 @@ class HeaderFile:
) )
@dataclass(**DATACLASS_KWARGS) @dataclass(slots=True, kw_only=True)
class TopicDocumentReference: class TopicDocumentReference:
class Meta: class Meta:
global_type = False global_type = False
@@ -150,7 +147,7 @@ class TopicDocumentReference:
) )
@dataclass(**DATACLASS_KWARGS) @dataclass(slots=True, kw_only=True)
class TopicRelatedTopic: class TopicRelatedTopic:
class Meta: class Meta:
global_type = False global_type = False
@@ -165,7 +162,7 @@ class TopicRelatedTopic:
) )
@dataclass(**DATACLASS_KWARGS) @dataclass(slots=True, kw_only=True)
class ViewPoint: class ViewPoint:
viewpoint: Optional[str] = field( viewpoint: Optional[str] = field(
default=None, default=None,
@@ -201,7 +198,7 @@ class ViewPoint:
) )
@dataclass(**DATACLASS_KWARGS) @dataclass(slots=True, kw_only=True)
class Comment: class Comment:
date: XmlDateTime = field( date: XmlDateTime = field(
metadata={ metadata={
@@ -261,7 +258,7 @@ class Comment:
) )
@dataclass(**DATACLASS_KWARGS) @dataclass(slots=True, kw_only=True)
class Header: class Header:
file: list[HeaderFile] = field( file: list[HeaderFile] = field(
default_factory=list, default_factory=list,
@@ -274,7 +271,7 @@ class Header:
) )
@dataclass(**DATACLASS_KWARGS) @dataclass(slots=True, kw_only=True)
class Topic: class Topic:
reference_link: list[str] = field( reference_link: list[str] = field(
default_factory=list, default_factory=list,
@@ -428,7 +425,7 @@ class Topic:
) )
@dataclass(**DATACLASS_KWARGS) @dataclass(slots=True, kw_only=True)
class Markup: class Markup:
header: Optional[Header] = field( header: Optional[Header] = field(
default=None, default=None,
+2 -5
View File
@@ -1,11 +1,8 @@
import sys
from dataclasses import dataclass, field from dataclasses import dataclass, field
from typing import Optional from typing import Optional
DATACLASS_KWARGS = {} if sys.version_info < (3, 10) else {"slots": True, "kw_only": True}
@dataclass(slots=True, kw_only=True)
@dataclass(**DATACLASS_KWARGS)
class Project: class Project:
name: Optional[str] = field( name: Optional[str] = field(
default=None, default=None,
@@ -24,7 +21,7 @@ class Project:
) )
@dataclass(**DATACLASS_KWARGS) @dataclass(slots=True, kw_only=True)
class ProjectExtension: class ProjectExtension:
project: Optional[Project] = field( project: Optional[Project] = field(
default=None, default=None,
+1 -4
View File
@@ -1,11 +1,8 @@
import sys
from dataclasses import dataclass, field from dataclasses import dataclass, field
from typing import Optional from typing import Optional
DATACLASS_KWARGS = {} if sys.version_info < (3, 10) else {"slots": True, "kw_only": True}
@dataclass(slots=True, kw_only=True)
@dataclass(**DATACLASS_KWARGS)
class Version: class Version:
detailed_version: Optional[str] = field( detailed_version: Optional[str] = field(
default=None, default=None,
+18 -21
View File
@@ -1,17 +1,14 @@
import sys
from dataclasses import dataclass, field from dataclasses import dataclass, field
from enum import Enum from enum import Enum
from typing import Optional from typing import Optional
DATACLASS_KWARGS = {} if sys.version_info < (3, 10) else {"slots": True, "kw_only": True}
class BitmapFormat(Enum): class BitmapFormat(Enum):
PNG = "PNG" PNG = "PNG"
JPG = "JPG" JPG = "JPG"
@dataclass(**DATACLASS_KWARGS) @dataclass(slots=True, kw_only=True)
class Component: class Component:
originating_system: Optional[str] = field( originating_system: Optional[str] = field(
default=None, default=None,
@@ -38,7 +35,7 @@ class Component:
) )
@dataclass(**DATACLASS_KWARGS) @dataclass(slots=True, kw_only=True)
class Direction: class Direction:
x: float = field( x: float = field(
metadata={ metadata={
@@ -63,7 +60,7 @@ class Direction:
) )
@dataclass(**DATACLASS_KWARGS) @dataclass(slots=True, kw_only=True)
class Point: class Point:
x: float = field( x: float = field(
metadata={ metadata={
@@ -88,7 +85,7 @@ class Point:
) )
@dataclass(**DATACLASS_KWARGS) @dataclass(slots=True, kw_only=True)
class ViewSetupHints: class ViewSetupHints:
spaces_visible: Optional[bool] = field( spaces_visible: Optional[bool] = field(
default=None, default=None,
@@ -113,7 +110,7 @@ class ViewSetupHints:
) )
@dataclass(**DATACLASS_KWARGS) @dataclass(slots=True, kw_only=True)
class ClippingPlane: class ClippingPlane:
location: Point = field( location: Point = field(
metadata={ metadata={
@@ -131,7 +128,7 @@ class ClippingPlane:
) )
@dataclass(**DATACLASS_KWARGS) @dataclass(slots=True, kw_only=True)
class ComponentColoringColor: class ComponentColoringColor:
class Meta: class Meta:
global_type = False global_type = False
@@ -154,7 +151,7 @@ class ComponentColoringColor:
) )
@dataclass(**DATACLASS_KWARGS) @dataclass(slots=True, kw_only=True)
class ComponentSelection: class ComponentSelection:
component: list[Component] = field( component: list[Component] = field(
default_factory=list, default_factory=list,
@@ -166,7 +163,7 @@ class ComponentSelection:
) )
@dataclass(**DATACLASS_KWARGS) @dataclass(slots=True, kw_only=True)
class ComponentVisibilityExceptions: class ComponentVisibilityExceptions:
class Meta: class Meta:
global_type = False global_type = False
@@ -181,7 +178,7 @@ class ComponentVisibilityExceptions:
) )
@dataclass(**DATACLASS_KWARGS) @dataclass(slots=True, kw_only=True)
class Line: class Line:
start_point: Point = field( start_point: Point = field(
metadata={ metadata={
@@ -199,7 +196,7 @@ class Line:
) )
@dataclass(**DATACLASS_KWARGS) @dataclass(slots=True, kw_only=True)
class OrthogonalCamera: class OrthogonalCamera:
""" """
Attributes Attributes
@@ -239,7 +236,7 @@ class OrthogonalCamera:
) )
@dataclass(**DATACLASS_KWARGS) @dataclass(slots=True, kw_only=True)
class PerspectiveCamera: class PerspectiveCamera:
""" """
Attributes Attributes
@@ -284,7 +281,7 @@ class PerspectiveCamera:
) )
@dataclass(**DATACLASS_KWARGS) @dataclass(slots=True, kw_only=True)
class VisualizationInfoBitmap: class VisualizationInfoBitmap:
class Meta: class Meta:
global_type = False global_type = False
@@ -333,7 +330,7 @@ class VisualizationInfoBitmap:
) )
@dataclass(**DATACLASS_KWARGS) @dataclass(slots=True, kw_only=True)
class ComponentColoring: class ComponentColoring:
color: list[ComponentColoringColor] = field( color: list[ComponentColoringColor] = field(
default_factory=list, default_factory=list,
@@ -345,7 +342,7 @@ class ComponentColoring:
) )
@dataclass(**DATACLASS_KWARGS) @dataclass(slots=True, kw_only=True)
class ComponentVisibility: class ComponentVisibility:
exceptions: Optional[ComponentVisibilityExceptions] = field( exceptions: Optional[ComponentVisibilityExceptions] = field(
default=None, default=None,
@@ -363,7 +360,7 @@ class ComponentVisibility:
) )
@dataclass(**DATACLASS_KWARGS) @dataclass(slots=True, kw_only=True)
class VisualizationInfoClippingPlanes: class VisualizationInfoClippingPlanes:
class Meta: class Meta:
global_type = False global_type = False
@@ -377,7 +374,7 @@ class VisualizationInfoClippingPlanes:
) )
@dataclass(**DATACLASS_KWARGS) @dataclass(slots=True, kw_only=True)
class VisualizationInfoLines: class VisualizationInfoLines:
class Meta: class Meta:
global_type = False global_type = False
@@ -392,7 +389,7 @@ class VisualizationInfoLines:
) )
@dataclass(**DATACLASS_KWARGS) @dataclass(slots=True, kw_only=True)
class Components: class Components:
view_setup_hints: Optional[ViewSetupHints] = field( view_setup_hints: Optional[ViewSetupHints] = field(
default=None, default=None,
@@ -424,7 +421,7 @@ class Components:
) )
@dataclass(**DATACLASS_KWARGS) @dataclass(slots=True, kw_only=True)
class VisualizationInfo: class VisualizationInfo:
""" """
VisualizationInfo documentation. VisualizationInfo documentation.
+2 -2
View File
@@ -1,12 +1,12 @@
"""BCF XML V2 Topic handler.""" """BCF XML V2 Topic handler."""
from __future__ import annotations from __future__ import annotations
import datetime import datetime
import tempfile
import uuid import uuid
import zipfile import zipfile
from pathlib import Path from pathlib import Path
from typing import Any, NoReturn, Optional, Union from typing import Any, NoReturn, Optional
import numpy as np import numpy as np
from ifcopenshell import entity_instance from ifcopenshell import entity_instance
+3 -3
View File
@@ -1,12 +1,12 @@
import uuid import uuid
import zipfile import zipfile
from typing import Any, Optional, Literal, Union
from collections.abc import Iterable from collections.abc import Iterable
from typing import Literal, Optional, Union
import ifcopenshell.util.placement
import ifcopenshell.util.unit
import numpy as np import numpy as np
from ifcopenshell import entity_instance from ifcopenshell import entity_instance
import ifcopenshell.util.unit
import ifcopenshell.util.placement
from numpy.typing import NDArray from numpy.typing import NDArray
import bcf.v2.model as mdl import bcf.v2.model as mdl
+3 -4
View File
@@ -24,7 +24,6 @@ import time
import urllib.parse import urllib.parse
import uuid import uuid
import webbrowser import webbrowser
from re import A
from typing import Any, Optional from typing import Any, Optional
import requests import requests
@@ -35,8 +34,8 @@ client_id, client_secret = "", ""
class OAuthReceiver(http.server.BaseHTTPRequestHandler): class OAuthReceiver(http.server.BaseHTTPRequestHandler):
def do_GET(self) -> None: def do_GET(self) -> None:
query = urllib.parse.parse_qs(urllib.parse.urlparse(self.path).query) query = urllib.parse.parse_qs(urllib.parse.urlparse(self.path).query)
self.server.auth_code = query.get("code", [""])[0] # type:ignore self.server.auth_code = query.get("code", [""])[0]
self.server.auth_state = query.get("state", [""])[0] # type:ignore self.server.auth_state = query.get("state", [""])[0]
self.send_response(200) self.send_response(200)
self.send_header("Content-type", "text/plain") self.send_header("Content-type", "text/plain")
self.end_headers() self.end_headers()
@@ -256,7 +255,7 @@ class BcfClient:
project_id: str = "", project_id: str = "",
topics: str = "", topics: str = "",
query_string: Optional[str] = None, query_string: Optional[str] = None,
) -> list[Any]: ) -> None:
# return self.get( # return self.get(
# f"/projects/{project_id}/topics", # f"/projects/{project_id}/topics",
# { # {
+1
View File
@@ -1,6 +1,7 @@
"""BCF XML V3 handlers.""" """BCF XML V3 handlers."""
from __future__ import annotations from __future__ import annotations
import uuid import uuid
import warnings import warnings
import zipfile import zipfile
+1 -1
View File
@@ -1,7 +1,7 @@
"""BCF XML V3 Documents handler.""" """BCF XML V3 Documents handler."""
import zipfile import zipfile
from typing import Any, Optional from typing import Optional
import bcf.v3.model as mdl import bcf.v3.model as mdl
from bcf.inmemory_zipfile import ZipFileInterface from bcf.inmemory_zipfile import ZipFileInterface

Some files were not shown because too many files have changed in this diff Show More