Skip to content

Commit b4ed5fc

Browse files
committed
Add initial CI workflows
- Lint workflow which just does linting, separateley to compilation workflows - Ubuntu workflow which tests different combinations of CUDA, GCC and Ubuntu
1 parent fdfd6b8 commit b4ed5fc

File tree

3 files changed

+382
-0
lines changed

3 files changed

+382
-0
lines changed
Lines changed: 196 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,196 @@
1+
# @todo - better / more robust parsing of inputs from env vars.
2+
## -------------------
3+
## Constants
4+
## -------------------
5+
6+
# List of sub-packages to install.
7+
# @todo - pass this in from outside the script?
8+
# @todo - check the specified subpackages exist via apt pre-install? apt-rdepends cuda-9-0 | grep "^cuda-"?
9+
10+
# Ideally choose from the list of meta-packages to minimise variance between cuda versions (although it does change too). Some of these packages may not be availble in older CUDA releases
11+
CUDA_PACKAGES_IN=(
12+
"cuda-compiler"
13+
"cuda-cudart-dev"
14+
"cuda-nvtx"
15+
"cuda-nvrtc-dev"
16+
"libcurand-dev" # 11-0+
17+
"cuda-cccl" # 11.4+, provides cub and thrust. On 11.3 knwon as cuda-thrust-11-3
18+
)
19+
20+
## -------------------
21+
## Bash functions
22+
## -------------------
23+
# returns 0 (true) if a >= b
24+
function version_ge() {
25+
[ "$#" != "2" ] && echo "${FUNCNAME[0]} requires exactly 2 arguments." && exit 1
26+
[ "$(printf '%s\n' "$@" | sort -V | head -n 1)" == "$2" ]
27+
}
28+
# returns 0 (true) if a > b
29+
function version_gt() {
30+
[ "$#" != "2" ] && echo "${FUNCNAME[0]} requires exactly 2 arguments." && exit 1
31+
[ "$1" = "$2" ] && return 1 || version_ge $1 $2
32+
}
33+
# returns 0 (true) if a <= b
34+
function version_le() {
35+
[ "$#" != "2" ] && echo "${FUNCNAME[0]} requires exactly 2 arguments." && exit 1
36+
[ "$(printf '%s\n' "$@" | sort -V | head -n 1)" == "$1" ]
37+
}
38+
# returns 0 (true) if a < b
39+
function version_lt() {
40+
[ "$#" != "2" ] && echo "${FUNCNAME[0]} requires exactly 2 arguments." && exit 1
41+
[ "$1" = "$2" ] && return 1 || version_le $1 $2
42+
}
43+
44+
## -------------------
45+
## Select CUDA version
46+
## -------------------
47+
48+
# Get the cuda version from the environment as $cuda.
49+
CUDA_VERSION_MAJOR_MINOR=${cuda}
50+
51+
# Split the version.
52+
# We (might/probably) don't know PATCH at this point - it depends which version gets installed.
53+
CUDA_MAJOR=$(echo "${CUDA_VERSION_MAJOR_MINOR}" | cut -d. -f1)
54+
CUDA_MINOR=$(echo "${CUDA_VERSION_MAJOR_MINOR}" | cut -d. -f2)
55+
CUDA_PATCH=$(echo "${CUDA_VERSION_MAJOR_MINOR}" | cut -d. -f3)
56+
# use lsb_release to find the OS.
57+
UBUNTU_VERSION=$(lsb_release -sr)
58+
UBUNTU_VERSION="${UBUNTU_VERSION//.}"
59+
60+
echo "CUDA_MAJOR: ${CUDA_MAJOR}"
61+
echo "CUDA_MINOR: ${CUDA_MINOR}"
62+
echo "CUDA_PATCH: ${CUDA_PATCH}"
63+
# echo "UBUNTU_NAME: ${UBUNTU_NAME}"
64+
echo "UBUNTU_VERSION: ${UBUNTU_VERSION}"
65+
66+
# If we don't know the CUDA_MAJOR or MINOR, error.
67+
if [ -z "${CUDA_MAJOR}" ] ; then
68+
echo "Error: Unknown CUDA Major version. Aborting."
69+
exit 1
70+
fi
71+
if [ -z "${CUDA_MINOR}" ] ; then
72+
echo "Error: Unknown CUDA Minor version. Aborting."
73+
exit 1
74+
fi
75+
# If we don't know the Ubuntu version, error.
76+
if [ -z ${UBUNTU_VERSION} ]; then
77+
echo "Error: Unknown Ubuntu version. Aborting."
78+
exit 1
79+
fi
80+
81+
82+
## -------------------------------
83+
## Select CUDA packages to install
84+
## -------------------------------
85+
CUDA_PACKAGES=""
86+
for package in "${CUDA_PACKAGES_IN[@]}"
87+
do :
88+
# @todo This is not perfect. Should probably provide a separate list for diff versions
89+
# cuda-compiler-X-Y if CUDA >= 9.1 else cuda-nvcc-X-Y
90+
if [[ "${package}" == "cuda-nvcc" ]] && version_ge "$CUDA_VERSION_MAJOR_MINOR" "9.1" ; then
91+
package="cuda-compiler"
92+
elif [[ "${package}" == "cuda-compiler" ]] && version_lt "$CUDA_VERSION_MAJOR_MINOR" "9.1" ; then
93+
package="cuda-nvcc"
94+
# CUB/Thrust are packages in cuda-thrust in 11.3, but cuda-cccl in 11.4+
95+
elif [[ "${package}" == "cuda-thrust" || "${package}" == "cuda-cccl" ]]; then
96+
# CUDA cuda-thrust >= 11.4
97+
if version_ge "$CUDA_VERSION_MAJOR_MINOR" "11.4" ; then
98+
package="cuda-cccl"
99+
# Use cuda-thrust > 11.2
100+
elif version_ge "$CUDA_VERSION_MAJOR_MINOR" "11.3" ; then
101+
package="cuda-thrust"
102+
# Do not include this pacakge < 11.3
103+
else
104+
continue
105+
fi
106+
fi
107+
# CUDA 11+ includes lib* / lib*-dev packages, which if they existed previously where cuda-cu*- / cuda-cu*-dev-
108+
if [[ ${package} == libcu* ]] && version_lt "$CUDA_VERSION_MAJOR_MINOR" "11.0" ; then
109+
package="${package/libcu/cuda-cu}"
110+
fi
111+
# Build the full package name and append to the string.
112+
CUDA_PACKAGES+=" ${package}-${CUDA_MAJOR}-${CUDA_MINOR}"
113+
done
114+
echo "CUDA_PACKAGES ${CUDA_PACKAGES}"
115+
116+
## -----------------
117+
## Prepare to install
118+
## -----------------
119+
CPU_ARCH="x86_64"
120+
PIN_FILENAME="cuda-ubuntu${UBUNTU_VERSION}.pin"
121+
PIN_URL="https://developer.download.nvidia.com/compute/cuda/repos/ubuntu${UBUNTU_VERSION}/${CPU_ARCH}/${PIN_FILENAME}"
122+
# apt keyring package now available https://developer.nvidia.com/blog/updating-the-cuda-linux-gpg-repository-key/
123+
KERYRING_PACKAGE_FILENAME="cuda-keyring_1.0-1_all.deb"
124+
KEYRING_PACKAGE_URL="https://developer.download.nvidia.com/compute/cuda/repos/ubuntu${UBUNTU_VERSION}/${CPU_ARCH}/${KERYRING_PACKAGE_FILENAME}"
125+
REPO_URL="https://developer.download.nvidia.com/compute/cuda/repos/ubuntu${UBUNTU_VERSION}/${CPU_ARCH}/"
126+
127+
echo "PIN_FILENAME ${PIN_FILENAME}"
128+
echo "PIN_URL ${PIN_URL}"
129+
echo "KEYRING_PACKAGE_URL ${KEYRING_PACKAGE_URL}"
130+
echo "APT_KEY_URL ${APT_KEY_URL}"
131+
132+
## -----------------
133+
## Check for root/sudo
134+
## -----------------
135+
136+
# Detect if the script is being run as root, storing true/false in is_root.
137+
is_root=false
138+
if (( $EUID == 0)); then
139+
is_root=true
140+
fi
141+
# Find if sudo is available
142+
has_sudo=false
143+
if command -v sudo &> /dev/null ; then
144+
has_sudo=true
145+
fi
146+
# Decide if we can proceed or not (root or sudo is required) and if so store whether sudo should be used or not.
147+
if [ "$is_root" = false ] && [ "$has_sudo" = false ]; then
148+
echo "Root or sudo is required. Aborting."
149+
exit 1
150+
elif [ "$is_root" = false ] ; then
151+
USE_SUDO=sudo
152+
else
153+
USE_SUDO=
154+
fi
155+
156+
## -----------------
157+
## Install
158+
## -----------------
159+
echo "Adding CUDA Repository"
160+
wget ${PIN_URL}
161+
$USE_SUDO mv ${PIN_FILENAME} /etc/apt/preferences.d/cuda-repository-pin-600
162+
wget ${KEYRING_PACKAGE_URL} && ${USE_SUDO} dpkg -i ${KERYRING_PACKAGE_FILENAME} && rm ${KERYRING_PACKAGE_FILENAME}
163+
$USE_SUDO add-apt-repository "deb ${REPO_URL} /"
164+
$USE_SUDO apt-get update
165+
166+
echo "Installing CUDA packages ${CUDA_PACKAGES}"
167+
$USE_SUDO apt-get -y install ${CUDA_PACKAGES}
168+
169+
if [[ $? -ne 0 ]]; then
170+
echo "CUDA Installation Error."
171+
exit 1
172+
fi
173+
174+
## -----------------
175+
## Set environment vars / vars to be propagated
176+
## -----------------
177+
178+
CUDA_PATH=/usr/local/cuda-${CUDA_MAJOR}.${CUDA_MINOR}
179+
echo "CUDA_PATH=${CUDA_PATH}"
180+
export CUDA_PATH=${CUDA_PATH}
181+
export PATH="$CUDA_PATH/bin:$PATH"
182+
export LD_LIBRARY_PATH="$CUDA_PATH/lib:$LD_LIBRARY_PATH"
183+
export LD_LIBRARY_PATH="$CUDA_PATH/lib64:$LD_LIBRARY_PATH"
184+
# Check nvcc is now available.
185+
nvcc -V
186+
187+
188+
# If executed on github actions, make the appropriate echo statements to update the environment
189+
if [[ $GITHUB_ACTIONS ]]; then
190+
# Set paths for subsequent steps, using ${CUDA_PATH}
191+
echo "Adding CUDA to CUDA_PATH, PATH and LD_LIBRARY_PATH"
192+
echo "CUDA_PATH=${CUDA_PATH}" >> $GITHUB_ENV
193+
echo "${CUDA_PATH}/bin" >> $GITHUB_PATH
194+
echo "LD_LIBRARY_PATH=${CUDA_PATH}/lib:${LD_LIBRARY_PATH}" >> $GITHUB_ENV
195+
echo "LD_LIBRARY_PATH=${CUDA_PATH}/lib64:${LD_LIBRARY_PATH}" >> $GITHUB_ENV
196+
fi

.github/workflows/Lint.yml

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
# Lint the project using cpplint, this currently requires CUDA for CMake configuration to succeed
2+
name: Lint
3+
4+
on:
5+
# Branch pushes that do not only modify other workflow files
6+
push:
7+
branches:
8+
- '**'
9+
paths:
10+
- "**"
11+
- "!.github/**"
12+
- ".github/scripts/install_cuda_ubuntu.sh"
13+
- ".github/workflows/Lint.yml"
14+
# Allow manual invocation.
15+
workflow_dispatch:
16+
17+
defaults:
18+
run:
19+
shell: bash
20+
21+
jobs:
22+
cpplint:
23+
runs-on: ${{ matrix.cudacxx.os }}
24+
name: "cpplint (${{ matrix.cudacxx.cuda }}, ${{ matrix.cudacxx.os }})"
25+
strategy:
26+
fail-fast: false
27+
# Multiplicative build matrix
28+
# optional exclude: can be partial, include: must be specific
29+
matrix:
30+
cudacxx:
31+
- cuda: "12.0"
32+
os: ubuntu-22.04
33+
env:
34+
# Define constants
35+
BUILD_DIR: "build"
36+
CUDA: ${{ matrix.cudacxx.cuda }}
37+
OS: ${{ matrix.cudacxx.os }}
38+
39+
steps:
40+
- uses: actions/checkout@v3
41+
42+
- name: Install CUDA
43+
if: ${{ startswith(env.OS, 'ubuntu') && env.CUDA != '' }}
44+
env:
45+
cuda: ${{ env.CUDA }}
46+
run: .github/scripts/install_cuda_ubuntu.sh
47+
48+
- name: Install cpplint
49+
run: |
50+
python3 -m pip install cpplint
51+
echo "$HOME/.local/bin" >> $GITHUB_PATH
52+
53+
- name: Add custom problem matchers for annotations
54+
run: echo "::add-matcher::.github/problem-matchers.json"
55+
56+
- name: Configure cmake
57+
run: >
58+
cmake . -B "${{ env.BUILD_DIR }}"
59+
-Wno-dev
60+
-DCMAKE_WARN_DEPRECATED="OFF"
61+
-DFLAMEGPU_WARNINGS_AS_ERRORS="ON"
62+
-DBUILD_TESTING="ON"
63+
64+
- name: Lint
65+
working-directory: ${{ env.BUILD_DIR }}
66+
run: cmake --build . --target lint --verbose -j `nproc`

.github/workflows/Ubuntu.yml

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
# Compile project on Ubuntu
2+
name: Ubuntu
3+
4+
on:
5+
# Branch pushes that do not only modify other workflow files
6+
push:
7+
branches:
8+
- '**'
9+
paths:
10+
- "**"
11+
- "!.github/**"
12+
- ".github/scripts/install_cuda_ubuntu.sh"
13+
- ".github/workflows/Ubuntu.yml"
14+
# Allow manual invocation.
15+
workflow_dispatch:
16+
17+
defaults:
18+
run:
19+
shell: bash
20+
21+
jobs:
22+
build:
23+
runs-on: ${{ matrix.cudacxx.os }}
24+
strategy:
25+
fail-fast: false
26+
# Multiplicative build matrix
27+
# optional exclude: can be partial, include: must be specific
28+
matrix:
29+
cudacxx:
30+
# CUDA 12.6 with gcc 12 on 24.04
31+
- cuda: "12.6"
32+
cuda_arch: "52"
33+
hostcxx: gcc-12
34+
os: ubuntu-24.04
35+
# CUDA 12.0 with gcc 11 on 22.04
36+
- cuda: "12.6"
37+
cuda_arch: "52"
38+
hostcxx: gcc-11
39+
os: ubuntu-22.04
40+
# CUDA 11.8 with GCC 10
41+
- cuda: "11.8"
42+
cuda_arch: "52"
43+
hostcxx: gcc-10
44+
os: ubuntu-22.04
45+
# CUDA 11.6 with GCC 9 on 22.04
46+
- cuda: "11.6"
47+
cuda_arch: "35"
48+
hostcxx: gcc-9
49+
os: ubuntu-22.04
50+
# CUDA 11.2, with GCC 8 on Ubuntu 20.04 to try and prevent use of C++17 features not present in gcc 8
51+
- cuda: "11.2"
52+
cuda_arch: "35"
53+
hostcxx: gcc-8
54+
os: ubuntu-20.04
55+
56+
# Name the job based on matrix/env options
57+
name: "build (${{ matrix.cudacxx.cuda }}, ${{ matrix.cudacxx.hostcxx }}, ${{ matrix.cudacxx.os }})"
58+
59+
# Define job-wide env constants, and promote matrix elements to env constants for portable steps.
60+
env:
61+
# Define constants
62+
BUILD_DIR: "build"
63+
# Port matrix options to environment, for more portability.
64+
CUDA: ${{ matrix.cudacxx.cuda }}
65+
CUDA_ARCH: ${{ matrix.cudacxx.cuda_arch }}
66+
HOSTCXX: ${{ matrix.cudacxx.hostcxx }}
67+
OS: ${{ matrix.cudacxx.os }}
68+
CONFIG: ${{ matrix.config.config }}
69+
70+
steps:
71+
- uses: actions/checkout@v3
72+
73+
- name: Install CUDA
74+
if: ${{ startswith(env.OS, 'ubuntu') && env.CUDA != '' }}
75+
env:
76+
cuda: ${{ env.CUDA }}
77+
run: .github/scripts/install_cuda_ubuntu.sh
78+
79+
- name: Install/Select gcc and g++
80+
if: ${{ startsWith(env.HOSTCXX, 'gcc-') }}
81+
run: |
82+
gcc_version=${HOSTCXX//gcc-/}
83+
sudo apt-get install -y gcc-${gcc_version} g++-${gcc_version}
84+
echo "CC=/usr/bin/gcc-${gcc_version}" >> $GITHUB_ENV
85+
echo "CXX=/usr/bin/g++-${gcc_version}" >> $GITHUB_ENV
86+
echo "CUDAHOSTCXX=/usr/bin/g++-${gcc_version}" >> $GITHUB_ENV
87+
88+
- name: Add custom problem matchers for annotations
89+
run: echo "::add-matcher::.github/problem-matchers.json"
90+
91+
- name: Enable git safe-directory
92+
run: git config --global --add safe.directory $GITHUB_WORKSPACE
93+
94+
- name: Configure cmake
95+
run: >
96+
cmake . -B "${{ env.BUILD_DIR }}"
97+
-DCMAKE_BUILD_TYPE="Release"
98+
-Wno-dev
99+
-DCMAKE_WARN_DEPRECATED="OFF"
100+
-DFLAMEGPU_WARNINGS_AS_ERRORS="ON"
101+
-DCMAKE_CUDA_ARCHITECTURES="${{ env.CUDA_ARCH }}"
102+
-DBUILD_TESTING="ON"
103+
104+
- name: Build flamegpu
105+
working-directory: ${{ env.BUILD_DIR }}
106+
run: cmake --build . --target flamegpu --verbose -j `nproc`
107+
108+
- name: Build the simulation binary
109+
if: ${{ env.FLAMEGPU_BUILD_PYTHON == 'ON' }}
110+
working-directory: ${{ env.BUILD_DIR }}
111+
run: cmake --build . --target exatepp_abm --verbose -j `nproc`
112+
113+
- name: Build the c++ test suite
114+
if: ${{ env.FLAMEGPU_BUILD_TESTS == 'ON' }}
115+
working-directory: ${{ env.BUILD_DIR }}
116+
run: cmake --build . --target tests --verbose -j `nproc`
117+
118+
- name: Build any remaining targets
119+
working-directory: ${{ env.BUILD_DIR }}
120+
run: cmake --build . --target all --verbose -j `nproc`

0 commit comments

Comments
 (0)