Tutorials:
Compilers: Source code -> Machine code
Preprocessor: process #IFDEF #END
Compiler: Source code to human-readable assembly
e.g.: GCC, CLang, MSVC
Build Systems: Help craft compiler command for specific platform
make, Makefile), Ninja (ninja build), Apache Ant (ant compile), XCode (.xcodeproj), Microsoft Visual Studio (.vcxproj)Build System Generators: generate build systems (usually Makefile)
cmake, CMakeLists.txt)-D[Options]: replace options defined in CMakeLists.txt
function and macro: ways to define functions. macro is similar to function but does not create new scope
project(${name}): set variable PROJECT_NAME to ${name}
add_executable(<target> ${main.cpp}): make ${main.cpp} an executable named <target>
add_library(<target> ${main.cpp}): make ${main.cpp} a non-executable named <target>
install(TARGETS <target> DESTINATION ${bin}): output Makefile so that when you run make install, <target> will be copied to ${bin} after <target> is built.
install(TARGETS <target> LIBRARY DESTINATION ${lib} PUBLIC_HEADER DESTINATION ${include}): same as above, but also copy header file to make it a library.
add_subdirectory(<dir>): add a path where additional CMakeLists.txt might be located. it will stop current task and run cmake there first. Changes to variables in the subdirectory do not affect the parent unless specifically cached or defined as PARENT_SCOPE. Used for adding interdependent targets.
include(): similar to add_subdirectory, but does not create new scopes; the variables and commands defined in the included file are processed in the context of the calling CMake file. Used for including reusable components: common dependencies, compiler flags, macros.target_link_directories(<target> <INTERFACE|PUBLIC|PRIVATE> ${lib_path}): where to find libraries header(include) during linking (only needed if not "installed" in standard path). You should avoid using it as we don't encourage non-standard path and so target_link_libraries is generally better alternative. Might be necessary though if you are doing RPATH stuff.
target_link_libraries(my_app PRIVATE my_library) can be used if my_library is a STATIC IMPORTED library target created using add_library(). You can customize location with set_target_properties(my_library PROPERTIES IMPORTED_LOCATION "/path/to/libmy_library.a" INTERFACE_INCLUDE_DIRECTORIES "/path/to/includes")
target_link_libraries(my_app PRIVATE MyLibrary::MyLibrary) can be used after find_package() or find_library().
if you are using Conan, vcpkg, or CPM.cmake generated target, you can use target_link_libraries directly
set_target_properties(<target> PROPERTIES PUBLIC_HEADER <file>): output header file for making library
target_link_libraries(<target> ${internal_lib_name}): link ${internal_lib_name} to <target>. If ${internal_lib_name} is a target name, the target name must be created by add_library(). If the target library already has header file copied by target_include_directories(), <target> will inherit its header file and you don't need to call target_include_directories again for <target>
target_include_directories(<target> <dir>): copy include files from this directory. (Note: you don't need this if target_link_libraries or target_link_directories are already doing it)
configure_file(<input> <output>): take in <input> file (C content) and transform it according to some CMake rules and output to <output> (most useful when outputing version to a header file, from *.h.in to *.h using @XXX_VERSION_MAJOR@)
add_compile_definitions: set directory-scoped macro value, less powerful but cleaner than configure_filefind_library: manually add library by specifying path
find_package: automatically add library automatically without specifying path
CONFIG mode: require config.cmake file on Windows? only need package to be apt installed
MODULE mode: require set(CMAKE_MODULE_PATH <path>) and a Find<Library>.cmake file inside <path>. If your library is popular, cmake might have Find<Library>.cmake built in and if so you can just find_package(Git) for example. Every builtin find_package is different, see documentation for its behavior.
Whether to use CONFIG or MODULE and how to target_link_libraries for libraries other people created should according to library documentation. You might need other things like target_compile_definitions and target_include_directories (e.g. Vulkan port doesn't copy header, only verify existence).
mode: by default, MODULE mode, if not found, then CONFIG mode.
CMAKE_SOURCE_DIR:
OSBitness: 32bit or 64bit address to compile?
CMAKE_ARCHIEVE_OUTPUT_DIRECTORY: where to output statically linked library
CMAKE_LIBRARY_OUTPUT_DIRECTORY:
CMAKE_RUNTIME_OUTPUT_DIRECTORY:
CMAKE_SIZEOF_VOID_P: if it is 8, then we are on 64 OSBitness
Making a library
cmake_minimum_required(VERSION 3.0)
project(MyLibrary)
# add source
set(SOURCES
src/foo.cpp
src/bar.cpp
) # or use file(GLOB_RECURSE SOURCES "src/*.cpp")
add_library(MyLibrary ${SOURCES}) # create a TARGET that is a library
# add header
target_include_directories(MyLibrary PUBLIC include) # you don't need this if:
# 1. Header Files in Source Directory
# 2. Global Include Directories with `include_directories`
# 3. include are inherited from the linked target using `target_link_libraries`
# output header
set(PUBLIC_HEADERS
include/mylib.h
include/mylib_utils.h
)
set_target_properties(MyLibrary PROPERTIES PUBLIC_HEADER "${PUBLIC_HEADERS}")
# or target_sources(MyLibrary PRIVATE ${PUBLIC_HEADERS})
# or file(GLOB PUBLIC_HEADERS "include/*.h")
# output library and header to default installation path
install(TARGETS MyLibrary
LIBRARY DESTINATION lib
PUBLIC_HEADER DESTINATION include
)
Making a Executable That Use Library
cmake_minimum_required(VERSION 3.0)
project(MyProgram)
add_executable(MyProgram main.cpp) # create a TARGET that is a executable (and you should also list other files without `main()`)
# target_link_directories(MyProgram PRIVATE path) not needed if library in default installation path
target_link_libraries(MyProgram MyLibrary)
Table of Content