A project trying to set 22th century defaults to CMake calls, with a simplified syntax for the most common needs during development and an emphasis on build speed.
The tool works by generating a CMake toolchain file from a list of features passed in arguments, and running a cmake ; cmake --build
cycle with that toolchain file. Requested features can have (acyclic) dependencies and will be ordered automatically if they do.
Either download the latest binary for your OS or install it through your package manager of choice:
- ArchLinux AUR:
yay -S cninja
- MSYS2:
pacman -S cninja
- Homebrew:
brew tap jcelerier/packages && brew install cninja
- Uses Ninja, Clang everywhere, and if possible libc++ and lld.
- Generates
compile_commands.json
by default. - Forces you to use a recent clang with a recent C++ standard.
- Configures and builds in one glorious stroke.
- Does not scream at you.
- Does not try to install in global system folders - the
install
target will copy things in abuild/install
folder. - Looks for config files in
.cninja
folders - easily create custom configs for your projects.
### Produces a release build with debug symbols in "build"
$ git clone something
$ cd something
$ cninja
### Produces a build in "build-static-lto=thin"
$ cninja static lto=thin
### Produces a build in "build-asan-ubsan-debugsyms-examples-tests"
$ cninja asan ubsan debugsyms tests examples
### Produces a build of the /foo/bar folder with some CMake flags
$ cninja /foo/bar asan ubsan debugsyms -- -DCMAKE_PREFIX_PATH=/path/to/somelib
### Custom configurations
### Can be per-project:
$ mkdir .cninja
$ echo 'string(APPEND CMAKE_CXX_FLAGS_INIT " -Weverything")' > .cninja/all_warnings.cmake
### Or per-user:
$ mkdir $HOME/.cninja
$ echo 'set(CMAKE_PREFIX_PATH "/home/myself/Qt/5.15/gcc_64")' > $HOME/.cninja/my_qt.cmake
$ cninja all_warnings my_qt asan
### Don't set any of the default flags (i.e. use CMake defaults)
$ cninja plain
As an example, here is a comparison of the default set-up of cninja
and the same build type for CMake on the Strawberry software :
Tool | Command | First build | After changing a file |
---|---|---|---|
cmake | mkdir build cd build cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo .. cmake --build . -- -j16 |
2m 40s | 7.6s |
cninja | cninja | 2m 16s | 1.7s |
The main goal is to uniformize semantics across platforms, with the strictest choice prevailing, to make portability easier and not have bad surprises when porting software written on Linux to macOS or Windows.
For instance :
- Symbols are hidden by default.
- Dynamic library symbols are resolved at compile-time and early-bound.
- Debug mode will perform iterator checking on all platforms.
It also splits the common "Debug" feature in its two orthogonal child features :
debugsyms
will generate binaries with debug symbols.debugmode
will enable run-time checks and assertions in the standard library - the default for Debug in Windows, but generally not in Linux and Mac platforms.
A further goal is to remove the need for adding various flags in each CMake file - ideally, CMake build scripts should just create targets and link libraries, not set up compiler flags. Running for instance
$ rg --no-filename --only-matching '[A-Za-z0-9_]+_SANITIZE[A-Z]?' -g '*.cmake' | sort | uniq
in my home directory reveals almost 30 distinct variables used in various CMake scripts to enable sanitizers... and even more if I also match CMakeLists.txt files.
-
I downloaded a CMake project on Github and want to build it presto
🡆 Yes
-
I have wrist pain from the mere thought of typing
CMAKE_CXX_FLAGS_RELWITHDEBINFO
once more🡆 Yes
-
My CMake files have options to enable sanitizers, LTO and build warnings
🡆 Yes (also, clean them !)
-
My projects have bash / powershell / python / perl / makefile / .travis.yml scripts which invoke CMake
🡆 Yes
-
history | grep cmake | grep CMAKE_
in my shell fills my terminal screen🡆 Yes
-
I want to get shit done
🡆 Yes
-
I want to cross-compile
🡆 No
-
My project only builds in C++98 mode
🡆 No
-
I don't want my code to be portable across platforms
🡆 No
-
I like typing CFLAGS="..." CXXFLAGS="..."
🡆 You lie
-
I want Haiku or SerenityOS support
🡆 PRs accepted
- PGO
- Code coverage
- ~Debug split -> done
- Downloading Clang / CMake / Ninja automatically if they aren't available
- Some kind of improved support for common libraries
- Looking for Qt in
~/Qt/system/latest_version
- Looking for Qt in
c:/Qt/system/latest_version
- Looking for Qt in
Cristian Adam for his blog post on using Github actions.