Documentation
- ๐ Welcome to the CMake RE Documentation
- ๐ Getting started with CMake RE for C++
- ๐ฆ Getting started with CMake RE for Rust (alpha)
- Key Principles and Goals
- ๐ชฉ Developer Machine Digital Twin
- ๐ฉ๐ผโ๐ป cmake-re --help | Command Line Reference
- ๐ฆ L1 Build cache
- ๐ฆ L1 Build Cache Sharing
- ๐ฆ FetchContent() and Package Managers
- ๐ป Environments
- ๐ป Environment Layers Specifications
- ๐ป Self-hosted runners
- Authentication
- Ignore and exclude - Caching and Mirroring
- Accessing hermetic builds folders
- Continuous integration
- Environment variables
- ๐ก๏ธ Data Security and Privacy
- tipi - ๐ฎ EXPERIMENTAL - CMakeLists.txt Generator
- tipi - ๐ฎ EXPERIMENTAL - Getting started with tipi CMakeLists generator
- tipi - Compile options
- tipi - Integrated Package Manager
- tipi - Running tests
- tipi - IDE Integration
tipi - ๐ฎ EXPERIMENTAL - CMakeLists.txt Generator
Why ?
Why did we ever write Makefile, CMakeLists.txt or configure IDE project settings? And why are we still doing it ?
Andrew Koenig once coined FTSE, the Fundamental theorem of software engineering:
"We can solve any problem by introducing an extra level of indirection."
Building applications is an extremely complex problem, and the layers are almost infinite: linker, assembler, compiler, front-end, build-system ( I.e. make
), meta-build-system ( I.e. cmake
) to quote only a few.
Tipi leverages all the fabulous work done in these layer to finally make building C++ a humane task.
Because
- C++ code expresses explicitly enough what is an application entry-point and what is reusable library code.
- There's no need to learn a new language to specify how to build.
- We are tired of specifying each single file that should be built.
Convention by example
Take the idea of building a game project. This game project will contain:
- The game domain with the player characters, game menu and so on
- The game app itself
- Tools apps like game maps and texture editor
The directory could look like this:
game.cpp
has a main function each, therefore they are apps by convention.
The main function may look like:
During the scan of src/
tipi classifies the *.hpp
and *.cpp
which do not have any entry-point to the library code ( i.e. the game domain).
In tools/
tipi detects a main()
function both map_editor.cpp
and texture_editor.cpp
, which has the apps convention kick-in.
The apps convention allows to have supporting file residing locally, therefore tools/common.cpp
is linked to map_editor
and texture_editor
.
The header tools/common.hpp
is accessible via #include "common.hpp"
or #include <common.hpp>
while the classes in src/game_classes/*
are exported on the compiler include directories which makes them usable via #include <game_classes/*.hpp>
.
tipi will give the following summary:
Resulting in a bin folder like the following:
<target>/bin
โโโ game.exe // game.cpp
โโโ demo.lib // game_classes *.cpp
โโโ tools
โโโ map_editor.exe // common.cpp, map_editor.cpp
โโโ texture_editor.exe // common.cpp, texture_editor.cpp
Conventions Types
Main conventions:
- Every project is a library. ( ref: every project is a library)
- Each git repositories passed to
tipi
results in one library
All the conventions described are applied if required and/or possible based on tipi's smart detection
It is possible to specify or reduce the scope of a library within a project in case the detection fails or hinting is required:
- by adding parameters:
tipi -s library-dir
- by adding dependency descriptors in the
.tipi/deps
file:"dependency/repo": { "s" : [ "library-dir" ] }
...with
-s
(or thes
key) specifying the additional search path for source files. Multiple entries can be specified both a multiple-s
parameters or multiple entries in thes
key.
Split libraries
.
โโโ include
โย ย โโโ header.hpp
โโโ src
โโโ impl.cpp
One typical kind of C++ project is when headers and implementation files are split in different folders. tipi will consider the include/
folder to be the publicly installable headers and src/
folder to contain the implementation files constituting the library.
tipi checks the presence of
include/
,inc/
,src/
andsources/
to infer this convention.
Same directory libraries
.
โโโ src
โโโ header.hpp
โโโ impl.cpp
Another typical convention C++ programmers use is having implementation and headers residing at the same level of the project's directory hierarchy.
tipi checks the presence of
src/
andsources/
to infer this convention and the absence of main() functions in the files.
Top-level libraries
These are libraries that don't have any special source folder, their headers are directly rooted at the top of their repositories.
When this is detected the same mechanism as for same directory libraries applies.
In this kind of structure disambiguation it might be required to to tell which directories are part of the lib using the
tipi -s
switch or the matching.tipi/deps
configuration.
Header-only libraries
It is possible to have code which is completely header only while application entry-points are in .cpp files aside materializing either lib examples or a corresponding app.
The headers will be put at disposal like in the aforementioned conventions with #include <...>
.
Apps
Any .cpp
file with an entry-point is considered to be an app.
For example any file containing a main()
function or a macro instantiating a main()
function (as commonly used in unit testing frameworks) will be compiled as an application.
apps are always linked to the project library.
if others
.cpp
files reside at same or deeper file-system directories they get linked with the applications in question. Exception to this rule are those directories explicitly declared in thes
/-s
configuration.
Tests or Examples
Equivalent to the apps convention, however they will registered within the CMake CTest test driver and calling tipi . --test all
will run them all and report result status.
This convention kicks-in when files with main()
functions in parent folder are named after one of test
, tests
, example
, examples
HTML and WebAssembly
Any .html
file containing <script type="text/c++"></script>
in it is compiled using the app convention.
When conventions are not enough
In some cases you may find that the convention based build doesn't suit your needs or fails on certain edge-cases.
In such a case please reach out using our community support forum or your premium support option.
Alternatively you can also try to tweak the build as explained in the chapters below. We'd really love to hear about your issues with the smart build algorithm still in order to improve tipi and find a way for the convention build to work, because we firmly believe that less CMakeLists is more time for your C++.
Override convention build for specific directories
Add an empty marker file use-cmake.tipi
and a valid CMakeLists.txt
to the folder you want to exclude from the convention based build.
This can be useful for custom test framework or in cases you need to use specific CMake features not yet supported by tipi.
Tweaking convention build
Tipi relies on CMake and the way we use it can be customized by adding CMakeLists.txt.tpl
files in your project.
The CMakeLists.txt.tpl
can be placed anywhere in the project and are applied to the matching sub-tree.
Run tipi cmaketpl
in any project folder to generate a sample CMakeLists.txt.tpl
with the docs embedded of the different variables at your disposal.
Found an error or want to add more info? Write an issue or contribute changes to this documentation at tipi-build/docs on