CMake

Tutorials:

The Hierarchy

Compilers: Source code -> Machine code

Build Systems: Help craft compiler command for specific platform

Build System Generators: generate build systems (usually Makefile)

Flags

-D[Options]: replace options defined in CMakeLists.txt

Functions

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.

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.

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@)

find_library: manually add library by specifying path find_package: automatically add library automatically without specifying path

Input Variables

CMAKE_SOURCE_DIR: OSBitness: 32bit or 64bit address to compile?

Output Variables

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

Examples

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