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
236 changes: 154 additions & 82 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,16 @@
name: threading
on: [push, pull_request]
on:
push:
branches:
- 'master'
pull_request:

# One in-flight run per branch/PR. `master` is excluded from cancellation
# (github.sha makes its group unique per commit) so the history of green
# builds there stays complete.
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}-${{ github.ref == 'refs/heads/master' && github.sha || '' }}
cancel-in-progress: true

jobs:
build:
Expand All @@ -8,88 +19,145 @@ jobs:
max-parallel: 20
matrix:
branch: [master]
# `builder` lives on the target rather than in a keyed `include`
# because the rows need runners an os-keyed include cannot express
# (and so a future linux/arm64 row can pick the arm image).
#
# Nim branches: `devel` and `version-2-4` get the full platform
# sweep; the older lines get a smoke row each. `version-1-6` is gone
# on purpose — nim-lang/nightlies stopped building it and its
# `latest-version-1-6` alias has pointed at a 2024-07-10 binary ever
# since, so that row was asserting nothing about today's 1.6. The
# `.nimble` floor moved to `>= 2.0.0` to match, so `version-2-0` is
# now the oldest row and it is the one that holds that floor honest.
target:
- os: linux
cpu: amd64
nim_branch: devel
builder: ubuntu-24.04
# 32-bit is where the pointer-sized atomics and the channel's
# alignment assumptions actually differ. Linux i386 is cheap
# (a gcc-multilib wrapper, see below) and catches those far
# faster than the windows-i386 row does.
- os: linux
cpu: amd64
nim_branch: version-2-0
- os: linux
cpu: amd64
nim_branch: version-1-6
# - os: linux
# cpu: i386
# nim_branch: devel
# - os: linux
# cpu: i386
# nim_branch: version-2-0
# - os: linux
# cpu: i386
# nim_branch: version-1-6
- os: macos
cpu: amd64
cpu: i386
nim_branch: devel
builder: ubuntu-24.04
- os: macos
cpu: amd64
nim_branch: version-2-0
- os: macos
cpu: amd64
nim_branch: version-1-6
cpu: arm64
nim_branch: devel
builder: macos-15
- os: windows
cpu: amd64
nim_branch: devel
builder: windows-2025
- os: windows
cpu: i386
nim_branch: devel
builder: windows-2025

- os: linux
cpu: amd64
nim_branch: version-2-0
nim_branch: version-2-4
builder: ubuntu-24.04
- os: linux
cpu: i386
nim_branch: version-2-4
builder: ubuntu-24.04
- os: macos
cpu: arm64
nim_branch: version-2-4
builder: macos-15
- os: windows
cpu: amd64
nim_branch: version-1-6
nim_branch: version-2-4
builder: windows-2025
- os: windows
cpu: i386
nim_branch: devel
nim_branch: version-2-4
builder: windows-2025

- os: linux
cpu: amd64
nim_branch: version-2-2
builder: ubuntu-24.04
- os: windows
cpu: i386
cpu: amd64
nim_branch: version-2-2
builder: windows-2025

# The oldest line still built by nightlies, kept as the floor check.
- os: linux
cpu: amd64
nim_branch: version-2-0
- os: windows
cpu: i386
nim_branch: version-1-6
include:
- target:
os: linux
builder: ubuntu-latest
- target:
os: macos
builder: macos-latest
- target:
os: windows
builder: windows-latest
builder: ubuntu-24.04

name: '${{ matrix.target.os }}-${{ matrix.target.cpu }}-nim-${{ matrix.target.nim_branch }} (${{ matrix.branch }})'
runs-on: ${{ matrix.builder }}
env:
NIM_DIR: nim-${{ matrix.target.nim_branch }}-${{ matrix.target.cpu }}
NIM_BRANCH: ${{ matrix.target.nim_branch }}
NIM_ARCH: ${{ matrix.target.cpu }}
runs-on: ${{ matrix.target.builder }}
steps:
- name: set `core.autocrlf` to false
shell: bash
run: |
git config --global core.autocrlf false
git config --global init.defaultBranch master

- name: Checkout threading
uses: actions/checkout@v5
with:
path: threading
submodules: false

- name: Install dependencies (Linux i386)
if: runner.os == 'Linux' && matrix.target.cpu == 'i386'
shell: bash
working-directory: ${{ github.workspace }}
run: |
# There is no 32-bit GitHub runner: the host stays x86_64 and the
# 32-bit target is reached by putting `gcc -m32` wrappers ahead of
# the real ones on PATH. gcc-multilib also pulls in libc6-i386,
# which is what lets the 32-bit Nim nightly run here at all.
#
# tests/nim.cfg switches this row to `--cc:gcc` for the same
# reason: clang is deliberately NOT wrapped, and would otherwise
# emit 64-bit objects that fail to link.
sudo dpkg --add-architecture i386
sudo apt-get update -qq
sudo DEBIAN_FRONTEND='noninteractive' apt-get install \
--no-install-recommends -yq gcc-multilib g++-multilib \
libssl-dev:i386

mkdir -p external/bin
cat << EOF > external/bin/gcc
#!/bin/bash

exec $(which gcc) -m32 "\$@"
EOF

cat << EOF > external/bin/g++
#!/bin/bash

exec $(which g++) -m32 "\$@"
EOF

chmod 755 external/bin/gcc external/bin/g++

echo "$PWD/external/bin" >> "${GITHUB_PATH}"

- name: Restore MinGW-W64 (Windows) from cache
if: runner.os == 'Windows'
id: windows-mingw-cache
uses: actions/cache@v3
uses: actions/cache@v5
with:
path: external/mingw-${{ matrix.target.cpu }}
key: 'mingw-${{ matrix.target.cpu }}'
# Bump the suffix when changing MINGW_URL below — the old cache
# would otherwise keep delivering the previous bundle even though
# the archive name and contents changed.
key: 'mingw-${{ matrix.target.cpu }}-gcc14-llvm19'

- name: Restore Nim DLLs dependencies (Windows) from cache
if: runner.os == 'Windows'
id: windows-dlls-cache
uses: actions/cache@v3
uses: actions/cache@v5
with:
path: external/dlls-${{ matrix.target.cpu }}
key: 'dlls-${{ matrix.target.cpu }}'
Expand All @@ -101,11 +169,14 @@ jobs:
shell: bash
run: |
mkdir -p external
# The GCC+LLVM winlibs variant, not the gcc-only one: tests/nim.cfg
# builds with clang on Windows too, so `clang` and `ld.lld` have to
# ship alongside `gcc` here.
if [[ '${{ matrix.target.cpu }}' == 'amd64' ]]; then
MINGW_URL="https://github.com/brechtsanders/winlibs_mingw/releases/download/14.1.0posix-18.1.8-12.0.0-ucrt-r3/winlibs-x86_64-posix-seh-gcc-14.1.0-mingw-w64ucrt-12.0.0-r3.7z"
MINGW_URL="https://github.com/brechtsanders/winlibs_mingw/releases/download/14.2.0posix-19.1.7-12.0.0-msvcrt-r3/winlibs-x86_64-posix-seh-gcc-14.2.0-llvm-19.1.7-mingw-w64msvcrt-12.0.0-r3.7z"
ARCH=64
else
MINGW_URL="https://github.com/brechtsanders/winlibs_mingw/releases/download/14.1.0posix-18.1.8-12.0.0-ucrt-r3/winlibs-i686-posix-dwarf-gcc-14.1.0-mingw-w64ucrt-12.0.0-r3.7z"
MINGW_URL="https://github.com/brechtsanders/winlibs_mingw/releases/download/14.2.0posix-19.1.7-12.0.0-msvcrt-r3/winlibs-i686-posix-dwarf-gcc-14.2.0-llvm-19.1.7-mingw-w64msvcrt-12.0.0-r3.7z"
ARCH=32
fi
curl -L "$MINGW_URL" -o "external/mingw-${{ matrix.target.cpu }}.7z"
Expand All @@ -123,51 +194,52 @@ jobs:
7z x -y external/windeps.zip -oexternal/dlls-${{ matrix.target.cpu }}

- name: Path to cached dependencies (Windows)
if: >
runner.os == 'Windows'
if: runner.os == 'Windows'
shell: bash
run: |
echo '${{ github.workspace }}'"/external/mingw-${{ matrix.target.cpu }}/bin" >> $GITHUB_PATH
echo '${{ github.workspace }}'"/external/dlls-${{ matrix.target.cpu }}" >> $GITHUB_PATH

- name: Restore Nim from cache
if: >
steps.nim-compiler-cache.outputs.cache-hit != 'true' &&
matrix.target.nim_branch != 'devel'
id: nim-compiler-cache
uses: actions/cache@v3
with:
path: '${{ github.workspace }}/nim-${{ matrix.target.nim_branch }}-${{ matrix.target.cpu }}'
key: 'nim-${{ matrix.target.cpu }}-${{ matrix.target.nim_branch }}'

- name: Setup Nim
uses: alaviss/setup-nim@0.1.1
with:
path: 'nim'
version: ${{ matrix.target.nim_branch }}
architecture: ${{ matrix.target.cpu }}

- name: Seed the nimble package list
shell: bash
run: |
# `nimble test` refreshes the official package list on a runner that
# has no `~/.nimble` yet, and the 32-bit Windows nimble binary
# segfaults doing it:
#
# Downloading Official package list
# SIGSEGV: Illegal storage access. (Attempt to read from nil?)
#
# It dies there before compiling a single test, which is why the two
# windows-i386 rows were the only red ones. The crash is nimble's
# own: the same 32-bit Nim fetches the same URL over HTTPS fine via
# std/httpclient, a plain-http list URL crashes identically, and
# `--offline` does not skip the download. Writing the list ourselves
# means nimble has nothing to refresh. Harmless on the rows that
# already work, and it keeps every row off nimble's network path.
#
# Fetched from the packages repo rather than from
# packages.nim-lang.org, which serves a 403 to anything that is not
# nimble (curl gets it with or without a browser User-Agent). The
# two are the same bytes: the file this writes is checksum-identical
# to the one a working `nimble refresh` leaves behind.
mkdir -p "$HOME/.nimble"
curl -fsSL https://raw.githubusercontent.com/nim-lang/packages/master/packages.json \
-o "$HOME/.nimble/packages_official.json"

- name: Run tests
# No flags here: `--threads:on`, `--mm:arc` and the per-target
# compiler/sanitizer choice all live in tests/nim.cfg, which nimble
# picks up because it is next to the test files. Passing `--gc:arc`
# on the command line only re-stated it and earned a deprecation
# warning on every single compile.
run: |
cd threading
nimble --threads:on --gc:arc test

# - name: Build docs
# if: matrix.branch == 'devel'
# run: nimble docs

# - name: Deploy docs
# # to view docs on your own fork: push a gh-pages branch on your fork,
# # enable gh-pages in your fork
# # and remove `github.ref == 'refs/heads/master'` below
# if: |
# github.event_name == 'push' && github.ref == 'refs/heads/master' &&
# matrix.target.os == 'linux' && matrix.target.cpu == 'amd64' &&
# matrix.branch == 'devel'
# uses: crazy-max/ghaction-github-pages@v1
# with:
# build_dir: fusion/htmldocs
# target_branch: gh-pages
# env:
# GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

nimble test
34 changes: 24 additions & 10 deletions tests/nim.cfg
Original file line number Diff line number Diff line change
@@ -1,14 +1,28 @@
--path:"../"
--gc:arc
--mm:arc
--threads:on
--define:useMalloc
--cc:clang
@if not windows:
--debugger:native
--passc:"-fsanitize=thread -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer"
--passl:"-fsanitize=thread -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer"

@if i386:
@if windows:
# The MinGW bundle CI installs for this row is the i686 one, but the Nim
# nightly still drives it as a cross-compiler, so the -m32 has to be
# spelled out.
--cc:clang
--passc:"-m32"
--passl:"-m32"
@else:
# ThreadSanitizer ships no 32-bit x86 runtime, so the sanitised build below
# cannot be used here. The 32-bit toolchain CI installs is the
# gcc-multilib wrapper pair (see .github/workflows/ci.yml); clang is not
# wrapped and would silently emit 64-bit objects.
--cc:gcc
@end
@else:
--cc:clang
@if not windows:
--debugger:native
--passc:"-fsanitize=thread -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer"
--passl:"-fsanitize=thread -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer"
@end
@end
@if windows and i386:
--passc:"-m32"
--passl:"-m32"
@end
2 changes: 1 addition & 1 deletion threading.nimble
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,4 @@ license = "MIT"

# Dependencies

requires "nim >= 1.6.0"
requires "nim >= 2.0.0"
Loading