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

+801
View File
@@ -0,0 +1,801 @@
#
# Automatically generated file; DO NOT EDIT.
# crosstool-NG 1.28.0 Configuration
#
CT_CONFIGURE_has_cxx11=y
CT_CONFIGURE_has_lzip=y
CT_CONFIGURE_has_curl=y
CT_CONFIGURE_has_ninja=y
CT_CONFIGURE_has_make_3_81_or_newer=y
CT_CONFIGURE_has_make_4_0_or_newer=y
CT_CONFIGURE_has_make_4_4_or_newer=y
CT_CONFIGURE_has_libtool_2_4_or_newer=y
CT_CONFIGURE_has_libtoolize_2_4_or_newer=y
CT_CONFIGURE_has_autoconf_2_65_or_newer=y
CT_CONFIGURE_has_autoreconf_2_65_or_newer=y
CT_CONFIGURE_has_gnu_m4_1_4_12_or_newer=y
CT_CONFIGURE_has_python_3_4_or_newer=y
CT_CONFIGURE_has_bison_2_7_or_newer=y
CT_CONFIGURE_has_bison_3_0_4_or_newer=y
CT_CONFIGURE_has_python=y
CT_CONFIGURE_has_svn=y
CT_CONFIGURE_has_git=y
CT_CONFIGURE_has_md5sum=y
CT_CONFIGURE_has_sha1sum=y
CT_CONFIGURE_has_sha256sum=y
CT_CONFIGURE_has_sha512sum=y
CT_CONFIGURE_has_install_with_strip_program=y
CT_VERSION="1.28.0"
CT_VCHECK="load"
CT_CONFIG_VERSION_ENV="4"
CT_CONFIG_VERSION_CURRENT="4"
CT_CONFIG_VERSION="4"
CT_MODULES=y
#
# Paths and misc options
#
#
# crosstool-NG behavior
#
# CT_OBSOLETE is not set
CT_EXPERIMENTAL=y
# CT_ALLOW_BUILD_AS_ROOT is not set
# CT_ENABLE_EXPERIMENTAL_BUNDLED_PATCHES is not set
# CT_DEBUG_CT is not set
#
# Paths
#
CT_LOCAL_TARBALLS_DIR="${HOME}/src"
CT_SAVE_TARBALLS=y
# CT_TARBALLS_BUILDROOT_LAYOUT is not set
CT_WORK_DIR="${CT_TOP_DIR}/.build"
CT_BUILD_TOP_DIR="${CT_WORK_DIR:-${CT_TOP_DIR}/.build}/${CT_HOST:+HOST-${CT_HOST}/}${CT_TARGET}"
CT_BUILD_DIR="${CT_BUILD_TOP_DIR}/build"
CT_PREFIX_DIR="${CT_PREFIX:-${HOME}/x-tools}/${CT_HOST:+HOST-${CT_HOST}/}${CT_TARGET}"
CT_RM_RF_PREFIX_DIR=y
CT_REMOVE_DOCS=y
CT_INSTALL_LICENSES=y
CT_PREFIX_DIR_RO=y
CT_STRIP_HOST_TOOLCHAIN_EXECUTABLES=y
# CT_STRIP_TARGET_TOOLCHAIN_EXECUTABLES is not set
# CT_TARBALL_RESULT is not set
#
# Downloading
#
CT_DOWNLOAD_AGENT_CURL=y
# CT_DOWNLOAD_AGENT_NONE is not set
# CT_FORBID_DOWNLOAD is not set
# CT_FORCE_DOWNLOAD is not set
CT_CONNECT_TIMEOUT=10
CT_DOWNLOAD_CURL_OPTIONS="--location --ftp-pasv --retry 3 --fail --silent"
# CT_ONLY_DOWNLOAD is not set
# CT_USE_MIRROR is not set
CT_VERIFY_DOWNLOAD_DIGEST=y
CT_VERIFY_DOWNLOAD_DIGEST_SHA512=y
# CT_VERIFY_DOWNLOAD_DIGEST_SHA256 is not set
# CT_VERIFY_DOWNLOAD_DIGEST_SHA1 is not set
# CT_VERIFY_DOWNLOAD_DIGEST_MD5 is not set
CT_VERIFY_DOWNLOAD_DIGEST_ALG="sha512"
# CT_VERIFY_DOWNLOAD_SIGNATURE is not set
#
# Extracting
#
# CT_FORCE_EXTRACT is not set
CT_OVERRIDE_CONFIG_GUESS_SUB=y
# CT_ONLY_EXTRACT is not set
CT_PATCH_BUNDLED=y
# CT_PATCH_LOCAL is not set
# CT_PATCH_BUNDLED_LOCAL is not set
# CT_PATCH_LOCAL_BUNDLED is not set
# CT_PATCH_NONE is not set
CT_PATCH_ORDER="bundled"
#
# Build behavior
#
CT_PARALLEL_JOBS=0
CT_LOAD=""
CT_USE_PIPES=y
CT_EXTRA_CFLAGS_FOR_BUILD=""
CT_EXTRA_CXXFLAGS_FOR_BUILD=""
CT_EXTRA_LDFLAGS_FOR_BUILD=""
CT_EXTRA_CFLAGS_FOR_HOST=""
CT_EXTRA_LDFLAGS_FOR_HOST=""
# CT_CONFIG_SHELL_SH is not set
# CT_CONFIG_SHELL_ASH is not set
CT_CONFIG_SHELL_BASH=y
# CT_CONFIG_SHELL_CUSTOM is not set
CT_CONFIG_SHELL="${bash}"
#
# Logging
#
# CT_LOG_ERROR is not set
# CT_LOG_WARN is not set
# CT_LOG_INFO is not set
CT_LOG_EXTRA=y
# CT_LOG_ALL is not set
# CT_LOG_DEBUG is not set
CT_LOG_LEVEL_MAX="EXTRA"
# CT_LOG_SEE_TOOLS_WARN is not set
CT_LOG_PROGRESS_BAR=y
CT_LOG_TO_FILE=y
CT_LOG_FILE_COMPRESS=y
# end of Paths and misc options
#
# Target options
#
# CT_ARCH_ALPHA is not set
# CT_ARCH_ARC is not set
# CT_ARCH_ARM is not set
# CT_ARCH_AVR is not set
# CT_ARCH_BPF is not set
# CT_ARCH_C6X is not set
# CT_ARCH_LM32 is not set
# CT_ARCH_LOONGARCH is not set
# CT_ARCH_M68K is not set
# CT_ARCH_MICROBLAZE is not set
# CT_ARCH_MIPS is not set
# CT_ARCH_MOXIE is not set
# CT_ARCH_MSP430 is not set
# CT_ARCH_NIOS2 is not set
# CT_ARCH_OPENRISC is not set
# CT_ARCH_PARISC is not set
# CT_ARCH_POWERPC is not set
# CT_ARCH_PRU is not set
# CT_ARCH_RISCV is not set
# CT_ARCH_RX is not set
# CT_ARCH_S390 is not set
# CT_ARCH_SH is not set
# CT_ARCH_SPARC is not set
# CT_ARCH_TRICORE is not set
CT_ARCH_X86=y
# CT_ARCH_XTENSA is not set
CT_ARCH="x86"
CT_ARCH_CHOICE_KSYM="X86"
CT_ARCH_CPU=""
CT_ARCH_TUNE=""
CT_ARCH_X86_SHOW=y
#
# Options for x86
#
CT_ARCH_X86_PKG_KSYM=""
CT_ALL_ARCH_CHOICES="ALPHA ARC ARM AVR BPF C6X LM32 LOONGARCH M68K MICROBLAZE MIPS MOXIE MSP430 NIOS2 OPENRISC PARISC POWERPC PRU RISCV RX S390 SH SPARC TRICORE X86 XTENSA"
CT_ARCH_SUFFIX=""
# CT_OMIT_TARGET_VENDOR is not set
#
# Generic target options
#
CT_MULTILIB=y
# CT_DEMULTILIB is not set
CT_ARCH_USE_MMU=y
CT_ARCH_SUPPORTS_LIBSANITIZER=y
CT_ARCH_SUPPORTS_32=y
CT_ARCH_SUPPORTS_64=y
CT_ARCH_DEFAULT_32=y
CT_ARCH_BITNESS=64
# CT_ARCH_32 is not set
CT_ARCH_64=y
CT_ARCH_SUPPORTS_WITH_32_64=y
#
# Target optimisations
#
CT_ARCH_SUPPORTS_WITH_ARCH=y
CT_ARCH_SUPPORTS_WITH_CPU=y
CT_ARCH_SUPPORTS_WITH_TUNE=y
CT_ARCH_ARCH=""
CT_TARGET_CFLAGS=""
CT_TARGET_LDFLAGS=""
# end of Target options
#
# Toolchain options
#
#
# General toolchain options
#
CT_FORCE_SYSROOT=y
CT_USE_SYSROOT=y
CT_SYSROOT_NAME="sysroot"
CT_SYSROOT_DIR_PREFIX=""
CT_SHOW_CT_VERSION=y
CT_TOOLCHAIN_PKGVERSION=""
CT_TOOLCHAIN_BUGURL=""
#
# Tuple completion and aliasing
#
CT_TARGET_VENDOR="w64"
CT_TARGET_ALIAS_SED_EXPR=""
CT_TARGET_ALIAS=""
#
# Toolchain type
#
# CT_NATIVE is not set
CT_CROSS=y
# CT_CROSS_NATIVE is not set
# CT_CANADIAN is not set
CT_TOOLCHAIN_TYPE="cross"
#
# Build system
#
CT_BUILD=""
CT_BUILD_PREFIX=""
CT_BUILD_SUFFIX=""
#
# Misc options
#
# CT_TOOLCHAIN_ENABLE_NLS is not set
CT_TOOLCHAIN_CMAKE_TOOLCHAIN_FILE=y
# end of Toolchain options
#
# Operating System
#
CT_WINDOWS=y
CT_KERNEL_SUPPORTS_SHARED_LIBS=y
# CT_KERNEL_BARE_METAL is not set
# CT_KERNEL_LINUX is not set
CT_KERNEL_WINDOWS=y
CT_KERNEL="windows"
CT_KERNEL_CHOICE_KSYM="WINDOWS"
CT_KERNEL_WINDOWS_SHOW=y
#
# Options for windows
#
CT_KERNEL_WINDOWS_PKG_KSYM=""
CT_ALL_KERNEL_CHOICES="BARE_METAL LINUX WINDOWS"
#
# Common kernel options
#
CT_SHARED_LIBS=y
# end of Operating System
#
# Binary utilities
#
CT_ARCH_BINFMT_ELF=y
CT_BINUTILS_BINUTILS=y
CT_BINUTILS="binutils"
CT_BINUTILS_CHOICE_KSYM="BINUTILS"
CT_BINUTILS_BINUTILS_SHOW=y
#
# Options for binutils
#
CT_BINUTILS_BINUTILS_PKG_KSYM="BINUTILS"
CT_BINUTILS_DIR_NAME="binutils"
CT_BINUTILS_USE_GNU=y
# CT_BINUTILS_USE_LINARO is not set
# CT_BINUTILS_USE_ORACLE is not set
CT_BINUTILS_USE="BINUTILS"
CT_BINUTILS_PKG_NAME="binutils"
CT_BINUTILS_SRC_RELEASE=y
# CT_BINUTILS_SRC_DEVEL is not set
# CT_BINUTILS_SRC_CUSTOM is not set
CT_BINUTILS_PATCH_GLOBAL=y
# CT_BINUTILS_PATCH_BUNDLED is not set
# CT_BINUTILS_PATCH_LOCAL is not set
# CT_BINUTILS_PATCH_BUNDLED_LOCAL is not set
# CT_BINUTILS_PATCH_LOCAL_BUNDLED is not set
# CT_BINUTILS_PATCH_NONE is not set
CT_BINUTILS_PATCH_ORDER="global"
CT_BINUTILS_V_2_45=y
# CT_BINUTILS_V_2_44 is not set
# CT_BINUTILS_V_2_43 is not set
# CT_BINUTILS_V_2_42 is not set
# CT_BINUTILS_V_2_41 is not set
# CT_BINUTILS_V_2_40 is not set
# CT_BINUTILS_V_2_39 is not set
# CT_BINUTILS_V_2_38 is not set
# CT_BINUTILS_V_2_37 is not set
# CT_BINUTILS_V_2_36 is not set
# CT_BINUTILS_V_2_35 is not set
# CT_BINUTILS_V_2_34 is not set
# CT_BINUTILS_V_2_33 is not set
# CT_BINUTILS_V_2_32 is not set
# CT_BINUTILS_V_2_31 is not set
# CT_BINUTILS_V_2_30 is not set
# CT_BINUTILS_V_2_29 is not set
# CT_BINUTILS_V_2_28 is not set
# CT_BINUTILS_V_2_27 is not set
# CT_BINUTILS_V_2_26 is not set
CT_BINUTILS_VERSION="2.45"
CT_BINUTILS_MIRRORS="$(CT_Mirrors GNU binutils) $(CT_Mirrors sourceware binutils/releases)"
CT_BINUTILS_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
CT_BINUTILS_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
CT_BINUTILS_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz"
CT_BINUTILS_SIGNATURE_FORMAT="packed/.sig"
CT_BINUTILS_2_45_or_later=y
CT_BINUTILS_2_45_or_older=y
CT_BINUTILS_later_than_2_44=y
CT_BINUTILS_2_44_or_later=y
CT_BINUTILS_later_than_2_41=y
CT_BINUTILS_2_41_or_later=y
CT_BINUTILS_later_than_2_39=y
CT_BINUTILS_2_39_or_later=y
CT_BINUTILS_later_than_2_30=y
CT_BINUTILS_2_30_or_later=y
CT_BINUTILS_later_than_2_27=y
CT_BINUTILS_2_27_or_later=y
CT_BINUTILS_later_than_2_26=y
CT_BINUTILS_2_26_or_later=y
#
# GNU binutils
#
CT_BINUTILS_GOLD_SUPPORTS_ARCH=y
CT_BINUTILS_FORCE_LD_BFD_DEFAULT=y
CT_BINUTILS_LINKER_LD=y
CT_BINUTILS_LINKERS_LIST="ld"
CT_BINUTILS_LINKER_DEFAULT="bfd"
CT_BINUTILS_PLUGINS=y
CT_BINUTILS_RELRO=m
CT_BINUTILS_DETERMINISTIC_ARCHIVES=y
CT_BINUTILS_EXTRA_CONFIG_ARRAY=""
# CT_BINUTILS_FOR_TARGET is not set
# CT_BINUTILS_GPROFNG is not set
CT_ALL_BINUTILS_CHOICES="BINUTILS"
# end of Binary utilities
#
# C-library
#
CT_LIBC_MINGW_W64=y
CT_LIBC="mingw-w64"
CT_LIBC_CHOICE_KSYM="MINGW_W64"
CT_THREADS="posix"
CT_LIBC_MINGW_W64_SHOW=y
#
# Options for mingw-w64
#
CT_LIBC_MINGW_W64_PKG_KSYM="MINGW_W64"
CT_MINGW_W64_DIR_NAME="mingw-w64"
CT_MINGW_W64_PKG_NAME="mingw-w64"
CT_MINGW_W64_SRC_RELEASE=y
# CT_MINGW_W64_SRC_DEVEL is not set
# CT_MINGW_W64_SRC_CUSTOM is not set
CT_MINGW_W64_PATCH_GLOBAL=y
# CT_MINGW_W64_PATCH_BUNDLED is not set
# CT_MINGW_W64_PATCH_LOCAL is not set
# CT_MINGW_W64_PATCH_BUNDLED_LOCAL is not set
# CT_MINGW_W64_PATCH_LOCAL_BUNDLED is not set
# CT_MINGW_W64_PATCH_NONE is not set
CT_MINGW_W64_PATCH_ORDER="global"
CT_MINGW_W64_V_V13_0=y
# CT_MINGW_W64_V_V12_0 is not set
# CT_MINGW_W64_V_V11_0 is not set
# CT_MINGW_W64_V_V10_0 is not set
# CT_MINGW_W64_V_V9_0 is not set
# CT_MINGW_W64_V_V8_0 is not set
# CT_MINGW_W64_V_V7_0 is not set
# CT_MINGW_W64_V_V6_0 is not set
# CT_MINGW_W64_V_V5_0 is not set
# CT_MINGW_W64_V_V4_0 is not set
CT_MINGW_W64_VERSION="v13.0.0"
CT_MINGW_W64_MIRRORS="http://downloads.sourceforge.net/sourceforge/mingw-w64 https://downloads.sourceforge.net/project/mingw-w64/mingw-w64/mingw-w64-release/"
CT_MINGW_W64_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
CT_MINGW_W64_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
CT_MINGW_W64_ARCHIVE_FORMATS=".tar.bz2 .zip"
CT_MINGW_W64_SIGNATURE_FORMAT="packed/.sig"
CT_MINGW_SECURE_API=y
CT_MINGW_DEFAULT_MSVCRT_DEFAULT=y
# CT_MINGW_DEFAULT_MSVCRT_MSVCRT is not set
# CT_MINGW_DEFAULT_MSVCRT_UCRT is not set
# CT_MINGW_DEFAULT_MSVCRT_CUSTOM is not set
CT_MINGW_DIRECTX=y
CT_MINGW_DDK=y
CT_MINGW_TOOLS=y
CT_MINGW_TOOL_LIST_ARRAY="gendef genidl genlib genpeimg widl"
CT_ALL_LIBC_CHOICES="AVR_LIBC GLIBC MINGW_W64 MOXIEBOX MUSL NEWLIB NONE PICOLIBC UCLIBC_NG"
CT_LIBC_SUPPORT_THREADS_ANY=y
CT_LIBC_SUPPORT_THREADS_NATIVE=y
CT_LIBC_SUPPORT_THREADS_POSIX=y
#
# Common C library options
#
# CT_THREADS_NATIVE is not set
CT_THREADS_POSIX=y
CT_CREATE_LDSO_CONF=y
CT_LDSO_CONF_EXTRA_DIRS_ARRAY=""
CT_LIBC_XLDD=y
# end of C-library
#
# C compiler
#
CT_CC_CORE_NEEDED=y
CT_CC_SUPPORT_CXX=y
CT_CC_SUPPORT_FORTRAN=y
CT_CC_SUPPORT_ADA=y
CT_CC_SUPPORT_D=y
CT_CC_SUPPORT_JIT=y
CT_CC_SUPPORT_OBJC=y
CT_CC_SUPPORT_OBJCXX=y
CT_CC_SUPPORT_GOLANG=y
CT_CC_GCC=y
CT_CC="gcc"
CT_CC_CHOICE_KSYM="GCC"
CT_CC_GCC_SHOW=y
#
# Options for gcc
#
CT_CC_GCC_PKG_KSYM="GCC"
CT_GCC_DIR_NAME="gcc"
CT_GCC_USE_GNU=y
# CT_GCC_USE_LINARO is not set
# CT_GCC_USE_ORACLE is not set
CT_GCC_USE="GCC"
CT_GCC_PKG_NAME="gcc"
CT_GCC_SRC_RELEASE=y
# CT_GCC_SRC_DEVEL is not set
# CT_GCC_SRC_CUSTOM is not set
CT_GCC_PATCH_GLOBAL=y
# CT_GCC_PATCH_BUNDLED is not set
# CT_GCC_PATCH_LOCAL is not set
# CT_GCC_PATCH_BUNDLED_LOCAL is not set
# CT_GCC_PATCH_LOCAL_BUNDLED is not set
# CT_GCC_PATCH_NONE is not set
CT_GCC_PATCH_ORDER="global"
CT_GCC_V_15=y
# CT_GCC_V_14 is not set
# CT_GCC_V_13 is not set
# CT_GCC_V_12 is not set
# CT_GCC_V_11 is not set
# CT_GCC_V_10 is not set
# CT_GCC_V_9 is not set
# CT_GCC_V_8 is not set
# CT_GCC_V_7 is not set
# CT_GCC_V_6 is not set
# CT_GCC_V_5 is not set
# CT_GCC_V_4_9 is not set
CT_GCC_VERSION="15.2.0"
CT_GCC_MIRRORS="$(CT_Mirrors GNU gcc/gcc-${CT_GCC_VERSION}) $(CT_Mirrors sourceware gcc/releases/gcc-${CT_GCC_VERSION})"
CT_GCC_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
CT_GCC_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
CT_GCC_ARCHIVE_FORMATS=".tar.xz .tar.gz"
CT_GCC_SIGNATURE_FORMAT=""
CT_GCC_later_than_15=y
CT_GCC_15_or_later=y
CT_GCC_later_than_14=y
CT_GCC_14_or_later=y
CT_GCC_later_than_13=y
CT_GCC_13_or_later=y
CT_GCC_later_than_12=y
CT_GCC_12_or_later=y
CT_GCC_later_than_11=y
CT_GCC_11_or_later=y
CT_GCC_later_than_10=y
CT_GCC_10_or_later=y
CT_GCC_later_than_9=y
CT_GCC_9_or_later=y
CT_GCC_later_than_8=y
CT_GCC_8_or_later=y
CT_GCC_later_than_7=y
CT_GCC_7_or_later=y
CT_GCC_later_than_6=y
CT_GCC_6_or_later=y
CT_GCC_later_than_5=y
CT_GCC_5_or_later=y
CT_GCC_later_than_4_9=y
CT_GCC_4_9_or_later=y
CT_CC_GCC_ENABLE_PLUGINS=y
CT_CC_GCC_HAS_LIBMPX=y
CT_CC_GCC_ENABLE_CXX_FLAGS=""
CT_CC_GCC_CORE_EXTRA_CONFIG_ARRAY=""
CT_CC_GCC_EXTRA_CONFIG_ARRAY=""
CT_CC_GCC_MULTILIB_LIST=""
# CT_CC_GCC_SYSTEM_ZLIB is not set
CT_CC_GCC_CONFIG_TLS=m
#
# Optimisation features
#
CT_CC_GCC_USE_GRAPHITE=y
CT_CC_GCC_USE_LTO=y
CT_CC_GCC_LTO_ZSTD=m
#
# Settings for libraries running on target
#
CT_CC_GCC_ENABLE_TARGET_OPTSPACE=y
CT_CC_GCC_LIBSTDCXX=m
# CT_CC_GCC_LIBSTDCXX_HOSTED_DISABLE is not set
CT_CC_GCC_LIBSTDCXX_TARGET_CXXFLAGS=""
# CT_CC_GCC_LIBMUDFLAP is not set
# CT_CC_GCC_LIBGOMP is not set
# CT_CC_GCC_LIBSSP is not set
# CT_CC_GCC_LIBQUADMATH is not set
CT_CC_GCC_LIBSTDCXX_VERBOSE=m
#
# Misc. obscure options.
#
CT_CC_CXA_ATEXIT=y
CT_CC_GCC_TM_CLONE_REGISTRY=m
# CT_CC_GCC_DISABLE_PCH is not set
CT_CC_GCC_SJLJ_EXCEPTIONS=m
CT_CC_GCC_LDBL_128=m
# CT_CC_GCC_BUILD_ID is not set
CT_CC_GCC_LNK_HASH_STYLE_DEFAULT=y
# CT_CC_GCC_LNK_HASH_STYLE_SYSV is not set
# CT_CC_GCC_LNK_HASH_STYLE_GNU is not set
# CT_CC_GCC_LNK_HASH_STYLE_BOTH is not set
CT_CC_GCC_LNK_HASH_STYLE=""
CT_CC_GCC_DEC_FLOATS_AUTO=y
# CT_CC_GCC_DEC_FLOATS_BID is not set
# CT_CC_GCC_DEC_FLOATS_DPD is not set
# CT_CC_GCC_DEC_FLOATS_NO is not set
CT_CC_GCC_DEC_FLOATS=""
CT_ALL_CC_CHOICES="GCC"
#
# Additional supported languages:
#
CT_CC_LANG_CXX=y
CT_CC_LANG_FORTRAN=y
# CT_CC_LANG_JIT is not set
# CT_CC_LANG_ADA is not set
# CT_CC_LANG_D is not set
# CT_CC_LANG_OBJC is not set
# CT_CC_LANG_OBJCXX is not set
# CT_CC_LANG_GOLANG is not set
CT_CC_LANG_OTHERS=""
# end of C compiler
#
# Linkers
#
#
# BFD enabled in binutils
#
# CT_LINKER_MOLD is not set
CT_ALL_LINKER_CHOICES="MOLD"
# end of Linkers
#
# Debug facilities
#
# CT_DEBUG_DUMA is not set
# CT_DEBUG_GDB is not set
# CT_DEBUG_LTRACE is not set
# CT_DEBUG_STRACE is not set
CT_ALL_DEBUG_CHOICES="DUMA GDB LTRACE STRACE"
# end of Debug facilities
#
# Companion libraries
#
# CT_COMPLIBS_CHECK is not set
# CT_COMP_LIBS_CLOOG is not set
# CT_COMP_LIBS_EXPAT is not set
# CT_COMP_LIBS_GETTEXT is not set
CT_COMP_LIBS_GMP=y
CT_COMP_LIBS_GMP_PKG_KSYM="GMP"
CT_GMP_DIR_NAME="gmp"
CT_GMP_PKG_NAME="gmp"
CT_GMP_SRC_RELEASE=y
# CT_GMP_SRC_DEVEL is not set
# CT_GMP_SRC_CUSTOM is not set
CT_GMP_PATCH_GLOBAL=y
# CT_GMP_PATCH_BUNDLED is not set
# CT_GMP_PATCH_LOCAL is not set
# CT_GMP_PATCH_BUNDLED_LOCAL is not set
# CT_GMP_PATCH_LOCAL_BUNDLED is not set
# CT_GMP_PATCH_NONE is not set
CT_GMP_PATCH_ORDER="global"
CT_GMP_V_6_3=y
# CT_GMP_V_6_2 is not set
# CT_GMP_V_6_1 is not set
CT_GMP_VERSION="6.3.0"
CT_GMP_MIRRORS="https://gmplib.org/download/gmp https://gmplib.org/download/gmp/archive $(CT_Mirrors GNU gmp)"
CT_GMP_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
CT_GMP_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
CT_GMP_ARCHIVE_FORMATS=".tar.xz .tar.lz .tar.bz2"
CT_GMP_SIGNATURE_FORMAT="packed/.sig"
CT_GMP_EXTRA_CFLAGS="-std=gnu17"
CT_COMP_LIBS_ISL=y
CT_COMP_LIBS_ISL_PKG_KSYM="ISL"
CT_ISL_DIR_NAME="isl"
CT_ISL_PKG_NAME="isl"
CT_ISL_SRC_RELEASE=y
# CT_ISL_SRC_DEVEL is not set
# CT_ISL_SRC_CUSTOM is not set
CT_ISL_PATCH_GLOBAL=y
# CT_ISL_PATCH_BUNDLED is not set
# CT_ISL_PATCH_LOCAL is not set
# CT_ISL_PATCH_BUNDLED_LOCAL is not set
# CT_ISL_PATCH_LOCAL_BUNDLED is not set
# CT_ISL_PATCH_NONE is not set
CT_ISL_PATCH_ORDER="global"
CT_ISL_V_0_27=y
# CT_ISL_V_0_26 is not set
# CT_ISL_V_0_25 is not set
# CT_ISL_V_0_24 is not set
# CT_ISL_V_0_23 is not set
# CT_ISL_V_0_22 is not set
# CT_ISL_V_0_21 is not set
# CT_ISL_V_0_20 is not set
# CT_ISL_V_0_19 is not set
# CT_ISL_V_0_18 is not set
# CT_ISL_V_0_17 is not set
# CT_ISL_V_0_16 is not set
# CT_ISL_V_0_15 is not set
CT_ISL_VERSION="0.27"
CT_ISL_MIRRORS="https://libisl.sourceforge.io"
CT_ISL_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
CT_ISL_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
CT_ISL_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz"
CT_ISL_SIGNATURE_FORMAT=""
CT_ISL_later_than_0_18=y
CT_ISL_0_18_or_later=y
CT_ISL_later_than_0_15=y
CT_ISL_0_15_or_later=y
# CT_COMP_LIBS_LIBELF is not set
# CT_COMP_LIBS_LIBICONV is not set
CT_COMP_LIBS_MPC=y
CT_COMP_LIBS_MPC_PKG_KSYM="MPC"
CT_MPC_DIR_NAME="mpc"
CT_MPC_PKG_NAME="mpc"
CT_MPC_SRC_RELEASE=y
# CT_MPC_SRC_DEVEL is not set
# CT_MPC_SRC_CUSTOM is not set
CT_MPC_PATCH_GLOBAL=y
# CT_MPC_PATCH_BUNDLED is not set
# CT_MPC_PATCH_LOCAL is not set
# CT_MPC_PATCH_BUNDLED_LOCAL is not set
# CT_MPC_PATCH_LOCAL_BUNDLED is not set
# CT_MPC_PATCH_NONE is not set
CT_MPC_PATCH_ORDER="global"
CT_MPC_V_1_3=y
CT_MPC_VERSION="1.3.1"
CT_MPC_MIRRORS="https://www.multiprecision.org/downloads $(CT_Mirrors GNU mpc)"
CT_MPC_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
CT_MPC_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
CT_MPC_ARCHIVE_FORMATS=".tar.gz"
CT_MPC_SIGNATURE_FORMAT="packed/.sig"
CT_COMP_LIBS_MPFR=y
CT_COMP_LIBS_MPFR_PKG_KSYM="MPFR"
CT_MPFR_DIR_NAME="mpfr"
CT_MPFR_PKG_NAME="mpfr"
CT_MPFR_SRC_RELEASE=y
# CT_MPFR_SRC_DEVEL is not set
# CT_MPFR_SRC_CUSTOM is not set
CT_MPFR_PATCH_GLOBAL=y
# CT_MPFR_PATCH_BUNDLED is not set
# CT_MPFR_PATCH_LOCAL is not set
# CT_MPFR_PATCH_BUNDLED_LOCAL is not set
# CT_MPFR_PATCH_LOCAL_BUNDLED is not set
# CT_MPFR_PATCH_NONE is not set
CT_MPFR_PATCH_ORDER="global"
CT_MPFR_V_4_2=y
CT_MPFR_VERSION="4.2.2"
CT_MPFR_MIRRORS="https://www.mpfr.org/mpfr-${CT_MPFR_VERSION} $(CT_Mirrors GNU mpfr)"
CT_MPFR_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
CT_MPFR_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
CT_MPFR_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz .zip"
CT_MPFR_SIGNATURE_FORMAT="packed/.asc"
# CT_COMP_LIBS_NCURSES is not set
CT_COMP_LIBS_ZLIB=y
CT_COMP_LIBS_ZLIB_PKG_KSYM="ZLIB"
CT_ZLIB_DIR_NAME="zlib"
CT_ZLIB_PKG_NAME="zlib"
CT_ZLIB_SRC_RELEASE=y
# CT_ZLIB_SRC_DEVEL is not set
# CT_ZLIB_SRC_CUSTOM is not set
CT_ZLIB_PATCH_GLOBAL=y
# CT_ZLIB_PATCH_BUNDLED is not set
# CT_ZLIB_PATCH_LOCAL is not set
# CT_ZLIB_PATCH_BUNDLED_LOCAL is not set
# CT_ZLIB_PATCH_LOCAL_BUNDLED is not set
# CT_ZLIB_PATCH_NONE is not set
CT_ZLIB_PATCH_ORDER="global"
CT_ZLIB_V_1_3_1=y
# CT_ZLIB_V_1_2_13 is not set
CT_ZLIB_VERSION="1.3.1"
CT_ZLIB_MIRRORS="https://github.com/madler/zlib/releases/download/v${CT_ZLIB_VERSION} https://www.zlib.net/"
CT_ZLIB_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
CT_ZLIB_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
CT_ZLIB_ARCHIVE_FORMATS=".tar.xz .tar.gz"
CT_ZLIB_SIGNATURE_FORMAT="packed/.asc"
CT_COMP_LIBS_ZSTD=y
CT_COMP_LIBS_ZSTD_PKG_KSYM="ZSTD"
CT_ZSTD_DIR_NAME="zstd"
CT_ZSTD_PKG_NAME="zstd"
CT_ZSTD_SRC_RELEASE=y
# CT_ZSTD_SRC_DEVEL is not set
# CT_ZSTD_SRC_CUSTOM is not set
CT_ZSTD_PATCH_GLOBAL=y
# CT_ZSTD_PATCH_BUNDLED is not set
# CT_ZSTD_PATCH_LOCAL is not set
# CT_ZSTD_PATCH_BUNDLED_LOCAL is not set
# CT_ZSTD_PATCH_LOCAL_BUNDLED is not set
# CT_ZSTD_PATCH_NONE is not set
CT_ZSTD_PATCH_ORDER="global"
CT_ZSTD_V_1_5_7=y
# CT_ZSTD_V_1_5_6 is not set
# CT_ZSTD_V_1_5_5 is not set
# CT_ZSTD_V_1_5_2 is not set
CT_ZSTD_VERSION="1.5.7"
CT_ZSTD_MIRRORS="https://github.com/facebook/zstd/releases/download/v${CT_ZSTD_VERSION} https://downloads.sourceforge.net/project/zstandard.mirror/v${CT_ZSTD_VERSION}"
CT_ZSTD_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
CT_ZSTD_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
CT_ZSTD_ARCHIVE_FORMATS=".tar.gz"
CT_ZSTD_SIGNATURE_FORMAT="packed/.sig"
CT_ALL_COMP_LIBS_CHOICES="CLOOG EXPAT GETTEXT GMP GNUPRUMCU ISL LIBELF LIBICONV MPC MPFR NCURSES NEWLIB_NANO PICOLIBC ZLIB ZSTD"
# CT_LIBICONV_NEEDED is not set
# CT_GETTEXT_NEEDED is not set
CT_GMP_NEEDED=y
CT_MPFR_NEEDED=y
CT_ISL_NEEDED=y
CT_MPC_NEEDED=y
CT_ZLIB_NEEDED=y
CT_ZSTD_NEEDED=y
CT_GMP=y
CT_MPFR=y
CT_ISL=y
CT_MPC=y
CT_ZLIB=y
CT_ZSTD=y
# end of Companion libraries
#
# Companion tools
#
# CT_COMP_TOOLS_FOR_HOST is not set
# CT_COMP_TOOLS_AUTOCONF is not set
CT_COMP_TOOLS_AUTOMAKE=y
CT_COMP_TOOLS_AUTOMAKE_PKG_KSYM="AUTOMAKE"
CT_AUTOMAKE_DIR_NAME="automake"
CT_AUTOMAKE_PKG_NAME="automake"
CT_AUTOMAKE_SRC_RELEASE=y
# CT_AUTOMAKE_SRC_DEVEL is not set
# CT_AUTOMAKE_SRC_CUSTOM is not set
CT_AUTOMAKE_PATCH_GLOBAL=y
# CT_AUTOMAKE_PATCH_BUNDLED is not set
# CT_AUTOMAKE_PATCH_LOCAL is not set
# CT_AUTOMAKE_PATCH_BUNDLED_LOCAL is not set
# CT_AUTOMAKE_PATCH_LOCAL_BUNDLED is not set
# CT_AUTOMAKE_PATCH_NONE is not set
CT_AUTOMAKE_PATCH_ORDER="global"
CT_AUTOMAKE_V_1_17=y
# CT_AUTOMAKE_V_1_16 is not set
# CT_AUTOMAKE_V_1_15 is not set
CT_AUTOMAKE_VERSION="1.17"
CT_AUTOMAKE_MIRRORS="$(CT_Mirrors GNU automake)"
CT_AUTOMAKE_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
CT_AUTOMAKE_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
CT_AUTOMAKE_ARCHIVE_FORMATS=".tar.xz .tar.gz"
CT_AUTOMAKE_SIGNATURE_FORMAT="packed/.sig"
# CT_COMP_TOOLS_BISON is not set
# CT_COMP_TOOLS_DTC is not set
# CT_COMP_TOOLS_LIBTOOL is not set
# CT_COMP_TOOLS_M4 is not set
# CT_COMP_TOOLS_MAKE is not set
CT_ALL_COMP_TOOLS_CHOICES="AUTOCONF AUTOMAKE BISON DTC LIBTOOL M4 MAKE"
# end of Companion tools
#
# Test suite
#
# CT_TEST_SUITE_GCC is not set
# end of Test suite
+44
View File
@@ -0,0 +1,44 @@
#!/bin/sh
# tools/fv/fv - Flying V build wrapper.
# The public Agila source now uses the .fv extension, but the underlying V
# compiler only accepts .v files. This wrapper stages temporary .v copies of
# every .fv file in the project, invokes tools/v/v, and then removes the copies.
set -eu
ROOT=$(CDPATH= cd -- "$(dirname -- "$0")/../.." && pwd)
V_CMD="./tools/v/v"
stage_all_fv() {
# Copy every .fv source to a sibling .v, except inside the V compiler tree.
find "$ROOT" -name '*.fv' -not -path '*/tools/v/*' -print0 \
| while IFS= read -r -d '' fv; do
cp "$fv" "${fv%.fv}.v"
done
}
cleanup() {
# Remove any temporary .v files we created, but never touch the V compiler.
find "$ROOT" -name '*.v' -not -path '*/tools/v/*' -delete
}
trap cleanup EXIT INT TERM
stage_all_fv
# Rewrite arguments from .fv to .v and make them relative to ROOT so the V
# compiler does not have to deal with the space in the parent directory name.
new_args=""
for arg in "$@"; do
rel="$arg"
case "$arg" in
"$ROOT"/*) rel="${arg#$ROOT/}" ;;
"$ROOT") rel="." ;;
esac
case "$rel" in
*.fv) new_args="$new_args ${rel%.fv}.v" ;;
*) new_args="$new_args $rel" ;;
esac
done
cd "$ROOT"
"$V_CMD" $new_args
+58
View File
@@ -0,0 +1,58 @@
#!/usr/bin/env python3
"""Generate an 8x8 bitmap font for Agila from a system monospace font."""
from PIL import Image, ImageDraw, ImageFont
font_names = [
"/System/Library/Fonts/Menlo.ttc",
"/System/Library/Fonts/Monaco.dfont",
"/Library/Fonts/Courier New.ttf",
"/System/Library/Fonts/Courier.dfont",
]
font = None
for name in font_names:
try:
font = ImageFont.truetype(name, 8)
print(f"Using font: {name}")
break
except Exception as e:
print(f"Failed {name}: {e}")
if font is None:
print("No suitable font found, using default")
font = ImageFont.load_default()
w, h = 8, 8
values = []
for code in range(32, 127):
ch = chr(code)
img = Image.new("L", (w, h), 0)
draw = ImageDraw.Draw(img)
draw.text((0, 0), ch, font=font, fill=255)
bytes_data = []
for col in range(w):
byte_val = 0
for row in range(h):
px = img.getpixel((col, row))
if px > 127:
byte_val |= 1 << row
bytes_data.append(byte_val)
values.extend(bytes_data)
with open("api/v/font5x7.fv", "w") as f:
f.write("// font5x7.fv - 8x8 bitmap font (ASCII 32-126)\n")
f.write("module agila\n\n")
f.write("const font5x7 = [u8(0x{:02x}), ".format(values[0]))
f.write(", ".join(f"0x{v:02x}" for v in values[1:]))
f.write("]\n\n")
f.write("pub fn glyph5x7(ch rune) []u8 {\n")
f.write("\tcode := int(ch) - 32\n")
f.write("\tif code < 0 || code > 94 {\n")
f.write("\t\treturn font5x7[0..8] // space\n")
f.write("\t}\n")
f.write("\toff := code * 8\n")
f.write("\treturn font5x7[off..off+8]\n")
f.write("}\n")
print(f"Generated {len(values)} bytes for {len(values)//8} glyphs")
+32
View File
@@ -0,0 +1,32 @@
root = true
[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
[*.{v,js,css}]
indent_style = tab
[*.{bat,cmd}]
# BAT/CMD ~ DOS/Win requires BAT/CMD files to have CRLF EOLNs
end_of_line = crlf
[*.{yml,yaml}]
indent_style = space
indent_size = 2
[*.md]
trim_trailing_whitespace = false
# lines that are too long will trigger an error in cmd/tools/vcheck-md.v
# run v check-md [folder/file] to test markdown files
# the longest normal line is specified with this constant:
# `too_long_line_length_other = 100`
max_line_length = 100
[*.{txt,out}]
insert_final_newline = false
[{Makefile,GNUmakefile}]
indent_style = tab
+10
View File
@@ -0,0 +1,10 @@
* text=auto eol=lf
*.bat eol=crlf
*.v linguist-language=V
*.vv linguist-language=V
*.vsh linguist-language=V
v.mod linguist-language=V
.vdocignore linguist-language=ignore
Dockerfile.* linguist-language=Dockerfile
+3
View File
@@ -0,0 +1,3 @@
{
"singleQuote": true
}
+5
View File
@@ -0,0 +1,5 @@
# These are supported funding model platforms
open_collective: vlang
patreon: vlang
github: [medvednikov]
+9
View File
@@ -0,0 +1,9 @@
blank_issues_enabled: true
contact_links:
- name: 💬 General Questions and Answers about V
url: https://github.com/vlang/v/discussions/categories/questions-and-answers
about: You can ask and answer questions about V in the discussions forum.
- name: 💬 Discord Server
url: https://discord.gg/vlang
about: You can join our Discord server for real time discussion and support
+19
View File
@@ -0,0 +1,19 @@
name: 📕 Documentation Issue
description: Report an issue in the Reference documentation or Developer Guide
labels: ['Unit: Documentation']
body:
- type: textarea
id: description
attributes:
label: Describe the issue
description: A clear and concise description of the issue.
validations:
required: true
- type: textarea
id: links
attributes:
label: Links
description: Include links to affected documentation page(s).
validations:
required: true
+63
View File
@@ -0,0 +1,63 @@
name: 🚀 Feature Request
description: Suggest an idea for this project
labels: [Feature Request]
body:
- type: textarea
id: description
attributes:
label: Describe the feature
description: A clear and concise description of the feature you are proposing.
validations:
required: true
- type: textarea
id: use-case
attributes:
label: Use Case
description: |
Why do you need this feature? For example: "I'm always frustrated when..."
validations:
required: true
- type: textarea
id: solution
attributes:
label: Proposed Solution
description: Suggest how to implement the addition or change. Please include prototype/workaround/sketch/reference implementation.
validations:
required: false
- type: textarea
id: other
attributes:
label: Other Information
description: Any alternative solutions or features you considered, a more detailed explanation, stack traces, related issues, links for context, etc.
validations:
required: false
- type: checkboxes
id: ack
attributes:
label: Acknowledgements
options:
- label: I may be able to implement this feature request
required: false
- label: This feature might incur a breaking change
required: false
- type: input
id: version
attributes:
label: Version used
description: Please provide the version of the repository or tool you are using.
validations:
required: true
- type: textarea
id: environment
attributes:
label: Environment details (OS name and version, etc.)
description: You can use `v doctor` to fill up this section.
validations:
required: true
+34
View File
@@ -0,0 +1,34 @@
<!--
Please title your PR as follows: `module: description` (e.g. `time: fix date format`).
Always start with the thing you are fixing, then describe the fix.
Don't use past tense (e.g. "fixed foo bar").
Explain what your PR does and why.
If you are adding a new function, please document it and add tests:
```
// foo does foo and bar
fn foo() {
// file_test.v
fn test_foo() {
assert foo() == ...
...
}
```
If you are fixing a bug, please add a test that covers it.
Before submitting a PR, please run `v test-all` .
See also `TESTS.md`.
I try to process PRs as soon as possible. They should be handled within 24 hours.
Applying labels to PRs is not needed.
Thanks a lot for your contribution!
-->
@@ -0,0 +1,30 @@
name: 'Cache Apt Packages'
description: 'Cache all commonly used apt packages to speed up CI jobs'
# imagemagick : convert, mogrify
# xvfb : xvfb
# openimageio-tools : idiff
# libxcursor-dev libxi-dev : V gfx deps
# libgl1-mesa-dri : For headless rendering on the CI / software DRI driver (LIBGL_ALWAYS_SOFTWARE=true)
# freeglut3-dev : Fixes graphic apps compilation with tcc
# sdl2 : needed for Puzzle Vibes & Chocolate Doom
# libsodium-dev : needed for Gitly and C2V
runs:
using: 'composite'
steps:
- uses: awalsh128/cache-apt-pkgs-action@v1.5.3
with:
version: 1.0
packages: expect binutils postgresql sqlite3 clang valgrind \
imagemagick openimageio-tools xvfb xsel xclip \
libsodium-dev libpq-dev libssl-dev libsqlite3-dev \
libfreetype6-dev libxi-dev libxcursor-dev \
libgl-dev libxrandr-dev libasound2-dev \
libx11-dev freeglut3-dev mesa-common-dev libgl1-mesa-dev libgl1-mesa-dri \
libsdl2-dev libsdl2-ttf-dev libsdl2-mixer-dev libsdl2-image-dev libsdl2-net-dev \
libpng-dev libsamplerate0-dev \
xfonts-75dpi xfonts-base
- name: Install common packages
run: echo "done installing packages"
shell: bash
+6
View File
@@ -0,0 +1,6 @@
version: 2
updates:
- package-ecosystem: 'github-actions'
directory: '/'
schedule:
interval: 'daily'
+19
View File
@@ -0,0 +1,19 @@
// The task of this program, is to register all available .json files
// in this folder with Github Actions, so that it can make annotations
// for all found notices/warnings/errors produced by the V compiler
// while running the CI jobs.
// Those annotations provide a way to get a quick overview for failures,
// without having to scroll into the detailed logs produced by each job.
const github_job = getenv('GITHUB_JOB')
if github_job == '' {
exit(0)
}
dump(github_job)
chdir(@VEXEROOT)!
for f in walk_ext('.github/problem-matchers/', '.json').sorted() {
println('::add-matcher::${real_path(f)}')
println('registered matcher: `${f}`')
}
+18
View File
@@ -0,0 +1,18 @@
{
"__comment": "Based on https://github.com/python/cpython/blob/main/.github/problem-matchers/gcc.json",
"problemMatcher": [
{
"owner": "v-problem-matcher",
"pattern": [
{
"regexp": "^(.*):(\\d+):(\\d+):\\s+(?:fatal\\s+)?(error):\\s+(.*)$",
"file": 1,
"line": 2,
"column": 3,
"severity": 4,
"message": 5
}
]
}
]
}
+30
View File
@@ -0,0 +1,30 @@
module main
import os
fn show_release_tag_for(now string) string {
script_path := os.join_path(os.dir(@FILE), 'workflows', 'show_manual_release_cmd.vsh')
cmd := 'V_RELEASE_TAG_NOW="${now}" ${os.quoted_path(@VEXE)} run ${os.quoted_path(script_path)}'
res := os.execute(cmd)
assert res.exit_code == 0, res.output
for line in res.output.split_into_lines() {
if line.contains('current release_tag: ') {
return line.all_after('current release_tag: ')
}
}
panic('missing release tag in output:\n${res.output}')
}
fn test_show_manual_release_cmd_uses_iso_week_year() {
test_cases := {
'2025-12-28 00:00:00': 'weekly.2025.52'
'2025-12-29 00:00:00': 'weekly.2026.01'
'2025-12-31 00:00:00': 'weekly.2026.01'
'2026-01-01 00:00:00': 'weekly.2026.01'
'2026-01-04 00:00:00': 'weekly.2026.01'
'2026-01-05 00:00:00': 'weekly.2026.02'
}
for input, expected in test_cases {
assert show_release_tag_for(input) == expected
}
}
+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
+174
View File
@@ -0,0 +1,174 @@
# ignore sub-level extensionless build outputs
*/**/*
!*/
!*.*
# ignore generated binaries and object files
*.exe
*.o
*.so
.*.c
*.tmp.c
*.obj
*.exp
*.ilk
*.pdb
*.dll
*.lib
*.bak
*.dylib
a.out
.noprefix.vrepl_temp
# ignore v build files
# *.exe is already ignored above
/v
/v2
/vc
/v.c
/v.*.c
/v.c.out
/v_old
/vdbg
/vold
/vnew
/vprod
/vprod_gcc
/vprod_clang
.vrepl_temp.v
fns.txt
.noprefix.vrepl_temp.v
# Prefix local scratch/repro files with tmp. when they should stay untracked.
tmp.*
# ignore temp and cache directories
temp/
tmp/
cache/
.cache/
# unignore special files without extension
!.github/PULL_REQUEST_TEMPLATE
!.editorconfig
!.gitattributes
!.gitignore
!BSDmakefile
!Dockerfile
!Dockerfile.alpine
!Dockerfile.cross
!LICENSE
!Makefile
!GNUmakefile
# ignore editor files
.project/
.classpath/
.c9/
.vs/
*.launch
.settings/
*.sublime-workspace
.vscode/
*.code-workspace
*~
~*
.sesskey
*.db
*.swp
*.swo
*.swn
.env
# ignore debugger files
cachegrind.out.*
.gdb_history
*.dSYM
*.def
vgcore.*
# ignore system files
.DS_Store
._*
thumbs.db
/.symlink
/.bin
_docs
# ignore vs databases
*.suo
*.VC.db
*.rsp
# ignore cmd/tools/.disable_autorecompilation, which some package managers use.
cmd/tools/.disable_autorecompilation
test.bin
# ignore codespace env
.venv/
.direnv/
shell.nix
default.nix
flake.nix
.envrc
# generated by thirdparty/stdatomic/nix/cpp/gen.v
thirdparty/stdatomic/nix/cpp/*.h
# ignore thirdparty libs that are distributed separately
thirdparty/binaryen*
thirdparty/wabt*
thirdparty/tcc/
thirdparty/sqlite/
# ignore VLS log
vls.log
# ignore v2go tmperror files
*.tmperr
.vtmp_cov_*/
# ignore Intellij files
.idea/
/*.iml
# ignore generated files:
wasm.v
# ignore large GTK *.gir files
Gtk-4.0.gir
*.gir
vlib/builtin/js/*.js
vlib/v/tests/*.js
# ignore tags indexes, used by emacs/vim:
ETAGS
TAGS
tags
# ignore the old regexp based v.ctags file (people using universal ctags < 6.1.0, can still benefit from them)
.ctags.d/v.ctags
# ignore .NET7.0 Assembly Files
bench/vectors/bin
bench/vectors/obj
autofuzz.log
.project.gf
.aider*
# ignore common file names for bugs/reproductions
bug*
issue*
# ignore cmd2/v stuff
cmd/v2/*.txt
cmd/v2/*.json
.claude/
.copilot/
.agents/
.codex/
+726
View File
@@ -0,0 +1,726 @@
<!-- V_AGENTS.md v1.1 2026-02-04 -->
# V Repo Guide
Practical quick reference for the V compiler, standard library, and tools.
Written for AI coding agents; useful for humans too.
## Contents
* Quick Start
* Top Rules
* Agent Rules
* Safety (Do Not Brick the Repo)
* Divergences From Repo Docs
* Quick Decisions
* Common Workflow
* Reporting
* Prerequisites
* Build & Rebuild
* Run Programs
* Testing
* Code Style
* Modules and Imports
* C/JS Interop Hygiene
* Environment-Specific Code (files and `$if`)
* Compile-Time Code and Reflection
* Debug
* Compiler Architecture
* Key Directories
* Test Locations
* Error Reporting (checker/parser)
* Option/Result Types
* Tools
* Commits and PRs
* Environment Variables
* Gotchas
## Quick Start
Get operational from the repo root in three steps:
1. Build once (only if `./v` is missing): `make`
2. Build a working compiler:
* Debug-friendly (recommended): `./v -g -keepc -o ./vnew cmd/v`
3. Use `./vnew` for everything:
* Run a file: `./vnew run examples/hello_world.v`
* Run tests: `./vnew -silent test vlib/v/`
* Format: `./vnew fmt -w path/to/file.v`
Then read Top Rules and Agent Rules before making changes.
## Top Rules
* Use `./v` only to build `./vnew`; use `./vnew` for everything else.
* Put all V flags immediately after `./vnew` and before the
subcommand/file, e.g. `./vnew -g run file.v`
(not `./vnew run file.v -g`); flags after the subcommand are passed
to that subcommand.
* Rebuild `./vnew` after compiler or core module changes
(see Build & Rebuild).
* Run the smallest relevant tests; see Testing for triggers and
minimums.
* Ask before large refactors or wide file touches (see Agent Rules).
* Do not stash or modify unrelated files unless explicitly instructed.
* This guide assumes agents run locally, not in CI; CI notes are
informational only.
* When a summary is required, include behavior change, tests run, and
touched file paths.
* If instructions overlap, prefer Build & Rebuild, Testing, and
Reporting.
* If duplicates drift, treat Build & Rebuild, Testing, and Reporting as
canonical and align other sections to them.
## Agent Rules
### Repo root
All commands assume the repo root as the working directory. The default
location is `/opt/v`, but this may differ in your environment. If a
command fails due to missing paths, verify with `pwd` and adjust
accordingly. Use a per-command workdir only when a task requires a
subdir.
### Tone and output
* Be concise by default. If the user asks for depth, provide it while
keeping structure tight.
* Keep output easy to scan: short sections, bullets when listing,
commands in backticks, no filler.
* Use a strict, operational tone unless higher-priority instructions
override it.
* Ask only when required. If information is missing, ask a direct
question.
### File access and edit scope
* You may read and edit all files in the V repo without asking for
permission. This is file access, not change scope; scope is
constrained below. Reading is always OK.
Edits to `ci/` or `Dockerfile*` still require an explicit ask.
* Run build, test, and format commands without asking for permission.
These are validation steps, not code changes. Only ask about edit
scope, not about running `fmt`, targeted tests, or `check-md`.
* Only modify files required for the user request; avoid unrelated
refactors. If duplication is harmful, small refactors to remove it
are OK only when needed. Only refactor duplication in code you are
already touching, and only when it directly supports the request or
fixes a bug there. "Touching" means files already modified for the
request.
* Avoid unrelated file changes; call them out if present.
* Avoid touching `thirdparty/` unless explicitly requested. If changes
are needed there, ask for approval before proceeding.
### When to ask
* Ask before large refactors or wide file touches (more than 5 files,
or changes across multiple repo-root directories like `cmd/`, `vlib/`,
`doc/`, `examples/`).
Exception: docs-only changes across many files are OK without asking;
call them out in the summary.
* Ask before large behavioral changes within a single subsystem or file,
even if the file count is small. Examples: changes to parser rules,
checker resolution, codegen output shape, diagnostic text/ordering, or
tool CLI behavior. Large means user-visible changes in CLI flags,
output, diagnostics, or codegen shape. If unsure whether a change is
"large," ask.
* Ask before touching `ci/` or `Dockerfile*` unless explicitly
requested. If changes are needed there, confirm whether local
validation is expected or if CI-only coverage is acceptable.
### Bootstrap
* Bootstrap/compiler usage rules: see Top Rules and Build & Rebuild.
### Completeness and summaries
* If you cannot complete a requested step, state the blocker and partial
progress (what was attempted and what remains).
* After substantial work, provide a short summary and list touched file
paths. Substantial work means any behavioral change, or changes in
more than one file. Always include tests run (or "Not run" with
reason) in the summary.
* Never change tests just to silence failures. Update expectations only
when behavior changes are intended, and note the rationale in the
summary.
### New files and deeper guidance
* New file checklist: format with `./vnew fmt -w`, add doc comments for
any public functions, run `./vnew check-md` for markdown files, and
keep Markdown lines <= 100 chars. Add or update tests when introducing
a new public API.
* For deeper edge cases, consult `CONTRIBUTING.md` and `TESTS.md`.
## Safety (Do Not Brick the Repo)
* Do not overwrite the working `./v` binary.
* Never run `./v self` without `-o`.
* Build with `./v -o ./vnew cmd/v`, then use `./vnew` for all checks.
* Keep generated C when debugging backend issues: add `-keepc`.
* Avoid hidden/bidirectional Unicode characters in source/markdown
files.
* If the compiler becomes unusable, recover with:
1. `git stash`
2. `make`
3. `git stash apply`
Check `git status` before stashing to avoid hiding unrelated work.
Do not stash unless explicitly instructed or the compiler is bricked.
## Divergences From Repo Docs
The repo docs use `v` in examples. In this environment:
* Use `./v -g -keepc -o ./vnew cmd/v` instead of `v self`.
* Use `./vnew` for all builds, runs, and tests.
* `TESTS.md` suggests `v test-all` before PRs; ask before running
`./vnew test-all`.
These overrides exist to keep agent workflows reproducible and to avoid
breaking the bootstrap compiler.
## Quick Decisions
* For rebuild and test choices, follow Build & Rebuild and Testing.
* Follow Common Workflow for the default execution order.
* For broader workflow guidance, see `CONTRIBUTING.md`.
### Compact decision table (rebuild/tests)
Use this table to pick the minimum rebuild/tests quickly. See Build &
Rebuild and Testing for full details and edge cases.
Commands omit `./vnew` for brevity; assume the `./vnew` prefix.
This table is the minimum set; check Testing for additional triggers.
REPL and backend changes have additional triggers in Testing.
Note: `cmd/v/` is compiler scope; treat changes there as compiler
changes.
When in doubt, ask before proceeding.
If you read only one section for tests, **read Testing**.
| Change area | Rebuild? | Minimum tests to run |
| --- | --- | --- |
| Docs only (`.md`) | No | `check-md file.md` |
| Compiler (`vlib/v/`, `cmd/v/`) | Yes | `-silent vlib/v/compiler_errors_test.v`; `test vlib/v/` |
| Core modules (builtin/strings/os/strconv/time) | Yes | Smallest relevant tests |
| Parser-only (`vlib/v/parser/`) | Yes | `test vlib/v/parser/` |
| Checker-only (`vlib/v/checker/`) | Yes | `test vlib/v/checker/` |
| Comptime (`vlib/v/comptime/`) | Yes | `test vlib/v/tests/`; comptime-related tests |
| vlib (non-compiler) | No | Nearest `*_test.v` or `test vlib/path/` |
| Tools (`cmd/tools/`) | No | Tool-specific test; else nearest `*_test.v` |
| Diagnostic/output changes | Yes | `vlib/v/slow_tests/inout/compiler_test.v` |
| C codegen (`vlib/v/gen/c/`) | Yes | `vlib/v/gen/c/coutput_test.v` |
## Common Workflow
0. Before work: `git status`; ensure `./vnew` exists; rebuild if needed.
If `./vnew` is missing, see Quick Start or Build & Rebuild.
1. Edit the relevant files.
2. If compiler sources or core modules changed, rebuild `./vnew` with
`./v -g -keepc -o ./vnew cmd/v` (see Build & Rebuild).
3. Format touched `.v`/`.vsh` files and run `./vnew check-md` on
touched markdown.
4. Run the smallest relevant tests for the change scope (see Testing).
See Build & Rebuild for rebuild triggers and flags.
## Reporting
* When a summary is required (see Agent Rules), it must include:
* Behavior changes (or "No behavior change").
* Tests run (or "Not run" with a reason).
* Touched file paths.
* Note unrelated changes if present.
* Note doc updates if public behavior/tool output changed.
* If public behavior or tool output changes, update relevant docs
(README.md, `doc/`, `tutorials/`) and note it.
For example: README.md for top-level CLI usage, `doc/` for
compiler/tool docs, `tutorials/` for learning material.
* If you add or change a public API, update module docs or README and
note it. Public API includes stdlib functions/types and user-visible
compiler flags, diagnostics, tool CLI behavior (including `cmd/tools`
and stdlib CLI tools), or output formats.
* Update `CHANGELOG.md` or `ROADMAP.md` only when explicitly requested.
* Public behavior includes compiler output, diagnostics, user-facing
CLI, and stdlib API. This includes developer-facing flags, error
codes, or output ordering changes.
* Internal refactors with no public behavior change do not require doc
updates.
* If unsure whether behavior is public, ask the user before updating
docs.
* Acceptable reasons for not running tests: docs-only change, no
relevant tests, or environment constraints. Be specific.
* Docs-only changes: run `./vnew check-md file.md`; no other tests
required unless a test explicitly reads those docs.
No rebuild is needed unless compiler or core modules changed.
* For docs-only, explicitly mention `check-md` in the summary.
* If you update `.out` files, state the rationale in the summary.
* Do not update `.out` files unless a behavior change is intended;
otherwise treat mismatches as regressions.
* Example summary line: `Behavior change: none` or
`Behavior change: fixed X`.
* Behavior change includes output, API, error messages, and test
expectations.
* If blocked, note what was attempted and why it failed.
* If tooling/network restrictions block a step, state the restriction
and the closest viable alternative.
* Use `git status` to confirm touched files before reporting.
## Prerequisites
* Toolchain: `make`, `git`, and a C compiler (`clang` or `gcc`).
* Windows: use `makev.bat` for the initial build.
## Build & Rebuild
* Initial build (only if `./v` is missing): `make`
(Windows: `makev.bat`).
* Build `./vnew` (debug-friendly, recommended for agent workflows):
`./v -g -keepc -o ./vnew cmd/v`
* Never run `./v self` directly; only build `./vnew` with the commands
above.
* If `./v` is missing, run `make` first, then build `./vnew`.
* If `./vnew` is missing but `./v` exists, run `./v -o ./vnew cmd/v`.
* This section is the source of truth for rebuild triggers.
If a rule appears elsewhere, defer to this section.
* Rebuild triggers:
* Compiler sources in `vlib/v/` or `cmd/v/`.
* Core modules: `builtin`, `strings`, `os`, `strconv`, `time`.
* If `./v` exists but compiler sources changed, still rebuild `./vnew`
before tests.
* If unsure whether compiler/core changes happened, rebuild `./vnew`.
* Common flags:
* `-g` debug info (V line numbers).
* `-cg` debug info (C line numbers); often combined with `-keepc`.
* `-keepc` keep generated C file(s).
* `-prod` optimized build.
* `-o file` output path/name.
* `-cc clang` pick a C compiler.
* `-cstrict` be stricter about the generated C.
* `-b js|native|wasm` select a backend.
* `-os <os>` cross-compile target selection (when supported).
## Code Style
* Comments: add succinct comments only when code is not self-explanatory.
Do not delete existing comments unless they are incorrect; you may fix
grammar or spelling without changing meaning.
Add V doc comments right before each new or modified public function
or method.
The V doc comments should start with the name of the fn,
example: `// the_name does ...`
* Copy pasta: avoid copy pasta. If there's duplicate logic, move to a
function only when it is required for the request and within code you
are already touching.
* Avoid using `unsafe{ code }` blocks where possible, and minimize
their scope. `unsafe` is acceptable for low-level interop (e.g. C
pointer casts, manual memory management) but should never wrap
ordinary V logic. When `unsafe` is required, keep the block as small
as possible and add a comment explaining why it is necessary.
* Keep Markdown lines <= 100 chars (the checker is strict).
Apply to touched lines in modified Markdown files.
* Avoid hidden/bidirectional Unicode characters in source/markdown
files.
* Non-V files: keep existing formatting; only reformat if required by
the change.
* Treat `.vv` files in `vlib/v/slow_tests/inout/` as fixtures; avoid
formatting unless a behavior change is intended and output
expectations are updated.
* Formatting and check commands are in Tools.
## Modules and Imports
* Module names must match their directory name (no hierarchy in the
`module` line). Mismatches cause silent import failures.
* Imports follow the folder hierarchy (e.g. `import abc.def`).
## C/JS Interop Hygiene
* Avoid using `C.` or `JS.` symbols in plain `.v` files.
* Use `.c.v` / `.js.v` files.
* Enable `-Wimpure-v` to catch accidental impurity.
* Do not refactor existing `C.`/`JS.` uses in `.v` files unless
required. If you must change those lines, prefer moving the interop
code to `.c.v`/`.js.v`.
* For C interop, use correct `const_` prefixes in C function
redeclarations when needed (helps with `-cstrict` and C static
analysis tooling).
## Environment-Specific Code (files and `$if`)
V supports environment-specific file suffixes. Prefer them when the
whole file is platform/backend specific.
Common patterns:
* Backend splits:
* `*.c.v` (C backend), `*.js.v` (JS backend), `*.native.v` (native
backend), `*.wasm.v` (WASM backend)
* OS splits:
* `*_windows.c.v`, `*_linux.c.v`, `*_nix.c.v`, with `*_default.c.v`
as fallback
* Flag splits:
* `*_d_customflag.v` is included only with `-d customflag`
* `*_notd_customflag.v` is included only when that flag is NOT passed
Notes:
* Do not use combinatorial suffixes like `_d_flag_linux.c.v`; use
`_d_flag.v` plus `$if linux {}` inside the file.
* For smaller platform differences, use compile-time `$if` blocks:
* `$if windows { ... } $else { ... }`
* See Compile-Time Code and Reflection for the full `$if` reference.
## Compile-Time Code and Reflection
V uses `$` as a prefix for compile-time (comptime) operations. These
are evaluated by the compiler, not at runtime. AI agents frequently
confuse comptime and runtime constructs; this section clarifies the
boundaries.
### Compile-time `$if`
`$if` evaluates conditions at compile time. It is not a runtime `if`.
Use it for platform, compiler, and custom-flag checks:
* `$if windows { ... } $else $if linux { ... } $else { ... }`
* `$if debug { ... }` (enabled by `-g` or `-cg`)
* `$if prod { ... }` (enabled by `-prod`)
* `$if custom_flag ? { ... }` (enabled by `-d custom_flag`)
Full list of builtin `$if` options: see the table at
<https://docs.vlang.io/conditional-compilation.html>.
Common mistakes:
* Using runtime `if` where `$if` is needed for platform-specific code.
Runtime `if` will fail to compile if it references platform-specific
symbols; `$if` excludes the block entirely on non-matching platforms.
* Forgetting the `?` suffix for custom flags: `$if myflag ? { ... }`.
Without `?`, the compiler treats it as a builtin option and silently
ignores it.
### Compile-time `$for`
`$for` iterates over type metadata at compile time. It works with:
* `StructType.fields` - iterate struct fields
* `StructType.methods` - iterate struct methods
* `EnumType.values` - iterate enum values
* `StructType.attributes` - iterate struct attributes
* `SumType.variants` - iterate sum type variants
* `method.params` - iterate method parameters
Inside `$for` blocks, use `$if` to branch on field/method types:
```v oksyntax
fn main() {
$for field in MyStruct.fields {
$if field.typ is string {
println(field.name)
}
}
}
```
Also works with generics: `T.fields`, `param.fields` where
`fn gen[T](param T) {}`.
Common mistakes:
* Using runtime `for` to iterate struct fields. This does not work;
V has no runtime reflection. Always use `$for`.
* Calling `obj.$method()` outside a `$for m in Type.methods` block.
The `$method()` call is only valid inside a comptime method
iteration.
* Assuming comptime `$for` produces a runtime loop. It does not; the
compiler unrolls it into concrete code for each field/method/variant.
### Compile-time functions
Only the following `$`-prefixed functions are supported:
* `$embed_file('path')` - embed a file's contents into the binary.
Paths can be absolute, relative to the source file, or use pseudo
variables like `@VEXEROOT` or `@VMODROOT`.
* `$tmpl('path')` - compile a V template file (used by veb).
* `$env('VAR')` - read an environment variable at compile time.
* `$d('ident', default)` - read a `-d ident=value` compile-time
define, with a default fallback.
* `$res('path')` - embed a resource (Android).
* `$compile_error('msg')` - emit a compile-time error.
* `$compile_warn('msg')` - emit a compile-time warning.
* `$pkgconfig('name')` - query pkg-config at compile time.
Common mistakes:
* Inventing comptime functions that do not exist (e.g. `$typeof`,
`$sizeof` as comptime calls). Use `typeof(expr).name` and
`sizeof(Type)` instead; these are builtins, not `$`-prefixed.
* Assuming `$embed_file` returns a string. It returns an
`EmbedFileData` object; use `.to_string()` or `.to_bytes()`.
* Using `$env` where a runtime `os.getenv` is appropriate, or vice
versa. `$env` is baked in at compile time and cannot change at
runtime.
### Compile-time pseudo variables
These are `@`-prefixed identifiers substituted at compile time:
* `@FN` - current function name.
* `@METHOD` - `ReceiverType.MethodName`.
* `@MOD` - current module name.
* `@STRUCT` - current struct name.
* `@FILE`, `@DIR`, `@LINE`, `@COLUMN`, `@FILE_LINE` - source
location.
* `@LOCATION` - file, line, and current type+method; good for logging.
* `@VEXE`, `@VEXEROOT` - path to the V compiler and its directory.
* `@VHASH`, `@VCURRENTHASH` - compiler commit hashes.
* `@VMOD_FILE`, `@VMODHASH`, `@VMODROOT` - nearest `v.mod` info.
* `@BUILD_DATE`, `@BUILD_TIME`, `@BUILD_TIMESTAMP` - build time (UTC).
Override with the `SOURCE_DATE_EPOCH` env var for reproducible
builds.
* `@OS`, `@CCOMPILER`, `@BACKEND`, `@PLATFORM` - build environment.
### Compile-time type groups
Comptime type groups combine multiple types into a higher-level type
for use in generic or comptime `$if` checks:
* `$int` - all integer types
* `$float` - all float types
* `$array` - all array types
* `$map` - all map types
* `$struct` - all struct types
* `$enum` - all enum types
* `$alias` - all type aliases
* `$sumtype` - all sum types
* `$function` - all function types
* `$interface` - all interface types
* `$option` - all option types
Example: `$if field.typ is $int { ... }`
### Comptime changes and testing
Comptime logic lives in `vlib/v/comptime/` and is exercised by the
checker, parser, and cgen stages. Changes here require a rebuild of
`./vnew` and should be tested with `./vnew -silent test vlib/v/tests/` plus
any comptime-specific tests. See the decision table and Testing.
## Run Programs
* Compile and run: `./vnew run file.v`.
* Just compile: `./vnew file.v` (creates executable).
* With debug info: `./vnew -g run file.v`.
* Debug run (C line numbers): `./vnew -keepc -cg run file.v`.
* Example: `./vnew run examples/hello_world.v`.
## Testing
Run:
* File (shows test output): `./vnew path/to/file_test.v`.
* File (test runner report only): `./vnew test path/to/file_test.v`.
* Dir: `./vnew -silent test path/to/dir/`.
* Dir with statistics/metrics: `./vnew -stats test path/to/dir/`.
* Compiler: `./vnew -silent vlib/v/compiler_errors_test.v`.
* Fix outputs (only when intended):
`VAUTOFIX=1 ./vnew -silent vlib/v/compiler_errors_test.v`.
* All: `./vnew test-all`.
Ask before running `./vnew test-all` unless explicitly requested.
When:
* Rule of thumb: for localized changes, run the smallest relevant
tests. If any trigger below matches, run the listed tests.
* Minimum tests listed are the floor, not the ceiling; add targeted
tests for cross-cutting changes.
* If unsure which tests apply, ask the user before proceeding.
* If in doubt, prefer the smallest targeted test and ask.
* Run all tests that apply. Start with the smallest targeted tests;
add slow tests as needed. Order does not matter.
* Compiler changes (`vlib/v/` or `cmd/v/`):
Run `./vnew -silent vlib/v/compiler_errors_test.v`,
`./vnew -silent test vlib/v/`.
* Parser-only changes (`vlib/v/parser/`):
Run `./vnew -silent test vlib/v/parser/`.
* Checker-only changes (`vlib/v/checker`):
Run `./vnew -silent test vlib/v/checker/`.
* vlib changes: Run nearest `*_test.v` or
`./vnew -silent test vlib/path/`.
* Tool changes (`cmd/tools/`): Run tool-specific tests. If none exist,
run the smallest relevant `*_test.v` that exercises the tool.
Note: `cmd/v/` is compiler scope, not tools.
Examples: `cmd/tools/vfmt` -> `vlib/v/fmt/fmt_test.v` .
`cmd/tools/vdoc` -> `cmd/tools/vdoc/vdoc_test.v`.
* Diagnostic/output changes:
Run `./vnew -silent vlib/v/slow_tests/inout/compiler_test.v`.
* C codegen changes: Run `./vnew -silent vlib/v/gen/c/coutput_test.v`.
Consider a stricter validation pass:
`./vnew -cstrict -cc clang -silent test vlib/v/`.
* REPL changes: Run `./vnew -silent vlib/v/slow_tests/repl/repl_test.v`.
* Broad refactors: Run `./vnew -silent test-all`.
* Backend-specific changes: run the smallest relevant tests for the
affected backend. JS/native/WASM backends are incomplete, so avoid
broad `-b <backend> test vlib/` runs. Prefer targeted `*_test.v`
files or small test dirs with `-b js|native|wasm`.
If time-constrained, prioritize
`./vnew -silent vlib/v/compiler_errors_test.v` and the smallest targeted tests.
Run `vlib/v/slow_tests/inout/compiler_test.v`
and `vlib/v/gen/c/coutput_test.v` when output or codegen changes are
likely.
See `TESTS.md` for more guidance on test selection and output
expectations.
See `CONTRIBUTING.md` for broader workflow guidance.
Concrete triggers:
* `vlib/v/slow_tests/inout/compiler_test.v` when error text or output
formatting changes, or changes in checker/parser error reporting.
* `vlib/v/gen/c/coutput_test.v` for changes under `vlib/v/gen/c/` or
C codegen output paths.
Types:
* Standard: `*_test.v` files with `test_` functions.
* Output: `.vv` source + `.out` expected output in
`vlib/v/slow_tests/inout/`.
Example: `./vnew -silent vlib/v/slow_tests/inout/compiler_test.v`.
* `vlib/v/tests/**` may use `.run.out` expectations; run with
`./vnew -silent test vlib/v/tests`.
Docs-only guidance: see Reporting.
If time-boxed, run at least the smallest relevant test and note
skipped coverage in the summary.
### Useful env variables and flags while testing
* `VAUTOFIX=1` - Auto-update .out files when tests fail (run twice).
Use only when a behavior change is intended.
* `VTEST_ONLY=glob_pattern` - Run only tests matching pattern.
* `VTEST_HIDE_OK=1` - Hide successful tests, show only failures.
* `./vnew -silent test path/to/dir/` - Show only failed tests (if any), and a summary report.
* `-cc tcc` can speed test builds when TCC is available.
* Output expectations: update `.out` files only when behavior changes
are intended; note the rationale in the summary.
## Debug
* See what the C compiler is doing:
* `-showcc` prints the C compile command.
* `-show-c-output` prints the C compiler output.
* Build a temporary compiler for debug flags:
* `./vnew -o ./w -d trace_checker cmd/v`
* Then run: `./w file.v`
* Keep and inspect generated C:
* `-keepc -cg` is the common combo.
* `-printfn <name> -o file.c` emits only the named C function to standart
output. The `name` uses the `modulename__fnname` format (e.g.
`main__main`). This flag can be repeated to print multiple
functions. Methods/generics may use more complex C names; use
`-keepc` to confirm exact symbols.
* Trace stages:
`-d trace_scanner|trace_parser|trace_checker|trace_gen`.
These flags can help diagnose a problem when a stage stops earlier
than expected.
* Time stages: `-d time_parsing|time_checking`.
* V panics: `-keepc -g`.
* C segfaults: `-keepc -cg -cc clang`.
* JS/native/wasm: prefer small, focused test files with
`-b js|native|wasm` and `-show-c-output` where applicable; avoid
broad `-b <backend> test vlib/`.
* Quick code location technique:
When debugging code generation issues, add unique comment tags to
relevant code generation points (e.g., `/*tom51*/`) in the compiler
source. Rebuild and generate C code, then search the generated file for these
tags to quickly map generated C code back to the exact compiler source
location. This is especially useful when multiple code paths generate
similar-looking output and you need to identify which path is actually used.
Example:
```v
// In vlib/v/gen/c/assign.v:
g.write('builtin___option_ok/*tom51*/(&(${styp}[]) { ')
// After rebuild, search generated C code for "tom51":
// builtin___option_ok/*tom51*/(&(int[]) { ... });
```
Remember to remove these debug tags after fixing the issue.
## Compiler Architecture
The V compiler has the following stages, orchestrated by the
`v.builder` module:
`v.scanner` -> `v.parser` -> `v.checker` -> `v.transformer` ->
`v.markused` -> `v.gen.c`
Their corresponding folders are: vlib/v/scanner, vlib/v/parser,
vlib/v/checker, vlib/v/transformer, vlib/v/markused, vlib/v/gen/c .
There are additional subsystems (supporting or optional compiler
modules) like v.comptime, v.generics, v.pref, v.reflection,
v.callgraph, etc.
### Key Directories
* `vlib/`: Standard library (changes here can affect the compiler
itself).
* `cmd/v/v.v`: Compiler entry.
* `cmd/tools/`: vfmt, vdoc, vup, vquest, etc.
* `examples/`: Example programs.
* `thirdparty/`: Bundled C libraries (tcc, mbedtls, sokol, etc.).
* `vlib/v/`: Compiler modules.
* ast/ - AST node definitions
* fmt/ - Code formatter
* scanner/ - Tokenizer
* token/ - Token definitions
* parser/ - Produces AST from tokens
* checker/ - Type checking and resolution
* comptime/ - Compile-time evaluation support
* transformer/ - Common optimisations and simplifications, makes the
backends simpler
* markused/ - Dead code eliminator
* gen/c/ - C code generation (primary backend, known as cgen)
* gen/js/ - JavaScript backend
* gen/native/ - Machine code generation (ELF, Mach-O)
* gen/wasm/ - WebAssembly backend
### Test Locations
* `vlib/v/tests/`: Compiler feature tests (including comptime).
* `vlib/v/slow_tests/`: Output-matching and slow tests for the
compiler.
* `vlib/v/slow_tests/inout/` - Output comparison tests
(.vv + .out pairs)
* `vlib/v/parser/` - Parser error tests
* `vlib/v/checker/` - Checker error tests
* `vlib/v/gen/c/testdata/` - C codegen tests (.vv + .c.must_have)
* `examples/compiletime/` - Comptime usage examples (including
`reflection.v`)
## Error Reporting (checker/parser)
* Error: `c.error('message', pos)` - hard error, stops compilation.
* Warning: `c.warn('message', pos)` - warning, allows compilation.
* Notice: `c.note('message', pos)` - informational only.
* Pattern: Most checker methods use `fn (mut c Checker)` receiver.
* Location: `vlib/v/checker/errors.v`.
## Option/Result Types
* Syntax: `?Type` (optional, can be none) vs `!Type` (result, can
error).
* Common bugs: Unwrapping in if guards, struct init with option fields,
ternaries with options.
* When changing option/result behavior, add a regression test in
`vlib/v/tests/`.
* Tests: Search `vlib/v/tests/` for option/result test files.
* Pitfall: Options in ternaries, SQL statements, and fixed arrays need
special handling in cgen.
## Tools
* Note: if a rule overlaps with Testing, follow Testing.
* Format: `./vnew fmt -w <file>` for touched `.v` and `.vsh` files.
Format only touched files unless explicitly asked to reformat broader
scope.
* Treat new files as touched for formatting and markdown checks.
* Check *all* files are formatted: `./vnew -silent test-fmt`.
Run only when asked or when validating the full tree.
* Check markdown: `./vnew check-md file.md` for touched `.md` files
(required before commits).
* Code style checker: `./vnew vet vlib/v`
Run only when asked or when making broad checker changes (more than
3 files in `vlib/v/checker/`).
* Module docs: `./vnew doc -readme -all -l module_name`.
* Search: `rg pattern` (or `git grep`); list files: `rg --files`.
* Auto-format hook: `./vnew git-fmt-hook install`.
## Commits and PRs
* See `CONTRIBUTING.md` for full commit message conventions and PR
workflow.
* Keep commits focused: one logical change per commit.
* If your branch has diverged and a rebase or merge is needed, do not
force-push or drop hunks without asking. State the conflict and let
the user decide the resolution strategy. When in doubt, prefer
`git rebase` over `git merge` for a linear history, but always ask
if the situation is ambiguous.
## Environment Variables
* VFLAGS: Pass flags to all V invocations
(e.g., `VFLAGS='-g' ./vnew test-all`).
* VEXE: Path to V compiler executable (useful in CI/scripts).
* TMPDIR: Controls where `.tmp.c` files are written (V uses
`TMPDIR/v/`).
* SOURCE_DATE_EPOCH: Override build timestamp for reproducible builds
(affects `@BUILD_DATE`, `@BUILD_TIME`, `@BUILD_TIMESTAMP`).
* V2-specific: `V2CC`, `V2CFLAGS`, `V2VERBOSE` (for v2 development).
## Gotchas
* Core modules (`builtin`, `strings`, `os`, `strconv`, `time`) can
affect the compiler because it is a V program. Rebuild `./vnew` when
they change.
* Module names must match their directory name; mismatches cause silent
import failures. See Modules and Imports.
* Some V programs and tools hardcode `os.execute('v ...')` in their
source. The `./vnew` workflow does not protect against these; if you
encounter unexpected behavior from such calls, check whether the
code is invoking the system `v` instead of `./vnew` and adjust
accordingly.
* Stale `./vnew` can cause confusing failures; rebuild if behavior
seems off.
* Output tests require exact matches; whitespace changes break tests.
* Formatting reminders: follow Code Style for `fmt` and `check-md`.
* C compilation errors? Check generated C with `-keepc`
(creates `/tmp/*.tmp.c`; see also TMPDIR in Environment Variables).
* Compile-time code (`$if`, `$for`, `$embed_file`, etc.) is a common
source of AI mistakes. See Compile-Time Code and Reflection for
correct usage and pitfalls.
* Broken compiler? See Safety for the recovery sequence.
* Consult `CONTRIBUTING.md` and `TESTS.md` for:
* New tests or test infra changes.
* Output tests or `.out` updates.
* Broad refactors or compiler-wide changes.
* Unsure which slow test runner applies to your change.
+6071
View File
File diff suppressed because it is too large. Load diff
+4
View File
@@ -0,0 +1,4 @@
# Code of Conduct
Be nice and respectful.
+355
View File
@@ -0,0 +1,355 @@
## How to help and contribute to the V project
The tasks in the lists below are ordered in terms of easiness/time/nerves
investment.
### Starting tasks
0. Run `v quest` once (or several times a day) to gain XP.
1. Read the [language documentation](https://docs.vlang.io/introduction.html) and [standard module documentation](https://modules.vlang.io/).
2. Fix doc errors and places you found unclear, and make [PRs](https://github.com/vlang/v/pulls) about it.
3. Make V programs, in the areas that you are interested in, or help others make
V programs. If the programs/libraries are public, post them to the channel
`#showcase-discussion` on [Discord](https://discord.gg/vlang) and/or to
[awesome-v](https://github.com/vlang/awesome-v). You can also answer other
people's questions in Discord channels `#help` or `#v-chat`, or in
[github's discussions page](https://github.com/vlang/v/discussions).
4. Read the new issues in the tracker.
5. Try to reproduce them on your system, and comment in the issues, with the
results.
6. Read the PRs, try to spot errors in them, and comment about them.
### Medium tasks (after gathering experience with 1..6)
7. Make PRs, with bug fixes to existing issues (found doing 1..6).
8. Suggest new features, tools, or modifications to the existing ones here,
based on the experience, that you gathered doing 1..7.
9. Make PRs with implementations of your suggestions, or based on other people's
suggestions, based on 1..7 and the feedback from 8.
### Advanced tasks (after doing 1..9 for a while)
10. Work on [V RFCs](https://github.com/vlang/rfcs/) (submitting new ones,
providing feedback to existing ones, implementing them).
## Code Structure
I tried to make the code of the compiler and vlib as simple and readable as
possible. One of V's goals is to be open to developers with different levels
of experience in compiler development. Compilers don't need to be black boxes
full of magic that only few people understand.
The V compiler is modular, and can be used by other applications. It is located
in `cmd/v/` and `vlib/v/`.
The most important and useful command to remember when working on the V compiler
is `v self`.
It rebuilds the V compiler.
Be careful, if you introduce a breaking change and rebuild V, you will no longer
be able to use V to build itself. So it's a good idea to make a backup copy of a
working compiler executable.
But don't worry, you can always simply run `make` (or `makev.bat`), it will
download the C version of the compiler and rebuild it from scratch.
The architecture of the compiler is very simple and has three distinct steps:
Parse/generate AST (`v.parser`) => Check types (`v.checker`)
=> Generate C/JavaScript/machine code (`v.gen`)
The main files are:
1. `cmd/v/v.v` The entry point.
- V figures out the build mode.
- Constructs the compiler object (`struct V`).
- Creates a list of .v files that need to be parsed.
- Creates a parser object for each file and runs `parse()` on them.
- The correct backend is called (C, JS, native), and a binary is compiled.
2. `vlib/v/scanner` The scanner's job is to parse a list of characters and convert
them to tokens.
3. `vlib/v/token` This is simply a list of all tokens, their string values, and a
couple of helper functions.
4. `vlib/v/parser` The parser. It converts a list of tokens into an AST.
In V, objects can be used before declaration, so unknown types are marked as
unresolved. They are resolved later in the type checker.
5. `vlib/v/table` V creates one table object that is shared by all parsers. It
contains all types, consts, and functions, as well as several helpers to search
for objects by name, register new objects, modify types' fields, etc.
6. `vlib/v/checker` Type checker and resolver. It processes the AST and makes sure
the types are correct. Unresolved types are resolved, type information is added
to the AST.
7. `vlib/v/gen/c` C backend. It simply walks the AST and generates C code that can be
compiled with Clang, GCC, Visual Studio, and TCC.
8. `vlib/v/gen/js` JavaScript backend. It simply walks the AST and generates JS code that can be
executed on the browser or in NodeJS/Deno.
9. `vlib/v/gen/c/json.v` defines the json code generation. This file will be removed once V
supports comptime code generation, and it will be possible to do this using the
language's tools.
10. `vlib/v/gen/native` is the directory with all the machine code generation logic. It
defines a set of functions that translate assembly instructions to machine code
and build the binary from scratch byte by byte. It manually builds all headers,
segments, sections, symtable, relocations, etc. Right now it only has basic
support of the native platform (ELF, MACHO format).
The rest of the directories are vlib modules: `builtin/` (strings, arrays,
maps), `time/`, `os/`, etc. Their documentation is pretty clear.
## Example Workflow for Contributing
(provided by [@spytheman](https://github.com/spytheman))
(If you don't already have a GitHub account, please create one. Your GitHub
username will be referred to later as 'YOUR_GITHUB_USERNAME'. Change it
accordingly in the steps below.)
1. Fork https://github.com/vlang/v using GitHub's interface to your own account.
Let's say that the forked repository is at
`https://github.com/YOUR_GITHUB_USERNAME/v` .
2. Clone the main v repository https://github.com/vlang/v to a local folder on
your computer, say named nv/ (`git clone --depth=1 https://github.com/vlang/v nv`)
3. `cd nv`
3.1 (optional) Run these commands, which ensure that all your code will be
automatically formatted, before committing:
```
cp cmd/tools/git_pre_commit_hook.vsh .git/hooks/pre-commit
chmod 755 .git/hooks/pre-commit
```
It has to be done in a shell where you have done cd /root/of/your/V_repo once.
Step 3 above does it with `cd nv`.
I.e. you have to be in the top level folder, that contains the .git folder for the V repository.
4. `git remote add pullrequest https://github.com/YOUR_GITHUB_USERNAME/v`
Note: The remote named `pullrequest` should point to YOUR own forked repo, not the
main v repository! After this, your local cloned repository is prepared for
making pull requests, and you can just do normal git operations such as:
`git pull` `git status` and so on.
5. When finished with a feature/bugfix/change, you can:
`git checkout -b fix_alabala`
- Don't forget to keep formatting standards, run `v fmt -w YOUR_MODIFIED_FILES`
before committing (if you have not run the commands from 3.1)
- If you changed Markdown (`.md`) files, check them `v check-md YOUR_MODIFIED_FILES`
before committing.
6. `git push pullrequest` Note: The `pullrequest` remote was setup on step 4
7. On GitHub's web interface, go to: https://github.com/vlang/v/pulls
Here the UI shows a dialog with a button to make a new pull request based on
the new pushed branch.
(Example dialog: https://url4e.com/gyazo/images/364edc04.png)
8. After making your pull request (aka, PR), you can continue to work on the
branch `fix_alabala` ... just do again `git push pullrequest` when you have more
commits.
9. If there are merge conflicts, or a branch lags too much behind V's master,
you can do the following:
1. `git pull --rebase origin master` # solve conflicts and do
`git rebase --continue`
2. `git push pullrequest -f` # this will overwrite your current remote branch
with the updated version of your changes.
The point of doing the above steps, is to never directly push to the main V
repository, *only to your own fork*. Since your local `master` branch tracks the
main V repository's master, then `git checkout master`, as well as
`git pull --rebase origin master` will continue to work as expected
(these are actually used by `v up`) and git can always do it cleanly.
Git is very flexible, so there are other ways to accomplish the same thing.
See the [GitHub flow](https://guides.github.com/introduction/git-handbook/#github), for more
information.
## Finding issues to contribute to
If you're willing to contribute to V but don't know which issue to resolve
- you can go to [Issues](https://github.com/vlang/v/issues) tab
in this repository. There you can see things logged by both users and developers
that need to be discussed and/or resolved.
It's recommended to filter issues by likes and labels to find an issue
you are interested in.
### Filtering by likes (recommended)
Filtering by likes helps you identify high-impact issues.
More likes mean more community interest.
To quickly use this filter, click [there](https://github.com/vlang/v/issues?q=is%3Aopen+is%3Aissue+sort%3Areactions-%2B1-desc).
To manually apply this filter, navigate to [Issues](https://github.com/vlang/v/issues)
tab, then paste the following in the "Filter" field:
```
is:open is:issue sort:reactions-+1-desc
```
This filter will return all open issues sorted by likes in descending order.
### Filtering by labels
The V repo has various labels to help navigate the extensive list of issues
and help you find issues you're both interested in and capable of resolving.
You can examine the list of labels [here](https://github.com/vlang/v/labels).
The most common labels are:
By issue type:
- `Bug`
- `Feature Request`
By OS:
- `OS: Linux`
- `OS: Windows`
- `OS: Mac`
By status:
- `Status: Confirmed`
To apply this filter, navigate to [Issues](https://github.com/vlang/v/issues)
tab, then paste the following in the "Filter" field:
```
is:open is:issue label:Bug label:"OS: Windows" label:"Status: Confirmed"
```
This filter will return all open issues with the labels `Bug`, `OS: Windows`,
and `Status: Confirmed`.
## Using Github's hub CLI tool
You can download the `hub` tool from https://hub.github.com/ . Using
`hub`, you will not need to go through the (sometimes) slow website
to make PRs. Most remote operations can be done through the `hub` CLI
command.
> [!NOTE]
> You still need to have a GitHub account.
### Preparation:
(steps 1..3 need to be done just *once*):
1. `hub clone vlang/v my_v`
2. `cd my_v`
2.1 (optional) Run these commands, which ensure that all your code will be
automatically formatted, before committing:
```
cp cmd/tools/git_pre_commit_hook.vsh .git/hooks/pre-commit
chmod 755 .git/hooks/pre-commit
```
3. `hub fork --remote-name pullrequest`
4. `git checkout -b my_cool_feature` # Step 4 is better done *once per each new
feature/bugfix* that you make.
### Improve V by making commits:
5. `git commit -am "math: add a new function copysign"`
### Testing your commits locally:
You can test locally whether your changes have not broken something by
running: `v test-all`. See `TESTS.md` for more details.
### Publishing your commits to GitHub:
6. `git push pullrequest`
### Making a PR with `hub`:
(so that your changes can be merged to the main V repository)
7. `hub pull-request`
Optionally, you can track the status of your PR CI tests with:
8. `hub ci-status --verbose`
### Fixing failing tests:
If everything is OK, after 5-10 minutes, the CI tests should pass for
all platforms. If not, visit the URLs for the failing CI jobs, see
which tests have failed and then fix them by making more changes. Just use
`git push pullrequest` to publish your changes. The CI tests will
run with your updated code. Use `hub ci-status --verbose` to monitor
their status.
## Compiler flags, useful while debugging the compiler itself:
V allows you to pass custom flags using `-d my_flag` that can then be checked
at compile time (see the documentation about
[compile-time if](https://github.com/vlang/v/blob/master/doc/docs.md#compile-time-if)).
Since the compiler is *also* an ordinary V program, there are numerous flags that can be
passed when building the compiler itself with `v self`, or when creating a copy of the
compiler, that will help you when debugging the compiler.
Note: beware that the flags below must be passed, when building the compiler, *not the program*,
so do for example:
`./v -o w -d time_parsing cmd/v`
or
`./v -o w -d trace_checker self`
... then use `./w file.v`, instead of `./v file.v`, to compile your program.
Note: some of the flags can make the compiler *very verbose*, so it is recommended to create
a copy of the compiler rather than replacing it with `v self`.
| Flag | Usage |
|-----------------------------------|---------------------------------------------------------------------------------------------------------------------|
| `debug_codegen` | Prints automatically generated V code during the scanning phase |
| `debug_interface_table` | Prints generated interfaces during C generation |
| `debug_interface_type_implements` | Prints debug information when checking that a type implements in interface |
| `print_veb_template_expansions` | Prints veb compiled HTML files |
| `time_checking` | Prints the time spent checking files and other related information |
| `time_parsing` | Prints the time spent parsing files and other related information |
| | |
| `trace_scanner` | Prints details about the recognized tokens. *Very* verbose. Use with `./vnew -no-builtin -check-syntax file.v` . |
| `trace_parse` | Prints details about the parsed files (number of tokens, lines, bytes). Use it for parsing order issues. |
| `trace_parser` | Prints details about parsed statements and expressions. Very verbose. Use it for panics in the parser. |
| `trace_check` | Prints the .v file which is checked. Use it to diagnose checker order issues. |
| `trace_checker` | Prints details about the statements being checked. Very verbose. Use it for panics in the checker. |
| `trace_transformer` | Prints details about the statements being transformed. Very verbose. Use it for panics in the transformer stage. |
| | |
| `trace_gen` | Prints all the strings written to the generated C file. Very verbose. |
| `trace_gen_wanted_value` | Prints a backtrace, when a specific *wanted* value, is part of what is printed in the generated C file. |
| | Use: `v -g -o vgen -d trace_gen_wanted -d trace_gen_wanted_value="message = _SLIT0" cmd/v && ./vgen bug.v` |
| `trace_cgen` | Prints the .v file for which C code generation runs. Use it to diagnose cgen order issues. |
| `trace_cgen_stmt` | Prints details about the statements that are being processed by cgen. |
| | Use it for panics in cgen, to see the closest input V source line, that caused the panic. |
| | Note: you need `v -no-parallel -d trace_cgen_stmt -o w cmd/v` to make sense of the output of that, |
| | otherwise by default cgen uses several threads, and the lines that are printed are out of order. |
| | |
| `trace_autofree` | Prints details about how/when -autofree puts free() calls |
| `trace_autostr` | Prints details about `.str()` method auto-generated by the compiler during C generation |
| | |
| `trace_ccoptions` | Prints options passed down to the C compiler |
| | |
| `trace_thirdparty_obj_files` | Prints details about built thirdparty obj files |
| `trace_usecache` | Prints details when -usecache is used |
| `trace_embed_file` | Prints details when $embed_file is used |
| `embed_only_metadata` | Embed only the metadata for the file(s) with `$embed_file('somefile')`; faster; for development, *not* distribution |
|-----------------------------------|---------------------------------------------------------------------------------------------------------------------|
+27
View File
@@ -0,0 +1,27 @@
#same container that golang use
FROM buildpack-deps:buster-curl
LABEL maintainer="ANAGO Ronnel <anagoandy@gmail.com>"
WORKDIR /opt/vlang
ARG USE_LOCAL
RUN apt update && \
DEBIAN_FRONTEND=noninteractive apt install -y --no-install-recommends gcc clang make git binutils && \
apt clean && rm -rf /var/cache/apt/archives/* && \
rm -rf /var/lib/apt/lists/*
COPY . /vlang-local
RUN if [ -z "${USE_LOCAL}" ] ; then \
git clone --depth=1 https://github.com/vlang/v /opt/vlang && \
rm -rf /vlang-local ; \
else \
mv /vlang-local/* . && \
rm -rf /vlang-local ; \
fi
RUN make && \
ln -s /opt/vlang/v /usr/local/bin/v
CMD [ "v" ]
+62
View File
@@ -0,0 +1,62 @@
## Usage:
## 1) docker build -t vlang_alpine - < Dockerfile.alpine
## 2) alias with_alpine='docker run -u 1000:1000 --rm -it -v .:/src -w /src vlang_alpine:latest'
FROM alpine:3.23.3
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 \
openssl-dev sqlite-dev mbedtls \
libuv-dev libev-dev libevent-dev libmemcached-dev \
binutils diffutils elfutils pcre strace rsync \
libunwind-dev libunwind-static gc gc-dev \
make bash file git upx tmux micro nano nano-syntax \
gcc gdb wasi-sdk \
mesa-dev mesa-gl mesa-gles \
glfw-dev \
glu-dev \
glew-dev \
freetype-dev \
freeglut-dev \
libxi-dev libxi-static \
libxcursor-dev \
libx11-dev \
icu-data-full \
sdl2_net-dev \
sdl2_gfx-dev \
sdl2_ttf-dev \
sdl2_image-dev \
sdl2_mixer-dev \
sdl2_pango-dev \
sdl2-dev
RUN ln -s /opt/vlang/v /usr/local/bin/v
COPY . /vlang-local
ARG USE_LOCAL
RUN if [[ -z "${USE_LOCAL}" ]] ; then \
git clone --depth=1 --quiet https://github.com/vlang/v/ /opt/vlang && \
rm -rf /vlang-local ; \
else \
mv /vlang-local/* . && \
rm -rf /vlang-local ; \
fi
RUN mkdir -p /tmp/v /tmp/v /home/ && chown -Rh 1000:1000 /opt/ /tmp/ /home/
## setup runtime environment for v and bash:
USER 1000:1000
ENV HOME=/home
ENV VTMP=/tmp/v
ENV VMODULES=/tmp/vmodules
RUN make && v -version && ls -la v && \
du -b -s . && \
time v doctor && \
time v cmd/tools/vfmt.v && \
time v -prod self && \
true
RUN find . -type f -name *_test.v -or -name *.vv -or -name *.out | xargs rm && \
rm -rf v_old vc/ .git/ && \
du -b -s .
CMD ["v"]
+10
View File
@@ -0,0 +1,10 @@
FROM mstorsjo/llvm-mingw
LABEL maintainer="Delyan Angelov <delian66@gmail.com>"
COPY . .
RUN make
RUN ./v -os windows -o v.c cmd/v
RUN x86_64-w64-mingw32-gcc v.c -std=c99 -w -municode -o v.exe -lws2_32
RUN file v.exe
CMD [ "bash" ]
Loaded 100 of 11957 files, more files were not shown because too many files have changed in this diff. Show more