neroued-3mf 0.2.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- neroued_3mf-0.2.0/.clang-format +17 -0
- neroued_3mf-0.2.0/.cursor/hooks/block-dangerous.sh +52 -0
- neroued_3mf-0.2.0/.cursor/hooks/check-docs-sync.sh +45 -0
- neroued_3mf-0.2.0/.cursor/hooks/format-cpp.sh +18 -0
- neroued_3mf-0.2.0/.cursor/hooks/protect-secrets.sh +43 -0
- neroued_3mf-0.2.0/.cursor/hooks.json +29 -0
- neroued_3mf-0.2.0/.cursor/rules/code-structure.mdc +25 -0
- neroued_3mf-0.2.0/.cursor/rules/cpp-formatting.mdc +17 -0
- neroued_3mf-0.2.0/.cursor/rules/cross-platform-cpp.mdc +27 -0
- neroued_3mf-0.2.0/.cursor/rules/git-policy.mdc +11 -0
- neroued_3mf-0.2.0/.cursor/rules/sync-docs.mdc +17 -0
- neroued_3mf-0.2.0/.github/workflows/ci.yml +230 -0
- neroued_3mf-0.2.0/.github/workflows/wheels.yml +158 -0
- neroued_3mf-0.2.0/.gitignore +42 -0
- neroued_3mf-0.2.0/AGENTS.md +130 -0
- neroued_3mf-0.2.0/CMakeLists.txt +127 -0
- neroued_3mf-0.2.0/COMMERCIAL_LICENSE.md +20 -0
- neroued_3mf-0.2.0/LICENSE +661 -0
- neroued_3mf-0.2.0/PKG-INFO +24 -0
- neroued_3mf-0.2.0/README.md +115 -0
- neroued_3mf-0.2.0/cmake/neroued_3mf-config.cmake.in +4 -0
- neroued_3mf-0.2.0/docs/API.md +126 -0
- neroued_3mf-0.2.0/docs/BUILDING.md +143 -0
- neroued_3mf-0.2.0/docs/DESIGN.md +456 -0
- neroued_3mf-0.2.0/docs/EXAMPLES.md +214 -0
- neroued_3mf-0.2.0/include/neroued/3mf/builder.h +96 -0
- neroued_3mf-0.2.0/include/neroued/3mf/document.h +124 -0
- neroued_3mf-0.2.0/include/neroued/3mf/error.h +26 -0
- neroued_3mf-0.2.0/include/neroued/3mf/fwd.h +45 -0
- neroued_3mf-0.2.0/include/neroued/3mf/materials.h +27 -0
- neroued_3mf-0.2.0/include/neroued/3mf/neroued_3mf.h +16 -0
- neroued_3mf-0.2.0/include/neroued/3mf/types.h +107 -0
- neroued_3mf-0.2.0/include/neroued/3mf/version.h.in +11 -0
- neroued_3mf-0.2.0/include/neroued/3mf/writer.h +43 -0
- neroued_3mf-0.2.0/pyproject.toml +76 -0
- neroued_3mf-0.2.0/python/CMakeLists.txt +28 -0
- neroued_3mf-0.2.0/python/neroued_3mf/__init__.py +70 -0
- neroued_3mf-0.2.0/python/neroued_3mf/py.typed +0 -0
- neroued_3mf-0.2.0/python/src/bind.cpp +549 -0
- neroued_3mf-0.2.0/python/tests/conftest.py +10 -0
- neroued_3mf-0.2.0/python/tests/test_basic.py +388 -0
- neroued_3mf-0.2.0/src/builder.cpp +234 -0
- neroued_3mf-0.2.0/src/internal/omp_config.h +18 -0
- neroued_3mf-0.2.0/src/internal/opc_types.h +24 -0
- neroued_3mf-0.2.0/src/internal/validate.h +163 -0
- neroued_3mf-0.2.0/src/internal/xml_stream_buffer.h +90 -0
- neroued_3mf-0.2.0/src/internal/xml_util.h +80 -0
- neroued_3mf-0.2.0/src/opc.cpp +311 -0
- neroued_3mf-0.2.0/src/opc.h +400 -0
- neroued_3mf-0.2.0/src/types.cpp +233 -0
- neroued_3mf-0.2.0/src/writer.cpp +204 -0
- neroued_3mf-0.2.0/src/zip.cpp +607 -0
- neroued_3mf-0.2.0/src/zip.h +41 -0
- neroued_3mf-0.2.0/tests/CMakeLists.txt +20 -0
- neroued_3mf-0.2.0/tests/test_builder.cpp +562 -0
- neroued_3mf-0.2.0/tests/test_types.cpp +162 -0
- neroued_3mf-0.2.0/tests/test_writer.cpp +607 -0
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
BasedOnStyle: LLVM
|
|
2
|
+
IndentWidth: 4
|
|
3
|
+
ColumnLimit: 100
|
|
4
|
+
AllowShortFunctionsOnASingleLine: Inline
|
|
5
|
+
AllowShortIfStatementsOnASingleLine: AllIfsAndElse
|
|
6
|
+
AllowShortLoopsOnASingleLine: true
|
|
7
|
+
AllowShortBlocksOnASingleLine: Always
|
|
8
|
+
BreakBeforeBraces: Attach
|
|
9
|
+
SortIncludes: CaseInsensitive
|
|
10
|
+
IncludeBlocks: Regroup
|
|
11
|
+
IncludeCategories:
|
|
12
|
+
- Regex: '^"neroued/'
|
|
13
|
+
Priority: 1
|
|
14
|
+
- Regex: '^"'
|
|
15
|
+
Priority: 2
|
|
16
|
+
- Regex: '^<'
|
|
17
|
+
Priority: 3
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# beforeShellExecution hook: block destructive commands
|
|
3
|
+
|
|
4
|
+
input=$(cat)
|
|
5
|
+
command=$(echo "$input" | python3 -c "import sys,json; print(json.load(sys.stdin).get('command',''))" 2>/dev/null)
|
|
6
|
+
|
|
7
|
+
[ -z "$command" ] && { echo '{"permission":"allow"}'; exit 0; }
|
|
8
|
+
|
|
9
|
+
deny_with() {
|
|
10
|
+
cat <<EOF
|
|
11
|
+
{"permission":"deny","user_message":"$1","agent_message":"$1 请使用更安全的替代方案。"}
|
|
12
|
+
EOF
|
|
13
|
+
exit 0
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
ask_with() {
|
|
17
|
+
cat <<EOF
|
|
18
|
+
{"permission":"ask","user_message":"$1"}
|
|
19
|
+
EOF
|
|
20
|
+
exit 0
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
# --- hard block ---
|
|
24
|
+
|
|
25
|
+
if echo "$command" | grep -qE 'rm\s+(-[^ ]*)?r[^ ]*f[^ ]*\s+/\s*$|rm\s+(-[^ ]*)?r[^ ]*f[^ ]*\s+/\*'; then
|
|
26
|
+
deny_with "已拦截:递归删除根文件系统"
|
|
27
|
+
fi
|
|
28
|
+
|
|
29
|
+
if echo "$command" | grep -qE 'git\s+push\s+.*--force.*\s+(origin\s+)?(master|main)\b|git\s+push\s+-f\s+.*\s+(origin\s+)?(master|main)\b'; then
|
|
30
|
+
deny_with "已拦截:禁止 force push 到 master/main"
|
|
31
|
+
fi
|
|
32
|
+
|
|
33
|
+
if echo "$command" | grep -qE 'mkfs\.|>\s*/dev/sd|:\(\)\{|fork\s*bomb'; then
|
|
34
|
+
deny_with "已拦截:潜在的破坏性系统命令"
|
|
35
|
+
fi
|
|
36
|
+
|
|
37
|
+
if echo "$command" | grep -qE 'dd\s+.*of=/dev/sd'; then
|
|
38
|
+
deny_with "已拦截:直接写入块设备"
|
|
39
|
+
fi
|
|
40
|
+
|
|
41
|
+
# --- ask confirmation ---
|
|
42
|
+
|
|
43
|
+
if echo "$command" | grep -qE 'git\s+reset\s+--hard'; then
|
|
44
|
+
ask_with "git reset --hard 将丢弃所有未提交的更改,是否继续?"
|
|
45
|
+
fi
|
|
46
|
+
|
|
47
|
+
if echo "$command" | grep -qE 'git\s+clean\s+-[^ ]*f'; then
|
|
48
|
+
ask_with "git clean -f 将删除未跟踪的文件,是否继续?"
|
|
49
|
+
fi
|
|
50
|
+
|
|
51
|
+
echo '{"permission":"allow"}'
|
|
52
|
+
exit 0
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# stop hook: remind to sync docs when API/build files changed but docs weren't
|
|
3
|
+
|
|
4
|
+
input=$(cat)
|
|
5
|
+
status=$(echo "$input" | python3 -c "import sys,json; print(json.load(sys.stdin).get('status',''))" 2>/dev/null)
|
|
6
|
+
|
|
7
|
+
[ "$status" != "completed" ] && { echo '{}'; exit 0; }
|
|
8
|
+
|
|
9
|
+
project_dir="${CURSOR_PROJECT_DIR:-$(pwd)}"
|
|
10
|
+
cd "$project_dir" || { echo '{}'; exit 0; }
|
|
11
|
+
|
|
12
|
+
changed=$(git diff --name-only HEAD 2>/dev/null; git diff --cached --name-only 2>/dev/null)
|
|
13
|
+
[ -z "$changed" ] && { echo '{}'; exit 0; }
|
|
14
|
+
|
|
15
|
+
needs_docs=false
|
|
16
|
+
|
|
17
|
+
if echo "$changed" | grep -qE '(include/.*\.(h|hpp))'; then
|
|
18
|
+
needs_docs=true
|
|
19
|
+
fi
|
|
20
|
+
if echo "$changed" | grep -qE '(src/.*\.(cpp|h|hpp))'; then
|
|
21
|
+
needs_docs=true
|
|
22
|
+
fi
|
|
23
|
+
if echo "$changed" | grep -qE '(CMakeLists\.txt|cmake/)'; then
|
|
24
|
+
needs_docs=true
|
|
25
|
+
fi
|
|
26
|
+
|
|
27
|
+
if [ "$needs_docs" = false ]; then
|
|
28
|
+
echo '{}'
|
|
29
|
+
exit 0
|
|
30
|
+
fi
|
|
31
|
+
|
|
32
|
+
docs_updated=false
|
|
33
|
+
if echo "$changed" | grep -qE '(^docs/|^README\.md|^AGENTS\.md)'; then
|
|
34
|
+
docs_updated=true
|
|
35
|
+
fi
|
|
36
|
+
|
|
37
|
+
if [ "$docs_updated" = false ]; then
|
|
38
|
+
cat <<'EOF'
|
|
39
|
+
{"followup_message":"检测到公共头文件、实现代码或构建配置有变更,但 docs/ 和 README.md 未同步更新。请检查是否需要更新文档(参考 .cursor/rules/sync-docs.mdc 中的触发条件)。如果本次变更不涉及用户可见 API 或构建选项,可以忽略此提醒。"}
|
|
40
|
+
EOF
|
|
41
|
+
else
|
|
42
|
+
echo '{}'
|
|
43
|
+
fi
|
|
44
|
+
|
|
45
|
+
exit 0
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# afterFileEdit hook: auto-format C++ files with clang-format
|
|
3
|
+
|
|
4
|
+
input=$(cat)
|
|
5
|
+
file_path=$(echo "$input" | python3 -c "import sys,json; print(json.load(sys.stdin).get('file_path',''))" 2>/dev/null)
|
|
6
|
+
|
|
7
|
+
[ -z "$file_path" ] && exit 0
|
|
8
|
+
[ ! -f "$file_path" ] && exit 0
|
|
9
|
+
|
|
10
|
+
case "$file_path" in
|
|
11
|
+
*.cpp|*.h|*.hpp|*.cc|*.cxx)
|
|
12
|
+
if command -v clang-format &>/dev/null; then
|
|
13
|
+
clang-format -i "$file_path" 2>/dev/null
|
|
14
|
+
fi
|
|
15
|
+
;;
|
|
16
|
+
esac
|
|
17
|
+
|
|
18
|
+
exit 0
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# beforeReadFile hook: block reading sensitive files
|
|
3
|
+
|
|
4
|
+
input=$(cat)
|
|
5
|
+
file_path=$(echo "$input" | python3 -c "import sys,json; print(json.load(sys.stdin).get('file_path',''))" 2>/dev/null)
|
|
6
|
+
|
|
7
|
+
[ -z "$file_path" ] && { echo '{"permission":"allow"}'; exit 0; }
|
|
8
|
+
|
|
9
|
+
filename=$(basename "$file_path")
|
|
10
|
+
|
|
11
|
+
deny_with() {
|
|
12
|
+
cat <<EOF
|
|
13
|
+
{"permission":"deny","user_message":"已阻止读取敏感文件: $filename — $1"}
|
|
14
|
+
EOF
|
|
15
|
+
exit 0
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
case "$filename" in
|
|
19
|
+
.env|.env.local|.env.production|.env.staging)
|
|
20
|
+
deny_with "环境变量文件可能包含密钥"
|
|
21
|
+
;;
|
|
22
|
+
.env.*.local)
|
|
23
|
+
deny_with "本地环境变量文件可能包含密钥"
|
|
24
|
+
;;
|
|
25
|
+
credentials.json|service-account*.json)
|
|
26
|
+
deny_with "凭据文件"
|
|
27
|
+
;;
|
|
28
|
+
id_rsa|id_ed25519|id_ecdsa|*.pem)
|
|
29
|
+
deny_with "私钥文件"
|
|
30
|
+
;;
|
|
31
|
+
.git-credentials|.netrc)
|
|
32
|
+
deny_with "Git 凭据文件"
|
|
33
|
+
;;
|
|
34
|
+
esac
|
|
35
|
+
|
|
36
|
+
case "$file_path" in
|
|
37
|
+
*/.ssh/*)
|
|
38
|
+
deny_with "SSH 目录中的文件"
|
|
39
|
+
;;
|
|
40
|
+
esac
|
|
41
|
+
|
|
42
|
+
echo '{"permission":"allow"}'
|
|
43
|
+
exit 0
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 1,
|
|
3
|
+
"hooks": {
|
|
4
|
+
"afterFileEdit": [
|
|
5
|
+
{
|
|
6
|
+
"command": ".cursor/hooks/format-cpp.sh"
|
|
7
|
+
}
|
|
8
|
+
],
|
|
9
|
+
"beforeShellExecution": [
|
|
10
|
+
{
|
|
11
|
+
"command": ".cursor/hooks/block-dangerous.sh",
|
|
12
|
+
"timeout": 5
|
|
13
|
+
}
|
|
14
|
+
],
|
|
15
|
+
"beforeReadFile": [
|
|
16
|
+
{
|
|
17
|
+
"command": ".cursor/hooks/protect-secrets.sh",
|
|
18
|
+
"timeout": 5
|
|
19
|
+
}
|
|
20
|
+
],
|
|
21
|
+
"stop": [
|
|
22
|
+
{
|
|
23
|
+
"command": ".cursor/hooks/check-docs-sync.sh",
|
|
24
|
+
"timeout": 15,
|
|
25
|
+
"loop_limit": 1
|
|
26
|
+
}
|
|
27
|
+
]
|
|
28
|
+
}
|
|
29
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: 工具函数复用与实现结构规范
|
|
3
|
+
globs: "**/*.cpp,**/*.h"
|
|
4
|
+
alwaysApply: true
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# 工具函数复用与实现结构
|
|
8
|
+
|
|
9
|
+
## 工具函数复用
|
|
10
|
+
|
|
11
|
+
- 禁止重复编写语义相同的工具函数。
|
|
12
|
+
- 新增工具函数前,先检索项目内是否已有可复用实现。
|
|
13
|
+
- 跨模块复用的函数应放入 `src/internal/` 目录下的内部头文件。
|
|
14
|
+
- 仅当前文件使用的工具函数应保留为匿名命名空间局部实现。
|
|
15
|
+
|
|
16
|
+
## .cpp 文件结构
|
|
17
|
+
|
|
18
|
+
- 避免在 .cpp 内做非必要前向声明;优先通过合理的函数定义顺序解决依赖。
|
|
19
|
+
- 实现文件应按"工具函数 → 核心流程 → 对外接口"组织。
|
|
20
|
+
|
|
21
|
+
## 命名空间约定
|
|
22
|
+
|
|
23
|
+
- 公共 API 使用 `neroued_3mf` 命名空间。
|
|
24
|
+
- 内部实现使用 `neroued_3mf::detail` 命名空间。
|
|
25
|
+
- 公共头文件位于 `include/neroued/3mf/`,内部头文件位于 `src/` 及 `src/internal/`。
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: C++ 代码格式化规范
|
|
3
|
+
globs: "**/*.cpp,**/*.h,**/*.hpp,**/*.cc,**/*.cxx"
|
|
4
|
+
alwaysApply: true
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# C++ 代码格式化
|
|
8
|
+
|
|
9
|
+
每次修改 `.cpp`、`.h`、`.hpp`、`.cc`、`.cxx` 文件后,必须使用项目根目录的 `.clang-format` 配置对修改的文件运行格式化:
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
clang-format -i <modified-files>
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
- 仅对本次修改过的文件执行,不要全量格式化
|
|
16
|
+
- 在所有编辑完成后统一执行一次即可,无需每次编辑后都执行
|
|
17
|
+
- 格式化风格基于 LLVM,缩进 4 空格,列宽限制 100
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: C++ 跨平台编译规范
|
|
3
|
+
globs: "**/*.cpp,**/*.h,**/*.hpp,**/CMakeLists.txt,**/*.cmake"
|
|
4
|
+
alwaysApply: false
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# C++ 跨平台编译规范
|
|
8
|
+
|
|
9
|
+
## 文件系统路径
|
|
10
|
+
|
|
11
|
+
禁止硬编码 POSIX 路径,一律使用 `std::filesystem`(C++17)。
|
|
12
|
+
|
|
13
|
+
## 随机数 / ID 生成
|
|
14
|
+
|
|
15
|
+
禁止直接读取 `/dev/urandom`,使用 `std::random_device`。
|
|
16
|
+
|
|
17
|
+
## CMake 外部库链接
|
|
18
|
+
|
|
19
|
+
禁止硬编码 Linux 特有的库名,使用 find_package 或条件分支。
|
|
20
|
+
|
|
21
|
+
## 平台宏判断
|
|
22
|
+
|
|
23
|
+
需要平台差异时,使用标准宏:`_WIN32`、`__APPLE__`。
|
|
24
|
+
|
|
25
|
+
## 变更检查
|
|
26
|
+
|
|
27
|
+
每次新增系统调用或文件操作时,必须确认跨平台兼容性。
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: 文档同步规范
|
|
3
|
+
globs: "**/*"
|
|
4
|
+
alwaysApply: true
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# 文档同步
|
|
8
|
+
|
|
9
|
+
当修改涉及以下内容时,检查对应文档是否需要同步更新:
|
|
10
|
+
|
|
11
|
+
- 公共 API 变更(头文件增删、函数签名变化)→ `docs/API.md`、`AGENTS.md`
|
|
12
|
+
- Document 模型变更(字段增删、校验规则变化)→ `docs/DESIGN.md`
|
|
13
|
+
- 配置参数增删(WriteOptions 等)→ `docs/BUILDING.md`
|
|
14
|
+
- 构建选项变化(CMake 选项、依赖变化)→ `docs/BUILDING.md`
|
|
15
|
+
- 用法示例变更 → `docs/EXAMPLES.md`
|
|
16
|
+
- 仓库结构变化(新增/删除/重命名文件或目录)→ `AGENTS.md`
|
|
17
|
+
- 核心亮点或定位变更 → `README.md`
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [master]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [master]
|
|
8
|
+
workflow_dispatch:
|
|
9
|
+
|
|
10
|
+
concurrency:
|
|
11
|
+
group: ci-${{ github.event.pull_request.number || github.sha }}
|
|
12
|
+
cancel-in-progress: true
|
|
13
|
+
|
|
14
|
+
env:
|
|
15
|
+
WIN_VCPKG_ROOT: C:/vcpkg
|
|
16
|
+
WIN_VCPKG_TRIPLET: x64-windows
|
|
17
|
+
|
|
18
|
+
jobs:
|
|
19
|
+
# ── C++ format check (changed files only) ─────────────────────────────────
|
|
20
|
+
format-check:
|
|
21
|
+
name: clang-format
|
|
22
|
+
runs-on: ubuntu-latest
|
|
23
|
+
if: github.event_name == 'pull_request'
|
|
24
|
+
steps:
|
|
25
|
+
- uses: actions/checkout@v4
|
|
26
|
+
with:
|
|
27
|
+
fetch-depth: 0
|
|
28
|
+
|
|
29
|
+
- name: Install clang-format-18
|
|
30
|
+
run: |
|
|
31
|
+
sudo apt-get update
|
|
32
|
+
sudo apt-get install -y --no-install-recommends clang-format-18
|
|
33
|
+
|
|
34
|
+
- name: Check formatting of changed files
|
|
35
|
+
run: |
|
|
36
|
+
BASE="${{ github.event.pull_request.base.sha }}"
|
|
37
|
+
FILES=$(git diff --name-only --diff-filter=ACM "$BASE" HEAD \
|
|
38
|
+
| grep -E '\.(cpp|h|hpp|cc|cxx)$' \
|
|
39
|
+
| grep -E '^(src|include|python|tests)/' || true)
|
|
40
|
+
|
|
41
|
+
if [ -z "$FILES" ]; then
|
|
42
|
+
echo "No C++ files changed, skipping."
|
|
43
|
+
exit 0
|
|
44
|
+
fi
|
|
45
|
+
|
|
46
|
+
echo "Checking formatting for:"
|
|
47
|
+
echo "$FILES"
|
|
48
|
+
FAILED=0
|
|
49
|
+
for f in $FILES; do
|
|
50
|
+
if ! clang-format-18 --dry-run --Werror "$f" 2>/dev/null; then
|
|
51
|
+
echo "::error file=$f::Format mismatch. Run: clang-format -i $f"
|
|
52
|
+
FAILED=1
|
|
53
|
+
fi
|
|
54
|
+
done
|
|
55
|
+
|
|
56
|
+
if [ "$FAILED" -eq 1 ]; then
|
|
57
|
+
echo "::error::Some files need formatting."
|
|
58
|
+
exit 1
|
|
59
|
+
fi
|
|
60
|
+
echo "All changed C++ files are correctly formatted."
|
|
61
|
+
|
|
62
|
+
# ── C++ build & test ──────────────────────────────────────────────────────
|
|
63
|
+
cpp-build:
|
|
64
|
+
name: C++ (${{ matrix.os }})
|
|
65
|
+
runs-on: ${{ matrix.os }}
|
|
66
|
+
strategy:
|
|
67
|
+
fail-fast: false
|
|
68
|
+
matrix:
|
|
69
|
+
os: [ubuntu-22.04, macos-14, windows-latest]
|
|
70
|
+
|
|
71
|
+
steps:
|
|
72
|
+
- uses: actions/checkout@v4
|
|
73
|
+
|
|
74
|
+
# ── Linux ─────────────────────────────────────────────────────────────
|
|
75
|
+
- name: Install dependencies (Linux)
|
|
76
|
+
if: runner.os == 'Linux'
|
|
77
|
+
run: |
|
|
78
|
+
sudo apt-get update
|
|
79
|
+
sudo apt-get install -y --no-install-recommends zlib1g-dev ninja-build ccache
|
|
80
|
+
mkdir -p ~/.cache/ccache
|
|
81
|
+
|
|
82
|
+
- name: Cache ccache (Linux)
|
|
83
|
+
if: runner.os == 'Linux'
|
|
84
|
+
uses: actions/cache@v4
|
|
85
|
+
with:
|
|
86
|
+
path: ~/.cache/ccache
|
|
87
|
+
key: ccache-linux-${{ hashFiles('CMakeLists.txt') }}
|
|
88
|
+
restore-keys: ccache-linux-
|
|
89
|
+
|
|
90
|
+
- name: Configure (Linux)
|
|
91
|
+
if: runner.os == 'Linux'
|
|
92
|
+
env:
|
|
93
|
+
CMAKE_C_COMPILER_LAUNCHER: ccache
|
|
94
|
+
CMAKE_CXX_COMPILER_LAUNCHER: ccache
|
|
95
|
+
run: |
|
|
96
|
+
ccache --set-config=max_size=500M
|
|
97
|
+
ccache -z
|
|
98
|
+
cmake -S . -B build -G Ninja \
|
|
99
|
+
-DCMAKE_BUILD_TYPE=Release \
|
|
100
|
+
-DN3MF_BUILD_TESTS=ON
|
|
101
|
+
|
|
102
|
+
# ── macOS ─────────────────────────────────────────────────────────────
|
|
103
|
+
- name: Install dependencies (macOS)
|
|
104
|
+
if: runner.os == 'macOS'
|
|
105
|
+
run: brew install ninja ccache libomp
|
|
106
|
+
|
|
107
|
+
- name: Cache ccache (macOS)
|
|
108
|
+
if: runner.os == 'macOS'
|
|
109
|
+
uses: actions/cache@v4
|
|
110
|
+
with:
|
|
111
|
+
path: ~/Library/Caches/ccache
|
|
112
|
+
key: ccache-macos-${{ hashFiles('CMakeLists.txt') }}
|
|
113
|
+
restore-keys: ccache-macos-
|
|
114
|
+
|
|
115
|
+
- name: Configure (macOS)
|
|
116
|
+
if: runner.os == 'macOS'
|
|
117
|
+
env:
|
|
118
|
+
CMAKE_C_COMPILER_LAUNCHER: ccache
|
|
119
|
+
CMAKE_CXX_COMPILER_LAUNCHER: ccache
|
|
120
|
+
run: |
|
|
121
|
+
ccache --set-config=max_size=500M
|
|
122
|
+
ccache -z
|
|
123
|
+
cmake -S . -B build -G Ninja \
|
|
124
|
+
-DCMAKE_BUILD_TYPE=Release \
|
|
125
|
+
-DN3MF_BUILD_TESTS=ON \
|
|
126
|
+
-DOpenMP_ROOT=$(brew --prefix libomp)
|
|
127
|
+
|
|
128
|
+
# ── Windows ───────────────────────────────────────────────────────────
|
|
129
|
+
- name: Cache vcpkg packages (Windows)
|
|
130
|
+
if: runner.os == 'Windows'
|
|
131
|
+
uses: actions/cache@v4
|
|
132
|
+
with:
|
|
133
|
+
path: ${{ env.WIN_VCPKG_ROOT }}/installed
|
|
134
|
+
key: vcpkg-win-zlib-${{ runner.os }}
|
|
135
|
+
restore-keys: vcpkg-win-zlib-
|
|
136
|
+
|
|
137
|
+
- name: Install dependencies (Windows)
|
|
138
|
+
if: runner.os == 'Windows'
|
|
139
|
+
run: vcpkg install zlib:${{ env.WIN_VCPKG_TRIPLET }}
|
|
140
|
+
|
|
141
|
+
- uses: ilammy/msvc-dev-cmd@v1
|
|
142
|
+
if: runner.os == 'Windows'
|
|
143
|
+
|
|
144
|
+
- name: Configure (Windows)
|
|
145
|
+
if: runner.os == 'Windows'
|
|
146
|
+
run: >
|
|
147
|
+
cmake -S . -B build -G Ninja
|
|
148
|
+
-DCMAKE_TOOLCHAIN_FILE="${{ env.WIN_VCPKG_ROOT }}/scripts/buildsystems/vcpkg.cmake"
|
|
149
|
+
-DVCPKG_TARGET_TRIPLET=${{ env.WIN_VCPKG_TRIPLET }}
|
|
150
|
+
-DCMAKE_BUILD_TYPE=Release
|
|
151
|
+
-DN3MF_BUILD_TESTS=ON
|
|
152
|
+
|
|
153
|
+
# ── Build & test ──────────────────────────────────────────────────────
|
|
154
|
+
- name: Build
|
|
155
|
+
run: cmake --build build --config Release -j4
|
|
156
|
+
|
|
157
|
+
- name: Test
|
|
158
|
+
run: ctest --test-dir build --build-config Release --output-on-failure
|
|
159
|
+
|
|
160
|
+
- name: ccache stats
|
|
161
|
+
if: always() && runner.os != 'Windows'
|
|
162
|
+
run: ccache -s
|
|
163
|
+
|
|
164
|
+
# ── Python bindings build & test ──────────────────────────────────────────
|
|
165
|
+
python-test:
|
|
166
|
+
name: Python ${{ matrix.python-version }} (${{ matrix.os }})
|
|
167
|
+
runs-on: ${{ matrix.os }}
|
|
168
|
+
strategy:
|
|
169
|
+
fail-fast: false
|
|
170
|
+
matrix:
|
|
171
|
+
os: [ubuntu-22.04, macos-14, windows-latest]
|
|
172
|
+
python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"]
|
|
173
|
+
|
|
174
|
+
steps:
|
|
175
|
+
- uses: actions/checkout@v4
|
|
176
|
+
with:
|
|
177
|
+
fetch-depth: 0
|
|
178
|
+
|
|
179
|
+
- name: Install system dependencies (Linux)
|
|
180
|
+
if: runner.os == 'Linux'
|
|
181
|
+
run: |
|
|
182
|
+
sudo apt-get update
|
|
183
|
+
sudo apt-get install -y --no-install-recommends zlib1g-dev
|
|
184
|
+
|
|
185
|
+
- name: Install system dependencies (macOS)
|
|
186
|
+
if: runner.os == 'macOS'
|
|
187
|
+
run: brew install libomp
|
|
188
|
+
|
|
189
|
+
- name: Cache vcpkg packages (Windows)
|
|
190
|
+
if: runner.os == 'Windows'
|
|
191
|
+
uses: actions/cache@v4
|
|
192
|
+
with:
|
|
193
|
+
path: ${{ env.WIN_VCPKG_ROOT }}/installed
|
|
194
|
+
key: vcpkg-win-zlib-${{ runner.os }}
|
|
195
|
+
restore-keys: vcpkg-win-zlib-
|
|
196
|
+
|
|
197
|
+
- name: Install system dependencies (Windows)
|
|
198
|
+
if: runner.os == 'Windows'
|
|
199
|
+
run: vcpkg install zlib:${{ env.WIN_VCPKG_TRIPLET }}
|
|
200
|
+
|
|
201
|
+
- uses: ilammy/msvc-dev-cmd@v1
|
|
202
|
+
if: runner.os == 'Windows'
|
|
203
|
+
|
|
204
|
+
- uses: actions/setup-python@v5
|
|
205
|
+
with:
|
|
206
|
+
python-version: ${{ matrix.python-version }}
|
|
207
|
+
|
|
208
|
+
- name: Install package (Linux)
|
|
209
|
+
if: runner.os == 'Linux'
|
|
210
|
+
run: pip install --verbose .
|
|
211
|
+
|
|
212
|
+
- name: Install package (macOS)
|
|
213
|
+
if: runner.os == 'macOS'
|
|
214
|
+
run: |
|
|
215
|
+
export SKBUILD_CMAKE_DEFINE="OpenMP_ROOT=$(brew --prefix libomp)"
|
|
216
|
+
pip install --verbose .
|
|
217
|
+
|
|
218
|
+
- name: Install package (Windows)
|
|
219
|
+
if: runner.os == 'Windows'
|
|
220
|
+
run: pip install --verbose .
|
|
221
|
+
env:
|
|
222
|
+
CMAKE_TOOLCHAIN_FILE: ${{ env.WIN_VCPKG_ROOT }}/scripts/buildsystems/vcpkg.cmake
|
|
223
|
+
SKBUILD_CMAKE_DEFINE: "VCPKG_TARGET_TRIPLET=${{ env.WIN_VCPKG_TRIPLET }}"
|
|
224
|
+
|
|
225
|
+
- name: Run tests
|
|
226
|
+
run: |
|
|
227
|
+
pip install pytest
|
|
228
|
+
pytest python/tests -v
|
|
229
|
+
env:
|
|
230
|
+
N3MF_DLL_DIR: ${{ runner.os == 'Windows' && format('{0}/installed/{1}/bin', env.WIN_VCPKG_ROOT, env.WIN_VCPKG_TRIPLET) || '' }}
|