Initial project import

This commit is contained in:
Agila Forge Importer committed 2026-07-13 15:20:32 +00:00
commit 23f2d29e32
11957 files changed
+1754577

No files matched your search

+52
View File
@@ -0,0 +1,52 @@
#######################################################################################
## The goal of this file, is to provide an easy and reproducible way to check *locally*
## the CI job `docker-alpine-musl-gcc`
## Building the docker image:
## docker build -t ci_alpine_local - < .github/workflows/Dockerfile.ci_alpine_local
## Running the docker image, after building it:
## docker run --rm -it -v .:/opt/vlang -w /opt/vlang ci_alpine_local
## Once it is running, inside the container you can:
## make && v -e 'println(2+2)'
## ... then do whatever you need to reproduce the CI test failure.
## Note: after you are finished, and exit the container, run `make` again, otherwise
## you will be using V (and potentially V tools) that were compiled with musl.
#######################################################################################
FROM thevlang/vlang:alpine-build
LABEL maintainer="spytheman <spytheman@bulsynt.org>"
WORKDIR /opt/vlang
ENV PATH /opt/vlang:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
## install development packages
RUN apk --no-cache add \
musl-dev libc-dev libc6-compat gcompat \
libunwind-dev libunwind-static \
gc gc-dev \
binutils diffutils elfutils \
strace gdb \
pcre bash fzf fzf-vim tmux less file colordiff \
vim vim-editorconfig \
nano nano-syntax \
micro
RUN git config --global --add safe.directory /opt/vlang &&\
git config --global --add safe.directory /opt/vlang/vc &&\
git config --global --add safe.directory /opt/vlang/thirdparty/tcc &&\
find /usr/share/nano/ -iname "*.nanorc" -exec echo include {} \; >> ~/.nanorc &&\
micro -plugin install detectindent &&\
micro -plugin install editorconfig &&\
micro -plugin install monokai-dark &&\
micro -plugin install quickfix &&\
micro -plugin install runit &&\
micro -plugin install cheat &&\
micro -plugin install jump &&\
true
## setup runtime environment for v and bash:
ENV VTMP /tmp/v
ENV VMODULES /tmp/vmodules
ENV VFLAGS "-d dynamic_boehm"
CMD ["bash"]
+25
View File
@@ -0,0 +1,25 @@
name: Add voting info to new issue
on:
issues:
types:
- opened
jobs:
add-voting-info:
runs-on: ubuntu-latest
permissions:
issues: write
steps:
- name: Append voting info to issue body
uses: julien-deramond/update-issue-body@v1
with:
issue-number: ${{ github.event.issue.number }}
body: |
> [!NOTE]
> You can use the 👍 reaction to increase the issue's priority for developers.
>
> Please note that only the 👍 reaction to the issue itself counts as a vote.
> Other reactions and those to comments will not be taken into account.
edit-mode: append
append-separator: newline
+15
View File
@@ -0,0 +1,15 @@
#!/bin/sh -l
set -e
pwd
uname -a
make -j4
./v version
du -s .
echo "DONE"
+25
View File
@@ -0,0 +1,25 @@
#!/bin/sh -l
set -e
pwd
uname -a
du -s .
ls -lat
##./v -silent test-all
## try running the known failing tests first to get faster feedback
./v vlib/builtin/string_test.v
./v vlib/strings/builder_test.v
./v -silent test-cleancode
./v -silent test-self
./v build-vbinaries
echo "DONE"
+67
View File
@@ -0,0 +1,67 @@
#!/usr/bin/env -S v
module main
import os
import vab.vxt
import vab.android.ndk
fn main() {
assert ndk.found()
assert vxt.found()
work_dir := os.join_path(os.vtmp_dir(), 'android_cross_compile_test')
os.rm(work_dir) or {}
os.mkdir_all(work_dir) or { panic(err) }
vexe := vxt.vexe()
examples_dir := os.join_path(vxt.home(), 'examples')
v_example := os.join_path(examples_dir, 'toml.v')
ndk_version := ndk.default_version()
sysroot_path := ndk.sysroot_path(ndk_version) or { panic(err) }
include_path := os.join_path(sysroot_path, 'usr', 'include')
android_include_path := os.join_path(include_path, 'android')
//'-I"${include_path}"'
cflags := ['-I"${android_include_path}"', '-Wno-unused-value', '-Wno-implicit-function-declaration',
'-Wno-int-conversion']
for arch in ndk.supported_archs {
for level in ['min', 'max'] {
compiler_api := match level {
'min' {
ndk.compiler_min_api(.c, ndk_version, arch) or { panic(err) }
}
'max' {
ndk.compiler_max_api(.c, ndk_version, arch) or { panic(err) }
}
else {
panic('invalid min/max level')
}
}
os.setenv('VCROSS_COMPILER_NAME', compiler_api, true)
c_file := os.join_path(work_dir, arch + '-' + level + '.c')
o_file := os.join_path(work_dir, arch + '-' + level + '.o')
// x.v -> x.c
v_compile_cmd := '${vexe} -o ${c_file} -os android -gc none ${v_example}'
vres := os.execute(v_compile_cmd)
if vres.exit_code != 0 {
panic('"${v_compile_cmd}" failed: ${vres.output}')
}
assert os.exists(c_file)
// x.c -> x.o
compile_cmd := '${compiler_api} ${cflags.join(' ')} -c ${c_file} -o ${o_file}'
cres := os.execute(compile_cmd)
if cres.exit_code != 0 {
panic('"${compile_cmd}" failed: ${cres.output}')
}
assert os.exists(o_file)
compiler_exe_name := os.file_name(compiler_api)
println('Compiled examples/toml.v successfully for (${level}) ${arch} ${compiler_exe_name}')
}
}
}
@@ -0,0 +1,29 @@
name: json decoder benchmark CI
on:
push:
branches:
- master
paths:
- 'vlib/x/json2/**' # Trigger on changes in this folder
jobs:
json-encode-benchmark:
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- name: Checkout repository
uses: actions/checkout@v7
- name: Build V
run: make -j4 && ./v symlink
- name: Run V benchmark and save output
run: (echo '```txt'; v -prod crun vlib/x/json2/tests/bench.v; echo '```') > vlib/x/json2/tests/bench_out.md
- name: Upload result file
uses: actions/upload-artifact@v7
with:
name: program-output
path: vlib/x/json2/tests/bench_out.md
@@ -0,0 +1,31 @@
name: json encoder benchmark CI
on:
push:
branches:
- master
paths:
- 'vlib/x/json2/**' # Trigger on changes in this folder
- '!vlib/x/json2/strict/**' # Ignore
- '!vlib/x/json2/tests/**' # Ignore
jobs:
json-encode-benchmark:
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- name: Checkout repository
uses: actions/checkout@v7
- name: Build V
run: make -j4 && ./v symlink
- name: Run V benchmark and save output
run: (echo '```sh'; v -prod crun vlib/v/tests/bench/bench_json_vs_json2.v; echo '```') > vlib/v/tests/bench/bench_json_vs_json2_out.md
- name: Upload result file
uses: actions/upload-artifact@v7
with:
name: program-output
path: vlib/v/tests/bench/bench_json_vs_json2_out.md
+135
View File
@@ -0,0 +1,135 @@
name: Bootstrapping CI
on:
workflow_dispatch:
push:
branches:
- master
paths-ignore:
- '**.yml'
- '**.md'
- '**.vv'
- '**.out'
- 'cmd/tools/**'
- '!cmd/tools/builders/**.v'
- '!cmd/tools/vup.v'
- '!**/bootstrapping_ci.yml'
pull_request:
paths-ignore:
- '**.yml'
- '**.md'
- '**.vv'
- '**.out'
- 'cmd/tools/**'
- '!cmd/tools/builders/**.v'
- '!cmd/tools/vup.v'
- '!**/bootstrapping_ci.yml'
concurrency:
group: bootstrapping-${{ github.workflow }}-${{ github.ref == 'refs/heads/master' && github.sha || github.ref }}
cancel-in-progress: true
jobs:
bootstrap-v:
strategy:
matrix:
os: [ubuntu-latest, macos-14]
fail-fast: false
runs-on: ${{ matrix.os }}
timeout-minutes: 20
env:
VFLAGS: -no-parallel
B_LFLAGS: -lm -lpthread
steps:
- uses: actions/checkout@v7
with:
fetch-depth: 0
- name: Build V
run: make -j4
- name: Test bootstrapping (v.c can be compiled and run with -os cross)
run: |
ls -la v vc/v.c
./v -os cross -o vc/v.c cmd/v
# shellcheck disable=SC2086
cc -o v_from_vc vc/v.c $B_LFLAGS
ls -lart v_from_vc
./v_from_vc version
./v_from_vc run examples/hello_world.v
./v_from_vc -o v_from_vc_produced_native_v cmd/v
./v_from_vc_produced_native_v run examples/hello_world.v
### the next make invocation will simulate building V from scratch
make local=1
ls -la v vc/v.c v_from_vc v_from_vc_produced_native_v
./v_from_vc_produced_native_v -os cross -o vc/v.c cmd/v
### do it a second time, just in case:
# shellcheck disable=SC2086
clang -o v_from_vc2 vc/v.c $B_LFLAGS
ls -lart v_from_vc2
./v_from_vc2 version
./v_from_vc2 run examples/hello_world.v
./v_from_vc2 -o v_from_vc_produced_native_v2 cmd/v
./v_from_vc_produced_native_v2 run examples/hello_world.v
make local=1
ls -la v vc/v.c
ls -la v_from_vc v_from_vc_produced_native_v
ls -la v_from_vc2 v_from_vc_produced_native_v2
- name: Ensure V master is available
if: github.ref_name != 'master'
run: git branch master remotes/origin/master
- name: Test `v up`
run: |
# Derive a commit sha from an older successful fast workflow on master that was able to build V.
# The workflow used below is `Path Testing CI` (18477644).
# Fetch several successful runs and pick the first commit that is actually reachable on master.
# Some runs may reference commits from force-pushed branches that are no longer on master.
fetch_page() {
local page="$1"
local body=""
for attempt in 1 2 3; do
body=$(curl -sL --max-time 30 \
-H "Accept: application/vnd.github+json" \
-H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" \
-H "X-GitHub-Api-Version: 2022-11-28" \
"https://api.github.com/repos/vlang/v/actions/workflows/18477644/runs?branch=master&status=success&event=push&per_page=10&page=$page")
if [ -n "$body" ] && echo "$body" | jq -e '.workflow_runs' >/dev/null 2>&1; then
echo "$body" | jq -r '.workflow_runs[].head_sha'
return 0
fi
echo "::warning::page $page attempt $attempt failed, retrying..." >&2
sleep 5
done
return 1
}
recent_good_commit=""
valid_count=0
for page in 1 2 3; do
commits=$(fetch_page "$page" || true)
commit_count=$(printf '%s\n' "$commits" | grep -c . || true)
echo "page $page: fetched $commit_count commits"
for sha in $commits; do
if git merge-base --is-ancestor "$sha" master 2>/dev/null; then
valid_count=$((valid_count + 1))
echo " valid #$valid_count: $sha"
# Skip the first few valid commits to get an older one for testing upgrades.
if [ "$valid_count" -ge 5 ]; then
recent_good_commit="$sha"
break 2
fi
fi
done
done
if [ -z "$recent_good_commit" ]; then
echo "Path Testing CI lookup yielded only $valid_count valid commits; falling back to git log."
recent_good_commit=$(git log master --first-parent --format=%H --before='14 days ago' -n 1)
fi
if [ -z "$recent_good_commit" ]; then
echo "Could not find a valid recent good commit on master"
exit 1
fi
echo "recent_good_commit=$recent_good_commit"
# Build oldv at recent_good_commit.
./v run cmd/tools/oldv.v -v "$recent_good_commit"
cd "$HOME/.cache/oldv/v_at_$recent_good_commit"
# Test updating
./v version && ./v -v up && ./v version
./v -o v2 cmd/v && ./v2 -o v3 cmd/v
+54
View File
@@ -0,0 +1,54 @@
name: CI Ubuntu 25 GCC 14.2
on:
workflow_dispatch:
push:
branches:
- master
paths-ignore:
- '**.md'
- '**.yml'
- '!**/build_on_ubuntu_25_ci.yml'
- 'cmd/tools/**'
- '!cmd/tools/builders/**.v'
pull_request:
paths-ignore:
- '**.md'
- '**.yml'
- '!**/build_on_ubuntu_25_ci.yml'
- 'cmd/tools/**'
- '!cmd/tools/builders/**.v'
jobs:
ubuntu-25-gcc-14-2-build:
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- uses: actions/checkout@v7
- name: Build and test in Ubuntu 25.04 with GCC 14.2
run: |
set -o xtrace
echo "$PWD"
whoami
touch outside_docker.txt
git log -n4
echo "running docker ..."
docker run --rm \
--mount type=bind,source=/home/runner/work/v/v,destination=/src \
-w /src ubuntu:25.04 bash -c '
set -o xtrace
echo "running inside docker"
whoami
cp -r /src ~/vproject; cd ~/vproject
touch inside_docker.txt
ls -la
git log -n4
apt update -y -qq
apt install -y -qq git build-essential make
git config --global --add safe.directory /src/vc
git config --global --add safe.directory /src/thirdparty/tcc
make
./v symlink
v run examples/hello_world.v
v run examples/primes.v
'
+56
View File
@@ -0,0 +1,56 @@
#!/usr/bin/env bash
set -e
V=$PWD/v
if [[ -x "$V" ]]
then
echo "The v executable exists."
else
echo "This script should be run from the top level folder of a V repository"
echo "i.e. the folder where your V executable is."
exit 1
fi
BUILD=$PWD/vinix_build
echo "Creating $BUILD folder..."
rm -rf $BUILD
mkdir -p $BUILD
cd $BUILD
echo "Clone current Vinix"
./v retry -- git clone --depth=1 https://github.com/vlang/vinix.git
cd $BUILD
echo "Clone current mlibc"
./v retry -- git clone --depth=1 https://github.com/managarm/mlibc.git
cd $BUILD
echo "Patch mlibc for Vinix"
cd mlibc
patch -p3 < ../vinix/patches/mlibc/mlibc.patch
cd $BUILD
echo "Install mlibc headers"
mkdir mlibc-build
cd mlibc-build
meson --cross-file ../vinix/cross_file.txt --prefix=/ -Dheaders_only=true ../mlibc
ninja
mkdir ../mlibc-headers
DESTDIR=`realpath ../mlibc-headers` ninja install
cd $BUILD
echo "Attempt to build the Vinix kernel (debug)"
cd vinix/kernel
make PROD=false CFLAGS="-D__vinix__ -O2 -g -pipe -I../../mlibc-headers/include"
make clean
cd $BUILD
echo "Attempt to build the Vinix kernel (prod)"
cd vinix/kernel
make PROD=true CFLAGS="-D__vinix__ -O2 -g -pipe -I../../mlibc-headers/include"
make clean
rm -rf $BUILD
+142
View File
@@ -0,0 +1,142 @@
name: C2V apps
on:
push:
branches:
- master
paths-ignore:
- '**.md'
- '**.yml'
- '!**/c2v_ci.yml'
- 'doc/**'
- 'examples/**'
- 'tutorials/**'
- 'cmd/tools/**'
- '!cmd/tools/builders/**.v'
pull_request:
paths-ignore:
- '**.md'
- '**.yml'
- '!**/c2v_ci.yml'
- 'doc/**'
- 'examples/**'
- 'tutorials/**'
- 'cmd/tools/**'
- '!cmd/tools/builders/**.v'
concurrency:
group: c2v-${{ github.workflow }}-${{ github.ref == 'refs/heads/master' && github.sha || github.ref }}
cancel-in-progress: true
jobs:
build-doom:
runs-on: ubuntu-24.04
timeout-minutes: 30
steps:
- uses: actions/checkout@v7
- uses: ./.github/actions/cache-apt-packages-action
- name: Build V
run: make && ./v symlink
- name: Set 8.8.8.8 as dns server
run: |
sudo sed -i 's/#DNS=/DNS=8.8.8.8 8.8.4.4/g' /etc/systemd/resolved.conf
sudo systemctl daemon-reload
sudo systemctl restart systemd-networkd
sudo systemctl restart systemd-resolved
dig distro.ibiblio.org
- name: Install C2V
run: |
v retry -- v install --git https://github.com/vlang/c2v
v -g ~/.vmodules/c2v/ || true
- name: Install dependencies
run: |
if [ "${{ runner.os }}" == "Linux" ]; then
.github/workflows/disable_azure_mirror.sh
v retry -- sudo apt update -y -qq
v retry -- sudo apt install libsdl2-dev libsdl2-mixer-dev libsdl2-net-dev libpng-dev libsamplerate0-dev
else
v retry -- brew install sdl2 sdl2_mixer sdl2_net libpng libsamplerate
fi
- name: Build original Chocolate Doom
run: |
v retry -- git clone --quiet --depth 1 https://github.com/vlang/doom ~/code/doom
cd ~/code/doom/chocolate-doom
cmake -DCMAKE_BUILD_TYPE=Debug .
make chocolate-doom
- name: Translate the whole game in project/folder mode and compile it
run: |
touch ~/DOOM1.WAD
WAD_FILE=~/DOOM1.WAD ~/code/doom/build_whole_project.sh
test-regression:
runs-on: ubuntu-24.04
timeout-minutes: 20
env:
VFLAGS: -cc tcc
DISPLAY: :99
LIBGL_ALWAYS_SOFTWARE: true
VTMP: /tmp
steps:
- uses: actions/checkout@v7
- uses: ./.github/actions/cache-apt-packages-action
- name: Build V
run: make && ./v symlink
- name: Set 8.8.8.8 as dns server
run: |
sudo sed -i 's/#DNS=/DNS=8.8.8.8 8.8.4.4/g' /etc/systemd/resolved.conf
sudo systemctl daemon-reload
sudo systemctl restart systemd-networkd
sudo systemctl restart systemd-resolved
dig distro.ibiblio.org
- name: Install C2V
run: |
v retry -- v install --git https://github.com/vlang/c2v
v -g ~/.vmodules/c2v/ || true
- name: Install dependencies
run: |
.github/workflows/disable_azure_mirror.sh
v retry -- sudo apt update -y -qq
v retry -- sudo apt install libsdl2-dev libsdl2-mixer-dev libsdl2-net-dev libpng-dev libsamplerate0-dev
# c2v / DOOM dependencies
# vgret dependencies
# imagemagick : convert, mogrify, import
# xvfb : For starting X11 Virtual FrameBuffers
# openimageio-tools : idiff
# libgl1-mesa-dri : For headless rendering / software DRI driver (LIBGL_ALWAYS_SOFTWARE=true)
# freeglut3-dev : Fixes graphic apps compilation with tcc
v retry -- sudo apt install imagemagick openimageio-tools freeglut3-dev libgl1-mesa-dri xvfb xsel xclip
- name: Setup test tools
run: |
# Fetch the free ~4MB DOOM1.WAD from the link at https://doomwiki.org/wiki/DOOM1.WAD
v retry -- v download https://distro.ibiblio.org/slitaz/sources/packages/d/doom1.wad
mv doom1.wad ~/doom1.wad
# Get imgur upload script
v retry -- v download https://raw.githubusercontent.com/tremby/imgur.sh/c98345d/imgur.sh
chmod +x ./imgur.sh
# Get regression images to test against
v retry -- git clone https://github.com/Larpon/doom-regression-images
- name: Build original Chocolate Doom
run: |
v retry -- git clone --quiet --depth 1 https://github.com/vlang/doom ~/code/doom
cd ~/code/doom/chocolate-doom
cmake -DCMAKE_BUILD_TYPE=Debug .
make chocolate-doom
- name: Translate the whole game in project/folder mode
run: WAD_FILE=~/doom1.wad ~/code/doom/build_whole_project.sh
- name: Sample and compare with vgret
id: compare
continue-on-error: true
run: |
Xvfb "$DISPLAY" -screen 0 800x600x24 -fbdir /var/tmp/ &
sleep 2; while [ ! -f /var/tmp/Xvfb_screen0 ]; do sleep 0.5; done # give xvfb time to start, even on slow CI runs
sleep 5; v gret -r ~/code/doom -t ./doom-regression-images/vgret.doom.toml -v ./doom-sample_images ./doom-regression-images
- name: Upload regression to imgur
if: steps.compare.outcome != 'success'
run: |
./imgur.sh /tmp/fail.png
./imgur.sh /tmp/diff.png
exit 1
+171
View File
@@ -0,0 +1,171 @@
import os
import time
const compare_prod = '-prod' in os.args
const cleanup_tmp = '-no-cleanup' !in os.args
const fetch_remote = '-no-fetch' !in os.args
fn gbranch() string {
return os.execute(r'git branch --list|grep ^\*').output.trim_left('* ').trim_space()
}
fn gcommit() string {
return os.execute(r'git rev-parse --short=7 HEAD').output.trim_left('* ').trim_space()
}
fn r(cmd string) {
res := os.system(cmd)
if res != 0 {
eprintln('> failed running: `${cmd}`')
exit(1)
}
}
fn xtime(cmd string) {
$if linux {
r('/usr/bin/time -f "CPU: %Us\tReal: %es\tElapsed: %E\tRAM: %MKB\t%C" ${cmd}')
return
}
$if macos {
r('/opt/homebrew/bin/gtime -f "CPU: %Us\tReal: %es\tElapsed: %E\tRAM: %MKB\t%C" ${cmd}')
return
}
// Pure V fallback - no memory stats, but better than nothing ...
before := time.now()
r(cmd)
after := time.now()
delta_time := after - before
println('> Elapsed time: ${delta_time.milliseconds()} ms, for cmd: ${cmd}')
}
fn show_size(fpath string) {
println('>Size of ${fpath:20s}: ${os.file_size(fpath):10}')
}
fn compare_size(fpath1 string, fpath2 string) {
size1 := os.file_size(fpath1)
size2 := os.file_size(fpath2)
diff_ := i64(size2) - i64(size1)
println('>>>>>> size("${fpath2:17}") - size("${fpath1:17}") = ${size2:10} - ${size1:10} = ${diff_:10}')
}
fn vcompare(vold string, vnew string) {
r("v repeat --nmaxs 7 -R 3 '${vold} -check-syntax examples/hello_world.v' '${vnew} -check-syntax examples/hello_world.v'")
r("v repeat --nmaxs 7 -R 3 '${vold} -check examples/hello_world.v' '${vnew} -check examples/hello_world.v'")
r("v repeat --nmaxs 7 -R 3 '${vold} -no-parallel -o ohw.c examples/hello_world.v' '${vnew} -no-parallel -o nhw.c examples/hello_world.v'")
compare_size('ohw.c', 'nhw.c')
r("v repeat --nmaxs 7 -R 3 '${vold} -no-parallel -o ohw.exe examples/hello_world.v' '${vnew} -no-parallel -o nhw.exe examples/hello_world.v'")
compare_size('ohw.exe', 'nhw.exe')
r("v repeat --nmaxs 7 -R 3 '${vold} -check-syntax cmd/v' '${vnew} -check-syntax cmd/v'")
r("v repeat --nmaxs 7 -R 3 '${vold} -check cmd/v' '${vnew} -check cmd/v'")
r("v repeat --nmaxs 7 -R 3 '${vold} -no-parallel -o ov.c cmd/v' '${vnew} -no-parallel -o nv.c cmd/v'")
compare_size('ov.c', 'nv.c')
r("v repeat --nmaxs 7 -R 3 '${vold} -no-parallel -o ov.exe cmd/v' '${vnew} -no-parallel -o nv.exe cmd/v'")
compare_size('ov.exe', 'nv.exe')
}
fn hline(header_message string) {
println('='.repeat(98))
println(header_message)
}
fn main() {
// The starting point, when this program should be started, is just after `gh pr checkout NUMBER`.
start := time.now()
pr_branch := gbranch()
pr_commit := gcommit()
hline('Current git branch: ${pr_branch}, commit: ${pr_commit}')
println(' Compiling new V executables from PR branch: ${pr_branch}, commit: ${pr_commit} ...')
// *not* using v self here is deliberate, so that the `v` executable itself, is not changed after running this script
xtime('./v -o vnew1 cmd/v')
xtime('./vnew1 -o vnew2 cmd/v')
xtime('./vnew2 -no-parallel -o vnew cmd/v')
xtime('./vnew -no-parallel -o nhw_current.c examples/hello_world.v')
xtime('./vnew -no-parallel -o nhw_current_gcc.c -cc gcc examples/hello_world.v')
xtime('./vnew -no-parallel -o nv_current.c cmd/v')
if compare_prod {
xtime('./vnew -no-parallel -prod -o vnew_prod cmd/v')
}
show_size('nhw_current.c')
show_size('nhw_current_gcc.c')
show_size('nv_current.c')
show_size('vnew')
if compare_prod {
show_size('vnew_prod')
}
r('rm -rf vnew1 vnew2')
if fetch_remote {
// make sure to always compare against the main V repo's master branch by default:
os.execute('git -C . remote add V_REPO https://github.com/vlang/v.git')
os.execute('git -C . fetch V_REPO')
os.execute('git branch -D v_repo_master')
os.execute('git branch -f --track v_repo_master V_REPO/master')
}
r('git checkout v_repo_master')
master_branch := gbranch()
hline(' Compiling old V executables from branch: ${master_branch}, commit: ${gcommit()} ...')
// Use `make` to bootstrap the old V from the C sources on the master branch,
// because the new V compiler may have breaking changes that prevent it from
// compiling the old code directly.
xtime('make -j4')
xtime('./v -o vold1 cmd/v')
xtime('./vold1 -no-parallel -o vold cmd/v')
xtime('./vold -no-parallel -o ohw_master.c examples/hello_world.v')
xtime('./vold -no-parallel -o ohw_master_gcc.c -cc gcc examples/hello_world.v')
xtime('./vold -no-parallel -o ov_master.c cmd/v')
if compare_prod {
xtime('./vold -no-parallel -prod -o vold_prod cmd/v')
show_size('vold_prod')
}
show_size('ohw_master.c')
show_size('ohw_master_gcc.c')
show_size('ov_master.c')
show_size('vold')
if compare_prod {
show_size('vold_prod')
}
r('rm -rf vold1')
hline('File sizes so far ...')
compare_size('ohw_master.c', 'nhw_current.c')
compare_size('ohw_master_gcc.c', 'nhw_current_gcc.c')
compare_size('ov_master.c', 'nv_current.c')
compare_size('vold', 'vnew')
r('git checkout ${pr_branch}')
// we are on the PR branch again
hline(' Measuring at PR branch: ${pr_branch}, commit: ${gcommit()} ...')
if compare_prod {
vcompare('./vold_prod', './vnew_prod')
} else {
vcompare('./vold', './vnew')
}
println('Done. Total time: ${(time.now() - start).seconds()} s.')
hline('Final summary for file diff sizes on their own branches:')
compare_size('ohw_master.c', 'nhw_current.c')
compare_size('ohw_master_gcc.c', 'nhw_current_gcc.c')
compare_size('ov_master.c', 'nv_current.c')
compare_size('vold', 'vnew')
if compare_prod {
compare_size('vold_prod', 'vnew_prod')
}
hline('Final summary for file diff sizes for generated files on the *current* branch:')
compare_size('ohw.c', 'nhw.c')
compare_size('ov.c', 'nv.c')
compare_size('ohw.exe', 'nhw.exe')
compare_size('ov.exe', 'nv.exe')
// After all the measurements are done, delete all the generated temporary files,
// except the `vold` and `vnew` compilers, so that they can be used later in manual
// experiments:
if cleanup_tmp {
r('rm -rf ohw* nhw* nv* ov*')
}
}
+25
View File
@@ -0,0 +1,25 @@
#!/usr/bin/env bash
set -e
function show() {
printf "\u001b[35m$1\u001b[0m\n"
}
## NOTE: this step is disabled in v_apps_and_modules_compile_ci.yml via `${{ false && ... }}`.
## Reason: discord.v uses x.json2.raw_decode which was deprecated-as-error in V on 2025-10-10.
## The upstream repo (vcv88/discord.v) has not been updated since Dec 2024.
## Re-enable both the yml step and this script once vcv88/discord.v#21 is resolved.
## Track: https://github.com/vlang/v/issues/26853
rm -rf discord/
show "Clone https://github.com/vcv88/discord.v"
v retry -- git clone --filter=blob:none --quiet https://github.com/vcv88/discord.v discord/
cd discord/
show "Checkout last known good commit"
git checkout ce9ff457fce92d5bb15df2974440cd8292457ee0
show "Execute Tests"
v test .
cd ..
rm -rf discord/
+47
View File
@@ -0,0 +1,47 @@
#!/usr/bin/env bash
set -e
function show() {
printf "\u001b[35m$1\u001b[0m\n"
}
rm -rf herolib/
show "Clone https://github.com/freeflowuniverse/herolib"
v retry -- git clone --filter=blob:none --quiet https://github.com/freeflowuniverse/herolib herolib
cd herolib
git checkout development
mkdir -p ~/.vmodules/freeflowuniverse
ln -s $(pwd)/lib ~/.vmodules/freeflowuniverse/herolib
cd cli
show "Checkout last known good commit"
git checkout ca8799af39228a5678a7be81128c5b0c342c9efc
v wipe-cache
show "Build project no parallel (gcc)"
v -cc gcc -cg -enable-globals -w -n hero.v
show "Checking build"
ls -l ./hero
v wipe-cache
show "Build project no parallel (clang)"
v -cc clang -cg -enable-globals -w -n hero.v
show "Checking build"
ls -l ./hero
v wipe-cache
show "Build project with -parallel-cc (clang)"
v -cc clang -cg -enable-globals -parallel-cc -w -n hero.v
show "Checking gcc build"
ls -l ./hero
v wipe-cache
show "Build project with -parallel-cc (gcc)"
v -cc gcc -cg -enable-globals -parallel-cc -w -n hero.v
show "Checking clang build"
ls -l ./hero
rm -rf ../../herolib
@@ -0,0 +1,7 @@
#!/usr/bin/env bash
for f in examples/sokol/*/ ; do
echo "compiling shaders for $f ...";
time ./v shader $f;
echo "done";
done;
+47
View File
@@ -0,0 +1,47 @@
#!/usr/bin/env bash
set -ex
function show() {
printf "\u001b[35m$1\u001b[0m\n"
}
show "Prepare"
rm -rf vtcc/
show "Clone vtcc"
.github/workflows/retry.sh git clone https://github.com/medvednikov/vtcc --branch stable --quiet vtcc/
du -s vtcc/
show "Compile vtcc"
cd vtcc/
v run make.vsh
cd ..
ls -la vtcc/vtcc
./vtcc/vtcc --version
show "Generate the C file, for the current V version"
./v -o vlang.c cmd/v
ls -la vlang.c
if [[ "$(uname)" == "Darwin" ]]; then
show "Compile the C file with vtcc (object only, vtcc targets x86_64 ELF)"
SDK_PATH="$(xcrun --show-sdk-path)"
./vtcc/vtcc -c vlang.c -o vlang.o -I"${SDK_PATH}/usr/include"
ls -la vlang.o
rm -rf vlang.o vlang.c vtcc/
else
show "Compile the C file with vtcc"
./vtcc/vtcc -o v_compiled_with_vtcc vlang.c -lpthread
ls -la v_compiled_with_vtcc
show "Test the resulting V compiler"
./v_compiled_with_vtcc version
show "Compile and run hello with vtcc"
./v_compiled_with_vtcc -cc vtcc/vtcc -showcc run examples/hello_world.v
show "Remove the generated temporary files, so the script can be re-run cleanly"
rm -rf v_compiled_with_vtcc vlang.c vtcc/
fi
+29
View File
@@ -0,0 +1,29 @@
#!/usr/bin/env bash
set -e
function show() {
printf "\u001b[35m$1\u001b[0m\n"
}
rm -rf ~/.vmodules/gui/ ~/.vmodules/vglyph/
export VJOBS=1
show "Clone https://github.com/vlang/vglyph"
v retry -- git clone --filter=blob:none --quiet https://github.com/vlang/vglyph ~/.vmodules/vglyph/
show "Use latest vlang/vglyph commit"
git -C ~/.vmodules/vglyph/ log -1 --oneline
show "Clone https://github.com/vlang/gui"
v retry -- git clone --filter=blob:none --quiet https://github.com/vlang/gui ~/.vmodules/gui/
show "Use latest vlang/gui commit"
git -C ~/.vmodules/gui/ log -1 --oneline
if [[ "$(uname)" == 'Darwin' ]]; then
export VFLAGS="${VFLAGS:-} -cc clang"
fi
show "Check module for syntax and semantic errors"
v -shared -check ~/.vmodules/gui
show "Execute Tests"
v test ~/.vmodules/gui/
show "Compile Examples"
v should-compile-all -no-parallel ~/.vmodules/gui/examples/
rm -rf ~/.vmodules/gui/ ~/.vmodules/vglyph/
+140
View File
@@ -0,0 +1,140 @@
name: Cross CI
on:
push:
branches:
- master
paths-ignore:
- '**.md'
- '**.yml'
- '!**/cross_ci.yml'
- 'cmd/tools/**'
- '!cmd/tools/builders/**.v'
pull_request:
paths-ignore:
- '**.md'
- '**.yml'
- '!**/cross_ci.yml'
- 'cmd/tools/**'
- '!cmd/tools/builders/**.v'
concurrency:
group: cross-${{ github.workflow }}-${{ github.ref == 'refs/heads/master' && github.sha || github.ref }}
cancel-in-progress: true
jobs:
cross-macos:
runs-on: macos-latest
timeout-minutes: 20
env:
VFLAGS: -cc clang
steps:
- uses: actions/checkout@v7
with:
fetch-depth: 10
- name: Cache Homebrew downloads
uses: actions/cache@v5
with:
path: ~/Library/Caches/Homebrew
key: brew-cross-macos-${{ hashFiles('.github/workflows/cross_ci.yml') }}
restore-keys: |
brew-cross-macos-
- name: Build V
run: make -j4 && ./v symlink
- name: Install dependencies
run: |
./v retry -- brew install mingw-w64
export LIBRARY_PATH="$LIBRARY_PATH:/usr/local/opt/openssl/lib/"
- name: Test symlink
run: ./v symlink
- name: Cross-compilation to Linux
run: |
./v -os linux cmd/v
# TODO: fix this: ./v -os linux examples/2048/2048.v
- name: Cross-compilation of veb app to Linux with -d use_openssl
run: ./v -d use_openssl -os linux examples/veb/veb_example.v
- name: Cross-compilation of vlang/gitly to Linux with -d use_openssl
run: |
./v retry -- ./v install markdown
./v retry -- ./v install pcre
./v retry -- git clone --depth 1 https://github.com/vlang/gitly /tmp/gitly
./v -d use_openssl -os linux /tmp/gitly
file /tmp/gitly/gitly
- name: Cross-compilation to Windows
run: |
./v -os windows cmd/v
./v -os windows examples/2048/2048.v
cross-linux:
runs-on: ubuntu-24.04
timeout-minutes: 20
env:
VFLAGS: -cc tcc -no-retry-compilation
steps:
- uses: actions/checkout@v7
with:
fetch-depth: 10
- uses: ./.github/actions/cache-apt-packages-action
- name: Build v
run: make -j4 && ./v symlink
- name: Install dependencies
run: |
.github/workflows/disable_azure_mirror.sh
./v retry -- sudo apt update -y -qq
./v retry -- sudo apt install --quiet -y mingw-w64 wine wine64 winetricks libssl-dev sqlite3 libsqlite3-dev
- name: Show diagnostics for wine
run: |
which wine
# shellcheck disable=SC2046
ls -la $(realpath $(which wine))
- name: v.c can be compiled and run with -os cross
run: |
./v -os cross -o /tmp/v.c cmd/v
gcc -g -std=gnu11 -w -o v_from_vc /tmp/v.c -lm -lpthread
ls -lart v_from_vc
./v_from_vc version
- name: v_win.c can be compiled and run with -os windows
run: |
./v -cc msvc -os windows -o /tmp/v_win.c cmd/v
x86_64-w64-mingw32-gcc /tmp/v_win.c -std=c99 -w -municode -o v_from_vc.exe -lws2_32 -Wl,-stack=33554432
ls -lart v_from_vc.exe
wine ./v_from_vc.exe version
- name: hello_world.v can be cross compiled to hello_world.exe
run: |
./v -os windows examples/hello_world.v
ls -lart examples/hello_world.exe
wine examples/hello_world.exe
- name: 2048.v can be cross compiled to 2048.exe
run: |
./v -os windows examples/2048/2048.v
ls -lart examples/2048/2048.exe
cross-windows:
runs-on: windows-2025
timeout-minutes: 20
steps:
- uses: actions/checkout@v7
- name: Build
run: |
echo %VFLAGS%
echo $VFLAGS
.\makev.bat -msvc
- name: TODO v_win.c can be compiled and run with -os windows
run: |
.\v.exe -os windows -cc msvc -showcc -o v2.exe cmd\v
.\v.exe -os windows -cc msvc -o v_win.c cmd\v
dir v2.exe
dir v_win.c
.\v2.exe version
+117
View File
@@ -0,0 +1,117 @@
name: Database CI
on:
workflow_dispatch:
push:
branches:
- master
paths-ignore:
- '**.md'
- '**.yml'
- '!**/db_ci.yml'
- 'examples/**'
- 'doc/**'
pull_request:
paths-ignore:
- '**.md'
- '**.yml'
- '!**/db_ci.yml'
- 'examples/**'
- 'doc/**'
concurrency:
group: db-${{ github.workflow }}-${{ github.ref == 'refs/heads/master' && github.sha || github.ref }}
cancel-in-progress: true
jobs:
mysql-driver-tests:
runs-on: ubuntu-24.04
timeout-minutes: 30
services:
mysql:
image: mysql:8.0
env:
MYSQL_ROOT_PASSWORD: 12345678
MYSQL_ROOT_HOST: '%'
ports:
- 3306:3306
options: >-
--health-cmd="mysqladmin ping -h 127.0.0.1 -uroot -p12345678"
--health-interval=10s
--health-timeout=5s
--health-retries=24
steps:
- uses: actions/checkout@v7
- name: Build V
run: make -j4 && ./v symlink
- name: Install mysql client headers
run: |
.github/workflows/disable_azure_mirror.sh
./v retry -- sudo apt update
./v retry -- sudo apt install --quiet -y libmariadb-dev
- name: Run mysql driver tests
run: ./v -d network -d started_mysqld -silent test vlib/db/mysql/
postgres-driver-tests:
runs-on: ubuntu-24.04
timeout-minutes: 30
services:
postgres:
image: postgres:16
env:
POSTGRES_PASSWORD: 12345678
ports:
- 5432:5432
options: >-
--health-cmd="pg_isready -U postgres -d postgres"
--health-interval=10s
--health-timeout=5s
--health-retries=24
steps:
- uses: actions/checkout@v7
- name: Build V
run: make -j4 && ./v symlink
- name: Install postgres client headers
run: |
.github/workflows/disable_azure_mirror.sh
./v retry -- sudo apt update
./v retry -- sudo apt install --quiet -y libpq-dev
- name: Run postgres driver tests
run: ./v -d network -d started_postgres -silent test vlib/db/pg/
mssql-driver-tests:
runs-on: ubuntu-24.04
timeout-minutes: 30
services:
mssql:
image: mcr.microsoft.com/mssql/server:2022-latest
env:
ACCEPT_EULA: Y
MSSQL_PID: Developer
MSSQL_SA_PASSWORD: Vlang12345678!
ports:
- 1433:1433
steps:
- uses: actions/checkout@v7
- name: Build V
run: make -j4 && ./v symlink
- name: Install ODBC dependencies
run: |
.github/workflows/disable_azure_mirror.sh
[ -f /usr/share/keyrings/microsoft-prod.gpg ] || curl -fsSL https://packages.microsoft.com/keys/microsoft.asc | sudo gpg --batch --no-tty --dearmor -o /usr/share/keyrings/microsoft-prod.gpg
curl -fsSL https://packages.microsoft.com/config/ubuntu/24.04/prod.list | sudo tee /etc/apt/sources.list.d/mssql-release.list
./v retry -- sudo apt update
sudo ACCEPT_EULA=Y apt install --quiet -y msodbcsql18 unixodbc-dev
- name: Wait for sql server
run: |
for _ in $(seq 1 60); do
if (echo > /dev/tcp/127.0.0.1/1433) >/dev/null 2>&1; then
exit 0
fi
sleep 2
done
exit 1
- name: Run mssql driver tests
env:
VMSSQL_CONN_STR: 'Driver={ODBC Driver 18 for SQL Server};Server=127.0.0.1;Port=1433;UID=sa;PWD=Vlang12345678!;Database=master;TrustServerCertificate=yes'
run: ./v -d network -d started_mssql -silent test vlib/db/mssql/
+40
View File
@@ -0,0 +1,40 @@
name: Debug CI
on: [workflow_dispatch]
jobs:
debug-msvc:
runs-on: windows-2025
timeout-minutes: 121
env:
VFLAGS: -cc msvc
steps:
- uses: actions/checkout@v7
- name: Build
run: |
echo %VFLAGS%
echo $VFLAGS
.\makev.bat -msvc
.\v.exe -cflags /WX self
- name: Install dependencies
run: |
.\v.exe setup-freetype
.\.github\workflows\windows-install-sqlite.bat
- name: v doctor
run: ./v doctor
- name: Verify `v test` works
run: |
./v cmd/tools/test_if_v_test_system_works.v
./cmd/tools/test_if_v_test_system_works
- name: All code is formatted
run: ./v -silent test-cleancode
- name: Self tests
run: ./v -silent test-self
- name: Test v->js
run: ./v -o hi.js examples/js_hello_world.v && node hi.js
- name: Test v binaries
run: ./v build-vbinaries
- name: Build examples
run: ./v -silent build-examples
- name: v2 self compilation
run: .\v.exe -o v2.exe cmd/v && .\v2.exe -o v3.exe cmd/v
+17
View File
@@ -0,0 +1,17 @@
#!/bin/bash
echo "APT MIRRORS BEFORE:"; cat /etc/apt/apt-mirrors.txt
sudo sed -i 's@http://azure.archive.ubuntu.com@http://archive.ubuntu.com@gm' /etc/apt/apt-mirrors.txt
echo "APT MIRRORS AFTER:"; cat /etc/apt/apt-mirrors.txt
echo "ls -la /etc/apt/sources.list.d/"; ls -la /etc/apt/sources.list.d/
for f in /etc/apt/sources.list.d/*; do echo "####### $f ######"; cat $f; done
for f in /etc/apt/sources.list.d/azure-cli.*; do
if [ -f "$f" ]; then
echo "DISABLE OPTIONAL APT SOURCE: $f"
sudo mv "$f" "$f.disabled"
fi
done
echo "APT SOURCES BEFORE:"; echo "ls -la /etc/apt/sources.list"; ls -la /etc/apt/sources.list; cat /etc/apt/sources.list
sudo sed -i 's@http://azure.archive.ubuntu.com@http://archive.ubuntu.com@gm' /etc/apt/sources.list
echo "APT SOURCES AFTER:"; echo "ls -la /etc/apt/sources.list"; ls -la /etc/apt/sources.list; cat /etc/apt/sources.list
+102
View File
@@ -0,0 +1,102 @@
name: Docker CI
on:
push:
branches:
- master
paths-ignore:
- '**.md'
- '**.yml'
- '!**/docker_ci.yml'
- 'cmd/tools/**'
- '!cmd/tools/builders/**.v'
pull_request:
paths-ignore:
- '**.md'
- '**.yml'
- '!**/docker_ci.yml'
- 'cmd/tools/**'
- '!cmd/tools/builders/**.v'
concurrency:
group: docker-${{ github.workflow }}-${{ github.ref == 'refs/heads/master' && github.sha || github.ref }}
cancel-in-progress: true
env:
V_CI_MUSL: 1
jobs:
docker-alpine-musl-gcc:
runs-on: ubuntu-24.04
timeout-minutes: 241
container:
image: thevlang/vlang:alpine-build
env:
VFLAGS: -cc gcc
volumes:
- ${{github.workspace}}:/opt/vlang
steps:
- name: Checkout
uses: actions/checkout@v7
- name: Show Environment
run: |
echo "PWD:"
pwd
echo "ENVIRONMENT:"
env
echo "C Compiler:"
gcc --version
- name: Add dependencies
run: apk add libc6-compat gcompat gc gc-dev binutils diffutils elfutils
- name: Build V
run: CC=gcc make
- name: All code is formatted
run: ./v -silent test-cleancode
- name: Run only essential tests
run: VTEST_JUST_ESSENTIAL=1 ./v -silent test-self
docker-alpine-musl-tcc:
runs-on: ubuntu-24.04
timeout-minutes: 241
container:
image: thevlang/vlang:alpine-build
volumes:
- ${{github.workspace}}:/opt/vlang
steps:
- name: Checkout
uses: actions/checkout@v7
- name: Add dependencies
run: apk add musl-dev libatomic_ops-dev libatomic openssl libc6-compat gcompat gc gc-dev binutils diffutils elfutils
- name: Build V
run: make
- name: Check if vpm compiles with tcc
run: ./v -show-c-output -showcc -no-retry-compilation -cc tcc cmd/tools/vpm
- name: Run only builtin and math tests
run: ./v test vlib/builtin
docker-ubuntu-musl:
runs-on: ubuntu-24.04
timeout-minutes: 121
container:
image: thevlang/vlang:ubuntu-build
env:
V_CI_UBUNTU_MUSL: 1
VFLAGS: -cc musl-gcc -gc none
volumes:
- ${{github.workspace}}:/opt/vlang
steps:
- name: Checkout
uses: actions/checkout@v7
- name: Build V
run: echo "$VFLAGS" && make -j4 && ./v -cg -o v cmd/v
- name: Verify `v test` works
run: |
echo "$VFLAGS"
./v cmd/tools/test_if_v_test_system_works.v
./cmd/tools/test_if_v_test_system_works
- name: Add dependencies
run: apt install libsqlite3-dev
- name: All code is formatted
run: ./v -silent test-cleancode
- name: Test V fixed tests
run: ./v -silent test-self vlib
+86
View File
@@ -0,0 +1,86 @@
name: Docs CI
### Run on *EVERY* .v or .md related commit.
### The documentation *SHOULD* stay valid, and the developers should receive
### early warning, if they break it.
on:
push:
branches:
- master
paths-ignore:
- '**.yml'
- '!**/docs_ci.yml'
- 'cmd/tools/vrepl.v'
pull_request:
paths-ignore:
- '**.yml'
- '!**/docs_ci.yml'
- 'cmd/tools/vrepl.v'
concurrency:
group: docs-${{ github.workflow }}-${{ github.ref == 'refs/heads/master' && github.sha || github.ref }}
cancel-in-progress: true
jobs:
check-markdown:
runs-on: ubuntu-24.04
timeout-minutes: 20
steps:
- uses: actions/checkout@v7
- uses: ./.github/actions/cache-apt-packages-action
- name: Build V
run: make
- name: Install dependencies (some examples show how to use sqlite and the x11 clipboard)
run: ./v retry -- sudo apt install --quiet -y libx11-dev libssl-dev sqlite3 libsqlite3-dev
- name: Check markdown line length & code examples
run: ./v check-md -hide-warnings .
## NB: -hide-warnings is used here, so that the output is less noisy,
## thus real errors are easier to spot.
report-missing-fn-doc:
runs-on: ubuntu-24.04
timeout-minutes: 5
env:
MOPTIONS: --diff --deprecated --relative-paths --exclude /vlib/v/ --exclude /vlib/v2_toberemoved/ --exclude /builtin/linux_bare/ --exclude /testdata/ --exclude /tests/ --exclude /vlib/sokol/ --exclude /vlib/x/
steps:
- uses: actions/checkout@v7
- name: Build V
run: make
- name: Checkout previous v
uses: actions/checkout@v7
with:
repository: vlang/v
ref: master
path: pv
- name: Check against parent commit
run: |
# shellcheck disable=SC2086
./v missdoc $MOPTIONS pv/vlib vlib
report-missing-dots-in-doc-comments:
runs-on: ubuntu-24.04
timeout-minutes: 20
steps:
- uses: actions/checkout@v7
- name: Build V
run: make
- name: Check doc comment dots for some key modules
run: ./v run cmd/tools/find_doc_comments_with_no_dots.v \
vlib/builtin/ vlib/arrays/ vlib/flag/ \
vlib/bitfield/ vlib/term/ vlib/strings/ \
vlib/rand/ vlib/compress/ vlib/clipboard/ \
vlib/time/ \
vlib/os
report-wrong-examples-in-doc-comments:
runs-on: ubuntu-24.04
timeout-minutes: 20
steps:
- uses: actions/checkout@v7
- name: Build V
run: make
- name: Check examples in the doc comments for all vlib modules
run: VJOBS=1 ./v doc -check-examples -f none vlib/
+114
View File
@@ -0,0 +1,114 @@
name: docs.vlang.io deploy
### Regenerate https://docs.vlang.io/ (the GitHub Pages site served from the
### `main` branch of https://github.com/vlang/docs ), on every change to
### doc/docs.md that lands on master.
###
### Historically docs.vlang.io was updated by the FreeBSD machine that also runs
### cmd/tools/fast/fast.v . When that single machine stops, the site silently
### goes stale (see issue #27038, where it was stuck at the 2026-02-09 snapshot).
### Generating and deploying from CI removes that single point of failure, the
### same way modules.vlang.io is deployed from module_docs_ci.yml .
on:
workflow_dispatch:
push:
branches:
- master
paths:
- 'doc/docs.md'
- '**/docs_site_ci.yml'
# Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued.
# However, do NOT cancel in-progress runs as we want to allow these production deployments to complete.
concurrency:
group: docs_site-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: ${{ !contains(github.ref, 'master')}}
jobs:
deploy-docs-site:
runs-on: ubuntu-latest
timeout-minutes: 20
steps:
- uses: actions/checkout@v7
- uses: ./.github/actions/cache-apt-packages-action
- name: Build V
run: make -j4 && ./v symlink
- name: Install dependencies (the docs generator uses the markdown module)
run: ./v retry -- ./v install markdown
- name: Generate the HTML pages from doc/docs.md
run: |
set -e
# The generator (the `generator` branch of vlang/docs) fetches
# doc/docs.md from the master branch of vlang/v, transforms it into one
# HTML page per section, and writes them into its own output/ folder.
rm -rf docs_generator
./v retry -- git clone --depth=1 --branch generator https://github.com/vlang/docs docs_generator
./v run docs_generator/.
[ -f docs_generator/output/introduction.html ]
- name: Deploy to vlang/docs (main branch -> docs.vlang.io)
if: github.event_name != 'pull_request' && github.repository == 'vlang/v' && github.ref == 'refs/heads/master'
run: |
set -e
git config --global user.email "vlang-bot@users.noreply.github.com"
git config --global user.name "vlang-bot"
COMMIT_HASH="$(git rev-parse --short HEAD)"
COMMIT_MSG="$(git log -1 --pretty='%s' HEAD)"
rm -rf docs_site
./v retry -- git clone --depth=1 --branch main "https://vlang-bot:${{ secrets.VLANG_BOT_SECRET }}@github.com/vlang/docs.git" docs_site
# The legacy FreeBSD uploader (cmd/tools/fast/fast.v) may still be
# pushing to vlang/docs main too, so our push can be rejected as
# non-fast-forward. `v retry` would only rerun the same push, never
# fetching the new tip, so retry here by re-syncing onto the latest main
# and pushing again. The sync is idempotent, so re-applying it on top of
# whatever landed meanwhile is safe.
deploy_attempts=5
for attempt in $(seq 1 "${deploy_attempts}"); do
git -C docs_site fetch --depth=1 origin main
git -C docs_site reset --hard FETCH_HEAD
# Sync the freshly generated pages onto the published site. --delete so
# that pages/assets removed or renamed in doc/docs.md do not linger as
# stale files, but protect the site-only files at the repo root that the
# generator does not produce (git metadata, CNAME, .nojekyll, README.md,
# favicon.ico and the legacy build.vsh).
rsync -a --delete \
--exclude '/.git' \
--exclude '/.gitattributes' \
--exclude '/.gitignore' \
--exclude '/.nojekyll' \
--exclude '/CNAME' \
--exclude '/README.md' \
--exclude '/favicon.ico' \
--exclude '/build.vsh' \
docs_generator/output/ docs_site/
git -C docs_site add -A
# `git diff --cached --quiet` exits 0 with nothing staged, 1 when there
# are staged changes, and >1 on a real error - so only 1 means "deploy".
set +e
git -C docs_site diff --cached --quiet
diff_rc=$?
set -e
if [ "${diff_rc}" -eq 0 ]; then
echo "docs.vlang.io is already up to date for ${COMMIT_HASH}; nothing to deploy."
exit 0
elif [ "${diff_rc}" -ne 1 ]; then
echo "::error::git diff --cached failed with exit code ${diff_rc}" >&2
exit "${diff_rc}"
fi
git -C docs_site commit -m "update docs for commit ${COMMIT_HASH} - ${COMMIT_MSG}"
if git -C docs_site push origin main; then
echo "docs.vlang.io updated for ${COMMIT_HASH} (attempt ${attempt})."
exit 0
fi
echo "push to vlang/docs main was rejected (attempt ${attempt}/${deploy_attempts}); refetching and retrying..."
done
echo "::error::could not push to vlang/docs main after ${deploy_attempts} attempts" >&2
exit 1
@@ -0,0 +1,20 @@
#!/usr/bin/env bash
set -ex
rm -rf vlib/toml/tests/testdata/iarna vlib/toml/tests/testdata/toml_rs vlib/toml/tests/testdata/toml_lang vlib/toml/tests/testdata/large_toml_file_test.toml
./v retry -- ./v download -o vlib/toml/tests/testdata/large_toml_file_test.toml https://gist.githubusercontent.com/Larpon/89b0e3d94c6903851ff15559e5df7a05/raw/62a1f87a4e37bf157f2e0bfb32d85d840c98e422/large_toml_file_test.toml
./v retry -- git clone -n https://github.com/iarna/toml-spec-tests.git vlib/toml/tests/testdata/iarna
git -C vlib/toml/tests/testdata/iarna checkout 1880b1a
./v retry -- git clone -n https://github.com/toml-lang/toml-test.git vlib/toml/tests/testdata/toml_lang
git -C vlib/toml/tests/testdata/toml_lang checkout 229ce2e
# A few history notes of toml-rs (previously alexcrichton):
# commit 7f5472c the test-suite dir moves to the crates/ sub-directory
# commit 8461f7c *a lot* of test files are removed in *hope* that they are covered by the compliance test suite (assumed to be BurntSushi/toml-test, later toml-lang/toml-test)
# commit 9bd454c the last known good commit we can test against
./v retry -- git clone -n https://github.com/toml-rs/toml.git vlib/toml/tests/testdata/toml_rs
git -C vlib/toml/tests/testdata/toml_rs reset --hard 9bd454c
+10
View File
@@ -0,0 +1,10 @@
@echo off
setlocal EnableDelayedExpansion
REM Find every openssl.exe reachable through PATH:
for /f "delims=" %%F in ('where openssl 2^>nul') do (
set "OPENSSL_DIR=%%~dpF"
echo OpenSSL lives in: "!OPENSSL_DIR!"
goto :end
)
echo OpenSSL not found in: "!PATH!"
:end
+149
View File
@@ -0,0 +1,149 @@
name: CI FreeBSD
on:
workflow_dispatch:
push:
branches:
- master
paths-ignore:
- '**.md'
- '**.yml'
- 'cmd/tools/**'
- '!**/freebsd_ci.yml'
- '!ci/freebsd_ci.vsh'
- '!cmd/tools/builders/**.v'
pull_request:
paths-ignore:
- '**.md'
- '**.yml'
- 'cmd/tools/**'
- '!**/freebsd_ci.yml'
- '!ci/freebsd_ci.vsh'
- '!cmd/tools/builders/**.v'
### See https://github.com/cross-platform-actions/action
### for a description of the used fields here
jobs:
tcc-freebsd:
runs-on: ubuntu-latest
timeout-minutes: 20
steps:
- uses: actions/checkout@v7
- name: Start FreeBSD VM for tcc
id: vm-freebsd-tcc
uses: cross-platform-actions/action@v1.2.0
with:
operating_system: freebsd
version: '15.0'
memory: 4G
shell: sh
sync_files: runner-to-vm
- name: Tests on FreeBSD with tcc
id: tests-freebsd-tcc
shell: cpa.sh {0}
run: |
sudo pkg install -y git sqlite3 gmake boehm-gc-threaded libiconv
# Install DB packages needed to build examples
sudo pkg install -y mariadb118-client postgresql18-client
# Install packages needed by Sokol to build examples
sudo pkg install -y alsa-lib libglvnd libXi libXcursor
# Mandatory: hostname not set in VM => some tests fail
sudo hostname -s freebsd-ci
echo "::group::OS infos"
uname -a
echo "::endgroup::"
echo "::group::Build V"
git config --global --add safe.directory .
gmake
sudo ./v symlink
export VTEST_SHOW_LONGEST_BY_RUNTIME=3
export VTEST_SHOW_LONGEST_BY_COMPTIME=3
export VTEST_SHOW_LONGEST_BY_TOTALTIME=3
export VFLAGS='-cc tcc -no-retry-compilation'
echo "::endgroup::"
./v run ci/freebsd_ci.vsh all
clang-freebsd:
runs-on: ubuntu-latest
timeout-minutes: 20
steps:
- uses: actions/checkout@v7
- name: Start FreeBSD VM for clang
id: vm-freebsd-clang
uses: cross-platform-actions/action@v1.2.0
with:
operating_system: freebsd
version: '15.0'
memory: 4G
shell: sh
sync_files: runner-to-vm
- name: Tests on FreeBSD with clang
id: tests-freebsd-clang
shell: cpa.sh {0}
run: |
sudo pkg install -y git sqlite3 gmake boehm-gc-threaded libiconv
# Install DB packages needed to build examples
sudo pkg install -y mariadb118-client postgresql18-client
# Install packages needed by Sokol to build examples
sudo pkg install -y alsa-lib libglvnd libXi libXcursor
# Mandatory: hostname not set in VM => some tests fail
sudo hostname -s freebsd-ci
echo "::group::OS infos"
uname -a
echo "::endgroup::"
echo "::group::Build V"
git config --global --add safe.directory .
gmake
sudo ./v symlink
export VTEST_SHOW_LONGEST_BY_RUNTIME=3
export VTEST_SHOW_LONGEST_BY_COMPTIME=3
export VTEST_SHOW_LONGEST_BY_TOTALTIME=3
export VFLAGS='-cc clang'
echo "::endgroup::"
./v run ci/freebsd_ci.vsh all
gcc-freebsd:
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- uses: actions/checkout@v7
- name: Start FreeBSD VM for gcc
id: vm-freebsd-gcc
uses: cross-platform-actions/action@v1.2.0
with:
operating_system: freebsd
version: '15.0'
memory: 4G
shell: sh
sync_files: runner-to-vm
- name: Tests on FreeBSD with gcc
id: tests-freebsd-gcc
shell: cpa.sh {0}
run: |
sudo pkg install -y git sqlite3 gmake boehm-gc-threaded libiconv gcc
# Install DB packages needed to build examples
sudo pkg install -y mariadb118-client postgresql18-client
# Install packages needed by Sokol to build examples
sudo pkg install -y alsa-lib libglvnd libXi libXcursor
# Mandatory: hostname not set in VM => some tests fail
sudo hostname -s freebsd-ci
echo "::group::OS infos"
uname -a
echo "::endgroup::"
echo "::group::Build V"
git config --global --add safe.directory .
gmake
sudo ./v symlink
export VTEST_SHOW_LONGEST_BY_RUNTIME=3
export VTEST_SHOW_LONGEST_BY_COMPTIME=3
export VTEST_SHOW_LONGEST_BY_TOTALTIME=3
export VFLAGS='-cc gcc'
echo "::endgroup::"
./v run ci/freebsd_ci.vsh all
+75
View File
@@ -0,0 +1,75 @@
name: VC gen
on:
workflow_dispatch:
pull_request:
paths-ignore:
- '**.vv'
- '**.out'
- '**.md'
- '**.yml'
- '!**/gen_vc_ci.yml'
- 'cmd/tools/**'
- '!cmd/tools/builders/**.v'
push:
branches:
- master
paths-ignore:
- '**.vv'
- '**.out'
- '**.md'
- '**.yml'
- '!**/gen_vc_ci.yml'
- 'cmd/tools/**'
- '!cmd/tools/builders/**.v'
# Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued.
# However, do NOT cancel in-progress runs as we want to allow these production deployments to complete.
concurrency:
group: gen_vc-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: ${{ !contains(github.ref, 'master')}}
jobs:
build-vc:
runs-on: ubuntu-latest
timeout-minutes: 20
steps:
- uses: actions/checkout@v7
- name: Build V
run: make -j4
- name: Regenerate v.c and v_win.c
run: |
git config --global user.email "vlang-bot@users.noreply.github.com"
git config --global user.name "vlang-bot"
COMMIT_HASH="$(git rev-parse HEAD)"
COMMIT_MSG="$(git log -1 --oneline --pretty='%s' HEAD)"
rm -rf vc
./v retry -- git clone --depth=1 "https://vlang-bot:${{ secrets.VLANG_BOT_SECRET }}@github.com/vlang/vc.git"
rm -rf vc/v.c vc/v_win.c
./v -o vc/v.c -cross cmd/v
./v -o vc/v_win.c -os windows -cc msvc cmd/v
sed -i "1s/^/#define V_COMMIT_HASH \"$COMMIT_HASH\"\n/" vc/v.c
sed -i "1s/^/#define V_COMMIT_HASH \"$COMMIT_HASH\"\n/" vc/v_win.c
# do some sanity checks for the generated v.c file:
grep 'Turned ON custom defines: no_backtrace,cross' vc/v.c
grep '#define CUSTOM_DEFINE_cross' vc/v.c
# ensure the generated C files for the compiler, are over 5000 lines long, as a safety measure
[ "$(wc -l < vc/v.c)" -gt 5000 ]
[ "$(wc -l < vc/v_win.c)" -gt 5000 ]
git -C vc add v.c v_win.c
git -C vc commit -m "[v:master] $COMMIT_HASH - $COMMIT_MSG"
# in case there are recent commits:
./v retry -- git -C vc pull --rebase origin master
git -C vc log -3
- name: Deploy
if: github.event_name == 'push' && github.repository == 'vlang/v' && github.ref == 'refs/heads/master'
run: git -C vc push || true
+74
View File
@@ -0,0 +1,74 @@
name: Graphics CI
on:
push:
branches:
- master
paths:
- 'vlib/**'
- 'thirdparty/**'
- 'cmd/tools/builders/**.v'
- '**/gg_regressions_ci.yml'
- '!**.md'
pull_request:
paths:
- 'vlib/**'
- 'thirdparty/**'
- 'cmd/tools/builders/**.v'
- '**/gg_regressions_ci.yml'
- '!**.md'
concurrency:
group: gg-regressions-${{ github.workflow }}-${{ github.ref == 'refs/heads/master' && github.sha || github.ref }}
cancel-in-progress: true
jobs:
gg-regressions:
runs-on: ubuntu-24.04
timeout-minutes: 20
env:
VFLAGS: -cc tcc
DISPLAY: :99
LIBGL_ALWAYS_SOFTWARE: true
VTMP: /tmp
steps:
- name: Checkout V
uses: actions/checkout@v7
- uses: ./.github/actions/cache-apt-packages-action
- name: Build local v
run: make -j4 && ./v symlink
- name: Clear module cache
run: ./v wipe-cache
- name: Setup dependencies
run: |
# imagemagick : convert, mogrify
# xvfb : xvfb
# openimageio-tools : idiff
# libxcursor-dev libxi-dev : V gfx deps
# libgl1-mesa-dri : For headless rendering / software DRI driver (LIBGL_ALWAYS_SOFTWARE=true)
# freeglut3-dev : Fixes graphic apps compilation with tcc
# libx11-dev : X11 headers for clipboard and sokol (default backend on Linux)
.github/workflows/disable_azure_mirror.sh
./v retry -- sudo apt update
./v retry -- sudo apt install imagemagick openimageio-tools libgl1-mesa-dri xvfb libxcursor-dev libxi-dev libxrandr-dev freeglut3-dev xsel xclip libx11-dev libegl-dev
./v retry -- ./v download https://raw.githubusercontent.com/tremby/imgur.sh/c98345d/imgur.sh
./v retry -- git clone https://github.com/Larpon/gg-regression-images gg-regression-images
chmod +x ./imgur.sh
- name: Sample and compare
id: compare
continue-on-error: true
run: |
Xvfb "$DISPLAY" -screen 0 1280x1024x24 -fbdir /var/tmp/ &
sleep 2; while [ ! -f /var/tmp/Xvfb_screen0 ]; do sleep 0.5; done # give xvfb time to start, even on slow CI runs
sleep 5; ./v gret -t ./gg-regression-images/vgret.v_examples.toml -v ./gg-sample_images ./gg-regression-images
- name: Upload regression to imgur
if: steps.compare.outcome != 'success'
run: |
./imgur.sh /tmp/fail.png
./imgur.sh /tmp/diff.png
exit 1
+184
View File
@@ -0,0 +1,184 @@
import os
import json
import term
import time
const c = term.colorize
const tg = term.green
const tm = term.magenta
const tb = term.bold
struct Check {
name string
bucket string
state string
link string
workflow string
}
fn (c Check) is_failed() bool {
return c.bucket == 'fail' || c.state in ['FAILURE', 'TIMED_OUT']
}
fn (c Check) is_cancelled() bool {
return c.bucket == 'cancel' || c.state == 'CANCELLED'
}
struct GhCheckRun {
name string
status string
conclusion string
html_url string @[json: html_url]
}
struct GhCheckRunsResponse {
check_runs []GhCheckRun @[json: check_runs]
}
fn main() {
unbuffer_stdout()
arg := os.args[1] or {
println('Usage: v run gh_restart_failed.v <PR_NUMBER|REF>')
return
}
is_pr := arg.len < 6 && arg.bytes().all(it.is_digit())
checks := if is_pr { get_checks_for_pr(arg.int()) } else { get_checks_for_commit(arg) }
mut failed := []Check{}
mut cancelled := []Check{}
mut succeeded := 0
mut in_progress := 0
for check in checks {
if check.is_failed() {
failed << check
} else if check.is_cancelled() {
cancelled << check
} else if check.bucket == 'pass' || check.state == 'SUCCESS' {
succeeded++
} else {
in_progress++
}
}
mut to_restart := []Check{}
to_restart << failed
to_restart << cancelled
mut restarted_count := 0
if to_restart.len > 0 {
println('Found ${to_restart.len} failed or cancelled jobs:')
for job in to_restart {
println('- ${job.workflow} / ${job.name} (${job.state})')
}
println('\n' + c(tg, 'Do you want to restart these ${to_restart.len} jobs? [y/N]: '))
if os.input('').to_lower().trim_space() == 'y' {
println('')
for job in to_restart {
run_id, job_id := parse_ids(job.link)
if run_id == '' || job_id == '' {
println('Could not parse IDs from link: ${job.link} (Skipping)')
continue
}
print('Restarting ${job.name} (Run: ${run_id}, Job: ${job_id})... ')
res := execute_with_progress('gh run rerun ${run_id} --job ${job_id}')
if res.exit_code == 0 {
restarted_count++
} else {
println(' Error: ${res.output.trim_space()}')
}
}
} else {
println('Aborted restart.')
}
} else {
println('No failed or cancelled jobs found.')
}
println('\n' + c(tg, 'Summary:'))
println('Total jobs: ${m(checks.len)}')
println('Failed: ${m(failed.len)}')
println('Cancelled: ${m(cancelled.len)}')
println('Succeeded: ${m(succeeded)}')
println('In Progress: ${m(in_progress)}')
println('Restarted: ${m(restarted_count)}')
}
fn m(n int) string {
return c(tb, n.str())
}
fn parse_ids(link string) (string, string) {
parts := link.split('/')
runs_idx := parts.index('runs')
job_idx := parts.index('job')
mut run_id := ''
mut job_id := ''
if runs_idx != -1 && runs_idx + 1 < parts.len {
run_id = parts[runs_idx + 1]
}
if job_idx != -1 && job_idx + 1 < parts.len {
job_id = parts[job_idx + 1]
}
return run_id, job_id
}
fn get_checks_for_pr(pr_number int) []Check {
println(c(tg, 'Fetching checks for PR ${m(pr_number)}...'))
res := execute_with_progress('gh pr checks ${pr_number} --json name,bucket,state,link,workflow')
if res.exit_code != 0 {
println('Error: ${res.output}')
exit(1)
}
return json.decode([]Check, res.output) or { exit(1) }
}
fn get_checks_for_commit(commit string) []Check {
println(c(tg, 'Fetching checks for ref ${c(tb, commit)}...'))
res := execute_with_progress('gh api repos/:owner/:repo/commits/${commit}/check-runs?per_page=100')
if res.exit_code != 0 {
println('Error: ${res.output}')
exit(1)
}
resp := json.decode(GhCheckRunsResponse, res.output) or { exit(1) }
mut checks := []Check{}
for cr in resp.check_runs {
checks << Check{
name: cr.name
bucket: if cr.conclusion == 'failure' {
'fail'
} else if cr.conclusion == 'cancelled' {
'cancel'
} else if cr.conclusion == 'success' {
'pass'
} else {
'pending'
}
state: if cr.conclusion != '' {
cr.conclusion.to_upper()
} else {
cr.status.to_upper()
}
link: cr.html_url
workflow: 'Actions'
}
}
return checks
}
fn execute_with_progress(cmd string) os.Result {
start := time.now()
mut stop := false
spawn fn (cmd string, start time.Time, mut stop &bool) {
start_str := start.hhmmss()
for !*stop {
elapsed := time.since(start).seconds()
print('\rRunning ${c(tm, cmd)} [${start_str}] ... ${elapsed:.1f}s')
os.flush()
time.sleep(100 * time.millisecond)
}
}(cmd, start, mut &stop)
res := os.execute(cmd)
elapsed := time.since(start).seconds()
stop = true
time.sleep(100 * time.millisecond)
status := if res.exit_code == 0 { 'OK' } else { 'Failed' }
print('\r')
println('Command ${c(tm, cmd)} done in ${elapsed:.1f}s. ${status}')
return res
}
+80
View File
@@ -0,0 +1,80 @@
name: hub_docker_ci
### NB: avoid caching things here, since the action is rare (once per week),
### and the potential benefits are less than the complexity of debugging
### cache invalidation issues...
## Trigger on both new release tags, and on weekly tags.
## Allow for manual override too:
on:
workflow_dispatch:
push:
tags:
- '[0-9].[0-9]+.[0-9]+'
- 'weekly.*'
concurrency:
group: 'hub_docker_ci-${{ github.ref }}'
cancel-in-progress: true
jobs:
publish-new-docker-images:
strategy:
matrix:
os: [debian, alpine]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
with:
repository: 'vlang/docker'
- name: Set up QEMU
uses: docker/setup-qemu-action@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v4
- name: Login to hub.docker.com
uses: docker/login-action@v4
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Create & bootstrap persistent builder
run: |
docker buildx create --name gh-builder --driver docker-container --use
docker buildx inspect --bootstrap
- name: generate tags conditionally
id: gen_tags
run: |
if [[ "${{ matrix.os }}" == 'debian' ]]; then
echo 'TAGS=thevlang/vlang:latest,thevlang/vlang:${{ matrix.os }}' >> "$GITHUB_OUTPUT"
else
echo 'TAGS=thevlang/vlang:${{ matrix.os }}' >> "$GITHUB_OUTPUT"
fi
- uses: docker/build-push-action@v7
name: Build and deploy v image
with:
builder: gh-builder
context: .
platforms: linux/amd64,linux/arm64
tags: ${{ steps.gen_tags.outputs.TAGS }}
file: docker/vlang/Dockerfile.${{ matrix.os }}
push: true
build-args: 'USER=thevlang'
## cache-from: type=registry,ref=thevlang/vlang:${{ matrix.os }}-buildcache
## cache-to: type=registry,ref=thevlang/vlang:${{ matrix.os }}-buildcache,mode=max
- uses: docker/build-push-action@v7
name: Build and deploy developer build
with:
builder: gh-builder
context: .
platforms: linux/amd64,linux/arm64
tags: thevlang/vlang:${{ matrix.os }}-dev
file: docker/vlang/Dockerfile.${{ matrix.os }}.dev-full
push: true
build-args: 'USER=thevlang'
## cache-from: type=registry,ref=thevlang/vlang:${{ matrix.os }}-dev-buildcache
## cache-to: type=registry,ref=thevlang/vlang:${{ matrix.os }}-dev-buildcache,mode=max
+575
View File
@@ -0,0 +1,575 @@
name: CI Linux
on:
workflow_dispatch:
push:
branches:
- master
paths-ignore:
- '**.md'
- '**.yml'
- '!**/linux_ci.yml'
- 'cmd/tools/**'
- '!cmd/tools/builders/**.v'
pull_request:
paths-ignore:
- '**.md'
- '**.yml'
- '!**/linux_ci.yml'
- 'cmd/tools/**'
- '!cmd/tools/builders/**.v'
concurrency:
group: linux-${{ github.workflow }}-${{ github.ref == 'refs/heads/master' && github.sha || github.ref }}
cancel-in-progress: true
jobs:
tcc-linux:
runs-on: ubuntu-24.04
timeout-minutes: 121
env:
VFLAGS: -cc tcc -no-retry-compilation
VTEST_SHOW_LONGEST_BY_RUNTIME: 3
VTEST_SHOW_LONGEST_BY_COMPTIME: 3
VTEST_SHOW_LONGEST_BY_TOTALTIME: 3
steps:
- uses: actions/checkout@v7
- uses: ./.github/actions/cache-apt-packages-action
- name: Build v
run: make -j4 && ./v symlink
- name: Build v with -prealloc
run: v run ci/linux_ci.vsh build_v_with_prealloc
- name: All code is formatted
run: v run ci/linux_ci.vsh all_code_is_formatted_tcc
- name: Install dependencies for examples and tools
run: v run ci/linux_ci.vsh install_dependencies_for_examples_and_tools_tcc
- name: Test v->c
run: v run ci/linux_ci.vsh test_v_to_c_tcc
- name: v self compilation
run: v run ci/linux_ci.vsh v_self_compilation_tcc
- name: v doctor
run: v run ci/linux_ci.vsh v_doctor_tcc
- name: Verify `v test` works
run: v run ci/linux_ci.vsh verify_v_test_works_tcc
- name: Test pure V math module
run: v run ci/linux_ci.vsh test_pure_v_math_module_tcc
- name: Test inline assembly on linux
run: v run ci/linux_ci.vsh test_inline_assembly
- name: Self tests
run: v run ci/linux_ci.vsh self_tests_tcc
- name: Build examples
run: v run ci/linux_ci.vsh build_examples_tcc
- name: Run the submodule example, using a relative path
run: v run ci/linux_ci.vsh run_submodule_example_tcc
- name: Build v tools
run: v run ci/linux_ci.vsh build_tools_tcc
- name: Build v binaries
run: v run ci/linux_ci.vsh build_vbinaries_tcc
- name: Build benches
run: v run ci/linux_ci.vsh build_benches_tcc
- name: Run a VSH script
run: v run ci/linux_ci.vsh run_vsh_script_tcc
- name: Test v tutorials
run: v run ci/linux_ci.vsh test_v_tutorials_tcc
- name: Build cmd/tools/fast
run: v run ci/linux_ci.vsh build_fast_tcc
- name: V self compilation with -usecache
run: v run ci/linux_ci.vsh v_self_compilation_usecache_tcc
- name: Test password input
run: v run ci/linux_ci.vsh test_password_input_tcc
- name: Test readline
run: v run ci/linux_ci.vsh test_readline_tcc
- name: Test leak detector
run: v run ci/linux_ci.vsh test_leak_detector_tcc
- name: Test leak detector not being active for normal compile
run: v run ci/linux_ci.vsh test_leak_detector_not_active_tcc
gcc-linux:
runs-on: ubuntu-24.04
timeout-minutes: 121
env:
VTEST_SHOW_LONGEST_BY_RUNTIME: 3
VTEST_SHOW_LONGEST_BY_COMPTIME: 3
VTEST_SHOW_LONGEST_BY_TOTALTIME: 3
steps:
- uses: actions/checkout@v7
- uses: ./.github/actions/cache-apt-packages-action
- name: Build V
run: make -j4 && ./v symlink
- name: backend x64 regressions
if: ${{ false }} # Temporarily disabled.
run: |
set -e
VJOBS=1 ./v test \
vlib/v2_toberemoved/abi \
vlib/v2_toberemoved/gen/x64/x64_abi_test.v \
vlib/v2_toberemoved/gen/x64/x64_backend_diagnostics_test.v \
vlib/v2_toberemoved/gen/x64/x64_object_format_test.v \
vlib/v2_toberemoved/gen/x64/x64_pe_linker_test.v \
vlib/v2_toberemoved/ssa/tree_sumtype_lowering_test.v
VJOBS=1 ./v test -run-only test_module_qualified_alias_array_field_index_has_alias_element_type,test_module_storage_legacy_direct_import_nested_module_selector_uses_declared_leaf_module,test_module_storage_flat_direct_import_nested_module_selector_uses_declared_leaf_module vlib/v2_toberemoved/ssa/module_storage_test.v
VJOBS=1 ./v test -run-only test_x64_linux_math_log_20_stdout_exact_bytes,test_x64_linux_generic_sumtype_direct_wrap_stdout_exact_bytes,test_x64_linux_generic_sumtype_repeated_base_specialization_stdout_exact_bytes,test_x64_linux_generic_sumtype_receiver_size_stdout_exact_bytes,test_x64_linux_generic_sumtype_insert_size_stdout_exact_bytes,test_x64_linux_struct_float_fields_stdout_exact_bytes,test_x64_linux_union_f64_bits_stdout_exact_bytes,test_x64_linux_f64_str_interpolation_stdout_exact_bytes,test_x64_linux_f64_for_interpolation_stdout_exact_bytes,test_x64_linux_formatted_int_interpolation_stdout_exact_bytes,test_x64_linux_formatted_int_width_100_interpolation_stdout_exact_bytes,test_x64_linux_formatted_f64_interpolation_stdout_exact_bytes,test_x64_linux_formatted_string_return_lifetime_stdout_exact_bytes,test_x64_linux_spectral_reduced_formatted_stdout_exact_bytes,test_x64_linux_bits_len32_stdout_exact_bytes,test_x64_linux_rand_u32n_interface_result_stdout_exact_bytes,test_x64_linux_rand_intn_range_interface_result_stdout_exact_bytes,test_x64_linux_textscanner_embedded_parser_stdout_exact_bytes,test_x64_linux_struct_positional_side_effect_stdout_exact_bytes,test_x64_linux_struct_named_side_effect_stdout_exact_bytes,test_x64_linux_unrelated_same_shape_struct_stdout_exact_bytes,test_x64_linux_named_init_embedded_value_stdout_exact_bytes,test_x64_linux_get_raw_line_example_stdin_stdout_exact_bytes,test_x64_linux_mini_calculator_example_stdin_stdout_exact_bytes,test_x64_linux_mini_calculator_recursive_descent_example_stdin_stdout_exact_bytes,test_x64_linux_external_c_flag_source_uses_hosted_link_with_compile_flags vlib/v2_toberemoved/gen/x64/x64_runtime_smoke_test.v
VJOBS=1 ./v test -run-only test_non_generic_concrete_sumtype_return_wraps_variant,test_option_concrete_sumtype_return_wraps_variant,test_generic_sumtype_declared_param_order_is_preserved_for_crossed_variants,test_worker_clone_sees_sumtype_decl_variant_cache,test_sumtype_decl_variant_cache_records_concrete_generic_variants_only,test_generic_sumtype_match_uses_full_specialization_when_generic_base_repeats,test_flat_direct_generic_sumtype_match_uses_full_specialization_when_generic_base_repeats,test_generic_sumtype_match_smartcast_scans_full_specialization_body,test_flat_direct_generic_sumtype_match_smartcast_scans_full_specialization_body,test_nested_module_concrete_generic_sumtype_base_does_not_fall_back_to_local_tree,test_leaf_module_concrete_generic_sumtype_base_fallback_beats_parent_module_tree vlib/v2_toberemoved/transformer/monomorphize_test.v
./v test vlib/v2_toberemoved/builder/native_test.v vlib/v2_toberemoved/builder/target_os_test.v
./v test vlib/v2_toberemoved/ssa/optimize
V2_VERIFY_STRICT=1 ./v test vlib/v2_toberemoved/ssa/optimize
- name: backend x64 examples
if: ${{ false }} # Temporarily disabled.
run: |
set -e
tmp="$(mktemp -d)"
trap 'rm -rf "$tmp"' EXIT
check_empty_stderr() {
label="$1"
stderr="$2"
if [ -s "$stderr" ]; then
echo "::error::$label wrote to stderr"
cat "$stderr"
return 1
fi
}
check_stdout() {
label="$1"
expected="$2"
actual="$3"
if ! cmp -s "$expected" "$actual"; then
echo "::error::$label stdout mismatch"
echo "expected:"
cat "$expected"
echo "actual:"
cat "$actual"
return 1
fi
}
run_native_x64_example() {
source="$1"
name="$2"
expected="$3"
shift 3
./v -v2 -no-parallel -b x64 "$source" -o "$tmp/$name"
"$tmp/$name" "$@" > "$tmp/$name.out" 2> "$tmp/$name.err"
check_empty_stderr "$name" "$tmp/$name.err"
check_stdout "$name" "$expected" "$tmp/$name.out"
}
run_native_x64_example_with_stdin() {
source="$1"
name="$2"
input="$3"
expected="$4"
shift 4
./v -v2 -no-parallel -b x64 "$source" -o "$tmp/$name"
"$tmp/$name" "$@" < "$input" > "$tmp/$name.out" 2> "$tmp/$name.err"
check_empty_stderr "$name" "$tmp/$name.err"
check_stdout "$name" "$expected" "$tmp/$name.out"
}
run_native_x64_example_capture() {
source="$1"
name="$2"
shift 2
./v -v2 -no-parallel -b x64 "$source" -o "$tmp/$name"
"$tmp/$name" "$@" > "$tmp/$name.out" 2> "$tmp/$name.err"
check_empty_stderr "$name" "$tmp/$name.err"
}
check_random_ips_stdout() {
label="$1"
actual="$2"
python3 - "$label" "$actual" <<'PY'
import sys
label = sys.argv[1]
path = sys.argv[2]
lines = open(path, "r", encoding="utf-8").read().splitlines()
if len(lines) != 10:
raise SystemExit(f"{label}: expected 10 lines, got {len(lines)}")
rows = []
for line in lines:
parts = line.split(".")
if len(parts) != 4:
raise SystemExit(f"{label}: invalid IPv4 shape: {line!r}")
row = []
for part in parts:
if not part.isdigit():
raise SystemExit(f"{label}: non-numeric octet in {line!r}")
value = int(part)
if value < 0 or value > 254:
raise SystemExit(f"{label}: octet out of range in {line!r}")
row.append(value)
rows.append(tuple(row))
if len(set(rows)) < 3:
raise SystemExit(f"{label}: output has too little row diversity")
if all(row[1] == 0 for row in rows) and all(row[3] == 0 for row in rows):
raise SystemExit(f"{label}: suspicious old x.0.x.0 pattern")
PY
}
check_rule110_stdout() {
label="$1"
actual="$2"
width="$3"
python3 - "$label" "$actual" "$width" <<'PY'
import sys
label = sys.argv[1]
path = sys.argv[2]
width = int(sys.argv[3])
lines = open(path, "r", encoding="utf-8").read().splitlines()
title = "Rule 110 V Implementation"
title_lines = [idx for idx, line in enumerate(lines) if title in line]
if not title_lines:
raise SystemExit(f"{label}: missing title")
idx = title_lines[0]
generations = lines[idx + 1:]
if generations and generations[0] == "":
generations = generations[1:]
if len(generations) != width:
raise SystemExit(f"{label}: expected {width} generation lines, got {len(generations)}")
for line in generations:
if len(line) != width:
raise SystemExit(f"{label}: generation line has width {len(line)}, expected {width}: {line!r}")
if any(ch not in " *" for ch in line):
raise SystemExit(f"{label}: invalid generation chars: {line!r}")
if not any("*" in line for line in generations):
raise SystemExit(f"{label}: expected at least one live cell")
if len(set(generations)) < 3:
raise SystemExit(f"{label}: expected at least 3 distinct generation lines")
PY
}
write_v_run_expected() {
source="$1"
expected="$2"
shift 2
stderr="$tmp/$(basename "$expected").stderr"
./v run "$source" "$@" > "$expected" 2> "$stderr"
check_empty_stderr "v run $source $*" "$stderr"
}
write_v_run_expected_with_stdin() {
source="$1"
input="$2"
expected="$3"
shift 3
stderr="$tmp/$(basename "$expected").stderr"
./v run "$source" "$@" < "$input" > "$expected" 2> "$stderr"
check_empty_stderr "v run $source $*" "$stderr"
}
write_fizz_buzz_expected() {
i=1
while [ "$i" -le 100 ]; do
if [ $((i % 15)) -eq 0 ]; then
echo FizzBuzz
elif [ $((i % 3)) -eq 0 ]; then
echo Fizz
elif [ $((i % 5)) -eq 0 ]; then
echo Buzz
else
echo "$i"
fi
i=$((i + 1))
done
}
write_hanoi_expected() {
python3 - <<'PY'
def hanoi(n, a, b, c):
if n == 1:
print(f"Disc 1 from {a} to {c}...")
else:
hanoi(n - 1, a, c, b)
print(f"Disc {n} from {a} to {c}...")
hanoi(n - 1, b, a, c)
hanoi(7, "A", "B", "C")
PY
}
write_sudoku_expected() {
python3 - <<'PY'
import sys
puzzle = [
[0, 3, 0, 0, 7, 0, 0, 0, 0],
[0, 0, 0, 1, 3, 5, 0, 0, 0],
[0, 0, 1, 0, 0, 0, 0, 5, 0],
[1, 0, 0, 0, 6, 0, 0, 0, 3],
[4, 0, 0, 8, 0, 3, 0, 0, 1],
[7, 0, 0, 0, 2, 0, 0, 0, 6],
[0, 0, 0, 0, 0, 0, 2, 1, 0],
[0, 0, 0, 4, 1, 2, 0, 0, 5],
[0, 0, 0, 0, 0, 0, 0, 7, 4],
]
solution = [
[2, 3, 5, 6, 7, 8, 1, 4, 9],
[9, 4, 7, 1, 3, 5, 8, 6, 2],
[6, 8, 1, 2, 4, 9, 3, 5, 7],
[1, 2, 8, 7, 6, 4, 5, 9, 3],
[4, 5, 6, 8, 9, 3, 7, 2, 1],
[7, 9, 3, 5, 2, 1, 4, 8, 6],
[3, 6, 4, 9, 5, 7, 2, 1, 8],
[8, 7, 9, 4, 1, 2, 6, 3, 5],
[5, 1, 2, 3, 8, 6, 9, 7, 4],
]
def append_grid(lines, label, grid):
lines.append(label)
for i, row in enumerate(grid):
if i % 3 == 0 and i != 0:
lines.append("- - - - - - - - - - - -")
line = ""
for j, value in enumerate(row):
if j % 3 == 0 and j != 0:
line += " | "
line += f"{value} "
lines.append(line)
lines = []
append_grid(lines, "Sudoku Puzzle:", puzzle)
lines.append("Solving...")
append_grid(lines, "Solution:", solution)
out = ("\n".join(lines) + "\n").encode()
if len(out) != 582:
raise SystemExit(f"sudoku stdout oracle shape changed: {len(out)} bytes")
sys.stdout.buffer.write(out)
PY
}
write_tree_of_nodes_expected() {
cat <<'EOF'
tree structure:
Node{
value: 10
left: Tree(Node{
value: 30
left: Tree(Empty{})
right: Tree(Empty{})
})
right: Tree(Node{
value: 20
left: Tree(Empty{})
right: Tree(Empty{})
})
}
tree size: 3
EOF
}
write_js_hello_world_expected() {
printf 'Hello from V.js (0)\nHello from V.js (1)\nHello from V.js (2)\n'
}
write_vascii_expected() {
python3 - <<'PY'
from pathlib import Path
import sys
source = Path("examples/vascii.v").read_text(encoding="utf-8")
start_marker = "println('"
end_marker = "')"
if source.count(start_marker) != 1:
raise SystemExit("vascii stdout oracle expects one single-quoted println literal")
start = source.index(start_marker) + len(start_marker)
end = source.rindex(end_marker)
if source[end + len(end_marker):].strip() != "}":
raise SystemExit("vascii stdout oracle expects the println literal to be the final main statement")
out = bytearray()
literal = source[start:end]
i = 0
while i < len(literal):
ch = literal[i]
if ch == "\\":
i += 1
if i >= len(literal):
raise SystemExit("unterminated escape in vascii literal")
escaped = literal[i]
if escaped == "n":
out.append(10)
elif escaped == "t":
out.append(9)
elif escaped == "r":
out.append(13)
elif escaped == "\\":
out.append(92)
elif escaped == "'":
out.append(39)
elif escaped == '"':
out.append(34)
else:
out.extend(escaped.encode("utf-8"))
else:
out.extend(ch.encode("utf-8"))
i += 1
out.append(10)
sys.stdout.buffer.write(out)
PY
}
write_rune_expected() {
printf '\360\237\230\200\n@\n'
}
printf 'Hello, World!\n' > "$tmp/hello_world.expected"
write_fizz_buzz_expected > "$tmp/fizz_buzz.expected"
write_hanoi_expected > "$tmp/hanoi.expected"
write_sudoku_expected > "$tmp/sudoku.expected"
printf 'HELLO WORLD\nHELLO WORLD\nHELLO WORLD\n' > "$tmp/function_types.expected"
printf '5\n3\n' > "$tmp/submodule.expected"
printf '1\n1\n2\n3\n5\n8\n13\n21\n34\n55\n89\n' > "$tmp/fibonacci_10.expected"
printf '120\n' > "$tmp/dump_factorial.expected"
write_v_run_expected examples/primes.v "$tmp/primes_20.expected" 20
write_tree_of_nodes_expected > "$tmp/tree_of_nodes.expected"
write_js_hello_world_expected > "$tmp/js_hello_world.expected"
write_vascii_expected > "$tmp/vascii.expected"
write_rune_expected > "$tmp/rune.expected"
write_v_run_expected examples/graphs/bfs.v "$tmp/bfs.expected"
write_v_run_expected examples/graphs/bfs3.v "$tmp/bfs3.expected"
write_v_run_expected examples/graphs/dfs.v "$tmp/dfs.expected"
write_v_run_expected examples/graphs/dijkstra.v "$tmp/dijkstra.expected"
write_v_run_expected examples/graphs/topological_sorting_greedy.v "$tmp/topological_sorting_greedy.expected"
write_v_run_expected examples/graphs/topological_sorting_dfs.v "$tmp/topological_sorting_dfs.expected"
write_v_run_expected examples/graphs/dfs2.v "$tmp/dfs2.expected"
write_v_run_expected examples/graphs/minimal_spann_tree_prim.v "$tmp/minimal_spann_tree_prim.expected"
write_v_run_expected examples/graphs/bellman-ford.v "$tmp/bellman_ford.expected"
write_v_run_expected examples/binary_search_tree.v "$tmp/binary_search_tree.expected"
printf 'wrong format\nempty input\n' > "$tmp/errors.expected"
write_v_run_expected examples/custom_error.v "$tmp/custom_error.expected"
write_v_run_expected examples/spectral.v "$tmp/spectral_10.expected" 10
printf 'length of random array is 1000\nbefore quick sort whether array is sorted: false\nafter quick sort whether array is sorted: true\n' > "$tmp/quick_sort.expected"
printf 'hello\nworld\n' > "$tmp/get_raw_line.in"
write_v_run_expected_with_stdin examples/get_raw_line.v "$tmp/get_raw_line.in" "$tmp/get_raw_line.expected"
printf '3+4*2\nexit\n' > "$tmp/mini_calculator.in"
write_v_run_expected_with_stdin examples/mini_calculator.v "$tmp/mini_calculator.in" "$tmp/mini_calculator.expected"
printf '3+4*2\nexit\n' > "$tmp/mini_calculator_recursive_descent.in"
write_v_run_expected_with_stdin examples/mini_calculator_recursive_descent.v "$tmp/mini_calculator_recursive_descent.in" "$tmp/mini_calculator_recursive_descent.expected"
run_native_x64_example examples/hello_world.v hello_world "$tmp/hello_world.expected"
run_native_x64_example examples/fizz_buzz.v fizz_buzz "$tmp/fizz_buzz.expected"
run_native_x64_example examples/hanoi.v hanoi "$tmp/hanoi.expected"
run_native_x64_example examples/sudoku.v sudoku "$tmp/sudoku.expected"
run_native_x64_example examples/function_types.v function_types "$tmp/function_types.expected"
run_native_x64_example examples/submodule/main.v submodule "$tmp/submodule.expected"
run_native_x64_example examples/fibonacci.v fibonacci "$tmp/fibonacci_10.expected" 10
run_native_x64_example examples/dump_factorial.v dump_factorial "$tmp/dump_factorial.expected"
run_native_x64_example examples/primes.v primes "$tmp/primes_20.expected" 20
run_native_x64_example examples/tree_of_nodes.v tree_of_nodes "$tmp/tree_of_nodes.expected"
run_native_x64_example examples/js_hello_world.v js_hello_world "$tmp/js_hello_world.expected"
run_native_x64_example examples/vascii.v vascii "$tmp/vascii.expected"
run_native_x64_example examples/rune.v rune "$tmp/rune.expected"
run_native_x64_example examples/graphs/bfs.v bfs "$tmp/bfs.expected"
run_native_x64_example examples/graphs/bfs3.v bfs3 "$tmp/bfs3.expected"
run_native_x64_example examples/graphs/dfs.v dfs "$tmp/dfs.expected"
run_native_x64_example examples/graphs/dijkstra.v dijkstra "$tmp/dijkstra.expected"
run_native_x64_example examples/graphs/topological_sorting_greedy.v topological_sorting_greedy "$tmp/topological_sorting_greedy.expected"
run_native_x64_example examples/graphs/topological_sorting_dfs.v topological_sorting_dfs "$tmp/topological_sorting_dfs.expected"
run_native_x64_example examples/graphs/dfs2.v dfs2 "$tmp/dfs2.expected"
run_native_x64_example examples/graphs/minimal_spann_tree_prim.v minimal_spann_tree_prim "$tmp/minimal_spann_tree_prim.expected"
run_native_x64_example examples/graphs/bellman-ford.v bellman_ford "$tmp/bellman_ford.expected"
run_native_x64_example examples/binary_search_tree.v binary_search_tree "$tmp/binary_search_tree.expected"
run_native_x64_example examples/errors.v errors "$tmp/errors.expected"
run_native_x64_example examples/custom_error.v custom_error "$tmp/custom_error.expected"
run_native_x64_example examples/spectral.v spectral "$tmp/spectral_10.expected" 10
run_native_x64_example examples/quick_sort.v quick_sort "$tmp/quick_sort.expected"
run_native_x64_example_with_stdin examples/get_raw_line.v get_raw_line "$tmp/get_raw_line.in" "$tmp/get_raw_line.expected"
run_native_x64_example_with_stdin examples/mini_calculator.v mini_calculator "$tmp/mini_calculator.in" "$tmp/mini_calculator.expected"
run_native_x64_example_with_stdin examples/mini_calculator_recursive_descent.v mini_calculator_recursive_descent "$tmp/mini_calculator_recursive_descent.in" "$tmp/mini_calculator_recursive_descent.expected"
run_native_x64_example_capture examples/random_ips.v random_ips
check_random_ips_stdout random_ips "$tmp/random_ips.out"
run_native_x64_example_capture examples/rule110.v rule110 31
check_rule110_stdout rule110 "$tmp/rule110.out" 31
- name: All code is formatted
run: v run ci/linux_ci.vsh all_code_is_formatted_gcc
- name: Install dependencies for examples and tools
run: v run ci/linux_ci.vsh install_dependencies_for_examples_and_tools_gcc
- name: Recompile V with -cstrict and gcc
run: v run ci/linux_ci.vsh recompile_v_with_cstrict_gcc
- name: Valgrind v.c
run: v run ci/linux_ci.vsh valgrind_v_c_gcc
- name: Run sanitizers
run: v run ci/linux_ci.vsh run_sanitizers_gcc
- name: v self compilation
run: v run ci/linux_ci.vsh v_self_compilation_gcc
- name: v self compilation with -usecache
run: v run ci/linux_ci.vsh v_self_compilation_usecache_gcc
- name: Verify `v test` works
run: v run ci/linux_ci.vsh verify_v_test_works_gcc
- name: Test pure V math module
run: v run ci/linux_ci.vsh test_pure_v_math_module_gcc
- name: Self tests
run: v run ci/linux_ci.vsh self_tests_gcc
- name: Self tests (-prod)
run: v run ci/linux_ci.vsh self_tests_prod_gcc
- name: Self tests (-cstrict)
run: v run ci/linux_ci.vsh self_tests_cstrict_gcc
- name: Build examples
run: v run ci/linux_ci.vsh build_examples_gcc
- name: Build tetris with -autofree
run: v run ci/linux_ci.vsh build_tetris_autofree_gcc
- name: Build blog tutorial with -autofree
run: v run ci/linux_ci.vsh build_blog_autofree_gcc
- name: Build option_test.c.v with -autofree
run: v run ci/linux_ci.vsh build_option_test_autofree_gcc
- name: V self compilation with -parallel-cc
run: v run ci/linux_ci.vsh v_self_compilation_parallel_cc_gcc
- name: Build modules
run: v run ci/linux_ci.vsh build_modules_gcc
- name: compile vdoctor.v with -prod
run: v run ci/linux_ci.vsh compile_vdoctor_prod_gcc
- name: compile vup.v with -prod
run: v run ci/linux_ci.vsh compile_vup_prod_gcc
clang-linux:
runs-on: ubuntu-24.04
timeout-minutes: 121
env:
VFLAGS: -cc clang
VTEST_SHOW_LONGEST_BY_RUNTIME: 3
VTEST_SHOW_LONGEST_BY_COMPTIME: 3
VTEST_SHOW_LONGEST_BY_TOTALTIME: 3
steps:
- uses: actions/checkout@v7
- uses: ./.github/actions/cache-apt-packages-action
- name: Build V
run: make -j4 && ./v symlink
- name: All code is formatted
run: v run ci/linux_ci.vsh all_code_is_formatted_clang
- name: Install dependencies for examples and tools
run: v run ci/linux_ci.vsh install_dependencies_for_examples_and_tools_clang
- name: Recompile V with -cstrict and clang
run: v run ci/linux_ci.vsh recompile_v_with_cstrict_clang
- name: Valgrind
run: v run ci/linux_ci.vsh valgrind_clang
- name: Run sanitizers
run: v run ci/linux_ci.vsh run_sanitizers_clang
- name: v self compilation
run: v run ci/linux_ci.vsh v_self_compilation_clang
- name: v self compilation with -usecache
run: v run ci/linux_ci.vsh v_self_compilation_usecache_clang
- name: Verify `v test` works
run: v run ci/linux_ci.vsh verify_v_test_works_clang
- name: Test pure V math module
run: v run ci/linux_ci.vsh test_pure_v_math_module_clang
- name: Self tests
run: v run ci/linux_ci.vsh self_tests_clang
- name: Self tests (vprod)
run: v run ci/linux_ci.vsh self_tests_vprod_clang
- name: Self tests (-cstrict)
run: v run ci/linux_ci.vsh self_tests_cstrict_clang
- name: Build examples
run: v run ci/linux_ci.vsh build_examples_clang
- name: Build examples with -autofree
run: v run ci/linux_ci.vsh build_examples_autofree_clang
- name: Build modules
run: v run ci/linux_ci.vsh build_modules_clang
+519
View File
@@ -0,0 +1,519 @@
name: CI macOS
on:
push:
branches:
- master
paths-ignore:
- '**.md'
- '**.yml'
- '!**/macos_ci.yml'
- 'cmd/tools/**'
- '!cmd/tools/builders/**.v'
pull_request:
paths-ignore:
- '**.md'
- '**.yml'
- '!**/macos_ci.yml'
- 'cmd/tools/**'
- '!cmd/tools/builders/**.v'
concurrency:
group: macos-${{ github.workflow }}-${{ github.ref == 'refs/heads/master' && github.sha || github.ref }}
cancel-in-progress: true
jobs:
clang-macos:
strategy:
matrix:
os: [macos-14]
fail-fast: false
runs-on: ${{ matrix.os }}
timeout-minutes: 151
env:
VFLAGS: -cc clang
VTEST_SHOW_LONGEST_BY_RUNTIME: 3
VTEST_SHOW_LONGEST_BY_COMPTIME: 3
VTEST_SHOW_LONGEST_BY_TOTALTIME: 3
steps:
- uses: actions/checkout@v7
- name: Cache Homebrew downloads
uses: actions/cache@v5
with:
path: ~/Library/Caches/Homebrew
key: brew-${{ matrix.os }}-${{ hashFiles('.github/workflows/macos_ci.yml', 'ci/macos_ci.vsh') }}
restore-keys: |
brew-${{ matrix.os }}-
- name: Build V
run: make -j4 && ./v symlink
- name: Test symlink
run: v run ci/macos_ci.vsh test_symlink
- name: v doctor
run: v run ci/macos_ci.vsh v_doctor
- name: Build v with -prealloc
run: v run ci/macos_ci.vsh build_v_with_prealloc
- name: Test cross compilation to Linux
run: v run ci/macos_ci.vsh test_cross_compilation
- name: Test inline assembly on macos
run: v run ci/macos_ci.vsh test_inline_assembly
- name: Build V with -cstrict
run: v run ci/macos_ci.vsh build_with_cstrict
- name: All code is formatted
run: v run ci/macos_ci.vsh all_code_is_formatted
- name: Run sanitizers
run: v run ci/macos_ci.vsh run_sanitizers
- name: Build V using V
run: v run ci/macos_ci.vsh build_using_v
- name: Verify `v test` works
run: v run ci/macos_ci.vsh verify_v_test_works
- name: Install iconv for encoding.iconv
run: v run ci/macos_ci.vsh install_iconv
- name: Test pure V math module
run: v run ci/macos_ci.vsh test_pure_v_math_module
- name: Self tests
run: v run ci/macos_ci.vsh self_tests
- name: Build examples
run: v run ci/macos_ci.vsh build_examples
- name: Build tetris with -autofree
run: v run ci/macos_ci.vsh build_tetris_autofree
- name: Build blog tutorial with -autofree
run: v run ci/macos_ci.vsh build_blog_autofree
- name: Build examples with -prod
run: v run ci/macos_ci.vsh build_examples_prod
- name: Build examples with V build with tcc
run: v run ci/macos_ci.vsh build_examples_v_compiled_with_tcc
## - name: V self compilation with -usecache
## run: v run ci/macos_ci.vsh v_self_compilation_usecache
- name: V self compilation with -parallel-cc
run: v run ci/macos_ci.vsh v_self_compilation_parallel_cc
- name: v2 test suite
if: ${{ false }} # Temporarily disabled.
run: v run cmd/v2/test_all.vsh -prod
- name: Test password input
run: v run ci/macos_ci.vsh test_password_input
- name: Test readline
run: v run ci/macos_ci.vsh test_readline
v2-x64-native-macos:
if: ${{ false }} # Temporarily disabled.
runs-on: macos-15-intel
timeout-minutes: 30
steps:
- uses: actions/checkout@v7
- name: Build V
run: make -j4
- name: backend x64 regressions
run: |
set -e
VJOBS=1 ./v test \
vlib/v2_toberemoved/abi \
vlib/v2_toberemoved/gen/x64/x64_abi_test.v \
vlib/v2_toberemoved/gen/x64/x64_backend_diagnostics_test.v \
vlib/v2_toberemoved/gen/x64/x64_object_format_test.v \
vlib/v2_toberemoved/gen/x64/x64_pe_linker_test.v \
vlib/v2_toberemoved/ssa/tree_sumtype_lowering_test.v
VJOBS=1 ./v test -run-only test_module_qualified_alias_array_field_index_has_alias_element_type,test_module_storage_legacy_direct_import_nested_module_selector_uses_declared_leaf_module,test_module_storage_flat_direct_import_nested_module_selector_uses_declared_leaf_module vlib/v2_toberemoved/ssa/module_storage_test.v
VJOBS=1 ./v test -run-only test_temporary_generic_receiver_init_maps_method_generic,test_temporary_generic_call_receiver_maps_method_generic,test_temporary_generic_selector_receiver_maps_method_generic,test_identifier_generic_receiver_from_call_maps_method_generic vlib/v2_toberemoved/types/checker_test.v
VJOBS=1 ./v test -run-only test_worker_clone_sees_sumtype_decl_variant_cache,test_sumtype_decl_variant_cache_records_concrete_generic_variants_only,test_generic_sumtype_match_uses_full_specialization_when_generic_base_repeats,test_flat_direct_generic_sumtype_match_uses_full_specialization_when_generic_base_repeats,test_generic_sumtype_match_smartcast_scans_full_specialization_body,test_flat_direct_generic_sumtype_match_smartcast_scans_full_specialization_body,test_nested_module_concrete_generic_sumtype_base_does_not_fall_back_to_local_tree,test_leaf_module_concrete_generic_sumtype_base_fallback_beats_parent_module_tree vlib/v2_toberemoved/transformer/monomorphize_test.v
VJOBS=1 ./v test -run-only test_x64_macos_windows_math_log_20_stdout_exact_bytes,test_x64_macos_windows_generic_sumtype_repeated_base_specialization_stdout_exact_bytes,test_x64_macos_windows_formatted_int_interpolation_stdout_exact_bytes,test_x64_macos_windows_formatted_int_width_100_interpolation_stdout_exact_bytes,test_x64_macos_windows_formatted_f64_interpolation_stdout_exact_bytes,test_x64_macos_windows_formatted_string_return_lifetime_stdout_exact_bytes,test_x64_macos_windows_spectral_reduced_formatted_stdout_exact_bytes,test_x64_macos_windows_bits_len32_stdout_exact_bytes,test_x64_macos_windows_rand_u32n_interface_result_stdout_exact_bytes,test_x64_macos_windows_rand_intn_range_interface_result_stdout_exact_bytes,test_x64_macos_windows_textscanner_embedded_parser_stdout_exact_bytes,test_x64_macos_windows_struct_positional_side_effect_stdout_exact_bytes,test_x64_macos_windows_struct_named_side_effect_stdout_exact_bytes,test_x64_macos_windows_unrelated_same_shape_struct_stdout_exact_bytes,test_x64_macos_windows_named_init_embedded_value_stdout_exact_bytes,test_x64_macos_windows_get_raw_line_example_stdin_stdout_exact_bytes,test_x64_macos_windows_mini_calculator_example_stdin_stdout_exact_bytes,test_x64_macos_windows_mini_calculator_recursive_descent_example_stdin_stdout_exact_bytes,test_x64_macos_external_c_flag_source_uses_hosted_link_with_compile_flags vlib/v2_toberemoved/gen/x64/x64_runtime_smoke_test.v
./v test vlib/v2_toberemoved/builder/native_test.v vlib/v2_toberemoved/builder/target_os_test.v
./v test vlib/v2_toberemoved/ssa/optimize
V2_VERIFY_STRICT=1 ./v test vlib/v2_toberemoved/ssa/optimize
- name: backend x64 examples
run: |
set -e
tmp="$(mktemp -d)"
trap 'rm -rf "$tmp"' EXIT
check_empty_stderr() {
label="$1"
stderr="$2"
if [ -s "$stderr" ]; then
echo "::error::$label wrote to stderr"
cat "$stderr"
return 1
fi
}
check_v_run_stderr() {
label="$1"
stderr="$2"
if [ ! -s "$stderr" ]; then
return 0
fi
if python3 - "$stderr" <<'PY'
import re
import sys
text = open(sys.argv[1], "rb").read().decode("utf-8", "replace")
text = re.sub(r"\x1b\[[0-?]*[ -/]*[@-~]", "", text).strip()
expected = "warning: tcc compilation failed, falling back to cc (this is much slower)"
raise SystemExit(0 if text == expected else 1)
PY
then
return 0
fi
echo "::error::$label wrote unexpected stderr"
cat "$stderr"
return 1
}
check_stdout() {
label="$1"
expected="$2"
actual="$3"
if ! cmp -s "$expected" "$actual"; then
echo "::error::$label stdout mismatch"
echo "expected:"
cat "$expected"
echo "actual:"
cat "$actual"
return 1
fi
}
run_native_x64_example() {
source="$1"
name="$2"
expected="$3"
shift 3
./v -v2 -no-parallel -b x64 "$source" -o "$tmp/$name"
"$tmp/$name" "$@" > "$tmp/$name.out" 2> "$tmp/$name.err"
check_empty_stderr "$name" "$tmp/$name.err"
check_stdout "$name" "$expected" "$tmp/$name.out"
}
run_native_x64_example_with_stdin() {
source="$1"
name="$2"
input="$3"
expected="$4"
shift 4
./v -v2 -no-parallel -b x64 "$source" -o "$tmp/$name"
"$tmp/$name" "$@" < "$input" > "$tmp/$name.out" 2> "$tmp/$name.err"
check_empty_stderr "$name" "$tmp/$name.err"
check_stdout "$name" "$expected" "$tmp/$name.out"
}
run_native_x64_example_capture() {
source="$1"
name="$2"
shift 2
./v -v2 -no-parallel -b x64 "$source" -o "$tmp/$name"
"$tmp/$name" "$@" > "$tmp/$name.out" 2> "$tmp/$name.err"
check_empty_stderr "$name" "$tmp/$name.err"
}
check_random_ips_stdout() {
label="$1"
actual="$2"
python3 - "$label" "$actual" <<'PY'
import sys
label = sys.argv[1]
path = sys.argv[2]
lines = open(path, "r", encoding="utf-8").read().splitlines()
if len(lines) != 10:
raise SystemExit(f"{label}: expected 10 lines, got {len(lines)}")
rows = []
for line in lines:
parts = line.split(".")
if len(parts) != 4:
raise SystemExit(f"{label}: invalid IPv4 shape: {line!r}")
row = []
for part in parts:
if not part.isdigit():
raise SystemExit(f"{label}: non-numeric octet in {line!r}")
value = int(part)
if value < 0 or value > 254:
raise SystemExit(f"{label}: octet out of range in {line!r}")
row.append(value)
rows.append(tuple(row))
if len(set(rows)) < 3:
raise SystemExit(f"{label}: output has too little row diversity")
if all(row[1] == 0 for row in rows) and all(row[3] == 0 for row in rows):
raise SystemExit(f"{label}: suspicious old x.0.x.0 pattern")
PY
}
check_rule110_stdout() {
label="$1"
actual="$2"
width="$3"
python3 - "$label" "$actual" "$width" <<'PY'
import sys
label = sys.argv[1]
path = sys.argv[2]
width = int(sys.argv[3])
lines = open(path, "r", encoding="utf-8").read().splitlines()
title = "Rule 110 V Implementation"
title_lines = [idx for idx, line in enumerate(lines) if title in line]
if not title_lines:
raise SystemExit(f"{label}: missing title")
idx = title_lines[0]
generations = lines[idx + 1:]
if generations and generations[0] == "":
generations = generations[1:]
if len(generations) != width:
raise SystemExit(f"{label}: expected {width} generation lines, got {len(generations)}")
for line in generations:
if len(line) != width:
raise SystemExit(f"{label}: generation line has width {len(line)}, expected {width}: {line!r}")
if any(ch not in " *" for ch in line):
raise SystemExit(f"{label}: invalid generation chars: {line!r}")
if not any("*" in line for line in generations):
raise SystemExit(f"{label}: expected at least one live cell")
if len(set(generations)) < 3:
raise SystemExit(f"{label}: expected at least 3 distinct generation lines")
PY
}
write_v_run_expected() {
source="$1"
expected="$2"
shift 2
stderr="$tmp/$(basename "$expected").stderr"
./v run "$source" "$@" > "$expected" 2> "$stderr"
check_v_run_stderr "v run $source $*" "$stderr"
}
write_v_run_expected_with_stdin() {
source="$1"
input="$2"
expected="$3"
shift 3
stderr="$tmp/$(basename "$expected").stderr"
./v run "$source" "$@" < "$input" > "$expected" 2> "$stderr"
check_v_run_stderr "v run $source $*" "$stderr"
}
write_fizz_buzz_expected() {
i=1
while [ "$i" -le 100 ]; do
if [ $((i % 15)) -eq 0 ]; then
echo FizzBuzz
elif [ $((i % 3)) -eq 0 ]; then
echo Fizz
elif [ $((i % 5)) -eq 0 ]; then
echo Buzz
else
echo "$i"
fi
i=$((i + 1))
done
}
write_hanoi_expected() {
python3 - <<'PY'
def hanoi(n, a, b, c):
if n == 1:
print(f"Disc 1 from {a} to {c}...")
else:
hanoi(n - 1, a, c, b)
print(f"Disc {n} from {a} to {c}...")
hanoi(n - 1, b, a, c)
hanoi(7, "A", "B", "C")
PY
}
write_sudoku_expected() {
python3 - <<'PY'
import sys
puzzle = [
[0, 3, 0, 0, 7, 0, 0, 0, 0],
[0, 0, 0, 1, 3, 5, 0, 0, 0],
[0, 0, 1, 0, 0, 0, 0, 5, 0],
[1, 0, 0, 0, 6, 0, 0, 0, 3],
[4, 0, 0, 8, 0, 3, 0, 0, 1],
[7, 0, 0, 0, 2, 0, 0, 0, 6],
[0, 0, 0, 0, 0, 0, 2, 1, 0],
[0, 0, 0, 4, 1, 2, 0, 0, 5],
[0, 0, 0, 0, 0, 0, 0, 7, 4],
]
solution = [
[2, 3, 5, 6, 7, 8, 1, 4, 9],
[9, 4, 7, 1, 3, 5, 8, 6, 2],
[6, 8, 1, 2, 4, 9, 3, 5, 7],
[1, 2, 8, 7, 6, 4, 5, 9, 3],
[4, 5, 6, 8, 9, 3, 7, 2, 1],
[7, 9, 3, 5, 2, 1, 4, 8, 6],
[3, 6, 4, 9, 5, 7, 2, 1, 8],
[8, 7, 9, 4, 1, 2, 6, 3, 5],
[5, 1, 2, 3, 8, 6, 9, 7, 4],
]
def append_grid(lines, label, grid):
lines.append(label)
for i, row in enumerate(grid):
if i % 3 == 0 and i != 0:
lines.append("- - - - - - - - - - - -")
line = ""
for j, value in enumerate(row):
if j % 3 == 0 and j != 0:
line += " | "
line += f"{value} "
lines.append(line)
lines = []
append_grid(lines, "Sudoku Puzzle:", puzzle)
lines.append("Solving...")
append_grid(lines, "Solution:", solution)
out = ("\n".join(lines) + "\n").encode()
if len(out) != 582:
raise SystemExit(f"sudoku stdout oracle shape changed: {len(out)} bytes")
sys.stdout.buffer.write(out)
PY
}
write_tree_of_nodes_expected() {
cat <<'EOF'
tree structure:
Node{
value: 10
left: Tree(Node{
value: 30
left: Tree(Empty{})
right: Tree(Empty{})
})
right: Tree(Node{
value: 20
left: Tree(Empty{})
right: Tree(Empty{})
})
}
tree size: 3
EOF
}
write_js_hello_world_expected() {
printf 'Hello from V.js (0)\nHello from V.js (1)\nHello from V.js (2)\n'
}
write_vascii_expected() {
python3 - <<'PY'
from pathlib import Path
import sys
source = Path("examples/vascii.v").read_text(encoding="utf-8")
start_marker = "println('"
end_marker = "')"
if source.count(start_marker) != 1:
raise SystemExit("vascii stdout oracle expects one single-quoted println literal")
start = source.index(start_marker) + len(start_marker)
end = source.rindex(end_marker)
if source[end + len(end_marker):].strip() != "}":
raise SystemExit("vascii stdout oracle expects the println literal to be the final main statement")
out = bytearray()
literal = source[start:end]
i = 0
while i < len(literal):
ch = literal[i]
if ch == "\\":
i += 1
if i >= len(literal):
raise SystemExit("unterminated escape in vascii literal")
escaped = literal[i]
if escaped == "n":
out.append(10)
elif escaped == "t":
out.append(9)
elif escaped == "r":
out.append(13)
elif escaped == "\\":
out.append(92)
elif escaped == "'":
out.append(39)
elif escaped == '"':
out.append(34)
else:
out.extend(escaped.encode("utf-8"))
else:
out.extend(ch.encode("utf-8"))
i += 1
out.append(10)
sys.stdout.buffer.write(out)
PY
}
write_rune_expected() {
printf '\360\237\230\200\n@\n'
}
printf 'Hello, World!\n' > "$tmp/hello_world.expected"
write_fizz_buzz_expected > "$tmp/fizz_buzz.expected"
write_hanoi_expected > "$tmp/hanoi.expected"
write_sudoku_expected > "$tmp/sudoku.expected"
printf 'HELLO WORLD\nHELLO WORLD\nHELLO WORLD\n' > "$tmp/function_types.expected"
printf '5\n3\n' > "$tmp/submodule.expected"
printf '1\n1\n2\n3\n5\n8\n13\n21\n34\n55\n89\n' > "$tmp/fibonacci_10.expected"
printf '120\n' > "$tmp/dump_factorial.expected"
write_v_run_expected examples/primes.v "$tmp/primes_20.expected" 20
write_tree_of_nodes_expected > "$tmp/tree_of_nodes.expected"
write_js_hello_world_expected > "$tmp/js_hello_world.expected"
write_vascii_expected > "$tmp/vascii.expected"
write_rune_expected > "$tmp/rune.expected"
write_v_run_expected examples/graphs/bfs.v "$tmp/bfs.expected"
write_v_run_expected examples/graphs/bfs3.v "$tmp/bfs3.expected"
write_v_run_expected examples/graphs/dfs.v "$tmp/dfs.expected"
write_v_run_expected examples/graphs/dijkstra.v "$tmp/dijkstra.expected"
write_v_run_expected examples/graphs/topological_sorting_greedy.v "$tmp/topological_sorting_greedy.expected"
write_v_run_expected examples/graphs/topological_sorting_dfs.v "$tmp/topological_sorting_dfs.expected"
write_v_run_expected examples/graphs/dfs2.v "$tmp/dfs2.expected"
write_v_run_expected examples/graphs/minimal_spann_tree_prim.v "$tmp/minimal_spann_tree_prim.expected"
write_v_run_expected examples/graphs/bellman-ford.v "$tmp/bellman_ford.expected"
write_v_run_expected examples/binary_search_tree.v "$tmp/binary_search_tree.expected"
printf 'wrong format\nempty input\n' > "$tmp/errors.expected"
write_v_run_expected examples/custom_error.v "$tmp/custom_error.expected"
write_v_run_expected examples/spectral.v "$tmp/spectral_10.expected" 10
printf 'length of random array is 1000\nbefore quick sort whether array is sorted: false\nafter quick sort whether array is sorted: true\n' > "$tmp/quick_sort.expected"
printf 'hello\nworld\n' > "$tmp/get_raw_line.in"
write_v_run_expected_with_stdin examples/get_raw_line.v "$tmp/get_raw_line.in" "$tmp/get_raw_line.expected"
printf '3+4*2\nexit\n' > "$tmp/mini_calculator.in"
write_v_run_expected_with_stdin examples/mini_calculator.v "$tmp/mini_calculator.in" "$tmp/mini_calculator.expected"
printf '3+4*2\nexit\n' > "$tmp/mini_calculator_recursive_descent.in"
write_v_run_expected_with_stdin examples/mini_calculator_recursive_descent.v "$tmp/mini_calculator_recursive_descent.in" "$tmp/mini_calculator_recursive_descent.expected"
run_native_x64_example examples/hello_world.v hello_world "$tmp/hello_world.expected"
run_native_x64_example examples/fizz_buzz.v fizz_buzz "$tmp/fizz_buzz.expected"
run_native_x64_example examples/hanoi.v hanoi "$tmp/hanoi.expected"
run_native_x64_example examples/sudoku.v sudoku "$tmp/sudoku.expected"
run_native_x64_example examples/function_types.v function_types "$tmp/function_types.expected"
run_native_x64_example examples/submodule/main.v submodule "$tmp/submodule.expected"
run_native_x64_example examples/fibonacci.v fibonacci "$tmp/fibonacci_10.expected" 10
run_native_x64_example examples/dump_factorial.v dump_factorial "$tmp/dump_factorial.expected"
run_native_x64_example examples/primes.v primes "$tmp/primes_20.expected" 20
run_native_x64_example examples/tree_of_nodes.v tree_of_nodes "$tmp/tree_of_nodes.expected"
run_native_x64_example examples/js_hello_world.v js_hello_world "$tmp/js_hello_world.expected"
run_native_x64_example examples/vascii.v vascii "$tmp/vascii.expected"
run_native_x64_example examples/rune.v rune "$tmp/rune.expected"
run_native_x64_example examples/graphs/bfs.v bfs "$tmp/bfs.expected"
run_native_x64_example examples/graphs/bfs3.v bfs3 "$tmp/bfs3.expected"
run_native_x64_example examples/graphs/dfs.v dfs "$tmp/dfs.expected"
run_native_x64_example examples/graphs/dijkstra.v dijkstra "$tmp/dijkstra.expected"
run_native_x64_example examples/graphs/topological_sorting_greedy.v topological_sorting_greedy "$tmp/topological_sorting_greedy.expected"
run_native_x64_example examples/graphs/topological_sorting_dfs.v topological_sorting_dfs "$tmp/topological_sorting_dfs.expected"
run_native_x64_example examples/graphs/dfs2.v dfs2 "$tmp/dfs2.expected"
run_native_x64_example examples/graphs/minimal_spann_tree_prim.v minimal_spann_tree_prim "$tmp/minimal_spann_tree_prim.expected"
run_native_x64_example examples/graphs/bellman-ford.v bellman_ford "$tmp/bellman_ford.expected"
run_native_x64_example examples/binary_search_tree.v binary_search_tree "$tmp/binary_search_tree.expected"
run_native_x64_example examples/errors.v errors "$tmp/errors.expected"
run_native_x64_example examples/custom_error.v custom_error "$tmp/custom_error.expected"
run_native_x64_example examples/spectral.v spectral "$tmp/spectral_10.expected" 10
run_native_x64_example examples/quick_sort.v quick_sort "$tmp/quick_sort.expected"
run_native_x64_example_with_stdin examples/get_raw_line.v get_raw_line "$tmp/get_raw_line.in" "$tmp/get_raw_line.expected"
run_native_x64_example_with_stdin examples/mini_calculator.v mini_calculator "$tmp/mini_calculator.in" "$tmp/mini_calculator.expected"
run_native_x64_example_with_stdin examples/mini_calculator_recursive_descent.v mini_calculator_recursive_descent "$tmp/mini_calculator_recursive_descent.in" "$tmp/mini_calculator_recursive_descent.expected"
run_native_x64_example_capture examples/random_ips.v random_ips
check_random_ips_stdout random_ips "$tmp/random_ips.out"
run_native_x64_example_capture examples/rule110.v rule110 31
check_rule110_stdout rule110 "$tmp/rule110.out" 31
@@ -0,0 +1,7 @@
fn test_ci_run_with_32bit_compiler() {
$if x64 && tinyc {
// TODO: uncomment that next assert when tcc32 vs tcc64 detection on windows works reliably
// assert false
assert true
}
}
@@ -0,0 +1,5 @@
fn test_ci_run_with_64bit_compiler() {
$if x32 {
assert false
}
}
+58
View File
@@ -0,0 +1,58 @@
name: vlib modules CI
on:
pull_request:
paths:
- 'vlib/**.v'
- 'vlib/**.md'
- 'cmd/tools/vdoc/**.v'
- 'cmd/tools/vdoc/theme/**.js'
- 'cmd/tools/vdoc/theme/**.css'
- 'cmd/tools/vdoc/theme/**.svg'
- 'cmd/tools/vdoc/theme/**.html'
- '**/module_docs_ci.yml'
push:
branches:
- master
paths:
- 'vlib/**.v'
- 'vlib/**.md'
- 'cmd/tools/vdoc/**.v'
- 'cmd/tools/vdoc/theme/**.js'
- 'cmd/tools/vdoc/theme/**.css'
- 'cmd/tools/vdoc/theme/**.svg'
- 'cmd/tools/vdoc/theme/**.html'
- '**/module_docs_ci.yml'
# Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued.
# However, do NOT cancel in-progress runs as we want to allow these production deployments to complete.
concurrency:
group: module_docs-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: ${{ !contains(github.ref, 'master')}}
jobs:
build-module-docs:
runs-on: ubuntu-24.04
timeout-minutes: 20
steps:
- uses: actions/checkout@v7
- uses: ./.github/actions/cache-apt-packages-action
- name: Build V
run: make -j4 && ./v symlink
- name: Update packages, before running apt install
run: .github/workflows/disable_azure_mirror.sh && v retry -- sudo apt update -y -qq
- name: Install dependencies (some modules wrap C libs)
run: v retry -- sudo apt install --quiet -y libpq-dev
libsodium-dev libasound2-dev libssl-dev \
sqlite3 libsqlite3-dev libfreetype6-dev \
libx11-dev libxi-dev freeglut3-dev \
libgl1-mesa-dri libxcursor-dev libgl-dev libxrandr-dev libegl-dev
- name: Install markdown from vpm
run: v retry -- v install markdown
- name: Test v doc
run: VJOBS=1 ./v test cmd/tools/vdoc/
- name: Build module documentation and check the examples in the comments
run: VJOBS=1 ./v doc -m -f html -unsafe-run-examples -time vlib/
- name: Deploy docs to vercel
if: github.event_name == 'push' && github.repository == 'vlang/v' && github.ref == 'refs/heads/master'
run: npx vercel --confirm --prod --name vmodules --token ${{ secrets.VERCEL_TOKEN }} vlib/_docs/ || true
+21
View File
@@ -0,0 +1,21 @@
name: Code CI vlib modules
on:
push:
branches:
- master
paths:
- '**/cmd/tools/vdoc/theme/**'
pull_request:
paths:
- '**/cmd/tools/vdoc/theme/**'
jobs:
lint-module-docs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- name: Check Formatting
uses: creyD/prettier_action@v4.6
with:
prettier_options: --check cmd/tools/vdoc/theme
@@ -0,0 +1,45 @@
name: More extensive but slower tests
on:
push:
branches:
- master
paths-ignore:
- '**.md'
- '**.yml'
- '!**/more_extensive_but_slower_tests_ci.yml'
- 'examples/**'
- 'cmd/tools/**'
pull_request:
paths-ignore:
- '**.md'
- '**.yml'
- '!**/more_extensive_but_slower_tests_ci.yml'
- 'examples/**'
- 'cmd/tools/**'
concurrency:
group: slower_tests-${{ github.workflow }}-${{ github.ref == 'refs/heads/master' && github.sha || github.ref }}
cancel-in-progress: true
jobs:
more-tests:
strategy:
matrix:
os: [ubuntu-latest, macos-14, windows-latest]
runs-on: ${{ matrix.os }}
timeout-minutes: 20
steps:
- uses: actions/checkout@v7
- name: Build V
if: runner.os != 'Windows'
run: make -j4 && ./v symlink
- name: Build V (Windows)
if: runner.os == 'Windows'
run: ./makev.bat && ./v symlink
- name: Run additional crypto tests
run: |
v retry -- git clone --depth 1 https://github.com/vlang/slower_tests
v test slower_tests/
+103
View File
@@ -0,0 +1,103 @@
name: CI OpenBSD
on:
workflow_dispatch:
push:
branches:
- master
paths-ignore:
- '**.md'
- '**.yml'
- 'cmd/tools/**'
- '!**/openbsd_ci.yml'
- '!ci/openbsd_ci.vsh'
- '!cmd/tools/builders/**.v'
pull_request:
paths-ignore:
- '**.md'
- '**.yml'
- 'cmd/tools/**'
- '!**/openbsd_ci.yml'
- '!ci/openbsd_ci.vsh'
- '!cmd/tools/builders/**.v'
### See https://github.com/cross-platform-actions/action
### for a description of the used fields here
jobs:
tcc-openbsd:
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- uses: actions/checkout@v7
- name: Start OpenBSD VM for tcc
id: vm-openbsd-tcc
uses: cross-platform-actions/action@v1.2.0
with:
operating_system: openbsd
version: '7.8'
memory: 4G
sync_files: runner-to-vm
- name: Tests on OpenBSD with tcc
id: tests-openbsd-tcc
shell: cpa.sh {0}
run: |
sudo pkg_add git sqlite3 gmake boehm-gc libiconv
# Install packages needed to build examples
sudo pkg_add mariadb-client postgresql-client
# Mandatory: hostname not set in VM => some tests fail
sudo hostname -s openbsd-ci
echo "::group::OS infos"
uname -a
echo "::endgroup::"
echo "::group::Build V"
git config --global --add safe.directory .
gmake
sudo ./v symlink
export VTEST_SHOW_LONGEST_BY_RUNTIME=3
export VTEST_SHOW_LONGEST_BY_COMPTIME=3
export VTEST_SHOW_LONGEST_BY_TOTALTIME=3
export VFLAGS='-cc tcc -no-retry-compilation'
echo "::endgroup::"
./v run ci/openbsd_ci.vsh all
clang-openbsd:
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- uses: actions/checkout@v7
- name: Start OpenBSD VM for clang
id: vm-openbsd-clang
uses: cross-platform-actions/action@v1.2.0
with:
operating_system: openbsd
version: '7.8'
memory: 4G
sync_files: runner-to-vm
- name: Tests on OpenBSD with clang
id: tests-openbsd-clang
shell: cpa.sh {0}
run: |
sudo pkg_add git sqlite3 gmake boehm-gc libiconv
# Install packages needed to build examples
sudo pkg_add mariadb-client postgresql-client
# Mandatory: hostname not set in VM => some tests fail
sudo hostname -s openbsd-ci
echo "::group::OS infos"
uname -a
clang -v
echo "::endgroup::"
echo "::group::Build V"
git config --global --add safe.directory .
gmake
sudo ./v symlink
export VTEST_SHOW_LONGEST_BY_RUNTIME=3
export VTEST_SHOW_LONGEST_BY_COMPTIME=3
export VTEST_SHOW_LONGEST_BY_TOTALTIME=3
export VFLAGS='-cc clang'
echo "::endgroup::"
./v run ci/openbsd_ci.vsh all
+192
View File
@@ -0,0 +1,192 @@
name: Other CI
on:
workflow_dispatch:
push:
branches:
- master
paths-ignore:
- '**.md'
- '**.yml'
- '!**/other_ci.yml'
- 'cmd/tools/**'
- '!cmd/tools/builders/**.v'
pull_request:
paths-ignore:
- '**.md'
- '**.yml'
- '!**/other_ci.yml'
- 'cmd/tools/**'
- '!cmd/tools/builders/**.v'
concurrency:
group: other-${{ github.workflow }}-${{ github.ref == 'refs/heads/master' && github.sha || github.ref }}
cancel-in-progress: true
jobs:
performance-compare-with-master:
runs-on: ubuntu-24.04
timeout-minutes: 30
steps:
- uses: actions/checkout@v7
with:
fetch-depth: 0
- name: Environment info
run: echo "$VFLAGS $GITHUB_SHA $GITHUB_REF"
- name: Name the local git branch
run: git checkout -b the_v_pr_branch
- name: Build local v
run: make && ./v symlink
- name: V version
run: ./v version
- name: Build the repeat tool
run: ./v cmd/tools/vrepeat.v
- name: Run compare_pr_to_master.v
run: VREPEAT_SILENT=1 ./v run .github/workflows/compare_pr_to_master.v
prevent-gpl-licenses:
runs-on: ubuntu-24.04
timeout-minutes: 20
steps:
- name: Checkout V ${{ github.head_ref }}
uses: actions/checkout@v7
with:
path: v
- name: Checkout V master
uses: actions/checkout@v7
with:
repository: vlang/v
path: vmaster
- name: Detect potentially added GPL licensed code
run: |
gpl_search_cmd="grep 'GPL' -r --exclude-dir=.git --exclude=*.yml --exclude=*.md --exclude=*.vv --exclude=*_test.v ."
cd vmaster
eval "$gpl_search_cmd" > ../gpl_res_vmaster
cd ../v
eval "$gpl_search_cmd" > ../gpl_res_vnew
cd ..
diff -d -a -U 2 --color=always gpl_res_vmaster gpl_res_vnew
code-formatting:
runs-on: ubuntu-24.04
timeout-minutes: 20
env:
VFLAGS: -cc gcc
steps:
- uses: actions/checkout@v7
- name: Environment info
run: echo "$VFLAGS $GITHUB_SHA $GITHUB_REF"
- name: Build local v
run: make -j4 && ./v symlink
- name: v test-cleancode
run: ./v -silent test-cleancode
- name: v test-fmt
run: ./v -silent test-fmt
performance-regressions:
runs-on: ubuntu-24.04
timeout-minutes: 20
env:
VFLAGS: -cc gcc
steps:
- uses: actions/checkout@v7
- name: Environment info
run: echo "$VFLAGS $GITHUB_SHA $GITHUB_REF"
- name: Build local v
run: make -j4 && ./v symlink
- name: Clone & Build previous vmaster/v
run: |
./v retry -- git clone --depth=1 https://github.com/vlang/v vmaster/
(cd vmaster; make -j4)
- name: V versions
run: ./v version && ./vmaster/v version
- name: Build the repeat tool
run: ./v cmd/tools/vrepeat.v
- name: Repeat -o hw.c examples/hello_world.v
run: ./v repeat --max_time 280 --series 3 --runs 20 --nmins 2 --nmaxs 5 --warmup 3 --fail_percent 10 -t 'cd {T} ; ./v -o hw.c examples/hello_world.v' . ./vmaster
- name: Repeat -o v.c cmd/v
run: ./v repeat --max_time 4000 --series 3 --runs 20 --nmins 2 --nmaxs 5 --warmup 3 --fail_percent 10 -t 'cd {T} ; ./v -o v.c cmd/v' . ./vmaster
misc-tooling:
runs-on: ubuntu-24.04
timeout-minutes: 20
env:
VFLAGS: -cc tcc -no-retry-compilation
steps:
- uses: actions/checkout@v7
with:
fetch-depth: 10
- uses: ./.github/actions/cache-apt-packages-action
- name: Build v
run: make -j4 && ./v symlink
- name: Install dependencies
run: |
.github/workflows/disable_azure_mirror.sh
./v retry -- sudo apt update
./v retry -- sudo apt install --quiet -y libsodium-dev libssl-dev sqlite3 libsqlite3-dev postgresql libpq-dev valgrind
./v retry -- sudo apt install --quiet -y libfreetype6-dev libxi-dev libxcursor-dev libgl-dev libxrandr-dev libasound2-dev xfonts-75dpi xfonts-base libegl-dev
./v retry -- sudo apt install --quiet -y g++-9 g++-10
- name: g++-9 version
run: g++-9 --version
- name: V self compilation with g++ and -std=c++11
run: ./v -cc g++-9 -no-std -cflags -std=c++11 -o v2 cmd/v && ./v2 -cc g++-9 -no-std -cflags -std=c++11 -o v3 cmd/v
- name: g++-10 version
run: g++-10 --version
- name: V self compilation with g++ and -std=c++20
run: ./v -cc g++-10 -no-std -cflags -std=c++20 -o v2 cmd/v && ./v2 -cc g++-10 -no-std -cflags -std=c++20 -o v3 cmd/v
# TODO: re-enable once autofree is fixed; see https://github.com/vlang/v/issues/27116
# - name: Ensure V can be compiled with -autofree
# run: ./v -autofree cmd/v
- name: Ensure V can be compiled with -no-closures
run: ./v -no-closures cmd/v
- name: Shader examples can be built
run: |
.github/workflows/compile_shaders_in_examples.sh
./v should-compile-all examples/sokol/*.v examples/sokol/0?*/*.v
parser-silent:
runs-on: ubuntu-24.04
timeout-minutes: 30
steps:
- uses: actions/checkout@v7
- name: Build local v
run: |
make -j4 && ./v symlink
./v -g -d trace_parse_stmt cmd/tools/vtest-parser.v
- name: Install zzuf
run: ./v retry -- sudo apt install -qq zzuf
- name: Run test-parser
run: |
./v test-parser --show_source --linear examples/hello_world.v
./v test-parser --show_source --linear examples/hanoi.v
./v test-parser --show_source --linear examples/fibonacci.v
./v test-parser --show_source --linear examples/cli.v
./v test-parser --show_source --linear examples/json.v
./v test-parser --show_source --linear examples/vmod.v
./v test-parser --show_source --linear examples/regex/regex_example.v
./v test-parser --show_source --linear examples/2048/2048.v
- name: Run test-parser over fuzzed files
run: |
zzuf -R '\x00-\x20\x7f-\xff' -r0.01 < examples/hello_world.v > examples/hello_world_fuzz.v
zzuf -R '\x00-\x20\x7f-\xff' -r0.01 < examples/hanoi.v > examples/hanoi_fuzz.v
zzuf -R '\x00-\x20\x7f-\xff' -r0.01 < examples/fibonacci.v > examples/fibonacci_fuzz.v
zzuf -R '\x00-\x20\x7f-\xff' -r0.01 < examples/cli.v > examples/cli_fuzz.v
zzuf -R '\x00-\x20\x7f-\xff' -r0.01 < examples/json.v > examples/json_fuzz.v
zzuf -R '\x00-\x20\x7f-\xff' -r0.01 < examples/vmod.v > examples/vmod_fuzz.v
zzuf -R '\x00-\x20\x7f-\xff' -r0.01 < examples/regex/regex_example.v > examples/regex_example_fuzz.v
zzuf -R '\x00-\x20\x7f-\xff' -r0.01 < examples/2048/2048.v > examples/2048/2048_fuzz.v
./v test-parser --show_source --linear examples/hello_world_fuzz.v
./v test-parser --show_source --linear examples/fibonacci_fuzz.v
./v test-parser --show_source --linear examples/hanoi_fuzz.v
./v test-parser --show_source --linear examples/cli_fuzz.v
./v test-parser --show_source --linear examples/json_fuzz.v
./v test-parser --show_source --linear examples/vmod_fuzz.v
./v test-parser --show_source --linear examples/regex_example_fuzz.v
./v test-parser --show_source --linear examples/2048/2048_fuzz.v
+117
View File
@@ -0,0 +1,117 @@
name: Path Testing CI
on:
workflow_dispatch:
push:
branches:
- master
paths-ignore:
- '**.md'
- '**.yml'
- '!**/paths_ci.yml'
- 'cmd/tools/**'
- '!cmd/tools/builders/**.v'
pull_request:
paths-ignore:
- '**.md'
- '**.yml'
- '!**/paths_ci.yml'
- 'cmd/tools/**'
- '!cmd/tools/builders/**.v'
concurrency:
group: paths-${{ github.workflow }}-${{ github.ref == 'refs/heads/master' && github.sha || github.ref }}
cancel-in-progress: true
jobs:
space-paths-linux:
runs-on: ubuntu-24.04
timeout-minutes: 20
steps:
- uses: actions/checkout@v7
with:
persist-credentials: false
path: '你好 my $path, @с интервали'
- name: Build V
run: |
# shellcheck disable=SC2016
echo '你好 my $path, @с интервали'
ls -la
# shellcheck disable=SC2016
cd '你好 my $path, @с интервали'
ls -la
make
- name: v doctor
run: |
# shellcheck disable=SC2016
cd '你好 my $path, @с интервали'
./v doctor
- name: v tests
run: |
# shellcheck disable=SC2016
cd '你好 my $path, @с интервали'
./v test vlib/builtin vlib/os
space-paths-macos:
runs-on: macos-14
timeout-minutes: 30
steps:
- uses: actions/checkout@v7
with:
path: '你好 my $path, @с интервали'
persist-credentials: false
- name: Build V
run: |
# shellcheck disable=SC2016
echo '你好 my $path, @с интервали'
ls -la
# shellcheck disable=SC2016
cd '你好 my $path, @с интервали'
ls -la
make
## prebuild cmd/tools/builders/js_builder, to minimise the
## chances of a sporadic "Killed" when running the tests later
./v -b js run examples/hello_world.v
- name: v doctor
run: |
# shellcheck disable=SC2016
cd '你好 my $path, @с интервали'
./v doctor
- name: v tests
run: |
# shellcheck disable=SC2016
cd '你好 my $path, @с интервали'
./v test vlib/builtin vlib/os
space-paths-windows:
runs-on: windows-2022
timeout-minutes: 30
## NB: the following paths do not work for now:
##### MY_V_PATH: '你好 my $path, @с интервали'
##### MY_V_PATH: 'path with some $punctuation, and some spaces '
## tcc has a problem interpreting paths with non latin letters in them,
## by default, but that can be solved with passing -Bthirdparty/tcc
## but after that V fails self building with:
####### builder error: cannot write to folder
####### D:\a\v\v\你好 my $path, @с интервали: No such file or directory
## and that happens even for gcc builds, not just tcc ones
steps:
- uses: actions/checkout@v7
with:
path: 'path with some $punctuation, and some spaces'
persist-credentials: false
- name: Build V
run: |
echo 'path with some $punctuation, and some spaces'
dir
cd 'path with some $punctuation, and some spaces'
dir
.\makev.bat -tcc
- name: v doctor
run: |
cd 'path with some $punctuation, and some spaces'
./v doctor
- name: v tests
run: |
cd 'path with some $punctuation, and some spaces'
./v test vlib/builtin vlib/os
+42
View File
@@ -0,0 +1,42 @@
name: Periodic CI
on:
schedule:
- cron: '0 */6 * * *'
push:
branches:
- master
paths:
- '**/periodic_ci.yml'
pull_request:
paths:
- '**/periodic_ci.yml'
jobs:
periodic-network:
strategy:
matrix:
include:
- os: ubuntu-latest
cc: tcc
- os: windows-latest
cc: msvc
- os: macos-latest
cc: clang
fail-fast: false
runs-on: ${{ matrix.os }}
if: github.event_name != 'schedule' || (github.ref == 'refs/heads/master' && github.repository == 'vlang/v')
timeout-minutes: 30
env:
VFLAGS: -cc ${{ matrix.cc }}
V_CI_PERIODIC: 1
steps:
- uses: actions/checkout@v7
- name: Build
if: runner.os != 'Windows'
run: make -j4 && ./v -showcc -o v cmd/v && ./v doctor
- name: Build V (Windows)
if: runner.os == 'Windows'
run: ./makev.bat -msvc && ./v -o v2.exe cmd/v && ./v2 -showcc -o v.exe cmd/v && ./v doctor
- name: Test
run: ./v -d network -silent test-self vlib/net
+71
View File
@@ -0,0 +1,71 @@
name: Test prebuilt binaries
on:
workflow_dispatch:
release:
types: [edited, published]
jobs:
prebuilt-linux:
runs-on: ubuntu-24.04
timeout-minutes: 5
steps:
- name: Download V
run: |
.github/workflows/retry.sh wget https://github.com/vlang/v/releases/latest/download/v_linux.zip
unzip v_linux.zip
cd v
./v -version
- name: Test V
run: |
cd v
./v run examples/hello_world.v
./v -showcc -gc none -cc tcc -no-retry-compilation run examples/hello_world.v
prebuilt-macos-arm64:
## macos-14 is a m1 runner
runs-on: macos-14
timeout-minutes: 5
steps:
- name: Download V
run: |
.github/workflows/retry.sh wget https://github.com/vlang/v/releases/latest/download/v_macos_arm64.zip
unzip v_macos_arm64.zip
cd v
./v -version
- name: Test V
run: |
cd v
./v run examples/hello_world.v
./v -showcc -gc none -cc tcc -no-retry-compilation run examples/hello_world.v
prebuilt-macos-x86_64:
runs-on: macos-latest
timeout-minutes: 5
steps:
- name: Download V
run: |
.github/workflows/retry.sh wget https://github.com/vlang/v/releases/latest/download/v_macos_x86_64.zip
unzip v_macos_x86_64.zip
cd v
./v -version
- name: Test V
run: |
cd v
./v run examples/hello_world.v
prebuilt-windows:
runs-on: windows-latest
timeout-minutes: 5
steps:
- name: Download V
run: |
curl -L https://github.com/vlang/v/releases/latest/download/v_windows.zip -o v_windows.zip
unzip .\v_windows.zip
cd v
.\v.exe -version
- name: Test V
run: |
cd v
.\v.exe run .\examples\hello_world.v
.\v.exe -showcc -gc none -cc tcc -no-retry-compilation run .\examples/hello_world.v
+62
View File
@@ -0,0 +1,62 @@
name: Shy and PV CI
on:
workflow_dispatch:
push:
branches:
- master
paths:
- 'vlib/v/checker/**.v'
- 'vlib/v/gen/c/**.v'
- 'thirdparty/**'
- 'cmd/tools/builders/**.v'
- 'cmd/tools/vshader.v'
- '**/puzzle_vibes_ci.yml'
- '!**_test.v'
- '!**.md'
pull_request:
paths:
- 'vlib/v/checker/**'
- 'vlib/v/gen/c/**'
- 'thirdparty/**'
- 'cmd/tools/builders/**.v'
- 'cmd/tools/vshader.v'
- '**/puzzle_vibes_ci.yml'
- '!**_test.v'
- '!**.md'
concurrency:
group: puzzle_vibes-${{ github.workflow }}-${{ github.ref == 'refs/heads/master' && github.sha || github.ref }}
cancel-in-progress: true
jobs:
v-compiles-puzzle-vibes:
runs-on: ubuntu-24.04
timeout-minutes: 20
steps:
- uses: actions/checkout@v7
- uses: ./.github/actions/cache-apt-packages-action
- name: Build V
run: make && ./v symlink
- name: Install & Setup SDL
run: v retry -- v install sdl && v ~/.vmodules/sdl/setup.vsh
- name: Install Shy
run: v retry -- v install https://github.com/medvednikov/shy
- name: Clone Puzzle Vibes
run: v retry -- git clone https://github.com/medvednikov/puzzle_vibes/
- name: Check PV compiles with -g
run: cd puzzle_vibes && v -g .
- name: Check PV compiles
run: cd puzzle_vibes && v .
- name: Check PV compiles with -prod
run: cd puzzle_vibes && v -prod -no-prod-options .
- name: Check PV compiles with -prod and -g
run: cd puzzle_vibes && v -prod -g -no-prod-options .
+128
View File
@@ -0,0 +1,128 @@
name: Release CI
on:
workflow_dispatch:
pull_request:
paths:
- '.github/workflows/release_ci.yml'
push:
paths:
- '.github/workflows/release_ci.yml'
tags:
- weekly.**
- 0.**
concurrency:
group: release-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: ${{ github.ref_type != 'tag' }}
permissions:
contents: write
jobs:
release-build:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os:
[
ubuntu-22.04,
ubuntu-22.04-arm,
macos-15-intel,
macos-15,
windows-latest,
]
include:
- os: ubuntu-22.04
cc: gcc
target: linux
artifact: v_linux.zip
- os: ubuntu-22.04-arm
cc: gcc
target: linux_arm64
artifact: v_linux_arm64.zip
- os: macos-15-intel
cc: clang
target: macos_x86_64
artifact: v_macos_x86_64.zip
- os: macos-15
cc: clang
target: macos_arm64
artifact: v_macos_arm64.zip
- os: windows-latest
cc: msvc
target: windows
artifact: v_windows.zip
fail-fast: false
steps:
- uses: actions/checkout@v7
- name: Compile release binaries
if: runner.os != 'Windows'
run: |
make
./v -cc ${{ matrix.cc }} ${{ matrix.cflags }} -prod -o v cmd/v
./v -cc ${{ matrix.cc }} ${{ matrix.cflags }} -prod cmd/tools/vup.v
./v -cc ${{ matrix.cc }} ${{ matrix.cflags }} -prod cmd/tools/vdoctor.v
- name: Compile release binaries (Windows)
if: runner.os == 'Windows'
run: |
./makev.bat -msvc
./v -prod -cc msvc -o cmd/vprod.exe cmd/v
./v -prod -cc msvc cmd/tools/vup.v
./v -prod -cc msvc cmd/tools/vdoctor.v
del ./*.exe
del ./*.tmp.obj
move cmd/vprod.exe v.exe
- name: Prepare artifact
shell: bash
run: |
if [[ ${{ matrix.os }} == 'macos-14' ]]; then
rm -rf thirdparty/tcc
git clone --branch thirdparty-macos-arm64 --depth=1 https://github.com/vlang/tccbin thirdparty/tcc
fi
# Remove excluded
if [[ $RUNNER_OS == 'Windows' ]]; then
find . -type f \( -name "*.ilk" -o -name "*.pdb" \) -exec rm -rf {} +
rm -rf v_old.exe
fi
find . -type d -name ".git" -exec rm -rf {} +
rm -rf vc/
rm -rf v_old
rm -rf vlib/v/tests/bench/gcboehm/*.svg.xz
- name: Create ZIP archive
shell: bash
run: |
cd ..
if [[ $RUNNER_OS == 'Windows' ]]; then
7z a -tzip ${{ matrix.artifact }} v/
else
zip -r9 --symlinks ${{ matrix.artifact }} v/
fi
zipinfo ${{ matrix.artifact }}
mv ${{ matrix.artifact }} v/
cd v/
- name: Create artifact
uses: actions/upload-artifact@v7
with:
name: ${{ matrix.target }}
path: ${{ matrix.artifact }}
release-publish:
if: github.ref_type == 'tag'
needs: release-build
runs-on: ubuntu-latest
steps:
- uses: actions/download-artifact@v8
- name: Create release
uses: ncipollo/release-action@v1
with:
artifacts: |
~/work/v/v/windows/v_windows.zip
~/work/v/v/linux/v_linux.zip
~/work/v/v/linux_arm64/v_linux_arm64.zip
~/work/v/v/macos_arm64/v_macos_arm64.zip
~/work/v/v/macos_x86_64/v_macos_x86_64.zip
tag: ${{ github.ref_name }}
name: ${{ github.ref_name }}
draft: false
prerelease: false
+22
View File
@@ -0,0 +1,22 @@
#!/usr/bin/env bash
cmd=$@
function elog() {
message=$1
printf "%(%Y/%m/%d %H:%M:%S)T | retry.sh $1\n"
}
declare -i iteration=0
declare -i max_iterations=9
for((iteration=1;iteration<=max_iterations;iteration++)); do
elog "iteration: $iteration/$max_iterations, cmd: $cmd"
if $cmd; then
exit 0
fi
elog "command failed, retrying ...";
sleep 1;
done;
elog "failed doing $max_iterations iterations of command: $cmd"
exit 1
+56
View File
@@ -0,0 +1,56 @@
name: riscv64 CI
on:
workflow_dispatch:
push:
branches:
- master
paths-ignore:
- '**.md'
- '**.yml'
- '!**/riscv64_linux_ci.yml'
- 'cmd/tools/**'
- '!cmd/tools/builders/**.v'
pull_request:
paths-ignore:
- '**.md'
- '**.yml'
- '!**/riscv64_linux_ci.yml'
- 'cmd/tools/**'
- '!cmd/tools/builders/**.v'
jobs:
riscv64_linux:
# The host should always be Linux
runs-on: ubuntu-24.04
timeout-minutes: 30
name: Build on ubuntu-24.04 riscv64
steps:
- uses: actions/checkout@v7
- uses: uraimo/run-on-arch-action@v3
name: Run commands
id: runcmd
with:
arch: riscv64
distro: ubuntu24.04
base_image: --platform=linux/riscv64 riscv64/ubuntu:24.04
# The token tag here is not required, but speeds up builds,
# by allowing caching of the installed dependencies, which is ~2.5min:
githubToken: ${{ github.token }}
shell: /bin/bash
install: |
apt-get update -q -y
apt-get install -q -y make gcc git file coreutils binutils
run: |
uname -a
make --version
gcc --version
ls -la
export LDFLAGS="-latomic"
export VFLAGS="-gc none -no-retry-compilation -cc cc"
make
file ./v
ls -la ./v
./v test vlib/builtin vlib/os vlib/encoding/binary
./v test vlib/v/slow_tests/assembly
VTEST_ONLY=closure ./v test vlib/v/tests
+25
View File
@@ -0,0 +1,25 @@
#!/usr/bin/env bash
export PS4='\033[0;33m+ >>>>> (${BASH_SOURCE}:${LINENO}): ${FUNCNAME[0]:+${FUNCNAME[0]}(): }\033[0m'
set -xe
echo " Setup environment ..."
export DEBUG_OPTS=${DEBUG_OPTS:-"-keepc -cg -cflags -fno-omit-frame-pointer"}
export VFLAGS=${VFLAGS:-"-cc clang"}
v version
v -show-c-output -cflags --version -e ';' || true
echo " Compile and run sanitizers ..."
v ${VFLAGS} ${DEBUG_OPTS} -o v2 cmd/v -cflags -fsanitize=memory
UBSAN_OPTIONS="print_stacktrace=1:halt_on_error=1" ./v2 -o v.c cmd/v
v ${VFLAGS} ${DEBUG_OPTS} -o v3 cmd/v -cflags -fsanitize=thread
TSAN_OPTIONS="suppressions=.github/workflows/run_sanitizers_thread.suppressions" UBSAN_OPTIONS="print_stacktrace=1:halt_on_error=1" ./v3 -o v.c cmd/v
v ${VFLAGS} ${DEBUG_OPTS} -o v4 cmd/v -cflags -fsanitize=undefined
UBSAN_OPTIONS="suppressions=.github/workflows/run_sanitizers_undefined.suppressions:print_stacktrace=1:halt_on_error=1" ./v4 -o v.c cmd/v
v ${VFLAGS} ${DEBUG_OPTS} -o v5 cmd/v -cflags -fsanitize=address,pointer-compare,pointer-subtract
ASAN_OPTIONS="detect_leaks=0" UBSAN_OPTIONS="print_stacktrace=1:halt_on_error=1" ./v5 -o v.c cmd/v
@@ -0,0 +1,16 @@
# websocket/ssl tests
leak:mbedtls_ssl_setup
leak:mbedtls_ssl_tls13_compute_application_transform
leak:rsa_alloc_wrap
leak:mbedtls_pk_parse
# sqlite tests
leak:*sqlite*
# v
leak:v__*
leak:os__*
leak:string__plus
leak:malloc_uncollectable
leak:new_array_from_c_array
leak:_vinit
@@ -0,0 +1,5 @@
## See https://github.com/google/sanitizers/wiki/ThreadSanitizerSuppressions
## and https://clang.llvm.org/docs/ThreadSanitizer.html
## The sync__stdatomic__add_i64 and sync__stdatomic__sub_i64 suppressions below, are needed for clang-10 to clang-12; clang-18 is fine without them
race:sync__stdatomic__add_i64
race:sync__stdatomic__sub_i64
@@ -0,0 +1,186 @@
## See https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html
## Most of the supressed functions here use asserts, that in turn use an indirection through an interface. TODO: if that is solved, most of these can be removed.
## Usually they contain a __test_ in their name, but not always (see the x.ttf ones like vlib/x/ttf/ttf_test.v ).
## TODO: extract the common part of the assertions to a VDO_ function (1 for pass and 1 for failure), so that they can be whitelisted here just once.
function:map_exists
function:map_get
function:IError_str
shift-exponent:math__bits__rotate_left_64
shift-exponent:math__bits__div_64
function:math__big__Integer_general_radix_str
function:math__big__Integer_div_mod_internal
function:math__bits__test_bits
function:math__bits__test_div_64_edge_cases
function:math__test_nan
alignment:rand__read_64
function:rand__internal_ulid_at_millisecond
function:rand__internal_string_from_set
function:rand__internal_uuid_v4
function:rand__deinit
function:rand__read_internal
function:rand__read_64
function:rand__PRNG_f64
function:rand__cuid2__test_cuid2
function:sync__pool__process_in_thread
function:sync__Once_do_slow_with_param
function:v__gen__c__FunctionDeferCollector_visit
function:v__gen__c__collect_function_defer_stmts
function:v__type_resolver__TypeResolver_resolve_fn_generic_args
function:v__type_resolver__TypeResolver_unwrap_generic_expr
function:v__type_resolver__TypeResolver_get_type
## these have asserts in them, and trigger due to the used indirection; TODO: remove them, when a more general solution is found for all interfaces
function:x__ttf__TTF_File_get_glyph_offset
function:x__ttf__TTF_File_get_horizontal_metrics
function:x__ttf__TTF_File_glyph_count
function:x__ttf__TTF_File_read_glyph
function:x__ttf__TTF_File_read_simple_glyph
function:x__ttf__TTF_File_read_kern_table
function:x__ttf__TTF_File_read_hhea_table
function:x__ttf__TTF_File_read_cmap_table
function:x__ttf__TTF_File_read_name_table
function:x__ttf__TTF_File_read_head_table
function:x__ttf__TTF_File_read_offset_tables
function:net__unix__select_deadline
function:net__select_deadline
function:net__socks__test_parse_ipv4
function:net__http__download_file_with_progress
function:net__http__download_progres_cb
function:net__http__check_headers
function:net__http__test_str
function:net__http__test_int
function:net__http__test_is_valid
function:net__http__test_is_error
function:net__http__test_is_success
function:net__http__test_parse_response_with_weird_cookie
function:net__http__test_parse_response_with_cookies
function:net__http__test_parse_response
function:net__http__test_response_bytestr_1
function:net__http__test_response_bytestr_2
function:net__http__test_parse_large_body
function:net__http__test_multipart_form_body
function:net__http__test_parse_multipart_form2
function:net__http__test_parse_request_no_headers
function:net__http__test_parse_multipart_form
function:net__http__test_parse_form
function:net__http__test_parse_request_line
function:net__http__test_parse_request_body
function:net__http__test_parse_request_two_header_values
function:net__http__test_parse_request_no_headers
function:net__http__test_parse_request_two_headers
function:net__http__test_proxy_fields
function:net__http__test_proxy_headers
function:net__http__test_set_cookie
function:net__http__test_parse_headers
function:net__http__parse_headers_test
function:net__http__test_header_join
function:net__http__test_header_from_map
function:net__http__test_custom_header_from_map
function:net__http__test_render_coerce_canonicalize
function:net__http__test_render_canonicalize
function:net__http__test_render_version
function:net__http__test_coerce_canonicalize_custom
function:net__http__test_coerce_custom
function:net__http__test_coerce_canonicalize
function:net__http__test_coerce
function:net__http__test_custom_values
function:net__http__test_starting_with
function:net__http__test_get_custom
function:net__http__test_contains_custom
function:net__http__test_custom_header
function:net__http__test_delete_header
function:net__http__test_header_delete_not_existing
function:net__http__test_header_delete
function:net__http__test_header_set
function:net__http__test_header_get
function:net__http__test_header_adds_multiple
function:net__http__test_header_new
function:net__test_ip6_str
function:net__test_ip_str
function:net__test_sizes_unix
function:net__test_sizes_ipv4
function:net__test_sizes_ipv6
function:net__test_offsets_unix
function:net__test_offsets_ipv4
function:net__test_offsets_ipv6
function:net__test_sizes_unix_sun_path
function:net__test_diagnostics
function:net__test_ip_port
function:net__websocket__delete_client_cb
function:net__websocket__Server_listen
function:net__websocket__Server_serve_client
function:net__websocket__Server_parse_client_handshake
function:net__websocket__Client_listen
function:net__websocket__Client_send_message_event
function:net__websocket__Client_send_close_event
function:net__websocket__Client_debug_log
function:net__websocket__Client_connect
function:io__BufferedReader_fill_buffer
function:io__read_all
function:log__info
function:log__debug
function:log__warn
function:log__error
function:log__set_level
function:log__Log_log_stream
function:log__free_logger
function:picoev__Picoev_poll_once
function:picoev__Picoev_set_timeout
function:picoev__Picoev_update_events
function:picoev__test_if_all_file_descriptors_are_properly_initialized
function:veb__RoutePair_test_param
function:veb__test_load_files_translations
## needed for tests; TODO: move the test specific setup code into its own separate VDO_tests function, so only it can be added here
function:main
function:crypto__sha3__test_0_length_hash
function:crypto__sha3__test_0_length_xof
function:crypto__sha3__test_200_length_hash
function:crypto__sha3__test_200_length_xof
function:crypto__sha3__test_2_x_24_rounds_on_zero
function:crypto__sha3__test_stepping_functions_on_zero
function:crypto__sha3__test_zero_state
function:crypto__sha3__test_rho_offsets
function:crypto__sha3__test_to_from_bytes
function:crypto__sha3__test_round_constants
function:crypto__pem__test_decode_rfc1421
function:crypto__pem__test_decode
function:crypto__pem__test_encode_rfc1421
function:crypto__pem__test_encode
function:crypto__hmac__test_hmac_equal
function:crypto__hmac__test_hmac_sha3_224
function:crypto__hmac__test_hmac_sha3_256
function:crypto__hmac__test_hmac_sha3_384
function:crypto__hmac__test_hmac_sha3_512
function:crypto__hmac__test_hmac_blake3_256
function:crypto__hmac__test_hmac_blake2b_160
function:crypto__hmac__test_hmac_blake2b_256
function:crypto__hmac__test_hmac_blake2b_384
function:crypto__hmac__test_hmac_blake2b_512
function:crypto__hmac__test_hmac_blake2s_128
function:crypto__hmac__test_hmac_blake2s_160
function:crypto__hmac__test_hmac_blake2s_224
function:crypto__hmac__test_hmac_blake2s_256
function:crypto__hmac__test_hmac_sha512
function:crypto__hmac__test_hmac_sha384
function:crypto__hmac__test_hmac_sha256
function:crypto__hmac__test_hmac_sha224
function:crypto__hmac__test_hmac_sha1
function:crypto__hmac__test_hmac_md5
function:crypto__ed25519__internal__edwards25519__sc_reduce
function:crypto__ed25519__internal__edwards25519__sc_reduce
+53
View File
@@ -0,0 +1,53 @@
name: s390 CI
on:
workflow_dispatch:
push:
branches:
- master
paths-ignore:
- '**.md'
- '**.yml'
- '!**/s390x_linux_ci.yml'
- 'cmd/tools/**'
- '!cmd/tools/builders/**.v'
pull_request:
paths-ignore:
- '**.md'
- '**.yml'
- '!**/s390x_linux_ci.yml'
- 'cmd/tools/**'
- '!cmd/tools/builders/**.v'
jobs:
s390x_linux:
# The host should always be Linux
runs-on: ubuntu-22.04
timeout-minutes: 30
name: Build on ubuntu-22.04 s390x
steps:
- uses: actions/checkout@v7
- uses: uraimo/run-on-arch-action@v3
name: Run commands
id: runcmd
with:
arch: s390x
distro: ubuntu22.04
base_image: --platform=linux/s390x s390x/ubuntu:22.04
# The token tag here is not required, but speeds up builds,
# by allowing caching of the installed dependencies, which is ~2.5min:
githubToken: ${{ github.token }}
shell: /bin/bash
install: |
apt-get update -q -y
apt-get install -q -y make gcc git file coreutils binutils
run: |
uname -a
make --version
gcc --version
ls -la
make
file ./v
ls -la ./v
./v test vlib/builtin vlib/os vlib/encoding/binary
./v test vlib/v/tests/fns/closure_test.v
+327
View File
@@ -0,0 +1,327 @@
name: Sanitized CI
## Running these jobs is slow (over ~1 hour, sometimes even 2)
## so we run them only when there is a chance that the generated
## C code could have changed, or for some critical vlib modules,
## like `builtin`, `os`, `sync`, where they have demonstrated
## their usefulness by catching actual very hard to find bugs.
## The cost of this selective running is delayed feedback when
## there are bugs in other V modules.
## The positive is *much faster CI runs* for most V contributors,
## that make PRs that are not concerning V itself, or the critical
## V modules.
on:
workflow_dispatch:
push:
branches:
- master
paths:
- '!**'
- '!**.md'
- '!**.yml'
- 'vlib/builtin/**.v'
- 'vlib/strconv/**.v'
- 'vlib/strings/**.v'
- 'vlib/math/**.v'
- 'vlib/math/big/**.v'
- 'vlib/arrays/**.v'
- 'vlib/crypto/ecdsa/**.v'
- 'vlib/datatypes/**.v'
- 'vlib/os/**.v'
- 'vlib/sync/**.v'
- 'vlib/v/tests/**.v'
- 'vlib/v/ast/**.v'
- 'vlib/v/scanner/**.v'
- 'vlib/v/parser/**.v'
- 'vlib/v/checker/**.v'
- 'vlib/v/gen/c/**.v'
- 'vlib/v/builder/**.v'
- 'vlib/v/cflag/**.v'
- 'vlib/v/live/**.v'
- 'vlib/v/util/**.v'
- 'vlib/v/markused/**.v'
- 'vlib/v/preludes/**.v'
- 'vlib/v/embed_file/**.v'
- 'vlib/x/json2/**.v'
- '**/sanitized_ci.yml'
pull_request:
paths:
- '!**'
- 'vlib/builtin/**.v'
- 'vlib/strconv/**.v'
- 'vlib/strings/**.v'
- 'vlib/math/**.v'
- 'vlib/math/big/**.v'
- 'vlib/arrays/**.v'
- 'vlib/crypto/ecdsa/**.v'
- 'vlib/datatypes/**.v'
- 'vlib/os/**.v'
- 'vlib/sync/**.v'
- 'vlib/v/tests/**.v'
- 'vlib/v/ast/**.v'
- 'vlib/v/scanner/**.v'
- 'vlib/v/parser/**.v'
- 'vlib/v/checker/**.v'
- 'vlib/v/gen/c/**.v'
- 'vlib/v/builder/**.v'
- 'vlib/v/cflag/**.v'
- 'vlib/v/live/**.v'
- 'vlib/v/util/**.v'
- 'vlib/v/markused/**.v'
- 'vlib/v/preludes/**.v'
- 'vlib/v/embed_file/**.v'
- 'vlib/x/json2/**.v'
- '**/sanitized_ci.yml'
concurrency:
group: sanitized-${{ github.workflow }}-${{ github.ref == 'refs/heads/master' && github.sha || github.ref }}
cancel-in-progress: true
jobs:
sanitize-undefined-clang:
runs-on: ubuntu-22.04
timeout-minutes: 120
env:
VFLAGS: -cc clang -cflags -fno-omit-frame-pointer
VJOBS: 1
UBSAN_OPTIONS: print_stacktrace=1:halt_on_error=1:print_suppressions=0:suppressions=/home/runner/work/v/v/.github/workflows/run_sanitizers_undefined.suppressions
VNATIVE_SKIP_LIBC_VV: 1
VTEST_SHOW_LONGEST_BY_RUNTIME: 3
VTEST_SHOW_LONGEST_BY_COMPTIME: 3
VTEST_SHOW_LONGEST_BY_TOTALTIME: 3
steps:
- uses: actions/checkout@v7
- uses: ./.github/actions/cache-apt-packages-action
- name: Build V
run: make -j4 && ./v symlink
- name: V doctor
run: ./v doctor
- name: Ensure code is well formatted
run: ./v -silent test-cleancode
- name: Install dependencies
run: |
.github/workflows/disable_azure_mirror.sh
./v retry -- sudo apt update
./v retry -- sudo apt install --quiet -y postgresql libpq-dev libssl-dev sqlite3 libsqlite3-dev valgrind
./v retry -- sudo apt install --quiet -y libfreetype6-dev libxi-dev libxcursor-dev libgl-dev libxrandr-dev libasound2-dev libegl-dev
./v retry -- sudo apt install clang
- name: Recompile V with -cstrict
run: ./v -cg -cstrict -o v cmd/v
- name: Self tests (-fsanitize=undefined)
run: |
./v -cflags -fsanitize=undefined -o v2 cmd/v
./v2 -cflags -fsanitize=undefined -silent test-self vlib
- name: Build examples (V compiled with -fsanitize=undefined)
run: ./v2 -silent build-examples
sanitize-undefined-gcc:
runs-on: ubuntu-22.04
timeout-minutes: 120
env:
VFLAGS: -cc gcc -cflags -fno-omit-frame-pointer
VJOBS: 1
UBSAN_OPTIONS: print_stacktrace=1:halt_on_error=1:print_suppressions=0:suppressions=/home/runner/work/v/v/.github/workflows/run_sanitizers_undefined.suppressions
VNATIVE_SKIP_LIBC_VV: 1
VTEST_SHOW_LONGEST_BY_RUNTIME: 3
VTEST_SHOW_LONGEST_BY_COMPTIME: 3
VTEST_SHOW_LONGEST_BY_TOTALTIME: 3
steps:
- uses: actions/checkout@v7
- uses: ./.github/actions/cache-apt-packages-action
- name: Build V
run: make -j4 && ./v symlink
- name: V doctor
run: ./v doctor
- name: Ensure code is well formatted
run: ./v -silent test-cleancode
- name: Install dependencies
run: |
.github/workflows/disable_azure_mirror.sh
./v retry -- sudo apt update
./v retry -- sudo apt install --quiet -y postgresql libpq-dev libssl-dev sqlite3 libsqlite3-dev valgrind
./v retry -- sudo apt install --quiet -y libfreetype6-dev libxi-dev libxcursor-dev libgl-dev libxrandr-dev libasound2-dev libegl-dev
- name: Recompile V with -cstrict
run: ./v -cg -cstrict -o v cmd/v
- name: Self tests (-fsanitize=undefined)
run: |
./v -cflags -fsanitize=undefined -o v2 cmd/v
./v2 -cflags -fsanitize=undefined -silent test-self vlib
- name: Build examples (V compiled with -fsanitize=undefined)
run: ./v2 -silent build-examples
sanitize-address-clang:
runs-on: ubuntu-22.04
timeout-minutes: 300
env:
VFLAGS: -cc clang -cflags -fno-omit-frame-pointer
VJOBS: 1
ASAN_OPTIONS: detect_leaks=1
LSAN_OPTIONS: max_leaks=1:print_suppressions=0:suppressions=/home/runner/work/v/v/.github/workflows/run_sanitizers_leak.suppressions
VNATIVE_SKIP_LIBC_VV: 1
VTEST_SHOW_LONGEST_BY_RUNTIME: 3
VTEST_SHOW_LONGEST_BY_COMPTIME: 3
VTEST_SHOW_LONGEST_BY_TOTALTIME: 3
steps:
- uses: actions/checkout@v7
- uses: ./.github/actions/cache-apt-packages-action
- name: Build V
run: make -j4 && ./v symlink
- name: V doctor
run: ./v doctor
- name: Ensure code is well formatted
run: ./v -silent test-cleancode
- name: Install dependencies
run: |
.github/workflows/disable_azure_mirror.sh
./v retry -- sudo apt update
./v retry -- sudo apt install --quiet -y postgresql libpq-dev libssl-dev sqlite3 libsqlite3-dev valgrind
./v retry -- sudo apt install --quiet -y libfreetype6-dev libxi-dev libxcursor-dev libgl-dev libxrandr-dev libasound2-dev libegl-dev
./v retry -- sudo apt install clang
- name: Recompile V with -cstrict
run: ./v -cg -cstrict -o v cmd/v
- name: Self tests (-fsanitize=address)
run: ./v -cflags -fsanitize=address,pointer-compare,pointer-subtract -silent test-self vlib
- name: Test vlib/v/tests/ (V compiled with -fsanitize=address)
run: |
./v -cflags -fsanitize=address -o v cmd/v
./v -cc tcc -silent test-self -asan-compiler vlib/v/tests/
- name: Build examples (V compiled with -fsanitize=address)
run: ./v -silent build-examples
sanitize-address-msvc:
runs-on: windows-2025
timeout-minutes: 30
env:
VFLAGS: -cc msvc
VJOBS: 1
VNATIVE_SKIP_LIBC_VV: 1
VTEST_SHOW_LONGEST_BY_RUNTIME: 3
VTEST_SHOW_LONGEST_BY_COMPTIME: 3
VTEST_SHOW_LONGEST_BY_TOTALTIME: 3
steps:
- uses: actions/checkout@v7
- name: Build
run: |
echo %VFLAGS%
echo $VFLAGS
.\makev.bat -msvc
.\v.exe self
- name: V doctor
run: .\v.exe doctor
- name: Ensure code is well formatted
run: .\v.exe -silent test-cleancode
# - name: Install dependencies
# run: |
# .\v.exe setup-freetype
# .\.github\workflows\windows-install-sqlite.bat
# - name: Self tests (/fsanitize=address) # TODO:
# run: .\v.exe -cflags "/fsanitize=address" -silent test-self vlib
sanitize-address-gcc:
runs-on: ubuntu-22.04
timeout-minutes: 300
env:
VFLAGS: -cc gcc -cflags -fno-omit-frame-pointer
VJOBS: 1
ASAN_OPTIONS: detect_leaks=1
LSAN_OPTIONS: max_leaks=1:print_suppressions=0:suppressions=/home/runner/work/v/v/.github/workflows/run_sanitizers_leak.suppressions
VNATIVE_SKIP_LIBC_VV: 1
VTEST_SHOW_LONGEST_BY_RUNTIME: 3
VTEST_SHOW_LONGEST_BY_COMPTIME: 3
VTEST_SHOW_LONGEST_BY_TOTALTIME: 3
steps:
- uses: actions/checkout@v7
- uses: ./.github/actions/cache-apt-packages-action
- name: Build V
run: make -j4 && ./v symlink
- name: V doctor
run: ./v doctor
- name: Ensure code is well formatted
run: ./v -silent test-cleancode
- name: Install dependencies
run: |
.github/workflows/disable_azure_mirror.sh
./v retry -- sudo apt update
./v retry -- sudo apt install --quiet -y postgresql libpq-dev libssl-dev sqlite3 libsqlite3-dev valgrind
./v retry -- sudo apt install --quiet -y libfreetype6-dev libxi-dev libxcursor-dev libgl-dev libxrandr-dev libasound2-dev libegl-dev
./v retry -- sudo apt install clang
- name: Recompile V with -cstrict
run: ./v -cg -cstrict -o v cmd/v
- name: Self tests (-fsanitize=address)
run: ./v -cflags -fsanitize=address -silent test-self vlib
- name: Test vlib/v/tests/ (V compiled with -fsanitize=address)
run: |
./v -cflags -fsanitize=address,pointer-compare,pointer-subtract -o v cmd/v
./v -cc tcc -silent test-self -asan-compiler vlib/v/tests/
- name: Build examples (V compiled with -fsanitize=address)
run: ./v -silent build-examples
sanitize-memory-clang:
runs-on: ubuntu-22.04
timeout-minutes: 300
env:
VFLAGS: -cc clang -gc none -cflags -fno-omit-frame-pointer
VJOBS: 1
VNATIVE_SKIP_LIBC_VV: 1
VTEST_SHOW_LONGEST_BY_RUNTIME: 3
VTEST_SHOW_LONGEST_BY_COMPTIME: 3
VTEST_SHOW_LONGEST_BY_TOTALTIME: 3
steps:
- uses: actions/checkout@v7
- uses: ./.github/actions/cache-apt-packages-action
- name: Build V
run: make -j4 && ./v symlink
- name: V doctor
run: ./v doctor
- name: Ensure code is well formatted
run: ./v -silent test-cleancode
- name: Install dependencies
run: |
.github/workflows/disable_azure_mirror.sh
./v retry -- sudo apt update
./v retry -- sudo apt install --quiet -y postgresql libpq-dev libssl-dev sqlite3 libsqlite3-dev valgrind
./v retry -- sudo apt install --quiet -y libfreetype6-dev libxi-dev libxcursor-dev libgl-dev libxrandr-dev libasound2-dev libegl-dev
./v retry -- sudo apt install clang
- name: Recompile V with clang and -cstrict
run: ./v -cc clang -cg -cstrict -o v cmd/v
- name: Self tests (-fsanitize=memory)
run: ./v -cflags -fsanitize=memory -silent test-self -msan-compiler vlib
- name: Test vlib/v/tests/ (V compiled with -fsanitize=memory)
run: |
./v -cflags -fsanitize=memory -o v cmd/v
./v -cc tcc -silent test-self -msan-compiler vlib/v/tests/
- name: Build examples (V compiled with -fsanitize=memory)
run: ./v -silent build-examples
sanitize-address-clang-without-gc:
runs-on: ubuntu-22.04
timeout-minutes: 300
env:
VFLAGS: -cc clang -gc none -cflags -fno-omit-frame-pointer
VJOBS: 1
LSAN_OPTIONS: detect_leaks=0
VNATIVE_SKIP_LIBC_VV: 1
VTEST_SHOW_LONGEST_BY_RUNTIME: 3
VTEST_SHOW_LONGEST_BY_COMPTIME: 3
VTEST_SHOW_LONGEST_BY_TOTALTIME: 3
steps:
- uses: actions/checkout@v7
- uses: ./.github/actions/cache-apt-packages-action
- name: Build V
run: make -j4 && ./v symlink
- name: V doctor
run: ./v doctor
- name: Ensure code is well formatted
run: ./v -silent test-cleancode
- name: Install dependencies
run: |
.github/workflows/disable_azure_mirror.sh
./v retry -- sudo apt update
./v retry -- sudo apt install --quiet -y postgresql libpq-dev libssl-dev sqlite3 libsqlite3-dev valgrind
./v retry -- sudo apt install --quiet -y libfreetype6-dev libxi-dev libxcursor-dev libgl-dev libxrandr-dev libasound2-dev libegl-dev
./v retry -- sudo apt install clang
- name: Recompile V with -cstrict
run: ./v -cg -cstrict -o v cmd/v
- name: Self tests (-fsanitize=address)
run: ./v -cflags -fsanitize=address -silent test-self vlib
+76
View File
@@ -0,0 +1,76 @@
name: sdl CI
on:
workflow_dispatch:
push:
branches:
- master
paths:
- 'vlib/**'
- 'thirdparty/**'
- 'cmd/tools/builders/**.v'
- 'cmd/tools/vshader.v'
- '**/sdl_ci.yml'
- '!**.md'
pull_request:
paths:
- 'vlib/**'
- 'thirdparty/**'
- 'cmd/tools/builders/**.v'
- 'cmd/tools/vshader.v'
- '**/sdl_ci.yml'
- '!**.md'
concurrency:
group: sdl-${{ github.workflow }}-${{ github.ref == 'refs/heads/master' && github.sha || github.ref }}
cancel-in-progress: true
jobs:
v-compiles-sdl-examples:
runs-on: ubuntu-24.04
timeout-minutes: 20
env:
VFLAGS: -cc tcc
steps:
- uses: actions/checkout@v7
- uses: ./.github/actions/cache-apt-packages-action
- name: Build V
run: make && sudo ./v symlink
- name: Install dependencies
run: |
.github/workflows/disable_azure_mirror.sh
v retry 'sudo apt update'
v retry 'sudo apt install -y libsdl2-dev libsdl2-ttf-dev'
v retry 'sudo apt install -y libsdl2-mixer-dev libsdl2-image-dev'
- name: Clone sdl into .vmodules
run: |
v retry 'git clone --filter=blob:none https://github.com/vlang/sdl'
cd sdl
mkdir -p ~/.vmodules
ln -s "$(pwd)" ~/.vmodules/sdl
- name: Ensure SDL setup works
run: ./v ~/.vmodules/sdl/setup.vsh
- name: Run tests
run: ./v test sdl
- name: Build sdl shared
run: ./v -shared -g sdl
- name: Build sdl examples
run: |
v shader sdl/examples/sdl_opengl_and_sokol
v should-compile-all sdl/examples/
~/.vmodules/sdl/examples/versions/main
- name: Check SDL works, when installed through vpm
run: |
rm -rf sdl/
rm -rf ~/.vmodules/sdl
v retry 'v install sdl'
ls -la ~/.vmodules/sdl/
v ~/.vmodules/sdl/setup.vsh
v run ~/.vmodules/sdl/examples/versions
+47
View File
@@ -0,0 +1,47 @@
module main
import os
import time
import term
fn iso_week_year(t time.Time) int {
// ISO 8601 assigns a date to the year of the Thursday in its week.
return t.add_days(4 - t.day_of_week()).year
}
fn default_release_tag_for(t time.Time) string {
return 'weekly.${iso_week_year(t):04}.${t.week_of_year():02}'
}
fn release_time() time.Time {
now_override := os.getenv('V_RELEASE_TAG_NOW')
if now_override != '' {
return time.parse(now_override) or {
panic('invalid V_RELEASE_TAG_NOW `${now_override}`: ${err}')
}
}
return time.now()
}
fn main() {
now := release_time()
mut remote_name := 'origin'
mut release_tag := default_release_tag_for(now)
if os.args.len > 1 {
remote_name = os.args[1]
}
if os.args.len > 2 {
release_tag = os.args[2]
}
println('## Usage: show_manual_release_cmd.vsh [REMOTE] [TAGNAME]')
println('## current remote_name: ${remote_name}')
println('## current release_tag: ${release_tag}')
println('## ▼▼▼ ${term.ecolorize(term.yellow,
'run the following, to make a new github release')} ▼▼▼ ')
git_cmd := 'git tag -s -m "releases: ${release_tag}" ${release_tag} && git push --atomic ${remote_name} ${release_tag}'
println(git_cmd)
}
+48
View File
@@ -0,0 +1,48 @@
name: SSA backends CI
on:
push:
paths:
- 'vlib/v2_toberemoved/**'
- 'cmd/tinyv/**'
- '.github/workflows/ssa_backends_ci.yml'
pull_request:
paths:
- 'vlib/v2_toberemoved/**'
- 'cmd/tinyv/**'
- '.github/workflows/ssa_backends_ci.yml'
concurrency:
group: ssa_backends-${{ github.workflow }}-${{ github.ref == 'refs/heads/master' && github.sha || github.ref }}
cancel-in-progress: true
jobs:
ssa-backends-linux:
runs-on: ubuntu-24.04
env:
VJOBS: 1
steps:
- uses: actions/checkout@v6
- name: Build V
run: make && ./v symlink
- name: Test native x64 backend
run: v run cmd/tinyv/test_ssa_backends.v
- name: Test cleanc backend
run: v run cmd/tinyv/test_ssa_backends.v cleanc
- name: Test c-ssa backend
run: v run cmd/tinyv/test_ssa_backends.v c
ssa-backends-macos:
runs-on: macos-14
env:
VJOBS: 1
steps:
- uses: actions/checkout@v6
- name: Build V
run: make -j4 && ./v symlink
- name: Test native arm64 backend
run: v run cmd/tinyv/test_ssa_backends.v
- name: Test cleanc backend
run: v run cmd/tinyv/test_ssa_backends.v cleanc
- name: Test c-ssa backend
run: v run cmd/tinyv/test_ssa_backends.v c
+79
View File
@@ -0,0 +1,79 @@
name: Symlink CI
on:
workflow_dispatch:
push:
branches:
- master
paths:
- 'cmd/tools/vsymlink/**.v'
- '.github/workflows/symlink_ci.yml'
pull_request:
paths:
- 'cmd/tools/vsymlink/**.v'
- '.github/workflows/symlink_ci.yml'
concurrency:
group: symlink-${{ github.workflow }}-${{ github.ref_name == 'master' && github.sha || github.ref_name }}
cancel-in-progress: true
jobs:
symlink-unix:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, macos-latest]
fail-fast: false
steps:
- uses: actions/checkout@v7
- name: Build V
run: make -j4
- name: Symlink
run: |
./v symlink
cd /tmp/ && v version
cd ~ && v version
echo 'println(123)' > hi.v
v run hi.v
- name: Unlink
run: |
rm "$(which v)"
v --version && exit 1 || exit 0
- name: Symlink (sudo)
run: |
sudo ./v symlink
cd /tmp/ && v version
cd ~ && v version
echo 'println(123)' > hi.v
v run hi.v
- name: Unlink
run: |
rm "$(which v)"
v --version && exit 1 || exit 0
- name: Symlink (-githubci)
run: ./v symlink -githubci
- name: Test after symlink with -githubci (in a separate script)
run: |
cd /tmp/ && v version
cd ~ && v version
echo 'println(123)' > hi.v
v run hi.v
symlink-windows:
runs-on: windows-2025
strategy:
matrix:
flags: ['', '-githubci']
fail-fast: false
steps:
- uses: actions/checkout@v7
- name: Build V
run: ./makev.bat
- name: Symlink
run: ./v symlink ${{ matrix.flags }}
- name: Check if V is usable
run: |
cd $RUNNER_TEMP && pwd && v version
cd ~ && pwd && v version
echo 'println(123)' > hi.v
v run hi.v
+129
View File
@@ -0,0 +1,129 @@
name: CI Termux
on:
workflow_dispatch:
push:
branches:
- master
paths-ignore:
- '**.md'
- '**.yml'
- '!**/termux_ci.yml'
- 'cmd/tools/**'
- '!cmd/tools/builders/**.v'
pull_request:
paths-ignore:
- '**.md'
- '**.yml'
- '!**/termux_ci.yml'
- 'cmd/tools/**'
- '!cmd/tools/builders/**.v'
jobs:
termux-build:
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- uses: actions/checkout@v7
- name: Build and test in Termux
run: |
set -o xtrace
echo "$PWD"
whoami
touch outside_docker.txt
git log -n4
echo "running docker ..."
docker run --rm --mount type=bind,source=/home/runner/work/v/v,destination=/src -w /src termux/termux-docker:latest bash -c '
set -o xtrace
echo "running inside docker"
whoami
cp -r /src ~/vproject; cd ~/vproject
touch inside_docker.txt
ls -la
echo "previous TERMUX_VERSION: $TERMUX_VERSION"
export TERMUX_VERSION=0.118.3
echo "explicit TERMUX_VERSION: $TERMUX_VERSION"
bash .github/workflows/retry.sh pkg update -y
bash .github/workflows/retry.sh pkg install -y clang libexecinfo libgc libgc-static make git
git log -n4
VFLAGS="-cc cc" make
./v symlink
export PATH="$HOME/.local/bin:/usr/local/bin:$PATH"
v run examples/hello_world.v
v run examples/primes.v
v -e "import os; dump( os.user_os() )"
'
termux-build-arm64-tcc:
# Diagnostic job for vlang/v#27207: reproduces the Termux/AArch64 tcc
# bootstrap failure on a real arm64 runner so we can collect logs without
# local hardware. Allowed to fail until the upstream tcc AArch64 bug is
# resolved.
runs-on: ubuntu-24.04-arm
continue-on-error: true
timeout-minutes: 45
steps:
- uses: actions/checkout@v7
- name: Build in Termux (arm64, default tcc)
run: |
set -o xtrace
uname -a
docker run --rm --platform=linux/arm64 --mount type=bind,source=/home/runner/work/v/v,destination=/src -w /src termux/termux-docker:aarch64 bash -c '
set -o xtrace
uname -a
cp -r /src ~/vproject; cd ~/vproject
export TERMUX_VERSION=0.118.3
bash .github/workflows/retry.sh pkg update -y
bash .github/workflows/retry.sh pkg install -y clang libexecinfo libgc libgc-static make git gdb file
git log -n4
ulimit -c unlimited || true
# Explicit `-cc tcc` is required: on Linux arm64 the Makefile
# otherwise injects `-cc "$(CC)"` (see GNUmakefile:149-155) and
# the bundled tcc path would never run — defeating the purpose
# of this diagnostic job for #27207. Capture every invocation
# via -showcc and the full build output to build.log.
set +e
VFLAGS="-cc tcc -showcc -stats" make 2>&1 | tee build.log
rc=${PIPESTATUS[0]}
set -e
echo "make exit code: $rc"
# Always copy the log back to the bind-mounted dir so the runner
# step that uploads the artifact can find it.
cp build.log /src/build.log || true
if [ "$rc" -ne 0 ] || [ ! -x ./v ]; then
echo "===== bootstrap failed; collecting diagnostics ====="
echo "--- tcc binary ---"
ls -la thirdparty/tcc/ 2>/dev/null || true
for t in thirdparty/tcc/tcc.exe thirdparty/tcc/tcc; do
if [ -x "$t" ]; then "$t" -v || true; fi
done
echo "--- last 120 lines of build.log ---"
tail -n 120 build.log || true
echo "--- v1/v2/v file info ---"
file v1 v2 v 2>/dev/null || true
echo "--- last tcc invocations from build.log ---"
grep -E "tcc(\.exe)? " build.log | tail -n10 || true
echo "--- core files (if any) ---"
ls -la core* 2>/dev/null || true
for c in core core.*; do
if [ -f "$c" ] && [ -x ./v2 ]; then
echo "--- gdb backtrace from $c against v2 ---"
gdb --batch --ex bt --ex "info registers" ./v2 "$c" || true
fi
done
# If make exited 0 but ./v is missing, force a nonzero exit so
# the diagnostic job does not go green without a usable compiler.
if [ "$rc" -eq 0 ]; then rc=1; fi
exit "$rc"
fi
echo "===== bootstrap succeeded ====="
./v -version
./v run examples/hello_world.v
'
- name: Upload build log
if: always()
uses: actions/upload-artifact@v7
with:
name: termux-arm64-build-log
path: build.log
if-no-files-found: ignore
+73
View File
@@ -0,0 +1,73 @@
name: Time CI
on:
push:
branches:
- master
paths:
- 'vlib/**'
- 'cmd/tools/builders/**.v'
- '**/time_ci.yml'
- '!**.md'
pull_request:
paths:
- 'vlib/**'
- 'cmd/tools/builders/**.v'
- '**/time_ci.yml'
- '!**.md'
concurrency:
group: time-${{ github.workflow }}-${{ github.ref == 'refs/heads/master' && github.sha || github.ref }}
cancel-in-progress: true
jobs:
time-linux:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- name: Build V
run: make
- name: Test time functions in a timezone UTC-12
run: TZ=Etc/GMT+12 ./v test vlib/time/
- name: Test time functions in a timezone UTC-3
run: TZ=Etc/GMT+3 ./v test vlib/time/
- name: Test time functions in a timezone UTC+3
run: TZ=Etc/GMT-3 ./v test vlib/time/
- name: Test time functions in a timezone UTC+12
run: TZ=Etc/GMT-12 ./v test vlib/time/
- name: Test in a timezone using daylight saving (Europe/Paris)
run: TZ=Europe/Paris ./v test vlib/time/
time-macos:
runs-on: macos-14
steps:
- uses: actions/checkout@v7
- name: Build V
run: make
- name: Test time functions in a timezone UTC-12
run: TZ=Etc/GMT+12 ./v test vlib/time/
- name: Test time functions in a timezone UTC-3
run: TZ=Etc/GMT+3 ./v test vlib/time/
- name: Test time functions in a timezone UTC+3
run: TZ=Etc/GMT-3 ./v test vlib/time/
- name: Test time functions in a timezone UTC+12
run: TZ=Etc/GMT-12 ./v test vlib/time/
- name: Test in a timezone using daylight saving (Europe/Paris)
run: TZ=Europe/Paris ./v test vlib/time/
time-windows:
runs-on: windows-2025
steps:
- uses: actions/checkout@v7
- name: Build V
run: .\makev.bat
- name: Test time functions in a timezone UTC-12
run: tzutil /s "Dateline Standard Time" && ./v test vlib/time/
- name: Test time functions in a timezone UTC-3
run: tzutil /s "Greenland Standard Time" && ./v test vlib/time/
- name: Test time functions in a timezone UTC+3
run: tzutil /s "Russian Standard Time" && ./v test vlib/time/
- name: Test time functions in a timezone UTC+12
run: tzutil /s "New Zealand Standard Time" && ./v test vlib/time/
- name: Test in a timezone using daylight saving (Europe/Paris)
run: tzutil /s "W. Europe Standard Time" && ./v test vlib/time/
+42
View File
@@ -0,0 +1,42 @@
name: toml CI
on:
push:
branches:
- master
paths:
- 'vlib/**'
- '**/toml_ci.yml'
- '!**.md'
pull_request:
paths:
- 'vlib/**'
- '**/toml_ci.yml'
- '!**.md'
concurrency:
group: toml-${{ github.workflow }}-${{ github.ref == 'refs/heads/master' && github.sha || github.ref }}
cancel-in-progress: true
jobs:
toml-module-pass-external-test-suites:
runs-on: ubuntu-latest
timeout-minutes: 20
steps:
- uses: actions/checkout@v7
- name: Build V
run: make -j4 && ./v symlink
- name: Install dependencies
run: |
v retry -- v download https://github.com/jqlang/jq/releases/download/jq-1.6/jq-linux64
sudo chmod 755 jq-linux64
sudo mv jq-linux64 /usr/bin/jq
- name: Show JQ Version
run: jq --version
- name: Download more TOML testsuits
run: .github/workflows/download_full_toml_test_suites.sh
- name: Run TOML tests
run: VTEST_TOML_DO_YAML_CONVERSION=1 VTEST_TOML_DO_LARGE_FILES=1 ./v test vlib/toml
+258
View File
@@ -0,0 +1,258 @@
name: Tools CI
on:
push:
branches:
- master
paths:
- 'cmd/**'
- '!cmd/tools/vpm/**'
- 'vlib/**'
- 'thirdparty/**'
- '!**.md'
- '**/tools_ci.yml'
pull_request:
paths:
- 'cmd/**'
- '!cmd/tools/vpm/**'
- 'vlib/**'
- 'thirdparty/**'
- '!**.md'
- '**/tools_ci.yml'
concurrency:
group: tools-${{ github.workflow }}-${{ github.ref == 'refs/heads/master' && github.sha || github.ref }}
cancel-in-progress: true
jobs:
tools-linux:
runs-on: ubuntu-22.04
timeout-minutes: 20
strategy:
matrix:
cc: [tcc, gcc, clang]
fail-fast: false
env:
VFLAGS: -cc ${{ matrix.cc }}
steps:
- uses: actions/checkout@v7
- name: Build V
run: make && ./v -showcc -o v cmd/v && ./v symlink && ./v doctor
- name: Code in cmd/ is formatted
run: ./v fmt -verify cmd/
- name: Check build-tools
run: ./v -silent -N -W -check build-tools
- name: Test tools
run: ./v -silent test-self cmd
- name: Test tools (-cstrict)
if: ${{ matrix.cc != 'tcc' }}
run: ./v -silent -W -cstrict test-self cmd
- name: Test sanitized
if: ${{ matrix.cc != 'tcc' }}
run: |
export VNATIVE_SKIP_LIBC_VV=1
if [[ ${{ matrix.cc }} == "clang" ]]; then
cmd="./v -silent -cc clang -cflags -fsanitize=undefined test-self -ubsan-compiler cmd"
echo "$cmd" && $cmd
cmd="./v -silent -gc none -cc clang -cflags -fsanitize=memory test-self -msan-compiler cmd"
echo "$cmd" && $cmd
else
cmd="./v -silent -cc gcc -cflags -fsanitize=thread test-self cmd"
echo "$cmd" && $cmd
cmd="./v -silent -cc gcc -cflags -fsanitize=address,leak,undefined,shift,shift-exponent,shift-base,integer-divide-by-zero,unreachable,vla-bound,null,return,signed-integer-overflow,bounds,bounds-strict,alignment,object-size,float-divide-by-zero,float-cast-overflow,nonnull-attribute,returns-nonnull-attribute,bool,enum,vptr test-self -asan-compiler cmd/tools"
echo "$cmd" && $cmd
## cmd="./v -silent -cc gcc -cflags -fsanitize=kernel-address test-self -asan-compiler cmd"
## echo "$cmd" && $cmd
fi
tools-macos:
runs-on: macos-14
timeout-minutes: 20
strategy:
matrix:
cc: [clang]
fail-fast: false
env:
VFLAGS: -cc ${{ matrix.cc }}
steps:
- uses: actions/checkout@v7
- name: Build V
run: make && ./v -showcc -o v cmd/v && ./v symlink && ./v doctor
- name: Check build-tools
run: ./v -silent -N -W -check build-tools
- name: Test tools
run: ./v -silent test-self cmd
- name: Test tools (-cstrict)
run: ./v -silent -W -cstrict test-self cmd
tools-windows:
runs-on: windows-2025
timeout-minutes: 20
strategy:
matrix:
cc: [tcc, gcc, msvc]
fail-fast: false
env:
VFLAGS: -cc ${{ matrix.cc }}
steps:
- uses: actions/checkout@v7
- name: Build V
run: ./makev.bat -${{ matrix.cc }} && ./v -o v2.exe cmd/v && ./v2 -showcc -o v.exe cmd/v && ./v symlink && ./v doctor
- name: Install SQLite (needed by vsqlite tool)
run: .\.github\workflows\windows-install-sqlite.bat
- name: Check build tools
run: ./v build-tools
- name: Test tools
run: ./v -silent test-self cmd
- name: Test tools (-cstrict)
if: ${{ matrix.cc == 'msvc' }}
run: ./v -silent -W -cstrict test-self cmd
tools-docker-ubuntu-musl:
runs-on: ubuntu-24.04
timeout-minutes: 20
container:
image: thevlang/vlang:ubuntu-build
env:
V_CI_MUSL: 1
V_CI_UBUNTU_MUSL: 1
VFLAGS: -cc musl-gcc -gc none
volumes:
- ${{github.workspace}}:/opt/vlang
steps:
- name: Checkout
uses: actions/checkout@v7
- name: Build V
run: make && ./v -cg -o v cmd/v && ./v symlink
- name: Ensure git commands can be used with no prompts on modern Git versions
run: git config --global --add safe.directory /__w/v/v
- name: Verify `v test` works
run: |
./v cmd/tools/test_if_v_test_system_works.v
./cmd/tools/test_if_v_test_system_works
- name: Check build tools
run: ./v -silent -N -W -check build-tools
- name: Test tools
run: ./v -silent test-self cmd
- name: Test tools (-cstrict)
run: ./v -silent -W -cstrict test-self cmd
tools-freebsd:
runs-on: ubuntu-latest
timeout-minutes: 20
strategy:
matrix:
cc: [tcc, gcc, clang]
fail-fast: false
env:
VFLAGS: -cc ${{ matrix.cc }}
steps:
- uses: actions/checkout@v7
- name: Start FreeBSD VM with ${{ matrix.cc }}
uses: cross-platform-actions/action@v1.2.0
with:
operating_system: freebsd
version: '15.0'
memory: 4G
shell: sh
sync_files: runner-to-vm
environment_variables: VFLAGS
- name: Tests tools on FreeBSD with ${{ matrix.cc }}
shell: cpa.sh {0}
run: |
sudo pkg install -y git sqlite3 gmake boehm-gc-threaded libiconv
if [ "$VFLAGS" = "-cc gcc" ]; then
sudo pkg install -y gcc
fi
# Mandatory: hostname not set in VM => some tests fail
sudo hostname -s freebsd-ci
echo "::group::OS infos"
uname -a
echo "::endgroup::"
# Build V
echo "::group::Build V"
git config --global --add safe.directory .
printf "VFLAGS = %s\n" "$VFLAGS"
gmake && ./v -showcc -o v cmd/v && sudo ./v symlink
echo "::endgroup::"
echo "::group::v doctor"
./v doctor
echo "::endgroup::"
# Code in cmd/ is formatted
echo "::group::Check code in cmd/ is formatted"
./v fmt -verify cmd/
echo "::endgroup::"
# Check build-tools
echo "::group::Check build tools"
./v -silent -N -W -check build-tools
echo "::endgroup::"
# Test tools
echo "::group::Test tools"
./v -silent test-self cmd
echo "::endgroup::"
# Test tools (-cstrict)
if [ "$VFLAGS" != "-cc tcc" ]; then
echo "::group::Test tools (-cstrict)"
./v -silent -W -cstrict test-self cmd
echo "::endgroup::"
fi
tools-openbsd:
runs-on: ubuntu-latest
timeout-minutes: 20
strategy:
matrix:
cc: [tcc, clang]
fail-fast: false
env:
VFLAGS: -cc ${{ matrix.cc }}
steps:
- uses: actions/checkout@v7
- name: Start OpenBSD VM with ${{ matrix.cc }}
uses: cross-platform-actions/action@v1.2.0
with:
operating_system: openbsd
version: '7.8'
memory: 4G
sync_files: runner-to-vm
environment_variables: VFLAGS
- name: Tests tools on OpenBSD with ${{ matrix.cc }}
shell: cpa.sh {0}
run: |
sudo pkg_add git sqlite3 gmake boehm-gc libiconv
# Mandatory: hostname not set in VM => some tests fail
sudo hostname -s openbsd-ci
echo "::group::OS infos"
uname -a
echo "::endgroup::"
# Build V
echo "::group::Build V"
git config --global --add safe.directory .
printf "VFLAGS = %s\n" "$VFLAGS"
gmake && ./v -showcc -o v cmd/v && sudo ./v symlink
echo "::endgroup::"
echo "::group::v doctor"
./v doctor
echo "::endgroup::"
# Code in cmd/ is formatted
echo "::group::Check code in cmd/ is formatted"
./v fmt -verify cmd/
echo "::endgroup::"
# Check build-tools
echo "::group::Check build tools"
./v -silent -N -W -check build-tools
echo "::endgroup::"
# Test tools
echo "::group::Test tools"
./v -silent test-self cmd
echo "::endgroup::"
# Test tools (-cstrict)
if [ "$VFLAGS" != "-cc tcc" ]; then
echo "::group::Test tools (-cstrict)"
./v -silent -W -cstrict test-self cmd
echo "::endgroup::"
fi
+216
View File
@@ -0,0 +1,216 @@
name: Update tccbin
on:
workflow_dispatch:
inputs:
tcc_commit:
description: 'TinyCC ref, branch, or commit to build'
required: false
default: mob
publish:
description: 'Push the rebuilt bundle to vlang/tccbin'
type: boolean
required: false
default: false
force_rebuild:
description: 'Rebuild even when tccbin already records the same TinyCC hash'
type: boolean
required: false
default: false
schedule:
- cron: '17 3 1 * *'
permissions:
contents: read
concurrency:
group: update-tccbin-${{ github.ref }}
cancel-in-progress: false
jobs:
update-tccbin-hosted:
if: github.repository == 'vlang/v' && (github.event_name != 'schedule' || github.ref == 'refs/heads/master')
strategy:
fail-fast: false
matrix:
include:
- id: linux-amd64
os: ubuntu-latest
branch: thirdparty-linux-amd64
script: thirdparty/build_scripts/thirdparty-linux-amd64_tcc.sh
- id: macos-amd64
os: macos-15-intel
branch: thirdparty-macos-amd64
script: thirdparty/build_scripts/thirdparty-macos-amd64_tcc.sh
- id: macos-arm64
os: macos-latest
branch: thirdparty-macos-arm64
script: thirdparty/build_scripts/thirdparty-macos-arm64_tcc.sh
runs-on: ${{ matrix.os }}
env:
TCC_COMMIT: ${{ github.event.inputs.tcc_commit || 'mob' }}
TCCBIN_REPO: vlang/tccbin
PUBLISH: ${{ github.event_name == 'schedule' || github.event.inputs.publish == 'true' }}
FORCE_REBUILD: ${{ github.event.inputs.force_rebuild == 'true' }}
steps:
- uses: actions/checkout@v7
- name: Install macOS build dependencies
if: runner.os == 'macOS'
run: brew install make
- name: Resolve TinyCC source hash
id: tinycc
shell: bash
run: |
set -euo pipefail
git clone --quiet https://repo.or.cz/tinycc.git /tmp/tinycc-ref
git -C /tmp/tinycc-ref checkout --quiet "$TCC_COMMIT"
hash="$(git -C /tmp/tinycc-ref rev-parse HEAD)"
echo "hash=$hash" >> "$GITHUB_OUTPUT"
echo "TinyCC $TCC_COMMIT resolves to $hash"
- name: Clone tccbin branch
shell: bash
env:
TCCBIN_TOKEN: ${{ secrets.VLANG_BOT_SECRET }}
run: |
set -euo pipefail
git clone --branch "${{ matrix.branch }}" --depth=1 \
"https://github.com/${TCCBIN_REPO}.git" thirdparty/tcc
if [ "$PUBLISH" = 'true' ]; then
if [ -z "$TCCBIN_TOKEN" ]; then
echo "::error::VLANG_BOT_SECRET is required to publish to ${TCCBIN_REPO}"
exit 1
fi
git -C thirdparty/tcc remote set-url origin \
"https://vlang-bot:${TCCBIN_TOKEN}@github.com/${TCCBIN_REPO}.git"
fi
- name: Check whether rebuild is needed
id: rebuild
shell: bash
run: |
set -euo pipefail
if [ "$FORCE_REBUILD" != 'true' ] \
&& [ -f thirdparty/tcc/build_source_hash.txt ] \
&& [ "$(cat thirdparty/tcc/build_source_hash.txt)" = "${{ steps.tinycc.outputs.hash }}" ]; then
echo "skip=true" >> "$GITHUB_OUTPUT"
echo "tccbin/${{ matrix.branch }} already has TinyCC ${{ steps.tinycc.outputs.hash }}"
else
echo "skip=false" >> "$GITHUB_OUTPUT"
fi
- name: Configure git identity
if: steps.rebuild.outputs.skip != 'true'
run: |
git config --global user.name vlang-bot
git config --global user.email vlang-bot@users.noreply.github.com
- name: Build TCC bundle
if: steps.rebuild.outputs.skip != 'true'
shell: bash
env:
BUILD_CMD: TCC_COMMIT=${{ env.TCC_COMMIT }} TCC_FOLDER=thirdparty/tcc bash ${{ matrix.script }}
run: |
set -euo pipefail
TCC_FOLDER=thirdparty/tcc bash "${{ matrix.script }}"
test "$(cat thirdparty/tcc/build_source_hash.txt)" = "${{ steps.tinycc.outputs.hash }}"
thirdparty/tcc/tcc.exe --version
thirdparty/tcc/tcc.exe -v -v
- name: Upload TCC bundle artifact
if: steps.rebuild.outputs.skip != 'true'
uses: actions/upload-artifact@v7
with:
name: tccbin-${{ matrix.id }}
path: thirdparty/tcc
- name: Push tccbin branch
if: steps.rebuild.outputs.skip != 'true' && env.PUBLISH == 'true'
shell: bash
run: |
set -euo pipefail
git -C thirdparty/tcc push origin HEAD:${{ matrix.branch }}
update-tccbin-bsd:
if: github.repository == 'vlang/v' && (github.event_name != 'schedule' || github.ref == 'refs/heads/master')
strategy:
fail-fast: false
matrix:
include:
- id: freebsd-amd64
operating_system: freebsd
version: '15.0'
branch: thirdparty-freebsd-amd64
script: thirdparty/build_scripts/thirdparty-freebsd-amd64_tcc.sh
install: sudo pkg install -y bash git gmake rsync
cc: cc
- id: openbsd-amd64
operating_system: openbsd
version: '7.8'
branch: thirdparty-openbsd-amd64
script: thirdparty/build_scripts/thirdparty-openbsd-amd64_tcc.sh
install: sudo pkg_add bash git gmake rsync
cc: clang
runs-on: ubuntu-latest
env:
TCC_COMMIT: ${{ github.event.inputs.tcc_commit || 'mob' }}
TCCBIN_REPO: vlang/tccbin
PUBLISH: ${{ github.event_name == 'schedule' || github.event.inputs.publish == 'true' }}
FORCE_REBUILD: ${{ github.event.inputs.force_rebuild == 'true' }}
TCCBIN_TOKEN: ${{ secrets.VLANG_BOT_SECRET }}
steps:
- uses: actions/checkout@v7
- name: Start ${{ matrix.id }} VM
uses: cross-platform-actions/action@v1.2.0
with:
operating_system: ${{ matrix.operating_system }}
version: ${{ matrix.version }}
memory: 4G
shell: sh
sync_files: runner-to-vm
environment_variables: TCC_COMMIT TCCBIN_REPO PUBLISH FORCE_REBUILD TCCBIN_TOKEN
- name: Build and publish ${{ matrix.id }} TCC bundle
shell: cpa.sh {0}
run: |
set -eu
${{ matrix.install }}
git config --global user.name vlang-bot
git config --global user.email vlang-bot@users.noreply.github.com
git config --global --add safe.directory "$PWD"
git clone --quiet https://repo.or.cz/tinycc.git /tmp/tinycc-ref
git -C /tmp/tinycc-ref checkout --quiet "$TCC_COMMIT"
tinycc_hash="$(git -C /tmp/tinycc-ref rev-parse HEAD)"
echo "TinyCC $TCC_COMMIT resolves to $tinycc_hash"
git clone --branch "${{ matrix.branch }}" --depth=1 \
"https://github.com/${TCCBIN_REPO}.git" thirdparty/tcc
if [ "$PUBLISH" = 'true' ]; then
if [ -z "$TCCBIN_TOKEN" ]; then
echo "VLANG_BOT_SECRET is required to publish to ${TCCBIN_REPO}" >&2
exit 1
fi
git -C thirdparty/tcc remote set-url origin \
"https://vlang-bot:${TCCBIN_TOKEN}@github.com/${TCCBIN_REPO}.git"
fi
if [ "$FORCE_REBUILD" != 'true' ] \
&& [ -f thirdparty/tcc/build_source_hash.txt ] \
&& [ "$(cat thirdparty/tcc/build_source_hash.txt)" = "$tinycc_hash" ]; then
echo "tccbin/${{ matrix.branch }} already has TinyCC $tinycc_hash"
exit 0
fi
BUILD_CMD="TCC_COMMIT=$TCC_COMMIT TCC_FOLDER=thirdparty/tcc CC=${{ matrix.cc }} bash ${{ matrix.script }}" \
TCC_FOLDER=thirdparty/tcc CC="${{ matrix.cc }}" bash "${{ matrix.script }}"
test "$(cat thirdparty/tcc/build_source_hash.txt)" = "$tinycc_hash"
thirdparty/tcc/tcc.exe --version
thirdparty/tcc/tcc.exe -v -v
if [ "$PUBLISH" = 'true' ]; then
git -C thirdparty/tcc push origin HEAD:${{ matrix.branch }}
fi
@@ -0,0 +1,267 @@
name: V Apps and Modules
on:
push:
branches:
- master
paths-ignore:
- '**.md'
- '**.yml'
- '!**/v_apps_and_modules_compile_ci.yml'
- 'examples/**'
- 'cmd/tools/vrepl.v'
pull_request:
paths-ignore:
- '**.md'
- '**.yml'
- '!**/v_apps_and_modules_compile_ci.yml'
- 'examples/**'
- 'cmd/tools/vrepl.v'
concurrency:
group: v_apps-${{ github.workflow }}-${{ github.ref == 'refs/heads/master' && github.sha || github.ref }}
cancel-in-progress: true
jobs:
v-apps-compile:
strategy:
matrix:
os: [ubuntu-latest, macos-14]
fail-fast: false
runs-on: ${{ matrix.os }}
timeout-minutes: 60
steps:
- uses: actions/checkout@v7
- name: Cache apt packages
if: runner.os == 'Linux'
uses: ./.github/actions/cache-apt-packages-action
- name: Cache Homebrew downloads
if: runner.os == 'macOS'
uses: actions/cache@v5
with:
path: ~/Library/Caches/Homebrew
key: brew-${{ matrix.os }}-v_apps-${{ hashFiles('.github/workflows/v_apps_and_modules_compile_ci.yml') }}
restore-keys: |
brew-${{ matrix.os }}-v_apps-
brew-${{ matrix.os }}-
- name: Build V
id: build
run: make && sudo ./v symlink
- name: Install dependencies
run: |
if [ "$RUNNER_OS" == 'Linux' ]; then
.github/workflows/disable_azure_mirror.sh
v retry -- sudo apt -qq update
v retry -- sudo apt -qq install libgc-dev libsodium-dev libssl-dev sqlite3 libsqlite3-dev
v retry -- sudo apt -qq install libfreetype6-dev libxi-dev libxcursor-dev libgl-dev libxrandr-dev libasound2-dev xfonts-75dpi xfonts-base libegl-dev libharfbuzz-dev libfribidi-dev libfontconfig1-dev libpango1.0-dev libglib2.0-dev libdbus-1-dev
v retry -- sudo apt -qq install sassc libgit2-dev # needed by gitly
v retry -- sudo apt -qq install libunwind-18-dev # needed by v-analyzer for libbacktrace
else
v retry brew install sassc libgit2 libsodium pango fribidi pkg-config
fi
- name: Build docs generator
run: |
v retry -- v install markdown
v retry -- git clone https://github.com/vlang/docs --branch generator --depth 1
cd docs
v .
- name: Test vtcc
if: runner.os == 'macOS'
run: .github/workflows/compile_v_with_vtcc.sh
- name: Test vsql compilation and examples
if: ${{ false && !cancelled() && steps.build.outcome == 'success' }}
run: |
echo "Install vsql"
v retry -- v install elliotchance.vsql
cd ~/.vmodules/elliotchance/vsql
echo "Compile vsql"
make bin/vsql
echo "Run examples"
make examples
echo "Run vsql/connection_test.v"
v vsql/connection_test.v
- name: Test vlang/gui
if: ${{ !cancelled() && steps.build.outcome == 'success' }}
run: .github/workflows/compile_vlang_gui_examples.sh
- name: Test discord.v
if: ${{ false && !cancelled() && steps.build.outcome == 'success' }} # disabled: upstream uses deprecated json2.raw_decode
run: .github/workflows/compile_discordv.sh
- name: Build herolib
if: ${{ false && !cancelled() && steps.build.outcome == 'success' }}
run: .github/workflows/compile_herolib.sh
- name: Build vlang/vab
if: ${{ !cancelled() && steps.build.outcome == 'success' }}
run: |
echo "Install VAB"
v retry -- v install vab
echo "Build vab"
v ~/.vmodules/vab
echo "Build vab with -g"
v -g ~/.vmodules/vab
- name: Build vlang/ved
if: ${{ !cancelled() && steps.build.outcome == 'success' }}
run: |
v retry -- git clone --depth 1 https://github.com/vlang/ved
cd ved && v -o ved .
echo "Build"
v .
echo "Build with -autofree ..."
v -autofree .
echo "Build with -prod ..."
v -prod .
cd ..
- name: Build vlang/pdf
if: ${{ !cancelled() && steps.build.outcome == 'success' }}
run: |
v retry -- v install pdf
echo "PDF examples should compile"
v should-compile-all ~/.vmodules/pdf/examples
- name: Build vlang/libsodium
if: ${{ !cancelled() && steps.build.outcome == 'success' }}
run: |
echo "Install the libsodium wrapper"
v retry -- v install libsodium
echo "Test libsodium"
VJOBS=1 v test ~/.vmodules/libsodium
- name: Build vlang/coreutils
if: ${{ !cancelled() && steps.build.outcome == 'success' }}
run: |
echo "Clone Coreutils"
v retry -- git clone --depth 1 https://github.com/vlang/coreutils /tmp/coreutils
echo "Build Coreutils"
cd /tmp/coreutils; make
- name: Build vlang/gitly
if: ${{ !cancelled() && steps.build.outcome == 'success' }}
run: |
echo "Install markdown"
v retry -- v install markdown
echo "Install pcre"
v retry -- v install pcre
echo "Clone Gitly"
v retry -- git clone https://github.com/vlang/gitly /tmp/gitly
echo "Build Gitly"
v -cc gcc /tmp/gitly
## echo "Build Gitly with -autofree"
## v -cc gcc -autofree /tmp/gitly
echo "Compile gitly.css from gitly.scss"
sassc /tmp/gitly/static/css/gitly.scss > /tmp/gitly/static/css/gitly.css
# echo "Run first_run.v"
# v -cc gcc run /tmp/gitly/tests/first_run.v
# # /tmp/gitly/gitly -ci_run
- name: Build V UI examples
if: ${{ !cancelled() && steps.build.outcome == 'success' }}
run: |
v retry -- v install ui
v -no-parallel ~/.vmodules/ui/examples/rectangles.v
v -no-parallel ~/.vmodules/ui/examples/users.v
# v run ~/.vmodules/ui/examples/build_examples.vsh
- name: Build vlang/v-analyzer
if: ${{ !cancelled() && steps.build.outcome == 'success' }}
run: |
echo "Clone v-analyzer"
v retry -- git clone --depth=1 --branch=master --filter=blob:none --recursive --shallow-submodules https://github.com/vlang/v-analyzer /tmp/v-analyzer
cd /tmp/v-analyzer
echo "Installing dependencies"
v install
echo "Build v-analyzer debug"
v build.vsh debug
echo "Build v-analyzer release"
v build.vsh release
- name: Format vlang/v-analyzer
if: ${{ !cancelled() && steps.build.outcome == 'success' }}
run: |
cd /tmp/v-analyzer
fmt_files=($(git ls-files '*.v' '*.vsh' ':!:metadata/stubs/*.v' ':!:src/metadata/stubs/*.v'))
set +e
v fmt -c "${fmt_files[@]}"
exit_code=$?
if [[ $exit_code -ne 0 && $exit_code -ne 5 ]]; then
# Don't fail if there are only internal errors (exit code 5).
v fmt -diff "${fmt_files[@]}"
exit 1
fi
- name: Build vlang/go2v
if: ${{ !cancelled() && steps.build.outcome == 'success' && matrix.os != 'macos-14' }}
run: |
echo "Clone Go2V"
v retry -- git clone --depth=1 https://github.com/vlang/go2v /tmp/go2v/
echo "Build Go2V"
v /tmp/go2v/
echo "Run Go2V tests"
VJOBS=1 v test /tmp/go2v/
- name: Install UI through VPM and make sure its examples compile
if: ${{ false && !cancelled() && steps.build.outcome == 'success' }} # disabled: upstream vlang/ui has unused parameter notices that fail with -N -W
run: |
echo "Official VPM modules should be installable"
v retry -- v install ui
echo "Examples of UI should compile"
v ~/.vmodules/ui/examples/build_examples.vsh
- name: Build vlang/adventofcode
if: ${{ !cancelled() && steps.build.outcome == 'success' }}
run: |
echo "Clone the AdventOfCode repo"
v retry -- git clone --depth 1 https://github.com/vlang/adventofcode /tmp/adventofcode
echo "Install dependencies"
v retry -- v install pcre
echo "Execute Tests"
cd /tmp/adventofcode && v run verify.v
- name: Build vlang/msgpack
if: ${{ !cancelled() && steps.build.outcome == 'success' }}
run: |
echo "Install msgpack"
v retry -- v install msgpack
echo "Build msgpack"
v -shared ~/.vmodules/msgpack/
echo "Run msgpack tests"
v test ~/.vmodules/msgpack/
echo "MessagePack examples should compile"
v should-compile-all ~/.vmodules/msgpack/examples
# - name: Build VEX
# if: ${{ !cancelled() }} && steps.build.outcome == 'success'
# run: |
# echo "Install Vex"
# v retry -- v install nedpals.vex
# echo "Compile all of the Vex examples"
# v should-compile-all ~/.vmodules/nedpals/vex/examples
# echo "Compile the simple Vex example"
# v ~/.vmodules/nedpals/vex/examples/simple_example.v
# echo "Run Vex Tests"
# v test ~/.vmodules/nedpals/vex
vpm-site-compile:
strategy:
matrix:
os: [ubuntu-24.04, macos-14]
fail-fast: false
runs-on: ${{ matrix.os }}
timeout-minutes: 20
steps:
- uses: actions/checkout@v7
- name: Build V
run: make && ./v symlink
- name: Build vpm
run: |
v retry -- v install markdown
v retry -- git clone --depth 1 https://github.com/vlang/vpm
cd vpm && v .
+90
View File
@@ -0,0 +1,90 @@
name: vab CI
on:
workflow_call:
push:
branches:
- master
paths:
- 'vlib/**'
- 'thirdparty/**'
- 'cmd/tools/builders/**.v'
- '**/vab_ci.yml'
- '!**.md'
pull_request:
paths:
- 'vlib/**'
- 'thirdparty/**'
- 'cmd/tools/builders/**.v'
- '**/vab_ci.yml'
- '!**.md'
concurrency:
group: vab-${{ github.workflow }}-${{ github.ref == 'refs/heads/master' && github.sha || github.ref }}
cancel-in-progress: true
jobs:
vab-compiles-v-examples:
runs-on: ubuntu-24.04
timeout-minutes: 20
env:
VAB_FLAGS: --api 30 --build-tools 29.0.0 -v 3
steps:
- uses: actions/setup-java@v5
with:
distribution: 'temurin'
java-version: 11
- uses: actions/checkout@v7
- name: Build V
run: make -j4 && ./v symlink
- name: Install vab
run: |
v retry -- v install vab
v -g ~/.vmodules/vab
sudo ln -s ~/.vmodules/vab/vab /usr/local/bin/vab
- name: Run tests
run: v -g test ~/.vmodules/vab
- name: Run vab --help
run: vab --help
- name: Run vab doctor
run: |
vab doctor
which d8 || true
which dx || true
- name: Build graphical V examples as APK
run: |
declare -a v_examples=('flappylearning' '2048' 'fireworks' 'tetris' 'sokol/particles' 'sokol/drawing.v' 'sokol/freetype_raven.v' 'gg/polygons.v' 'gg/raven_text_rendering.v' 'gg/rectangles.v' 'gg/stars.v' 'gg/worker_thread.v')
mkdir apks
for example in "${v_examples[@]}"; do
safe_name=$(echo "$example" | sed 's%/%-%' | sed 's%\.%-%' )
vab "examples/$example" -o "apks/$safe_name.apk"
done
v-compiles-os-android:
runs-on: ubuntu-24.04
timeout-minutes: 20
steps:
- uses: actions/checkout@v7
- name: Build V
run: make -j4 && ./v symlink
- name: Install vab
run: |
v retry -- v install vab
v -g ~/.vmodules/vab
sudo ln -s ~/.vmodules/vab/vab /usr/local/bin/vab
- name: Run vab --help
run: vab --help
- name: Run vab doctor
run: vab doctor
- name: Check `v -os android` *without* -apk flag
run: .github/workflows/android_cross_compile.vsh
+81
View File
@@ -0,0 +1,81 @@
name: Build Vinix
on:
workflow_call:
pull_request:
paths-ignore:
- '**.md'
- '**.yml'
- '!**/vinix_ci.yml'
- 'cmd/tools/vrepl.v'
push:
branches:
- master
paths-ignore:
- '**.md'
- '**.yml'
- '!**/vinix_ci.yml'
- 'cmd/tools/vrepl.v'
concurrency:
group: vinix-${{ github.workflow }}-${{ github.ref == 'refs/heads/master' && github.sha || github.ref }}
cancel-in-progress: true
jobs:
vinix-build:
runs-on: ubuntu-24.04
timeout-minutes: 20
steps:
- uses: actions/checkout@v7
- name: Build V
run: make -j4 && ./v symlink
- name: Install dependencies
run: |
.github/workflows/disable_azure_mirror.sh
v retry -- sudo apt update
v retry -- sudo apt install build-essential -y
- name: Clone current Vinix
run: v retry -- git clone --depth=1 --branch master https://github.com/vlang/vinix.git
- name: Download Vinix kernel dependencies
run: cd vinix/kernel && v retry -- ./get-deps
- name: Attempt to build the Vinix kernel (debug)
run: |
set -e
cd vinix/kernel
make PROD=false \
CFLAGS="-Ulinux -U__linux -U__linux__ -U__gnu_linux__ -D__vinix__ -O2 -g -pipe" \
V="$(realpath ../../v)"
make clean
- name: Attempt to build the Vinix kernel (prod)
run: |
set -e
cd vinix/kernel
make PROD=true \
CFLAGS="-Ulinux -U__linux -U__linux__ -U__gnu_linux__ -D__vinix__ -O2 -g -pipe" \
V="$(realpath ../../v)"
make clean
- name: Attempt to build the util-vinix (debug)
run: |
set -e
cd vinix/util-vinix
make PROD=false \
VFLAGS="-os vinix -gc none" \
CFLAGS="-Ulinux -U__linux -U__linux__ -U__gnu_linux__ -D__vinix__ -O2 -g -pipe" \
V="$(realpath ../../v)"
make clean
- name: Attempt to build the util-vinix (prod)
run: |
set -e
cd vinix/util-vinix
make PROD=true \
VFLAGS="-os vinix -gc none" \
CFLAGS="-Ulinux -U__linux -U__linux__ -U__gnu_linux__ -D__vinix__ -O2 -g -pipe" \
V="$(realpath ../../v)"
make clean
+77
View File
@@ -0,0 +1,77 @@
name: VPM CI
on:
push:
branches:
- master
paths:
- '**/vpm_ci.yml'
- '**/cmd/tools/vpm/**'
pull_request:
paths:
- '**/vpm_ci.yml'
- '**/cmd/tools/vpm/**'
concurrency:
group: vpm-${{ github.workflow }}-${{ github.ref == 'refs/heads/master' && github.sha || github.ref }}
cancel-in-progress: true
jobs:
setup-vpm:
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
fail-fast: false
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v7
with:
path: vlang
- name: Show git version
run: git version
- name: Build V
if: runner.os != 'Windows'
run: cd vlang && make -j4 && ./v doctor
- name: Build V (Windows)
if: runner.os == 'Windows'
run: cd vlang && ./makev.bat && ./v doctor
- name: Cache V
uses: actions/cache/save@v5
with:
path: vlang
key: ${{ runner.os }}-${{ github.sha }}
test-vpm:
needs: setup-vpm
strategy:
matrix:
include:
- os: ubuntu-latest
cc: tcc
- os: ubuntu-latest
cc: gcc
- os: ubuntu-latest
cc: clang
- os: macos-latest
cc: clang
- os: windows-latest
cc: tcc
- os: windows-latest
cc: gcc
- os: windows-latest
cc: msvc
fail-fast: false
runs-on: ${{ matrix.os }}
steps:
- name: Restore V cache
uses: actions/cache/restore@v5
with:
path: vlang
key: ${{ runner.os }}-${{ github.sha }}
- name: Show git version
run: git version
- name: Build and test VPM
run: |
cd vlang
./v -W -N cmd/tools/vpm
./v -cc ${{ matrix.cc }} -d network test cmd/tools/vpm
+131
View File
@@ -0,0 +1,131 @@
name: VSL and VTL
on:
push:
branches:
- master
paths-ignore:
- '**.md'
- '**.yml'
- '!**/vsl_and_vtl_compile_ci.yml'
- 'examples/**'
- 'cmd/tools/vrepl.v'
pull_request:
paths-ignore:
- '**.md'
- '**.yml'
- '!**/vsl_and_vtl_compile_ci.yml'
- 'examples/**'
- 'cmd/tools/vrepl.v'
concurrency:
group: vsl-vtl-${{ github.workflow }}-${{ github.ref == 'refs/heads/master' && github.sha || github.ref }}
cancel-in-progress: true
jobs:
vsl-compiles:
strategy:
matrix:
os: [ubuntu-24.04, macos-14]
fail-fast: false
runs-on: ${{ matrix.os }}
timeout-minutes: 30
env:
VFLAGS: -no-parallel
steps:
- uses: actions/checkout@v7
- name: Cache apt packages
if: runner.os == 'Linux'
uses: ./.github/actions/cache-apt-packages-action
- name: Cache Homebrew downloads
if: runner.os == 'macOS'
uses: actions/cache@v5
with:
path: ~/Library/Caches/Homebrew
key: brew-${{ matrix.os }}-vsl-${{ hashFiles('.github/workflows/vsl_and_vtl_compile_ci.yml') }}
restore-keys: |
brew-${{ matrix.os }}-vsl-
brew-${{ matrix.os }}-
- name: Build V
id: build
run: make && sudo ./v symlink
- name: Install dependencies
run: |
if [ "$RUNNER_OS" == 'Linux' ]; then
.github/workflows/disable_azure_mirror.sh
v retry -- sudo apt -qq update
v retry -- sudo apt -qq install \
libgc-dev libgl1-mesa-dev mesa-common-dev liblapacke-dev libopenblas-dev libopenmpi-dev \
opencl-headers libvulkan-dev libxcursor-dev libxi-dev libxrandr-dev \
libhdf5-cpp-103-1t64 libhdf5-dev libhdf5-mpi-dev hdf5-tools
else
v retry brew install coreutils hdf5 open-mpi openblas lapack opencl-headers
fi
- name: Install vsl
run: v retry -- v install vsl
- name: Skip optional Vulkan examples on macOS
if: runner.os == 'macOS'
run: |
for file in "$HOME"/.vmodules/vsl/examples/*vulkan*/*.v; do
[ -e "$file" ] || continue
mv "$file" "${file%.v}_not_ci.v"
done
- name: Test with Pure V Backend
run: ~/.vmodules/vsl/bin/test
- name: Test with Pure V Backend and Pure V Math
run: ~/.vmodules/vsl/bin/test --use-cblas --skip-examples
vtl-compiles:
strategy:
matrix:
os: [ubuntu-24.04, macos-14]
fail-fast: false
runs-on: ${{ matrix.os }}
timeout-minutes: 25
env:
VFLAGS: -no-parallel
VJOBS: 1
# Fixes complaints about $TERM not being set when running the vtl test script
# (a warning on Linux, but an error on macOS).
TERM: xterm
steps:
- uses: actions/checkout@v7
- name: Cache apt packages
if: runner.os == 'Linux'
uses: ./.github/actions/cache-apt-packages-action
- name: Cache Homebrew downloads
if: runner.os == 'macOS'
uses: actions/cache@v5
with:
path: ~/Library/Caches/Homebrew
key: brew-${{ matrix.os }}-vtl-${{ hashFiles('.github/workflows/vsl_and_vtl_compile_ci.yml') }}
restore-keys: |
brew-${{ matrix.os }}-vtl-
brew-${{ matrix.os }}-
- name: Build V
id: build
run: make && sudo ./v symlink
- name: Install dependencies
run: |
if [ "$RUNNER_OS" == 'Linux' ]; then
.github/workflows/disable_azure_mirror.sh
v retry -- sudo apt -qq update
v retry -- sudo apt -qq install \
libgc-dev libgl1-mesa-dev mesa-common-dev liblapacke-dev libopenblas-dev libopenmpi-dev
else
v retry brew install coreutils hdf5 open-mpi openblas lapack opencl-headers
fi
v retry v install vsl
- name: Install vtl
run: v retry v install vtl
- name: Skip optional Vulkan examples on macOS
if: runner.os == 'macOS'
run: |
for file in "$HOME"/.vmodules/vtl/examples/*vulkan*/*.v; do
[ -e "$file" ] || continue
mv "$file" "${file%.v}_not_ci.v"
done
- name: Test with Pure V Backend
run: ~/.vmodules/vtl/bin/test
- name: Test with Pure V Backend and Pure V Math
run: ~/.vmodules/vtl/bin/test --use-cblas
+87
View File
@@ -0,0 +1,87 @@
name: Upgrading from a previous release with v up works
on:
push:
branches:
- master
paths-ignore:
- '**.md'
- '**.yml'
- '**.vv'
- '**.out'
- '!**/vup_works.yml'
- '!cmd/tools/vup.v'
- 'cmd/tools/vrepl.v'
pull_request:
paths-ignore:
- '**.md'
- '**.yml'
- '**.vv'
- '**.out'
- '!**/vup_works.yml'
- '!cmd/tools/vup.v'
- 'cmd/tools/vrepl.v'
concurrency:
group: vup-${{ github.workflow }}-${{ github.ref == 'refs/heads/master' && github.sha || github.ref }}
cancel-in-progress: true
jobs:
v-up-works-nix:
strategy:
fail-fast: false
matrix:
include:
- os: ubuntu-latest
zip: v_linux.zip
- os: macos-15-intel
zip: v_macos_x86_64.zip
- os: macos-latest
zip: v_macos_arm64.zip
runs-on: ${{ matrix.os }}
timeout-minutes: 20
env:
VDIR: /tmp/v_from_release_zip
steps:
- uses: actions/checkout@v7
- name: Build v
run: make && ./v symlink && ./v version
- name: Download latest release ZIP
run: ./v retry -- ./v download --sha256 https://github.com/vlang/v/releases/latest/download/${{ matrix.zip }}
- name: Extract ZIP 1, no changes
run: |
rm -rf "$VDIR" && unzip -q -d v_from_release/ ${{ matrix.zip }} && mv v_from_release "$VDIR"
cd "$VDIR/v"
./v version
./v up
echo "Updated ./v version: $(./v version) | Current v version: $(v version)"
- name: Extract ZIP 2, with local changes
run: |
rm -rf "$VDIR" && unzip -q -d v_from_release/ ${{ matrix.zip }} && mv v_from_release "$VDIR"
touch "$VDIR/v/vlib/v/pref/local_file_not_present_in_master.c.v" && rm "$VDIR/v/examples/hello_world.v"
cd "$VDIR/v"
./v version
./v up
echo "Updated ./v version: $(./v version) | Current v version: $(v version)"
- name: Extract ZIP 3, with current vup.v in the extract
run: |
rm -rf "$VDIR" && unzip -q -d v_from_release/ ${{ matrix.zip }} && mv v_from_release "$VDIR"
rm -rf "$VDIR/v/cmd/tools/vup" && cp cmd/tools/vup.v "$VDIR/v/cmd/tools/vup.v"
cd "$VDIR/v"
./v version
./v up
echo "Updated ./v version: $(./v version) | Current v version: $(v version)"
- name: Extract ZIP 4, with local changes, and with current vup.v
run: |
rm -rf "$VDIR" && unzip -q -d v_from_release/ ${{ matrix.zip }} && mv v_from_release "$VDIR"
rm -rf "$VDIR/v/cmd/tools/vup" && cp cmd/tools/vup.v "$VDIR/v/cmd/tools/vup.v"
touch "$VDIR/v/vlib/v/pref/local_file_not_present_in_master.c.v" && rm "$VDIR/v/examples/hello_world.v"
cd "$VDIR/v"
./v version
./v up
echo "Updated ./v version: $(./v version) | Current v version: $(v version)"
+87
View File
@@ -0,0 +1,87 @@
name: wasm backend CI
on:
push:
branches:
- master
paths:
- 'cmd/tools/builders/**.v'
- 'vlib/builtin/**.v'
- 'vlib/v/ast/**.v'
- 'vlib/v/scanner/**.v'
- 'vlib/v/parser/**.v'
- 'vlib/v/checker/**.v'
- 'vlib/v/gen/c/**.v'
- 'vlib/v/builder/**.v'
- 'vlib/v/cflag/**.v'
- 'vlib/v/live/**.v'
- 'vlib/v/util/**.v'
- 'vlib/v/markused/**.v'
- 'vlib/v/preludes/**.v'
- 'vlib/v/gen/wasm/**.v'
- 'vlib/v/gen/wasm/tests/**.v'
- 'vlib/v/gen/wasm/tests/**.vv'
- 'vlib/v/gen/wasm/tests_decompile/**.v'
- 'vlib/v/gen/wasm/tests_decompile/**.vv'
- '**/wasm_backend_ci.yml'
pull_request:
paths:
- 'cmd/tools/builders/**.v'
- 'vlib/builtin/**.v'
- 'vlib/v/ast/**.v'
- 'vlib/v/scanner/**.v'
- 'vlib/v/parser/**.v'
- 'vlib/v/checker/**.v'
- 'vlib/v/gen/c/**.v'
- 'vlib/v/builder/**.v'
- 'vlib/v/cflag/**.v'
- 'vlib/v/live/**.v'
- 'vlib/v/util/**.v'
- 'vlib/v/markused/**.v'
- 'vlib/v/preludes/**.v'
- 'vlib/v/gen/wasm/**.v'
- 'vlib/v/gen/wasm/tests/**.v'
- 'vlib/v/gen/wasm/tests/**.vv'
- 'vlib/v/gen/wasm/tests_decompile/**.v'
- 'vlib/v/gen/wasm/tests_decompile/**.vv'
- '**/wasm_backend_ci.yml'
concurrency:
group: wasm-${{ github.workflow }}-${{ github.ref == 'refs/heads/master' && github.sha || github.ref }}
cancel-in-progress: true
jobs:
wasm-backend:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-22.04, windows-2022]
fail-fast: false
timeout-minutes: 20
env:
VTEST_ONLY: wasm
steps:
- uses: actions/checkout@v7
- name: Build V
if: runner.os != 'Windows'
run: make -j4
- name: Build V (Windows)
if: runner.os == 'Windows'
run: ./makev.bat
- name: Install WABT to get wasm-decompile
if: runner.os != 'Windows'
run: ./v retry -- sudo apt install wabt
- name: Setup Wasmer
uses: wasmerio/setup-wasmer@v3.1
- name: Prebuild the WASM backend
run: ./v cmd/tools/builders/wasm_builder.v
- name: Test the WASM backend
run: ./v test vlib/v/gen/wasm/
- name: Build examples
run: ./v build-examples
+104
View File
@@ -0,0 +1,104 @@
name: Websockets CI
on:
push:
branches:
- master
paths-ignore:
- '**.md'
- '**.yml'
- '!**/websockets_ci.yml'
- 'cmd/tools/**'
- '!cmd/tools/builders/**.v'
pull_request:
paths-ignore:
- '**.md'
- '**.yml'
- '!**/websockets_ci.yml'
- 'cmd/tools/**'
- '!cmd/tools/builders/**.v'
concurrency:
group: websockets-${{ github.workflow }}-${{ github.ref == 'refs/heads/master' && github.sha || github.ref }}
cancel-in-progress: true
jobs:
websocket_tests:
runs-on: ubuntu-24.04
timeout-minutes: 121
env:
VFLAGS: -cc tcc -no-retry-compilation
steps:
- uses: actions/checkout@v7
- uses: ./.github/actions/cache-apt-packages-action
- name: Build v
run: |
echo "$VFLAGS"
sudo ln -s "$PWD/thirdparty/tcc/tcc.exe" /usr/local/bin/tcc ## TODO: remove
make -j4 && ./v symlink
./v -g -o v cmd/v
- name: Install dependencies
run: v retry -- sudo apt install --quiet -y libssl-dev
- name: v doctor
run: ./v doctor
- name: Run websockets tests
run: ./v -g test vlib/net/websocket/
## Autobahn integrations tests
- name: Run autobahn services
run: docker compose -f ${{github.workspace}}/vlib/net/websocket/tests/autobahn/docker-compose.yml up -d
- name: Wait for the service to start
run: sleep 10s
- name: Build client test
run: docker exec autobahn_client "/src/v" "/src/vlib/net/websocket/tests/autobahn/autobahn_client.v"
- name: Run client test
run: docker exec autobahn_client "/src/vlib/net/websocket/tests/autobahn/autobahn_client"
- name: Build client wss test
run: docker exec autobahn_client "/src/v" "/src/vlib/net/websocket/tests/autobahn/autobahn_client_wss.v"
- name: Run client wss test
run: docker exec autobahn_client "/src/vlib/net/websocket/tests/autobahn/autobahn_client_wss"
- name: Run server test
run: docker exec autobahn_server "wstest" "-m" "fuzzingclient" "-s" "/config/fuzzingclient.json"
- name: Copy reports
run: docker cp autobahn_server:/reports ${{github.workspace}}/reports
- name: Copy reports wss
run: docker cp autobahn_server_wss:/reports ${{github.workspace}}/reports_wss
- name: Test success
run: docker exec autobahn_server "python" "/check_results.py"
- name: Test success WSS
run: docker exec autobahn_server_wss "python" "/check_results.py"
- name: Publish all reports
uses: actions/upload-artifact@v7
with:
name: full report
path: ${{github.workspace}}/reports
- name: Publish report client
uses: actions/upload-artifact@v7
with:
name: client
path: ${{github.workspace}}/reports/clients/index.html
- name: Publish report server
uses: actions/upload-artifact@v7
with:
name: server
path: ${{github.workspace}}/reports/servers/index.html
- name: Publish all reports WSS
uses: actions/upload-artifact@v7
with:
name: full report wss
path: ${{github.workspace}}/reports_wss
- name: Publish report client wss
uses: actions/upload-artifact@v7
with:
name: client wss
path: ${{github.workspace}}/reports_wss/clients/index.html
+16
View File
@@ -0,0 +1,16 @@
@echo off
curl -L https://www.libsdl.org/release/SDL2-devel-2.0.10-VC.zip -o SDL2.zip
curl -L https://www.libsdl.org/projects/SDL_ttf/release/SDL2_ttf-devel-2.0.15-VC.zip -o SDL2_ttf.zip
curl -L https://www.libsdl.org/projects/SDL_image/release/SDL2_image-devel-2.0.5-VC.zip -o SDL2_image.zip
curl -L https://www.libsdl.org/projects/SDL_mixer/release/SDL2_mixer-devel-2.0.4-VC.zip -o SDL2_mixer.zip
unzip SDL2.zip -d thirdparty/
unzip SDL2_ttf.zip -d thirdparty/
unzip SDL2_image.zip -d thirdparty/
unzip SDL2_mixer.zip -d thirdparty/
move /y thirdparty/SDL2-2.0.10 thirdparty/SDL2
move /y thirdparty/SDL2_ttf-2.0.15 thirdparty/SDL2_ttf
move /y thirdparty/SDL2_image-2.0.5 thirdparty/SDL2_image
move /y thirdparty/SDL2_mixer-2.0.4 thirdparty/SDL2_mixer
+3
View File
@@ -0,0 +1,3 @@
REM This file should be run from the top folder of the V compiler itself.
v vlib/db/sqlite/install_thirdparty_sqlite.vsh
+105
View File
@@ -0,0 +1,105 @@
name: CI Windows GCC
on:
push:
branches:
- master
paths-ignore:
- '**.md'
- '**.yml'
- '!**.bat'
- '!**/windows_ci_gcc.yml'
- 'cmd/tools/**'
- '!cmd/tools/builders/**.v'
pull_request:
paths-ignore:
- '**.md'
- '**.yml'
- '!**.bat'
- '!**/windows_ci_gcc.yml'
- '!**/windows-install-sqlite.bat'
- 'cmd/tools/**'
- '!cmd/tools/builders/**.v'
concurrency:
group: windows-${{ github.workflow }}-${{ github.ref == 'refs/heads/master' && github.sha || github.ref }}
cancel-in-progress: true
jobs:
gcc-windows:
runs-on: windows-2025
timeout-minutes: 110
env:
VFLAGS: -cc gcc
VTEST_SHOW_LONGEST_BY_RUNTIME: 3
VTEST_SHOW_LONGEST_BY_COMPTIME: 3
VTEST_SHOW_LONGEST_BY_TOTALTIME: 3
steps:
- uses: actions/checkout@v7
- name: Show tool versions
run: |
gcc --version
pkg-config --version
openssl version
echo "Flags for openssl:"
pkg-config openssl --cflags
echo "Flags for openssl libs:"
pkg-config openssl --libs
.github/workflows/find_openssl.bat
echo "OpenSSL files:"
where.exe /R "C:\Program Files\OpenSSL" *.*
echo "Include files for openssl:"
dir "c:/Program Files/OpenSSL/include"
echo "Lib Include files for openssl:"
dir "c:/Program Files/OpenSSL/lib/VC/x64/"
- name: Build
run: |
.\makev.bat -gcc
.\v.exe symlink
.\v.exe -stats vlib/crypto/ecdsa/ecdsa_test.v
- name: Test v binaries
run: v build-vbinaries
- name: All code is formatted
run: v -silent test-cleancode
- name: Test new v.c
run: |
v -o v.c cmd/v
$direct_c_flags = @(
'-Ithirdparty/zip'
'-Ithirdparty/cJSON'
'-Ithirdparty/mbedtls/library'
'-Ithirdparty/mbedtls/include'
'-Ithirdparty/mbedtls/3rdparty/everest/include'
'-Ithirdparty/mbedtls/3rdparty/everest/include/everest'
'-Ithirdparty/mbedtls/3rdparty/everest/include/everest/kremlib'
'-Ithirdparty/vschannel'
)
gcc -Werror -municode -w @direct_c_flags v.c -lws2_32 -std=c99
- name: Install dependencies
run: |
v retry -- v setup-freetype
.\.github\workflows\windows-install-sqlite.bat
- name: v doctor
run: |
v doctor
- name: Verify `v test` works
run: |
echo $VFLAGS
v cmd/tools/test_if_v_test_system_works.v
./cmd/tools/test_if_v_test_system_works
- name: Test pure V math module
run: v -silent -exclude @vlib/math/*.c.v test vlib/math/
- name: Self tests
run: v -silent test-self vlib
- name: Build option_test.c.v with -autofree
run: v -autofree vlib/v/tests/options/option_test.c.v
- name: Test v->js
run: v -o hi.js examples/js_hello_world.v && node hi.js
- name: Build examples
run: v build-examples
- name: v2 self compilation
run: v -o v2.exe cmd/v && .\v2.exe -o v3.exe cmd/v
- name: compile vdoctor.v with -prod
run: v -showcc -prod cmd/tools/vdoctor.v
- name: compile vup.v with -prod
run: v -showcc -prod cmd/tools/vup.v
+679
View File
@@ -0,0 +1,679 @@
name: CI Windows MSVC
on:
push:
branches:
- master
paths-ignore:
- '**.md'
- '**.yml'
- '!**.bat'
- '!**/windows_ci_msvc.yml'
- 'cmd/tools/**'
- '!cmd/tools/builders/**.v'
pull_request:
paths-ignore:
- '**.md'
- '**.yml'
- '!**.bat'
- '!**/windows_ci_msvc.yml'
- '!**/windows-install-sqlite.bat'
- 'cmd/tools/**'
- '!cmd/tools/builders/**.v'
concurrency:
group: windows-${{ github.workflow }}-${{ github.ref == 'refs/heads/master' && github.sha || github.ref }}
cancel-in-progress: true
jobs:
msvc-windows:
runs-on: windows-2022
timeout-minutes: 70
env:
VFLAGS: -cc msvc
VTEST_SHOW_LONGEST_BY_RUNTIME: 3
VTEST_SHOW_LONGEST_BY_COMPTIME: 3
VTEST_SHOW_LONGEST_BY_TOTALTIME: 3
steps:
- uses: actions/checkout@v7
- uses: ilammy/msvc-dev-cmd@v1
with:
arch: x64
- name: Verify MSVC tools
run: |
where.exe cl.exe
where.exe link.exe
where.exe dumpbin.exe
- name: Build
run: |
echo %VFLAGS%
echo $VFLAGS
.\makev.bat -msvc
.\v.exe symlink
- name: backend x64 regressions
if: ${{ false }} # Temporarily disabled.
run: |
function Assert-LastExit([string] $label) {
if ($LASTEXITCODE -ne 0) {
throw "$label failed with exit code $LASTEXITCODE"
}
}
$env:VJOBS = '1'
.\v.exe test `
vlib/v2_toberemoved/abi `
vlib/v2_toberemoved/gen/x64/x64_abi_test.v `
vlib/v2_toberemoved/gen/x64/x64_backend_diagnostics_test.v `
vlib/v2_toberemoved/gen/x64/x64_object_format_test.v `
vlib/v2_toberemoved/gen/x64/x64_pe_linker_test.v `
vlib/v2_toberemoved/ssa/tree_sumtype_lowering_test.v
Assert-LastExit 'stable V2 x64 unit tests'
.\v.exe test -run-only test_module_qualified_alias_array_field_index_has_alias_element_type,test_module_storage_legacy_direct_import_nested_module_selector_uses_declared_leaf_module,test_module_storage_flat_direct_import_nested_module_selector_uses_declared_leaf_module vlib/v2_toberemoved/ssa/module_storage_test.v
Assert-LastExit 'targeted vlib/v2_toberemoved/ssa/module_storage_test.v regressions'
.\v.exe test -run-only test_x64_macos_windows_math_log_20_stdout_exact_bytes,test_x64_macos_windows_generic_sumtype_repeated_base_specialization_stdout_exact_bytes,test_x64_macos_windows_formatted_int_interpolation_stdout_exact_bytes,test_x64_macos_windows_formatted_int_width_100_interpolation_stdout_exact_bytes,test_x64_macos_windows_formatted_f64_interpolation_stdout_exact_bytes,test_x64_macos_windows_formatted_string_return_lifetime_stdout_exact_bytes,test_x64_macos_windows_spectral_reduced_formatted_stdout_exact_bytes,test_x64_macos_windows_bits_len32_stdout_exact_bytes,test_x64_macos_windows_rand_u32n_interface_result_stdout_exact_bytes,test_x64_macos_windows_rand_intn_range_interface_result_stdout_exact_bytes,test_x64_macos_windows_textscanner_embedded_parser_stdout_exact_bytes,test_x64_macos_windows_struct_positional_side_effect_stdout_exact_bytes,test_x64_macos_windows_struct_named_side_effect_stdout_exact_bytes,test_x64_macos_windows_unrelated_same_shape_struct_stdout_exact_bytes,test_x64_macos_windows_named_init_embedded_value_stdout_exact_bytes,test_x64_macos_windows_get_raw_line_example_stdin_stdout_exact_bytes,test_x64_macos_windows_mini_calculator_example_stdin_stdout_exact_bytes,test_x64_macos_windows_mini_calculator_recursive_descent_example_stdin_stdout_exact_bytes vlib/v2_toberemoved/gen/x64/x64_runtime_smoke_test.v
Assert-LastExit 'reduced V2 x64 runtime smoke tests'
Remove-Item Env:\VJOBS -ErrorAction SilentlyContinue
.\v.exe test vlib/v2_toberemoved/builder/native_test.v vlib/v2_toberemoved/builder/target_os_test.v
Assert-LastExit 'vlib/v2_toberemoved/builder/native_test.v vlib/v2_toberemoved/builder/target_os_test.v'
.\v.exe test vlib/v2_toberemoved/ssa/optimize
Assert-LastExit 'vlib/v2_toberemoved/ssa/optimize'
$env:V2_VERIFY_STRICT = '1'
.\v.exe test vlib/v2_toberemoved/ssa/optimize
Assert-LastExit 'strict vlib/v2_toberemoved/ssa/optimize'
Remove-Item Env:\V2_VERIFY_STRICT -ErrorAction SilentlyContinue
- name: backend x64 examples
if: ${{ false }} # Temporarily disabled.
run: |
function Assert-LastExit([string] $label) {
if ($LASTEXITCODE -ne 0) {
throw "$label failed with exit code $LASTEXITCODE"
}
}
function Assert-ByteArrayEqual([byte[]] $actual, [byte[]] $expected, [string] $label) {
if ($actual.Length -ne $expected.Length) {
$actual_text = [System.Text.Encoding]::UTF8.GetString($actual)
$expected_text = [System.Text.Encoding]::UTF8.GetString($expected)
throw "$label mismatch. Expected length $($expected.Length), got $($actual.Length).`nExpected:`n$expected_text`nActual:`n$actual_text"
}
for ($i = 0; $i -lt $actual.Length; $i++) {
if ($actual[$i] -ne $expected[$i]) {
$actual_text = [System.Text.Encoding]::UTF8.GetString($actual)
$expected_text = [System.Text.Encoding]::UTF8.GetString($expected)
throw "$label mismatch at byte $i.`nExpected:`n$expected_text`nActual:`n$actual_text"
}
}
}
function Get-PeImportedDlls([string] $exe) {
$output = & dumpbin.exe /imports $exe 2>&1
if ($LASTEXITCODE -ne 0) {
$text = ($output | Out-String).Trim()
throw "dumpbin import inspection failed for $exe with exit code $LASTEXITCODE`n$text"
}
$dlls = [System.Collections.Generic.List[string]]::new()
foreach ($lineObject in $output) {
$line = [string] $lineObject
if ($line -match '^\s*([A-Za-z0-9_.-]+\.dll)\s*$') {
$dlls.Add($matches[1].ToLowerInvariant())
}
}
return $dlls | Sort-Object -Unique
}
function Assert-TinyPeImports([string] $name, [string] $exe, [string] $pe_import_mode) {
if ($pe_import_mode -eq '') {
return
}
if ($pe_import_mode -eq 'tiny-used') {
[string[]] $allowed_dlls = @('kernel32.dll')
} elseif ($pe_import_mode -eq 'tiny-shell32-argv') {
[string[]] $allowed_dlls = @('kernel32.dll', 'shell32.dll')
} else {
throw "$name has unknown PE import validation mode: $pe_import_mode"
}
[string[]] $dlls = @(Get-PeImportedDlls $exe)
if ($dlls.Count -eq 0) {
throw "$name PE import validation found no imported DLLs with dumpbin.exe"
}
$crt_dlls = $dlls | Where-Object {
$_ -match '^(msvcrt|ucrtbase|vcruntime)[0-9]*\.dll$' -or $_ -match '^api-ms-win-crt-.*\.dll$'
}
if ($crt_dlls.Count -gt 0) {
throw "$name tiny PE unexpectedly imports CRT DLL(s): $($crt_dlls -join ', ')"
}
$unexpected_dlls = $dlls | Where-Object { $_ -notin $allowed_dlls }
if ($unexpected_dlls.Count -gt 0) {
throw "$name PE imports unexpected DLL(s): $($unexpected_dlls -join ', ')"
}
$missing_dlls = $allowed_dlls | Where-Object { $_ -notin $dlls }
if ($missing_dlls.Count -gt 0) {
throw "$name PE import validation missed expected DLL(s): $($missing_dlls -join ', ')"
}
}
function Invoke-NativeX64Example([string] $source, [string] $name, [byte[]] $expected_stdout, [string] $pe_import_mode = '', [string[]] $program_args = @()) {
$exe = Join-Path $tmp "$name.exe"
$stdout_path = Join-Path $tmp "$name.out"
$stderr_path = Join-Path $tmp "$name.err"
$compile_output = & .\v.exe -v2 -no-parallel -b x64 $source -o $exe 2>&1
$compile_exit = $LASTEXITCODE
foreach ($line in $compile_output) {
Write-Host $line
}
if ($compile_exit -ne 0) {
throw "compile $source failed with exit code $compile_exit"
}
Assert-TinyPeImports $name $exe $pe_import_mode
Remove-Item -LiteralPath $stdout_path, $stderr_path -Force -ErrorAction SilentlyContinue
if ($program_args.Count -gt 0) {
$process = Start-Process -FilePath $exe -ArgumentList $program_args -NoNewWindow -Wait -PassThru -RedirectStandardOutput $stdout_path -RedirectStandardError $stderr_path
} else {
$process = Start-Process -FilePath $exe -NoNewWindow -Wait -PassThru -RedirectStandardOutput $stdout_path -RedirectStandardError $stderr_path
}
if ($process.ExitCode -ne 0) {
if (Test-Path -LiteralPath $stderr_path) {
Get-Content -LiteralPath $stderr_path
}
throw "$source exited with code $($process.ExitCode)"
}
[byte[]] $stdout = if (Test-Path -LiteralPath $stdout_path) { [System.IO.File]::ReadAllBytes($stdout_path) } else { New-Object byte[] 0 }
[byte[]] $stderr = if (Test-Path -LiteralPath $stderr_path) { [System.IO.File]::ReadAllBytes($stderr_path) } else { New-Object byte[] 0 }
$empty = New-Object byte[] 0
Assert-ByteArrayEqual $stdout $expected_stdout "$source stdout"
Assert-ByteArrayEqual $stderr $empty "$source stderr"
}
function Invoke-NativeX64ExampleWithStdin([string] $source, [string] $name, [byte[]] $expected_stdout, [string] $stdin_path, [string] $pe_import_mode = '', [string[]] $program_args = @()) {
$exe = Join-Path $tmp "$name.exe"
$stdout_path = Join-Path $tmp "$name.out"
$stderr_path = Join-Path $tmp "$name.err"
$compile_output = & .\v.exe -v2 -no-parallel -b x64 $source -o $exe 2>&1
$compile_exit = $LASTEXITCODE
foreach ($line in $compile_output) {
Write-Host $line
}
if ($compile_exit -ne 0) {
throw "compile $source failed with exit code $compile_exit"
}
Assert-TinyPeImports $name $exe $pe_import_mode
Remove-Item -LiteralPath $stdout_path, $stderr_path -Force -ErrorAction SilentlyContinue
if ($program_args.Count -gt 0) {
$process = Start-Process -FilePath $exe -ArgumentList $program_args -NoNewWindow -Wait -PassThru -RedirectStandardInput $stdin_path -RedirectStandardOutput $stdout_path -RedirectStandardError $stderr_path
} else {
$process = Start-Process -FilePath $exe -NoNewWindow -Wait -PassThru -RedirectStandardInput $stdin_path -RedirectStandardOutput $stdout_path -RedirectStandardError $stderr_path
}
if ($process.ExitCode -ne 0) {
if (Test-Path -LiteralPath $stderr_path) {
Get-Content -LiteralPath $stderr_path
}
throw "$source exited with code $($process.ExitCode)"
}
[byte[]] $stdout = if (Test-Path -LiteralPath $stdout_path) { [System.IO.File]::ReadAllBytes($stdout_path) } else { New-Object byte[] 0 }
[byte[]] $stderr = if (Test-Path -LiteralPath $stderr_path) { [System.IO.File]::ReadAllBytes($stderr_path) } else { New-Object byte[] 0 }
$empty = New-Object byte[] 0
Assert-ByteArrayEqual $stdout $expected_stdout "$source stdout"
Assert-ByteArrayEqual $stderr $empty "$source stderr"
}
function Invoke-NativeX64ExampleCapture([string] $source, [string] $name, [string[]] $program_args = @()) {
$exe = Join-Path $tmp "$name.exe"
$stdout_path = Join-Path $tmp "$name.out"
$stderr_path = Join-Path $tmp "$name.err"
$compile_output = & .\v.exe -v2 -no-parallel -b x64 $source -o $exe 2>&1
$compile_exit = $LASTEXITCODE
foreach ($line in $compile_output) {
Write-Host $line
}
if ($compile_exit -ne 0) {
throw "compile $source failed with exit code $compile_exit"
}
Remove-Item -LiteralPath $stdout_path, $stderr_path -Force -ErrorAction SilentlyContinue
if ($program_args.Count -gt 0) {
$process = Start-Process -FilePath $exe -ArgumentList $program_args -NoNewWindow -Wait -PassThru -RedirectStandardOutput $stdout_path -RedirectStandardError $stderr_path
} else {
$process = Start-Process -FilePath $exe -NoNewWindow -Wait -PassThru -RedirectStandardOutput $stdout_path -RedirectStandardError $stderr_path
}
if ($process.ExitCode -ne 0) {
if (Test-Path -LiteralPath $stderr_path) {
Get-Content -LiteralPath $stderr_path
}
throw "$source exited with code $($process.ExitCode)"
}
[byte[]] $stderr = if (Test-Path -LiteralPath $stderr_path) { [System.IO.File]::ReadAllBytes($stderr_path) } else { New-Object byte[] 0 }
$empty = New-Object byte[] 0
Assert-ByteArrayEqual $stderr $empty "$source stderr"
return $stdout_path
}
function Assert-RandomIpsStdout([string] $path) {
[string[]] $lines = [System.IO.File]::ReadAllLines($path)
if ($lines.Count -ne 10) {
throw "random_ips expected 10 lines, got $($lines.Count)"
}
$rows = [System.Collections.Generic.List[string]]::new()
$all_second_zero = $true
$all_fourth_zero = $true
foreach ($line in $lines) {
[string[]] $parts = $line.Split('.')
if ($parts.Count -ne 4) {
throw "random_ips invalid IPv4 shape: $line"
}
[int[]] $octets = @()
foreach ($part in $parts) {
if ($part -notmatch '^[0-9]+$') {
throw "random_ips non-numeric octet: $line"
}
$value = [int] $part
if ($value -lt 0 -or $value -gt 254) {
throw "random_ips octet out of range: $line"
}
$octets += $value
}
if ($octets[1] -ne 0) {
$all_second_zero = $false
}
if ($octets[3] -ne 0) {
$all_fourth_zero = $false
}
$rows.Add(($octets -join '.'))
}
if (($rows | Sort-Object -Unique).Count -lt 3) {
throw 'random_ips output has too little row diversity'
}
if ($all_second_zero -and $all_fourth_zero) {
throw 'random_ips suspicious old x.0.x.0 pattern'
}
}
function Assert-Rule110Stdout([string] $path, [int] $width) {
[string[]] $lines = [System.IO.File]::ReadAllLines($path)
$title = 'Rule 110 V Implementation'
$idx = -1
for ($i = 0; $i -lt $lines.Count; $i++) {
if ($lines[$i].Contains($title)) {
$idx = $i
break
}
}
if ($idx -lt 0) {
throw 'rule110 missing title'
}
[string[]] $generations = @()
if ($idx + 1 -lt $lines.Count) {
$generations = @($lines[($idx + 1)..($lines.Count - 1)])
}
if ($generations.Count -gt 0 -and $generations[0] -eq '') {
if ($generations.Count -eq 1) {
$generations = @()
} else {
$generations = @($generations[1..($generations.Count - 1)])
}
}
if ($generations.Count -ne $width) {
throw "rule110 expected $width generation lines, got $($generations.Count)"
}
$has_live_cell = $false
foreach ($line in $generations) {
if ($line.Length -ne $width) {
throw "rule110 generation line has width $($line.Length), expected $width`: '$line'"
}
if ($line -match '[^ *]') {
throw "rule110 invalid generation chars: '$line'"
}
if ($line.Contains('*')) {
$has_live_cell = $true
}
}
if (-not $has_live_cell) {
throw 'rule110 expected at least one live cell'
}
if (($generations | Sort-Object -Unique).Count -lt 3) {
throw 'rule110 expected at least 3 distinct generation lines'
}
}
$tmp = Join-Path $env:RUNNER_TEMP 'v2_x64_native'
New-Item -ItemType Directory -Force -Path $tmp | Out-Null
function Get-VRunExpectedBytes([string] $source, [string] $name, [string[]] $program_args = @()) {
$stdout_path = Join-Path $tmp "$name.vrun.out"
$stderr_path = Join-Path $tmp "$name.vrun.err"
Remove-Item -LiteralPath $stdout_path, $stderr_path -Force -ErrorAction SilentlyContinue
$v_args = @('run', $source) + $program_args
$process = Start-Process -FilePath '.\v.exe' -ArgumentList $v_args -NoNewWindow -Wait -PassThru -RedirectStandardOutput $stdout_path -RedirectStandardError $stderr_path
if ($process.ExitCode -ne 0) {
if (Test-Path -LiteralPath $stderr_path) {
Get-Content -LiteralPath $stderr_path
}
throw "v run $source $($program_args -join ' ') failed with code $($process.ExitCode)"
}
[byte[]] $stderr = if (Test-Path -LiteralPath $stderr_path) { [System.IO.File]::ReadAllBytes($stderr_path) } else { New-Object byte[] 0 }
$empty = New-Object byte[] 0
Assert-ByteArrayEqual $stderr $empty "v run $source stderr"
return [System.IO.File]::ReadAllBytes($stdout_path)
}
function Get-VRunExpectedBytesWithStdin([string] $source, [string] $name, [string] $stdin_path, [string[]] $program_args = @()) {
$stdout_path = Join-Path $tmp "$name.vrun.out"
$stderr_path = Join-Path $tmp "$name.vrun.err"
Remove-Item -LiteralPath $stdout_path, $stderr_path -Force -ErrorAction SilentlyContinue
$v_args = @('run', $source) + $program_args
$process = Start-Process -FilePath '.\v.exe' -ArgumentList $v_args -NoNewWindow -Wait -PassThru -RedirectStandardInput $stdin_path -RedirectStandardOutput $stdout_path -RedirectStandardError $stderr_path
if ($process.ExitCode -ne 0) {
if (Test-Path -LiteralPath $stderr_path) {
Get-Content -LiteralPath $stderr_path
}
throw "v run $source $($program_args -join ' ') failed with code $($process.ExitCode)"
}
[byte[]] $stderr = if (Test-Path -LiteralPath $stderr_path) { [System.IO.File]::ReadAllBytes($stderr_path) } else { New-Object byte[] 0 }
$empty = New-Object byte[] 0
Assert-ByteArrayEqual $stderr $empty "v run $source stderr"
return [System.IO.File]::ReadAllBytes($stdout_path)
}
$hello_expected = [System.Text.Encoding]::UTF8.GetBytes("Hello, World!`n")
Invoke-NativeX64Example 'examples/hello_world.v' 'hello_world' $hello_expected 'tiny-used'
$fizz_lines = 1..100 | ForEach-Object {
if ($_ % 15 -eq 0) {
'FizzBuzz'
} elseif ($_ % 3 -eq 0) {
'Fizz'
} elseif ($_ % 5 -eq 0) {
'Buzz'
} else {
[string] $_
}
}
$fizz_expected = [System.Text.Encoding]::UTF8.GetBytes(($fizz_lines -join "`n") + "`n")
Invoke-NativeX64Example 'examples/fizz_buzz.v' 'fizz_buzz' $fizz_expected 'tiny-used'
$fibonacci_expected = [System.Text.Encoding]::UTF8.GetBytes("1`n1`n2`n3`n5`n8`n13`n21`n34`n55`n89`n")
Invoke-NativeX64Example 'examples/fibonacci.v' 'fibonacci' $fibonacci_expected 'tiny-shell32-argv' @('10')
$dump_factorial_expected = [System.Text.Encoding]::UTF8.GetBytes("120`n")
Invoke-NativeX64Example 'examples/dump_factorial.v' 'dump_factorial' $dump_factorial_expected 'tiny-used'
function Get-HanoiExpectedLines([int] $n, [string] $a, [string] $b, [string] $c) {
if ($n -eq 1) {
"Disc 1 from $a to $c..."
return
}
Get-HanoiExpectedLines ($n - 1) $a $c $b
"Disc $n from $a to $c..."
Get-HanoiExpectedLines ($n - 1) $b $a $c
}
$hanoi_lines = @(Get-HanoiExpectedLines 7 'A' 'B' 'C')
$hanoi_expected = [System.Text.Encoding]::UTF8.GetBytes(($hanoi_lines -join "`n") + "`n")
Invoke-NativeX64Example 'examples/hanoi.v' 'hanoi' $hanoi_expected 'tiny-used'
function Get-SudokuExpectedLines {
$puzzle = @(
,@(0, 3, 0, 0, 7, 0, 0, 0, 0)
,@(0, 0, 0, 1, 3, 5, 0, 0, 0)
,@(0, 0, 1, 0, 0, 0, 0, 5, 0)
,@(1, 0, 0, 0, 6, 0, 0, 0, 3)
,@(4, 0, 0, 8, 0, 3, 0, 0, 1)
,@(7, 0, 0, 0, 2, 0, 0, 0, 6)
,@(0, 0, 0, 0, 0, 0, 2, 1, 0)
,@(0, 0, 0, 4, 1, 2, 0, 0, 5)
,@(0, 0, 0, 0, 0, 0, 0, 7, 4)
)
$solution = @(
,@(2, 3, 5, 6, 7, 8, 1, 4, 9)
,@(9, 4, 7, 1, 3, 5, 8, 6, 2)
,@(6, 8, 1, 2, 4, 9, 3, 5, 7)
,@(1, 2, 8, 7, 6, 4, 5, 9, 3)
,@(4, 5, 6, 8, 9, 3, 7, 2, 1)
,@(7, 9, 3, 5, 2, 1, 4, 8, 6)
,@(3, 6, 4, 9, 5, 7, 2, 1, 8)
,@(8, 7, 9, 4, 1, 2, 6, 3, 5)
,@(5, 1, 2, 3, 8, 6, 9, 7, 4)
)
$lines = [System.Collections.Generic.List[string]]::new()
function Add-SudokuGrid([string] $label, [object[]] $grid) {
$lines.Add($label)
for ($i = 0; $i -lt $grid.Count; $i++) {
if ($i % 3 -eq 0 -and $i -ne 0) {
$lines.Add('- - - - - - - - - - - -')
}
$line = ''
for ($j = 0; $j -lt $grid[$i].Count; $j++) {
if ($j % 3 -eq 0 -and $j -ne 0) {
$line += ' | '
}
$line += "$($grid[$i][$j]) "
}
$lines.Add($line)
}
}
Add-SudokuGrid 'Sudoku Puzzle:' $puzzle
$lines.Add('Solving...')
Add-SudokuGrid 'Solution:' $solution
return $lines.ToArray()
}
$sudoku_lines = @(Get-SudokuExpectedLines)
$sudoku_expected = [System.Text.Encoding]::UTF8.GetBytes(($sudoku_lines -join "`n") + "`n")
if ($sudoku_expected.Length -ne 582) {
throw "sudoku stdout oracle shape changed: $($sudoku_expected.Length) bytes"
}
Invoke-NativeX64Example 'examples/sudoku.v' 'sudoku' $sudoku_expected
$function_types_expected = [System.Text.Encoding]::UTF8.GetBytes("HELLO WORLD`nHELLO WORLD`nHELLO WORLD`n")
Invoke-NativeX64Example 'examples/function_types.v' 'function_types' $function_types_expected
$submodule_expected = [System.Text.Encoding]::UTF8.GetBytes("5`n3`n")
Invoke-NativeX64Example 'examples/submodule/main.v' 'submodule' $submodule_expected 'tiny-used'
function Get-TreeOfNodesExpectedLines {
@(
'tree structure:'
' Node{'
' value: 10'
' left: Tree(Node{'
' value: 30'
' left: Tree(Empty{})'
' right: Tree(Empty{})'
' })'
' right: Tree(Node{'
' value: 20'
' left: Tree(Empty{})'
' right: Tree(Empty{})'
' })'
'}'
'tree size: 3'
)
}
$tree_of_nodes_lines = @(Get-TreeOfNodesExpectedLines)
$tree_of_nodes_expected = [System.Text.Encoding]::UTF8.GetBytes(($tree_of_nodes_lines -join "`n") + "`n")
if ($tree_of_nodes_expected.Length -ne 259) {
throw "tree_of_nodes stdout oracle shape changed: $($tree_of_nodes_expected.Length) bytes"
}
Invoke-NativeX64Example 'examples/tree_of_nodes.v' 'tree_of_nodes' $tree_of_nodes_expected
$js_hello_world_expected = [System.Text.Encoding]::UTF8.GetBytes("Hello from V.js (0)`nHello from V.js (1)`nHello from V.js (2)`n")
Invoke-NativeX64Example 'examples/js_hello_world.v' 'js_hello_world' $js_hello_world_expected 'tiny-used'
function Get-VSingleQuotedLiteralBytes([string] $literal) {
$bytes = [System.Collections.Generic.List[byte]]::new()
for ($i = 0; $i -lt $literal.Length; $i++) {
$ch = $literal[$i]
if ($ch -eq '\') {
$i++
if ($i -ge $literal.Length) {
throw 'unterminated escape in V single-quoted literal'
}
$escaped = $literal[$i]
switch ([int][char] $escaped) {
110 { [void] $bytes.Add(10) }
116 { [void] $bytes.Add(9) }
114 { [void] $bytes.Add(13) }
92 { [void] $bytes.Add(92) }
39 { [void] $bytes.Add(39) }
34 { [void] $bytes.Add(34) }
default {
foreach ($byte in [System.Text.Encoding]::UTF8.GetBytes([string] $escaped)) {
[void] $bytes.Add($byte)
}
}
}
} else {
foreach ($byte in [System.Text.Encoding]::UTF8.GetBytes([string] $ch)) {
[void] $bytes.Add($byte)
}
}
}
return $bytes.ToArray()
}
function Get-VasciiExpectedBytes() {
$source = [System.IO.File]::ReadAllText((Join-Path (Get-Location) 'examples/vascii.v'), [System.Text.Encoding]::UTF8)
$start_marker = "println('"
$end_marker = "')"
$first = $source.IndexOf($start_marker, [System.StringComparison]::Ordinal)
if ($first -lt 0) {
throw 'missing vascii println literal start'
}
$second = $source.IndexOf($start_marker, $first + $start_marker.Length, [System.StringComparison]::Ordinal)
if ($second -ne -1) {
throw 'vascii stdout oracle expects one single-quoted println literal'
}
$start = $first + $start_marker.Length
$end = $source.LastIndexOf($end_marker, [System.StringComparison]::Ordinal)
if ($end -lt $start) {
throw 'missing vascii println literal end'
}
if ($source.Substring($end + $end_marker.Length).Trim() -ne '}') {
throw 'vascii stdout oracle expects the println literal to be the final main statement'
}
[byte[]] $bytes = Get-VSingleQuotedLiteralBytes ($source.Substring($start, $end - $start))
return $bytes + [byte] 10
}
[byte[]] $vascii_expected = Get-VasciiExpectedBytes
Invoke-NativeX64Example 'examples/vascii.v' 'vascii' $vascii_expected 'tiny-used'
[byte[]] $rune_expected = 0xF0, 0x9F, 0x98, 0x80, 0x0A, 0x40, 0x0A
Invoke-NativeX64Example 'examples/rune.v' 'rune' $rune_expected 'tiny-used'
[byte[]] $bfs_expected = Get-VRunExpectedBytes 'examples/graphs/bfs.v' 'bfs'
Invoke-NativeX64Example 'examples/graphs/bfs.v' 'bfs' $bfs_expected
[byte[]] $bfs3_expected = Get-VRunExpectedBytes 'examples/graphs/bfs3.v' 'bfs3'
Invoke-NativeX64Example 'examples/graphs/bfs3.v' 'bfs3' $bfs3_expected
[byte[]] $primes_expected = Get-VRunExpectedBytes 'examples/primes.v' 'primes' @('20')
Invoke-NativeX64Example 'examples/primes.v' 'primes' $primes_expected '' @('20')
[byte[]] $dfs_expected = Get-VRunExpectedBytes 'examples/graphs/dfs.v' 'dfs'
Invoke-NativeX64Example 'examples/graphs/dfs.v' 'dfs' $dfs_expected
[byte[]] $dijkstra_expected = Get-VRunExpectedBytes 'examples/graphs/dijkstra.v' 'dijkstra'
Invoke-NativeX64Example 'examples/graphs/dijkstra.v' 'dijkstra' $dijkstra_expected
[byte[]] $topological_sorting_greedy_expected = Get-VRunExpectedBytes 'examples/graphs/topological_sorting_greedy.v' 'topological_sorting_greedy'
Invoke-NativeX64Example 'examples/graphs/topological_sorting_greedy.v' 'topological_sorting_greedy' $topological_sorting_greedy_expected
[byte[]] $topological_sorting_dfs_expected = Get-VRunExpectedBytes 'examples/graphs/topological_sorting_dfs.v' 'topological_sorting_dfs'
Invoke-NativeX64Example 'examples/graphs/topological_sorting_dfs.v' 'topological_sorting_dfs' $topological_sorting_dfs_expected
[byte[]] $dfs2_expected = Get-VRunExpectedBytes 'examples/graphs/dfs2.v' 'dfs2'
Invoke-NativeX64Example 'examples/graphs/dfs2.v' 'dfs2' $dfs2_expected
[byte[]] $minimal_spann_tree_prim_expected = Get-VRunExpectedBytes 'examples/graphs/minimal_spann_tree_prim.v' 'minimal_spann_tree_prim'
Invoke-NativeX64Example 'examples/graphs/minimal_spann_tree_prim.v' 'minimal_spann_tree_prim' $minimal_spann_tree_prim_expected
[byte[]] $bellman_ford_expected = Get-VRunExpectedBytes 'examples/graphs/bellman-ford.v' 'bellman_ford'
Invoke-NativeX64Example 'examples/graphs/bellman-ford.v' 'bellman_ford' $bellman_ford_expected
[byte[]] $binary_search_tree_expected = Get-VRunExpectedBytes 'examples/binary_search_tree.v' 'binary_search_tree'
Invoke-NativeX64Example 'examples/binary_search_tree.v' 'binary_search_tree' $binary_search_tree_expected
# normal-required: IError/custom errors
[byte[]] $errors_expected = [System.Text.Encoding]::UTF8.GetBytes("wrong format`nempty input`n")
Invoke-NativeX64Example 'examples/errors.v' 'errors' $errors_expected
[byte[]] $custom_error_expected = Get-VRunExpectedBytes 'examples/custom_error.v' 'custom_error'
Invoke-NativeX64Example 'examples/custom_error.v' 'custom_error' $custom_error_expected
# normal-required: spectral norm/math.sqrt/formatted f64 interpolation
[byte[]] $spectral_expected = Get-VRunExpectedBytes 'examples/spectral.v' 'spectral' @('10')
Invoke-NativeX64Example 'examples/spectral.v' 'spectral' $spectral_expected '' @('10')
[byte[]] $quick_sort_expected = [System.Text.Encoding]::UTF8.GetBytes("length of random array is 1000`nbefore quick sort whether array is sorted: false`nafter quick sort whether array is sorted: true`n")
Invoke-NativeX64Example 'examples/quick_sort.v' 'quick_sort' $quick_sort_expected
$get_raw_line_input = Join-Path $tmp 'get_raw_line.in'
[System.IO.File]::WriteAllText($get_raw_line_input, "hello`nworld`n", [System.Text.UTF8Encoding]::new($false))
[byte[]] $get_raw_line_expected = Get-VRunExpectedBytesWithStdin 'examples/get_raw_line.v' 'get_raw_line' $get_raw_line_input
Invoke-NativeX64ExampleWithStdin 'examples/get_raw_line.v' 'get_raw_line' $get_raw_line_expected $get_raw_line_input
$mini_calculator_input = Join-Path $tmp 'mini_calculator.in'
[System.IO.File]::WriteAllText($mini_calculator_input, "3+4*2`nexit`n", [System.Text.UTF8Encoding]::new($false))
[byte[]] $mini_calculator_expected = Get-VRunExpectedBytesWithStdin 'examples/mini_calculator.v' 'mini_calculator' $mini_calculator_input
Invoke-NativeX64ExampleWithStdin 'examples/mini_calculator.v' 'mini_calculator' $mini_calculator_expected $mini_calculator_input
$mini_calculator_recursive_descent_input = Join-Path $tmp 'mini_calculator_recursive_descent.in'
[System.IO.File]::WriteAllText($mini_calculator_recursive_descent_input, "3+4*2`nexit`n", [System.Text.UTF8Encoding]::new($false))
[byte[]] $mini_calculator_recursive_descent_expected = Get-VRunExpectedBytesWithStdin 'examples/mini_calculator_recursive_descent.v' 'mini_calculator_recursive_descent' $mini_calculator_recursive_descent_input
Invoke-NativeX64ExampleWithStdin 'examples/mini_calculator_recursive_descent.v' 'mini_calculator_recursive_descent' $mini_calculator_recursive_descent_expected $mini_calculator_recursive_descent_input
$random_ips_stdout = Invoke-NativeX64ExampleCapture 'examples/random_ips.v' 'random_ips'
Assert-RandomIpsStdout $random_ips_stdout
$rule110_stdout = Invoke-NativeX64ExampleCapture 'examples/rule110.v' 'rule110' @('31')
Assert-Rule110Stdout $rule110_stdout 31
- name: Build V with WX
run: v -cflags /WX self
- name: All code is formatted
run: v -silent test-cleancode
- name: Test -cc msvc works
run: v -no-retry-compilation run examples/hello_world.v
- name: Install dependencies
run: |
v retry -- v setup-freetype
.\.github\workflows\windows-install-sqlite.bat
- name: v doctor
run: |
v doctor
- name: Verify `v test` works
run: |
echo $VFLAGS
v cmd/tools/test_if_v_test_system_works.v
./cmd/tools/test_if_v_test_system_works
- name: Test pure V math module
run: v -silent -exclude @vlib/math/*.c.v test vlib/math/
- name: Self tests
run: v -silent test-self vlib
- name: Test v->js
run: v -o hi.js examples/js_hello_world.v && node hi.js
- name: Test v binaries
run: v build-vbinaries
- name: Build examples
run: v build-examples
- name: v2 self compilation
run: v -o v2.exe cmd/v && .\v2.exe -o v3.exe cmd/v
+93
View File
@@ -0,0 +1,93 @@
name: CI Windows TCC
on:
push:
branches:
- master
paths-ignore:
- '**.md'
- '**.yml'
- '!**.bat'
- '!**/windows_ci_tcc.yml'
- 'cmd/tools/**'
- '!cmd/tools/builders/**.v'
pull_request:
paths-ignore:
- '**.md'
- '**.yml'
- '!**.bat'
- '!**/windows_ci_tcc.yml'
- '!**/windows-install-sqlite.bat'
- 'cmd/tools/**'
- '!cmd/tools/builders/**.v'
concurrency:
group: windows-${{ github.workflow }}-${{ github.ref == 'refs/heads/master' && github.sha || github.ref }}
cancel-in-progress: true
jobs:
tcc-windows:
runs-on: windows-2022
timeout-minutes: 60
env:
VFLAGS: -cc tcc -no-retry-compilation
VTEST_SHOW_LONGEST_BY_RUNTIME: 3
VTEST_SHOW_LONGEST_BY_COMPTIME: 3
VTEST_SHOW_LONGEST_BY_TOTALTIME: 3
steps:
- uses: actions/checkout@v7
- name: Build with makev.bat -tcc
run: |
.\makev.bat -tcc
.\v.exe symlink
- name: All code is formatted
run: v -silent test-cleancode
- name: Test new v.c
run: |
v -o v.c cmd/v
$direct_c_flags = @(
'-Ithirdparty/zip'
'-Ithirdparty/cJSON'
'-Ithirdparty/mbedtls/library'
'-Ithirdparty/mbedtls/include'
'-Ithirdparty/mbedtls/3rdparty/everest/include'
'-Ithirdparty/mbedtls/3rdparty/everest/include/everest'
'-Ithirdparty/mbedtls/3rdparty/everest/include/everest/kremlib'
'-Ithirdparty/vschannel'
)
# Match makev.bat's Windows stack reserve; the direct TCC-built
# compiler can otherwise crash while compiling net.http-heavy scripts.
.\thirdparty\tcc\tcc.exe -Werror -w @direct_c_flags -ladvapi32 -lws2_32 -bt10 '-Wl,-stack=33554432' v.c
- name: Install dependencies
run: |
v retry -- v setup-freetype
.\.github\workflows\windows-install-sqlite.bat
- name: v -g self
run: v -g self
- name: v doctor
run: |
v doctor
- name: Verify `v test` works
run: |
v cmd/tools/test_if_v_test_system_works.v
.\cmd\tools\test_if_v_test_system_works.exe
- name: Verify `v vlib/v/gen/c/coutput_test.v` works
run: v vlib/v/gen/c/coutput_test.v
- name: Make sure running TCC64 instead of TCC32
run: v test .github\workflows\make_sure_ci_run_with_64bit_compiler_test.v
- name: Test ./v doc -v clipboard *BEFORE building tools*
run: v doc -v clipboard
- name: Test v build-tools
run: v -silent -W build-tools
- name: Test pure V math module
run: v -silent -exclude @vlib/math/*.c.v test vlib/math/
- name: Self tests
run: v -silent test-self vlib
- name: Test v->js
run: v -o hi.js examples/js_hello_world.v && node hi.js
- name: Test v binaries
run: v build-vbinaries
- name: Build examples
run: v build-examples
- name: v2 self compilation
run: v -o v2.exe cmd/v && .\v2.exe -o v3.exe cmd/v && .\v3.exe -o v4.exe cmd/v
+27
View File
@@ -0,0 +1,27 @@
name: Workflow Lint
## Note: to install `prettier` locally, see https://prettier.io/docs/en/install,
## or just: `npm install --save-dev --save-exact prettier`
## If you already have `prettier` installed, to run it locally,
## just run: `npx prettier --check **.yml` .
on:
push:
branches:
- master
paths:
- '**.yml'
pull_request:
paths:
- '**.yml'
jobs:
lint-yml-workflows:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- name: Verify formatting
uses: creyD/prettier_action@v4.6
with:
prettier_options: --check **.yml