The usage steps of this template can be divided into
- Rename
- Configure
- Switch to developer mode
- Build
- Test
- Install
- A note for multi-config generators and LSP based on
compile_commands.json
- Almost always use conan
Note that vcpkg can also be handled like configure option 1, see aminya/cpp_vcpkg_project.
In addition, the appendix gives a hint on almost-always-use-conan style usage.
Of course, you can use release conan packages in your debug configuration, see below.
First, rename all sample_project
in file contents and file names to a project name you like. You can do this via the script rename.py
in script.py
folder:
python3 script/rename.py sample_project <new_project_name>
You can also do this to the sample C++ executable, header-only library and library:
python3 script/rename.py sample_app <new_app_name>
python3 script/rename.py sample_header_only_lib <new_header_only_lib_name>
python3 script/rename.py sample_lib <new_lib_name>
dirname(dirname(abspath(__file__))
). DON'T move the script to somewhere else.
Edit CMakeLists.txt
, add a line run_conan()
between include(sample_project_fetch_project_options)
and project(cpp_novice LANGUAGES CXX)
. That is:
cmake_minimum_required(VERSION 3.25)
list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
include(fix_msvc)
include(sample_project_options)
include(sample_project_fetch_project_options)
run_conan()
project(sample_project VERSION 0.0.1 LANGUAGES CXX)
By adding this line of code, we enable cmake to use conan automatically, all we need to do is to configure cmake as usual. For example:
cmake -B build -S .
See Conan Docs: Consuming packages for more help.
You can let conan try to guess the profile, based on the current operating system and installed tools:
conan profile detect --force
You can set environment variables CC
and CXX
to help conan find the correct compilers, for example in bash:
export CC="clang"
export CXX="clang++"
conan profile detect --force
In addition, in the conan/profiles
folder, I've provided some generic profiles for you (and for CI). You can use script/match_conan_profile.py
to find the best matching generic profile based on your query:
(See more details in conan/profiles/README.md.)
# "Usage: python3 script/match_conan_profile.py <conan_profile> (specified as <os>-<os_version>-<architecture>-<compiler>-<compiler_version>-<build_type>)"
python3 script/match_conan_profile.py "macos-#-armv8-clang-#-Debug" # `#` represents a wildcard character
However, it is highly recommended to write a conan profile manually instead of depending on the detected one. In the profile, you can set information like the operating system, compiler or build configuration.
For example, the following is my clang and gcc profile on MacOS m1: (see more in conan/profiles)
_common
for common profile settings
[settings]
arch={{ detect_api.detect_arch() }}
os={{ detect_api.detect_os() }}
build_type=Release
benchmark/*:build_type=Release
boost/*:compiler.cppstd=20
[platform_tool_requires]
cmake/3.29.3
ninja/1.12.1
[conf]
# &: influence only the current package but not any depedencies
# see more in https://docs.conan.io/2/reference/config_files/profiles.html#profile-patterns
&:tools.cmake.cmaketoolchain:generator=Ninja Multi-Config
clang
profile
include(_common)
{% set compiler, version, compiler_exe = detect_api.detect_clang_compiler("clang") %}
[settings]
compiler={{ compiler }}
compiler.cppstd=26
compiler.libcxx={{ detect_api.detect_libcxx(compiler, version, compiler_exe) }}
compiler.version={{ detect_api.default_compiler_version(compiler, version) }}
[conf]
tools.build:compiler_executables = {"c": "{{ compiler_exe }}", "cpp": "{{ compiler_exe | replace("clang", "clang++") }}"}
tools.build:cflags=['-L/opt/homebrew/opt/llvm/lib/c++', '-Wno-unused-command-line-argument']
tools.build:cxxflags=['-L/opt/homebrew/opt/llvm/lib/c++', '-Wno-unused-command-line-argument']
gcc
profile
include(_common)
{% set compiler, version, compiler_exe = detect_api.detect_gcc_compiler("gcc-14") %}
[settings]
compiler={{ compiler }}
compiler.cppstd=23
compiler.libcxx={{ detect_api.detect_libcxx(compiler, version, compiler_exe) }}
compiler.version={{ detect_api.default_compiler_version(compiler, version) }}
scnlib/*:compiler.cppstd=20
[conf]
tools.build:compiler_executables = {"c": "{{ compiler_exe }}", "cpp": "{{ compiler_exe | replace("gcc", "g++") }}"}
Use conan install -h
for help.
To install conan dependencies:
conan install . -pr <profile> -b missing
You can add -s build_type=[Release|Debug|MinSizeRel|RelWithDebInfo]
or other settings/configurations/options in the command line:
conan install . -pr <profile> -b missing -s build_type=Release
You can specify more than one profiles, to merge the profile settings:
conan install . -pr _common -pr gcc -b missing -s build_type=Release
You can specify build_type for some specific packages:
conan install . -pr _common -pr gcc -b missing -s build_type=Debug -s "opencv/*:build_type=Release" -s "&:build_type=Release"
After this, conan will generate CMakeUserPresets.json
for cmake.
Use cmake --help
for help.
List all available configure presets:
cmake --list-presets
Choose one to configure (preset clang
for instance):
cmake --preset clang
By default, cmake configures the project on user mode. For developers, you can switch to developer mode by:
cmake --preset clang -DENABLE_DEVELOPER_MODE:BOOL=ON
cmake --preset clang
ccmake --preset clang
Try it yourself.
Use cmake --build
and conan build -h
for help.
List all available build presets:
cmake --build --list-presets
Choose one to build (preset clang-debug
for instance):
cmake --build --preset clang-debug
List all available targets:
cmake --build --preset clang-debug -t help
Then build (targets app
and test_app
for instance):
cmake --build --preset clang-debug -t app test_app
Use ctest --help
for help.
List all available test presets:
ctest --list-presets
Choose one to test (preset clang-debug
for instance):
ctest --preset clang-debug
If fails, run the failed test with coloured output:
ctest --preset clang-debug --rerun-failed --output-on-failure
the install prefix defaults to
/usr/local
on UNIX andC:/Program Files/${PROJECT_NAME}
on Windows
Reconfigure to specify the install prefix if hasn't:
cmake --preset clang --install-prefix <directory>
Install:
cmake --build --preset clang-debug -t install
Use cmake --install
for help.
cmake --install <build_dir> [<options>]
If you use CMake with multi-config generators (like Ninja Multi-Config
, XCode
, Visual Studio
) and a LSP based on compile_commands.json
(like clangd, Qt Creator, CLion), please make sure to define CMAKE_CONFIGURATION_TYPES
yourself and install conan packages for all configuration types.
For example, if you're setting cmake <other args> "-DCMAKE_CONFIGURATION_TYPES=Release;Debug"
, you should install conan packages for both Release
and Debug
configuration types.
Why? When using cmake with multi-config-generators, cmake merges compile flags in all configuration types into a single compile_commands.json
file, and this project template uses Release;Debug;RelWithDebInfo;MinSizeRel
by default. If you only install conan packages for Release
configuration, your LSP may be confused: while your Release
configuration includes conan packages installed, your compile flags in Debug
/RelWithDebInfo
/MinSizeRel
configurations includes nothing!
Of course, you could use Release
conan packages in Debug
/RelWithDebInfo
/MinSizeRel
conan packages, or vice versa. See here.
See Conan Docs: Creating packages and Conan Docs: Developing packages locally for more help.
You can make use of conan commands to simplify CI and so on.
- install dependencies:
conan install <args>
- install dependencies and build:
conan build <args> -c tools.build:skip_test=True
- install dependencies, build and test:
conan build <args>
- install, build, test and package project:
conan create <args>
- pacakge built project:
conan export-pkg <args>
⚠️ Not working, you need to writepacakge()
andpacakge_id()
methods in conanfile.py