一键导入
building
All documentation related to building and running Project or Tests
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
All documentation related to building and running Project or Tests
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
Comprehensive guide to the Chemical compiler test infrastructure — how tests are organized, written, and executed. Covers the test framework, @test annotation dispatch, test_env and test libraries, and how compiler plugins get tested via lang/tests/build.lab.
Comprehensive deep-dive into the Chemical build pipeline — how chemical.mod is converted to build.lab, how build scripts are JIT-compiled via TinyCC, how jobs are created and executed, and how ASTProcessor orchestrates the parallel compilation passes.
Comprehensive guide to the Chemical Compiler Binding Interface (CBI) — how compiler plugins are built, registered, and integrated into the compilation pipeline.
Documentation of Syntax and APIs for Chemical Programming Language, A must read before implementing something in chemical programming language.s
Comprehensive guide to Chemical's compiler intrinsic functions and reflection APIs — how GlobalFunctions.cpp provides interpreter-friendly implementations, compile-time reflection, and metadata access.
The Chemical compiler API bindings in lang/libs/compiler/ and the C++ AST node hierarchy — ASTNode, Value, BaseType, ASTAllocator, and their unsafe casting methods.
| name | Building |
| description | All documentation related to building and running Project or Tests |
Its likely user is using CLion, in this case in the root dir, you'll find cmake-build-debug where there are two
compilers present
TCCCompiler (the compiler that embeds Tiny CC)
Compiler (the compiler that embeds LLVM/Clang and Tiny CC)
--use-tcc or ask it to translate to C and then compile that using--use-cIt's likely that you don't need to rebuild the compiler, because you are working on libraries (lang/libs/<library> or lang/compiled/<library>).
To properly understand building of the compilers, You should analyze the CMakeLists.txt in the root of the repo.
If you are working on any code that doesn't interact with LLVM/Clang then you should not compile Compiler target. you should focus on TCCCompiler which would build faster and would compile faster.
# Configure with LLVM support (default)
./scripts/configure.sh
# Configure without LLVM (TCCCompiler only)
./scripts/configure.sh --no-llvm
There are three CMake targets: TCCCompiler, Compiler, and ChemicalLsp.
./scripts/build.sh --tcc # Build TCCCompiler only
./scripts/build.sh --llvm # Build Compiler (LLVM/Clang backend)
./scripts/build.sh --lsp # Build ChemicalLsp
./scripts/build.sh --all # Build all targets
./scripts/build.sh --llvm -j 16 # Build with 16 parallel jobs
make -C cmake-build-debug Compiler -j$(nproc)
make -C cmake-build-debug TCCCompiler -j$(nproc)
make -C cmake-build-debug ChemicalLsp -j$(nproc)
cmake-build-debug/Makefile (configured by CLion).cmake is at /opt/clion/bin/cmake/linux/x64/bin/cmake (not in PATH).out/host contains LLVM/Clang Libraries — do not overwrite../scripts/configure.sh --no-llvm (sets -DBUILD_COMPILER=OFF).# Build TCCCompiler, compile tests, run them
./scripts/test.sh --tcc
# Build Compiler, compile tests, run them
./scripts/test.sh --llvm
# Include library tests
./scripts/test.sh --tcc --plugins
# Custom output path
./scripts/test.sh --tcc -o my_tests
# Build only (no run)
./scripts/test.sh --tcc --no-run
# Skip compiler rebuild, use existing binary
./scripts/test.sh --tcc --no-build
# Run tests under GDB batch mode to capture backtrace on crash:
./scripts/test.sh --tcc --bt # gdb -batch, print bt full
./scripts/test.sh --tcc --bt-full # gdb -batch with full bt, registers, disasm
🐛
-bt/-bt-full: These flags wrap the test executable ingdb -batchmode. On crash, they print a backtrace (and optionally registers, disassembly, locals). Implies-gautomatically. Works for both compiled and interpretation modes.
-bt→gdb -batch -ex "run" -ex "bt full" --args <program>-bt-full→gdb -batch -ex "run" -ex "thread apply all bt full" -ex "info registers" -ex "x/16i $pc" -ex "info locals" -ex "info args" --args <program>
⚠️
--no-buildwarning: This flag skips rebuilding the C++ compiler binary. Any changes to.cpp/.hfiles will NOT be reflected — the previously built binary is used as-is. Only use--no-buildwhen iterating on.chtest files or Chemical library sources without any compiler C++ changes. To include C++ changes, omit--no-build(or run once without it to rebuild, then you can use--no-buildfor subsequent iterations).
# TCC backend
cmake-build-debug/TCCCompiler "lang/tests/build.lab" -o lang/tests/build/tests-tcc.exe --mode debug_quick --no-cache
# LLVM backend
cmake-build-debug/Compiler "lang/tests/build.lab" -o lang/tests/build/tests.exe --mode debug_complete --no-cache
./scripts/test.sh --tcc --interpret # Build TCC + run interpretation tests
./scripts/test.sh --tcc --interpret --no-build # Skip rebuild
# Manual:
./chemical lang/tests/build.lab --arg-interpret --mode debug_complete --no-cache
The --arg-interpret flag causes build.lab to create a LabJobType::Interpretation job. The compiler calls do_interpretation_job() in compiler/lab/LabBuildCompiler.cpp, which:
interpret/ + common/ modulesVarInitStmt variables on the global scopemain() via the AST interpreter directly — no object code generatedTests use a common framework at lang/tests/common/src/test.ch that works in both modes:
comptime if(intrinsics::is_interpretation()) {
intrinsics::expr_println(`${ANSI_COLOR_GREEN}Test ${total_tests + 1} [${name}] succeeded${ANSI_COLOR_RESET}`);
} else {
printf("%sTest %d [%s] succeeded %s\n", ANSI_COLOR_GREEN, total_tests + 1, name, ANSI_COLOR_RESET);
}
intrinsics::expr_println(expr: %expressive_string) walks the expressive string's parts — StringValue literals go directly to std::cout, ${} expressions are evaluated and printed via RepresentationVisitor with interpret_representation = true (no quotes).printf with ANSI escape string constants.--mode debug_quick — quickly compile the project with debug info--mode debug_complete — full debug mode for LLVM backend--no-cache — do not rely on previously generated objects--emit-c — write the Translated.c file to the build directory--arg-interpret — run in interpretation mode (interpret AST directly, no codegen)--arg-test-plugins — build library tests executable-frecompile-plugins — recompile compiler pluginsWe test most libraries in the tests above (lang/tests/build.lab) but some libraries like:
html_cbi, css_cbi, js_cbi, componentsreact_cbi, preact_cbi, solid_cbi, universal_cbiThese are compiler plugins, tested via a separate executable:
# Using test script
./scripts/test.sh --tcc --plugins
# Manual
cmake-build-debug/TCCCompiler "lang/tests/build.lab" -o lang/tests/build/lib-tests-tcc.exe --mode debug_quick --no-cache --arg-test-plugins -frecompile-plugins
Helpful flags:
--plugin-mode debug_complete — compile plugins in debug mode for full stack traces--arg-test-html, --arg-test-css, etc. — individual library testsIf you modify anything inside the server directory, note that it's part of the LSP target.
These modules are all LSP-related and require the LSP server running to verify:
html_ide, css_ide, js_ide, react_ide, preact_ide, solid_ide, universal_ide, md_ide# Build LSP
./scripts/build.sh --lsp
LSP target name is ChemicalLsp. Read CMakeLists.txt before building the LSP target.
Interpret tests run via --arg-interpret and execute the AST interpreter directly. The entry point is:
// lang/tests/interpret/src/main.ch
public func main() {
run_common_tests(); // Tests 1-97 (core language features)
run_native_common_tests(); // Pointer arithmetic, casts, comptime pointers
print_test_stats();
}
| Module | Location | What it tests |
|---|---|---|
common_tests | lang/tests/common/ | Core features (arithmetic, loops, structs, variants, inc/dec) |
native_common_tests | lang/tests/native_common/ | Pointer operations, casts, comptime pointer arithmetic |
interpret_tests | lang/tests/interpret/ | Wrapper that imports both and runs main() |
lang/tests/src/comptime/)| File | Tests |
|---|---|
basic.ch | Basic comptime: sum, structs, strings, enums, constructors, get_child_fn, get_line_no |
features.ch | Comptime features: bitwise ops, loops, casting, logical ops, for-in, struct mutation, destructors |
expressions.ch | comptime { } block expressions: arithmetic in comptime blocks |
satisfies.ch | intrinsics::satisfies<T, U>() type relationship tests |
is_value.ch | intrinsics::is_same_type() and is operator type identity tests |
vector.ch | intrinsics::vector<T>() vector operations |
# Quick iteration (interpret only, skip rebuild)
./scripts/test.sh --tcc --interpret --no-build
# Full compiled test run
./scripts/test.sh --tcc --no-build
# Both in sequence
./scripts/test.sh --tcc --interpret --no-build && ./scripts/test.sh --tcc --no-build
Create the test source in lang/tests/src/comptime/ or lang/tests/common/src/:
// lang/tests/src/comptime/my_feature.ch
comptime func my_feature(a : int, b : int) : int {
return a * b + a;
}
func test_my_feature() {
test("my feature works", () => {
return my_feature(3, 4) == 15;
});
}
Register the test by calling the function from the appropriate runner:
test_my_feature(); to run_common_tests() in lang/tests/common/src/main.chrun_native_common_tests() in lang/tests/native_common/src/main.chmain() in lang/tests/src/tests.chBuild and test: Use the commands above.
ahead/behind on PointerValues. Dereferencing past bounds returns null (not crash). Tests with pointer arithmetic reaching one-past-end may fail.&raw struct_val): Not supported in interpreter (returns error). Use &mut struct_val (ReferenceOfValue) instead, or parameter passing by reference.(params) => return_type are called via FunctionDeclaration::call(). If the function reference can't be resolved, a non-fatal "function not found" error appears.float→int and double→int are supported. Other float/double combinations work via standard arithmetic.@delete destructors have their destructor body interpreted when the scope exits. Empty destructors work fine.[InterpretError] messages — these indicate exact failuresstd::cerr << "[DEBUG] ..." << std::endl; to interpreter source files to trace specific operationsderef() itself crashes — we've made this non-fatal by returning getNullValue() insteadRunning the full test suite on every iteration is slow. Instead of working through
the entire test suite, isolate the failing test by copying its source code
(plus the types/functions it depends on) into a single file at lang/compiled/temp.ch.
The lang/compiled/ directory is in .gitignore, so nothing there will be committed.
lang/compiled/temp.ch./scripts/build.sh --tcc # For TCCCompiler
./scripts/build.sh --llvm # For Compiler (LLVM)
cmake-build-debug/Compiler "lang/compiled/temp.ch" --out-ll-all --build-dir "lang/compiled" \
-o "lang/compiled/temp.exe" --mode debug_complete --debug-ir -v --assertions -fno-unwind-tables
LLVM IR is emitted at lang/compiled/modules/main/llvm_ir.ll# Produce .c output:
cmake-build-debug/TCCCompiler "lang/compiled/temp.ch" -o "lang/compiled/temp.c" -v -bm-modules
# Or produce an executable:
cmake-build-debug/TCCCompiler "lang/compiled/temp.ch" -o "lang/compiled/temp.exe" -v -bm-modules
./lang/compiled/temp.exe--mode debug_complete — maximum debug info in LLVM IR; omit for cleaner IR without metadata--mode debug_quick — minimal debug info (good for TCCCompiler)--debug-ir — don't crash on potentially bad IR--assertions — verify the generated IR is valid-fno-unwind-tables — cleaner IR (removes unwind data on Windows)-v — verbose output-bm-modules — emit build module information⚠️ Always rebuild the compiler (
./scripts/build.sh --tccor--llvm) after changing.cpp/.hfiles. The previously built binary is used otherwise and your changes won't be reflected.
.agents/skills/build_system/SKILL.md) — Detailed internals of the Lab build system, job execution, plugin compilation, caching, dependency management.agents/skills/performance/SKILL.md) — Compiler optimization patterns, parallelization strategies, arena allocation.agents/skills/testing/SKILL.md) — Test infrastructure, writing tests, how tests are wired in lang/tests/build.lab