diff --git a/.github/workflows/cmake_build.yml b/.github/workflows/cmake_build.yml new file mode 100644 index 00000000..c9c95a61 --- /dev/null +++ b/.github/workflows/cmake_build.yml @@ -0,0 +1,237 @@ +name: CMake Build + +permissions: + contents: read + +on: + workflow_call: + inputs: + cmake_version: + type: string + description: "CMake version to install and build with" + default: "4.0.3" + linux_x86_64_hash: + type: string + description: "SHA-256 of cmake--linux-x86_64.tar.gz" + default: "585ae9e013107bc8e7c7c9ce872cbdcbdff569e675b07ef57aacfb88c886faac" + linux_aarch64_hash: + type: string + description: "SHA-256 of cmake--linux-aarch64.tar.gz" + default: "391da1544ef50ac31300841caaf11db4de3976cdc4468643272e44b3f4644713" + macos_hash: + type: string + description: "SHA-256 of cmake--macos-universal.tar.gz" + default: "4e85de4daf1c3e82d7dc6b8ba5683972944b466343aeb9c327a742437bb3ce9a" + windows_x86_64_hash: + type: string + description: "SHA-256 of cmake--windows-x86_64.zip" + default: "b59a31dfbfa376a4aaea9ff560ff2b29f78ee5f9fb15447fc71ae7bf9fea9379" + windows_arm64_hash: + type: string + description: "SHA-256 of cmake--windows-arm64.zip" + default: "86ccd6485bbd4bb41a1a858db397be5bca5e0de96858bf8dbba7a64407bd6c00" + enable_linux_checks: + type: boolean + description: "Boolean to enable the Linux build. Defaults to true" + default: true + enable_macos_checks: + type: boolean + description: "Boolean to enable the macOS build (requires self-hosted runners). Defaults to false" + default: false + enable_windows_checks: + type: boolean + description: "Boolean to enable the Windows build. Defaults to true" + default: true + linux_container_image: + type: string + description: "Container image used for the Linux build" + default: "swift:6.2-jammy" + linux_prerequisites_command: + type: string + description: "Linux command to install prerequisites the install-cmake action needs (it shells out to curl)" + default: "apt-get update && apt-get install -y curl" + linux_pre_build_command: + type: string + description: "Linux command to execute before configuring the CMake project" + default: "" + linux_configure_command: + type: string + description: "Linux command to configure the CMake project" + default: "$CMAKE -G Ninja -B build -S ." + linux_build_command: + type: string + description: "Linux command to build the CMake project" + default: "$CMAKE --build build" + macos_pre_build_command: + type: string + description: "macOS command to execute before configuring the CMake project" + default: "" + macos_configure_command: + type: string + description: "macOS command to configure the CMake project" + default: "$CMAKE -G Ninja -B build -S ." + macos_build_command: + type: string + description: "macOS command to build the CMake project" + default: "$CMAKE --build build" + windows_pre_build_command: + type: string + description: | + Windows PowerShell command to execute before configuring the CMake project. + The Invoke-Program helper is available to propagate non-zero exit codes. + default: "" + windows_configure_command: + type: string + description: | + Windows PowerShell command to configure the CMake project. + The Invoke-Program helper is available to propagate non-zero exit codes. + default: "Invoke-Program cmake -G Ninja -B build -S ." + windows_build_command: + type: string + description: | + Windows PowerShell command to build the CMake project. + The Invoke-Program helper is available to propagate non-zero exit codes. + default: "Invoke-Program cmake --build build" + workflow_dispatch: + +jobs: + linux-build: + name: "Linux (${{ matrix.arch }})" + if: ${{ inputs.enable_linux_checks }} + strategy: + fail-fast: false + matrix: + include: + - arch: X64 + runner: ubuntu-24.04 + hash: ${{ inputs.linux_x86_64_hash }} + - arch: ARM64 + runner: ubuntu-24.04-arm + hash: ${{ inputs.linux_aarch64_hash }} + runs-on: ${{ matrix.runner }} + container: + image: ${{ inputs.linux_container_image }} + steps: + - name: Checkout + uses: actions/checkout@v7 + - name: Install prerequisites + shell: bash + env: + PREREQUISITES_COMMAND: ${{ inputs.linux_prerequisites_command }} + run: | + set -euo pipefail + eval "${PREREQUISITES_COMMAND}" + - name: Install CMake + id: install + uses: ./.github/actions/install-cmake + with: + cmake-version: ${{ inputs.cmake_version }} + hash: ${{ matrix.hash }} + - name: Pre-build + if: ${{ inputs.linux_pre_build_command != '' }} + shell: bash + env: + CMAKE: ${{ steps.install.outputs.cmake }} + CTEST: ${{ steps.install.outputs.ctest }} + # zizmor: ignore[template-injection] + run: ${{ inputs.linux_pre_build_command }} + - name: Configure + shell: bash + env: + CMAKE: ${{ steps.install.outputs.cmake }} + CTEST: ${{ steps.install.outputs.ctest }} + # zizmor: ignore[template-injection] + run: ${{ inputs.linux_configure_command }} + - name: Build + shell: bash + env: + CMAKE: ${{ steps.install.outputs.cmake }} + CTEST: ${{ steps.install.outputs.ctest }} + # zizmor: ignore[template-injection] + run: ${{ inputs.linux_build_command }} + + macos-build: + name: "macOS (ARM64)" + if: ${{ inputs.enable_macos_checks }} + runs-on: [self-hosted, macos, tahoe, ARM64] + steps: + - name: Checkout + uses: actions/checkout@v7 + - name: Install CMake + id: install + uses: ./.github/actions/install-cmake + with: + cmake-version: ${{ inputs.cmake_version }} + hash: ${{ inputs.macos_hash }} + - name: Pre-build + if: ${{ inputs.macos_pre_build_command != '' }} + shell: bash + env: + CMAKE: ${{ steps.install.outputs.cmake }} + CTEST: ${{ steps.install.outputs.ctest }} + # zizmor: ignore[template-injection] + run: ${{ inputs.macos_pre_build_command }} + - name: Configure + shell: bash + env: + CMAKE: ${{ steps.install.outputs.cmake }} + CTEST: ${{ steps.install.outputs.ctest }} + # zizmor: ignore[template-injection] + run: ${{ inputs.macos_configure_command }} + - name: Build + shell: bash + env: + CMAKE: ${{ steps.install.outputs.cmake }} + CTEST: ${{ steps.install.outputs.ctest }} + # zizmor: ignore[template-injection] + run: ${{ inputs.macos_build_command }} + + windows-build: + name: "Windows (${{ matrix.runner }})" + if: ${{ inputs.enable_windows_checks }} + strategy: + fail-fast: false + matrix: + include: + - runner: windows-2022 + hash: ${{ inputs.windows_x86_64_hash }} + - runner: windows-11-arm + hash: ${{ inputs.windows_arm64_hash }} + runs-on: ${{ matrix.runner }} + steps: + - name: Checkout + uses: actions/checkout@v7 + - name: Install CMake + id: install + uses: ./.github/actions/install-cmake + with: + cmake-version: ${{ inputs.cmake_version }} + hash: ${{ matrix.hash }} + - name: Pre-build + if: ${{ inputs.windows_pre_build_command != '' }} + env: + CMAKE: ${{ steps.install.outputs.cmake }} + CTEST: ${{ steps.install.outputs.ctest }} + # zizmor: ignore[template-injection] + run: | + $ErrorActionPreference = "Stop" + function Invoke-Program($Executable) { & $Executable @args; if ($LastExitCode -ne 0) { exit $LastExitCode } } + ${{ inputs.windows_pre_build_command }} + - name: Configure + env: + CMAKE: ${{ steps.install.outputs.cmake }} + CTEST: ${{ steps.install.outputs.ctest }} + # zizmor: ignore[template-injection] + run: | + $ErrorActionPreference = "Stop" + function Invoke-Program($Executable) { & $Executable @args; if ($LastExitCode -ne 0) { exit $LastExitCode } } + ${{ inputs.windows_configure_command }} + - name: Build + env: + CMAKE: ${{ steps.install.outputs.cmake }} + CTEST: ${{ steps.install.outputs.ctest }} + # zizmor: ignore[template-injection] + run: | + $ErrorActionPreference = "Stop" + function Invoke-Program($Executable) { & $Executable @args; if ($LastExitCode -ne 0) { exit $LastExitCode } } + ${{ inputs.windows_build_command }} diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index bcd264ae..48582c9d 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -114,6 +114,16 @@ jobs: name: Install CMake uses: ./.github/workflows/install_cmake_test.yml + cmake_build: + name: CMake Build + uses: ./.github/workflows/cmake_build.yml + with: + # Linux uses the default Ninja generator; install Ninja first. + linux_pre_build_command: "apt-get install -y ninja-build" + linux_configure_command: "$CMAKE -G Ninja -B build -S tests/CMakeProject" + # Windows uses CMake's default generator (MSVC), so Ninja is not required. + windows_configure_command: "Invoke-Program cmake -B build -S tests/CMakeProject" + soundness-docs: name: "Soundness - Docs (override_target_name: ${{ matrix.override_target_name }} ; post command: ${{ matrix.post_command }})" strategy: diff --git a/README.md b/README.md index de2f40de..a756df0f 100644 --- a/README.md +++ b/README.md @@ -94,6 +94,56 @@ Linked PR: swiftlang/swift-syntax#2859 Enabling cross-PR testing will add about 10s to PR testing time. +### CMake Build + +The `cmake_build` workflow installs a pinned CMake (using the `install-cmake` +action) and runs your configure and build commands across Linux, macOS, and +Windows. It removes the boilerplate of installing CMake and wiring up +`$CMAKE`-based build steps in each consumer. + +By default it installs CMake 4.0.3, configures with +`$CMAKE -G Ninja -B build -S .`, and builds with `$CMAKE --build build`. +Linux builds run by default. macOS and Windows builds can be enabled with +`enable_macos_checks` and `enable_windows_checks` respectively. A minimal +example: + +```yaml +name: Pull request + +on: + pull_request: + types: [opened, reopened, synchronize] + +jobs: + cmake_build: + name: CMake Build + uses: swiftlang/github-workflows/.github/workflows/cmake_build.yml@ +``` + +Override the per-platform configure and build commands to point at your +project. `$CMAKE` and `$CTEST` are exposed as environment variables, and the +installed CMake is also on `PATH`: + +```yaml +with: + linux_configure_command: "$CMAKE -G Ninja -B build -S Sources -DCMAKE_BUILD_TYPE=Release" + linux_build_command: "$CMAKE --build build" +``` + +The default configure command uses the Ninja generator, but the workflow does +not install Ninja. Ensure Ninja is available in your environment, install it +via a `*_pre_build_command`, or override the configure command to use a +different generator: + +```yaml +with: + linux_pre_build_command: "apt-get install -y ninja-build" +``` + +To pin a different CMake version, override `cmake_version` together with the +matching per-platform SHA-256 hashes (`linux_x86_64_hash`, `linux_aarch64_hash`, +`macos_hash`, `windows_x86_64_hash`, `windows_arm64_hash`). + ### Evolution Proposal Validation The proposal validation workflow validates added and changed proposals in a pull request to check for formatting and content errors that will cause metadata extraction to fail or be incomplete. diff --git a/tests/CMakeProject/CMakeLists.txt b/tests/CMakeProject/CMakeLists.txt new file mode 100644 index 00000000..42f9ddaf --- /dev/null +++ b/tests/CMakeProject/CMakeLists.txt @@ -0,0 +1,3 @@ +cmake_minimum_required(VERSION 4.0) +project(Sample C) +add_executable(sample main.c) diff --git a/tests/CMakeProject/main.c b/tests/CMakeProject/main.c new file mode 100644 index 00000000..8a57f3e9 --- /dev/null +++ b/tests/CMakeProject/main.c @@ -0,0 +1,13 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2026 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See https://swift.org/LICENSE.txt for license information +// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// +//===----------------------------------------------------------------------===// + +int main(void) { return 0; }