Skip to content

Commit 673dcb1

Browse files
committed
Upstream CMake workflow from SwiftNIO
This commit upstreams the re-usable CMake workflow from the SwiftNIO repository. It in turn generalized and built on the existing CMake check scripts in swift-asn1, swift-certificates and swif-crypto. The workflow performs two checks: * Ensure that the `CMakeLists` files in the repository are up-to-date * Perform a CMake build using `ninja`
1 parent 23b52b7 commit 673dcb1

File tree

3 files changed

+243
-0
lines changed

3 files changed

+243
-0
lines changed

.github/workflows/cmake_tests.yml

+50
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
name: CMake build
2+
3+
on:
4+
workflow_call:
5+
inputs:
6+
update_cmake_lists_config:
7+
type: string
8+
description: "The configuration used when updating the CMake lists."
9+
required: true
10+
cmake_build_target_directory:
11+
type: string
12+
description: "The directory to pass to `cmake build`."
13+
default: "."
14+
cmake_version:
15+
type: string
16+
description: "The version of CMake to install."
17+
default: ""
18+
image:
19+
type: string
20+
description: "The docker image to run the checks in."
21+
default: "swift:6.0-jammy"
22+
23+
jobs:
24+
cmake-checks:
25+
name: CMake checks
26+
runs-on: ubuntu-latest
27+
container:
28+
image: ${{ inputs.image }}
29+
steps:
30+
- name: Checkout repository
31+
uses: actions/checkout@v4
32+
with:
33+
persist-credentials: false
34+
submodules: true
35+
- name: Mark the workspace as safe
36+
# https://github.com/actions/checkout/issues/766
37+
run: git config --global --add safe.directory ${GITHUB_WORKSPACE}
38+
- name: Check CMakeLists files
39+
run: |
40+
which curl jq || apt -q update
41+
which curl || apt -yq install curl
42+
which jq || apt -yq install jq
43+
curl -s https://raw.githubusercontent.com/apple/swift-nio/main/scripts/update-cmake-lists.sh | CONFIG_JSON='${{ inputs.update_cmake_lists_config }}' FAIL_ON_CHANGES=true bash
44+
- name: CMake build
45+
run: |
46+
which curl cmake ninja || apt -q update
47+
which curl || apt -yq install curl
48+
which cmake || apt -yq install cmake
49+
which ninja || apt -yq install ninja-build
50+
curl -s https://raw.githubusercontent.com/apple/swift-nio/main/scripts/cmake-build.sh | TARGET_DIRECTORY="${{ inputs.cmake_build_target_directory }}" CMAKE_VERSION="${{ inputs.cmake_version }}" bash
+52
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
#!/bin/bash
2+
##===----------------------------------------------------------------------===##
3+
##
4+
## This source file is part of the Swift.org open source project
5+
##
6+
## Copyright (c) 2025 Apple Inc. and the Swift project authors
7+
## Licensed under Apache License v2.0 with Runtime Library Exception
8+
##
9+
## See https://swift.org/LICENSE.txt for license information
10+
## See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
11+
##
12+
##===----------------------------------------------------------------------===##
13+
##===----------------------------------------------------------------------===##
14+
##
15+
## This source file is part of the SwiftNIO open source project
16+
##
17+
## Copyright (c) 2025 Apple Inc. and the SwiftNIO project authors
18+
## Licensed under Apache License v2.0
19+
##
20+
## See LICENSE.txt for license information
21+
## See CONTRIBUTORS.txt for the list of SwiftNIO project authors
22+
##
23+
## SPDX-License-Identifier: Apache-2.0
24+
##
25+
##===----------------------------------------------------------------------===##
26+
27+
set -uo pipefail
28+
29+
log() { printf -- "** %s\n" "$*" >&2; }
30+
error() { printf -- "** ERROR: %s\n" "$*" >&2; }
31+
fatal() { error "$@"; exit 1; }
32+
33+
target_dir="${TARGET_DIRECTORY:=""}"
34+
35+
if [ -z "$target_dir" ]; then
36+
fatal "Target directory must be specified."
37+
fi
38+
39+
CURL_BIN="${CURL_BIN:-$(which curl)}" || fatal "CURL_BIN unset and no curl on PATH"
40+
TAR_BIN="${TAR_BIN:-$(which tar)}" || fatal "TAR_BIN unset and no tar on PATH"
41+
CMAKE_BIN="${CMAKE_BIN:-$(which cmake)}" || fatal "CMAKE_BIN unset and no cmake on PATH"
42+
NINJA_BIN="${NINJA_BIN:-$(which ninja)}" || fatal "NINJA_BIN unset and no ninja on PATH"
43+
ASSEMBLY_COMPILER_BIN="${ASSEMBLY_COMPILER_BIN:-$(which clang)}" || fatal "ASSEMBLY_COMPILER_BIN unset and no clang on PATH"
44+
45+
log "Building Ninja build files for target"
46+
build_dir="${target_dir}/build"
47+
mkdir -p "$build_dir"
48+
cd "${build_dir}" || fatal "Could not 'cd' to ${build_dir}"
49+
ASM="$ASSEMBLY_COMPILER_BIN" "$CMAKE_BIN" build -G Ninja -S ..
50+
51+
log "Building target"
52+
"$NINJA_BIN"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
#!/bin/bash
2+
##===----------------------------------------------------------------------===##
3+
##
4+
## This source file is part of the Swift.org open source project
5+
##
6+
## Copyright (c) 2025 Apple Inc. and the Swift project authors
7+
## Licensed under Apache License v2.0 with Runtime Library Exception
8+
##
9+
## See https://swift.org/LICENSE.txt for license information
10+
## See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
11+
##
12+
##===----------------------------------------------------------------------===##
13+
##===----------------------------------------------------------------------===##
14+
##
15+
## This source file is part of the SwiftNIO open source project
16+
##
17+
## Copyright (c) 2025 Apple Inc. and the SwiftNIO project authors
18+
## Licensed under Apache License v2.0
19+
##
20+
## See LICENSE.txt for license information
21+
## See CONTRIBUTORS.txt for the list of SwiftNIO project authors
22+
##
23+
## SPDX-License-Identifier: Apache-2.0
24+
##
25+
##===----------------------------------------------------------------------===##
26+
27+
set -eu
28+
29+
log() { printf -- "** %s\n" "$*" >&2; }
30+
error() { printf -- "** ERROR: %s\n" "$*" >&2; }
31+
fatal() { error "$@"; exit 1; }
32+
33+
config="${CONFIG_JSON:=""}"
34+
fail_on_changes="${FAIL_ON_CHANGES:="false"}"
35+
36+
if [ -z "$config" ]; then
37+
fatal "Configuration must be provided."
38+
fi
39+
40+
here=$(pwd)
41+
42+
case "$(uname -s)" in
43+
Darwin)
44+
find=gfind # brew install findutils
45+
;;
46+
*)
47+
find='find'
48+
;;
49+
esac
50+
51+
function update_cmakelists_source() {
52+
src_root="$here/Sources/$1"
53+
54+
src_exts=("*.c" "*.swift" "*.cc")
55+
num_exts=${#src_exts[@]}
56+
log "Finding source files (" "${src_exts[@]}" ") and platform independent assembly files under $src_root"
57+
58+
# Build file extensions argument for `find`
59+
declare -a exts_arg
60+
exts_arg+=(-name "${src_exts[0]}")
61+
for (( i=1; i<num_exts; i++ ));
62+
do
63+
exts_arg+=(-o -name "${src_exts[$i]}")
64+
done
65+
66+
# Build an array with the rest of the arguments
67+
shift
68+
exceptions=("$@")
69+
# Add path exceptions for `find`
70+
if (( ${#exceptions[@]} )); then
71+
log "Excluding source paths (" "${exceptions[@]}" ") under $src_root"
72+
num_exceptions=${#exceptions[@]}
73+
for (( i=0; i<num_exceptions; i++ ));
74+
do
75+
exts_arg+=(! -path "${exceptions[$i]}")
76+
done
77+
fi
78+
79+
# Wrap quotes around each filename since it might contain spaces
80+
srcs=$($find -L "${src_root}" -type f \( "${exts_arg[@]}" \) -printf ' "%P"\n' | LC_ALL=POSIX sort)
81+
asm_srcs=$($find -L "${src_root}" -type f \( \( -name "*.S" -a ! -name "*x86_64*" -a ! -name "*arm*" -a ! -name "*apple*" -a ! -name "*linux*" \) \) -printf ' "$<$<NOT:$<PLATFORM_ID:Windows>>:%P>"\n' | LC_ALL=POSIX sort)
82+
83+
srcs="$srcs"$'\n'"$asm_srcs"
84+
log "$srcs"
85+
86+
# Update list of source files in CMakeLists.txt
87+
# The first part in `BEGIN` (i.e., `undef $/;`) is for working with multi-line;
88+
# the second is so that we can pass in a variable to replace with.
89+
perl -pi -e 'BEGIN { undef $/; $replace = shift } s/add_library\(([^\n]+)\n([^\)]+)/add_library\($1\n$replace/' "$srcs" "$src_root/CMakeLists.txt"
90+
log "Updated $src_root/CMakeLists.txt"
91+
}
92+
93+
function update_cmakelists_assembly() {
94+
src_root="$here/Sources/$1"
95+
log "Finding assembly files (.S) under $src_root"
96+
97+
mac_x86_64_asms=$($find "${src_root}" -type f \( -name "*x86_64*" -or -name "*avx2*" \) -name "*apple*" -name "*.S" -printf ' %P\n' | LC_ALL=POSIX sort)
98+
linux_x86_64_asms=$($find "${src_root}" -type f \( -name "*x86_64*" -or -name "*avx2*" \) -name "*linux*" -name "*.S" -printf ' %P\n' | LC_ALL=POSIX sort)
99+
mac_aarch64_asms=$($find "${src_root}" -type f -name "*armv8*" -name "*apple*" -name "*.S" -printf ' %P\n' | LC_ALL=POSIX sort)
100+
linux_aarch64_asms=$($find "${src_root}" -type f -name "*armv8*" -name "*linux*" -name "*.S" -printf ' %P\n' | LC_ALL=POSIX sort)
101+
log "$mac_x86_64_asms"
102+
log "$linux_x86_64_asms"
103+
log "$mac_aarch64_asms"
104+
log "$linux_aarch64_asms"
105+
106+
# Update list of assembly files in CMakeLists.txt
107+
# The first part in `BEGIN` (i.e., `undef $/;`) is for working with multi-line;
108+
# the second is so that we can pass in a variable to replace with.
109+
perl -pi -e 'BEGIN { undef $/; $replace = shift } s/Darwin([^\)]+)x86_64"\)\n target_sources\(([^\n]+)\n([^\)]+)/Darwin$1x86_64"\)\n target_sources\($2\n$replace/' "$mac_x86_64_asms" "$src_root/CMakeLists.txt"
110+
perl -pi -e 'BEGIN { undef $/; $replace = shift } s/Linux([^\)]+)x86_64"\)\n target_sources\(([^\n]+)\n([^\)]+)/Linux$1x86_64"\)\n target_sources\($2\n$replace/' "$linux_x86_64_asms" "$src_root/CMakeLists.txt"
111+
perl -pi -e 'BEGIN { undef $/; $replace = shift } s/Darwin([^\)]+)aarch64"\)\n target_sources\(([^\n]+)\n([^\)]+)/Darwin$1aarch64"\)\n target_sources\($2\n$replace/' "$mac_aarch64_asms" "$src_root/CMakeLists.txt"
112+
perl -pi -e 'BEGIN { undef $/; $replace = shift } s/Linux([^\)]+)aarch64"\)\n target_sources\(([^\n]+)\n([^\)]+)/Linux$1aarch64"\)\n target_sources\($2\n$replace/' "$linux_aarch64_asms" "$src_root/CMakeLists.txt"
113+
log "Updated $src_root/CMakeLists.txt"
114+
}
115+
116+
echo "$config" | jq -c '.targets[]' | while read -r target; do
117+
name="$(echo "$target" | jq -r .name)"
118+
type="$(echo "$target" | jq -r .type)"
119+
exceptions=("$(echo "$target" | jq -r .exceptions | jq -r @sh)")
120+
log "Updating cmake list for ${name}"
121+
122+
case "$type" in
123+
source)
124+
update_cmakelists_source "$name" "${exceptions[@]}"
125+
;;
126+
assembly)
127+
update_cmakelists_assembly "$name"
128+
;;
129+
*)
130+
fatal "Unknown target type: $type"
131+
;;
132+
esac
133+
done
134+
135+
if [[ "${fail_on_changes}" == true ]]; then
136+
if [ -n "$(git status --untracked-files=no --porcelain)" ]; then
137+
fatal "Changes in the cmake files detected. Please update."
138+
else
139+
log "✅ CMake files are up-to-date."
140+
fi
141+
fi

0 commit comments

Comments
 (0)