diff --git a/.github/workflows/build_orca.yml b/.github/workflows/build_orca.yml index db24f4327b..a7652c3bd6 100644 --- a/.github/workflows/build_orca.yml +++ b/.github/workflows/build_orca.yml @@ -221,15 +221,41 @@ jobs: security import $CERTIFICATE_PATH -P $P12_PASSWORD -A -t cert -f pkcs12 -k $KEYCHAIN_PATH security list-keychain -d user -s $KEYCHAIN_PATH security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k $P12_PASSWORD $KEYCHAIN_PATH - codesign --deep --force --verbose --options runtime --timestamp --entitlements ${{ github.workspace }}/scripts/disable_validation.entitlements --sign "$CERTIFICATE_ID" ${{ github.workspace }}/build/universal/OrcaSlicer/OrcaSlicer.app - # --deep is deprecated and signing/sealing can fail or skip files in - # non-standard layouts (python/bin, python/lib/**, tools/uv). Verify - # here so coverage gaps fail at CI time rather than at notarization. - codesign --verify --deep --strict --verbose=2 ${{ github.workspace }}/build/universal/OrcaSlicer/OrcaSlicer.app + # codesign --deep is deprecated and cannot sign the bundled Python + # runtime (see relocate_python_runtime in build_release_macos.sh). + # Sign every nested Mach-O in the bundle explicitly -- notarization + # requires the hardened-runtime signature on each -- then seal the + # bundle itself last, and verify so coverage gaps fail at CI time + # rather than at notarization. + ENTITLEMENTS=${{ github.workspace }}/scripts/disable_validation.entitlements + sign() { + codesign --force --options runtime --timestamp --entitlements "$ENTITLEMENTS" --sign "$CERTIFICATE_ID" "$@" + } + sign_app() { + local app="$1" + local machos=() + # file is batched via xargs (per-file it costs minutes); universal + # binaries also print per-architecture lines, dropped by grep -v. + while IFS= read -r f; do machos+=("$f"); done < <( + find "$app" -type f -print0 | + xargs -0 file --no-pad --mime-type -- | + grep -v ' (for architecture ' | + grep ': application/x-mach-binary$' | + sed 's|: application/x-mach-binary$||' + ) + if [ "${#machos[@]}" -eq 0 ]; then + echo "ERROR: no Mach-O files found in $app -- detection is broken" >&2 + exit 1 + fi + echo "signing ${#machos[@]} Mach-O files in $app" + sign "${machos[@]}" + sign --verbose "$app" + codesign --verify --deep --strict --verbose=2 "$app" + } + sign_app "${{ github.workspace }}/build/universal/OrcaSlicer/OrcaSlicer.app" # Sign OrcaSlicer_profile_validator.app if it exists if [ -f "${{ github.workspace }}/build/universal/OrcaSlicer/OrcaSlicer_profile_validator.app/Contents/MacOS/OrcaSlicer_profile_validator" ]; then - codesign --deep --force --verbose --options runtime --timestamp --entitlements ${{ github.workspace }}/scripts/disable_validation.entitlements --sign "$CERTIFICATE_ID" ${{ github.workspace }}/build/universal/OrcaSlicer/OrcaSlicer_profile_validator.app - codesign --verify --deep --strict --verbose=2 ${{ github.workspace }}/build/universal/OrcaSlicer/OrcaSlicer_profile_validator.app + sign_app "${{ github.workspace }}/build/universal/OrcaSlicer/OrcaSlicer_profile_validator.app" fi # Create main OrcaSlicer DMG without the profile validator helper @@ -238,7 +264,7 @@ jobs: cp -R ${{ github.workspace }}/build/universal/OrcaSlicer/OrcaSlicer.app ${{ github.workspace }}/build/universal/OrcaSlicer_dmg/ ln -sfn /Applications ${{ github.workspace }}/build/universal/OrcaSlicer_dmg/Applications retry hdiutil create -volname "OrcaSlicer" -srcfolder ${{ github.workspace }}/build/universal/OrcaSlicer_dmg -ov -format UDZO OrcaSlicer_Mac_universal_${{ env.ver }}.dmg - codesign --deep --force --verbose --options runtime --timestamp --entitlements ${{ github.workspace }}/scripts/disable_validation.entitlements --sign "$CERTIFICATE_ID" OrcaSlicer_Mac_universal_${{ env.ver }}.dmg + codesign --deep --force --verbose --options runtime --timestamp --entitlements "$ENTITLEMENTS" --sign "$CERTIFICATE_ID" OrcaSlicer_Mac_universal_${{ env.ver }}.dmg # Create separate OrcaSlicer_profile_validator DMG if the app exists if [ -f "${{ github.workspace }}/build/universal/OrcaSlicer/OrcaSlicer_profile_validator.app/Contents/MacOS/OrcaSlicer_profile_validator" ]; then @@ -247,7 +273,7 @@ jobs: cp -R ${{ github.workspace }}/build/universal/OrcaSlicer/OrcaSlicer_profile_validator.app ${{ github.workspace }}/build/universal/OrcaSlicer_profile_validator_dmg/ ln -sfn /Applications ${{ github.workspace }}/build/universal/OrcaSlicer_profile_validator_dmg/Applications retry hdiutil create -volname "OrcaSlicer Profile Validator" -srcfolder ${{ github.workspace }}/build/universal/OrcaSlicer_profile_validator_dmg -ov -format UDZO OrcaSlicer_profile_validator_Mac_universal_${{ env.ver }}.dmg - codesign --deep --force --verbose --options runtime --timestamp --entitlements ${{ github.workspace }}/scripts/disable_validation.entitlements --sign "$CERTIFICATE_ID" OrcaSlicer_profile_validator_Mac_universal_${{ env.ver }}.dmg + codesign --deep --force --verbose --options runtime --timestamp --entitlements "$ENTITLEMENTS" --sign "$CERTIFICATE_ID" OrcaSlicer_profile_validator_Mac_universal_${{ env.ver }}.dmg fi # Notarize main DMG diff --git a/build_release_macos.sh b/build_release_macos.sh index e1a191a7d4..2fd7b26cd8 100755 --- a/build_release_macos.sh +++ b/build_release_macos.sh @@ -179,6 +179,22 @@ function pack_deps() { ) } +# codesign cannot seal the runtime's dotted directories (include/python3.12, +# lib/python3.12) anywhere under Contents/MacOS -- it mistakes any dotted +# directory there for a nested bundle and fails with "bundle format +# unrecognized" -- so packaged apps ship the runtime under Contents/Resources +# with a compatibility symlink that keeps every Contents/MacOS/python path and +# the @executable_path/python/lib rpath resolving unchanged. +function relocate_python_runtime() { + local app="$1" + local pydir="$app/Contents/MacOS/python" + if [ -d "$pydir" ] && [ ! -L "$pydir" ]; then + rm -rf "$app/Contents/Resources/python" + mv "$pydir" "$app/Contents/Resources/python" + ln -s ../Resources/python "$pydir" + fi +} + # --- Bundled Python runtime verification -------------------------------------- # Relocation is handled at the source: deps/python3/python3.cmake stamps # libpython with an @rpath id and src/CMakeLists.txt gives the app a matching @@ -190,6 +206,11 @@ function verify_python_runtime() { local app="$1" local pydir="$app/Contents/MacOS/python" [ -d "$pydir" ] || return 0 # app doesn't bundle Python (e.g. profile validator) + if [ ! -L "$pydir" ]; then + echo "ERROR: Contents/MacOS/python must be a symlink into Contents/Resources" >&2 + echo " (see relocate_python_runtime in this script)" >&2 + exit 1 + fi # Version-agnostic interpreter name so a CPython version bump cannot # silently skip the gate; if the dir exists the interpreter must too. local pybin="$pydir/bin/python3" @@ -273,6 +294,7 @@ function build_slicer() { resources_path=$(readlink ./OrcaSlicer.app/Contents/Resources) rm ./OrcaSlicer.app/Contents/Resources cp -R "$resources_path" ./OrcaSlicer.app/Contents/Resources + relocate_python_runtime ./OrcaSlicer.app # delete .DS_Store file find ./OrcaSlicer.app/ -name '.DS_Store' -delete diff --git a/src/slic3r/CMakeLists.txt b/src/slic3r/CMakeLists.txt index 82a7e7a448..67b55e7879 100644 --- a/src/slic3r/CMakeLists.txt +++ b/src/slic3r/CMakeLists.txt @@ -842,6 +842,14 @@ endif() target_link_libraries(libslic3r_gui libslic3r cereal::cereal imgui imguizmo minilzo libvgcode md4c-html glad ${_opengl_link_lib} hidapi mdns ${wxWidgets_LIBRARIES} glfw libcurl OpenSSL::SSL OpenSSL::Crypto noise::noise pybind11::embed) +if (CMAKE_SYSTEM_NAME STREQUAL "Linux") + # Linux finds wxWidgets in module mode, whose include dirs and definitions + # only apply at src/ directory scope; export them from the target so wx + # headers reach GUI-header consumers outside src/ (tests). The CONFIG-mode + # wx::* imported targets used on Windows/macOS already propagate these. + target_include_directories(libslic3r_gui SYSTEM PUBLIC ${wxWidgets_INCLUDE_DIRS}) + target_compile_definitions(libslic3r_gui PUBLIC ${wxWidgets_DEFINITIONS} $<$:${wxWidgets_DEFINITIONS_DEBUG}>) +endif () if (MSVC) target_link_libraries(libslic3r_gui Setupapi.lib)