Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
271 changes: 127 additions & 144 deletions .github/workflows/build.yml

Large diffs are not rendered by default.

142 changes: 142 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
# This file is part of mfaktc.
# Copyright (c) 2025 NStorm (https://github.com/N-Storm)
# Copyright (c) 2009-2011 Oliver Weihe (o.weihe@t-online.de)
#
# mfaktc is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# mfaktc is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with mfaktc. If not, see <http://www.gnu.org/licenses/>.
#
# SPDX-License-Identifier: GPL-3.0-or-later

name: mfaktc CI

on:
push:
paths-ignore:
- '**/*.txt'
- '**/*.ini'
- 'COPYING'
- '.gitignore'
pull_request:
paths-ignore:
- '**/*.txt'
- '**/*.ini'
- 'COPYING'
- '.gitignore'
types:
- 'opened'
- 'reopened'
- 'synchronize'
- 'ready_for_review'
schedule:
- cron: '0 0 1 * *'

jobs:
# Begin job "Linux"
Linux:
runs-on: ${{ matrix.os }}

strategy:
# If set to true, all jobs within the same matrix (such as Linux or
# Windows builds) will be aborted at the same time if any one job fails.
fail-fast: false

matrix:
os: [ubuntu-22.04, ubuntu-24.04, ubuntu-26.04]
cc: [gcc, clang]

env:
CC: ${{ matrix.cc }}
CXX: ${{ matrix.cc == 'gcc' && 'g++' || 'clang++' }}

steps:

- name: Checkout repo
uses: actions/checkout@v7
with:
fetch-depth: 0
fetch-tags: true

- name: Update and install dependencies
run: |
sudo apt-get update
sudo apt-get install -y nvidia-cuda-toolkit

- name: Prepare sources
run: |
cuda_version=$(nvcc --version | awk '/release/ { sub(/^V/, "", $NF); print $NF }')
bash .github/workflows/scripts/build_helper.sh "$cuda_version"

- name: Build from sources
run: |
cd src
make -O -j$(nproc) DEBUG=1
make clean

- name: Upload build artifacts
uses: actions/upload-artifact@v7
if: always()
with:
name: mfaktc-linux64-${{ matrix.os }}-${{ matrix.cc }}
path: ${{ github.workspace }}
# End job "Linux"

# Begin job "Windows"
Windows:
# windows-2022 also works and produces nearly identical binaries, so let's
# target the image that will be supported in the longer term. windows-2025
# is in beta as of June 2025, but testing has shown it is reliable.
runs-on: windows-2022

steps:

- name: Checkout repo
uses: actions/checkout@v7
with:
fetch-depth: 0
fetch-tags: true

- name: Install CUDA Toolkit
uses: N-Storm/cuda-toolkit@v0.2.34

- name: Prepare sources
shell: bash
run: |
cuda_version=$(nvcc --version | awk '/release/ { sub(/^V/, "", $NF); print $NF }')
bash .github/workflows/scripts/build_helper.sh "$cuda_version"

- name: Build from sources with MSVC
shell: cmd
run: |
"C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat" x64 || exit /b 1
cd src || exit /b 1
copy mfaktc.ini .. || exit /b 1
make SHELL="cmd.exe" -j%NUMBER_OF_PROCESSORS% -f Makefile.win DEBUG=1 || exit /b 1
make clean -f Makefile.win || exit /b 1

- name: Upload build artifacts
uses: actions/upload-artifact@v7
if: always()
with:
name: mfaktc-win64
path: ${{ github.workspace }}
# End job "Windows"

ShellCheck:
name: ShellCheck

runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- name: Script
run: shopt -s globstar; shellcheck -o avoid-nullary-conditions,check-set-e-suppressed,deprecate-which,quote-safe-variables,require-double-brackets -s bash **/*.sh
continue-on-error: true
38 changes: 18 additions & 20 deletions .github/workflows/scripts/build_helper.sh
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@
# support building under GitHub Actions runner environments and compiling
# kernels for all devices with NVCC-supported compute capabilities.

set -e -o pipefail

if [[ -z "$1" ]]; then
echo "Usage: $0 <CUDA version>" >&2
exit 1
Expand All @@ -35,7 +37,7 @@ fi
# to GNU sort
export GSORT='/usr/bin/sort'

CUDA_VERSION_FULL="$(echo "$1" | head -n1 | grep -Eom1 -e '^[1-9]([0-9])?\.[0-9]{1,2}(\.[0-9]{1,3})?$')"
CUDA_VERSION_FULL=$(echo "$1" | head -n1 | grep -Eom1 -e '^[1-9]([0-9])?\.[0-9]{1,2}(\.[0-9]{1,3})?$')
declare -a CUDA_VERSION
IFS=" " read -r -a CUDA_VERSION <<< "$(echo "$CUDA_VERSION_FULL" | tr '.' ' ')"
if [[ -z "${CUDA_VERSION[*]}" ]]; then
Expand All @@ -54,18 +56,18 @@ printf -v CUDA_VER %d%02d "${CUDA_VER_MAJOR}" "${CUDA_VER_MINOR}";
# CUDA supports the --list-gpu-arch flag from 11.0.0 onwards.
# For older CUDA versions, use grep to parse the supported architectures from
# the output of --help
[ "$CUDA_VER" -gt 1100 ] && NVCC_OPTS='--list-gpu-arch' || NVCC_OPTS='--help'
[[ "$CUDA_VER" -gt 1100 ]] && NVCC_OPTS='--list-gpu-arch' || NVCC_OPTS='--help'
NVCC_REGEX='compute_[1-9][0-9]{1,2}'
# CUDA 11.0.x is a special case. Its --help output lists compute_32 and higher,
# but only compute capability 3.5 and later are supported.
[ "$CUDA_VER" -eq 1100 ] && NVCC_REGEX='compute_(3[5-9]|[4-9][0-9])'
[[ "$CUDA_VER" -eq 1100 ]] && NVCC_REGEX='compute_(3[5-9]|[4-9][0-9])'

declare -a CC_LIST
IFS=" " read -r -a CC_LIST <<< "$(nvcc "$NVCC_OPTS" | grep -Eoe "$NVCC_REGEX" | cut -d '_' -f2 | $GSORT -un | xargs)"
if [ ${#CC_LIST[*]} -eq 0 ]; then
if [[ ${#CC_LIST[*]} -eq 0 ]]; then
echo "Error: could not parse list of supported compute capabilities" >&2
exit 3
elif [ ${#CC_LIST[*]} -lt 3 ]; then
elif [[ ${#CC_LIST[*]} -lt 3 ]]; then
echo "Warning: less than three (3) supported compute capabilities" >&2
fi

Expand All @@ -80,46 +82,42 @@ for CC in "${CC_LIST[@]}"; do
sed -i "/^NVCCFLAGS = .*\$/a NVCCFLAGS += --generate-code arch=compute_${CC},code=sm_${CC}" src/Makefile src/Makefile.win
done

if [ "$CUDA_VER" -ge 1100 ]; then
if [[ "$CUDA_VER" -ge 1100 ]]; then
echo 'Adding NVCCFLAGS to allow unsupported MSVC versions...'
sed -i '/^NVCCFLAGS = .*/a NVCCFLAGS += -allow-unsupported-compiler -D_ALLOW_COMPILER_AND_STL_VERSION_MISMATCH' src/Makefile.win
fi
if [ "$CUDA_VER" -lt 1200 ]; then
echo "Adding libraries to LDFLAGS to support static build on older Ubuntu versions..."
sed -i -E 's/^(LDFLAGS = .*? -lcudart_static) (.*)/\1 -ldl -lrt -lpthread \2/' src/Makefile
fi

echo 'Gathering host compiler and NVCC version info...'
# COMPILER_VER for Windows builds is actually set to the MSVC product version.
# We retrieve the cl.exe version during the build step and add it to the table.
if [[ -x "$(command -v vswhere.exe)" ]]; then
CC_VSPROD="$(vswhere -latest -products '*' -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property displayName | sed -e 's/Visual Studio/MSVC/')"
CC_VSPROD=$(vswhere -latest -products '*' -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property displayName | sed -e 's/Visual Studio/MSVC/')
COMPILER_VER="${CC_VSPROD}, $(vswhere -latest -products '*' -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationVersion)"
elif [[ -x "$(command -v powershell.exe)" ]]; then
CC_VSINFO="$(powershell -Command Get-VSSetupInstance)"
CC_VSPROD="$(echo "$CC_VSINFO" | grep DisplayName | cut -d':' -f2 | xargs | sed -e 's/Visual Studio/MSVC/')"
CC_VSINFO=$(powershell -Command Get-VSSetupInstance)
CC_VSPROD=$(echo "$CC_VSINFO" | grep DisplayName | cut -d':' -f2 | xargs | sed -e 's/Visual Studio/MSVC/')
COMPILER_VER="${CC_VSPROD}, $(echo "$CC_VSINFO" | grep InstallationVersion | cut -d':' -f2 | xargs)"
else
COMPILER_VER="$(gcc --version | head -n1)"
COMPILER_VER=$(gcc --version | head -n1)
# shellcheck source=/dev/null
source /etc/os-release
OS_VER="${PRETTY_NAME}"
OS_VER=${PRETTY_NAME}
OS_TYPE="linux64"
fi

if [[ -x "$(command -v powershell.exe)" ]]; then
OS_VER="$(powershell -Command "[System.Environment]::OSVersion.VersionString" | cut -d ' ' -f2-)"
OS_VER=$(powershell -Command "[System.Environment]::OSVersion.VersionString" | cut -d ' ' -f2-)
OS_TYPE="win64"
fi

NVCC_VER="$(nvcc --version | tail -n1 | sed -E 's/^Build //;s/^Cuda compilation tools, //')"
NVCC_VER=$(nvcc --version | tail -n1 | sed -E 's/^Build //;s/^Cuda compilation tools, //')

# get mfaktc version from src/params.h
# match SemVer and GIMPS version strings: https://regex101.com/r/m38d3i/2
MFAKTC_VER="$(LC_ALL=en_US.utf8 grep -iPo '#define[\s\t]+MFAKTC_VERSION[\s\t]+"v?\d+(?:\.\d+(?:\.\d+)?(?:-\d+)?|\b)(?:-?(?:alpha|beta|pre)\.?(?:\d+)?\b)?' src/params.h | cut -d '"' -f 2)"
MFAKTC_VER=$(LC_ALL=en_US.utf8 grep -iPo '#define[\s\t]+MFAKTC_VERSION[\s\t]+"v?\d+(?:\.\d+(?:\.\d+)?(?:-\d+)?|\b)(?:-?(?:alpha|beta|pre)\.?(?:\d+)?\b)?' src/params.h | cut -d '"' -f 2)

# Git-formatted version
GIT_TAG_VER="$(git describe --tags)"
GIT_TAG_VER=$(git describe --tags)

# Compare MFAKTC_VER with the version extracted from GIT_TAG_VER using tags.
# If they don't match, throw a warning and use MFAKTC_VER and the short commit
Expand All @@ -130,7 +128,7 @@ GIT_TAG_VER="$(git describe --tags)"
# reference. This gives a shorter BASE_NAME without the commit hash for
# releases.
if [[ "$MFAKTC_VER" != "${GIT_TAG_VER:0:${#MFAKTC_VER}}" ]]; then
SHA_SHORT="$(git rev-parse --short HEAD)"
SHA_SHORT=$(git rev-parse --short HEAD)
BASE_NAME="mfaktc-${MFAKTC_VER}-${SHA_SHORT}-${OS_TYPE}-cuda${CUDA_VERSION_FULL}"
echo "Warning: version from 'git describe' (${GIT_TAG_VER}) doesn't begin with MFAKTC_VER (${MFAKTC_VER}) from params.h"
echo "Using version from params.h and short commit hash (${SHA_SHORT}) for BASE_NAME"
Expand Down
11 changes: 5 additions & 6 deletions contrib/start-mfaktc.sh
Original file line number Diff line number Diff line change
Expand Up @@ -51,16 +51,15 @@ LOCK=$APP.lock
run_on_device() {
# ensure instance has its own folder
mkdir -p "device-$1"
if ! cd "device-$1"
then
if ! cd "device-$1"; then
echo "error: could not enter directory 'device-$1' for device $1" >&2
exit 1
fi

# don't run if device is in use
exec 200>"$LOCK"
exec {LOCK_FD}>"$LOCK"

if ! flock -n 200; then
if ! flock -n "$LOCK_FD"; then
echo "error: lock file $LOCK exists, mfaktc may already be running on device $1" >&2
exit 1
fi
Expand Down Expand Up @@ -105,9 +104,9 @@ fi

if [[ $# -eq 0 ]]; then
# don't run if device is in use
exec 200>"$LOCK"
exec {LOCK_FD}>"$LOCK"

if ! flock -n 200; then
if ! flock -n "$LOCK_FD"; then
echo "error: lock file $LOCK exists, mfaktc may already be running" >&2
exit 1
fi
Expand Down
27 changes: 20 additions & 7 deletions src/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,23 @@ CUDA_DIR = /usr/local/cuda
CUDA_INCLUDE = -I$(CUDA_DIR)/include/
CUDA_LIB = -L$(CUDA_DIR)/lib64/

DEBUG = 0

# compiler settings for .c files (CPU)
CC = gcc
CFLAGS = -Wall -Wextra -O3 -flto -malign-double -ffunction-sections -fdata-sections -Wl,--gc-sections $(CUDA_INCLUDE)
CFLAGS_EXTRA_SIEVE = -funroll-all-loops
CC ?= gcc
CXX ?= g++
CFLAGS = -Wall -Wextra $(CUDA_INCLUDE)

ifeq ($(DEBUG), 1)
CFLAGS += -g -Og
else
CFLAGS += -O3 -ffast-math -flto -ffunction-sections -fdata-sections
CFLAGS_EXTRA_SIEVE = -funroll-all-loops
endif

# compiler settings for .cu files (GPU)
NVCC = nvcc
NVCCFLAGS = $(CUDA_INCLUDE) --ptxas-options=-v -O3 -Wno-deprecated-gpu-targets
NVCCFLAGS = $(CUDA_INCLUDE) --ptxas-options=-v -Wno-deprecated-gpu-targets

# generate code for compute capabilities - see this table for supported
# versions: https://en.wikipedia.org/wiki/CUDA#GPUs_supported
Expand Down Expand Up @@ -40,11 +49,15 @@ NVCCFLAGS += --generate-code arch=compute_90,code=sm_90 # Hopper GPUs
NVCCFLAGS += --generate-code arch=compute_120,code=sm_120 # Blackwell GPUs

# pass some options to the C host compiler
NVCCFLAGS += --compiler-options=-Wall
ifeq ($(DEBUG), 1)
NVCCFLAGS += -g -G -O1 --compiler-options="-Wall -Wextra -Og"
else
NVCCFLAGS += -O3 --compiler-options="-Wall -Wextra -O3"
endif

# Linker
LD = gcc
LDFLAGS = -flto -fPIC -Wl,--gc-sections $(CUDA_LIB) -lcudart_static -lm -lstdc++
LD = $(CXX)
LDFLAGS = -flto -Wl,--gc-sections $(CUDA_LIB) -lcudart_static -lm -ldl -lrt -lpthread

INSTALL = install

Expand Down
29 changes: 25 additions & 4 deletions src/Makefile.win
Original file line number Diff line number Diff line change
@@ -1,8 +1,24 @@
DEBUG = 0

CC = cl
CFLAGS = /O2 /Oy /W2 /fp:fast /I"$(CUDA_PATH)\include" /I"$(CUDA_PATH)\include\cudart" /nologo
CFLAGS = /W4 /I"$(CUDA_PATH)\include" /I"$(CUDA_PATH)\include\cudart" /nologo

ifeq ($(DEBUG), 1)
CFLAGS += /Od /Zi /RTC1
else
CFLAGS += /O2 /GL /Gw /fp:fast
endif

NVCCFLAGS = -m64 -O3 --ptxas-options=-v -Wno-deprecated-gpu-targets
CUFLAGS = -DWIN64 -Xcompiler "/EHsc /W3 /nologo /O2" $(NVCCFLAGS)
NVCCFLAGS = -m64 --ptxas-options=-v -Wno-deprecated-gpu-targets
CUFLAGS = -DWIN64 $(NVCCFLAGS)

ifeq ($(DEBUG), 1)
NVCCFLAGS += -g -G -O1
CUFLAGS += -Xcompiler "/EHsc /W4 /nologo /Od /Zi"
else
NVCCFLAGS += -O3
CUFLAGS += -Xcompiler "/EHsc /W4 /nologo /O2 /Gw"
endif

############################################################

Expand All @@ -29,7 +45,12 @@ NVCCFLAGS += --generate-code arch=compute_120,code=sm_120
############################################################

LINK = link
LFLAGS = /nologo

ifeq ($(DEBUG), 1)
LFLAGS = /nologo
else
LFLAGS = /nologo /LTCG /OPT:REF /OPT:ICF
endif

CSRC = sieve.c timer.c parse.c read_config.c mfaktc.c checkpoint.c \
filelocking.c signal_handler.c output.c crc.c
Expand Down
3 changes: 3 additions & 0 deletions src/output.c
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,9 @@ void print_help(char *string)
printf(" --sleeptest test sleep functions\n");
}

#ifdef __GNUC__
__attribute__ ((format(printf, 2, 3)))
#endif
void logprintf(mystuff_t *mystuff, const char *fmt, ...)
{
va_list args;
Expand Down
3 changes: 3 additions & 0 deletions src/output.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ along with mfaktc. If not, see <http://www.gnu.org/licenses/>.
extern "C" {
#endif
void print_help(char *string);
#ifdef __GNUC__
__attribute__ ((format(printf, 2, 3)))
#endif
void logprintf(mystuff_t *mystuff, const char *fmt, ...);

void print_dez96(int96 a, char *buf);
Expand Down
Loading