Build from Source
clice depends on C++23 features and requires a modern C++ toolchain. We also need to link against LLVM/Clang to parse ASTs. Both come from xclang, clice-io's clang toolchain: Bazel builds clice with xclang's toolchain and links the prebuilt LLVM/Clang libraries of the same xclang release, both downloaded by Bazel itself. The two must match: the libraries hold ThinLTO bitcode, which only the toolchain of that release reads.
To simplify setup and keep builds reproducible, we strongly recommend pixi to manage the development environment. Dependency versions are pinned in pixi.toml; Bazel's are in MODULE.bazel.
Quick Start
Install pixi following the official guide.
We ship several tasks; the commands below build and run tests:
# build (default RelWithDebInfo) into build/RelWithDebInfo
pixi run build
# unit + integration + smoke + snap tests
pixi run testFor finer-grained tasks (first argument sets the build type):
pixi run build Debug
pixi run unit-test Debug
pixi run integration-test Debug
pixi run smoke-test Debug
pixi run snap-test Debugpixi run build builds //:dist with Bazel. Each build type has a directory of its own, build/<type>, whose bin is Bazel's output tree of that type: clice is build/<type>/bin/bin/clice, next to the resource directory it reads clang's headers from, build/<type>/bin/lib/clang; the tests and the editors run it from there.
TIP
Run pixi shell to enter a shell with all env vars configured, and npx bazel there for Bazel itself.
Bazel
Bazel is run through bazelisk, an npm package of the repository (npm install installs it), which fetches the Bazel release .bazelversion names:
npx bazel build //:bin/clice //:bin/unit_testsThe build types are configurations of bazel/clice.bazelrc:
| Configuration | Effect |
|---|---|
--config=RelWithDebInfo | The default: optimized, with debug info |
--config=Debug | Light optimization (-O1), with Address Sanitizer |
Options after -- reach Bazel through pixi run build, for example pixi run build RelWithDebInfo -- //:package.
--platforms=@xclang//platforms:<triple> builds for another architecture of the host's operating system, for example --platforms=@xclang//platforms:aarch64-unknown-linux-gnu on x86_64 Linux.
The LLVM/Clang libraries hold ThinLTO bitcode, so every link of a program redoes their code generation, minutes per program. lld keeps what it generated in a cache, /var/tmp/xclang-thinlto (C:/xclang-thinlto on Windows), and later links take seconds.
npx bazel build //:package //:symbols builds the release archive and the symbol package, clice's GSYM for scripts/symbolize.py: clice.tar.gz and clice-symbol.tar.xz in build/<type>/bin (.zip on Windows).
npx bazel run @compdb//:refresh writes a compile_commands.json of clice's own sources to the repository root, for clice to work on its own code.
On Windows, Bazel's default output root is too deep for Windows paths; put a short one in %USERPROFILE%\.bazelrc:
startup --output_user_root=C:/bBazel also needs a Bash on Windows, which Git for Windows provides.
About LLVM
clice calls Clang APIs to parse C++ code, so it must link against LLVM/Clang, of the exact version it is written for: the system LLVM package cannot be used directly.
Every xclang release publishes prebuilt LLVM/Clang libraries (the libclang-* archives) for all six targets, built by that release's toolchain, and its Bazel module makes them repositories Bazel downloads with the toolchain.
IMPORTANT
Debug builds enable Address Sanitizer and link the ASan-instrumented libraries xclang publishes for x86_64 Linux and arm64 macOS; the other targets have none, and no Debug build: the module of the third-party libraries in modules/ has no debug configuration for them, and a compilation of theirs without NDEBUG stops at its #error.
A build of LLVM/Clang of one's own replaces the release's with --repo_env=XCLANG_LIBCLANG_ROOT=<directory> (XCLANG_LIBCLANG_ASAN_ROOT for the ASan one); it has to be built the way xclang builds it, by xclang's scripts/toolchain.ts; see xclang.
