Thank you for your interest in contributing to Vix.cpp.
Vix.cpp is a modular C++20 runtime. The project is built around clean APIs, high performance, strong tests, reproducible benchmarks, and strict CI.
This guide explains how to contribute code, tests, documentation, examples, benchmarks, and bug reports.
Vix.cpp aims to provide:
- a modern C++20 runtime,
- modular components that can be used independently,
- fast HTTP and async runtime foundations,
- a strong CLI developer experience,
- reliable tests and CI,
- reproducible benchmark baselines,
- safe and maintainable C++ code.
Contributions should help move the project toward these goals.
All contributors are expected to follow the project Code of Conduct.
Please read:
CODE_OF_CONDUCT.mdRespectful technical discussion is welcome. Personal attacks, harassment, or bad-faith behavior are not.
The repository is organized as an umbrella project with multiple modules.
Common directories:
modules/
core/
cli/
json/
async/
threadpool/
websocket/
template/
middleware/
crypto/
validation/
conversion/
db/
orm/
cache/
kv/
sync/
p2p/
game/
fs/
io/
path/
env/
os/
process/
log/
error/
time/
utils/
docs/
benchmarks/
.github/workflows/Most modules have their own:
include/
src/
tests/
examples/
benchmarks/
CMakeLists.txtNot every module has all of these directories.
Use a feature branch for your work.
Example:
git checkout -b fix/threadpool-cancellationGood branch names:
fix/threadpool-cancellation
test/core-session-errors
docs/json-readme
ci/static-analysis-scope
bench/core-routerAvoid working directly on release branches unless you are a maintainer preparing a release.
Recommended tools:
- C++20 compiler,
- CMake 3.20 or newer,
- Ninja or Make,
- Git,
vixCLI,- GoogleTest where required,
- cppcheck,
- clang-tidy,
- Valgrind,
- ASan / UBSan capable compiler.
On Ubuntu, useful packages include:
sudo apt update
sudo apt install -y \
build-essential \
cmake \
ninja-build \
git \
pkg-config \
cppcheck \
clang-tidy \
valgrindSome modules may require optional dependencies such as:
OpenSSL
SQLite3
ZLIB
fmt
spdlog
SDL2
SDL2_image
OpenGL
MySQL Connector/C++Only install optional dependencies when working on modules that need them.
From the repository root:
vix build --build-target allOr with CMake directly:
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build -jFor development builds:
vix build --build-target all -vVix.cpp tests are usually stored inside each module, not only in the root tests/ directory.
The root tests/ directory may be empty. This is expected.
To enable broad test coverage:
vix build --clean --build-target all -v -- \
-DBUILD_TESTING=ON \
-DVIX_BUILD_TESTS=ON \
-DVIX_CORE_BUILD_TESTS=ON \
-DVIX_ASYNC_BUILD_TESTS=ON \
-DVIX_CACHE_BUILD_TESTS=ON \
-DVIX_CONVERSION_BUILD_TESTS=ON \
-DVIX_CRYPTO_BUILD_TESTS=ON \
-DVIX_DB_BUILD_TESTS=ON \
-DVIX_ENV_BUILD_TESTS=ON \
-DVIX_ERROR_BUILD_TESTS=ON \
-DVIX_FS_BUILD_TESTS=ON \
-DVIX_GAME_BUILD_TESTS=ON \
-DVIX_IO_BUILD_TESTS=ON \
-DVIX_JSON_BUILD_TESTS=ON \
-DVIX_KV_BUILD_TESTS=ON \
-DVIX_LOG_BUILD_TESTS=ON \
-DVIX_MIDDLEWARE_BUILD_TESTS=ON \
-DVIX_OS_BUILD_TESTS=ON \
-DVIX_PATH_BUILD_TESTS=ON \
-DVIX_P2P_BUILD_TESTS=ON \
-DVIX_PROCESS_BUILD_TESTS=ON \
-DVIX_SYNC_BUILD_TESTS=ON \
-DVIX_TEMPLATE_BUILD_TESTS=ON \
-DVIX_TESTS_BUILD_TESTS=ON \
-DVIX_THREADPOOL_BUILD_TESTS=ON \
-DVIX_TIME_BUILD_TESTS=ON \
-DVIX_VALIDATION_BUILD_TESTS=ON \
-DVIX_WEBRPC_BUILD_TESTS=ON \
-DVIX_WEBSOCKET_BUILD_TESTS=ON \
-DVIX_AI_AGENT_BUILD_TESTS=ONRun tests:
ctest --test-dir build-ninja --output-on-failure --timeout 180To run a specific test:
ctest --test-dir build-ninja --output-on-failure -R ThreadPoolTestTo run a GoogleTest binary directly:
./build-ninja/threadpool_build/tests/ExecutorTestWith a filter:
./build-ninja/threadpool_build/tests/ExecutorTest \
--gtest_filter=ExecutorTest.ThreadPoolExecutorCanPostToThreadPoolUse sanitizer builds when changing runtime, async, memory, lifecycle, threadpool, or low-level code.
vix build --clean --build-target all -v -- \
-DBUILD_TESTING=ON \
-DVIX_ENABLE_SANITIZERS=ON \
-DVIX_BUILD_TESTS=ONRun sanitizer tests:
ctest --test-dir build-san-tests --output-on-failure --timeout 180If you add a new test executable that links against a sanitizer-enabled static library, make sure the test executable also links with sanitizer flags.
Example:
if (VIX_ENABLE_SANITIZERS AND NOT MSVC)
target_compile_options(my_test_target
PRIVATE
-fno-omit-frame-pointer
-fsanitize=address,undefined
)
target_link_options(my_test_target
PRIVATE
-fsanitize=address,undefined
)
endif()If the module uses a shared helper target:
if (VIX_ENABLE_SANITIZERS AND TARGET vix_sanitizers)
target_link_libraries(my_test_target PRIVATE vix_sanitizers)
endif()Use Valgrind for memory-sensitive changes.
ctest --test-dir build-valgrind --output-on-failure --timeout 300Do not treat benchmark binaries as normal Valgrind test executables.
Valgrind jobs should focus on correctness and memory safety, not performance workloads.
The project uses static analysis tools such as:
- cppcheck,
- clang-tidy,
- compiler warnings.
Static analysis should focus on Vix project source code.
Do not run blocking static analysis on:
third_party/
_deps/
build/
tests/
examples/
benchmarks/
optional disabled backend filesFor cppcheck, prefer analyzing implementation sources only:
mapfile -t CPPCHECK_FILES < <(
find modules \
-type f \
-path '*/src/*.cpp' \
! -path '*/third_party/*' \
! -path '*/_deps/*' \
! -path '*/build/*' \
! -path '*/tests/*' \
! -path '*/test/*' \
! -path '*/examples/*' \
! -path '*/benchmarks/*' \
! -path '*/benchmark/*' \
! -path '*/backends/sdl/*' \
| sort
)
cppcheck \
--enable=warning,performance,portability \
--std=c++20 \
--inconclusive \
--error-exitcode=2 \
--suppress=missingIncludeSystem \
--inline-suppr \
-j "$(nproc)" \
"${CPPCHECK_FILES[@]}"For clang-tidy, prefer using the configured CMake compilation database:
build-analyze/compile_commands.jsonThis prevents analyzing source files that are not part of the current build profile.
If a tool reports a false positive, prefer a narrow local suppression instead of weakening the whole workflow.
Example:
if (!runs.empty())
{
// cppcheck-suppress containerOutOfBounds
return runs.front();
}Only suppress when:
- the code is clearly safe,
- the warning is demonstrably false,
- the suppression is local,
- the suppression ID is specific,
- the reason is easy to understand from the surrounding code.
Do not add broad global suppressions for project code unless absolutely necessary.
Use modern, readable C++20.
General rules:
- prefer clear names,
- keep functions focused,
- avoid unnecessary global state,
- avoid raw owning pointers,
- prefer RAII,
- avoid undefined behavior,
- avoid data races,
- avoid hidden lifetime assumptions,
- prefer
std::optional,std::variant, and strong result types when useful, - use
std::string_viewcarefully and never return dangling views, - make error paths explicit,
- keep APIs predictable.
Match the style of the existing file.
General style used across Vix.cpp:
if (condition)
{
do_work();
}Use braces for control flow.
Prefer readable code over clever code.
Public headers should live under:
modules/<module>/include/vix/<module>/Implementation files should live under:
modules/<module>/src/Tests should live under:
modules/<module>/tests/Examples should live under:
modules/<module>/examples/When adding a module target:
- provide a namespaced alias such as
vix::<module>, - set C++20 compile features,
- install public headers,
- support umbrella builds,
- support standalone builds where applicable,
- export targets correctly,
- keep optional dependencies behind options,
- do not force optional dependencies when a feature is disabled.
Example target naming:
vix_core
vix::coreFor tests:
- register with
add_test, - link to the correct module target,
- attach sanitizer options when enabled,
- avoid merging plain test files that each define
main()into one executable.
Some modules use GoogleTest. Some modules use simple executable tests with their own main().
Do not combine multiple plain test files that each define main() into one executable.
Bad:
add_executable(vix_validation_tests
validate_parsed_invalid.cpp
validate_parsed_ok.cpp
validate_string_smoke.cpp
)Correct:
foreach(src ${VIX_VALIDATION_TEST_SOURCES})
get_filename_component(fname ${src} NAME_WE)
set(tname "vix_validation_test_${fname}")
add_executable(${tname} ${src})
target_link_libraries(${tname} PRIVATE vix::validation)
add_test(NAME ${tname} COMMAND ${tname})
endforeach()Threading and async changes require extra care.
When changing threadpool, scheduler, executor, runtime, async TCP, or shutdown code:
- test normal builds,
- test sanitizer builds,
- test cancellation paths,
- test shutdown paths,
- ensure futures are always resolved,
- ensure promises are not left pending,
- avoid assuming async work completes immediately,
- avoid race-prone tests.
Bad test pattern:
executor.post([&] {
counter.fetch_add(1);
});
EXPECT_EQ(counter.load(), 1);Better:
executor.post([&] {
counter.fetch_add(1);
});
ASSERT_TRUE(wait_until_true([&] {
return counter.load() == 1;
}));Avoid reading objects after ownership has moved or after a container clears owned objects.
Bad:
auto system = std::make_unique<CountingSystem>();
auto *raw = system.get();
registry.add_system(std::move(system));
registry.clear();
EXPECT_EQ(raw->stopped_count, 1);After registry.clear(), the system object may be destroyed.
Use an external counter:
auto stopped_count = std::make_shared<int>(0);Benchmarks must be reproducible.
Official benchmark numbers must come from Release builds, not debug or dev builds.
Good:
cmake -S . -B build-release -DCMAKE_BUILD_TYPE=Release
cmake --build build-release -jBad:
vix buildDevelopment builds are useful for debugging, but they are not official performance numbers.
Benchmark reports should include:
- build type,
- compiler,
- platform,
- CPU,
- benchmark target,
- sample count,
- median time,
- mean time,
- operations per second.
Documentation contributions are welcome.
Good documentation should be:
- clear,
- accurate,
- tested when it contains commands,
- consistent with current APIs,
- free of outdated benchmark claims,
- honest about limitations.
When changing APIs, update the relevant documentation.
Common files:
README.md
README.ja.md
docs/
SECURITY_TESTS.md
CHANGELOG.mdUse short, clear commit messages.
Examples:
fix: resolve futures for queued cancellations
test: wait for threadpool executor task completion
ci: run clang-tidy on configured module sources
docs: update Japanese README
docs: add security test matrixCommon prefixes:
fix:
test:
docs:
ci:
bench:
refactor:
chore:
feat:Avoid vague messages such as:
update
fix bug
changes
workSome modules may be tracked as nested repositories or submodules.
When changing a module:
cd /vixcpp/vix/modules/<module>
git status
git add <files>
git commit -m "type: message"
git push origin devThen update the umbrella repository:
cd /vixcpp/vix
git status
git add modules/<module>
git commit -m "chore: update <module> module"
git push origin release/v2.6.3Always commit the module first, then the umbrella pointer.
Before opening a pull request, check:
- The code builds locally.
- Relevant module tests pass.
- New behavior has tests.
- Sanitizer build passes for low-level changes.
- No benchmark binary is treated as a normal test.
- Static analysis does not include vendored dependencies.
- Documentation is updated if APIs changed.
- Changelog is updated for user-facing changes.
- Commit messages are clear.
- The PR description explains what changed and why.
A good bug report should include:
- Vix.cpp version or commit,
- operating system,
- compiler version,
- command that failed,
- full error log,
- expected behavior,
- actual behavior,
- minimal reproduction if possible.
Example:
OS: Ubuntu 24.04
Compiler: GCC 13.3
Command: vix build --build-target all
Module: threadpool
Error: future.get() blocks after queued cancellationA good feature request should explain:
- the problem,
- why the feature is useful,
- expected API shape if known,
- examples of usage,
- alternatives considered.
Feature requests should focus on the project goals.
Performance reports should include enough context to reproduce the result.
Include:
- build type,
- compiler,
- CPU,
- OS,
- command used,
- benchmark target,
- raw output,
- whether CPU affinity was used,
- whether logging was disabled,
- whether the result is warm or cold.
Avoid comparing debug builds against release builds.
For user-facing changes, update:
CHANGELOG.mdUse sections such as:
Added
Changed
Fixed
Removed
Deprecated
SecurityKeep release notes factual and specific.
Do not open public issues for sensitive security vulnerabilities.
For security-sensitive reports, contact the maintainer privately:
adastrablockchain@gmail.comInclude:
- affected module,
- reproduction steps,
- impact,
- suggested fix if known.
By contributing to Vix.cpp, you agree that your contributions are provided under the project license.
Vix.cpp is licensed under the MIT License.