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

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 57 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,28 @@ jobs:
- name: Run Tests
run: ./scripts/run_tests.sh

build-linux-ubsan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Install
run: sudo apt-get update && sudo apt-get install -y clang
- name: Build tests
run: CXX=clang++ STDVERSION=c++17 ARCH=-m64 USE_UBSAN=1 ./scripts/compile.sh
- name: Run Tests
run: ./scripts/run_tests.sh

build-linux-msan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Install
run: sudo apt-get update && sudo apt-get install -y clang
- name: Build tests
run: CXX=clang++ STDVERSION=c++17 ARCH=-m64 USE_MSAN=1 ./scripts/compile.sh
- name: Run Tests
run: ./scripts/run_tests.sh

build-macos:
strategy:
matrix:
Expand All @@ -33,6 +55,26 @@ jobs:
- name: Run Tests
run: ./scripts/run_tests.sh

build-linux-staticanalyze:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Install
run: sudo apt-get update && sudo apt-get install -y clang
- name: Build tests
run: CXX=clang++ STDVERSION=c++17 ARCH=-m64 USE_STATICANALYZE=1 ./scripts/compile.sh
- name: Run Tests
run: ./scripts/run_tests.sh

build-macos-staticanalyze:
runs-on: macos-latest
steps:
- uses: actions/checkout@v2
- name: Build tests
run: CXX=clang++ STDVERSION=c++17 ARCH=-m64 USE_STATICANALYZE=1 ./scripts/compile.sh
- name: Run Tests
run: ./scripts/run_tests.sh

build-windows:
strategy:
matrix:
Expand All @@ -47,3 +89,18 @@ jobs:
run: ./scripts/compile_cl.bat
- name: Run Tests
run: ./scripts/run_tests.bat

build-windows-staticanalyze:
runs-on: windows-latest
if: ${{ false }}
steps:
- uses: actions/checkout@v2
- uses: ilammy/msvc-dev-cmd@v1
with:
arch: amd64
- name: Build tests
env:
USE_STATICANALYZE: 1
run: ./scripts/compile_cl.bat
- name: Run Tests
run: ./scripts/run_tests.bat
32 changes: 32 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# AGENTS.md

These instructions apply to the entire repository.

## Language and Design

* Prefer C-like C++ ("Orthodox C++"): simple types, explicit ownership, RAII, and clear invariants.
* Target C++98 when possible.
* Do not introduce C++11+ features unless there is a clear need. If newer features are required, guard them and keep a C++98-compatible path when practical.
* Keep dependencies minimal and avoid template-heavy or meta-programming-heavy solutions.
* Do not rely on exceptions (the project builds with `-fno-exceptions`).

## Style

* Follow the existing style in nearby files. Do not reformat unrelated code.
* Use 4 spaces for indentation and keep whitespace changes minimal.
* Keep include order consistent with existing files: system headers first, then local headers.
* Prefer project-established forms such as `#if defined(...)` preprocessor guards and uppercase macro names.
* Use simple, readable control flow; avoid clever constructs.

## Compatibility Guidelines

* Prefer C/C++98-friendly headers and APIs already used in this repo (`<stdio.h>`, `<string.h>`, etc.) unless there is a reason to use something else.
* Avoid unguarded use of features like `nullptr`, `auto`, lambdas, `override`, variadic templates, and `static_assert`.
* Keep code warning-clean under the current compile flags.

## Validation

* Build with C++98 first when touching C++ code:
* `STDVERSION=c++98 scripts/compile.sh`
* Run tests after changes:
* `scripts/run_tests.sh`
74 changes: 66 additions & 8 deletions scripts/compile.sh
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,47 @@ fi
#DISASSEMBLY="-S -masm=intel"
#PREPROCESS="-E"

if [ "$CXX" == "" ]; then
CXX=clang++
fi

if [ "$USE_STATICANALYZE" != "" ]; then
if [ "$CXX" == "clang++" ]; then
STATIC_ANALYZER_CLANG=1
STATIC_ANALYZER_FLAGS="-Xanalyzer -analyzer-output=text -Xanalyzer -analyzer-werror -Xanalyzer -analyzer-disable-checker -Xanalyzer deadcode.DeadStores"
echo "Using STATIC ANALYZER (clang)"
else
echo "USE_STATICANALYZE requires clang++ in scripts/compile.sh"
exit 1
fi
fi

if [ "$USE_ASAN" != "" ]; then
if [ "$CXX" != "g++" ]; then
ASAN="-fsanitize=address -fno-omit-frame-pointer -fsanitize-address-use-after-scope -fsanitize=undefined"
ASAN_LDFLAGS="-fsanitize=address "
SANITIZER_CXXFLAGS="$SANITIZER_CXXFLAGS -fsanitize=address -fno-omit-frame-pointer -fsanitize-address-use-after-scope"
SANITIZER_LDFLAGS="$SANITIZER_LDFLAGS -fsanitize=address"
echo "Using ASAN"
fi
fi

if [ "$USE_UBSAN" != "" ]; then
if [ "$CXX" != "g++" ]; then
SANITIZER_CXXFLAGS="$SANITIZER_CXXFLAGS -fsanitize=undefined -fno-omit-frame-pointer"
SANITIZER_LDFLAGS="$SANITIZER_LDFLAGS -fsanitize=undefined"
echo "Using UBSAN"
fi
fi

if [ "$USE_MSAN" != "" ]; then
if [ "$CXX" != "clang++" ]; then
echo "MSAN requires clang++"
exit 1
fi
SANITIZER_CXXFLAGS="$SANITIZER_CXXFLAGS -fsanitize=memory -fsanitize-memory-track-origins=2 -fno-omit-frame-pointer"
SANITIZER_LDFLAGS="$SANITIZER_LDFLAGS -fsanitize=memory"
echo "Using MSAN"
fi

if [ "$OPT" == "" ]; then
OPT="-O2"
fi
Expand All @@ -27,9 +60,6 @@ fi
echo Using -std=$STDVERSION


if [ "$CXX" == "" ]; then
CXX=clang++
fi
echo Using CXX=$CXX
$CXX --version

Expand All @@ -39,17 +69,21 @@ if [ "$ARCH" == "" ]; then
fi
echo Using ARCH=$ARCH

CXXFLAGS="$CXXFLAGS -std=$STDVERSION -g -Wall -pedantic -fno-exceptions -Werror=format -Isrc -I. $ASAN $PREPROCESS -Wno-old-style-cast"
CXXFLAGS="$CXXFLAGS -std=$STDVERSION -g -Wall -pedantic -fno-exceptions -Werror=format -Isrc -I. $SANITIZER_CXXFLAGS $PREPROCESS -Wno-old-style-cast"

if [ "$CXX" == "clang++" ]; then
CXXFLAGS="$CXXFLAGS -Weverything -Wno-global-constructors"
CXXFLAGS="$CXXFLAGS -Weverything -Wno-global-constructors -Wuninitialized -Wsometimes-uninitialized -Wconditional-uninitialized"
fi

if [ "$CXX" == "g++" ]; then
CXXFLAGS="$CXXFLAGS -Wuninitialized -Wmaybe-uninitialized"
fi

if [ "$CXX" != "c++98" ]; then
CXXFLAGS="$CXXFLAGS -Wno-zero-as-null-pointer-constant -Wno-c++98-compat -Wno-c++98-compat-pedantic -Wno-suggest-override"
fi

LDFLAGS="$LDFLAGS $ASAN_LDFLAGS"
LDFLAGS="$LDFLAGS $SANITIZER_LDFLAGS"



Expand All @@ -72,16 +106,37 @@ echo "COMPILING WITH JCTEST"
PREFIX=jctest

EXAMPLE_SOURCE_DIR=./hugo/static/code
ANALYZE_INDEX=0
ANALYZED_MAIN=0

function analyze_source {
local file=$1
shift
local outfile=./build/analyze_${ANALYZE_INDEX}.o
ANALYZE_INDEX=$((ANALYZE_INDEX + 1))
echo "Analyzing ${file}"
$CXX --analyze $OPT $ARCH $SYSROOT $CXXFLAGS $STATIC_ANALYZER_FLAGS $* ${file} -o ${outfile}
}

function compile_doc_example {
local file=example_${1}.cpp
if [ "$STATIC_ANALYZER_CLANG" != "" ]; then
analyze_source ${EXAMPLE_SOURCE_DIR}/${file}
fi
echo "Compiling ${file}"
$CXX -o ./build/example_${1} $OPT $ARCH $SYSROOT $CXXFLAGS ${EXAMPLE_SOURCE_DIR}/${file}
}

function compile_test {
local name=$1
shift
if [ "$STATIC_ANALYZER_CLANG" != "" ]; then
analyze_source test/test_${name}.cpp $*
if [ "$ANALYZED_MAIN" == "0" ]; then
analyze_source test/main.cpp
ANALYZED_MAIN=1
fi
fi
echo "Compiling test $name"
$CXX -o ./build/${PREFIX}_test_${name}.o $OPT $DISASSEMBLY $ARCH $SYSROOT $CXXFLAGS $* -c test/test_${name}.cpp
$CXX -o ./build/${PREFIX}_main.o $OPT $DISASSEMBLY $ARCH $SYSROOT $CXXFLAGS -c test/main.cpp
Expand All @@ -91,6 +146,9 @@ function compile_test {
function compile_test_with_main {
local name=$1
shift
if [ "$STATIC_ANALYZER_CLANG" != "" ]; then
analyze_source test/test_${name}.cpp $*
fi
echo "Compiling test $name"
$CXX -o ./build/${PREFIX}_test_${name}.o $OPT $DISASSEMBLY $ARCH $SYSROOT $CXXFLAGS $* -c test/test_${name}.cpp
$CXX -o ./build/${PREFIX}_${name} $OPT $ARCH ./build/${PREFIX}_test_${name}.o $LDFLAGS
Expand Down
70 changes: 41 additions & 29 deletions scripts/compile_cl.bat
Original file line number Diff line number Diff line change
@@ -1,29 +1,41 @@
rem echo off

call python3 --version 2>NUL
if '%errorlevel%'=='1' goto errorNoPython
set TIMEIT=python %~dp0\timeit.py
goto hasPython
:errorNoPython
echo "No python found!"
goto end

set TIMEIT
:hasPython

mkdir build

set FLAGS=/Od /Zi /D_CRT_SECURE_NO_WARNINGS /nologo /D_HAS_EXCEPTIONS=0 /EHsc /W4 /wd4611 /Isrc

call %TIMEIT% cl.exe %FLAGS% test\test_params.cpp test\main.cpp /link /out:.\build\test_params.exe
call %TIMEIT% cl.exe %FLAGS% test\test_typed_test.cpp test\main.cpp /link /out:.\build\test_typed_test.exe
call %TIMEIT% cl.exe %FLAGS% test\test_expect.cpp test\main.cpp /link /out:.\build\test_expect.exe
call %TIMEIT% cl.exe %FLAGS% test\test_death.cpp test\main.cpp /link /out:.\build\test_death.exe
call %TIMEIT% cl.exe %FLAGS% test\test_empty.cpp test\main.cpp /link /out:.\build\test_empty.exe
call %TIMEIT% cl.exe %FLAGS% test\test_array.cpp test\main.cpp /link /out:.\build\test_array.exe
call %TIMEIT% cl.exe %FLAGS% test\test_color_off.cpp /link /out:.\build\test_color_off.exe
call %TIMEIT% cl.exe %FLAGS% test\test_color_on.cpp /link /out:.\build\test_color_on.exe

del *.obj

:end
@echo off

call python3 --version 2>NUL
if '%errorlevel%'=='1' goto errorNoPython
set TIMEIT=python3 %~dp0\timeit.py
goto hasPython
:errorNoPython
echo "No python found!"
exit /b 1

set TIMEIT
:hasPython

if not exist build mkdir build

set FLAGS=/Od /Zi /D_CRT_SECURE_NO_WARNINGS /nologo /D_HAS_EXCEPTIONS=0 /EHsc /W4 /wd4611 /Isrc
if not "%USE_STATICANALYZE%"=="" (
set FLAGS=%FLAGS% /analyze /WX
echo Using STATIC ANALYZER (msvc)
)

call %TIMEIT% cl.exe %FLAGS% test\test_params.cpp test\main.cpp /link /out:.\build\test_params.exe
if errorlevel 1 exit /b %errorlevel%
call %TIMEIT% cl.exe %FLAGS% test\test_typed_test.cpp test\main.cpp /link /out:.\build\test_typed_test.exe
if errorlevel 1 exit /b %errorlevel%
call %TIMEIT% cl.exe %FLAGS% test\test_expect.cpp test\main.cpp /link /out:.\build\test_expect.exe
if errorlevel 1 exit /b %errorlevel%
call %TIMEIT% cl.exe %FLAGS% test\test_death.cpp test\main.cpp /link /out:.\build\test_death.exe
if errorlevel 1 exit /b %errorlevel%
call %TIMEIT% cl.exe %FLAGS% test\test_empty.cpp test\main.cpp /link /out:.\build\test_empty.exe
if errorlevel 1 exit /b %errorlevel%
call %TIMEIT% cl.exe %FLAGS% test\test_array.cpp test\main.cpp /link /out:.\build\test_array.exe
if errorlevel 1 exit /b %errorlevel%
call %TIMEIT% cl.exe %FLAGS% test\test_color_off.cpp /link /out:.\build\test_color_off.exe
if errorlevel 1 exit /b %errorlevel%
call %TIMEIT% cl.exe %FLAGS% test\test_color_on.cpp /link /out:.\build\test_color_on.exe
if errorlevel 1 exit /b %errorlevel%

del *.obj

exit /b 0
31 changes: 20 additions & 11 deletions scripts/run_tests.bat
Original file line number Diff line number Diff line change
@@ -1,11 +1,20 @@
echo off

.\build\test_params.exe
.\build\test_typed_test.exe
.\build\test_expect.exe
.\build\test_death.exe
.\build\test_empty.exe
.\build\test_array.exe
.\build\test_doctest.exe
.\build\test_color_off.exe
.\build\test_color_on.exe
@echo off

call :run_test .\build\test_params.exe
call :run_test .\build\test_typed_test.exe
call :run_test .\build\test_expect.exe
call :run_test .\build\test_death.exe
call :run_test .\build\test_empty.exe
call :run_test .\build\test_array.exe
call :run_test .\build\test_color_off.exe
call :run_test .\build\test_color_on.exe
exit /b 0

:run_test
if not exist "%~1" (
echo Missing test executable: %~1
exit /b 1
)
call "%~1"
if errorlevel 1 exit /b %errorlevel%
exit /b 0
1 change: 1 addition & 0 deletions scripts/timeit.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@
p.wait()
tend = time.time()
print("%s took %f ms" % (sys.argv[1], (tend-tstart)*1000.0))
sys.exit(p.returncode)
Loading