build: use clang-cl for Windows CI builds (faster slicing and faster builds) (#15428)

* ci: build the Windows x64 dependencies and slicer with clang-cl

Passes -l -x from the Windows jobs, using the clang-cl and Ninja options
added in #15373. Ninja runs each dependency's build step as a plain command,
so the jobs set up a VC environment for OpenSSL's nmake. arm64 stays on MSVC
for now.

The deps cache key gains the compiler, so windows-x64 becomes
windows-x64-clang and windows-arm64 becomes windows-arm64-msvc.

* deps: select OpenSSL's ARM64 target from DEPS_ARCH

CMAKE_GENERATOR_PLATFORM is only set by -A, which Ninja never receives, so
the Ninja build selected the x64 target on ARM64. DEPS_ARCH is derived from
CMAKE_SYSTEM_PROCESSOR and is already independent of the generator.

* ci: build the Windows ARM64 dependencies and slicer with clang-cl

Three dependencies need handling first. libpng and OpenCV each build an ARM
SIMD path that does not compile with clang-cl, so those paths are off; PNG
already had the same opt-out for Apple ARM. OCCT is built with cl, since
clang-cl cannot emit one of its large generated files and there is no option
to turn that off. All three are gated to Windows ARM64 with clang.
This commit is contained in:
Kris Austin
2026-09-01 08:30:45 -05:00
committed by GitHub
parent 9933cab59f
commit 7eaff76cec
8 changed files with 67 additions and 10 deletions

View File

@@ -81,14 +81,15 @@ jobs:
# SELF_HOSTED skips arm64 (the self-hosted Windows server is x64-only). # SELF_HOSTED skips arm64 (the self-hosted Windows server is x64-only).
matrix: matrix:
include: ${{ fromJSON(vars.SELF_HOSTED include: ${{ fromJSON(vars.SELF_HOSTED
&& '[{"arch":"x64","os":"orca-win-server"}]' && '[{"arch":"x64","os":"orca-win-server","compiler":"clang"}]'
|| '[{"arch":"x64","os":"windows-latest"},{"arch":"arm64","os":"windows-11-arm"}]') }} || '[{"arch":"x64","os":"windows-latest","compiler":"clang"},{"arch":"arm64","os":"windows-11-arm","compiler":"clang"}]') }}
# Don't run scheduled builds on forks: # Don't run scheduled builds on forks:
if: ${{ !cancelled() && (github.event_name != 'schedule' || github.repository == 'OrcaSlicer/OrcaSlicer') }} if: ${{ !cancelled() && (github.event_name != 'schedule' || github.repository == 'OrcaSlicer/OrcaSlicer') }}
uses: ./.github/workflows/build_check_cache.yml uses: ./.github/workflows/build_check_cache.yml
with: with:
os: ${{ matrix.os }} os: ${{ matrix.os }}
arch: ${{ matrix.arch }} arch: ${{ matrix.arch }}
compiler: ${{ matrix.compiler }}
build-deps-only: ${{ inputs.build-deps-only || false }} build-deps-only: ${{ inputs.build-deps-only || false }}
force-build: ${{ github.event_name == 'schedule' }} force-build: ${{ github.event_name == 'schedule' }}
secrets: inherit secrets: inherit

View File

@@ -9,6 +9,10 @@ on:
arch: arch:
required: false required: false
type: string type: string
compiler:
required: false
type: string
default: msvc
build-deps-only: build-deps-only:
required: false required: false
type: boolean type: boolean
@@ -33,10 +37,10 @@ jobs:
- name: set outputs - name: set outputs
id: set_outputs id: set_outputs
env: env:
# Keep macOS/Windows cache keys architecture-specific. amd64 Linux passes # Anything that changes how the tree is built belongs in the key, or a job
# no arch (key stays 'linux-clang', preserving the existing cache); # restores one it cannot use. Linux amd64 passes no arch deliberately, so
# aarch64 gets its own 'linux-clang-aarch64' key. # 'linux-clang' keeps the cache it already has.
cache-os: ${{ runner.os == 'macOS' && format('macos-{0}', inputs.arch) || (runner.os == 'Windows' && format('windows-{0}', inputs.arch) || format('linux-clang{0}', inputs.arch && format('-{0}', inputs.arch) || '')) }} cache-os: ${{ runner.os == 'macOS' && format('macos-{0}', inputs.arch) || (runner.os == 'Windows' && format('windows-{0}-{1}', inputs.arch, inputs.compiler) || format('linux-clang{0}', inputs.arch && format('-{0}', inputs.arch) || '')) }}
# ARM64 builds use the build-arm64 tree (see build_release_vs.bat); x64/other use build. # ARM64 builds use the build-arm64 tree (see build_release_vs.bat); x64/other use build.
dep-folder-name: ${{ runner.os == 'macOS' && format('/{0}', inputs.arch) || (runner.os == 'Windows' && inputs.arch == 'arm64') && '-arm64/OrcaSlicer_dep' || '/OrcaSlicer_dep' }} dep-folder-name: ${{ runner.os == 'macOS' && format('/{0}', inputs.arch) || (runner.os == 'Windows' && inputs.arch == 'arm64') && '-arm64/OrcaSlicer_dep' || '/OrcaSlicer_dep' }}
output-cmd: ${{ runner.os == 'Windows' && '$env:GITHUB_OUTPUT' || '"$GITHUB_OUTPUT"'}} output-cmd: ${{ runner.os == 'Windows' && '$env:GITHUB_OUTPUT' || '"$GITHUB_OUTPUT"'}}
@@ -62,6 +66,7 @@ jobs:
valid-cache: ${{ needs.check_cache.outputs.valid-cache == 'true' }} valid-cache: ${{ needs.check_cache.outputs.valid-cache == 'true' }}
os: ${{ inputs.os }} os: ${{ inputs.os }}
arch: ${{ inputs.arch }} arch: ${{ inputs.arch }}
compiler: ${{ inputs.compiler }}
build-deps-only: ${{ inputs.build-deps-only }} build-deps-only: ${{ inputs.build-deps-only }}
force-build: ${{ inputs.force-build }} force-build: ${{ inputs.force-build }}
secrets: inherit secrets: inherit

View File

@@ -16,6 +16,10 @@ on:
arch: arch:
required: false required: false
type: string type: string
compiler:
required: false
type: string
default: msvc
build-deps-only: build-deps-only:
required: false required: false
type: boolean type: boolean
@@ -135,11 +139,22 @@ jobs:
choco install strawberryperl choco install strawberryperl
} }
$arch = "${{ inputs.arch }}" $arch = "${{ inputs.arch }}"
# -l selects clang-cl and -x Ninja; together they build the deps with clang.
$clang = "${{ inputs.compiler }}" -eq "clang"
$flags = if ($clang) { "-l", "-x" } else { @() }
if ($clang) {
# OpenSSL builds with nmake, which needs a VC environment.
$vswhere = "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere.exe"
$vs = & $vswhere -latest -property installationPath
$devArch = if ($arch -eq "arm64") { "arm64" } else { "amd64" }
Import-Module "$vs\Common7\Tools\Microsoft.VisualStudio.DevShell.dll"
Enter-VsDevShell -VsInstallPath $vs -SkipAutomaticLocation -DevCmdArguments "-arch=$devArch"
}
if ($arch -eq "arm64") { if ($arch -eq "arm64") {
.\build_release_vs.bat deps arm64 .\build_release_vs.bat deps arm64 @flags
.\build_release_vs.bat pack arm64 .\build_release_vs.bat pack arm64
} else { } else {
.\build_release_vs.bat deps .\build_release_vs.bat deps @flags
.\build_release_vs.bat pack .\build_release_vs.bat pack
} }
shell: pwsh shell: pwsh
@@ -204,4 +219,5 @@ jobs:
cache-path: ${{ inputs.cache-path }} cache-path: ${{ inputs.cache-path }}
os: ${{ inputs.os }} os: ${{ inputs.os }}
arch: ${{ inputs.arch }} arch: ${{ inputs.arch }}
compiler: ${{ inputs.compiler }}
secrets: inherit secrets: inherit

View File

@@ -13,6 +13,10 @@ on:
arch: arch:
required: false required: false
type: string type: string
compiler:
required: false
type: string
default: msvc
macos-combine-only: macos-combine-only:
required: false required: false
type: boolean type: boolean
@@ -395,7 +399,18 @@ jobs:
# "tests" builds the unit tests too; the unit_tests_windows_* jobs run them. # "tests" builds the unit tests too; the unit_tests_windows_* jobs run them.
run: | run: |
$arch = "${{ inputs.arch }}" $arch = "${{ inputs.arch }}"
if ($arch -eq "arm64") { .\build_release_vs.bat slicer arm64 tests } else { .\build_release_vs.bat slicer tests } # -l selects clang-cl and -x Ninja; together they build the slicer with clang.
$clang = "${{ inputs.compiler }}" -eq "clang"
$flags = if ($clang) { "-l", "-x" } else { @() }
if ($clang) {
# Build against the same VC toolchain and SDK as the dependencies.
$vswhere = "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere.exe"
$vs = & $vswhere -latest -property installationPath
$devArch = if ($arch -eq "arm64") { "arm64" } else { "amd64" }
Import-Module "$vs\Common7\Tools\Microsoft.VisualStudio.DevShell.dll"
Enter-VsDevShell -VsInstallPath $vs -SkipAutomaticLocation -DevCmdArguments "-arch=$devArch"
}
if ($arch -eq "arm64") { .\build_release_vs.bat slicer arm64 @flags tests } else { .\build_release_vs.bat slicer @flags tests }
shell: pwsh shell: pwsh
- name: Build system preset cache (Windows) - name: Build system preset cache (Windows)

View File

@@ -1,3 +1,10 @@
# clang-cl cannot emit IGESAppli_GeneralModule.cxx on ARM64
# (llvm/llvm-project#62081). cl and clang-cl share an ABI.
set(_occt_compiler_args "")
if ("${DEPS_ARCH}" STREQUAL "arm64" AND CMAKE_CXX_COMPILER_ID STREQUAL Clang)
set(_occt_compiler_args -DCMAKE_C_COMPILER:STRING=cl -DCMAKE_CXX_COMPILER:STRING=cl)
endif ()
if(WIN32) if(WIN32)
set(library_build_type "Shared") set(library_build_type "Shared")
else() else()
@@ -31,6 +38,7 @@ orcaslicer_add_cmake_project(OCCT
-DBUILD_MODULE_ModelingAlgorithms=OFF -DBUILD_MODULE_ModelingAlgorithms=OFF
-DBUILD_MODULE_ModelingData=OFF -DBUILD_MODULE_ModelingData=OFF
-DBUILD_MODULE_Visualization=OFF -DBUILD_MODULE_Visualization=OFF
${_occt_compiler_args}
) )
# add_dependencies(dep_OCCT ${FREETYPE_PKG}) # add_dependencies(dep_OCCT ${FREETYPE_PKG})

View File

@@ -10,6 +10,13 @@ else ()
set(_options "") set(_options "")
endif () endif ()
# carotene is OpenCV's ARM NEON HAL. It uses M_PI without _USE_MATH_DEFINES
# and does not compile with clang-cl.
set(_disable_carotene "")
if ("${DEPS_ARCH}" STREQUAL "arm64" AND CMAKE_CXX_COMPILER_ID STREQUAL Clang)
set(_disable_carotene "-DWITH_CAROTENE=OFF")
endif ()
if (IN_GIT_REPO) if (IN_GIT_REPO)
set(OpenCV_DIRECTORY_FLAG --directory ${BINARY_DIR_REL}/dep_OpenCV-prefix/src/dep_OpenCV) set(OpenCV_DIRECTORY_FLAG --directory ${BINARY_DIR_REL}/dep_OpenCV-prefix/src/dep_OpenCV)
endif () endif ()
@@ -83,5 +90,6 @@ orcaslicer_add_cmake_project(OpenCV
-DWITH_PROTOBUF=OFF -DWITH_PROTOBUF=OFF
-DWITH_WIN32UI=OFF -DWITH_WIN32UI=OFF
-DHAVE_WIN32UI=FALSE -DHAVE_WIN32UI=FALSE
${_disable_carotene}
) )

View File

@@ -6,7 +6,7 @@ if(DEFINED OPENSSL_ARCH)
set(_cross_arch ${OPENSSL_ARCH}) set(_cross_arch ${OPENSSL_ARCH})
else() else()
if(WIN32) if(WIN32)
if("${CMAKE_GENERATOR_PLATFORM}" STREQUAL "ARM64") if("${DEPS_ARCH}" STREQUAL "arm64")
set(_cross_arch "VC-WIN64-ARM") set(_cross_arch "VC-WIN64-ARM")
else() else()
set(_cross_arch "VC-WIN64A") set(_cross_arch "VC-WIN64A")

4
deps/PNG/PNG.cmake vendored
View File

@@ -1,6 +1,10 @@
if (APPLE) if (APPLE)
# Only disable NEON extension for Apple ARM builds, leave it enabled for Raspberry PI. # Only disable NEON extension for Apple ARM builds, leave it enabled for Raspberry PI.
set(_disable_neon_extension "-DPNG_ARM_NEON=off") set(_disable_neon_extension "-DPNG_ARM_NEON=off")
elseif ("${DEPS_ARCH}" STREQUAL "arm64" AND CMAKE_CXX_COMPILER_ID STREQUAL Clang)
# libpng's CMake ignores PNG_ARM_NEON on Windows ARM64 and skips the NEON
# sources, but pngpriv.h enables NEON anyway.
set(_disable_neon_extension "-DCMAKE_C_FLAGS=/DWIN32 /D_WINDOWS /DPNG_ARM_NEON_OPT=0")
else () else ()
set(_disable_neon_extension "") set(_disable_neon_extension "")
endif () endif ()