Compare commits

..

8 Commits

Author SHA1 Message Date
SoftFever
f5ca14ebb5 Merge branch 'main' into feature/auto-update 2026-01-05 18:09:53 +08:00
SoftFever
6d358443ec Merge branch 'main' into feature/auto-update 2026-01-05 16:49:15 +08:00
SoftFever
5771f63edd fix 2026-01-05 13:32:25 +08:00
SoftFever
444e191c2b fix build error 2026-01-05 09:09:54 +08:00
SoftFever
82abc70460 skip unit test 2026-01-05 00:34:46 +08:00
SoftFever
58278596df Merge branch 'main' into feature/auto-update 2026-01-05 00:33:58 +08:00
SoftFever
b7af2efe4c fix build errors 2026-01-05 00:29:19 +08:00
SoftFever
e35f4dbf62 WIP: auto update 2026-01-04 21:56:59 +08:00
11891 changed files with 1957725 additions and 2048588 deletions

View File

@@ -5,7 +5,7 @@ Language: Cpp
AccessModifierOffset: -4
AlignAfterOpenBracket: Align
AlignConsecutiveAssignments: true
AlignConsecutiveDeclarations: false
AlignConsecutiveDeclarations: true
AlignEscapedNewlines: DontAlign
AlignOperands: true
AlignTrailingComments: true

View File

@@ -11,15 +11,6 @@ body:
For this, please use the [Feature request](https://github.com/OrcaSlicer/OrcaSlicer/issues/new?assignees=&labels=&projects=&template=feature_request.yml) issue type or you can discuss your idea on our [Discord server](https://discord.gg/P4VE9UY9gJ) with others.
Before filing, please check if the issue already exists (either open or closed) by using the search bar on the issues page. If it does, comment there. Even if it's closed, we can reopen it based on your comment.
- type: checkboxes
attributes:
label: Is this issue reproducible in the latest nightly build?
description: >
Please verify this issue still happens in the latest nightly build first. It may already be fixed there:
[Nightly builds](https://github.com/OrcaSlicer/OrcaSlicer/releases/tag/nightly-builds).
options:
- label: I have checked the latest nightly build and the issue is still reproducible
required: true
- type: checkboxes
attributes:
label: Is there an existing issue for this problem?

View File

@@ -19,9 +19,3 @@
<!--
> Please describe the tests that you have conducted to verify the changes made in this PR.
-->
<!--
> A guide for users on how to download the artifacts from this PR.
-->
[How to Download Pull Requests Artifacts for Testing](https://www.orcaslicer.com/wiki/how_to_download_pr_artifacts)

View File

@@ -14,9 +14,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Assign the user or unassign stale assignments
# Note: v3.0.0 is broken (dist/index.mjs vs action.yml expects index.js)
# See: https://github.com/takanome-dev/assign-issue-action/issues/426
uses: takanome-dev/assign-issue-action@v2.2
uses: takanome-dev/assign-issue-action@v2.3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
maintainers: 'noisyfox,softfever'

View File

@@ -5,6 +5,7 @@ on:
branches:
- main
- release/*
- feature/auto-update # TODO: Remove after auto-update testing is complete
paths:
- 'deps/**'
- 'src/**'
@@ -48,189 +49,139 @@ concurrency:
jobs:
build_linux:
strategy:
fail-fast: false
# Don't run scheduled builds on forks:
if: ${{ !cancelled() && (github.event_name != 'schedule' || github.repository == 'OrcaSlicer/OrcaSlicer') }}
uses: ./.github/workflows/build_check_cache.yml
with:
os: ${{ vars.SELF_HOSTED && 'orca-lnx-server' || 'ubuntu-24.04' }}
build-deps-only: ${{ inputs.build-deps-only || false }}
secrets: inherit
build_windows:
# Don't run scheduled builds on forks:
if: ${{ !cancelled() && (github.event_name != 'schedule' || github.repository == 'OrcaSlicer/OrcaSlicer') }}
uses: ./.github/workflows/build_check_cache.yml
with:
os: ${{ vars.SELF_HOSTED && 'orca-win-server' || 'windows-latest' }}
build-deps-only: ${{ inputs.build-deps-only || false }}
force-build: ${{ github.event_name == 'schedule' }}
secrets: inherit
build_macos_arch:
# build_linux:
# name: Build Linux
# strategy:
# fail-fast: false
# # Don't run scheduled builds on forks:
# if: ${{ !cancelled() && (github.event_name != 'schedule' || github.repository == 'OrcaSlicer/OrcaSlicer') }}
# uses: ./.github/workflows/build_check_cache.yml
# with:
# os: ubuntu-24.04
# build-deps-only: ${{ inputs.build-deps-only || false }}
# secrets: inherit
build_all:
name: Build macOS (testing auto-update)
strategy:
fail-fast: false
matrix:
arch:
- arm64
- x86_64
include:
# TODO: Re-enable Windows after auto-update testing is complete
# - os: windows-latest
- os: macos-14
arch: arm64
# Don't run scheduled builds on forks:
if: ${{ !cancelled() && (github.event_name != 'schedule' || github.repository == 'OrcaSlicer/OrcaSlicer') }}
uses: ./.github/workflows/build_check_cache.yml
with:
os: ${{ vars.SELF_HOSTED && 'orca-macos-arm64' || 'macos-14' }}
os: ${{ matrix.os }}
arch: ${{ matrix.arch }}
build-deps-only: ${{ inputs.build-deps-only || false }}
force-build: ${{ github.event_name == 'schedule' }}
secrets: inherit
build_macos_universal:
name: Build macOS Universal
needs: build_macos_arch
if: ${{ !cancelled() && needs.build_macos_arch.result == 'success' && !inputs.build-deps-only && (github.event_name != 'schedule' || github.repository == 'OrcaSlicer/OrcaSlicer') }}
uses: ./.github/workflows/build_orca.yml
with:
os: ${{ vars.SELF_HOSTED && 'orca-macos-arm64' || 'macos-14' }}
arch: universal
macos-combine-only: true
secrets: inherit
unit_tests:
name: Unit Tests
runs-on: ${{ vars.SELF_HOSTED && 'orca-lnx-server' || 'ubuntu-24.04' }}
needs: build_linux
if: ${{ !cancelled() && success() }}
steps:
- name: Checkout
uses: actions/checkout@v6
with:
sparse-checkout: |
.github
scripts
tests
- name: Apt-Install Dependencies
if: ${{ !vars.SELF_HOSTED }}
uses: ./.github/actions/apt-install-deps
- name: Restore Test Artifact
uses: actions/download-artifact@v8
with:
name: ${{ github.sha }}-tests
- uses: lukka/get-cmake@latest
with:
cmakeVersion: "~4.3.0" # use most recent 4.3.x version
useLocalCache: true # <--= Use the local cache (default is 'false').
useCloudCache: true
- name: Unpackage and Run Unit Tests
timeout-minutes: 20
run: |
tar -xvf build_tests.tar
scripts/run_unit_tests.sh
- name: Upload Test Logs
uses: actions/upload-artifact@v7
if: ${{ failure() }}
with:
name: unit-test-logs
path: build/tests/**/*.log
- name: Publish Test Results
if: always()
uses: EnricoMi/publish-unit-test-result-action@v2
with:
files: "ctest_results.xml"
- name: Delete Test Artifact
if: success()
uses: geekyeggo/delete-artifact@v6
with:
name: ${{ github.sha }}-tests
flatpak:
name: "Flatpak"
container:
image: ghcr.io/flathub-infra/flatpak-github-actions:gnome-49
options: --privileged
volumes:
- /usr/local/lib/android:/usr/local/lib/android
- /usr/share/dotnet:/usr/share/dotnet
- /opt/ghc:/opt/ghc1
- /usr/local/share/boost:/usr/local/share/boost1
- /opt/hostedtoolcache:/opt/hostedtoolcache1
strategy:
fail-fast: false
matrix:
variant:
- arch: x86_64
runner: ubuntu-24.04
- arch: aarch64
runner: ubuntu-24.04-arm
# Don't run scheduled builds on forks; skip entirely on self-hosted runners
if: ${{ !cancelled() && !vars.SELF_HOSTED && (github.event_name != 'schedule' || github.repository == 'OrcaSlicer/OrcaSlicer') }}
runs-on: ${{ matrix.variant.runner }}
env:
date:
ver:
ver_pure:
steps:
- name: "Remove unneeded stuff to free disk space"
run:
rm -rf /usr/local/lib/android/* /usr/share/dotnet/* /opt/ghc1/* "/usr/local/share/boost1/*" /opt/hostedtoolcache1/*
- uses: actions/checkout@v6
- name: Get the version and date
run: |
ver_pure=$(grep 'set(SoftFever_VERSION' version.inc | cut -d '"' -f2)
if [[ "${{ github.event_name }}" == "pull_request" ]]; then
ver="PR-${{ github.event.number }}"
git_commit_hash="${{ github.event.pull_request.head.sha }}"
else
ver=V$ver_pure
git_commit_hash="${{ github.sha }}"
fi
echo "ver=$ver" >> $GITHUB_ENV
echo "ver_pure=$ver_pure" >> $GITHUB_ENV
echo "date=$(date +'%Y%m%d')" >> $GITHUB_ENV
echo "git_commit_hash=$git_commit_hash" >> $GITHUB_ENV
shell: bash
# Manage flatpak-builder cache externally so PRs restore but never upload
- name: Restore flatpak-builder cache
if: github.event_name == 'pull_request'
uses: actions/cache/restore@v5
with:
path: .flatpak-builder
key: flatpak-builder-${{ matrix.variant.arch }}-${{ github.event.pull_request.base.sha }}
restore-keys: flatpak-builder-${{ matrix.variant.arch }}-
- name: Save/restore flatpak-builder cache
if: github.event_name != 'pull_request'
uses: actions/cache@v5
with:
path: .flatpak-builder
key: flatpak-builder-${{ matrix.variant.arch }}-${{ github.sha }}
restore-keys: flatpak-builder-${{ matrix.variant.arch }}-
- name: Disable debug info for faster CI builds
run: |
sed -i '/^build-options:/a\ no-debuginfo: true\n strip: true' \
scripts/flatpak/com.orcaslicer.OrcaSlicer.yml
shell: bash
- name: Inject git commit hash into Flatpak manifest
run: |
sed -i "/name: OrcaSlicer/{n;s|buildsystem: simple|buildsystem: simple\n build-options:\n env:\n git_commit_hash: \"$git_commit_hash\"|}" \
scripts/flatpak/com.orcaslicer.OrcaSlicer.yml
shell: bash
- uses: flatpak/flatpak-github-actions/flatpak-builder@master
with:
bundle: OrcaSlicer-Linux-flatpak_${{ env.ver }}_${{ matrix.variant.arch }}.flatpak
manifest-path: scripts/flatpak/com.orcaslicer.OrcaSlicer.yml
cache: false
arch: ${{ matrix.variant.arch }}
upload-artifact: false
- name: Upload artifacts Flatpak
uses: actions/upload-artifact@v7
with:
name: OrcaSlicer-Linux-flatpak_${{ env.ver }}_${{ matrix.variant.arch }}.flatpak
path: '/__w/OrcaSlicer/OrcaSlicer/OrcaSlicer-Linux-flatpak_${{ env.ver }}_${{ matrix.variant.arch }}.flatpak'
- name: Deploy Flatpak to nightly release
if: github.repository == 'OrcaSlicer/OrcaSlicer' && github.ref == 'refs/heads/main'
uses: WebFreak001/deploy-nightly@v3.2.0
with:
upload_url: https://uploads.github.com/repos/OrcaSlicer/OrcaSlicer/releases/137995723/assets{?name,label}
release_id: 137995723
asset_path: /__w/OrcaSlicer/OrcaSlicer/OrcaSlicer-Linux-flatpak_${{ env.ver }}_${{ matrix.variant.arch }}.flatpak
asset_name: OrcaSlicer-Linux-flatpak_nightly_${{ matrix.variant.arch }}.flatpak
asset_content_type: application/octet-stream
max_releases: 1 # optional, if there are more releases than this matching the asset_name, the oldest ones are going to be deleted
# unit_tests:
# name: Unit Tests
# runs-on: ubuntu-24.04
# needs: build_linux
# if: ${{ !cancelled() && success() }}
# steps:
# - name: Checkout
# uses: actions/checkout@v6
# with:
# sparse-checkout: |
# .github
# scripts
# tests
# - name: Apt-Install Dependencies
# uses: ./.github/actions/apt-install-deps
# - name: Restore Test Artifact
# uses: actions/download-artifact@v7
# with:
# name: ${{ github.sha }}-tests
# - uses: lukka/get-cmake@latest
# with:
# cmakeVersion: "~3.28.0" # use most recent 3.28.x version
# - name: Unpackage and Run Unit Tests
# timeout-minutes: 20
# run: |
# tar -xvf build_tests.tar
# scripts/run_unit_tests.sh
# - name: Upload Test Logs
# uses: actions/upload-artifact@v6
# if: ${{ failure() }}
# with:
# name: unit-test-logs
# path: build/tests/**/*.log
# - name: Publish Test Results
# if: always()
# uses: EnricoMi/publish-unit-test-result-action@v2
# with:
# files: "ctest_results.xml"
# flatpak:
# name: "Flatpak"
# container:
# image: ghcr.io/flathub-infra/flatpak-github-actions:gnome-48
# options: --privileged
# volumes:
# - /usr/local/lib/android:/usr/local/lib/android
# - /usr/share/dotnet:/usr/share/dotnet
# - /opt/ghc:/opt/ghc1
# - /usr/local/share/boost:/usr/local/share/boost1
# - /opt/hostedtoolcache:/opt/hostedtoolcache1
# strategy:
# fail-fast: false
# matrix:
# variant:
# - arch: x86_64
# runner: ubuntu-24.04
# - arch: aarch64
# runner: ubuntu-24.04-arm
# # Don't run scheduled builds on forks:
# if: ${{ !cancelled() && (github.event_name != 'schedule' || github.repository == 'OrcaSlicer/OrcaSlicer') }}
# runs-on: ${{ matrix.variant.runner }}
# env:
# date:
# ver:
# ver_pure:
# steps:
# - name: "Remove unneeded stuff to free disk space"
# run:
# rm -rf /usr/local/lib/android/* /usr/share/dotnet/* /opt/ghc1/* "/usr/local/share/boost1/*" /opt/hostedtoolcache1/*
# - uses: actions/checkout@v6
# - name: Get the version and date
# run: |
# ver_pure=$(grep 'set(SoftFever_VERSION' version.inc | cut -d '"' -f2)
# if [[ "${{ github.event_name }}" == "pull_request" ]]; then
# ver="PR-${{ github.event.number }}"
# git_commit_hash="${{ github.event.pull_request.head.sha }}"
# else
# ver=V$ver_pure
# git_commit_hash=""
# fi
# echo "ver=$ver" >> $GITHUB_ENV
# echo "ver_pure=$ver_pure" >> $GITHUB_ENV
# echo "date=$(date +'%Y%m%d')" >> $GITHUB_ENV
# echo "git_commit_hash=$git_commit_hash" >> $GITHUB_ENV
# shell: bash
# - uses: flatpak/flatpak-github-actions/flatpak-builder@master
# with:
# bundle: OrcaSlicer-Linux-flatpak_${{ env.ver }}_${{ matrix.variant.arch }}.flatpak
# manifest-path: scripts/flatpak/io.github.softfever.OrcaSlicer.yml
# cache: true
# arch: ${{ matrix.variant.arch }}
# upload-artifact: false
# - name: Upload artifacts Flatpak
# uses: actions/upload-artifact@v6
# with:
# name: OrcaSlicer-Linux-flatpak_${{ env.ver }}_${{ matrix.variant.arch }}.flatpak
# path: '/__w/OrcaSlicer/OrcaSlicer/OrcaSlicer-Linux-flatpak_${{ env.ver }}_${{ matrix.variant.arch }}.flatpak'
# - name: Deploy Flatpak to nightly release
# if: github.repository == 'OrcaSlicer/OrcaSlicer' && github.ref == 'refs/heads/main'
# uses: WebFreak001/deploy-nightly@v3.2.0
# with:
# upload_url: https://uploads.github.com/repos/OrcaSlicer/OrcaSlicer/releases/137995723/assets{?name,label}
# release_id: 137995723
# asset_path: /__w/OrcaSlicer/OrcaSlicer/OrcaSlicer-Linux-flatpak_${{ env.ver }}_${{ matrix.variant.arch }}.flatpak
# asset_name: OrcaSlicer-Linux-flatpak_nightly_${{ matrix.variant.arch }}.flatpak
# asset_content_type: application/octet-stream
# max_releases: 1 # optional, if there are more releases than this matching the asset_name, the oldest ones are going to be deleted

View File

@@ -28,17 +28,15 @@ jobs:
- name: Checkout
uses: actions/checkout@v6
with:
lfs: 'false'
lfs: 'true'
- name: set outputs
id: set_outputs
env:
# Keep macOS cache keys and paths architecture-specific.
cache-os: ${{ runner.os == 'macOS' && format('macos-{0}', inputs.arch) || (runner.os == 'Windows' && 'windows' || 'linux-clang') }}
dep-folder-name: ${{ runner.os == 'macOS' && format('/{0}', inputs.arch) || '/OrcaSlicer_dep' }}
output-cmd: ${{ runner.os == 'Windows' && '$env:GITHUB_OUTPUT' || '"$GITHUB_OUTPUT"'}}
dep-folder-name: ${{ inputs.os != 'macos-14' && '/OrcaSlicer_dep' || '' }}
output-cmd: ${{ inputs.os == 'windows-latest' && '$env:GITHUB_OUTPUT' || '"$GITHUB_OUTPUT"'}}
run: |
echo cache-key=${{ env.cache-os }}-cache-orcaslicer_deps-build-${{ hashFiles('deps/**') }} >> ${{ env.output-cmd }}
echo cache-key=${{ inputs.os }}-cache-orcaslicer_deps-build-${{ hashFiles('deps/**') }} >> ${{ env.output-cmd }}
echo cache-path=${{ github.workspace }}/deps/build${{ env.dep-folder-name }} >> ${{ env.output-cmd }}
- name: load cache

View File

@@ -36,7 +36,7 @@ jobs:
- name: Checkout
uses: actions/checkout@v6
with:
lfs: 'false'
lfs: 'true'
- name: load cached deps
uses: actions/cache@v5
@@ -46,86 +46,85 @@ jobs:
- uses: lukka/get-cmake@latest
with:
cmakeVersion: "~4.3.0" # use most recent 4.3.x version
useLocalCache: true # <--= Use the local cache (default is 'false').
useCloudCache: true
cmakeVersion: "~3.28.0" # use most recent 3.28.x version
- name: setup dev on Windows
if: runner.os == 'Windows'
uses: microsoft/setup-msbuild@v3
if: inputs.os == 'windows-latest'
uses: microsoft/setup-msbuild@v2
- name: Get the date on Ubuntu and macOS
if: runner.os != 'Windows'
if: inputs.os != 'windows-latest'
run: echo "date=$(date +'%Y%m%d')" >> $GITHUB_ENV
shell: bash
- name: Get the date on Windows
if: runner.os == 'Windows'
if: inputs.os == 'windows-latest'
run: echo "date=$(Get-Date -Format 'yyyyMMdd')" | Out-File -Append -FilePath $env:GITHUB_ENV -Encoding utf8
shell: pwsh
# Build Dependencies
- name: Build on Windows
if: runner.os == 'Windows'
if: inputs.os == 'windows-latest'
working-directory: ${{ github.workspace }}
run: |
if (-not "${{ vars.SELF_HOSTED }}") {
choco install strawberryperl
}
choco install strawberryperl
.\build_release_vs.bat deps
.\build_release_vs.bat pack
shell: pwsh
cd ${{ github.workspace }}/deps/build
- name: Build on Mac ${{ inputs.arch }}
if: runner.os == 'macOS'
if: inputs.os == 'macos-14'
working-directory: ${{ github.workspace }}
run: |
if [ -z "${{ vars.SELF_HOSTED }}" ]; then
brew install automake texinfo libtool
fi
./build_release_macos.sh -dx ${{ !vars.SELF_HOSTED && '-1' || '' }} -a ${{ inputs.arch }} -t 10.15
(cd "${{ github.workspace }}/deps/build/${{ inputs.arch }}" && \
find . -mindepth 1 -maxdepth 1 ! -name 'OrcaSlicer_dep' -exec rm -rf {} +)
brew install automake texinfo libtool
brew list
brew uninstall --ignore-dependencies zstd
./build_release_macos.sh -dx -a universal -t 10.15 -1
for arch in arm64 x86_64; do
(cd "${{ github.workspace }}/deps/build/${arch}" && \
find . -mindepth 1 -maxdepth 1 ! -name 'OrcaSlicer_dep' -exec rm -rf {} +)
done
brew install zstd
- name: Apt-Install Dependencies
if: runner.os == 'Linux' && !vars.SELF_HOSTED
if: inputs.os == 'ubuntu-24.04'
uses: ./.github/actions/apt-install-deps
- name: Build on Ubuntu
if: runner.os == 'Linux'
if: inputs.os == 'ubuntu-20.04' || inputs.os == 'ubuntu-24.04'
working-directory: ${{ github.workspace }}
run: |
mkdir -p ${{ github.workspace }}/deps/build/destdir
./build_linux.sh -drlL
./build_linux.sh -dr
cd deps/build
tar -czvf OrcaSlicer_dep_ubuntu_$(date +"%Y%m%d").tar.gz destdir
# Upload Artifacts
# - name: Upload Mac ${{ inputs.arch }} artifacts
# if: runner.os == 'macOS'
# if: inputs.os == 'macos-14'
# uses: actions/upload-artifact@v6
# with:
# name: OrcaSlicer_dep_mac_${{ env.date }}
# path: ${{ github.workspace }}/deps/build/OrcaSlicer_dep*.tar.gz
# - name: Upload Windows artifacts
# if: runner.os == 'Windows'
# uses: actions/upload-artifact@v6
# with:
# name: OrcaSlicer_dep_win64_${{ env.date }}
# path: ${{ github.workspace }}/deps/build/OrcaSlicer_dep*.zip
- name: Upload Windows artifacts
if: inputs.os == 'windows-latest'
uses: actions/upload-artifact@v6
with:
name: OrcaSlicer_dep_win64_${{ env.date }}
path: ${{ github.workspace }}/deps/build/OrcaSlicer_dep*.zip
# - name: Upload Ubuntu artifacts
# if: runner.os == 'Linux' && !env.ACT
# env:
# ubuntu-ver: '2404'
# uses: actions/upload-artifact@v6
# with:
# name: OrcaSlicer_dep_ubuntu_${{ env.ubuntu-ver }}_${{ env.date }}
# path: ${{ github.workspace }}/deps/build/OrcaSlicer_dep_ubuntu_*.tar.gz
- name: Upload Ubuntu artifacts
if: ${{ ! env.ACT && inputs.os == 'ubuntu-20.04' || inputs.os == 'ubuntu-24.04' }}
env:
ubuntu-ver: ${{ (inputs.os == 'ubuntu-20.04' && '2004') || (inputs.os == 'ubuntu-24.04' && '2404') || '' }}
uses: actions/upload-artifact@v6
with:
name: OrcaSlicer_dep_ubuntu_${{ env.ubuntu-ver }}_${{ env.date }}
path: ${{ github.workspace }}/deps/build/OrcaSlicer_dep_ubuntu_*.tar.gz
build_orca:
name: Build OrcaSlicer

View File

@@ -2,10 +2,10 @@ on:
workflow_call:
inputs:
cache-key:
required: false
required: true
type: string
cache-path:
required: false
required: true
type: string
os:
required: true
@@ -13,10 +13,6 @@ on:
arch:
required: false
type: string
macos-combine-only:
required: false
type: boolean
default: false
jobs:
build_orca:
@@ -26,18 +22,15 @@ jobs:
date:
ver:
ver_pure:
ubuntu-ver: '2404'
ubuntu-ver-str: '_Ubuntu2404'
ORCA_UPDATER_SIG_KEY: ${{ secrets.ORCA_UPDATER_SIG_KEY }}
steps:
- name: Checkout
uses: actions/checkout@v6
with:
lfs: 'false'
lfs: 'true'
- name: load cached deps
if: ${{ !(runner.os == 'macOS' && inputs.macos-combine-only) }}
uses: actions/cache@v5
with:
path: ${{ inputs.cache-path }}
@@ -46,12 +39,10 @@ jobs:
- uses: lukka/get-cmake@latest
with:
cmakeVersion: "~4.3.0" # use most recent 4.3.x version
useLocalCache: true # <--= Use the local cache (default is 'false').
useCloudCache: true
cmakeVersion: "~3.28.0" # use most recent 3.28.x version
- name: Get the version and date on Ubuntu and macOS
if: runner.os != 'Windows'
if: inputs.os != 'windows-latest'
run: |
ver_pure=$(grep 'set(SoftFever_VERSION' version.inc | cut -d '"' -f2)
if [[ "${{ github.event_name }}" == "pull_request" ]]; then
@@ -68,7 +59,7 @@ jobs:
shell: bash
- name: Get the version and date on Windows
if: runner.os == 'Windows'
if: inputs.os == 'windows-latest'
run: |
$date = Get-Date -Format 'yyyyMMdd'
$ref = "${{ github.ref }}"
@@ -95,16 +86,14 @@ jobs:
# Mac
- name: Install tools mac
if: runner.os == 'macOS' && !inputs.macos-combine-only
if: inputs.os == 'macos-14'
run: |
if [ -z "${{ vars.SELF_HOSTED }}" ]; then
brew install libtool
brew list
fi
mkdir -p ${{ github.workspace }}/deps/build/${{ inputs.arch }}
brew install libtool
brew list
mkdir -p ${{ github.workspace }}/deps/build
- name: Free disk space
if: runner.os == 'macOS' && !inputs.macos-combine-only && !vars.SELF_HOSTED
if: inputs.os == 'macos-14'
run: |
df -hI /dev/disk3s1s1
sudo find /Applications -maxdepth 1 -type d -name "Xcode_*.app" ! -name "Xcode_15.4.app" -exec rm -rf {} +
@@ -112,58 +101,16 @@ jobs:
df -hI /dev/disk3s1s1
- name: Build slicer mac
if: runner.os == 'macOS' && !inputs.macos-combine-only
if: inputs.os == 'macos-14'
working-directory: ${{ github.workspace }}
run: |
./build_release_macos.sh -s -n -x ${{ !vars.SELF_HOSTED && '-1' || '' }} -a ${{ inputs.arch }} -t 10.15
- name: Pack macOS app bundle ${{ inputs.arch }}
if: runner.os == 'macOS' && !inputs.macos-combine-only
working-directory: ${{ github.workspace }}
run: |
tar -czvf OrcaSlicer_Mac_bundle_${{ inputs.arch }}_${{ github.sha }}.tar.gz -C build/${{ inputs.arch }} OrcaSlicer
- name: Upload macOS app bundle ${{ inputs.arch }}
if: runner.os == 'macOS' && !inputs.macos-combine-only
uses: actions/upload-artifact@v7
with:
name: OrcaSlicer_Mac_bundle_${{ inputs.arch }}_${{ github.sha }}
path: ${{ github.workspace }}/OrcaSlicer_Mac_bundle_${{ inputs.arch }}_${{ github.sha }}.tar.gz
- name: Download macOS app bundles
if: runner.os == 'macOS' && inputs.macos-combine-only
uses: actions/download-artifact@v8
with:
pattern: OrcaSlicer_Mac_bundle_*_${{ github.sha }}
path: ${{ github.workspace }}/mac_bundles
- name: Extract macOS app bundles
if: runner.os == 'macOS' && inputs.macos-combine-only
working-directory: ${{ github.workspace }}
run: |
mkdir -p build/arm64 build/x86_64
arm_bundle=$(find "${{ github.workspace }}/mac_bundles/OrcaSlicer_Mac_bundle_arm64_${{ github.sha }}" -name '*.tar.gz' -print -quit)
x86_bundle=$(find "${{ github.workspace }}/mac_bundles/OrcaSlicer_Mac_bundle_x86_64_${{ github.sha }}" -name '*.tar.gz' -print -quit)
tar -xzvf "$arm_bundle" -C "${{ github.workspace }}/build/arm64"
tar -xzvf "$x86_bundle" -C "${{ github.workspace }}/build/x86_64"
- name: Build universal mac app bundle
if: runner.os == 'macOS' && inputs.macos-combine-only
working-directory: ${{ github.workspace }}
run: |
./build_release_macos.sh -u -x ${{ !vars.SELF_HOSTED && '-1' || '' }} -a universal -t 10.15
- name: Delete intermediate per-arch artifacts
if: runner.os == 'macOS' && inputs.macos-combine-only
uses: geekyeggo/delete-artifact@v6
with:
name: |
OrcaSlicer_Mac_bundle_arm64_${{ github.sha }}
OrcaSlicer_Mac_bundle_x86_64_${{ github.sha }}
# TODO: Change back to -a universal after auto-update testing is complete
./build_release_macos.sh -s -n -x -a arm64 -t 10.15 -1
# Thanks to RaySajuuk, it's working now
- name: Sign app and notary
if: github.repository == 'OrcaSlicer/OrcaSlicer' && (github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/heads/release/')) && runner.os == 'macOS' && inputs.macos-combine-only
# TODO: Remove feature/auto-update after testing is complete
if: github.repository == 'OrcaSlicer/OrcaSlicer' && (github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/heads/release/') || github.ref == 'refs/heads/feature/auto-update') && inputs.os == 'macos-14'
working-directory: ${{ github.workspace }}
env:
BUILD_CERTIFICATE_BASE64: ${{ secrets.BUILD_CERTIFICATE_BASE64 }}
@@ -177,81 +124,131 @@ jobs:
security create-keychain -p $KEYCHAIN_PASSWORD $KEYCHAIN_PATH
security set-keychain-settings -lut 21600 $KEYCHAIN_PATH
security unlock-keychain -p $KEYCHAIN_PASSWORD $KEYCHAIN_PATH
# Set the temporary keychain as the default to prevent codesign from accessing the locked login keychain
security default-keychain -s "$KEYCHAIN_PATH"
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
# TODO: Change build/arm64 back to build/universal after auto-update testing is complete
codesign --deep --force --verbose --options runtime --timestamp --entitlements ${{ github.workspace }}/scripts/disable_validation.entitlements --sign "$CERTIFICATE_ID" ${{ github.workspace }}/build/arm64/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
if [ -f "${{ github.workspace }}/build/arm64/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/arm64/OrcaSlicer/OrcaSlicer_profile_validator.app
fi
# Create main OrcaSlicer DMG without the profile validator helper
mkdir -p ${{ github.workspace }}/build/universal/OrcaSlicer_dmg
rm -rf ${{ github.workspace }}/build/universal/OrcaSlicer_dmg/*
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
hdiutil create -volname "OrcaSlicer" -srcfolder ${{ github.workspace }}/build/universal/OrcaSlicer_dmg -ov -format UDZO OrcaSlicer_Mac_universal_${{ env.ver }}.dmg
mkdir -p ${{ github.workspace }}/build/arm64/OrcaSlicer_dmg
rm -rf ${{ github.workspace }}/build/arm64/OrcaSlicer_dmg/*
cp -R ${{ github.workspace }}/build/arm64/OrcaSlicer/OrcaSlicer.app ${{ github.workspace }}/build/arm64/OrcaSlicer_dmg/
ln -sfn /Applications ${{ github.workspace }}/build/arm64/OrcaSlicer_dmg/Applications
hdiutil create -volname "OrcaSlicer" -srcfolder ${{ github.workspace }}/build/arm64/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
# 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
mkdir -p ${{ github.workspace }}/build/universal/OrcaSlicer_profile_validator_dmg
rm -rf ${{ github.workspace }}/build/universal/OrcaSlicer_profile_validator_dmg/*
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
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
if [ -f "${{ github.workspace }}/build/arm64/OrcaSlicer/OrcaSlicer_profile_validator.app/Contents/MacOS/OrcaSlicer_profile_validator" ]; then
mkdir -p ${{ github.workspace }}/build/arm64/OrcaSlicer_profile_validator_dmg
rm -rf ${{ github.workspace }}/build/arm64/OrcaSlicer_profile_validator_dmg/*
cp -R ${{ github.workspace }}/build/arm64/OrcaSlicer/OrcaSlicer_profile_validator.app ${{ github.workspace }}/build/arm64/OrcaSlicer_profile_validator_dmg/
ln -sfn /Applications ${{ github.workspace }}/build/arm64/OrcaSlicer_profile_validator_dmg/Applications
hdiutil create -volname "OrcaSlicer Profile Validator" -srcfolder ${{ github.workspace }}/build/arm64/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
fi
# Notarize main DMG
xcrun notarytool submit "OrcaSlicer_Mac_universal_${{ env.ver }}.dmg" --apple-id "${{ secrets.APPLE_DEV_ACCOUNT }}" --team-id "${{ secrets.TEAM_ID }}" --password "${{ secrets.APP_PWD }}" --wait
xcrun notarytool store-credentials "notarytool-profile" --apple-id "${{ secrets.APPLE_DEV_ACCOUNT }}" --team-id "${{ secrets.TEAM_ID }}" --password "${{ secrets.APP_PWD }}"
xcrun notarytool submit "OrcaSlicer_Mac_universal_${{ env.ver }}.dmg" --keychain-profile "notarytool-profile" --wait
xcrun stapler staple OrcaSlicer_Mac_universal_${{ env.ver }}.dmg
# Notarize profile validator DMG if it exists
if [ -f "OrcaSlicer_profile_validator_Mac_universal_${{ env.ver }}.dmg" ]; then
xcrun notarytool submit "OrcaSlicer_profile_validator_Mac_universal_${{ env.ver }}.dmg" --apple-id "${{ secrets.APPLE_DEV_ACCOUNT }}" --team-id "${{ secrets.TEAM_ID }}" --password "${{ secrets.APP_PWD }}" --wait
xcrun notarytool submit "OrcaSlicer_profile_validator_Mac_universal_${{ env.ver }}.dmg" --keychain-profile "notarytool-profile" --wait
xcrun stapler staple OrcaSlicer_profile_validator_Mac_universal_${{ env.ver }}.dmg
fi
- name: Sign DMG for Sparkle auto-update
# TODO: Remove feature/auto-update after testing is complete
if: github.repository == 'OrcaSlicer/OrcaSlicer' && (github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/heads/release/') || github.ref == 'refs/heads/feature/auto-update') && inputs.os == 'macos-14'
working-directory: ${{ github.workspace }}
env:
SPARKLE_PRIVATE_KEY: ${{ secrets.SPARKLE_PRIVATE_KEY }}
run: |
# Get the Sparkle sign_update tool from deps (installed to OrcaSlicer_dep/bin)
SIGN_UPDATE="${{ github.workspace }}/deps/build/arm64/OrcaSlicer_dep/bin/sign_update"
# Fallback to x86_64 if arm64 not found
if [ ! -f "$SIGN_UPDATE" ]; then
SIGN_UPDATE="${{ github.workspace }}/deps/build/x86_64/OrcaSlicer_dep/bin/sign_update"
fi
if [ -f "$SIGN_UPDATE" ] && [ -n "$SPARKLE_PRIVATE_KEY" ]; then
# Write the private key to a temp file
echo "$SPARKLE_PRIVATE_KEY" > /tmp/sparkle_private_key
chmod 600 /tmp/sparkle_private_key
# Sign the DMG and capture the signature
SIGNATURE=$("$SIGN_UPDATE" "OrcaSlicer_Mac_universal_${{ env.ver }}.dmg" -f /tmp/sparkle_private_key)
# Clean up the key file
rm -f /tmp/sparkle_private_key
# Save signature to a file for later use in appcast generation
echo "$SIGNATURE" > OrcaSlicer_Mac_universal_${{ env.ver }}.dmg.sig
echo "Sparkle signature generated: $SIGNATURE"
# Also output as GitHub Actions output
echo "sparkle_signature=$SIGNATURE" >> $GITHUB_OUTPUT
else
echo "Warning: Sparkle sign_update tool not found at $SIGN_UPDATE or private key not set, skipping signature generation"
if [ ! -f "$SIGN_UPDATE" ]; then
echo "sign_update not found. Available files:"
ls -la "${{ github.workspace }}/deps/build/arm64/OrcaSlicer_dep/" || true
fi
fi
- name: Create DMG without notary
if: github.ref != 'refs/heads/main' && runner.os == 'macOS' && inputs.macos-combine-only
# TODO: Remove feature/auto-update exclusion after testing is complete
if: github.ref != 'refs/heads/main' && github.ref != 'refs/heads/feature/auto-update' && !startsWith(github.ref, 'refs/heads/release/') && inputs.os == 'macos-14'
working-directory: ${{ github.workspace }}
run: |
mkdir -p ${{ github.workspace }}/build/universal/OrcaSlicer_dmg
rm -rf ${{ github.workspace }}/build/universal/OrcaSlicer_dmg/*
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
hdiutil create -volname "OrcaSlicer" -srcfolder ${{ github.workspace }}/build/universal/OrcaSlicer_dmg -ov -format UDZO OrcaSlicer_Mac_universal_${{ env.ver }}.dmg
# TODO: Change build/arm64 back to build/universal after auto-update testing is complete
mkdir -p ${{ github.workspace }}/build/arm64/OrcaSlicer_dmg
rm -rf ${{ github.workspace }}/build/arm64/OrcaSlicer_dmg/*
cp -R ${{ github.workspace }}/build/arm64/OrcaSlicer/OrcaSlicer.app ${{ github.workspace }}/build/arm64/OrcaSlicer_dmg/
ln -sfn /Applications ${{ github.workspace }}/build/arm64/OrcaSlicer_dmg/Applications
hdiutil create -volname "OrcaSlicer" -srcfolder ${{ github.workspace }}/build/arm64/OrcaSlicer_dmg -ov -format UDZO 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
mkdir -p ${{ github.workspace }}/build/universal/OrcaSlicer_profile_validator_dmg
rm -rf ${{ github.workspace }}/build/universal/OrcaSlicer_profile_validator_dmg/*
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
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
if [ -f "${{ github.workspace }}/build/arm64/OrcaSlicer/OrcaSlicer_profile_validator.app/Contents/MacOS/OrcaSlicer_profile_validator" ]; then
mkdir -p ${{ github.workspace }}/build/arm64/OrcaSlicer_profile_validator_dmg
rm -rf ${{ github.workspace }}/build/arm64/OrcaSlicer_profile_validator_dmg/*
cp -R ${{ github.workspace }}/build/arm64/OrcaSlicer/OrcaSlicer_profile_validator.app ${{ github.workspace }}/build/arm64/OrcaSlicer_profile_validator_dmg/
ln -sfn /Applications ${{ github.workspace }}/build/arm64/OrcaSlicer_profile_validator_dmg/Applications
hdiutil create -volname "OrcaSlicer Profile Validator" -srcfolder ${{ github.workspace }}/build/arm64/OrcaSlicer_profile_validator_dmg -ov -format UDZO OrcaSlicer_profile_validator_Mac_universal_${{ env.ver }}.dmg
fi
- name: Upload artifacts mac
if: runner.os == 'macOS' && inputs.macos-combine-only
uses: actions/upload-artifact@v7
if: inputs.os == 'macos-14'
uses: actions/upload-artifact@v6
with:
name: OrcaSlicer_Mac_universal_${{ env.ver }}
path: ${{ github.workspace }}/OrcaSlicer_Mac_universal_${{ env.ver }}.dmg
- name: Upload Sparkle signature mac
if: inputs.os == 'macos-14'
uses: actions/upload-artifact@v5
with:
name: OrcaSlicer_Mac_universal_${{ env.ver }}_sig
path: ${{ github.workspace }}/OrcaSlicer_Mac_universal_${{ env.ver }}.dmg.sig
if-no-files-found: ignore
- name: Upload OrcaSlicer_profile_validator DMG mac
if: runner.os == 'macOS' && inputs.macos-combine-only && !vars.SELF_HOSTED
uses: actions/upload-artifact@v7
if: inputs.os == 'macos-14'
uses: actions/upload-artifact@v6
with:
name: OrcaSlicer_profile_validator_Mac_universal_DMG_${{ env.ver }}
path: ${{ github.workspace }}/OrcaSlicer_profile_validator_Mac_universal_${{ env.ver }}.dmg
if-no-files-found: ignore
- name: Deploy Mac release
if: github.repository == 'OrcaSlicer/OrcaSlicer' && github.ref == 'refs/heads/main' && runner.os == 'macOS' && inputs.macos-combine-only && !vars.SELF_HOSTED
if: github.repository == 'OrcaSlicer/OrcaSlicer' && github.ref == 'refs/heads/main' && inputs.os == 'macos-14'
uses: WebFreak001/deploy-nightly@v3.2.0
with:
upload_url: https://uploads.github.com/repos/OrcaSlicer/OrcaSlicer/releases/137995723/assets{?name,label}
@@ -262,7 +259,7 @@ jobs:
max_releases: 1 # optional, if there are more releases than this matching the asset_name, the oldest ones are going to be deleted
- name: Deploy Mac OrcaSlicer_profile_validator DMG release
if: github.repository == 'OrcaSlicer/OrcaSlicer' && github.ref == 'refs/heads/main' && runner.os == 'macOS' && inputs.macos-combine-only && !vars.SELF_HOSTED
if: github.repository == 'OrcaSlicer/OrcaSlicer' && github.ref == 'refs/heads/main' && inputs.os == 'macos-14'
uses: WebFreak001/deploy-nightly@v3.2.0
with:
upload_url: https://uploads.github.com/repos/OrcaSlicer/OrcaSlicer/releases/137995723/assets{?name,label}
@@ -274,72 +271,71 @@ jobs:
# Windows
- name: setup MSVC
if: runner.os == 'Windows'
uses: microsoft/setup-msbuild@v3
if: inputs.os == 'windows-latest'
uses: microsoft/setup-msbuild@v2
- name: Install nsis
if: runner.os == 'Windows' && !vars.SELF_HOSTED
if: inputs.os == 'windows-latest'
run: |
dir "C:/Program Files (x86)/Windows Kits/10/Include"
choco install nsis
- name: Build slicer Win
if: runner.os == 'Windows'
if: inputs.os == 'windows-latest'
working-directory: ${{ github.workspace }}
# Orca: Removed Netfabb STL fixing service support in favor of CGAL.
# env:
# WindowsSdkDir: 'C:\Program Files (x86)\Windows Kits\10\'
# WindowsSDKVersion: '10.0.26100.0\'
env:
WindowsSdkDir: 'C:\Program Files (x86)\Windows Kits\10\'
WindowsSDKVersion: '10.0.26100.0\'
run: .\build_release_vs.bat slicer
- name: Create installer Win
if: runner.os == 'Windows' && !vars.SELF_HOSTED
if: inputs.os == 'windows-latest'
working-directory: ${{ github.workspace }}/build
run: |
cpack -G NSIS
- name: Pack app
if: runner.os == 'Windows'
if: inputs.os == 'windows-latest'
working-directory: ${{ github.workspace }}/build
shell: cmd
run: '"C:/Program Files/7-Zip/7z.exe" a -tzip OrcaSlicer_Windows_${{ env.ver }}_portable.zip ${{ github.workspace }}/build/OrcaSlicer'
- name: Pack PDB
if: runner.os == 'Windows' && !vars.SELF_HOSTED
if: inputs.os == 'windows-latest'
working-directory: ${{ github.workspace }}/build/src/Release
shell: cmd
run: '"C:/Program Files/7-Zip/7z.exe" a -m0=lzma2 -mx9 Debug_PDB_${{ env.ver }}_for_developers_only.7z *.pdb'
- name: Upload artifacts Win zip
if: runner.os == 'Windows'
uses: actions/upload-artifact@v7
if: inputs.os == 'windows-latest'
uses: actions/upload-artifact@v6
with:
name: OrcaSlicer_Windows_${{ env.ver }}_portable
path: ${{ github.workspace }}/build/OrcaSlicer
- name: Upload artifacts Win installer
if: runner.os == 'Windows' && !vars.SELF_HOSTED
uses: actions/upload-artifact@v7
if: inputs.os == 'windows-latest'
uses: actions/upload-artifact@v6
with:
name: OrcaSlicer_Windows_${{ env.ver }}
path: ${{ github.workspace }}/build/OrcaSlicer*.exe
- name: Upload artifacts Win PDB
if: runner.os == 'Windows' && !vars.SELF_HOSTED
uses: actions/upload-artifact@v7
if: inputs.os == 'windows-latest'
uses: actions/upload-artifact@v6
with:
name: PDB
path: ${{ github.workspace }}/build/src/Release/Debug_PDB_${{ env.ver }}_for_developers_only.7z
- name: Upload OrcaSlicer_profile_validator Win
if: runner.os == 'Windows' && !vars.SELF_HOSTED
uses: actions/upload-artifact@v7
if: inputs.os == 'windows-latest'
uses: actions/upload-artifact@v6
with:
name: OrcaSlicer_profile_validator_Windows_${{ env.ver }}
path: ${{ github.workspace }}/build/src/Release/OrcaSlicer_profile_validator.exe
- name: Deploy Windows release portable
if: github.repository == 'OrcaSlicer/OrcaSlicer' && github.ref == 'refs/heads/main' && runner.os == 'Windows' && !vars.SELF_HOSTED
if: github.repository == 'OrcaSlicer/OrcaSlicer' && github.ref == 'refs/heads/main' && inputs.os == 'windows-latest'
uses: WebFreak001/deploy-nightly@v3.2.0
with:
upload_url: https://uploads.github.com/repos/OrcaSlicer/OrcaSlicer/releases/137995723/assets{?name,label}
@@ -350,7 +346,7 @@ jobs:
max_releases: 1
- name: Deploy Windows release installer
if: github.repository == 'OrcaSlicer/OrcaSlicer' && github.ref == 'refs/heads/main' && runner.os == 'Windows' && !vars.SELF_HOSTED
if: github.repository == 'OrcaSlicer/OrcaSlicer' && github.ref == 'refs/heads/main' && inputs.os == 'windows-latest'
uses: WebFreak001/deploy-nightly@v3.2.0
with:
upload_url: https://uploads.github.com/repos/OrcaSlicer/OrcaSlicer/releases/137995723/assets{?name,label}
@@ -361,7 +357,7 @@ jobs:
max_releases: 1
- name: Deploy Windows OrcaSlicer_profile_validator release
if: github.repository == 'OrcaSlicer/OrcaSlicer' && github.ref == 'refs/heads/main' && runner.os == 'Windows' && !vars.SELF_HOSTED
if: github.repository == 'OrcaSlicer/OrcaSlicer' && github.ref == 'refs/heads/main' && inputs.os == 'windows-latest'
uses: WebFreak001/deploy-nightly@v3.2.0
with:
upload_url: https://uploads.github.com/repos/OrcaSlicer/OrcaSlicer/releases/137995723/assets{?name,label}
@@ -373,17 +369,18 @@ jobs:
# Ubuntu
- name: Apt-Install Dependencies
if: runner.os == 'Linux' && !vars.SELF_HOSTED
if: inputs.os == 'ubuntu-24.04'
uses: ./.github/actions/apt-install-deps
# Tests must built at the same time as the slicer;
# if you untangle them feel free to separate them here too
- name: Build slicer and tests
if: runner.os == 'Linux'
if: inputs.os == 'ubuntu-20.04' || inputs.os == 'ubuntu-24.04'
shell: bash
env:
ubuntu-ver-str: ${{ (inputs.os == 'ubuntu-24.04' && '_Ubuntu2404') || '' }}
run: |
./build_linux.sh -istrlL
./scripts/check_appimage_libs.sh ./build/package ./build/package/bin/orca-slicer
./build_linux.sh -istr
mv -n ./build/OrcaSlicer_Linux_V${{ env.ver_pure }}.AppImage ./build/OrcaSlicer_Linux_AppImage${{ env.ubuntu-ver-str }}_${{ env.ver }}.AppImage
chmod +x ./build/OrcaSlicer_Linux_AppImage${{ env.ubuntu-ver-str }}_${{ env.ver }}.AppImage
tar -cvpf build_tests.tar build/tests
@@ -391,8 +388,8 @@ jobs:
# Use tar because upload-artifacts won't always preserve directory structure
# and doesn't preserve file permissions
- name: Upload Test Artifact
if: runner.os == 'Linux'
uses: actions/upload-artifact@v7
if: inputs.os == 'ubuntu-24.04'
uses: actions/upload-artifact@v6
with:
name: ${{ github.sha }}-tests
overwrite: true
@@ -400,18 +397,8 @@ jobs:
retention-days: 5
if-no-files-found: error
- name: Run external slicer regression tests
if: runner.os == 'Linux'
timeout-minutes: 20
shell: bash
run: |
test_repo_dir="${{ runner.temp }}/orca-test-repo"
rm -rf "$test_repo_dir"
git clone --depth 1 https://github.com/OrcaSlicer/orca-test-repo.git "$test_repo_dir"
python3 "$test_repo_dir/run_test.py" "${{ github.workspace }}/build/package/bin/orca-slicer"
- name: Build orca_custom_preset_tests
if: github.ref == 'refs/heads/main' && runner.os == 'Linux' && !vars.SELF_HOSTED
if: github.ref == 'refs/heads/main' && inputs.os == 'ubuntu-24.04'
working-directory: ${{ github.workspace }}/build/src/Release
shell: bash
run: |
@@ -420,21 +407,28 @@ jobs:
zip -r orca_custom_preset_tests.zip user/
- name: Upload artifacts Ubuntu
if: ${{ ! env.ACT && runner.os == 'Linux' }}
uses: actions/upload-artifact@v7
if: ${{ ! env.ACT && inputs.os == 'ubuntu-20.04' || inputs.os == 'ubuntu-24.04' }}
env:
ubuntu-ver: ${{ (inputs.os == 'ubuntu-20.04' && '2004') || (inputs.os == 'ubuntu-24.04' && '2404') || '' }}
ubuntu-ver-str: ${{ (inputs.os == 'ubuntu-24.04' && '_Ubuntu2404') || '' }}
uses: actions/upload-artifact@v6
with:
name: OrcaSlicer_Linux_ubuntu_${{ env.ubuntu-ver }}_${{ env.ver }}
path: './build/OrcaSlicer_Linux_AppImage${{ env.ubuntu-ver-str }}_${{ env.ver }}.AppImage'
- name: Upload OrcaSlicer_profile_validator Ubuntu
if: ${{ ! env.ACT && runner.os == 'Linux' && !vars.SELF_HOSTED }}
uses: actions/upload-artifact@v7
if: ${{ ! env.ACT && inputs.os == 'ubuntu-20.04' || inputs.os == 'ubuntu-24.04' }}
env:
ubuntu-ver: ${{ (inputs.os == 'ubuntu-20.04' && '2004') || (inputs.os == 'ubuntu-24.04' && '2404') || '' }}
uses: actions/upload-artifact@v6
with:
name: OrcaSlicer_profile_validator_Linux_ubuntu_${{ env.ubuntu-ver }}_${{ env.ver }}
path: './build/src/Release/OrcaSlicer_profile_validator'
- name: Deploy Ubuntu release
if: ${{ github.repository == 'OrcaSlicer/OrcaSlicer' && ! env.ACT && github.ref == 'refs/heads/main' && runner.os == 'Linux' && !vars.SELF_HOSTED }}
if: ${{ github.repository == 'OrcaSlicer/OrcaSlicer' && ! env.ACT && github.ref == 'refs/heads/main' && (inputs.os == 'ubuntu-20.04' || inputs.os == 'ubuntu-24.04') }}
env:
ubuntu-ver-str: ${{ (inputs.os == 'ubuntu-24.04' && '_Ubuntu2404') || '' }}
uses: WebFreak001/deploy-nightly@v3.2.0
with:
upload_url: https://uploads.github.com/repos/OrcaSlicer/OrcaSlicer/releases/137995723/assets{?name,label}
@@ -444,7 +438,7 @@ jobs:
asset_content_type: application/octet-stream
max_releases: 1 # optional, if there are more releases than this matching the asset_name, the oldest ones are going to be deleted
- name: Deploy Ubuntu release
if: ${{ github.repository == 'OrcaSlicer/OrcaSlicer' && ! env.ACT && github.ref == 'refs/heads/main' && runner.os == 'Linux' && !vars.SELF_HOSTED }}
if: ${{ github.repository == 'OrcaSlicer/OrcaSlicer' && ! env.ACT && github.ref == 'refs/heads/main' && inputs.os == 'ubuntu-24.04' }}
uses: rickstaa/action-create-tag@v1
with:
tag: "nightly-builds"
@@ -453,7 +447,9 @@ jobs:
message: "nightly-builds"
- name: Deploy Ubuntu OrcaSlicer_profile_validator release
if: ${{ github.repository == 'OrcaSlicer/OrcaSlicer' && ! env.ACT && github.ref == 'refs/heads/main' && runner.os == 'Linux' && !vars.SELF_HOSTED }}
if: ${{ github.repository == 'OrcaSlicer/OrcaSlicer' && ! env.ACT && github.ref == 'refs/heads/main' && (inputs.os == 'ubuntu-20.04' || inputs.os == 'ubuntu-24.04') }}
env:
ubuntu-ver-str: ${{ (inputs.os == 'ubuntu-24.04' && '_Ubuntu2404') || '' }}
uses: WebFreak001/deploy-nightly@v3.2.0
with:
upload_url: https://uploads.github.com/repos/OrcaSlicer/OrcaSlicer/releases/137995723/assets{?name,label}
@@ -464,7 +460,7 @@ jobs:
max_releases: 1
- name: Deploy orca_custom_preset_tests
if: ${{ github.repository == 'OrcaSlicer/OrcaSlicer' && ! env.ACT && github.ref == 'refs/heads/main' && runner.os == 'Linux' && !vars.SELF_HOSTED }}
if: ${{ github.repository == 'OrcaSlicer/OrcaSlicer' && ! env.ACT && github.ref == 'refs/heads/main' && inputs.os == 'ubuntu-24.04' }}
uses: WebFreak001/deploy-nightly@v3.2.0
with:
upload_url: https://uploads.github.com/repos/OrcaSlicer/OrcaSlicer/releases/137995723/assets{?name,label}

View File

@@ -1,8 +1,8 @@
name: Check profiles
on:
on:
pull_request:
branches:
- main
branches:
- main
paths:
- 'resources/profiles/**'
- ".github/workflows/check_profiles.yml"
@@ -10,72 +10,25 @@ on:
workflow_dispatch:
inputs:
logLevel:
description: 'Log level'
description: 'Log level'
required: true
default: 'warning'
permissions:
contents: read
jobs:
check_profiles:
check_translation:
name: Check profiles
runs-on: ubuntu-24.04
steps:
steps:
- name: Checkout repository
uses: actions/checkout@v6
- name: Run extra JSON check
id: extra_json_check
continue-on-error: true
run: |
set +e
python3 ./scripts/orca_extra_profile_check.py 2>&1 | tee ${{ runner.temp }}/extra_json_check.log
exit ${PIPESTATUS[0]}
- name: Check profile indentation
id: indentation_check
continue-on-error: true
run: |
set +e
python3 - <<'PY' 2>&1 | tee ${{ runner.temp }}/indentation_check.log
import re
from pathlib import Path
import sys
profiles_root = Path("resources/profiles")
invalid_files = []
for file_path in sorted(profiles_root.rglob("*.json")):
try:
for line_number, line in enumerate(file_path.read_text(encoding="utf-8").splitlines(), start=1):
if not line.strip():
continue
leading_ws = re.match(r"^[ \t]*", line).group(0)
if " " in leading_ws:
invalid_files.append((file_path, line_number))
break
except Exception as exc:
print(f"[ERROR] Unable to read {file_path}: {exc}")
invalid_files.append((file_path, 0))
if invalid_files:
for path, line in invalid_files:
if line > 0:
print(f"[ERROR] Space indentation found in {path}:{line}")
else:
print(f"[ERROR] Could not validate indentation in {path}")
print("Use tab indentation in profile JSON files (1 tab per indentation level).")
print("Tip: run python3 ./scripts/orca_filament_lib.py --fix --force to normalize formatting.")
sys.exit(1)
print("All profile JSON files use tab-only indentation.")
PY
exit ${PIPESTATUS[0]}
python3 ./scripts/orca_extra_profile_check.py
# download
- name: Download
- name: Download
working-directory: ${{ github.workspace }}
run: |
curl -LJO https://github.com/SoftFever/Orca_tools/releases/download/1/OrcaSlicer_profile_validator
@@ -83,85 +36,16 @@ jobs:
# validate profiles
- name: validate system profiles
id: validate_system
continue-on-error: true
run: |
set +e
./OrcaSlicer_profile_validator -p ${{ github.workspace }}/resources/profiles -l 2 2>&1 | tee ${{ runner.temp }}/validate_system.log
exit ${PIPESTATUS[0]}
./OrcaSlicer_profile_validator -p ${{ github.workspace }}/resources/profiles -l 2
- name: validate custom presets
id: validate_custom
continue-on-error: true
working-directory: ${{ github.workspace }}
run: |
set +e
curl -LJO https://github.com/OrcaSlicer/OrcaSlicer/releases/download/nightly-builds/orca_custom_preset_tests.zip
unzip -q ./orca_custom_preset_tests.zip -d ${{ github.workspace }}/resources/profiles
./OrcaSlicer_profile_validator -p ${{ github.workspace }}/resources/profiles -l 2 2>&1 | tee ${{ runner.temp }}/validate_custom.log
exit ${PIPESTATUS[0]}
unzip ./orca_custom_preset_tests.zip -d ${{ github.workspace }}/resources/profiles
./OrcaSlicer_profile_validator -p ${{ github.workspace }}/resources/profiles -l 2
- name: Prepare comment artifact
if: ${{ always() && github.event_name == 'pull_request' && (steps.extra_json_check.outcome == 'failure' || steps.indentation_check.outcome == 'failure' || steps.validate_system.outcome == 'failure' || steps.validate_custom.outcome == 'failure') }}
run: |
mkdir -p ${{ runner.temp }}/profile-check-results
{
echo "## :x: Profile Validation Errors"
echo ""
if [ "${{ steps.extra_json_check.outcome }}" = "failure" ]; then
echo "### Extra JSON Check Failed"
echo ""
echo '```'
head -c 30000 ${{ runner.temp }}/extra_json_check.log || echo "No output captured"
echo '```'
echo ""
fi
if [ "${{ steps.indentation_check.outcome }}" = "failure" ]; then
echo "### Indentation Check Failed"
echo ""
echo '```'
head -c 30000 ${{ runner.temp }}/indentation_check.log || echo "No output captured"
echo '```'
echo ""
fi
if [ "${{ steps.validate_system.outcome }}" = "failure" ]; then
echo "### System Profile Validation Failed"
echo ""
echo '```'
head -c 30000 ${{ runner.temp }}/validate_system.log || echo "No output captured"
echo '```'
echo ""
fi
if [ "${{ steps.validate_custom.outcome }}" = "failure" ]; then
echo "### Custom Preset Validation Failed"
echo ""
echo '```'
head -c 30000 ${{ runner.temp }}/validate_custom.log || echo "No output captured"
echo '```'
echo ""
fi
echo "---"
echo "*Please fix the above errors and push a new commit.*"
} > ${{ runner.temp }}/profile-check-results/pr_comment.md
echo "${{ github.event.pull_request.number }}" > ${{ runner.temp }}/profile-check-results/pr_number.txt
- name: Upload comment artifact
if: ${{ always() && github.event_name == 'pull_request' && (steps.extra_json_check.outcome == 'failure' || steps.indentation_check.outcome == 'failure' || steps.validate_system.outcome == 'failure' || steps.validate_custom.outcome == 'failure') }}
uses: actions/upload-artifact@v7
with:
name: profile-check-results
path: ${{ runner.temp }}/profile-check-results/
retention-days: 1
- name: Fail if any check failed
if: ${{ always() && (steps.extra_json_check.outcome == 'failure' || steps.indentation_check.outcome == 'failure' || steps.validate_system.outcome == 'failure' || steps.validate_custom.outcome == 'failure') }}
run: |
echo "One or more profile checks failed. See above for details."
exit 1

View File

@@ -1,46 +0,0 @@
name: Post profile check comment
# NOTE: The workflow name in the 'workflows' filter below must match the 'name'
# field in check_profiles.yml exactly. If that name changes, update it here too.
on:
workflow_run:
workflows: ["Check profiles"]
types:
- completed
permissions:
pull-requests: write
jobs:
post_comment:
name: Post PR comment
runs-on: ubuntu-24.04
if: ${{ github.event.workflow_run.event == 'pull_request' && github.event.workflow_run.conclusion == 'failure' }}
steps:
- name: Download artifact
id: download
uses: actions/download-artifact@v8
continue-on-error: true
with:
name: profile-check-results
run-id: ${{ github.event.workflow_run.id }}
github-token: ${{ github.token }}
- name: Post comment on PR
if: ${{ steps.download.outcome == 'success' }}
env:
GH_TOKEN: ${{ github.token }}
GH_REPO: ${{ github.repository }}
run: |
if [ ! -f pr_number.txt ] || [ ! -f pr_comment.md ]; then
echo "No comment artifact found, skipping."
exit 0
fi
PR_NUMBER=$(cat pr_number.txt)
if ! [[ "$PR_NUMBER" =~ ^[0-9]+$ ]]; then
echo "Invalid PR number: $PR_NUMBER"
exit 1
fi
gh pr comment "$PR_NUMBER" --body-file pr_comment.md

138
.github/workflows/generate_appcast.yml vendored Normal file
View File

@@ -0,0 +1,138 @@
name: Generate Appcast
on:
release:
types: [published]
workflow_dispatch:
inputs:
version:
description: 'Version to generate appcast for (e.g., 2.3.2)'
required: true
jobs:
generate_appcast:
name: Generate and Deploy Appcast
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: Get version from release or input
id: version
run: |
if [ "${{ github.event_name }}" == "release" ]; then
VERSION="${{ github.event.release.tag_name }}"
VERSION="${VERSION#v}" # Remove 'v' prefix if present
else
VERSION="${{ github.event.inputs.version }}"
fi
echo "version=$VERSION" >> $GITHUB_OUTPUT
echo "Version: $VERSION"
- name: Download release assets info
id: assets
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
VERSION="${{ steps.version.outputs.version }}"
TAG="v$VERSION"
# Get release info
RELEASE_URL="https://github.com/${{ github.repository }}/releases/tag/$TAG"
echo "release_url=$RELEASE_URL" >> $GITHUB_OUTPUT
# Get macOS DMG URL and size
# Use browser_download_url for public access (not .url which is the API endpoint)
MAC_ASSET=$(gh release view "$TAG" --json assets -q '.assets[] | select(.name | contains("Mac_universal")) | select(.name | endswith(".dmg"))')
if [ -n "$MAC_ASSET" ]; then
MAC_URL=$(echo "$MAC_ASSET" | jq -r '.browser_download_url // .url')
MAC_SIZE=$(echo "$MAC_ASSET" | jq -r '.size')
echo "mac_url=$MAC_URL" >> $GITHUB_OUTPUT
echo "mac_size=$MAC_SIZE" >> $GITHUB_OUTPUT
fi
# Get Windows installer URL and size
# Use browser_download_url for public access (not .url which is the API endpoint)
WIN_ASSET=$(gh release view "$TAG" --json assets -q '.assets[] | select(.name | contains("Windows_Installer")) | select(.name | endswith(".exe"))')
if [ -n "$WIN_ASSET" ]; then
WIN_URL=$(echo "$WIN_ASSET" | jq -r '.browser_download_url // .url')
WIN_SIZE=$(echo "$WIN_ASSET" | jq -r '.size')
echo "win_url=$WIN_URL" >> $GITHUB_OUTPUT
echo "win_size=$WIN_SIZE" >> $GITHUB_OUTPUT
fi
- name: Download signatures
id: signatures
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
VERSION="${{ steps.version.outputs.version }}"
TAG="v$VERSION"
# Try to download macOS signature artifact
MAC_SIG_ARTIFACT="OrcaSlicer_Mac_universal_V${VERSION}_sig"
if gh run download --name "$MAC_SIG_ARTIFACT" -D /tmp/mac_sig 2>/dev/null; then
MAC_SIG=$(cat /tmp/mac_sig/*.sig)
echo "mac_signature=$MAC_SIG" >> $GITHUB_OUTPUT
echo "Found macOS signature: $MAC_SIG"
else
echo "No macOS signature artifact found"
fi
# For Windows, signature would come from WinSparkle signing (if implemented)
# echo "win_signature=$WIN_SIG" >> $GITHUB_OUTPUT
- name: Generate appcast.xml
run: |
python scripts/generate_appcast.py \
--version "${{ steps.version.outputs.version }}" \
--release-notes-url "${{ steps.assets.outputs.release_url }}" \
--mac-url "${{ steps.assets.outputs.mac_url }}" \
--mac-signature "${{ steps.signatures.outputs.mac_signature }}" \
--mac-length "${{ steps.assets.outputs.mac_size }}" \
--output appcast.xml
echo "Generated appcast.xml:"
cat appcast.xml
- name: Upload appcast artifact
uses: actions/upload-artifact@v4
with:
name: appcast
path: appcast.xml
# Deploy to Cloudflare KV (for check-version.orcaslicer.com Worker)
- name: Deploy appcast to Cloudflare KV
if: github.event_name == 'release'
env:
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
KV_NAMESPACE_ID: ${{ secrets.CLOUDFLARE_KV_APPCAST_ID }}
run: |
if [ -n "$CLOUDFLARE_API_TOKEN" ] && [ -n "$CLOUDFLARE_ACCOUNT_ID" ] && [ -n "$KV_NAMESPACE_ID" ]; then
# Deploy appcast.xml
curl -X PUT \
"https://api.cloudflare.com/client/v4/accounts/$CLOUDFLARE_ACCOUNT_ID/storage/kv/namespaces/$KV_NAMESPACE_ID/values/appcast.xml" \
-H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
-H "Content-Type: text/plain" \
--data-binary @appcast.xml
echo "Appcast deployed to Cloudflare KV"
# Deploy macOS signature file (for verification/auditing)
if [ -n "${{ steps.signatures.outputs.mac_signature }}" ]; then
echo "${{ steps.signatures.outputs.mac_signature }}" > mac_signature.txt
curl -X PUT \
"https://api.cloudflare.com/client/v4/accounts/$CLOUDFLARE_ACCOUNT_ID/storage/kv/namespaces/$KV_NAMESPACE_ID/values/signatures/${{ steps.version.outputs.version }}/mac.sig" \
-H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
-H "Content-Type: text/plain" \
--data-binary @mac_signature.txt
echo "macOS signature deployed to Cloudflare KV"
fi
else
echo "Cloudflare credentials not configured, skipping deployment"
fi

View File

@@ -1,275 +0,0 @@
name: PR Label Bot
on:
pull_request_target:
types:
- opened
- reopened
issue_comment:
types:
- created
permissions:
contents: read
pull-requests: write
issues: write
jobs:
request-label:
if: github.event_name == 'pull_request_target' && github.event.pull_request.author_association != 'COLLABORATOR' && github.event.pull_request.author_association != 'OWNER' && github.event.pull_request.author_association != 'MEMBER'
permissions:
contents: read
pull-requests: write
issues: write
runs-on: ubuntu-latest
steps:
- name: Ask PR author for label
uses: actions/github-script@v7
with:
script: |
function isPermissionDenied(error) {
return error && error.status === 403 && /Resource not accessible by integration/i.test(error.message || '');
}
const allowedLabels = [
'bug-fix',
'enhancement',
'Localization',
'profile',
'QoL',
'UI/UX',
'dependencies'
];
const pr = context.payload.pull_request;
const labelsList = `${allowedLabels
.slice(0, -1)
.map((label) => `\`${label}\``)
.join(', ')} and \`${allowedLabels[allowedLabels.length - 1]}\`.`;
const examplesText = [
'```',
'/bot add-label bug-fix',
'```',
'```',
'/bot add-label bug-fix, UI/UX',
'```',
'```',
'/bot remove-label bug-fix, UI/UX',
'```'
].join('\n');
try {
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: pr.number,
body:
`Hi @${pr.user.login}, you can manage the labels for this PR by \`/bot add-label\` and \`/bot remove-label\`\n\n` +
`Allowed labels are:\n${labelsList}\n\n` +
`Examples:\n${examplesText}`
});
} catch (error) {
if (isPermissionDenied(error)) {
core.warning(
'Skipping PR comment because token cannot write. Enable Actions write permissions, ' +
'or run with a token that has issues:write and pull_requests:write.'
);
return;
}
throw error;
}
apply-label:
if: github.event_name == 'issue_comment'
permissions:
contents: read
pull-requests: write
issues: write
runs-on: ubuntu-latest
steps:
- name: Apply label command from PR author
uses: actions/github-script@v7
with:
script: |
function isPermissionDenied(error) {
return error && error.status === 403 && /Resource not accessible by integration/i.test(error.message || '');
}
const allowedLabels = [
'bug-fix',
'enhancement',
'Localization',
'profile',
'QoL',
'UI/UX',
'dependencies'
];
const issue = context.payload.issue;
if (!issue.pull_request) {
core.info('Ignoring comment that is not on a pull request.');
return;
}
const body = (context.payload.comment.body || '').trim();
const commandLine = body
.split('\n')
.map((line) => line.trim())
.find((line) => /^\/bot\s+(add-label|remove-label)(?:\s*:\s*|\s+)/i.test(line));
if (!commandLine) {
core.info('No /bot add-label or /bot remove-label command found.');
return;
}
const commandMatch = commandLine.match(/^\/bot\s+(add-label|remove-label)(?:\s*:\s*|\s+)(.+)\s*$/i);
if (!commandMatch) {
core.info('Label command format is invalid.');
return;
}
const action = commandMatch[1].toLowerCase() === 'add-label' ? 'add' : 'remove';
let labelsExpr = (commandMatch[2] || '').trim();
if (!labelsExpr) {
core.info('Label command is missing label name.');
return;
}
if (labelsExpr.startsWith('[') && labelsExpr.endsWith(']')) {
labelsExpr = labelsExpr.slice(1, -1).trim();
}
const requestedRawLabels = labelsExpr
.split(',')
.map((part) => part.trim())
.filter(Boolean);
if (!requestedRawLabels.length) {
core.info('No labels were provided in the command.');
return;
}
const { data: pr } = await github.rest.pulls.get({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: issue.number
});
const commenter = context.payload.comment.user.login;
if (commenter !== pr.user.login) {
core.info('Ignoring command because commenter is not the PR author.');
return;
}
const labelsByLower = new Map(
allowedLabels.map((label) => [label.toLowerCase(), label])
);
const resolvedLabels = [];
const invalidLabels = [];
for (const rawLabel of requestedRawLabels) {
const resolved = labelsByLower.get(rawLabel.toLowerCase());
if (resolved) {
resolvedLabels.push(resolved);
} else {
invalidLabels.push(rawLabel);
}
}
const uniqueRequestedLabels = [...new Set(resolvedLabels)];
if (action === 'add' && uniqueRequestedLabels.length) {
try {
await github.rest.issues.addLabels({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: issue.number,
labels: uniqueRequestedLabels
});
} catch (error) {
if (isPermissionDenied(error)) {
core.warning(
'Cannot add labels because token cannot write. Enable Actions write permissions, ' +
'or run with a token that has issues:write and pull_requests:write.'
);
return;
}
throw error;
}
core.info(`Added labels: ${uniqueRequestedLabels.join(', ')}`);
}
if (action === 'remove' && uniqueRequestedLabels.length) {
let removedCount = 0;
try {
for (const label of uniqueRequestedLabels) {
try {
await github.rest.issues.removeLabel({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: issue.number,
name: label
});
removedCount += 1;
} catch (error) {
if (isPermissionDenied(error)) {
core.warning(
'Cannot remove labels because token cannot write. Enable Actions write permissions, ' +
'or run with a token that has issues:write and pull_requests:write.'
);
return;
}
if (error.status === 404) {
core.info(`Label is not currently applied: ${label}`);
continue;
}
throw error;
}
}
core.info(`Removed labels count: ${removedCount}`);
} catch (error) {
throw error;
}
}
if (!uniqueRequestedLabels.length) {
core.info('No valid labels were provided in the command.');
}
if (invalidLabels.length) {
const allowedText = allowedLabels.map((label) => `\`${label}\``).join(', ');
const invalidText = invalidLabels.map((label) => `\`${label}\``).join(', ');
const validText = uniqueRequestedLabels.length
? `\n\nProcessed valid label(s): ${uniqueRequestedLabels.map((label) => `\`${label}\``).join(', ')}`
: '';
try {
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: issue.number,
body:
`@${commenter} invalid label(s): ${invalidText}.${validText}\n\n` +
`Allowed labels: ${allowedText}\n\n` +
`Use:\n` +
`- \`/bot add-label label\`\n` +
`- \`/bot remove-label label\`\n` +
`- \`/bot add-label label1, label2\``
});
} catch (error) {
if (isPermissionDenied(error)) {
core.warning('Cannot post invalid-label feedback because token cannot write comments.');
return;
}
throw error;
}
}
const processedLabelsText = uniqueRequestedLabels.length ? uniqueRequestedLabels.join(', ') : '(none)';
core.info(`Processed label command: ${action} ${processedLabelsText}`);

View File

@@ -1,14 +0,0 @@
name: Publish to WinGet
on:
release:
types: [ released ]
jobs:
publish:
runs-on: windows-latest
steps:
- uses: vedantmgoyal9/winget-releaser@main
with:
identifier: SoftFever.OrcaSlicer
version: ${{ github.event.release.tag_name }}
token: ${{ secrets.WINGET_TOKEN }}
installers-regex: '\.exe$'

5
.gitignore vendored
View File

@@ -36,7 +36,6 @@ src/OrcaSlicer-doc/
/deps/DL_CACHE/
/deps/DL_CACHE
**/.flatpak-builder/
*.no-debug.yml
resources/profiles/user/default
*.code-workspace
deps_src/build/
@@ -44,5 +43,5 @@ test.js
/.cache/
.clangd
internal_docs/
*.flatpak
/flatpak-repo/
# Sparkle auto-update test artifacts
/.sparkle-test/

View File

@@ -1,48 +1,23 @@
# CLAUDE.md
# Repository Guidelines
OrcaSlicer — open-source C++17 3D slicer. wxWidgets GUI, CMake build system.
## Project Structure & Module Organization
OrcaSlicers C++17 sources live in `src/`, split by feature modules and platform adapters. User assets, icons, and printer presets are in `resources/`; translations stay in `localization/`. Tests sit in `tests/`, grouped by domain (`libslic3r/`, `sla_print/`, etc.) with fixtures under `tests/data/`. CMake helpers reside in `cmake/`, and longer references in `doc/` and `SoftFever_doc/`. Automation scripts belong in `scripts/` and `tools/`. Treat everything in `deps/` and `deps_src/` as vendored snapshots—do not modify without mirroring upstream tags.
## Build Commands
## Build, Test, and Development Commands
Use out-of-source builds:
- `cmake -S . -B build -DCMAKE_BUILD_TYPE=Release` configures dependencies and generates build files.
- `cmake --build build --target OrcaSlicer --config Release` compiles the app; add `--parallel` to speed up.
- `cmake --build build --target tests` then `ctest --test-dir build --output-on-failure` runs automated suites.
Platform helpers such as `build_linux.sh`, `build_release_macos.sh`, and `build_release_vs2022.bat` wrap the same flow with toolchain flags. Use `build_release_macos.sh -sx` when reproducing macOS build issues, and `scripts/DockerBuild.sh` for reproducible container builds.
```bash
# macOS
cmake --build build/arm64 --config RelWithDebInfo --target all --
## Coding Style & Naming Conventions
`.clang-format` enforces 4-space indents, a 140-column limit, aligned initializers, and brace wrapping for classes and functions. Run `clang-format -i <file>` before committing; the CMake `clang-format` target is available when LLVM tools are on your PATH. Prefer `CamelCase` for classes, `snake_case` for functions and locals, and `SCREAMING_CASE` for constants, matching conventions in `src/`. Keep headers self-contained and align include order with the IWYU pragmas.
# Linux
cmake --build build --config RelWithDebInfo --target all --
## Testing Guidelines
Unit tests rely on Catch2 (`tests/catch2/`). Name specs after the component under test—for example `tests/libslic3r/TestPlanarHole.cpp`—and tag long-running cases so `ctest -L fast` remains useful. Cover new algorithms with deterministic fixtures or sample G-code stored in `tests/data/`. Document manual printer validation or regression slicer checks in your PR when automated coverage is insufficient.
# Windows (replace %build_type% with Debug/Release/RelWithDebInfo)
cmake --build . --config %build_type% --target ALL_BUILD -- -m
```
## Commit & Pull Request Guidelines
The history favors concise, sentence-style subject lines with optional issue references, e.g., `Fix grid lines origin for multiple plates (#10724)`. Squash fixups locally before opening a PR. Complete `.github/pull_request_template.md`, include reproduction steps or screenshots for UI changes, and mention impacted presets or translations. Link issues via `Closes #NNNN` when applicable, and call out dependency bumps or profile migrations for maintainer review.
## Testing
Catch2 framework. Tests in `tests/` directory.
```bash
cd build && ctest --output-on-failure # all tests
ctest --test-dir ./tests/libslic3r # individual suite
ctest --test-dir ./tests/fff_print
```
## Code Style
- C++17, selective C++20. PascalCase classes, snake_case functions/variables
- `#pragma once` for headers. Smart pointers and RAII preferred
- Parallelization via TBB — be mindful of shared state
## Key Entry Points
- App startup: `src/OrcaSlicer.cpp`
- Slicing pipeline: `src/libslic3r/Print.cpp`
- All print/printer/material settings: `src/libslic3r/PrintConfig.cpp`
- GUI: `src/slic3r/GUI/`
- Core algorithms: `src/libslic3r/` (GCode/, Fill/, Support/, Geometry/, Format/, Arachne/)
- Printer profiles: `resources/profiles/[manufacturer].json`
## Critical Constraints
- **Backward compatibility required** for .3mf project files and printer profiles
- **Cross-platform** — all changes must work on Windows, macOS, and Linux
- Profile/format changes need version migration handling
- Dependencies built separately in `deps/build/`, then linked to main app
## Security & Configuration Tips
Follow `SECURITY.md` for vulnerability reporting. Keep API tokens and printer credentials out of tracked configs; use `sandboxes/` for experimental settings. When touching third-party code in `deps_src/`, record the upstream commit or release in your PR description and run the relevant platform build script to confirm integration.

260
CLAUDE.md
View File

@@ -1 +1,259 @@
@AGENTS.md
# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## Overview
OrcaSlicer is an open-source 3D slicer application forked from Bambu Studio, built using C++ with wxWidgets for the GUI and CMake as the build system. The project uses a modular architecture with separate libraries for core slicing functionality, GUI components, and platform-specific code.
## Build Commands
### Building on Windows
```bash
# Build everything
build_release_vs2022.bat
# Build with debug symbols
build_release_vs2022.bat debug
# Build only dependencies
build_release_vs2022.bat deps
# Build only slicer (after deps are built)
build_release_vs2022.bat slicer
```
### Building on macOS
```bash
# Build everything (dependencies and slicer)
./build_release_macos.sh
# Build only dependencies
./build_release_macos.sh -d
# Build only slicer (after deps are built)
./build_release_macos.sh -s
# Use Ninja generator for faster builds
./build_release_macos.sh -x
# Build for specific architecture
./build_release_macos.sh -a arm64 # or x86_64 or universal
# Build for specific macOS version target
./build_release_macos.sh -t 11.3
```
### Building on Linux
```bash
# First time setup - install system dependencies
./build_linux.sh -u
# Build dependencies and slicer
./build_linux.sh -dsi
# Build everything (alternative)
./build_linux.sh -dsi
# Individual options:
./build_linux.sh -d # dependencies only
./build_linux.sh -s # slicer only
./build_linux.sh -i # build AppImage
# Performance and debug options:
./build_linux.sh -j N # limit to N cores
./build_linux.sh -1 # single core build
./build_linux.sh -b # Debug build
./build_linux.sh -e # RelWithDebInfo build
./build_linux.sh -c # clean build
./build_linux.sh -r # skip RAM/disk checks
./build_linux.sh -l # use Clang instead of GCC
```
### Build System
- Uses CMake with minimum version 3.13 (maximum 3.31.x on Windows)
- Primary build directory: `build/`
- Dependencies are built in `deps/build/`
- The build process is split into dependency building and main application building
- Windows builds use Visual Studio generators
- macOS builds use Xcode by default, Ninja with -x flag
- Linux builds use Ninja generator
### Testing
Tests are located in the `tests/` directory and use the Catch2 testing framework. Test structure:
- `tests/libslic3r/` - Core library tests (21 test files)
- Geometry processing, algorithms, file formats (STL, 3MF, AMF)
- Polygon operations, clipper utilities, Voronoi diagrams
- `tests/fff_print/` - Fused Filament Fabrication tests (12 test files)
- Slicing algorithms, G-code generation, print mechanics
- Fill patterns, extrusion, support material
- `tests/sla_print/` - Stereolithography tests (4 test files)
- SLA-specific printing algorithms, support generation
- `tests/libnest2d/` - 2D nesting algorithm tests
- `tests/slic3rutils/` - Utility function tests
- `tests/sandboxes/` - Experimental/sandbox test code
Run all tests after building:
```bash
cd build && ctest
```
Run tests with verbose output:
```bash
cd build && ctest --output-on-failure
```
Run individual test suites:
```bash
# From build directory
ctest --test-dir ./tests/libslic3r/libslic3r_tests
ctest --test-dir ./tests/fff_print/fff_print_tests
ctest --test-dir ./tests/sla_print/sla_print_tests
# and so on
```
## Architecture
### Core Libraries
- **libslic3r/**: Core slicing engine and algorithms (platform-independent)
- Main slicing logic, geometry processing, G-code generation
- Key classes: Print, PrintObject, Layer, GCode, Config
- Modular design with specialized subdirectories:
- `GCode/` - G-code generation, cooling, pressure equalization, thumbnails
- `Fill/` - Infill pattern implementations (gyroid, honeycomb, lightning, etc.)
- `Support/` - Tree supports and traditional support generation
- `Geometry/` - Advanced geometry operations, Voronoi diagrams, medial axis
- `Format/` - File I/O for 3MF, AMF, STL, OBJ, STEP formats
- `SLA/` - SLA-specific print processing and support generation
- `Arachne/` - Advanced wall generation using skeletal trapezoidation
- **src/slic3r/**: Main application framework and GUI
- GUI application built with wxWidgets
- Integration between libslic3r core and user interface
- Located in `src/slic3r/GUI/` (not shown in this directory but exists)
### Key Algorithmic Components
- **Arachne Wall Generation**: Variable-width perimeter generation using skeletal trapezoidation
- **Tree Supports**: Organic support generation algorithm
- **Lightning Infill**: Sparse infill optimization for internal structures
- **Adaptive Slicing**: Variable layer height based on geometry
- **Multi-material**: Multi-extruder and soluble support processing
- **G-code Post-processing**: Cooling, fan control, pressure advance, conflict checking
### File Format Support
- **3MF/BBS_3MF**: Native format with extensions for multi-material and metadata
- **STL**: Standard tessellation language for 3D models
- **AMF**: Additive Manufacturing Format with color/material support
- **OBJ**: Wavefront OBJ with material definitions
- **STEP**: CAD format support for precise geometry
- **G-code**: Output format with extensive post-processing capabilities
### External Dependencies
- **Clipper2**: Advanced 2D polygon clipping and offsetting
- **libigl**: Computational geometry library for mesh operations
- **TBB**: Intel Threading Building Blocks for parallelization
- **wxWidgets**: Cross-platform GUI framework
- **OpenGL**: 3D graphics rendering and visualization
- **CGAL**: Computational Geometry Algorithms Library (selective use)
- **OpenVDB**: Volumetric data structures for advanced operations
- **Eigen**: Linear algebra library for mathematical operations
## File Organization
### Resources and Configuration
- `resources/profiles/` - Printer and material profiles organized by manufacturer
- `resources/printers/` - Printer-specific configurations and G-code templates
- `resources/images/` - UI icons, logos, calibration images
- `resources/calib/` - Calibration test patterns and data
- `resources/handy_models/` - Built-in test models (benchy, calibration cubes)
### Internationalization and Localization
- `localization/i18n/` - Source translation files (.pot, .po)
- `resources/i18n/` - Runtime language resources
- Translation managed via `scripts/run_gettext.sh` / `scripts/run_gettext.bat`
### Platform-Specific Code
- `src/libslic3r/Platform.cpp` - Platform abstractions and utilities
- `src/libslic3r/MacUtils.mm` - macOS-specific utilities (Objective-C++)
- Windows-specific build scripts and configurations
- Linux distribution support scripts in `scripts/linux.d/`
### Build and Development Tools
- `cmake/modules/` - Custom CMake find modules and utilities
- `scripts/` - Python utilities for profile generation and validation
- `tools/` - Windows build tools (gettext utilities)
- `deps/` - External dependency build configurations
## Development Workflow
### Code Style and Standards
- **C++17 standard** with selective C++20 features
- **Naming conventions**: PascalCase for classes, snake_case for functions/variables
- **Header guards**: Use `#pragma once`
- **Memory management**: Prefer smart pointers, RAII patterns
- **Thread safety**: Use TBB for parallelization, be mindful of shared state
### Common Development Tasks
#### Adding New Print Settings
1. Define setting in `PrintConfig.cpp` with proper bounds and defaults
2. Add UI controls in appropriate GUI components
3. Update serialization in config save/load
4. Add tooltips and help text for user guidance
5. Test with different printer profiles
#### Modifying Slicing Algorithms
1. Core algorithms live in `libslic3r/` subdirectories
2. Performance-critical code should be profiled and optimized
3. Consider multi-threading implications (TBB integration)
4. Validate changes don't break existing profiles
5. Add regression tests where appropriate
#### GUI Development
1. GUI code resides in `src/slic3r/GUI/` (not visible in current tree)
2. Use existing wxWidgets patterns and custom controls
3. Support both light and dark themes
4. Consider DPI scaling on high-resolution displays
5. Maintain cross-platform compatibility
#### Adding Printer Support
1. Create JSON profile in `resources/profiles/[manufacturer].json`
2. Add printer-specific start/end G-code templates
3. Configure build volume, capabilities, and material compatibility
4. Test thoroughly with actual hardware when possible
5. Follow existing profile structure and naming conventions
### Dependencies and Build System
- **CMake-based** with separate dependency building phase
- **Dependencies** built once in `deps/build/`, then linked to main application
- **Cross-platform** considerations important for all changes
- **Resource files** embedded at build time, platform-specific handling
### Performance Considerations
- **Slicing algorithms** are CPU-intensive, profile before optimizing
- **Memory usage** can be substantial with complex models
- **Multi-threading** extensively used via TBB
- **File I/O** optimized for large 3MF files with embedded textures
- **Real-time preview** requires efficient mesh processing
## Important Development Notes
### Codebase Navigation
- Use search tools extensively - codebase has 500k+ lines
- Key entry points: `src/OrcaSlicer.cpp` for application startup
- Core slicing: `libslic3r/Print.cpp` orchestrates the slicing pipeline
- Configuration: `PrintConfig.cpp` defines all print/printer/material settings
### Compatibility and Stability
- **Backward compatibility** maintained for project files and profiles
- **Cross-platform** support essential (Windows/macOS/Linux)
- **File format** changes require careful version handling
- **Profile migrations** needed when settings change significantly
### Quality and Testing
- **Regression testing** important due to algorithm complexity
- **Performance benchmarks** help catch performance regressions
- **Memory leak** detection important for long-running GUI application
- **Cross-platform** testing required before releases

View File

@@ -1,9 +1,9 @@
if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "4.0")
set(CMAKE_POLICY_VERSION_MINIMUM 3.13 CACHE STRING "" FORCE)
endif()
cmake_minimum_required(VERSION 3.13)
# Verify that your CMake version is exactly 3.5 series or higher on windows
if ( (MSVC OR WIN32) AND (${CMAKE_VERSION} VERSION_LESS "3.5") )
message(FATAL_ERROR "CMake current version ${CMAKE_VERSION} is too old. Minimum required is 3.5.")
endif()
# The following line used to be in tests/CMakeLists.txt
# Having it there causes rebuilds of all targets on any CMakeLists.txt change under tests/
@@ -85,9 +85,10 @@ else ()
endif ()
find_package(Git)
if(DEFINED ENV{git_commit_hash} AND NOT "$ENV{git_commit_hash}" STREQUAL "")
message(STATUS "Specified git commit hash: $ENV{git_commit_hash}")
if(GIT_FOUND AND EXISTS "${CMAKE_SOURCE_DIR}/.git")
if(GIT_FOUND AND EXISTS "${CMAKE_SOURCE_DIR}/.git")
if(DEFINED ENV{git_commit_hash} AND NOT "$ENV{git_commit_hash}" STREQUAL "")
message(STATUS "Specified git commit hash: $ENV{git_commit_hash}")
# Convert the given hash to short hash
execute_process(
COMMAND ${GIT_EXECUTABLE} rev-parse --short "$ENV{git_commit_hash}"
@@ -95,20 +96,17 @@ if(DEFINED ENV{git_commit_hash} AND NOT "$ENV{git_commit_hash}" STREQUAL "")
OUTPUT_VARIABLE GIT_COMMIT_HASH
OUTPUT_STRIP_TRAILING_WHITESPACE
)
add_definitions("-DGIT_COMMIT_HASH=\"${GIT_COMMIT_HASH}\"")
else()
# No .git directory (e.g., Flatpak sandbox) — truncate directly
string(SUBSTRING "$ENV{git_commit_hash}" 0 7 GIT_COMMIT_HASH)
# Check current Git commit hash
execute_process(
COMMAND ${GIT_EXECUTABLE} log -1 --format=%h
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
OUTPUT_VARIABLE GIT_COMMIT_HASH
OUTPUT_STRIP_TRAILING_WHITESPACE
)
add_definitions("-DGIT_COMMIT_HASH=\"${GIT_COMMIT_HASH}\"")
endif()
add_definitions("-DGIT_COMMIT_HASH=\"${GIT_COMMIT_HASH}\"")
elseif(GIT_FOUND AND EXISTS "${CMAKE_SOURCE_DIR}/.git")
# Check current Git commit hash
execute_process(
COMMAND ${GIT_EXECUTABLE} log -1 --format=%h
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
OUTPUT_VARIABLE GIT_COMMIT_HASH
OUTPUT_STRIP_TRAILING_WHITESPACE
)
add_definitions("-DGIT_COMMIT_HASH=\"${GIT_COMMIT_HASH}\"")
endif()
if(DEFINED ENV{SLIC3R_STATIC})
@@ -117,16 +115,17 @@ else()
set(SLIC3R_STATIC_INITIAL 1)
endif()
option(SLIC3R_STATIC "Compile OrcaSlicer with static libraries (Boost, TBB)" ${SLIC3R_STATIC_INITIAL})
option(SLIC3R_STATIC "Compile OrcaSlicer with static libraries (Boost, TBB, glew)" ${SLIC3R_STATIC_INITIAL})
option(SLIC3R_GUI "Compile OrcaSlicer with GUI components (OpenGL, wxWidgets)" 1)
option(SLIC3R_FHS "Assume OrcaSlicer is to be installed in a FHS directory structure" 0)
option(SLIC3R_WX_STABLE "Build against wxWidgets stable (3.0) as oppsed to dev (3.1) on Linux" 0)
option(SLIC3R_PROFILE "Compile OrcaSlicer with an invasive Shiny profiler" 0)
option(SLIC3R_PCH "Use precompiled headers" 1)
option(SLIC3R_MSVC_COMPILE_PARALLEL "Compile on Visual Studio in parallel" 1)
option(SLIC3R_MSVC_PDB "Generate PDB files on MSVC in Release mode" 1)
option(SLIC3R_ASAN "Enable ASan on Clang and GCC" 0)
# If SLIC3R_FHS is 1 -> SLIC3R_DESKTOP_INTEGRATION is always 0, othrewise variable.
CMAKE_DEPENDENT_OPTION(SLIC3R_DESKTOP_INTEGRATION "Allow performing desktop integration during runtime" 1 "NOT SLIC3R_FHS" 0)
CMAKE_DEPENDENT_OPTION(SLIC3R_DESKTOP_INTEGRATION "Allow perfoming desktop integration during runtime" 1 "NOT SLIC3R_FHS" 0)
set(OPENVDB_FIND_MODULE_PATH "" CACHE PATH "Path to OpenVDB installation's find modules.")
@@ -157,7 +156,7 @@ if (APPLE)
if (CMAKE_MACOSX_BUNDLE)
set(CMAKE_INSTALL_RPATH @executable_path/../Frameworks)
endif()
SET(CMAKE_XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER "com.orcaslicer.OrcaSlicer")
SET(CMAKE_XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER "com.softfever3d.orca-slicer")
message(STATUS "Orca: IS_CROSS_COMPILE: ${IS_CROSS_COMPILE}")
endif ()
@@ -168,7 +167,10 @@ option(BUILD_TESTS "Build unit tests" OFF)
option(ORCA_TOOLS "Build Orca tools" OFF)
if (FLATPAK)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++20")
set(SLIC3R_PCH OFF CACHE BOOL "" FORCE)
set(SLIC3R_FHS ON CACHE BOOL "" FORCE)
set(BUILD_TESTS OFF CACHE BOOL "" FORCE)
set(SLIC3R_DESKTOP_INTEGRATION OFF CACHE BOOL "" FORCE)
endif ()
@@ -323,44 +325,43 @@ set(CMAKE_POSITION_INDEPENDENT_CODE ON)
# WIN10SDK_PATH is used to point CMake to the WIN10 SDK installation directory.
# We pick it from environment if it is not defined in another way
# ORCA: Removed Netfabb STL fixing service support in favor of CGAL.
# if(WIN32)
# if(NOT DEFINED WIN10SDK_PATH)
# if(DEFINED ENV{WIN10SDK_PATH})
# set(WIN10SDK_PATH "$ENV{WIN10SDK_PATH}")
# endif()
# endif()
# if(DEFINED WIN10SDK_PATH)
# #BBS: modify win10sdk_path
# if (EXISTS "${WIN10SDK_PATH}/winrt/windows.graphics.printing3d.h")
# set(WIN10SDK_INCLUDE_PATH "${WIN10SDK_PATH}")
# else()
# message("WIN10SDK_PATH is invalid: ${WIN10SDK_PATH}")
# message("${WIN10SDK_PATH}/winrt/windows.graphics.printing3d.h was not found")
# message("STL fixing by the Netfabb service will not be compiled")
# unset(WIN10SDK_PATH)
# endif()
# else()
# # Try to use the default Windows 10 SDK path.
# if (DEFINED ENV{WindowsSdkDir} AND DEFINED ENV{WindowsSDKVersion})
# set(WIN10SDK_INCLUDE_PATH "$ENV{WindowsSdkDir}/Include/$ENV{WindowsSDKVersion}")
# else ()
# set(WIN10SDK_INCLUDE_PATH "C:/Program Files (x86)/Windows Kits/10/Include/10.0.26100.0")
# endif ()
# if (NOT EXISTS "${WIN10SDK_INCLUDE_PATH}/winrt/windows.graphics.printing3d.h")
# message("${WIN10SDK_INCLUDE_PATH}/winrt/windows.graphics.printing3d.h was not found")
# message("STL fixing by the Netfabb service will not be compiled")
# unset(WIN10SDK_INCLUDE_PATH)
# endif()
# endif()
# if(WIN10SDK_INCLUDE_PATH)
# message("Building with Win10 Netfabb STL fixing service support")
# add_definitions(-DHAS_WIN10SDK)
# include_directories(SYSTEM "${WIN10SDK_INCLUDE_PATH}")
# else()
# message("Building without Win10 Netfabb STL fixing service support")
# endif()
# endif()
if(WIN32)
if(NOT DEFINED WIN10SDK_PATH)
if(DEFINED ENV{WIN10SDK_PATH})
set(WIN10SDK_PATH "$ENV{WIN10SDK_PATH}")
endif()
endif()
if(DEFINED WIN10SDK_PATH)
#BBS: modify win10sdk_path
if (EXISTS "${WIN10SDK_PATH}/winrt/windows.graphics.printing3d.h")
set(WIN10SDK_INCLUDE_PATH "${WIN10SDK_PATH}")
else()
message("WIN10SDK_PATH is invalid: ${WIN10SDK_PATH}")
message("${WIN10SDK_PATH}/winrt/windows.graphics.printing3d.h was not found")
message("STL fixing by the Netfabb service will not be compiled")
unset(WIN10SDK_PATH)
endif()
else()
# Try to use the default Windows 10 SDK path.
if (DEFINED ENV{WindowsSdkDir} AND DEFINED ENV{WindowsSDKVersion})
set(WIN10SDK_INCLUDE_PATH "$ENV{WindowsSdkDir}/Include/$ENV{WindowsSDKVersion}")
else ()
set(WIN10SDK_INCLUDE_PATH "C:/Program Files (x86)/Windows Kits/10/Include/10.0.26100.0")
endif ()
if (NOT EXISTS "${WIN10SDK_INCLUDE_PATH}/winrt/windows.graphics.printing3d.h")
message("${WIN10SDK_INCLUDE_PATH}/winrt/windows.graphics.printing3d.h was not found")
message("STL fixing by the Netfabb service will not be compiled")
unset(WIN10SDK_INCLUDE_PATH)
endif()
endif()
if(WIN10SDK_INCLUDE_PATH)
message("Building with Win10 Netfabb STL fixing service support")
add_definitions(-DHAS_WIN10SDK)
include_directories(SYSTEM "${WIN10SDK_INCLUDE_PATH}")
else()
message("Building without Win10 Netfabb STL fixing service support")
endif()
endif()
if (APPLE)
message("OS X SDK Path: ${CMAKE_OSX_SYSROOT}")
@@ -374,6 +375,11 @@ endif ()
if (CMAKE_SYSTEM_NAME STREQUAL "Linux")
find_package(PkgConfig REQUIRED)
if (CMAKE_VERSION VERSION_LESS "3.1")
# Workaround for an old CMake, which does not understand CMAKE_CXX_STANDARD.
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
endif()
# Boost on Raspberry-Pi does not link to pthreads.
set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads REQUIRED)
@@ -426,11 +432,7 @@ if (NOT MSVC AND ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMP
endif()
if((${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang" OR ${CMAKE_CXX_COMPILER_ID} STREQUAL "AppleClang") AND ${CMAKE_CXX_COMPILER_VERSION} VERSION_GREATER 15)
include(CheckCXXCompilerFlag)
check_cxx_compiler_flag(-Wno-error=enum-constexpr-conversion HAS_WNO_ERROR_ENUM_CONSTEXPR_CONV)
if(HAS_WNO_ERROR_ENUM_CONSTEXPR_CONV)
add_compile_options(-Wno-error=enum-constexpr-conversion)
endif()
add_compile_options(-Wno-error=enum-constexpr-conversion)
endif()
#GCC generates loads of -Wunknown-pragmas when compiling igl. The fix is not easy due to a bug in gcc, see
@@ -445,12 +447,9 @@ if (NOT MSVC AND ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMP
add_compile_options(-Wno-unknown-pragmas)
endif()
# Compress the debug info with zstd to save space in Flatpak CI builds
if(FLATPAK)
if(("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 13.0) OR
("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang" AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 15.0))
add_compile_options(-gz=zstd)
endif()
# Bit of a hack for flatpak building: compress the debug info with zstd to save space in CI
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 13.0)
add_compile_options(-gz=zstd)
endif()
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 14)
@@ -484,8 +483,7 @@ if (APPLE)
endif ()
if(MSVC)
# Ignore truncating casts in initializers & constructors
# https://learn.microsoft.com/en-us/cpp/error-messages/compiler-warnings/compiler-warning-level-1-c4305
# 添加编译选项,忽略警告 C4305 (格式转换截断)
add_compile_options(/wd4305)
endif()
@@ -573,7 +571,6 @@ endif()
if(POLICY CMP0167)
cmake_policy(SET CMP0167 NEW)
endif()
set(Boost_NO_SYSTEM_PATHS TRUE)
find_package(Boost 1.83.0 REQUIRED COMPONENTS system filesystem thread log log_setup locale regex chrono atomic date_time iostreams program_options nowide)
add_library(boost_libs INTERFACE)
@@ -691,10 +688,16 @@ find_package(PNG REQUIRED)
set(OpenGL_GL_PREFERENCE "LEGACY")
find_package(OpenGL REQUIRED)
if(APPLE AND CMAKE_VERSION VERSION_GREATER_EQUAL "4.0")
set(OPENGL_LIBRARIES "-framework OpenGL" CACHE STRING "OpenGL framework" FORCE)
set(GLEW_ROOT "${CMAKE_PREFIX_PATH}")
message("GLEW_ROOT: ${GLEW_ROOT}")
# Find glew or use bundled version
if (SLIC3R_STATIC AND NOT SLIC3R_STATIC_EXCLUDE_GLEW)
set(GLEW_USE_STATIC_LIBS ON)
set(GLEW_VERBOSE ON)
endif()
find_package(GLEW REQUIRED)
find_package(glfw3 REQUIRED)
# Find the Cereal serialization library
@@ -719,7 +722,7 @@ add_custom_target(gettext_make_pot
)
add_custom_target(gettext_merge_po_with_pot
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
COMMENT "Merge localization po with new generated pot file"
COMMENT "Merge localization po with new generted pot file"
)
file(GLOB BBL_L10N_PO_FILES "${BBL_L18N_DIR}/*/OrcaSlicer*.po")
foreach(po_file ${BBL_L10N_PO_FILES})
@@ -785,10 +788,8 @@ function(orcaslicer_copy_dlls target config postfix output_dlls)
set(_arch "x64")
elseif ("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "X86")
set(_arch "x86")
elseif ("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "ARM64")
set(_arch "arm64")
else ()
message(FATAL_ERROR "Unable to detect architecture: ${CMAKE_SYSTEM_PROCESSOR}")
message(FATAL_ERROR "Unable to detect architecture")
endif ()
get_property(_is_multi GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
@@ -810,6 +811,11 @@ function(orcaslicer_copy_dlls target config postfix output_dlls)
${TOP_LEVEL_PROJECT_DIR}/deps/WebView2/lib/win-${_arch}/WebView2Loader.dll
DESTINATION ${_out_dir})
# WinSparkle for auto-updates
if(EXISTS "${CMAKE_PREFIX_PATH}/bin/WinSparkle.dll")
file(COPY ${CMAKE_PREFIX_PATH}/bin/WinSparkle.dll DESTINATION ${_out_dir})
endif()
file(COPY ${CMAKE_PREFIX_PATH}/bin/occt/TKBO.dll
${CMAKE_PREFIX_PATH}/bin/occt/TKBRep.dll
${CMAKE_PREFIX_PATH}/bin/occt/TKCAF.dll
@@ -912,7 +918,7 @@ elseif (SLIC3R_FHS)
install(DIRECTORY ${SLIC3R_RESOURCES_DIR}/ DESTINATION ${SLIC3R_FHS_RESOURCES}
PATTERN "*/udev" EXCLUDE
)
install(FILES src/dev-utils/platform/unix/com.orcaslicer.OrcaSlicer.desktop DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/applications)
install(FILES src/dev-utils/platform/unix/OrcaSlicer.desktop DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/applications)
foreach(SIZE 32 128 192)
install(FILES ${SLIC3R_RESOURCES_DIR}/images/OrcaSlicer_${SIZE}px.png
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/${SIZE}x${SIZE}/apps RENAME OrcaSlicer.png
@@ -921,7 +927,7 @@ elseif (SLIC3R_FHS)
elseif (CMAKE_MACOSX_BUNDLE)
# install(DIRECTORY "${SLIC3R_RESOURCES_DIR}/" DESTINATION "${CMAKE_INSTALL_PREFIX}/OrcaSlicer.app/Contents/resources")
else ()
install(FILES src/dev-utils/platform/unix/com.orcaslicer.OrcaSlicer.desktop DESTINATION ${CMAKE_INSTALL_PREFIX}/resources/applications)
install(FILES src/dev-utils/platform/unix/OrcaSlicer.desktop DESTINATION ${CMAKE_INSTALL_PREFIX}/resources/applications)
install(DIRECTORY "${SLIC3R_RESOURCES_DIR}/" DESTINATION "${CMAKE_INSTALL_PREFIX}/resources")
endif ()

View File

@@ -4,7 +4,7 @@
<img alt="OrcaSlicer logo" src="resources/images/OrcaSlicer.png" width="15%" height="15%">
</picture>
<a href="https://trendshift.io/repositories/15552" target="_blank"><img src="https://trendshift.io/api/badge/repositories/15552" alt="OrcaSlicer%2FOrcaSlicer | Trendshift" style="width: 250px; height: 55px;" width="250" height="55"/></a>
<a href="https://trendshift.io/repositories/952" target="_blank"><img src="https://trendshift.io/api/badge/repositories/952" alt="SoftFever%2FOrcaSlicer | Trendshift" style="width: 250px; height: 55px;" width="250" height="55"/></a>
[![GitHub Repo stars](https://img.shields.io/github/stars/OrcaSlicer/OrcaSlicer)](https://github.com/OrcaSlicer/OrcaSlicer/stargazers) [![Build all](https://github.com/OrcaSlicer/OrcaSlicer/actions/workflows/build_all.yml/badge.svg?branch=main)](https://github.com/OrcaSlicer/OrcaSlicer/actions/workflows/build_all.yml)
@@ -44,7 +44,7 @@ If you come across any of these in search results, please <b>report them</b> as
# Main features
- **[Advanced Calibration Tools](https://www.orcaslicer.com/wiki/calibration_guide)**
- **[Advanced Calibration Tools](https://www.orcaslicer.com/wiki/Calibration)**
Comprehensive suite: temperature towers, flow rate, retraction & more for optimal performance.
- **[Precise Wall](https://www.orcaslicer.com/wiki/quality_settings_precision#precise-wall) and [Seam Control](https://www.orcaslicer.com/wiki/quality_settings_seam)**
Adjust outer wall spacing and apply scarf seams to enhance print accuracy.
@@ -71,7 +71,7 @@ If you come across any of these in search results, please <b>report them</b> as
The [wiki](https://www.orcaslicer.com/wiki) aims to provide a detailed explanation of the slicer settings, including how to maximize their use and how to calibrate and set up your printer.
- **[Access the wiki here](https://www.orcaslicer.com/wiki)**
- **[Contribute to the wiki](https://www.orcaslicer.com/wiki/how_to_wiki)**
- **[Contribute to the wiki](https://www.orcaslicer.com/wiki/How-to-wiki)**
# Download
@@ -137,32 +137,14 @@ winget install --id=SoftFever.OrcaSlicer -e
![mac_security_setting](./SoftFever_doc/mac_security_setting.png)
</details>
## Linux
## Linux (Ubuntu)
### Flathub (Recommended)
OrcaSlicer is available through FlatHub:
<a href='https://flathub.org/apps/com.orcaslicer.OrcaSlicer'><img width='240' alt='Download on Flathub' src='https://dl.flathub.org/assets/badges/flathub-badge-en.png'/></a>
Install from the command line:
```shell
flatpak install flathub com.orcaslicer.OrcaSlicer
flatpak run com.orcaslicer.OrcaSlicer
```
It can also be installed through graphical software managers (KDE Discover, GNOME Software, etc.) when Flathub is enabled. Search for **OrcaSlicer** in your software center.
### AppImage
1. Download App image from the [releases page](https://github.com/OrcaSlicer/OrcaSlicer/releases).
2. Double click the downloaded file to run it.
3. If you run into trouble executing it, try this command in the terminal:
1. If you run into trouble executing it, try this command in the terminal:
`chmod +x /path_to_appimage/OrcaSlicer_Linux.AppImage`
# How to Compile
All updated build instructions for Windows, macOS, and Linux are now available on the official [OrcaSlicer Wiki - How to build](https://www.orcaslicer.com/wiki/how_to_build) page.
All updated build instructions for Windows, macOS, and Linux are now available on the official [OrcaSlicer Wiki - How to build](https://www.orcaslicer.com/wiki/How-to-build) page.
Please refer to the wiki to ensure you're following the latest and most accurate steps for your platform.
@@ -212,16 +194,20 @@ Thank you! :)
<a href="https://ko-fi.com/G2G5IP3CP"><img src="https://img.shields.io/badge/Support_me_on_Ko--fi-FF5E5B?style=flat&logo=ko-fi&logoColor=white" height="50"></a>
<a href="https://paypal.me/softfever3d"><img src="https://img.shields.io/badge/PayPal-003087?style=flat&logo=paypal&logoColor=fff" height="50"></a>
## Some Background
## Some background
Open-source slicing has always been built on a tradition of collaboration and attribution. [Slic3r](https://github.com/Slic3r/Slic3r), created by Alessandro Ranellucci and the RepRap community, laid the foundation. [PrusaSlicer](https://github.com/prusa3d/PrusaSlicer) by Prusa Research built on Slic3r and acknowledged that heritage. [Bambu Studio](https://github.com/bambulab/BambuStudio) in turn forked from PrusaSlicer, and [SuperSlicer](https://github.com/supermerill/SuperSlicer) by @supermerill extended PrusaSlicer with community-driven enhancements. Each project carried the work of its predecessors forward, crediting those who came before.
OrcaSlicer was originally forked from Bambu Studio, it was previously known as BambuStudio-SoftFever.
OrcaSlicer began in that same spirit, drawing from BambuStudio, PrusaSlicer, and ideas inspired by CuraSlicer and SuperSlicer. But it has since grown far beyond its origins. Through relentless innovation — introducing advanced calibration tools, precise wall and seam control, tree supports, adaptive slicing, and hundreds of other features — OrcaSlicer has become the most widely used and actively developed open-source slicer in the 3D printing community. Many of its innovations have been adopted by other slicers, making it a driving force for the entire industry.
The OrcaSlicer logo was designed by community member Justin Levine (@freejstnalxndr).
[Bambu Studio](https://github.com/bambulab/BambuStudio) is forked from [PrusaSlicer](https://github.com/prusa3d/PrusaSlicer) by Prusa Research, which is from [Slic3r](https://github.com/Slic3r/Slic3r) by Alessandro Ranellucci and the RepRap community.
OrcaSlicer incorporates a lot of features from [SuperSlicer](https://github.com/supermerill/SuperSlicer) by @supermerill
OrcaSlicer's logo is designed by community member Justin Levine (@freejstnalxndr).
# License
- **OrcaSlicer** is licensed under the GNU Affero General Public License, version 3.
- **OrcaSlicer** is licensed under the GNU Affero General Public License, version 3. OrcaSlicer is based on Bambu Studio by BambuLab.
- **Bambu Studio** is licensed under the GNU Affero General Public License, version 3. Bambu Studio is based on PrusaSlicer by PrusaResearch.
- **PrusaSlicer** is licensed under the GNU Affero General Public License, version 3. PrusaSlicer is owned by Prusa Research. PrusaSlicer is originally based on Slic3r by Alessandro Ranellucci.
- **Slic3r** is licensed under the GNU Affero General Public License, version 3. Slic3r was created by Alessandro Ranellucci with the help of many other contributors.
- The **GNU Affero General Public License**, version 3 ensures that if you use any part of this software in any way (even behind a web server), your software must be released under the same license.
- OrcaSlicer includes a **pressure advance calibration pattern test** adapted from Andrew Ellis' generator, which is licensed under GNU General Public License, version 3. Ellis' generator is itself adapted from a generator developed by Sineos for Marlin, which is licensed under GNU General Public License, version 3.
- The **Bambu networking plugin** is based on non-free libraries from BambuLab. It is optional to the OrcaSlicer and provides extended functionalities for Bambulab printer users.

View File

@@ -5,7 +5,6 @@
# Based on the GitHub Actions workflow in .github/workflows/build_all.yml
set -e
SECONDS=0
# Colors for output
RED='\033[0;31m'
@@ -22,8 +21,6 @@ INSTALL_RUNTIME=false
JOBS=$(nproc)
FORCE_CLEAN=false
ENABLE_CCACHE=false
DISABLE_ROFILES_FUSE=false
NO_DEBUGINFO=true
CACHE_DIR=".flatpak-builder"
# Help function
@@ -39,8 +36,6 @@ show_help() {
echo " -c, --cleanup Clean build directory before building"
echo " -f, --force-clean Force clean build (disables caching)"
echo " --ccache Enable ccache for faster rebuilds (requires ccache in SDK)"
echo " --disable-rofiles-fuse Disable rofiles-fuse (workaround for FUSE issues)"
echo " --with-debuginfo Include debug info (slower builds, needed for Flathub)"
echo " --cache-dir DIR Flatpak builder cache directory [default: $CACHE_DIR]"
echo " -i, --install-runtime Install required Flatpak runtime and SDK"
echo " -h, --help Show this help message"
@@ -80,14 +75,6 @@ while [[ $# -gt 0 ]]; do
ENABLE_CCACHE=true
shift
;;
--disable-rofiles-fuse)
DISABLE_ROFILES_FUSE=true
shift
;;
--with-debuginfo)
NO_DEBUGINFO=false
shift
;;
--cache-dir)
CACHE_DIR="$2"
shift 2
@@ -199,22 +186,22 @@ echo -e "${GREEN}All required dependencies found${NC}"
# Install runtime and SDK if requested
if [[ "$INSTALL_RUNTIME" == true ]]; then
echo -e "${YELLOW}Installing GNOME runtime and SDK...${NC}"
flatpak install --user -y flathub org.gnome.Platform//49
flatpak install --user -y flathub org.gnome.Sdk//49
flatpak install --user -y flathub org.gnome.Platform//48
flatpak install --user -y flathub org.gnome.Sdk//48
fi
# Check if required runtime is available
if ! flatpak info --user org.gnome.Platform//49 &> /dev/null; then
echo -e "${RED}Error: GNOME Platform 49 runtime is not installed.${NC}"
if ! flatpak info --user org.gnome.Platform//48 &> /dev/null; then
echo -e "${RED}Error: GNOME Platform 48 runtime is not installed.${NC}"
echo "Run with -i flag to install it automatically, or install manually:"
echo "flatpak install --user flathub org.gnome.Platform//49"
echo "flatpak install --user flathub org.gnome.Platform//48"
exit 1
fi
if ! flatpak info --user org.gnome.Sdk//49 &> /dev/null; then
echo -e "${RED}Error: GNOME SDK 49 is not installed.${NC}"
if ! flatpak info --user org.gnome.Sdk//48 &> /dev/null; then
echo -e "${RED}Error: GNOME SDK 48 is not installed.${NC}"
echo "Run with -i flag to install it automatically, or install manually:"
echo "flatpak install --user flathub org.gnome.Sdk//49"
echo "flatpak install --user flathub org.gnome.Sdk//48"
exit 1
fi
@@ -255,8 +242,8 @@ mkdir -p "$BUILD_DIR"
rm -rf "$BUILD_DIR/build-dir"
# Check if flatpak manifest exists
if [[ ! -f "./scripts/flatpak/com.orcaslicer.OrcaSlicer.yml" ]]; then
echo -e "${RED}Error: Flatpak manifest not found at scripts/flatpak/com.orcaslicer.OrcaSlicer.yml${NC}"
if [[ ! -f "./scripts/flatpak/io.github.softfever.OrcaSlicer.yml" ]]; then
echo -e "${RED}Error: Flatpak manifest not found at scripts/flatpak/io.github.softfever.OrcaSlicer.yml${NC}"
exit 1
fi
@@ -292,7 +279,6 @@ BUILDER_ARGS=(
--verbose
--state-dir="$CACHE_DIR"
--jobs="$JOBS"
--mirror-screenshots-url=https://dl.flathub.org/media/
)
# Add force-clean only if explicitly requested (disables caching)
@@ -309,40 +295,21 @@ if [[ "$ENABLE_CCACHE" == true ]]; then
echo -e "${GREEN}Using ccache for compiler caching${NC}"
fi
# Disable rofiles-fuse if requested (workaround for FUSE issues)
if [[ "$DISABLE_ROFILES_FUSE" == true ]]; then
BUILDER_ARGS+=(--disable-rofiles-fuse)
echo -e "${YELLOW}rofiles-fuse disabled${NC}"
fi
# Use a temp manifest with no-debuginfo if requested
MANIFEST="scripts/flatpak/com.orcaslicer.OrcaSlicer.yml"
if [[ "$NO_DEBUGINFO" == true ]]; then
MANIFEST="scripts/flatpak/com.orcaslicer.OrcaSlicer.no-debug.yml"
sed '/^build-options:/a\ no-debuginfo: true\n strip: true' \
scripts/flatpak/com.orcaslicer.OrcaSlicer.yml > "$MANIFEST"
echo -e "${YELLOW}Debug info disabled (using temp manifest)${NC}"
fi
if ! flatpak-builder \
"${BUILDER_ARGS[@]}" \
"$BUILD_DIR/build-dir" \
"$MANIFEST"; then
scripts/flatpak/io.github.softfever.OrcaSlicer.yml; then
echo -e "${RED}Error: flatpak-builder failed${NC}"
echo -e "${YELLOW}Check the build log above for details${NC}"
rm -f "scripts/flatpak/com.orcaslicer.OrcaSlicer.no-debug.yml"
exit 1
fi
# Clean up temp manifest
rm -f "scripts/flatpak/com.orcaslicer.OrcaSlicer.no-debug.yml"
# Create bundle
echo -e "${YELLOW}Creating Flatpak bundle...${NC}"
if ! flatpak build-bundle \
"$BUILD_DIR/repo" \
"$BUNDLE_NAME" \
com.orcaslicer.OrcaSlicer \
io.github.softfever.OrcaSlicer \
--arch="$ARCH"; then
echo -e "${RED}Error: Failed to create Flatpak bundle${NC}"
exit 1
@@ -361,10 +328,10 @@ echo -e "${BLUE}To install the Flatpak:${NC}"
echo -e "flatpak install --user $BUNDLE_NAME"
echo ""
echo -e "${BLUE}To run OrcaSlicer:${NC}"
echo -e "flatpak run com.orcaslicer.OrcaSlicer"
echo -e "flatpak run io.github.softfever.OrcaSlicer"
echo ""
echo -e "${BLUE}To uninstall:${NC}"
echo -e "flatpak uninstall --user com.orcaslicer.OrcaSlicer"
echo -e "flatpak uninstall --user io.github.softfever.OrcaSlicer"
echo ""
if [[ "$FORCE_CLEAN" != true ]]; then
echo -e "${BLUE}Cache Management:${NC}"
@@ -372,6 +339,3 @@ if [[ "$FORCE_CLEAN" != true ]]; then
echo -e "• To force a clean build: $0 -f"
echo -e "• To clean cache manually: rm -rf $CACHE_DIR"
fi
elapsed=$SECONDS
printf "\nBuild completed in %dh %dm %ds\n" $((elapsed/3600)) $((elapsed%3600/60)) $((elapsed%60))

View File

@@ -1,6 +1,5 @@
#!/usr/bin/env bash
set -e # Exit immediately if a command exits with a non-zero status.
SECONDS=0
SCRIPT_NAME=$(basename "$0")
SCRIPT_PATH=$(dirname "$(readlink -f "${0}")")
@@ -8,7 +7,7 @@ SCRIPT_PATH=$(dirname "$(readlink -f "${0}")")
pushd "${SCRIPT_PATH}" > /dev/null
function usage() {
echo "Usage: ./${SCRIPT_NAME} [-1][-b][-c][-d][-D][-e][-F][-g][-h][-i][-j N][-p][-r][-s][-t][-u][-l][-L]"
echo "Usage: ./${SCRIPT_NAME} [-1][-b][-c][-d][-D][-e][-h][-i][-j N][-p][-r][-s][-t][-u][-l][-L]"
echo " -1: limit builds to one core (where possible)"
echo " -j N: limit builds to N cores (where possible)"
echo " -b: build in Debug mode"
@@ -17,8 +16,6 @@ function usage() {
echo " -d: download and build dependencies in ./deps/ (build prerequisite)"
echo " -D: dry run"
echo " -e: build in RelWithDebInfo mode"
echo " -F: rebuild the cached Docker/Podman runner image from scratch when used with -g"
echo " -g: run the requested build steps inside a Docker/Podman Ubuntu 24.04 container similar to the GitHub Actions Linux runner"
echo " -h: prints this help text"
echo " -i: build the Orca Slicer AppImage (optional)"
echo " -p: boost ccache hit rate by disabling precompiled headers (default: ON)"
@@ -30,9 +27,6 @@ function usage() {
echo " -L: use ld.lld as linker (if available)"
echo "For a first use, you want to './${SCRIPT_NAME} -u'"
echo " and then './${SCRIPT_NAME} -dsi'"
echo "For a GitHub Actions-like Linux build locally, use './${SCRIPT_NAME} -g -istrlL'"
echo "Use './${SCRIPT_NAME} -gF -istrlL' to rebuild the cached runner image first."
echo "Set ORCA_CONTAINER_CLI, ORCA_DOCKER_IMAGE, ORCA_DOCKER_BASE_IMAGE, or ORCA_DOCKER_CMAKE_VERSION to override the container runtime, cached image tag, base image, or CMake version."
}
SLIC3R_PRECOMPILED_HEADERS="ON"
@@ -40,83 +34,60 @@ SLIC3R_PRECOMPILED_HEADERS="ON"
unset name
BUILD_DIR=build
BUILD_CONFIG=Release
FORWARDED_ARGS=()
while getopts ":1j:bcCdDeFghiprstulL" opt ; do
while getopts ":1j:bcCdDehiprstulL" opt ; do
case ${opt} in
1 )
export CMAKE_BUILD_PARALLEL_LEVEL=1
FORWARDED_ARGS+=("-1")
;;
j )
export CMAKE_BUILD_PARALLEL_LEVEL=$OPTARG
FORWARDED_ARGS+=("-j" "$OPTARG")
;;
b )
BUILD_DIR=build-dbg
BUILD_CONFIG=Debug
FORWARDED_ARGS+=("-b")
;;
c )
CLEAN_BUILD=1
FORWARDED_ARGS+=("-c")
;;
C )
COLORED_OUTPUT="-DCOLORED_OUTPUT=ON"
FORWARDED_ARGS+=("-C")
;;
d )
BUILD_DEPS="1"
FORWARDED_ARGS+=("-d")
;;
D )
DRY_RUN="1"
FORWARDED_ARGS+=("-D")
;;
e )
BUILD_DIR=build-dbginfo
BUILD_CONFIG=RelWithDebInfo
FORWARDED_ARGS+=("-e")
;;
F )
CLEAN_DOCKER_IMAGE="1"
;;
g )
USE_DOCKER="1"
;;
h ) usage
exit 1
;;
i )
BUILD_IMAGE="1"
FORWARDED_ARGS+=("-i")
;;
p )
SLIC3R_PRECOMPILED_HEADERS="OFF"
FORWARDED_ARGS+=("-p")
;;
r )
SKIP_RAM_CHECK="1"
FORWARDED_ARGS+=("-r")
;;
s )
BUILD_ORCA="1"
FORWARDED_ARGS+=("-s")
;;
t )
BUILD_TESTS="1"
FORWARDED_ARGS+=("-t")
;;
u )
export UPDATE_LIB="1"
FORWARDED_ARGS+=("-u")
;;
l )
USE_CLANG="1"
FORWARDED_ARGS+=("-l")
;;
L )
USE_LLD="1"
FORWARDED_ARGS+=("-L")
;;
* )
echo "Unknown argument '${opt}', aborting."
@@ -130,11 +101,6 @@ if [ ${OPTIND} -eq 1 ] ; then
exit 1
fi
if [[ -n "${CLEAN_DOCKER_IMAGE}" ]] && [[ -z "${USE_DOCKER}" ]] ; then
echo "Error: -F requires -g."
exit 1
fi
function check_available_memory_and_disk() {
FREE_MEM_GB=$(free --gibi --total | grep 'Mem' | rev | cut --delimiter=" " --fields=1 | rev)
MIN_MEM_GB=10
@@ -172,275 +138,6 @@ function print_and_run() {
fi
}
function resolve_container_cli() {
if [[ -n "${ORCA_CONTAINER_CLI}" ]] ; then
if ! command -v "${ORCA_CONTAINER_CLI}" >/dev/null 2>&1 ; then
echo "Error: container runtime '${ORCA_CONTAINER_CLI}' was not found." >&2
exit 1
fi
echo "${ORCA_CONTAINER_CLI}"
return
fi
if command -v docker >/dev/null 2>&1 ; then
echo "docker"
return
fi
if command -v podman >/dev/null 2>&1 ; then
echo "podman"
return
fi
echo "Error: neither docker nor podman is available. Install one of them or set ORCA_CONTAINER_CLI." >&2
exit 1
}
function get_docker_runner_image() {
local base_image
local docker_cmake_version
local recipe_hash
local sanitized_base_image
local sanitized_cmake_version
if [[ -n "${ORCA_DOCKER_IMAGE}" ]] ; then
echo "${ORCA_DOCKER_IMAGE}"
return
fi
base_image="${ORCA_DOCKER_BASE_IMAGE:-ubuntu:24.04}"
docker_cmake_version="${ORCA_DOCKER_CMAKE_VERSION-4.3.0}"
recipe_hash=$(find "${SCRIPT_PATH}/build_linux.sh" "${SCRIPT_PATH}/scripts/linux.d" -type f -print0 | sort -z | xargs -0 cat | sha256sum | cut -c1-12)
sanitized_base_image=$(echo "${base_image}" | tr '/:@' '---' | tr -cs 'A-Za-z0-9_.-' '-')
sanitized_cmake_version=$(echo "${docker_cmake_version:-system}" | tr -cs 'A-Za-z0-9_.-' '-')
echo "orcaslicer-linux-builder:${sanitized_base_image}-cmake-${sanitized_cmake_version}-${recipe_hash}"
}
function docker_runner_dockerfile() {
cat <<'EOF'
ARG BASE_IMAGE=ubuntu:24.04
FROM ${BASE_IMAGE}
ARG CMAKE_VERSION=4.3.0
ENV DEBIAN_FRONTEND=noninteractive
SHELL ["/bin/bash", "-c"]
RUN apt-get update && apt-get install -y sudo ca-certificates curl tar
COPY build_linux.sh /tmp/orcaslicer/build_linux.sh
COPY scripts/linux.d /tmp/orcaslicer/scripts/linux.d
WORKDIR /tmp/orcaslicer
RUN chmod +x ./build_linux.sh
RUN ./build_linux.sh -ur
RUN if [[ -n "${CMAKE_VERSION}" ]] ; then \
case "$(uname -m)" in \
x86_64|amd64) cmake_arch="x86_64" ;; \
aarch64|arm64) cmake_arch="aarch64" ;; \
*) cmake_arch="" ;; \
esac ; \
if [[ -n "${cmake_arch}" ]] ; then \
cmake_root="/opt/cmake-${CMAKE_VERSION}-linux-${cmake_arch}" ; \
if ! curl -fsSL "https://github.com/Kitware/CMake/releases/download/v${CMAKE_VERSION}/cmake-${CMAKE_VERSION}-linux-${cmake_arch}.tar.gz" | tar -xz -C /opt ; then \
echo "Warning: failed to install CMake ${CMAKE_VERSION}; falling back to the distro cmake package." ; \
elif [[ -d "${cmake_root}" ]] ; then \
ln -sf "${cmake_root}/bin/"* /usr/local/bin/ ; \
fi ; \
else \
echo "Skipping GitHub Actions CMake install for unsupported architecture $(uname -m)." ; \
fi ; \
fi
RUN rm -rf /var/lib/apt/lists/* /tmp/orcaslicer
EOF
}
function ensure_docker_runner_image() {
local container_cli
local base_image
local runner_image
local docker_cmake_version
local image_exists="0"
local force_rebuild="0"
local -a build_cmd
container_cli="$1"
runner_image="$2"
base_image="${ORCA_DOCKER_BASE_IMAGE:-ubuntu:24.04}"
docker_cmake_version="${ORCA_DOCKER_CMAKE_VERSION-4.3.0}"
if "${container_cli}" image inspect "${runner_image}" >/dev/null 2>&1 ; then
image_exists="1"
fi
if [[ -n "${CLEAN_DOCKER_IMAGE}" ]] ; then
force_rebuild="1"
if [[ "${image_exists}" == "1" ]] ; then
echo "Removing cached container image ${runner_image} ..."
if [[ -z "${DRY_RUN}" ]] ; then
"${container_cli}" image rm -f "${runner_image}" >/dev/null
else
printf '%q ' "${container_cli}" image rm -f "${runner_image}"
echo
fi
image_exists="0"
fi
fi
if [[ "${image_exists}" == "1" ]] ; then
echo "Using cached container image ${runner_image}"
return
fi
build_cmd=(
"${container_cli}" build --pull
-t "${runner_image}"
--build-arg "BASE_IMAGE=${base_image}"
--build-arg "CMAKE_VERSION=${docker_cmake_version}"
)
if [[ "${force_rebuild}" == "1" ]] ; then
build_cmd+=(--no-cache)
fi
build_cmd+=(-f - "${SCRIPT_PATH}")
printf '%q ' "${build_cmd[@]}"
echo
if [[ -n "${DRY_RUN}" ]] ; then
return
fi
docker_runner_dockerfile | "${build_cmd[@]}"
}
function run_in_docker() {
local container_cli
local runner_image
local container_workspace
local host_uid
local host_gid
local host_user
local -a build_args
local -a container_env
container_cli=$(resolve_container_cli)
runner_image=$(get_docker_runner_image)
host_uid=$(id -u)
host_gid=$(id -g)
host_user="${USER:-orca}"
container_workspace="/__w/OrcaSlicer/OrcaSlicer"
build_args=()
for item in "${FORWARDED_ARGS[@]}" ; do
if [[ "${item}" == "-u" ]] || [[ "${item}" == "-D" ]] ; then
continue
fi
build_args+=("${item}")
done
container_env=(
-e "CI=true"
-e "GITHUB_ACTIONS=true"
-e "GITHUB_WORKSPACE=${container_workspace}"
-e "RUNNER_OS=Linux"
-e "RUNNER_TEMP=/tmp"
-e "HOST_UID=${host_uid}"
-e "HOST_GID=${host_gid}"
-e "HOST_USER=${host_user}"
)
if [[ -n "${CMAKE_BUILD_PARALLEL_LEVEL}" ]] ; then
container_env+=( -e "CMAKE_BUILD_PARALLEL_LEVEL=${CMAKE_BUILD_PARALLEL_LEVEL}" )
fi
if [[ -n "${ORCA_UPDATER_SIG_KEY}" ]] ; then
container_env+=( -e "ORCA_UPDATER_SIG_KEY=${ORCA_UPDATER_SIG_KEY}" )
fi
ensure_docker_runner_image "${container_cli}" "${runner_image}"
printf '%q ' "${container_cli}" run --rm -i \
-v "${SCRIPT_PATH}:${container_workspace}" \
-w "${container_workspace}" \
"${container_env[@]}" \
"${runner_image}" \
bash -s -- "${build_args[@]}"
echo
if [[ -n "${DRY_RUN}" ]] ; then
return
fi
"${container_cli}" run --rm -i \
-v "${SCRIPT_PATH}:${container_workspace}" \
-w "${container_workspace}" \
"${container_env[@]}" \
"${runner_image}" \
bash -s -- "${build_args[@]}" <<'EOF'
set -e
function create_builder_user() {
if [[ "${HOST_UID}" == "0" ]] ; then
HOST_USER=root
return
fi
if getent group "${HOST_GID}" >/dev/null 2>&1 ; then
HOST_GROUP=$(getent group "${HOST_GID}" | cut -d: -f1)
else
HOST_GROUP="orca-builder"
if getent group "${HOST_GROUP}" >/dev/null 2>&1 ; then
HOST_GROUP="orca-builder-${HOST_GID}"
fi
groupadd -g "${HOST_GID}" "${HOST_GROUP}"
fi
if getent passwd "${HOST_UID}" >/dev/null 2>&1 ; then
HOST_USER=$(getent passwd "${HOST_UID}" | cut -d: -f1)
usermod -g "${HOST_GROUP}" "${HOST_USER}"
elif id -u "${HOST_USER}" >/dev/null 2>&1 ; then
usermod -u "${HOST_UID}" -g "${HOST_GROUP}" "${HOST_USER}"
else
useradd -m -u "${HOST_UID}" -g "${HOST_GROUP}" -s /bin/bash "${HOST_USER}"
fi
echo "${HOST_USER} ALL=(ALL) NOPASSWD:ALL" >/etc/sudoers.d/orcaslicer-builder
chmod 0440 /etc/sudoers.d/orcaslicer-builder
}
create_builder_user
mkdir -p "${GITHUB_WORKSPACE}/deps/build/destdir"
chown -R "${HOST_UID}:${HOST_GID}" "${GITHUB_WORKSPACE}/deps/build"
if [[ -d "${GITHUB_WORKSPACE}/build" ]] ; then
chown -R "${HOST_UID}:${HOST_GID}" "${GITHUB_WORKSPACE}/build"
fi
if [[ -d "${GITHUB_WORKSPACE}/build-dbg" ]] ; then
chown -R "${HOST_UID}:${HOST_GID}" "${GITHUB_WORKSPACE}/build-dbg"
fi
if [[ -d "${GITHUB_WORKSPACE}/build-dbginfo" ]] ; then
chown -R "${HOST_UID}:${HOST_GID}" "${GITHUB_WORKSPACE}/build-dbginfo"
fi
sudo -H -u "${HOST_USER}" env \
CMAKE_BUILD_PARALLEL_LEVEL="${CMAKE_BUILD_PARALLEL_LEVEL-}" \
GITHUB_WORKSPACE="${GITHUB_WORKSPACE}" \
ORCA_UPDATER_SIG_KEY="${ORCA_UPDATER_SIG_KEY-}" \
bash -c '
set -e
cd "${GITHUB_WORKSPACE}"
if [[ "$#" -gt 0 ]] ; then
./build_linux.sh "$@"
else
echo "No build steps were requested after container setup."
fi
' bash "$@"
EOF
}
if [[ -n "${USE_DOCKER}" ]] ; then
run_in_docker
popd > /dev/null # ${SCRIPT_PATH}
exit 0
fi
# cmake 4.x compatibility workaround
export CMAKE_POLICY_VERSION_MINIMUM=3.5
@@ -454,8 +151,6 @@ elif [[ "${DISTRIBUTION_LIKE}" == *"debian"* ]] || [[ "${DISTRIBUTION_LIKE}" ==
DISTRIBUTION="debian"
elif [[ "${DISTRIBUTION_LIKE}" == *"arch"* ]] ; then
DISTRIBUTION="arch"
elif [[ "${DISTRIBUTION_LIKE}" == *"suse"* ]] ; then
DISTRIBUTION="suse"
fi
if [ ! -f "./scripts/linux.d/${DISTRIBUTION}" ] ; then
@@ -504,15 +199,6 @@ if [[ -n "${USE_LLD}" ]] ; then
fi
fi
# Auto-detect ccache for faster rebuilds
export CMAKE_CCACHE_ARGS=()
if command -v ccache >/dev/null 2>&1 ; then
echo "ccache found at $(command -v ccache), enabling compiler caching..."
export CMAKE_CCACHE_ARGS=(-DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache)
else
echo "Note: ccache not found. Install ccache for faster rebuilds."
fi
if [[ -n "${BUILD_DEPS}" ]] ; then
echo "Configuring dependencies..."
read -r -a BUILD_ARGS <<< "${DEPS_EXTRA_BUILD_ARGS}"
@@ -526,7 +212,7 @@ if [[ -n "${BUILD_DEPS}" ]] ; then
fi
print_and_run cmake -S deps -B deps/$BUILD_DIR "${CMAKE_C_CXX_COMPILER_CLANG[@]}" "${CMAKE_LLD_LINKER_ARGS[@]}" -G Ninja "${COLORED_OUTPUT}" "${BUILD_ARGS[@]}"
print_and_run cmake --build deps/$BUILD_DIR -j1
print_and_run cmake --build deps/$BUILD_DIR
fi
if [[ -n "${BUILD_ORCA}" ]] || [[ -n "${BUILD_TESTS}" ]] ; then
@@ -545,7 +231,7 @@ if [[ -n "${BUILD_ORCA}" ]] || [[ -n "${BUILD_TESTS}" ]] ; then
BUILD_ARGS+=(-DORCA_UPDATER_SIG_KEY="${ORCA_UPDATER_SIG_KEY}")
fi
print_and_run cmake -S . -B $BUILD_DIR "${CMAKE_C_CXX_COMPILER_CLANG[@]}" "${CMAKE_LLD_LINKER_ARGS[@]}" "${CMAKE_CCACHE_ARGS[@]}" -G "Ninja Multi-Config" \
print_and_run cmake -S . -B $BUILD_DIR "${CMAKE_C_CXX_COMPILER_CLANG[@]}" "${CMAKE_LLD_LINKER_ARGS[@]}" -G "Ninja Multi-Config" \
-DSLIC3R_PCH=${SLIC3R_PRECOMPILED_HEADERS} \
-DORCA_TOOLS=ON \
"${COLORED_OUTPUT}" \
@@ -580,7 +266,4 @@ if [[ -n "${BUILD_IMAGE}" || -n "${BUILD_ORCA}" ]] ; then
popd > /dev/null # build
fi
elapsed=$SECONDS
printf "\nBuild completed in %dh %dm %ds\n" $((elapsed/3600)) $((elapsed%3600/60)) $((elapsed%60))
popd > /dev/null # ${SCRIPT_PATH}

View File

@@ -2,9 +2,8 @@
set -e
set -o pipefail
SECONDS=0
while getopts ":dpa:snt:xbc:i:1Tuh" opt; do
while getopts ":dpa:snt:xbc:1h" opt; do
case "${opt}" in
d )
export BUILD_TARGET="deps"
@@ -35,31 +34,19 @@ while getopts ":dpa:snt:xbc:i:1Tuh" opt; do
c )
export BUILD_CONFIG="$OPTARG"
;;
i )
export CMAKE_IGNORE_PREFIX_PATH="${CMAKE_IGNORE_PREFIX_PATH:+$CMAKE_IGNORE_PREFIX_PATH;}$OPTARG"
;;
1 )
export CMAKE_BUILD_PARALLEL_LEVEL=1
;;
T )
export BUILD_TESTS="1"
;;
u )
export BUILD_TARGET="universal"
;;
h ) echo "Usage: ./build_release_macos.sh [-d]"
echo " -d: Build deps only"
echo " -a: Set ARCHITECTURE (arm64 or x86_64 or universal)"
echo " -s: Build slicer only"
echo " -u: Build universal app only (requires existing arm64 and x86_64 app bundles)"
echo " -n: Nightly build"
echo " -t: Specify minimum version of the target platform, default is 11.3"
echo " -x: Use Ninja Multi-Config CMake generator, default is Xcode"
echo " -b: Build without reconfiguring CMake"
echo " -c: Set CMake build configuration, default is Release"
echo " -i: Add a prefix to ignore during CMake dependency discovery (repeatable), defaults to /opt/local:/usr/local:/opt/homebrew"
echo " -1: Use single job for building"
echo " -T: Build and run tests"
exit 0
;;
* )
@@ -98,26 +85,12 @@ if [ -z "$OSX_DEPLOYMENT_TARGET" ]; then
export OSX_DEPLOYMENT_TARGET="11.3"
fi
if [ -z "$CMAKE_IGNORE_PREFIX_PATH" ]; then
export CMAKE_IGNORE_PREFIX_PATH="/opt/local:/usr/local:/opt/homebrew"
fi
CMAKE_VERSION=$(cmake --version | head -1 | sed 's/[^0-9]*\([0-9]*\).*/\1/')
if [ "$CMAKE_VERSION" -ge 4 ] 2>/dev/null; then
export CMAKE_POLICY_VERSION_MINIMUM=3.5
export CMAKE_POLICY_COMPAT="-DCMAKE_POLICY_VERSION_MINIMUM=3.5"
echo "Detected CMake 4.x, adding compatibility flag (env + cmake arg)"
else
export CMAKE_POLICY_COMPAT=""
fi
echo "Build params:"
echo " - ARCH: $ARCH"
echo " - BUILD_CONFIG: $BUILD_CONFIG"
echo " - BUILD_TARGET: $BUILD_TARGET"
echo " - CMAKE_GENERATOR: $SLICER_CMAKE_GENERATOR for Slicer, $DEPS_CMAKE_GENERATOR for deps"
echo " - OSX_DEPLOYMENT_TARGET: $OSX_DEPLOYMENT_TARGET"
echo " - CMAKE_IGNORE_PREFIX_PATH: $CMAKE_IGNORE_PREFIX_PATH"
echo
# if which -s brew; then
@@ -160,9 +133,7 @@ function build_deps() {
-G "${DEPS_CMAKE_GENERATOR}" \
-DCMAKE_BUILD_TYPE="$BUILD_CONFIG" \
-DCMAKE_OSX_ARCHITECTURES:STRING="${_ARCH}" \
-DCMAKE_OSX_DEPLOYMENT_TARGET="${OSX_DEPLOYMENT_TARGET}" \
-DCMAKE_IGNORE_PREFIX_PATH="${CMAKE_IGNORE_PREFIX_PATH}" \
${CMAKE_POLICY_COMPAT}
-DCMAKE_OSX_DEPLOYMENT_TARGET="${OSX_DEPLOYMENT_TARGET}"
fi
cmake --build . --config "$BUILD_CONFIG" --target deps
)
@@ -199,25 +170,13 @@ function build_slicer() {
-G "${SLICER_CMAKE_GENERATOR}" \
-DORCA_TOOLS=ON \
${ORCA_UPDATER_SIG_KEY:+-DORCA_UPDATER_SIG_KEY="$ORCA_UPDATER_SIG_KEY"} \
${BUILD_TESTS:+-DBUILD_TESTS=ON} \
-DCMAKE_BUILD_TYPE="$BUILD_CONFIG" \
-DCMAKE_OSX_ARCHITECTURES="${_ARCH}" \
-DCMAKE_OSX_DEPLOYMENT_TARGET="${OSX_DEPLOYMENT_TARGET}" \
-DCMAKE_IGNORE_PREFIX_PATH="${CMAKE_IGNORE_PREFIX_PATH}" \
${CMAKE_POLICY_COMPAT}
-DCMAKE_OSX_DEPLOYMENT_TARGET="${OSX_DEPLOYMENT_TARGET}"
fi
cmake --build . --config "$BUILD_CONFIG" --target "$SLICER_BUILD_TARGET"
)
if [ "1." == "$BUILD_TESTS". ]; then
echo "Running tests for $_ARCH..."
(
set -x
cd "$PROJECT_BUILD_DIR"
ctest --build-config "$BUILD_CONFIG" --output-on-failure
)
fi
echo "Verify localization with gettext..."
(
cd "$PROJECT_DIR"
@@ -265,54 +224,48 @@ function build_slicer() {
done
}
function lipo_dir() {
local universal_dir="$1"
local x86_64_dir="$2"
# Find all Mach-O files in the universal (arm64-based) copy and lipo them
while IFS= read -r -d '' f; do
local rel="${f#"$universal_dir"/}"
local x86="$x86_64_dir/$rel"
if [ -f "$x86" ]; then
echo " lipo: $rel"
lipo -create "$f" "$x86" -output "$f.tmp"
mv "$f.tmp" "$f"
else
echo " warning: no x86_64 counterpart for $rel, keeping arm64 only"
fi
done < <(find "$universal_dir" -type f -print0 | while IFS= read -r -d '' candidate; do
if file "$candidate" | grep -q "Mach-O"; then
printf '%s\0' "$candidate"
fi
done)
}
function build_universal() {
echo "Building universal binary..."
PROJECT_BUILD_DIR="$PROJECT_DIR/build/$ARCH"
ARM64_APP="$PROJECT_DIR/build/arm64/OrcaSlicer/OrcaSlicer.app"
X86_64_APP="$PROJECT_DIR/build/x86_64/OrcaSlicer/OrcaSlicer.app"
# Create universal binary
echo "Creating universal binary..."
# PROJECT_BUILD_DIR="$PROJECT_DIR/build_Universal"
mkdir -p "$PROJECT_BUILD_DIR/OrcaSlicer"
UNIVERSAL_APP="$PROJECT_BUILD_DIR/OrcaSlicer/OrcaSlicer.app"
rm -rf "$UNIVERSAL_APP"
cp -R "$ARM64_APP" "$UNIVERSAL_APP"
echo "Creating universal binaries for OrcaSlicer.app..."
lipo_dir "$UNIVERSAL_APP" "$X86_64_APP"
echo "Universal OrcaSlicer.app created at $UNIVERSAL_APP"
cp -R "$PROJECT_DIR/build/arm64/OrcaSlicer/OrcaSlicer.app" "$UNIVERSAL_APP"
# Get the binary path inside the .app bundle
BINARY_PATH="Contents/MacOS/OrcaSlicer"
# Create universal binary using lipo
lipo -create \
"$PROJECT_DIR/build/x86_64/OrcaSlicer/OrcaSlicer.app/$BINARY_PATH" \
"$PROJECT_DIR/build/arm64/OrcaSlicer/OrcaSlicer.app/$BINARY_PATH" \
-output "$UNIVERSAL_APP/$BINARY_PATH"
echo "Universal binary created at $UNIVERSAL_APP"
# Create universal binary for profile validator if it exists
ARM64_VALIDATOR="$PROJECT_DIR/build/arm64/OrcaSlicer/OrcaSlicer_profile_validator.app"
X86_64_VALIDATOR="$PROJECT_DIR/build/x86_64/OrcaSlicer/OrcaSlicer_profile_validator.app"
if [ -d "$ARM64_VALIDATOR" ] && [ -d "$X86_64_VALIDATOR" ]; then
echo "Creating universal binaries for OrcaSlicer_profile_validator.app..."
if [ -f "$PROJECT_DIR/build/arm64/OrcaSlicer/OrcaSlicer_profile_validator.app/Contents/MacOS/OrcaSlicer_profile_validator" ] && \
[ -f "$PROJECT_DIR/build/x86_64/OrcaSlicer/OrcaSlicer_profile_validator.app/Contents/MacOS/OrcaSlicer_profile_validator" ]; then
echo "Creating universal binary for OrcaSlicer_profile_validator..."
UNIVERSAL_VALIDATOR_APP="$PROJECT_BUILD_DIR/OrcaSlicer/OrcaSlicer_profile_validator.app"
rm -rf "$UNIVERSAL_VALIDATOR_APP"
cp -R "$ARM64_VALIDATOR" "$UNIVERSAL_VALIDATOR_APP"
lipo_dir "$UNIVERSAL_VALIDATOR_APP" "$X86_64_VALIDATOR"
echo "Universal OrcaSlicer_profile_validator.app created at $UNIVERSAL_VALIDATOR_APP"
cp -R "$PROJECT_DIR/build/arm64/OrcaSlicer/OrcaSlicer_profile_validator.app" "$UNIVERSAL_VALIDATOR_APP"
# Get the binary path inside the profile validator .app bundle
VALIDATOR_BINARY_PATH="Contents/MacOS/OrcaSlicer_profile_validator"
# Create universal binary using lipo
lipo -create \
"$PROJECT_DIR/build/x86_64/OrcaSlicer/OrcaSlicer_profile_validator.app/$VALIDATOR_BINARY_PATH" \
"$PROJECT_DIR/build/arm64/OrcaSlicer/OrcaSlicer_profile_validator.app/$VALIDATOR_BINARY_PATH" \
-output "$UNIVERSAL_VALIDATOR_APP/$VALIDATOR_BINARY_PATH"
echo "Universal binary for OrcaSlicer_profile_validator created at $UNIVERSAL_VALIDATOR_APP"
fi
}
@@ -327,22 +280,16 @@ case "${BUILD_TARGET}" in
slicer)
build_slicer
;;
universal)
build_universal
;;
*)
echo "Unknown target: $BUILD_TARGET. Available targets: deps, slicer, universal, all."
echo "Unknown target: $BUILD_TARGET. Available targets: deps, slicer, all."
exit 1
;;
esac
if [ "$ARCH" = "universal" ] && { [ "$BUILD_TARGET" = "all" ] || [ "$BUILD_TARGET" = "slicer" ]; }; then
if [ "$ARCH" = "universal" ] && [ "$BUILD_TARGET" != "deps" ]; then
build_universal
fi
if [ "1." == "$PACK_DEPS". ]; then
pack_deps
fi
elapsed=$SECONDS
printf "\nBuild completed in %dh %dm %ds\n" $((elapsed/3600)) $((elapsed%3600/60)) $((elapsed%60))

View File

@@ -1,20 +1,6 @@
@REM OrcaSlicer build script for Windows with VS auto-detect
@echo off
set WP=%CD%
set _START_TIME=%TIME%
@REM Check for Ninja Multi-Config option (-x)
set USE_NINJA=0
for %%a in (%*) do (
if "%%a"=="-x" set USE_NINJA=1
)
if "%USE_NINJA%"=="1" (
echo Using Ninja Multi-Config generator
set CMAKE_GENERATOR="Ninja Multi-Config"
set VS_VERSION=Ninja
goto :generator_ready
)
@REM Detect Visual Studio version using msbuild
echo Detecting Visual Studio version using msbuild...
@@ -64,8 +50,6 @@ if "%VS_MAJOR%"=="16" (
echo Detected Visual Studio %VS_VERSION% (version %VS_MAJOR%)
echo Using CMake generator: %CMAKE_GENERATOR%
:generator_ready
@REM Pack deps
if "%1"=="pack" (
setlocal ENABLEDELAYEDEXPANSION
@@ -74,7 +58,7 @@ if "%1"=="pack" (
echo packing deps: OrcaSlicer_dep_win64_!build_date!_vs!VS_VERSION!.zip
%WP%/tools/7z.exe a OrcaSlicer_dep_win64_!build_date!_vs!VS_VERSION!.zip OrcaSlicer_dep
goto :done
exit /b 0
)
set debug=OFF
@@ -112,16 +96,11 @@ echo "building deps.."
echo on
REM Set minimum CMake policy to avoid <3.5 errors
set CMAKE_POLICY_VERSION_MINIMUM=3.5
if "%USE_NINJA%"=="1" (
cmake ../ -G %CMAKE_GENERATOR% -DCMAKE_BUILD_TYPE=%build_type%
cmake --build . --config %build_type% --target deps
) else (
cmake ../ -G %CMAKE_GENERATOR% -A x64 -DCMAKE_BUILD_TYPE=%build_type%
cmake --build . --config %build_type% --target deps -- -m
)
cmake ../ -G %CMAKE_GENERATOR% -A x64 -DCMAKE_BUILD_TYPE=%build_type%
cmake --build . --config %build_type% --target deps -- -m
@echo off
if "%1"=="deps" goto :done
if "%1"=="deps" exit /b 0
:slicer
echo "building Orca Slicer..."
@@ -131,28 +110,10 @@ cd %build_dir%
echo on
set CMAKE_POLICY_VERSION_MINIMUM=3.5
if "%USE_NINJA%"=="1" (
cmake .. -G %CMAKE_GENERATOR% -DORCA_TOOLS=ON %SIG_FLAG% -DCMAKE_BUILD_TYPE=%build_type%
cmake --build . --config %build_type% --target ALL_BUILD
) else (
cmake .. -G %CMAKE_GENERATOR% -A x64 -DORCA_TOOLS=ON %SIG_FLAG% -DCMAKE_BUILD_TYPE=%build_type%
cmake --build . --config %build_type% --target ALL_BUILD -- -m
)
cmake .. -G %CMAKE_GENERATOR% -A x64 -DORCA_TOOLS=ON %SIG_FLAG% -DCMAKE_BUILD_TYPE=%build_type%
cmake --build . --config %build_type% --target ALL_BUILD -- -m
@echo off
cd ..
call scripts/run_gettext.bat
cd %build_dir%
cmake --build . --target install --config %build_type%
:done
@echo off
for /f "tokens=1-3 delims=:.," %%a in ("%_START_TIME: =0%") do set /a "_start_s=%%a*3600+%%b*60+%%c"
for /f "tokens=1-3 delims=:.," %%a in ("%TIME: =0%") do set /a "_end_s=%%a*3600+%%b*60+%%c"
set /a "_elapsed=_end_s - _start_s"
if %_elapsed% lss 0 set /a "_elapsed+=86400"
set /a "_hours=_elapsed / 3600"
set /a "_remainder=_elapsed - _hours * 3600"
set /a "_mins=_remainder / 60"
set /a "_secs=_remainder - _mins * 60"
echo.
echo Build completed in %_hours%h %_mins%m %_secs%s

View File

@@ -1,26 +0,0 @@
set(_q "")
if(${CMAKE_FIND_PACKAGE_NAME}_FIND_QUIETLY)
set(_q QUIET)
set(_quietly TRUE)
endif()
find_package(${CMAKE_FIND_PACKAGE_NAME} ${${CMAKE_FIND_PACKAGE_NAME}_FIND_VERSION} CONFIG ${_q})
if (NOT ${CMAKE_FIND_PACKAGE_NAME}_FOUND)
include(CheckIncludeFileCXX)
add_library(draco INTERFACE)
target_include_directories(draco INTERFACE include)
if (_quietly)
set(CMAKE_REQUIRED_QUIET ON)
endif()
CHECK_INCLUDE_FILE_CXX("draco/draco_features.h" HAVE_DRACO_H)
if (NOT HAVE_DRACO_H)
if (${CMAKE_FIND_PACKAGE_NAME}_FIND_REQUIRED)
message(FATAL_ERROR "Draco library not found. Please install the dependency.")
elseif(NOT _quietly)
message(WARNING "Draco library not found.")
endif()
endif ()
endif()

View File

@@ -3,7 +3,7 @@
# PrusaSlicer specifics:
# This file is backported from CMake 3.15 distribution to behave uniformly
# across all versions of CMake. It explicitly adds GLEW_STATIC compile
# across all versions of CMake. It explicitly adds GLEW_STATIC complile
# definition to static targets which is needed to prevent link errors.
#[=======================================================================[.rst:
@@ -223,13 +223,8 @@ if(NOT TARGET GLEW::glew AND NOT GLEW_USE_STATIC_LIBS)
PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${GLEW_INCLUDE_DIRS}")
if(APPLE)
if(CMAKE_VERSION VERSION_GREATER_EQUAL "4.0")
set_target_properties(GLEW::glew
PROPERTIES INTERFACE_LINK_LIBRARIES "-framework OpenGL")
else()
set_target_properties(GLEW::glew
PROPERTIES INTERFACE_LINK_LIBRARIES OpenGL::GL)
endif()
set_target_properties(GLEW::glew
PROPERTIES INTERFACE_LINK_LIBRARIES OpenGL::GL)
endif()
if(GLEW_SHARED_LIBRARY_RELEASE)
@@ -263,13 +258,8 @@ elseif(NOT TARGET GLEW::glew_s AND GLEW_USE_STATIC_LIBS)
set_target_properties(GLEW::glew_s PROPERTIES INTERFACE_COMPILE_DEFINITIONS GLEW_STATIC)
if(APPLE)
if(CMAKE_VERSION VERSION_GREATER_EQUAL "4.0")
set_target_properties(GLEW::glew_s
PROPERTIES INTERFACE_LINK_LIBRARIES "-framework OpenGL")
else()
set_target_properties(GLEW::glew_s
PROPERTIES INTERFACE_LINK_LIBRARIES OpenGL::GL)
endif()
set_target_properties(GLEW::glew_s
PROPERTIES INTERFACE_LINK_LIBRARIES OpenGL::GL)
endif()
if(GLEW_STATIC_LIBRARY_RELEASE)
@@ -302,13 +292,8 @@ if(NOT TARGET GLEW::GLEW)
PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${GLEW_INCLUDE_DIRS}")
if(APPLE)
if(CMAKE_VERSION VERSION_GREATER_EQUAL "4.0")
set_target_properties(GLEW::GLEW
PROPERTIES INTERFACE_LINK_LIBRARIES "-framework OpenGL")
else()
set_target_properties(GLEW::GLEW
PROPERTIES INTERFACE_LINK_LIBRARIES OpenGL::GL)
endif()
set_target_properties(GLEW::GLEW
PROPERTIES INTERFACE_LINK_LIBRARIES OpenGL::GL)
endif()
if(TARGET GLEW::glew)

View File

@@ -61,7 +61,7 @@
#
# * TBB_FOUND - Set to false, or undefined, if we havent found, or
# dont want to use TBB.
# * TBB_<component>_FOUND - If False, optional <component> part of TBB system is
# * TBB_<component>_FOUND - If False, optional <component> part of TBB sytem is
# not available.
# * TBB_VERSION - The full version string
# * TBB_VERSION_MAJOR - The major version
@@ -77,7 +77,7 @@
# tbbmalloc, tbbmalloc_debug, tbb_preview, or
# tbb_preview_debug.
#
# The following variables should be used to build and link with TBB:
# The following varibles should be used to build and link with TBB:
#
# * TBB_INCLUDE_DIRS - The include directory for TBB.
# * TBB_LIBRARIES - The libraries to link against to use TBB.

View File

@@ -11,7 +11,7 @@
<key>CFBundleIconFile</key>
<string>${MACOSX_BUNDLE_ICON_FILE}</string>
<key>CFBundleIdentifier</key>
<string>com.orcaslicer.OrcaSlicer</string>
<string>com.softfever3d.orca-slicer</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleLongVersionString</key>
@@ -131,13 +131,22 @@
<true/>
<key>NSHumanReadableCopyright</key>
<string>${MACOSX_BUNDLE_COPYRIGHT}</string>
<key>NSAppTransportSecurity</key>
<key>NSAppTransportSecurity</key>
<dict>
<!-- Disable App Transport Security. Resolves https://github.com/OrcaSlicer/OrcaSlicer/issues/791 -->
<key>NSAllowsArbitraryLoads</key>
<true/>
<true/>
<key>NSAllowsArbitraryLoadsInWebContent</key>
<true/>
</dict>
<!-- Sparkle 2 Auto-Update Configuration -->
<key>SUFeedURL</key>
<string>https://check-version.orcaslicer.com/appcast.xml</string>
<key>SUPublicEDKey</key>
<string>eLFARgt9i0VZQR4FtXiTL6jdwjkGr2RMPjfYCCfBWeM=</string>
<key>SUEnableAutomaticChecks</key>
<true/>
<key>SUAllowsAutomaticUpdates</key>
<true/>
</dict>
</plist>

View File

@@ -18,8 +18,6 @@ orcaslicer_add_cmake_project(Boost
-DBOOST_EXCLUDE_LIBRARIES:STRING=contract|fiber|numpy|stacktrace|wave|test
-DBOOST_LOCALE_ENABLE_ICU:BOOL=OFF # do not link to libicu, breaks compatibility between distros
-DBUILD_TESTING:BOOL=OFF
-DBOOST_IOSTREAMS_ENABLE_BZIP2:BOOL=OFF # avoid libbz2 soname differences in AppImage builds
-DBOOST_IOSTREAMS_ENABLE_ZSTD:BOOL=OFF
"${_context_abi_line}"
"${_context_arch_line}"
)

56
deps/CMakeLists.txt vendored
View File

@@ -1,7 +1,3 @@
if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "4.0")
set(CMAKE_POLICY_VERSION_MINIMUM 3.5 CACHE STRING "" FORCE)
endif()
#
# This CMake project downloads, configures and builds OrcaSlicer dependencies on Unix and Windows.
#
@@ -20,8 +16,8 @@ endif()
# On Windows, architecture (64 vs 32 bits) is judged based on the compiler variant.
# To build dependencies for either 64 or 32 bit OS, use the respective compiler command line.
#
# WARNING: On UNIX platforms wxWidgets hardcode the destdir path into its `wx-config` utility,
# therefore, unfortunately, the installation cannot be copied/moved elsewhere without re-installing wxWidgets.
# WARNING: On UNIX platforms wxWidgets hardcode the destdir path into its `wx-conffig` utility,
# therefore, unfortunatelly, the installation cannot be copied/moved elsewhere without re-installing wxWidgets.
#
cmake_minimum_required(VERSION 3.2)
@@ -166,18 +162,11 @@ function(orcaslicer_add_cmake_project projectname)
endif ()
endif ()
set(_gen "")
set(_build_j "-j${NPROC}")
if (MSVC)
set(_gen CMAKE_GENERATOR "${DEP_MSVC_GEN}" CMAKE_GENERATOR_PLATFORM "${DEP_PLATFORM}")
else()
set(_gen "")
endif()
if ($ENV{CMAKE_BUILD_PARALLEL_LEVEL})
set(_build_j "") # assume environment will control --build parallel setting
elseif(MSVC)
set(_build_j "/m")
else()
set(_build_j "-j${NPROC}")
set(_gen CMAKE_GENERATOR "${DEP_MSVC_GEN}" CMAKE_GENERATOR_PLATFORM "${DEP_PLATFORM}")
set(_build_j "/m")
endif ()
if (NOT IS_CROSS_COMPILE OR NOT APPLE)
@@ -188,18 +177,13 @@ if (NOT IS_CROSS_COMPILE OR NOT APPLE)
DOWNLOAD_DIR ${DEP_DOWNLOAD_DIR}/${projectname}
${_gen}
CMAKE_ARGS
-DCMAKE_POLICY_VERSION_MINIMUM=3.5
-DCMAKE_INSTALL_PREFIX:STRING=${DESTDIR}
-DCMAKE_MODULE_PATH:STRING=${PROJECT_SOURCE_DIR}/../cmake/modules
-DCMAKE_PREFIX_PATH:STRING=${DESTDIR}
-DCMAKE_IGNORE_PREFIX_PATH:STRING=${CMAKE_IGNORE_PREFIX_PATH}
-DCMAKE_DEBUG_POSTFIX:STRING=d
-DCMAKE_C_COMPILER:STRING=${CMAKE_C_COMPILER}
-DCMAKE_CXX_COMPILER:STRING=${CMAKE_CXX_COMPILER}
-DCMAKE_TOOLCHAIN_FILE:STRING=${CMAKE_TOOLCHAIN_FILE}
-DCMAKE_EXE_LINKER_FLAGS:STRING=${CMAKE_EXE_LINKER_FLAGS}
-DCMAKE_SHARED_LINKER_FLAGS:STRING=${CMAKE_SHARED_LINKER_FLAGS}
-DCMAKE_MODULE_LINKER_FLAGS:STRING=${CMAKE_MODULE_LINKER_FLAGS}
-DBUILD_SHARED_LIBS:BOOL=OFF
${_cmake_osx_arch}
"${_configs_line}"
@@ -237,10 +221,8 @@ else()
DOWNLOAD_DIR ${DEP_DOWNLOAD_DIR}/${projectname}
${_gen}
CMAKE_ARGS
-DCMAKE_POLICY_VERSION_MINIMUM=3.5
-DCMAKE_INSTALL_PREFIX:STRING=${DESTDIR}
-DCMAKE_PREFIX_PATH:STRING=${DESTDIR}
-DCMAKE_IGNORE_PREFIX_PATH:STRING=${CMAKE_IGNORE_PREFIX_PATH}
-DBUILD_SHARED_LIBS:BOOL=OFF
${_cmake_osx_arch}
"${_configs_line}"
@@ -265,12 +247,8 @@ if (MSVC)
message(STATUS "\nDetected X86 compiler => building X86 deps bundle\n")
set(DEPS_ARCH "x86")
include("deps-windows.cmake")
elseif ("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "ARM64")
message(STATUS "\nDetected ARM64 compiler => building ARM64 deps bundle\n")
set(DEPS_ARCH "arm64")
include("deps-windows.cmake")
else ()
message(FATAL_ERROR "Unable to detect architecture: ${CMAKE_SYSTEM_PROCESSOR}")
message(FATAL_ERROR "Unable to detect architecture")
endif ()
elseif (APPLE)
message("OS X SDK Path: ${CMAKE_OSX_SYSROOT}")
@@ -352,8 +330,6 @@ include(CGAL/CGAL.cmake)
include(NLopt/NLopt.cmake)
include(libnoise/libnoise.cmake)
include(Draco/Draco.cmake)
# I *think* 1.1 is used for *just* md5 hashing?
# 3.1 has everything in the right place, but the md5 funcs used are deprecated
@@ -410,6 +386,16 @@ endif ()
include(OCCT/OCCT.cmake)
include(OpenCV/OpenCV.cmake)
# WinSparkle for Windows auto-updates
if(WIN32)
include(WinSparkle/WinSparkle.cmake)
endif()
# Sparkle 2 for macOS auto-updates
if(APPLE)
include(Sparkle/Sparkle.cmake)
endif()
set(_dep_list
dep_Boost
dep_TBB
@@ -417,7 +403,6 @@ set(_dep_list
${CURL_PKG}
${WXWIDGETS_PKG}
dep_Cereal
dep_Draco
dep_NLopt
dep_OpenVDB
dep_OpenCSG
@@ -435,12 +420,19 @@ set(_dep_list
if (MSVC)
# Experimental
#list(APPEND _dep_list "dep_qhull")
# WinSparkle for auto-updates
list(APPEND _dep_list "dep_WinSparkle")
else()
list(APPEND _dep_list "dep_Qhull")
# Not working, static build has different Eigen
#list(APPEND _dep_list "dep_libigl")
endif()
if (APPLE)
# Sparkle 2 for auto-updates
list(APPEND _dep_list "dep_Sparkle")
endif()
add_custom_target(deps ALL DEPENDS ${_dep_list})
# Note: I'm not using any of the LOG_xxx options in ExternalProject_Add() commands

View File

@@ -1,4 +0,0 @@
orcaslicer_add_cmake_project(Draco
URL https://github.com/google/draco/archive/refs/tags/1.5.7.zip
URL_HASH SHA256=27b72ba2d5ff3d0a9814ad40d4cb88f8dc89a35491c0866d952473f8f9416b77
)

View File

@@ -5,8 +5,6 @@ find_package(OpenGL QUIET REQUIRED)
orcaslicer_add_cmake_project(
GLEW
SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR}/glew
CMAKE_ARGS
-DGLEW_USE_EGL=OFF
)
if (MSVC)

View File

@@ -3,17 +3,9 @@ project(GLEW)
find_package(OpenGL REQUIRED)
# Allow parent project to control EGL usage.
# Default to OFF since OrcaSlicer forces GDK_BACKEND=x11 (using GLX contexts).
# GLEW must use glXGetProcAddressARB (GLX) to match wxWidgets GL canvas.
# Using EGL function loading with GLX contexts causes rendering failures.
option(GLEW_USE_EGL "Use EGL instead of GLX for OpenGL function loading" OFF)
if(GLEW_USE_EGL)
message(STATUS "Building GLEW with EGL support")
if(OpenGL_EGL_FOUND)
message(STATUS "building GLEW for EGL (hope that wxWidgets agrees, otherwise you won't have any output!)")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DGLEW_EGL")
else()
message(STATUS "Building GLEW with GLX support")
endif()
add_library(GLEW src/glew.c)

16
deps/GLFW/GLFW.cmake vendored
View File

@@ -6,20 +6,22 @@ else()
set(_build_static ON)
endif()
set(_glfw_platform_args "")
if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
set(_glfw_platform_args -DGLFW_BUILD_WAYLAND=ON -DGLFW_BUILD_X11=ON)
set(_glfw_use_wayland "-DGLFW_USE_WAYLAND=ON")
else()
set(_glfw_use_wayland "-DGLFW_USE_WAYLAND=FF")
endif()
orcaslicer_add_cmake_project(GLFW
URL https://github.com/glfw/glfw/archive/refs/tags/3.4.zip
URL_HASH SHA256=a133ddc3d3c66143eba9035621db8e0bcf34dba1ee9514a9e23e96afd39fd57a
URL https://github.com/glfw/glfw/archive/refs/tags/3.3.7.zip
URL_HASH SHA256=e02d956935e5b9fb4abf90e2c2e07c9a0526d7eacae8ee5353484c69a2a76cd0
#DEPENDS dep_Boost
CMAKE_ARGS
-DBUILD_SHARED_LIBS=${_build_shared}
-DBUILD_SHARED_LIBS=${_build_shared}
-DGLFW_BUILD_DOCS=OFF
-DGLFW_BUILD_EXAMPLES=OFF
-DGLFW_BUILD_TESTS=OFF
${_glfw_platform_args}
-DGLFW_BUILD_TESTS=OFF
${_glfw_use_wayland}
)
if (MSVC)

2
deps/GMP/GMP.cmake vendored
View File

@@ -65,7 +65,7 @@ else ()
DOWNLOAD_DIR ${DEP_DOWNLOAD_DIR}/GMP
PATCH_COMMAND git apply ${GMP_DIRECTORY_FLAG} --verbose ${CMAKE_CURRENT_LIST_DIR}/0001-GMP_GCC15.patch
BUILD_IN_SOURCE ON
CONFIGURE_COMMAND env "CC=${CMAKE_C_COMPILER}" "CXX=${CMAKE_CXX_COMPILER}" "CFLAGS=${_gmp_ccflags}" "CXXFLAGS=${_gmp_ccflags}" "LDFLAGS=${CMAKE_EXE_LINKER_FLAGS}" ./configure ${_cross_compile_arg} --enable-shared=no --enable-cxx=yes --enable-static=yes "--prefix=${DESTDIR}" ${_gmp_build_tgt}
CONFIGURE_COMMAND env "CFLAGS=${_gmp_ccflags}" "CXXFLAGS=${_gmp_ccflags}" ./configure ${_cross_compile_arg} --enable-shared=no --enable-cxx=yes --enable-static=yes "--prefix=${DESTDIR}" ${_gmp_build_tgt}
BUILD_COMMAND make -j
INSTALL_COMMAND make install
)

View File

@@ -31,7 +31,7 @@ else ()
DOWNLOAD_DIR ${DEP_DOWNLOAD_DIR}/MPFR
BUILD_IN_SOURCE ON
CONFIGURE_COMMAND autoreconf -f -i &&
env "CC=${CMAKE_C_COMPILER}" "CXX=${CMAKE_CXX_COMPILER}" "CFLAGS=${_gmp_ccflags}" "CXXFLAGS=${_gmp_ccflags}" "LDFLAGS=${CMAKE_EXE_LINKER_FLAGS}" ./configure ${_cross_compile_arg} --prefix=${DESTDIR} --enable-shared=no --enable-static=yes --with-gmp=${DESTDIR} ${_gmp_build_tgt}
env "CFLAGS=${_gmp_ccflags}" "CXXFLAGS=${_gmp_ccflags}" ./configure ${_cross_compile_arg} --prefix=${DESTDIR} --enable-shared=no --enable-static=yes --with-gmp=${DESTDIR} ${_gmp_build_tgt}
BUILD_COMMAND make -j
INSTALL_COMMAND make install
DEPENDS dep_GMP

View File

@@ -16,7 +16,6 @@ orcaslicer_add_cmake_project(OCCT
#DEPENDS dep_Boost
DEPENDS ${FREETYPE_PKG}
CMAKE_ARGS
-DCMAKE_CXX_STANDARD=17
-DBUILD_LIBRARY_TYPE=${library_build_type}
-DUSE_TK=OFF
-DUSE_TBB=OFF

View File

@@ -55,8 +55,6 @@ orcaslicer_add_cmake_project(OpenCV
-DWITH_VTK=OFF
-DWITH_JPEG=OFF
-DWITH_WEBP=OFF
-DWITH_TIFF=OFF
-DBUILD_TIFF=OFF
-DENABLE_PRECOMPILED_HEADERS=OFF
-DINSTALL_TESTS=OFF
-DINSTALL_C_EXAMPLES=OFF

View File

@@ -21,7 +21,7 @@ else()
if(APPLE)
set(_conf_cmd export MACOSX_DEPLOYMENT_TARGET=${CMAKE_OSX_DEPLOYMENT_TARGET} && ./Configure -mmacosx-version-min=${CMAKE_OSX_DEPLOYMENT_TARGET})
else()
set(_conf_cmd env "CC=${CMAKE_C_COMPILER}" "LDFLAGS=${CMAKE_EXE_LINKER_FLAGS}" "./config")
set(_conf_cmd "./config")
endif()
set(_cross_comp_prefix_line "")
set(_make_cmd make -j${NPROC})

27
deps/Sparkle/Sparkle.cmake vendored Normal file
View File

@@ -0,0 +1,27 @@
# Sparkle 2 - Auto-update framework for macOS
# https://sparkle-project.org/
# https://github.com/sparkle-project/Sparkle
#
# Sparkle is distributed as a pre-built framework, so we just download and extract.
if(APPLE)
set(SPARKLE_VERSION "2.8.1")
ExternalProject_Add(
dep_Sparkle
EXCLUDE_FROM_ALL ON
URL "https://github.com/sparkle-project/Sparkle/releases/download/${SPARKLE_VERSION}/Sparkle-${SPARKLE_VERSION}.tar.xz"
URL_HASH SHA256=5cddb7695674ef7704268f38eccaee80e3accbf19e61c1689efff5b6116d85be
DOWNLOAD_DIR ${DEP_DOWNLOAD_DIR}/Sparkle
# No build step needed - just install pre-built framework and tools
CONFIGURE_COMMAND ""
BUILD_COMMAND ""
INSTALL_COMMAND ${CMAKE_COMMAND} -E make_directory ${DESTDIR}/Frameworks
# Use ditto to preserve symlinks in framework bundle (cmake -E copy_directory breaks symlinks)
COMMAND ditto <SOURCE_DIR>/Sparkle.framework ${DESTDIR}/Frameworks/Sparkle.framework
# Also install the Sparkle CLI tools (sign_update, generate_appcast) for CI/CD signing
COMMAND ${CMAKE_COMMAND} -E make_directory ${DESTDIR}/bin
COMMAND ${CMAKE_COMMAND} -E copy <SOURCE_DIR>/bin/sign_update ${DESTDIR}/bin/sign_update
COMMAND ${CMAKE_COMMAND} -E copy <SOURCE_DIR>/bin/generate_appcast ${DESTDIR}/bin/generate_appcast
)
endif()

2
deps/TBB/TBB.cmake vendored
View File

@@ -1,4 +1,4 @@
if (FLATPAK AND "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
if (FLATPAK)
set(_patch_command ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_LIST_DIR}/GNU.cmake ./cmake/compilers/GNU.cmake)
else()
set(_patch_command "")

33
deps/WinSparkle/WinSparkle.cmake vendored Normal file
View File

@@ -0,0 +1,33 @@
# WinSparkle - Auto-update framework for Windows
# https://winsparkle.org/
# https://github.com/vslavik/winsparkle
#
# WinSparkle is distributed as pre-built binaries, so we just download and extract.
if(WIN32)
set(WINSPARKLE_VERSION "0.8.3")
# Determine architecture
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
set(WINSPARKLE_ARCH "x64")
else()
set(WINSPARKLE_ARCH "x86")
endif()
ExternalProject_Add(
dep_WinSparkle
EXCLUDE_FROM_ALL ON
URL "https://github.com/vslavik/winsparkle/releases/download/v${WINSPARKLE_VERSION}/WinSparkle-${WINSPARKLE_VERSION}.zip"
URL_HASH SHA256=5ff4a4604c78d57e01d83e22f79f5ffea0c4969defd48b45c69ccbd6b1a71e94
DOWNLOAD_DIR ${DEP_DOWNLOAD_DIR}/WinSparkle
# No build step needed - just install pre-built binaries
CONFIGURE_COMMAND ""
BUILD_COMMAND ""
INSTALL_COMMAND ${CMAKE_COMMAND} -E copy_directory
<SOURCE_DIR>/include ${DESTDIR}/include
COMMAND ${CMAKE_COMMAND} -E copy
<SOURCE_DIR>/${WINSPARKLE_ARCH}/Release/WinSparkle.dll ${DESTDIR}/bin/WinSparkle.dll
COMMAND ${CMAKE_COMMAND} -E copy
<SOURCE_DIR>/${WINSPARKLE_ARCH}/Release/WinSparkle.lib ${DESTDIR}/lib/WinSparkle.lib
)
endif()

View File

@@ -36,10 +36,8 @@ if ("${DEPS_ARCH}" STREQUAL "x86")
set(DEP_PLATFORM "Win32")
elseif ("${DEPS_ARCH}" STREQUAL "x64")
set(DEP_PLATFORM "x64")
elseif ("${DEPS_ARCH}" STREQUAL "arm64")
set(DEP_PLATFORM "ARM64")
else ()
message(FATAL_ERROR "Unsupported OS architecture: ${DEPS_ARCH}")
message(FATAL_ERROR "Unsupported OS architecture")
endif ()
if (${DEP_DEBUG})
@@ -66,11 +64,8 @@ if ("${DEPS_ARCH}" STREQUAL "x86")
elseif ("${DEPS_ARCH}" STREQUAL "x64")
set(DEP_WXWIDGETS_TARGET "TARGET_CPU=X64")
set(DEP_WXWIDGETS_LIBDIR "vc_x64_lib")
elseif ("${DEPS_ARCH}" STREQUAL "arm64")
set(DEP_WXWIDGETS_TARGET "TARGET_CPU=ARM64")
set(DEP_WXWIDGETS_LIBDIR "vc_arm64_lib")
else ()
message(FATAL_ERROR "Unsupported OS architecture: ${DEPS_ARCH}")
message(FATAL_ERROR "Unsupported OS architecture")
endif ()
find_package(Git REQUIRED)

View File

@@ -1,6 +1,8 @@
set(_wx_toolkit "")
set(_wx_debug_postfix "")
set(_wx_shared -DwxBUILD_SHARED=OFF)
set(_wx_flatpak_patch "")
if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
set(_gtk_ver 2)
@@ -12,6 +14,7 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
if (FLATPAK)
set(_wx_debug_postfix "d")
set(_wx_shared -DwxBUILD_SHARED=ON -DBUILD_SHARED_LIBS:BOOL=ON)
set(_wx_flatpak_patch PATCH_COMMAND ${PATCH_CMD} ${CMAKE_CURRENT_LIST_DIR}/0001-flatpak.patch)
endif ()
endif()
@@ -24,9 +27,9 @@ endif ()
orcaslicer_add_cmake_project(
wxWidgets
GIT_REPOSITORY "https://github.com/SoftFever/Orca-deps-wxWidgets"
GIT_TAG v3.3.2
GIT_SHALLOW ON
DEPENDS ${PNG_PKG} ${ZLIB_PKG} ${EXPAT_PKG} ${JPEG_PKG}
${_wx_flatpak_patch}
CMAKE_ARGS
-DwxBUILD_PRECOMP=ON
${_wx_toolkit}
@@ -36,9 +39,9 @@ orcaslicer_add_cmake_project(
${_wx_shared}
-DwxUSE_MEDIACTRL=ON
-DwxUSE_DETECT_SM=OFF
-DwxUSE_UNICODE=ON
-DwxUSE_PRIVATE_FONTS=ON
-DwxUSE_OPENGL=ON
-DwxUSE_GLCANVAS_EGL=ON
-DwxUSE_WEBREQUEST=ON
-DwxUSE_WEBVIEW=ON
${_wx_edge}
@@ -52,31 +55,7 @@ orcaslicer_add_cmake_project(
-DwxUSE_ZLIB=sys
-DwxUSE_LIBJPEG=sys
-DwxUSE_LIBTIFF=OFF
-DwxUSE_LIBWEBP=builtin
-DwxUSE_EXPAT=sys
-DwxUSE_NANOSVG=OFF
)
# wxWidgets 3.3 cmake install doesn't include private headers.
# OrcaSlicer uses some of the private headers (for accessibility support).
# Copy the private headers directory after install.
if(MSVC)
set(_wx_inc_dest ${DESTDIR}/include/wx)
else()
set(_wx_inc_dest ${DESTDIR}/include/wx-3.3/wx)
endif()
ExternalProject_Add_Step(dep_wxWidgets copy_private_headers
DEPENDEES install
COMMENT "Copying wxWidgets private headers"
COMMAND ${CMAKE_COMMAND} -E copy_directory
<SOURCE_DIR>/include/wx/private
${_wx_inc_dest}/private
COMMAND ${CMAKE_COMMAND} -E copy_directory
<SOURCE_DIR>/include/wx/generic/private
${_wx_inc_dest}/generic/private
COMMAND ${CMAKE_COMMAND} -E copy_directory
<SOURCE_DIR>/include/wx/gtk/private
${_wx_inc_dest}/gtk/private
)
if (MSVC)

View File

@@ -26,7 +26,6 @@ add_subdirectory(imguizmo)
add_subdirectory(libigl)
add_subdirectory(libnest2d)
add_subdirectory(mcut)
add_subdirectory(md4c)
add_subdirectory(miniz)
add_subdirectory(minilzo)
add_subdirectory(qhull)

View File

@@ -153,8 +153,6 @@ namespace ImGui
// const wchar_t CustomSupportsMarker = 0x1D;
// const wchar_t CustomSeamMarker = 0x1E;
// const wchar_t MmuSegmentationMarker = 0x1F;
//const wchar_t HorizontalHide = 0xB1; // ORCA use FoldButtonIcon / UnfoldButtonIcon
//const wchar_t HorizontalShow = 0xB2;
// Do not forget use following letters only in wstring
//BBS use 08xx to avoid unicode character which may be used

View File

@@ -18,7 +18,7 @@ template <
typename DerivedF,
typename SType,
typename DerivedNF>
IGL_INLINE bool igl::loop(
IGL_INLINE void igl::loop(
const int n_verts,
const Eigen::PlainObjectBase<DerivedF> & F,
Eigen::SparseMatrix<SType>& S,
@@ -26,15 +26,15 @@ IGL_INLINE bool igl::loop(
{
typedef Eigen::SparseMatrix<SType> SparseMat;
typedef Eigen::Triplet<SType> Triplet_t;
//Ref. https://graphics.stanford.edu/~mdfisher/subdivision.html
//Heavily borrowing from igl::upsample
DerivedF FF, FFi;
triangle_triangle_adjacency(F, FF, FFi);
std::vector<std::vector<typename DerivedF::Scalar>> adjacencyList;
adjacency_list(F, adjacencyList, true);
//Compute the number and positions of the vertices to insert (on edges)
Eigen::MatrixXi NI = Eigen::MatrixXi::Constant(FF.rows(), FF.cols(), -1);
Eigen::MatrixXi NIdoubles = Eigen::MatrixXi::Zero(FF.rows(), FF.cols());
@@ -48,18 +48,12 @@ IGL_INLINE bool igl::loop(
{
NI(i,j) = counter;
NIdoubles(i,j) = 0;
if (FF(i,j) != -1)
if (FF(i,j) != -1)
{
//If it is not a boundary
int adj_triangle = FF(i, j);
int adj_edge = FFi(i, j);
if (adj_triangle >= 0 && adj_triangle < NI.rows() && adj_edge >= 0 && adj_edge < NI.cols()) {
NI(adj_triangle, adj_edge) = counter;
NIdoubles(i, j) = 1;
} else {
return false;
}
} else
NI(FF(i,j), FFi(i,j)) = counter;
NIdoubles(i,j) = 1;
} else
{
//Mark boundary vertices for later
vertIsOnBdry(F(i,j)) = 1;
@@ -69,24 +63,24 @@ IGL_INLINE bool igl::loop(
}
}
}
const int& n_odd = n_verts;
const int& n_even = counter;
const int n_newverts = n_odd + n_even;
//Construct vertex positions
std::vector<Triplet_t> tripletList;
for(int i=0; i<n_odd; ++i)
for(int i=0; i<n_odd; ++i)
{
//Old vertices
const std::vector<int>& localAdjList = adjacencyList[i];
if(vertIsOnBdry(i)==1)
if(vertIsOnBdry(i)==1)
{
//Boundary vertex
tripletList.emplace_back(i, localAdjList.front(), 1./8.);
tripletList.emplace_back(i, localAdjList.back(), 1./8.);
tripletList.emplace_back(i, i, 3./4.);
} else
} else
{
const int n = localAdjList.size();
const SType dn = n;
@@ -105,19 +99,19 @@ IGL_INLINE bool igl::loop(
tripletList.emplace_back(i, i, 1.-dn*beta);
}
}
for(int i=0; i<FF.rows(); ++i)
for(int i=0; i<FF.rows(); ++i)
{
//New vertices
for(int j=0; j<3; ++j)
for(int j=0; j<3; ++j)
{
if(NIdoubles(i,j)==0)
if(NIdoubles(i,j)==0)
{
if(FF(i,j)==-1)
if(FF(i,j)==-1)
{
//Boundary vertex
tripletList.emplace_back(NI(i,j) + n_odd, F(i,j), 1./2.);
tripletList.emplace_back(NI(i,j) + n_odd, F(i, (j+1)%3), 1./2.);
} else
} else
{
tripletList.emplace_back(NI(i,j) + n_odd, F(i,j), 3./8.);
tripletList.emplace_back(NI(i,j) + n_odd, F(i, (j+1)%3), 3./8.);
@@ -129,34 +123,33 @@ IGL_INLINE bool igl::loop(
}
S.resize(n_newverts, n_verts);
S.setFromTriplets(tripletList.begin(), tripletList.end());
// Build the new topology (Every face is replaced by four)
NF.resize(F.rows()*4, 3);
for(int i=0; i<F.rows();++i)
{
Eigen::VectorXi VI(6);
VI << F(i,0), F(i,1), F(i,2), NI(i,0) + n_odd, NI(i,1) + n_odd, NI(i,2) + n_odd;
Eigen::VectorXi f0(3), f1(3), f2(3), f3(3);
f0 << VI(0), VI(3), VI(5);
f1 << VI(1), VI(4), VI(3);
f2 << VI(3), VI(4), VI(5);
f3 << VI(4), VI(2), VI(5);
NF.row((i*4)+0) = f0;
NF.row((i*4)+1) = f1;
NF.row((i*4)+2) = f2;
NF.row((i*4)+3) = f3;
}
return true;
}
template <
typename DerivedV,
typename DerivedV,
typename DerivedF,
typename DerivedNV,
typename DerivedNF>
IGL_INLINE bool igl::loop(
IGL_INLINE void igl::loop(
const Eigen::PlainObjectBase<DerivedV>& V,
const Eigen::PlainObjectBase<DerivedF>& F,
Eigen::PlainObjectBase<DerivedNV>& NV,
@@ -165,19 +158,16 @@ IGL_INLINE bool igl::loop(
{
NV = V;
NF = F;
for(int i=0; i<number_of_subdivs; ++i)
for(int i=0; i<number_of_subdivs; ++i)
{
DerivedNF tempF = NF;
Eigen::SparseMatrix<typename DerivedV::Scalar> S;
if (!loop(NV.rows(), tempF, S, NF)) {
return false;
}
loop(NV.rows(), tempF, S, NF);
// This .eval is super important
NV = (S*NV).eval();
}
return true;
}
#ifdef IGL_STATIC_LIBRARY
template void igl::loop<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, int);
#endif
#endif

View File

@@ -29,7 +29,7 @@ namespace igl
typename DerivedF,
typename SType,
typename DerivedNF>
IGL_INLINE bool loop(
IGL_INLINE void loop(
const int n_verts,
const Eigen::PlainObjectBase<DerivedF> & F,
Eigen::SparseMatrix<SType>& S,
@@ -44,11 +44,11 @@ namespace igl
// NV a matrix containing the new vertices
// NF a matrix containing the new faces
template <
typename DerivedV,
typename DerivedV,
typename DerivedF,
typename DerivedNV,
typename DerivedNF>
IGL_INLINE bool loop(
IGL_INLINE void loop(
const Eigen::PlainObjectBase<DerivedV>& V,
const Eigen::PlainObjectBase<DerivedF>& F,
Eigen::PlainObjectBase<DerivedNV>& NV,

View File

@@ -1,71 +0,0 @@
cmake_minimum_required(VERSION 3.5)
project(MD4C C)
set(MD_VERSION_MAJOR 0)
set(MD_VERSION_MINOR 5)
set(MD_VERSION_RELEASE 2)
set(MD_VERSION "${MD_VERSION_MAJOR}.${MD_VERSION_MINOR}.${MD_VERSION_RELEASE}")
set(PROJECT_VERSION "${MD_VERSION}")
set(PROJECT_URL "https://github.com/mity/md4c")
#option(BUILD_MD2HTML_EXECUTABLE "Whether to compile the md2html executable" ON)
#if(WIN32)
# # On Windows, given there is no standard lib install dir etc., we rather
# # by default build static lib.
# option(BUILD_SHARED_LIBS "help string describing option" OFF)
#else()
# # On Linux, MD4C is slowly being adding into some distros which prefer
# # shared lib.
# option(BUILD_SHARED_LIBS "help string describing option" ON)
#endif()
add_definitions(
-DMD_VERSION_MAJOR=${MD_VERSION_MAJOR}
-DMD_VERSION_MINOR=${MD_VERSION_MINOR}
-DMD_VERSION_RELEASE=${MD_VERSION_RELEASE}
)
#set(CMAKE_CONFIGURATION_TYPES Debug Release RelWithDebInfo MinSizeRel)
#if("${CMAKE_BUILD_TYPE}" STREQUAL "")
# set(CMAKE_BUILD_TYPE $ENV{CMAKE_BUILD_TYPE})
#
# if("${CMAKE_BUILD_TYPE}" STREQUAL "")
# set(CMAKE_BUILD_TYPE "Release")
# endif()
#endif()
if(${CMAKE_C_COMPILER_ID} MATCHES GNU|Clang)
add_compile_options(-Wall -Wextra -Wshadow)
# We enforce -Wdeclaration-after-statement because Qt project needs to
# build MD4C with Integrity compiler which chokes whenever a declaration
# is not at the beginning of a block.
add_compile_options(-Wdeclaration-after-statement)
elseif(MSVC)
# Disable warnings about the so-called unsecured functions:
add_definitions(/D_CRT_SECURE_NO_WARNINGS)
add_compile_options(/W3)
# Specify proper C runtime library:
string(REGEX REPLACE "/M[DT]d?" "" CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}")
string(REGEX REPLACE "/M[DT]d?" "" CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}")
string(REGEX REPLACE "/M[DT]d?" "" CMAKE_C_FLAGS_RELWITHDEBINFO "{$CMAKE_C_FLAGS_RELWITHDEBINFO}")
string(REGEX REPLACE "/M[DT]d?" "" CMAKE_C_FLAGS_MINSIZEREL "${CMAKE_C_FLAGS_MINSIZEREL}")
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /MTd")
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /MT")
set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELEASE} /MT")
set(CMAKE_C_FLAGS_MINSIZEREL "${CMAKE_C_FLAGS_RELEASE} /MT")
endif()
include(GNUInstallDirs)
add_subdirectory(src)
#if (BUILD_MD2HTML_EXECUTABLE)
# add_subdirectory(md2html)
#endif ()

View File

@@ -1,22 +0,0 @@
# The MIT License (MIT)
Copyright © 2016-2024 Martin Mitáš
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the “Software”),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.

View File

@@ -1,297 +0,0 @@
# MD4C Readme
* Home: http://github.com/mity/md4c
* Wiki: http://github.com/mity/md4c/wiki
* Issue tracker: http://github.com/mity/md4c/issues
MD4C stands for "Markdown for C" and that's exactly what this project is about.
## What is Markdown
In short, Markdown is the markup language this `README.md` file is written in.
The following resources can explain more if you are unfamiliar with it:
* [Wikipedia article](http://en.wikipedia.org/wiki/Markdown)
* [CommonMark site](http://commonmark.org)
## What is MD4C
MD4C is Markdown parser implementation in C, with the following features:
* **Compliance:** Generally, MD4C aims to be compliant to the latest version of
[CommonMark specification](http://spec.commonmark.org/). Currently, we are
fully compliant to CommonMark 0.31.
* **Extensions:** MD4C supports some commonly requested and accepted extensions.
See below.
* **Performance:** MD4C is [very fast](https://talk.commonmark.org/t/2520).
* **Compactness:** MD4C parser is implemented in one source file and one header
file. There are no dependencies other than standard C library.
* **Embedding:** MD4C parser is easy to reuse in other projects, its API is
very straightforward: There is actually just one function, `md_parse()`.
* **Push model:** MD4C parses the complete document and calls few callback
functions provided by the application to inform it about a start/end of
every block, a start/end of every span, and with any textual contents.
* **Portability:** MD4C builds and works on Windows and POSIX-compliant OSes.
(It should be simple to make it run also on most other platforms, at least as
long as the platform provides C standard library, including a heap memory
management.)
* **Encoding:** MD4C by default expects UTF-8 encoding of the input document.
But it can be compiled to recognize ASCII-only control characters (i.e. to
disable all Unicode-specific code), or (on Windows) to expect UTF-16 (i.e.
what is on Windows commonly called just "Unicode"). See more details below.
* **Permissive license:** MD4C is available under the [MIT license](LICENSE.md).
## Using MD4C
### Parsing Markdown
If you need just to parse a Markdown document, you need to include `md4c.h`
and link against MD4C library (`-lmd4c`); or alternatively add `md4c.[hc]`
directly to your code base as the parser is only implemented in the single C
source file.
The main provided function is `md_parse()`. It takes a text in the Markdown
syntax and a pointer to a structure which provides pointers to several callback
functions.
As `md_parse()` processes the input, it calls the callbacks (when entering or
leaving any Markdown block or span; and when outputting any textual content of
the document), allowing application to convert it into another format or render
it onto the screen.
### Converting to HTML
If you need to convert Markdown to HTML, include `md4c-html.h` and link against
MD4C-HTML library (`-lmd4c-html`); or alternatively add the sources `md4c.[hc]`,
`md4c-html.[hc]` and `entity.[hc]` into your code base.
To convert a Markdown input, call `md_html()` function. It takes the Markdown
input and calls the provided callback function. The callback is fed with
chunks of the HTML output. Typical callback implementation just appends the
chunks into a buffer or writes them to a file.
## Markdown Extensions
The default behavior is to recognize only Markdown syntax defined by the
[CommonMark specification](http://spec.commonmark.org/).
However, with appropriate flags, the behavior can be tuned to enable some
extensions:
* With the flag `MD_FLAG_COLLAPSEWHITESPACE`, a non-trivial whitespace is
collapsed into a single space.
* With the flag `MD_FLAG_TABLES`, GitHub-style tables are supported.
* With the flag `MD_FLAG_TASKLISTS`, GitHub-style task lists are supported.
* With the flag `MD_FLAG_STRIKETHROUGH`, strike-through spans are enabled
(text enclosed in tilde marks, e.g. `~foo bar~`).
* With the flag `MD_FLAG_PERMISSIVEURLAUTOLINKS` permissive URL autolinks
(not enclosed in `<` and `>`) are supported.
* With the flag `MD_FLAG_PERMISSIVEEMAILAUTOLINKS`, permissive e-mail
autolinks (not enclosed in `<` and `>`) are supported.
* With the flag `MD_FLAG_PERMISSIVEWWWAUTOLINKS` permissive WWW autolinks
without any scheme specified (e.g. `www.example.com`) are supported. MD4C
then assumes `http:` scheme.
* With the flag `MD_FLAG_LATEXMATHSPANS` LaTeX math spans (`$...$`) and
LaTeX display math spans (`$$...$$`) are supported. (Note though that the
HTML renderer outputs them verbatim in a custom tag `<x-equation>`.)
* With the flag `MD_FLAG_WIKILINKS`, wiki-style links (`[[link label]]` and
`[[target article|link label]]`) are supported. (Note that the HTML renderer
outputs them in a custom tag `<x-wikilink>`.)
* With the flag `MD_FLAG_UNDERLINE`, underscore (`_`) denotes an underline
instead of an ordinary emphasis or strong emphasis.
Few features of CommonMark (those some people see as mis-features) may be
disabled with the following flags:
* With the flag `MD_FLAG_NOHTMLSPANS` or `MD_FLAG_NOHTMLBLOCKS`, raw inline
HTML or raw HTML blocks respectively are disabled.
* With the flag `MD_FLAG_NOINDENTEDCODEBLOCKS`, indented code blocks are
disabled.
## Input/Output Encoding
The CommonMark specification declares that any sequence of Unicode code points
is a valid CommonMark document.
But, under a closer inspection, Unicode plays any role in few very specific
situations when parsing Markdown documents:
1. For detection of word boundaries when processing emphasis and strong
emphasis, some classification of Unicode characters (whether it is
a whitespace or a punctuation) is needed.
2. For (case-insensitive) matching of a link reference label with the
corresponding link reference definition, Unicode case folding is used.
3. For translating HTML entities (e.g. `&amp;`) and numeric character
references (e.g. `&#35;` or `&#xcab;`) into their Unicode equivalents.
However note MD4C leaves this translation on the renderer/application; as
the renderer is supposed to really know output encoding and whether it
really needs to perform this kind of translation. (For example, when the
renderer outputs HTML, it may leave the entities untranslated and defer the
work to a web browser.)
MD4C relies on this property of the CommonMark and the implementation is, to
a large degree, encoding-agnostic. Most of MD4C code only assumes that the
encoding of your choice is compatible with ASCII. I.e. that the codepoints
below 128 have the same numeric values as ASCII.
Any input MD4C does not understand is simply seen as part of the document text
and sent to the renderer's callback functions unchanged.
The two situations (word boundary detection and link reference matching) where
MD4C has to understand Unicode are handled as specified by the following
preprocessor macros (as specified at the time MD4C is being built):
* If preprocessor macro `MD4C_USE_UTF8` is defined, MD4C assumes UTF-8 for the
word boundary detection and for the case-insensitive matching of link labels.
When none of these macros is explicitly used, this is the default behavior.
* On Windows, if preprocessor macro `MD4C_USE_UTF16` is defined, MD4C uses
`WCHAR` instead of `char` and assumes UTF-16 encoding in those situations.
(UTF-16 is what Windows developers usually call just "Unicode" and what
Win32API generally works with.)
Note that because this macro affects also the types in `md4c.h`, you have
to define the macro both when building MD4C as well as when including
`md4c.h`.
Also note this is only supported in the parser (`md4c.[hc]`). The HTML
renderer does not support this and you will have to write your own custom
renderer to use this feature.
* If preprocessor macro `MD4C_USE_ASCII` is defined, MD4C assumes nothing but
an ASCII input.
That effectively means that non-ASCII whitespace or punctuation characters
won't be recognized as such and that link reference matching will work in
a case-insensitive way only for ASCII letters (`[a-zA-Z]`).
## Documentation
The API of the parser is quite well documented in the comments in the `md4c.h`.
Similarly, the markdown-to-html API is described in its header `md4c-html.h`.
There is also [project wiki](http://github.com/mity/md4c/wiki) which provides
some more comprehensive documentation. However note it is incomplete and some
details may be somewhat outdated.
## FAQ
**Q: How does MD4C compare to other Markdown parsers?**
**A:** Some other implementations combine Markdown parser and HTML generator
into a single entangled code hidden behind an interface which just allows the
conversion from Markdown to HTML. They are often unusable if you want to
process the input in any other way.
Second, most parsers (if not all of them; at least within the scope of C/C++
language) are full DOM-like parsers: They construct abstract syntax tree (AST)
representation of the whole Markdown document. That takes time and it leads to
bigger memory footprint.
Building AST is completely fine as long as you need it. If you don't, there is
a very high chance that using MD4C will be substantially faster and less hungry
in terms of memory consumption.
Last but not least, some Markdown parsers are implemented in a naive way. When
fed with a [smartly crafted input pattern](test/pathological_tests.py), they
may exhibit quadratic (or even worse) parsing times. What MD4C can still parse
in a fraction of second may turn into long minutes or possibly hours with them.
Hence, when such a naive parser is used to process an input from an untrusted
source, the possibility of denial-of-service attacks becomes a real danger.
A lot of our effort went into providing linear parsing times no matter what
kind of crazy input MD4C parser is fed with. (If you encounter an input pattern
which leads to a sub-linear parsing times, please do not hesitate and report it
as a bug.)
**Q: Does MD4C perform any input validation?**
**A:** No. And we are proud of it. :-)
CommonMark specification states that any sequence of Unicode characters is
a valid Markdown document. (In practice, this more or less always means UTF-8
encoding.)
In other words, according to the specification, it does not matter whether some
Markdown syntax construction is in some way broken or not. If it's broken, it
won't be recognized and the parser should see it just as a verbatim text.
MD4C takes this a step further: It sees any sequence of bytes as a valid input,
following completely the GIGO philosophy (garbage in, garbage out). I.e. any
ill-formed UTF-8 byte sequence will propagate to the respective callback as
a part of the text.
If you need to validate that the input is, say, a well-formed UTF-8 document,
you have to do it on your own. The easiest way how to do this is to simply
validate the whole document before passing it to the MD4C parser.
## License
MD4C is covered with MIT license, see the file `LICENSE.md`.
## Links to Related Projects
Ports and bindings to other languages:
* [commonmark-d](https://github.com/AuburnSounds/commonmark-d):
Port of MD4C to D language.
* [markdown-wasm](https://github.com/rsms/markdown-wasm):
Port of MD4C to WebAssembly.
* [PyMD4C](https://github.com/dominickpastore/pymd4c):
Python bindings for MD4C
Software using MD4C:
* [imgui_md](https://github.com/mekhontsev/imgui_md):
Markdown renderer for [Dear ImGui](https://github.com/ocornut/imgui)
* [MarkDown Monolith Assembler](https://github.com/1Hyena/mdma):
A command line tool for building browser-based books.
* [QOwnNotes](https://www.qownnotes.org/):
A plain-text file notepad and todo-list manager with markdown support and
ownCloud / Nextcloud integration.
* [Qt](https://www.qt.io/):
Cross-platform C++ GUI framework.
* [Textosaurus](https://github.com/martinrotter/textosaurus):
Cross-platform text editor based on Qt and Scintilla.
* [8th](https://8th-dev.com/):
Cross-platform concatenative programming language.

View File

@@ -1,53 +0,0 @@
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS 1)
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DDEBUG")
# Build rules for MD4C parser library
configure_file(md4c.pc.in md4c.pc @ONLY)
add_library(md4c md4c.c md4c.h)
set_target_properties(md4c PROPERTIES
COMPILE_FLAGS "-DMD4C_USE_UTF8"
VERSION ${MD_VERSION}
SOVERSION ${MD_VERSION_MAJOR}
PUBLIC_HEADER md4c.h
)
# Build rules for HTML renderer library
configure_file(md4c-html.pc.in md4c-html.pc @ONLY)
add_library(md4c-html md4c-html.c md4c-html.h entity.c entity.h)
set_target_properties(md4c-html PROPERTIES
VERSION ${MD_VERSION}
SOVERSION ${MD_VERSION_MAJOR}
PUBLIC_HEADER md4c-html.h
)
target_link_libraries(md4c-html md4c)
# Install rules
#install(
# TARGETS md4c
# EXPORT md4cConfig
# ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
# LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
# RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
# PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
# INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
#)
#install(FILES ${CMAKE_BINARY_DIR}/src/md4c.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)
#
#install(
# TARGETS md4c-html
# EXPORT md4cConfig
# ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
# LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
# RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
# PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
#)
#install(FILES ${CMAKE_BINARY_DIR}/src/md4c-html.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)
#
#install(EXPORT md4cConfig DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/md4c/ NAMESPACE md4c::)
#

File diff suppressed because it is too large Load Diff

View File

@@ -1,43 +0,0 @@
/*
* MD4C: Markdown parser for C
* (http://github.com/mity/md4c)
*
* Copyright (c) 2016-2024 Martin Mitáš
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
#ifndef MD4C_ENTITY_H
#define MD4C_ENTITY_H
#include <stdlib.h>
/* Most entities are formed by single Unicode codepoint, few by two codepoints.
* Single-codepoint entities have codepoints[1] set to zero. */
typedef struct ENTITY_tag ENTITY;
struct ENTITY_tag {
const char* name;
unsigned codepoints[2];
};
const ENTITY* entity_lookup(const char* name, size_t name_size);
#endif /* MD4C_ENTITY_H */

View File

@@ -1,567 +0,0 @@
/*
* MD4C: Markdown parser for C
* (http://github.com/mity/md4c)
*
* Copyright (c) 2016-2024 Martin Mitáš
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
#include <stdio.h>
#include <string.h>
#include "md4c-html.h"
#include "entity.h"
#if !defined(__STDC_VERSION__) || __STDC_VERSION__ < 199409L
/* C89/90 or old compilers in general may not understand "inline". */
#if defined __GNUC__
#define inline __inline__
#elif defined _MSC_VER
#define inline __inline
#else
#define inline
#endif
#endif
#ifdef _WIN32
#define snprintf _snprintf
#endif
typedef struct MD_HTML_tag MD_HTML;
struct MD_HTML_tag {
void (*process_output)(const MD_CHAR*, MD_SIZE, void*);
void* userdata;
unsigned flags;
int image_nesting_level;
char escape_map[256];
};
#define NEED_HTML_ESC_FLAG 0x1
#define NEED_URL_ESC_FLAG 0x2
/*****************************************
*** HTML rendering helper functions ***
*****************************************/
#define ISDIGIT(ch) ('0' <= (ch) && (ch) <= '9')
#define ISLOWER(ch) ('a' <= (ch) && (ch) <= 'z')
#define ISUPPER(ch) ('A' <= (ch) && (ch) <= 'Z')
#define ISALNUM(ch) (ISLOWER(ch) || ISUPPER(ch) || ISDIGIT(ch))
static inline void
render_verbatim(MD_HTML* r, const MD_CHAR* text, MD_SIZE size)
{
r->process_output(text, size, r->userdata);
}
/* Keep this as a macro. Most compiler should then be smart enough to replace
* the strlen() call with a compile-time constant if the string is a C literal. */
#define RENDER_VERBATIM(r, verbatim) \
render_verbatim((r), (verbatim), (MD_SIZE) (strlen(verbatim)))
static void
render_html_escaped(MD_HTML* r, const MD_CHAR* data, MD_SIZE size)
{
MD_OFFSET beg = 0;
MD_OFFSET off = 0;
/* Some characters need to be escaped in normal HTML text. */
#define NEED_HTML_ESC(ch) (r->escape_map[(unsigned char)(ch)] & NEED_HTML_ESC_FLAG)
while(1) {
/* Optimization: Use some loop unrolling. */
while(off + 3 < size && !NEED_HTML_ESC(data[off+0]) && !NEED_HTML_ESC(data[off+1])
&& !NEED_HTML_ESC(data[off+2]) && !NEED_HTML_ESC(data[off+3]))
off += 4;
while(off < size && !NEED_HTML_ESC(data[off]))
off++;
if(off > beg)
render_verbatim(r, data + beg, off - beg);
if(off < size) {
switch(data[off]) {
case '&': RENDER_VERBATIM(r, "&amp;"); break;
case '<': RENDER_VERBATIM(r, "&lt;"); break;
case '>': RENDER_VERBATIM(r, "&gt;"); break;
case '"': RENDER_VERBATIM(r, "&quot;"); break;
}
off++;
} else {
break;
}
beg = off;
}
}
static void
render_url_escaped(MD_HTML* r, const MD_CHAR* data, MD_SIZE size)
{
static const MD_CHAR hex_chars[] = "0123456789ABCDEF";
MD_OFFSET beg = 0;
MD_OFFSET off = 0;
/* Some characters need to be escaped in URL attributes. */
#define NEED_URL_ESC(ch) (r->escape_map[(unsigned char)(ch)] & NEED_URL_ESC_FLAG)
while(1) {
while(off < size && !NEED_URL_ESC(data[off]))
off++;
if(off > beg)
render_verbatim(r, data + beg, off - beg);
if(off < size) {
char hex[3];
switch(data[off]) {
case '&': RENDER_VERBATIM(r, "&amp;"); break;
default:
hex[0] = '%';
hex[1] = hex_chars[((unsigned)data[off] >> 4) & 0xf];
hex[2] = hex_chars[((unsigned)data[off] >> 0) & 0xf];
render_verbatim(r, hex, 3);
break;
}
off++;
} else {
break;
}
beg = off;
}
}
static unsigned
hex_val(char ch)
{
if('0' <= ch && ch <= '9')
return ch - '0';
if('A' <= ch && ch <= 'Z')
return ch - 'A' + 10;
else
return ch - 'a' + 10;
}
static void
render_utf8_codepoint(MD_HTML* r, unsigned codepoint,
void (*fn_append)(MD_HTML*, const MD_CHAR*, MD_SIZE))
{
static const MD_CHAR utf8_replacement_char[] = { (char)0xef, (char)0xbf, (char)0xbd };
unsigned char utf8[4];
size_t n;
if(codepoint <= 0x7f) {
n = 1;
utf8[0] = codepoint;
} else if(codepoint <= 0x7ff) {
n = 2;
utf8[0] = 0xc0 | ((codepoint >> 6) & 0x1f);
utf8[1] = 0x80 + ((codepoint >> 0) & 0x3f);
} else if(codepoint <= 0xffff) {
n = 3;
utf8[0] = 0xe0 | ((codepoint >> 12) & 0xf);
utf8[1] = 0x80 + ((codepoint >> 6) & 0x3f);
utf8[2] = 0x80 + ((codepoint >> 0) & 0x3f);
} else {
n = 4;
utf8[0] = 0xf0 | ((codepoint >> 18) & 0x7);
utf8[1] = 0x80 + ((codepoint >> 12) & 0x3f);
utf8[2] = 0x80 + ((codepoint >> 6) & 0x3f);
utf8[3] = 0x80 + ((codepoint >> 0) & 0x3f);
}
if(0 < codepoint && codepoint <= 0x10ffff)
fn_append(r, (char*)utf8, (MD_SIZE)n);
else
fn_append(r, utf8_replacement_char, 3);
}
/* Translate entity to its UTF-8 equivalent, or output the verbatim one
* if such entity is unknown (or if the translation is disabled). */
static void
render_entity(MD_HTML* r, const MD_CHAR* text, MD_SIZE size,
void (*fn_append)(MD_HTML*, const MD_CHAR*, MD_SIZE))
{
if(r->flags & MD_HTML_FLAG_VERBATIM_ENTITIES) {
render_verbatim(r, text, size);
return;
}
/* We assume UTF-8 output is what is desired. */
if(size > 3 && text[1] == '#') {
unsigned codepoint = 0;
if(text[2] == 'x' || text[2] == 'X') {
/* Hexadecimal entity (e.g. "&#x1234abcd;")). */
MD_SIZE i;
for(i = 3; i < size-1; i++)
codepoint = 16 * codepoint + hex_val(text[i]);
} else {
/* Decimal entity (e.g. "&1234;") */
MD_SIZE i;
for(i = 2; i < size-1; i++)
codepoint = 10 * codepoint + (text[i] - '0');
}
render_utf8_codepoint(r, codepoint, fn_append);
return;
} else {
/* Named entity (e.g. "&nbsp;"). */
const ENTITY* ent;
ent = entity_lookup(text, size);
if(ent != NULL) {
render_utf8_codepoint(r, ent->codepoints[0], fn_append);
if(ent->codepoints[1])
render_utf8_codepoint(r, ent->codepoints[1], fn_append);
return;
}
}
fn_append(r, text, size);
}
static void
render_attribute(MD_HTML* r, const MD_ATTRIBUTE* attr,
void (*fn_append)(MD_HTML*, const MD_CHAR*, MD_SIZE))
{
int i;
for(i = 0; attr->substr_offsets[i] < attr->size; i++) {
MD_TEXTTYPE type = attr->substr_types[i];
MD_OFFSET off = attr->substr_offsets[i];
MD_SIZE size = attr->substr_offsets[i+1] - off;
const MD_CHAR* text = attr->text + off;
switch(type) {
case MD_TEXT_NULLCHAR: render_utf8_codepoint(r, 0x0000, render_verbatim); break;
case MD_TEXT_ENTITY: render_entity(r, text, size, fn_append); break;
default: fn_append(r, text, size); break;
}
}
}
static void
render_open_ol_block(MD_HTML* r, const MD_BLOCK_OL_DETAIL* det)
{
char buf[64];
if(det->start == 1) {
RENDER_VERBATIM(r, "<ol>\n");
return;
}
snprintf(buf, sizeof(buf), "<ol start=\"%u\">\n", det->start);
RENDER_VERBATIM(r, buf);
}
static void
render_open_li_block(MD_HTML* r, const MD_BLOCK_LI_DETAIL* det)
{
if(det->is_task) {
RENDER_VERBATIM(r, "<li class=\"task-list-item\">"
"<input type=\"checkbox\" class=\"task-list-item-checkbox\" disabled");
if(det->task_mark == 'x' || det->task_mark == 'X')
RENDER_VERBATIM(r, " checked");
RENDER_VERBATIM(r, ">");
} else {
RENDER_VERBATIM(r, "<li>");
}
}
static void
render_open_code_block(MD_HTML* r, const MD_BLOCK_CODE_DETAIL* det)
{
RENDER_VERBATIM(r, "<pre><code");
/* If known, output the HTML 5 attribute class="language-LANGNAME". */
if(det->lang.text != NULL) {
RENDER_VERBATIM(r, " class=\"language-");
render_attribute(r, &det->lang, render_html_escaped);
RENDER_VERBATIM(r, "\"");
}
RENDER_VERBATIM(r, ">");
}
static void
render_open_td_block(MD_HTML* r, const MD_CHAR* cell_type, const MD_BLOCK_TD_DETAIL* det)
{
RENDER_VERBATIM(r, "<");
RENDER_VERBATIM(r, cell_type);
switch(det->align) {
case MD_ALIGN_LEFT: RENDER_VERBATIM(r, " align=\"left\">"); break;
case MD_ALIGN_CENTER: RENDER_VERBATIM(r, " align=\"center\">"); break;
case MD_ALIGN_RIGHT: RENDER_VERBATIM(r, " align=\"right\">"); break;
default: RENDER_VERBATIM(r, ">"); break;
}
}
static void
render_open_a_span(MD_HTML* r, const MD_SPAN_A_DETAIL* det)
{
RENDER_VERBATIM(r, "<a href=\"");
render_attribute(r, &det->href, render_url_escaped);
if(det->title.text != NULL) {
RENDER_VERBATIM(r, "\" title=\"");
render_attribute(r, &det->title, render_html_escaped);
}
RENDER_VERBATIM(r, "\">");
}
static void
render_open_img_span(MD_HTML* r, const MD_SPAN_IMG_DETAIL* det)
{
RENDER_VERBATIM(r, "<img src=\"");
render_attribute(r, &det->src, render_url_escaped);
RENDER_VERBATIM(r, "\" alt=\"");
}
static void
render_close_img_span(MD_HTML* r, const MD_SPAN_IMG_DETAIL* det)
{
if(det->title.text != NULL) {
RENDER_VERBATIM(r, "\" title=\"");
render_attribute(r, &det->title, render_html_escaped);
}
RENDER_VERBATIM(r, (r->flags & MD_HTML_FLAG_XHTML) ? "\" />" : "\">");
}
static void
render_open_wikilink_span(MD_HTML* r, const MD_SPAN_WIKILINK_DETAIL* det)
{
RENDER_VERBATIM(r, "<x-wikilink data-target=\"");
render_attribute(r, &det->target, render_html_escaped);
RENDER_VERBATIM(r, "\">");
}
/**************************************
*** HTML renderer implementation ***
**************************************/
static int
enter_block_callback(MD_BLOCKTYPE type, void* detail, void* userdata)
{
static const MD_CHAR* head[6] = { "<h1>", "<h2>", "<h3>", "<h4>", "<h5>", "<h6>" };
MD_HTML* r = (MD_HTML*) userdata;
switch(type) {
case MD_BLOCK_DOC: /* noop */ break;
case MD_BLOCK_QUOTE: RENDER_VERBATIM(r, "<blockquote>\n"); break;
case MD_BLOCK_UL: RENDER_VERBATIM(r, "<ul>\n"); break;
case MD_BLOCK_OL: render_open_ol_block(r, (const MD_BLOCK_OL_DETAIL*)detail); break;
case MD_BLOCK_LI: render_open_li_block(r, (const MD_BLOCK_LI_DETAIL*)detail); break;
case MD_BLOCK_HR: RENDER_VERBATIM(r, (r->flags & MD_HTML_FLAG_XHTML) ? "<hr />\n" : "<hr>\n"); break;
case MD_BLOCK_H: RENDER_VERBATIM(r, head[((MD_BLOCK_H_DETAIL*)detail)->level - 1]); break;
case MD_BLOCK_CODE: render_open_code_block(r, (const MD_BLOCK_CODE_DETAIL*) detail); break;
case MD_BLOCK_HTML: /* noop */ break;
case MD_BLOCK_P: RENDER_VERBATIM(r, "<p>"); break;
case MD_BLOCK_TABLE: RENDER_VERBATIM(r, "<table>\n"); break;
case MD_BLOCK_THEAD: RENDER_VERBATIM(r, "<thead>\n"); break;
case MD_BLOCK_TBODY: RENDER_VERBATIM(r, "<tbody>\n"); break;
case MD_BLOCK_TR: RENDER_VERBATIM(r, "<tr>\n"); break;
case MD_BLOCK_TH: render_open_td_block(r, "th", (MD_BLOCK_TD_DETAIL*)detail); break;
case MD_BLOCK_TD: render_open_td_block(r, "td", (MD_BLOCK_TD_DETAIL*)detail); break;
}
return 0;
}
static int
leave_block_callback(MD_BLOCKTYPE type, void* detail, void* userdata)
{
static const MD_CHAR* head[6] = { "</h1>\n", "</h2>\n", "</h3>\n", "</h4>\n", "</h5>\n", "</h6>\n" };
MD_HTML* r = (MD_HTML*) userdata;
switch(type) {
case MD_BLOCK_DOC: /*noop*/ break;
case MD_BLOCK_QUOTE: RENDER_VERBATIM(r, "</blockquote>\n"); break;
case MD_BLOCK_UL: RENDER_VERBATIM(r, "</ul>\n"); break;
case MD_BLOCK_OL: RENDER_VERBATIM(r, "</ol>\n"); break;
case MD_BLOCK_LI: RENDER_VERBATIM(r, "</li>\n"); break;
case MD_BLOCK_HR: /*noop*/ break;
case MD_BLOCK_H: RENDER_VERBATIM(r, head[((MD_BLOCK_H_DETAIL*)detail)->level - 1]); break;
case MD_BLOCK_CODE: RENDER_VERBATIM(r, "</code></pre>\n"); break;
case MD_BLOCK_HTML: /* noop */ break;
case MD_BLOCK_P: RENDER_VERBATIM(r, "</p>\n"); break;
case MD_BLOCK_TABLE: RENDER_VERBATIM(r, "</table>\n"); break;
case MD_BLOCK_THEAD: RENDER_VERBATIM(r, "</thead>\n"); break;
case MD_BLOCK_TBODY: RENDER_VERBATIM(r, "</tbody>\n"); break;
case MD_BLOCK_TR: RENDER_VERBATIM(r, "</tr>\n"); break;
case MD_BLOCK_TH: RENDER_VERBATIM(r, "</th>\n"); break;
case MD_BLOCK_TD: RENDER_VERBATIM(r, "</td>\n"); break;
}
return 0;
}
static int
enter_span_callback(MD_SPANTYPE type, void* detail, void* userdata)
{
MD_HTML* r = (MD_HTML*) userdata;
int inside_img = (r->image_nesting_level > 0);
/* We are inside a Markdown image label. Markdown allows to use any emphasis
* and other rich contents in that context similarly as in any link label.
*
* However, unlike in the case of links (where that contents becomescontents
* of the <a>...</a> tag), in the case of images the contents is supposed to
* fall into the attribute alt: <img alt="...">.
*
* In that context we naturally cannot output nested HTML tags. So lets
* suppress them and only output the plain text (i.e. what falls into text()
* callback).
*
* CommonMark specification declares this a recommended practice for HTML
* output.
*/
if(type == MD_SPAN_IMG)
r->image_nesting_level++;
if(inside_img)
return 0;
switch(type) {
case MD_SPAN_EM: RENDER_VERBATIM(r, "<em>"); break;
case MD_SPAN_STRONG: RENDER_VERBATIM(r, "<strong>"); break;
case MD_SPAN_U: RENDER_VERBATIM(r, "<u>"); break;
case MD_SPAN_A: render_open_a_span(r, (MD_SPAN_A_DETAIL*) detail); break;
case MD_SPAN_IMG: render_open_img_span(r, (MD_SPAN_IMG_DETAIL*) detail); break;
case MD_SPAN_CODE: RENDER_VERBATIM(r, "<code>"); break;
case MD_SPAN_DEL: RENDER_VERBATIM(r, "<del>"); break;
case MD_SPAN_LATEXMATH: RENDER_VERBATIM(r, "<x-equation>"); break;
case MD_SPAN_LATEXMATH_DISPLAY: RENDER_VERBATIM(r, "<x-equation type=\"display\">"); break;
case MD_SPAN_WIKILINK: render_open_wikilink_span(r, (MD_SPAN_WIKILINK_DETAIL*) detail); break;
}
return 0;
}
static int
leave_span_callback(MD_SPANTYPE type, void* detail, void* userdata)
{
MD_HTML* r = (MD_HTML*) userdata;
if(type == MD_SPAN_IMG)
r->image_nesting_level--;
if(r->image_nesting_level > 0)
return 0;
switch(type) {
case MD_SPAN_EM: RENDER_VERBATIM(r, "</em>"); break;
case MD_SPAN_STRONG: RENDER_VERBATIM(r, "</strong>"); break;
case MD_SPAN_U: RENDER_VERBATIM(r, "</u>"); break;
case MD_SPAN_A: RENDER_VERBATIM(r, "</a>"); break;
case MD_SPAN_IMG: render_close_img_span(r, (MD_SPAN_IMG_DETAIL*) detail); break;
case MD_SPAN_CODE: RENDER_VERBATIM(r, "</code>"); break;
case MD_SPAN_DEL: RENDER_VERBATIM(r, "</del>"); break;
case MD_SPAN_LATEXMATH: /*fall through*/
case MD_SPAN_LATEXMATH_DISPLAY: RENDER_VERBATIM(r, "</x-equation>"); break;
case MD_SPAN_WIKILINK: RENDER_VERBATIM(r, "</x-wikilink>"); break;
}
return 0;
}
static int
text_callback(MD_TEXTTYPE type, const MD_CHAR* text, MD_SIZE size, void* userdata)
{
MD_HTML* r = (MD_HTML*) userdata;
switch(type) {
case MD_TEXT_NULLCHAR: render_utf8_codepoint(r, 0x0000, render_verbatim); break;
case MD_TEXT_BR: RENDER_VERBATIM(r, (r->image_nesting_level == 0
? ((r->flags & MD_HTML_FLAG_XHTML) ? "<br />\n" : "<br>\n")
: " "));
break;
case MD_TEXT_SOFTBR: RENDER_VERBATIM(r, (r->image_nesting_level == 0 ? "\n" : " ")); break;
case MD_TEXT_HTML: render_verbatim(r, text, size); break;
case MD_TEXT_ENTITY: render_entity(r, text, size, render_html_escaped); break;
default: render_html_escaped(r, text, size); break;
}
return 0;
}
static void
debug_log_callback(const char* msg, void* userdata)
{
MD_HTML* r = (MD_HTML*) userdata;
if(r->flags & MD_HTML_FLAG_DEBUG)
fprintf(stderr, "MD4C: %s\n", msg);
}
int
md_html(const MD_CHAR* input, MD_SIZE input_size,
void (*process_output)(const MD_CHAR*, MD_SIZE, void*),
void* userdata, unsigned parser_flags, unsigned renderer_flags)
{
MD_HTML render = { process_output, userdata, renderer_flags, 0, { 0 } };
int i;
MD_PARSER parser = {
0,
parser_flags,
enter_block_callback,
leave_block_callback,
enter_span_callback,
leave_span_callback,
text_callback,
debug_log_callback,
NULL
};
/* Build map of characters which need escaping. */
for(i = 0; i < 256; i++) {
unsigned char ch = (unsigned char) i;
if(strchr("\"&<>", ch) != NULL)
render.escape_map[i] |= NEED_HTML_ESC_FLAG;
if(!ISALNUM(ch) && strchr("~-_.+!*(),%#@?=;:/,+$", ch) == NULL)
render.escape_map[i] |= NEED_URL_ESC_FLAG;
}
/* Consider skipping UTF-8 byte order mark (BOM). */
if(renderer_flags & MD_HTML_FLAG_SKIP_UTF8_BOM && sizeof(MD_CHAR) == 1) {
static const MD_CHAR bom[3] = { (char)0xef, (char)0xbb, (char)0xbf };
if(input_size >= sizeof(bom) && memcmp(input, bom, sizeof(bom)) == 0) {
input += sizeof(bom);
input_size -= sizeof(bom);
}
}
return md_parse(input, input_size, &parser, (void*) &render);
}

View File

@@ -1,68 +0,0 @@
/*
* MD4C: Markdown parser for C
* (http://github.com/mity/md4c)
*
* Copyright (c) 2016-2024 Martin Mitáš
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
#ifndef MD4C_HTML_H
#define MD4C_HTML_H
#include "md4c.h"
#ifdef __cplusplus
extern "C" {
#endif
/* If set, debug output from md_parse() is sent to stderr. */
#define MD_HTML_FLAG_DEBUG 0x0001
#define MD_HTML_FLAG_VERBATIM_ENTITIES 0x0002
#define MD_HTML_FLAG_SKIP_UTF8_BOM 0x0004
#define MD_HTML_FLAG_XHTML 0x0008
/* Render Markdown into HTML.
*
* Note only contents of <body> tag is generated. Caller must generate
* HTML header/footer manually before/after calling md_html().
*
* Params input and input_size specify the Markdown input.
* Callback process_output() gets called with chunks of HTML output.
* (Typical implementation may just output the bytes to a file or append to
* some buffer).
* Param userdata is just propagated back to process_output() callback.
* Param parser_flags are flags from md4c.h propagated to md_parse().
* Param render_flags is bitmask of MD_HTML_FLAG_xxxx.
*
* Returns -1 on error (if md_parse() fails.)
* Returns 0 on success.
*/
int md_html(const MD_CHAR* input, MD_SIZE input_size,
void (*process_output)(const MD_CHAR*, MD_SIZE, void*),
void* userdata, unsigned parser_flags, unsigned renderer_flags);
#ifdef __cplusplus
} /* extern "C" { */
#endif
#endif /* MD4C_HTML_H */

View File

@@ -1,13 +0,0 @@
prefix=@CMAKE_INSTALL_PREFIX@
exec_prefix=@CMAKE_INSTALL_PREFIX@
libdir=${exec_prefix}/@CMAKE_INSTALL_LIBDIR@
includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@
Name: @PROJECT_NAME@ HTML renderer
Description: Markdown to HTML converter library.
Version: @PROJECT_VERSION@
URL: @PROJECT_URL@
Requires: md4c = @PROJECT_VERSION@
Libs: -L${libdir} -lmd4c-html
Cflags: -I${includedir}

File diff suppressed because it is too large Load Diff

View File

@@ -1,407 +0,0 @@
/*
* MD4C: Markdown parser for C
* (http://github.com/mity/md4c)
*
* Copyright (c) 2016-2024 Martin Mitáš
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
#ifndef MD4C_H
#define MD4C_H
#ifdef __cplusplus
extern "C" {
#endif
#if defined MD4C_USE_UTF16
/* Magic to support UTF-16. Note that in order to use it, you have to define
* the macro MD4C_USE_UTF16 both when building MD4C as well as when
* including this header in your code. */
#ifdef _WIN32
#include <windows.h>
typedef WCHAR MD_CHAR;
#else
#error MD4C_USE_UTF16 is only supported on Windows.
#endif
#else
typedef char MD_CHAR;
#endif
typedef unsigned MD_SIZE;
typedef unsigned MD_OFFSET;
/* Block represents a part of document hierarchy structure like a paragraph
* or list item.
*/
typedef enum MD_BLOCKTYPE {
/* <body>...</body> */
MD_BLOCK_DOC = 0,
/* <blockquote>...</blockquote> */
MD_BLOCK_QUOTE,
/* <ul>...</ul>
* Detail: Structure MD_BLOCK_UL_DETAIL. */
MD_BLOCK_UL,
/* <ol>...</ol>
* Detail: Structure MD_BLOCK_OL_DETAIL. */
MD_BLOCK_OL,
/* <li>...</li>
* Detail: Structure MD_BLOCK_LI_DETAIL. */
MD_BLOCK_LI,
/* <hr> */
MD_BLOCK_HR,
/* <h1>...</h1> (for levels up to 6)
* Detail: Structure MD_BLOCK_H_DETAIL. */
MD_BLOCK_H,
/* <pre><code>...</code></pre>
* Note the text lines within code blocks are terminated with '\n'
* instead of explicit MD_TEXT_BR. */
MD_BLOCK_CODE,
/* Raw HTML block. This itself does not correspond to any particular HTML
* tag. The contents of it _is_ raw HTML source intended to be put
* in verbatim form to the HTML output. */
MD_BLOCK_HTML,
/* <p>...</p> */
MD_BLOCK_P,
/* <table>...</table> and its contents.
* Detail: Structure MD_BLOCK_TABLE_DETAIL (for MD_BLOCK_TABLE),
* structure MD_BLOCK_TD_DETAIL (for MD_BLOCK_TH and MD_BLOCK_TD)
* Note all of these are used only if extension MD_FLAG_TABLES is enabled. */
MD_BLOCK_TABLE,
MD_BLOCK_THEAD,
MD_BLOCK_TBODY,
MD_BLOCK_TR,
MD_BLOCK_TH,
MD_BLOCK_TD
} MD_BLOCKTYPE;
/* Span represents an in-line piece of a document which should be rendered with
* the same font, color and other attributes. A sequence of spans forms a block
* like paragraph or list item. */
typedef enum MD_SPANTYPE {
/* <em>...</em> */
MD_SPAN_EM,
/* <strong>...</strong> */
MD_SPAN_STRONG,
/* <a href="xxx">...</a>
* Detail: Structure MD_SPAN_A_DETAIL. */
MD_SPAN_A,
/* <img src="xxx">...</a>
* Detail: Structure MD_SPAN_IMG_DETAIL.
* Note: Image text can contain nested spans and even nested images.
* If rendered into ALT attribute of HTML <IMG> tag, it's responsibility
* of the parser to deal with it.
*/
MD_SPAN_IMG,
/* <code>...</code> */
MD_SPAN_CODE,
/* <del>...</del>
* Note: Recognized only when MD_FLAG_STRIKETHROUGH is enabled.
*/
MD_SPAN_DEL,
/* For recognizing inline ($) and display ($$) equations
* Note: Recognized only when MD_FLAG_LATEXMATHSPANS is enabled.
*/
MD_SPAN_LATEXMATH,
MD_SPAN_LATEXMATH_DISPLAY,
/* Wiki links
* Note: Recognized only when MD_FLAG_WIKILINKS is enabled.
*/
MD_SPAN_WIKILINK,
/* <u>...</u>
* Note: Recognized only when MD_FLAG_UNDERLINE is enabled. */
MD_SPAN_U
} MD_SPANTYPE;
/* Text is the actual textual contents of span. */
typedef enum MD_TEXTTYPE {
/* Normal text. */
MD_TEXT_NORMAL = 0,
/* NULL character. CommonMark requires replacing NULL character with
* the replacement char U+FFFD, so this allows caller to do that easily. */
MD_TEXT_NULLCHAR,
/* Line breaks.
* Note these are not sent from blocks with verbatim output (MD_BLOCK_CODE
* or MD_BLOCK_HTML). In such cases, '\n' is part of the text itself. */
MD_TEXT_BR, /* <br> (hard break) */
MD_TEXT_SOFTBR, /* '\n' in source text where it is not semantically meaningful (soft break) */
/* Entity.
* (a) Named entity, e.g. &nbsp;
* (Note MD4C does not have a list of known entities.
* Anything matching the regexp /&[A-Za-z][A-Za-z0-9]{1,47};/ is
* treated as a named entity.)
* (b) Numerical entity, e.g. &#1234;
* (c) Hexadecimal entity, e.g. &#x12AB;
*
* As MD4C is mostly encoding agnostic, application gets the verbatim
* entity text into the MD_PARSER::text_callback(). */
MD_TEXT_ENTITY,
/* Text in a code block (inside MD_BLOCK_CODE) or inlined code (`code`).
* If it is inside MD_BLOCK_CODE, it includes spaces for indentation and
* '\n' for new lines. MD_TEXT_BR and MD_TEXT_SOFTBR are not sent for this
* kind of text. */
MD_TEXT_CODE,
/* Text is a raw HTML. If it is contents of a raw HTML block (i.e. not
* an inline raw HTML), then MD_TEXT_BR and MD_TEXT_SOFTBR are not used.
* The text contains verbatim '\n' for the new lines. */
MD_TEXT_HTML,
/* Text is inside an equation. This is processed the same way as inlined code
* spans (`code`). */
MD_TEXT_LATEXMATH
} MD_TEXTTYPE;
/* Alignment enumeration. */
typedef enum MD_ALIGN {
MD_ALIGN_DEFAULT = 0, /* When unspecified. */
MD_ALIGN_LEFT,
MD_ALIGN_CENTER,
MD_ALIGN_RIGHT
} MD_ALIGN;
/* String attribute.
*
* This wraps strings which are outside of a normal text flow and which are
* propagated within various detailed structures, but which still may contain
* string portions of different types like e.g. entities.
*
* So, for example, lets consider this image:
*
* ![image alt text](http://example.org/image.png 'foo &quot; bar')
*
* The image alt text is propagated as a normal text via the MD_PARSER::text()
* callback. However, the image title ('foo &quot; bar') is propagated as
* MD_ATTRIBUTE in MD_SPAN_IMG_DETAIL::title.
*
* Then the attribute MD_SPAN_IMG_DETAIL::title shall provide the following:
* -- [0]: "foo " (substr_types[0] == MD_TEXT_NORMAL; substr_offsets[0] == 0)
* -- [1]: "&quot;" (substr_types[1] == MD_TEXT_ENTITY; substr_offsets[1] == 4)
* -- [2]: " bar" (substr_types[2] == MD_TEXT_NORMAL; substr_offsets[2] == 10)
* -- [3]: (n/a) (n/a ; substr_offsets[3] == 14)
*
* Note that these invariants are always guaranteed:
* -- substr_offsets[0] == 0
* -- substr_offsets[LAST+1] == size
* -- Currently, only MD_TEXT_NORMAL, MD_TEXT_ENTITY, MD_TEXT_NULLCHAR
* substrings can appear. This could change only of the specification
* changes.
*/
typedef struct MD_ATTRIBUTE {
const MD_CHAR* text;
MD_SIZE size;
const MD_TEXTTYPE* substr_types;
const MD_OFFSET* substr_offsets;
} MD_ATTRIBUTE;
/* Detailed info for MD_BLOCK_UL. */
typedef struct MD_BLOCK_UL_DETAIL {
int is_tight; /* Non-zero if tight list, zero if loose. */
MD_CHAR mark; /* Item bullet character in MarkDown source of the list, e.g. '-', '+', '*'. */
} MD_BLOCK_UL_DETAIL;
/* Detailed info for MD_BLOCK_OL. */
typedef struct MD_BLOCK_OL_DETAIL {
unsigned start; /* Start index of the ordered list. */
int is_tight; /* Non-zero if tight list, zero if loose. */
MD_CHAR mark_delimiter; /* Character delimiting the item marks in MarkDown source, e.g. '.' or ')' */
} MD_BLOCK_OL_DETAIL;
/* Detailed info for MD_BLOCK_LI. */
typedef struct MD_BLOCK_LI_DETAIL {
int is_task; /* Can be non-zero only with MD_FLAG_TASKLISTS */
MD_CHAR task_mark; /* If is_task, then one of 'x', 'X' or ' '. Undefined otherwise. */
MD_OFFSET task_mark_offset; /* If is_task, then offset in the input of the char between '[' and ']'. */
} MD_BLOCK_LI_DETAIL;
/* Detailed info for MD_BLOCK_H. */
typedef struct MD_BLOCK_H_DETAIL {
unsigned level; /* Header level (1 - 6) */
} MD_BLOCK_H_DETAIL;
/* Detailed info for MD_BLOCK_CODE. */
typedef struct MD_BLOCK_CODE_DETAIL {
MD_ATTRIBUTE info;
MD_ATTRIBUTE lang;
MD_CHAR fence_char; /* The character used for fenced code block; or zero for indented code block. */
} MD_BLOCK_CODE_DETAIL;
/* Detailed info for MD_BLOCK_TABLE. */
typedef struct MD_BLOCK_TABLE_DETAIL {
unsigned col_count; /* Count of columns in the table. */
unsigned head_row_count; /* Count of rows in the table header (currently always 1) */
unsigned body_row_count; /* Count of rows in the table body */
} MD_BLOCK_TABLE_DETAIL;
/* Detailed info for MD_BLOCK_TH and MD_BLOCK_TD. */
typedef struct MD_BLOCK_TD_DETAIL {
MD_ALIGN align;
} MD_BLOCK_TD_DETAIL;
/* Detailed info for MD_SPAN_A. */
typedef struct MD_SPAN_A_DETAIL {
MD_ATTRIBUTE href;
MD_ATTRIBUTE title;
int is_autolink; /* nonzero if this is an autolink */
} MD_SPAN_A_DETAIL;
/* Detailed info for MD_SPAN_IMG. */
typedef struct MD_SPAN_IMG_DETAIL {
MD_ATTRIBUTE src;
MD_ATTRIBUTE title;
} MD_SPAN_IMG_DETAIL;
/* Detailed info for MD_SPAN_WIKILINK. */
typedef struct MD_SPAN_WIKILINK {
MD_ATTRIBUTE target;
} MD_SPAN_WIKILINK_DETAIL;
/* Flags specifying extensions/deviations from CommonMark specification.
*
* By default (when MD_PARSER::flags == 0), we follow CommonMark specification.
* The following flags may allow some extensions or deviations from it.
*/
#define MD_FLAG_COLLAPSEWHITESPACE 0x0001 /* In MD_TEXT_NORMAL, collapse non-trivial whitespace into single ' ' */
#define MD_FLAG_PERMISSIVEATXHEADERS 0x0002 /* Do not require space in ATX headers ( ###header ) */
#define MD_FLAG_PERMISSIVEURLAUTOLINKS 0x0004 /* Recognize URLs as autolinks even without '<', '>' */
#define MD_FLAG_PERMISSIVEEMAILAUTOLINKS 0x0008 /* Recognize e-mails as autolinks even without '<', '>' and 'mailto:' */
#define MD_FLAG_NOINDENTEDCODEBLOCKS 0x0010 /* Disable indented code blocks. (Only fenced code works.) */
#define MD_FLAG_NOHTMLBLOCKS 0x0020 /* Disable raw HTML blocks. */
#define MD_FLAG_NOHTMLSPANS 0x0040 /* Disable raw HTML (inline). */
#define MD_FLAG_TABLES 0x0100 /* Enable tables extension. */
#define MD_FLAG_STRIKETHROUGH 0x0200 /* Enable strikethrough extension. */
#define MD_FLAG_PERMISSIVEWWWAUTOLINKS 0x0400 /* Enable WWW autolinks (even without any scheme prefix, if they begin with 'www.') */
#define MD_FLAG_TASKLISTS 0x0800 /* Enable task list extension. */
#define MD_FLAG_LATEXMATHSPANS 0x1000 /* Enable $ and $$ containing LaTeX equations. */
#define MD_FLAG_WIKILINKS 0x2000 /* Enable wiki links extension. */
#define MD_FLAG_UNDERLINE 0x4000 /* Enable underline extension (and disables '_' for normal emphasis). */
#define MD_FLAG_HARD_SOFT_BREAKS 0x8000 /* Force all soft breaks to act as hard breaks. */
#define MD_FLAG_PERMISSIVEAUTOLINKS (MD_FLAG_PERMISSIVEEMAILAUTOLINKS | MD_FLAG_PERMISSIVEURLAUTOLINKS | MD_FLAG_PERMISSIVEWWWAUTOLINKS)
#define MD_FLAG_NOHTML (MD_FLAG_NOHTMLBLOCKS | MD_FLAG_NOHTMLSPANS)
/* Convenient sets of flags corresponding to well-known Markdown dialects.
*
* Note we may only support subset of features of the referred dialect.
* The constant just enables those extensions which bring us as close as
* possible given what features we implement.
*
* ABI compatibility note: Meaning of these can change in time as new
* extensions, bringing the dialect closer to the original, are implemented.
*/
#define MD_DIALECT_COMMONMARK 0
#define MD_DIALECT_GITHUB (MD_FLAG_PERMISSIVEAUTOLINKS | MD_FLAG_TABLES | MD_FLAG_STRIKETHROUGH | MD_FLAG_TASKLISTS)
/* Parser structure.
*/
typedef struct MD_PARSER {
/* Reserved. Set to zero.
*/
unsigned abi_version;
/* Dialect options. Bitmask of MD_FLAG_xxxx values.
*/
unsigned flags;
/* Caller-provided rendering callbacks.
*
* For some block/span types, more detailed information is provided in a
* type-specific structure pointed by the argument 'detail'.
*
* The last argument of all callbacks, 'userdata', is just propagated from
* md_parse() and is available for any use by the application.
*
* Note any strings provided to the callbacks as their arguments or as
* members of any detail structure are generally not zero-terminated.
* Application has to take the respective size information into account.
*
* Any rendering callback may abort further parsing of the document by
* returning non-zero.
*/
int (*enter_block)(MD_BLOCKTYPE /*type*/, void* /*detail*/, void* /*userdata*/);
int (*leave_block)(MD_BLOCKTYPE /*type*/, void* /*detail*/, void* /*userdata*/);
int (*enter_span)(MD_SPANTYPE /*type*/, void* /*detail*/, void* /*userdata*/);
int (*leave_span)(MD_SPANTYPE /*type*/, void* /*detail*/, void* /*userdata*/);
int (*text)(MD_TEXTTYPE /*type*/, const MD_CHAR* /*text*/, MD_SIZE /*size*/, void* /*userdata*/);
/* Debug callback. Optional (may be NULL).
*
* If provided and something goes wrong, this function gets called.
* This is intended for debugging and problem diagnosis for developers;
* it is not intended to provide any errors suitable for displaying to an
* end user.
*/
void (*debug_log)(const char* /*msg*/, void* /*userdata*/);
/* Reserved. Set to NULL.
*/
void (*syntax)(void);
} MD_PARSER;
/* For backward compatibility. Do not use in new code.
*/
typedef MD_PARSER MD_RENDERER;
/* Parse the Markdown document stored in the string 'text' of size 'size'.
* The parser provides callbacks to be called during the parsing so the
* caller can render the document on the screen or convert the Markdown
* to another format.
*
* Zero is returned on success. If a runtime error occurs (e.g. a memory
* fails), -1 is returned. If the processing is aborted due any callback
* returning non-zero, the return value of the callback is returned.
*/
int md_parse(const MD_CHAR* text, MD_SIZE size, const MD_PARSER* parser, void* userdata);
#ifdef __cplusplus
} /* extern "C" { */
#endif
#endif /* MD4C_H */

View File

@@ -1,13 +0,0 @@
prefix=@CMAKE_INSTALL_PREFIX@
exec_prefix=@CMAKE_INSTALL_PREFIX@
libdir=${exec_prefix}/@CMAKE_INSTALL_LIBDIR@
includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@
Name: @PROJECT_NAME@
Description: Markdown parser library with a SAX-like callback-based interface.
Version: @PROJECT_VERSION@
URL: @PROJECT_URL@
Requires:
Libs: -L${libdir} -lmd4c
Cflags: -I${includedir}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,3 +1,4 @@
src/libslic3r/PresetBundle.cpp
src/slic3r/GUI/DeviceCore/DevBed.cpp
src/slic3r/GUI/DeviceCore/DevBed.h
src/slic3r/GUI/DeviceCore/DevConfig.h
@@ -67,7 +68,6 @@ src/slic3r/GUI/Gizmos/GLGizmoText.hpp
src/slic3r/GUI/Gizmos/GLGizmoEmboss.cpp
src/slic3r/GUI/Gizmos/GLGizmoSVG.cpp
src/slic3r/GUI/Gizmos/GLGizmoMeasure.cpp
src/slic3r/GUI/Gizmos/GLGizmoAssembly.cpp
src/slic3r/GUI/GUI.cpp
src/slic3r/GUI/GUI_App.cpp
src/slic3r/GUI/GUI_AuxiliaryList.cpp
@@ -81,7 +81,6 @@ src/slic3r/GUI/GUI_ObjectTable.hpp
src/slic3r/GUI/GUI_ObjectTableSettings.cpp
src/slic3r/GUI/GUI_ObjectTableSettings.hpp
src/slic3r/GUI/GUI_Preview.cpp
src/slic3r/GUI/2DBed.cpp
src/slic3r/GUI/HintNotification.cpp
src/slic3r/GUI/IMSlider.cpp
src/slic3r/GUI/Widgets/SideTools.cpp
@@ -97,7 +96,6 @@ src/slic3r/GUI/Jobs/RotoptimizeJob.cpp
src/slic3r/GUI/Jobs/BindJob.cpp
src/slic3r/GUI/Jobs/PrintJob.cpp
src/slic3r/GUI/Jobs/SendJob.cpp
src/slic3r/GUI/Jobs/EmbossJob.cpp
src/slic3r/GUI/ThermalPreconditioningDialog.cpp
src/slic3r/GUI/ThermalPreconditioningDialog.hpp
src/slic3r/GUI/Jobs/SLAImportJob.cpp
@@ -167,6 +165,7 @@ src/slic3r/GUI/Tab.hpp
src/slic3r/GUI/UnsavedChangesDialog.cpp
src/slic3r/GUI/Auxiliary.cpp
src/slic3r/GUI/UpdateDialogs.cpp
src/slic3r/GUI/UnsavedChangesDialog.cpp
src/slic3r/GUI/ObjColorDialog.cpp
src/slic3r/GUI/SyncAmsInfoDialog.cpp
src/slic3r/GUI/WipeTowerDialog.cpp
@@ -179,10 +178,12 @@ src/slic3r/GUI/KBShortcutsDialog.cpp
src/slic3r/GUI/ReleaseNote.cpp
src/slic3r/GUI/ReleaseNote.hpp
src/slic3r/GUI/UpgradePanel.cpp
src/slic3r/GUI/UnsavedChangesDialog.cpp
src/slic3r/Utils/FixModelByWin10.cpp
src/slic3r/Utils/PresetUpdater.cpp
src/slic3r/Utils/Http.cpp
src/slic3r/Utils/Process.cpp
src/slic3r/GUI/Jobs/PrintJob.cpp
src/libslic3r/GCode.cpp
src/libslic3r/GCode/ToolOrdering.cpp
src/libslic3r/ExtrusionEntity.cpp
@@ -236,6 +237,7 @@ src/slic3r/Utils/Obico.cpp
src/slic3r/Utils/SimplyPrint.cpp
src/slic3r/Utils/Flashforge.cpp
src/slic3r/GUI/Jobs/OAuthJob.cpp
src/slic3r/GUI/BackgroundSlicingProcess.cpp
src/slic3r/GUI/Gizmos/GLGizmoBrimEars.cpp
src/slic3r/GUI/PartSkipDialog.cpp
src/slic3r/GUI/PartSkipDialog.hpp
@@ -244,8 +246,4 @@ src/slic3r/GUI/SkipPartCanvas.hpp
src/slic3r/GUI/FilamentBitmapUtils.cpp
src/slic3r/GUI/FilamentBitmapUtils.hpp
src/slic3r/GUI/FilamentPickerDialog.cpp
src/slic3r/GUI/NetworkPluginDialog.cpp
src/slic3r/GUI/RammingChart.cpp
src/slic3r/GUI/StepMeshDialog.cpp
src/slic3r/GUI/FilamentPickerDialog.hpp
src/libslic3r/PresetBundle.cpp

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
resources/calib/vfa/VFA.stl Normal file

Binary file not shown.

Binary file not shown.

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

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