CMake

Documentation is for the weak


CMake is cross-platform build system that use textfiles to create the platform dependent project files.

How to run cmake from commandline

In the directory where you wish to have all your solutions files created run cmake with the generator-name command (-G) and the path to the cmake config file you wish to use. List of generators.

cmake -G "Visual Studio 12" ../src

cmake_minimum_required

cmake_minimum_required sets the the minimum required version of cmake for a project. The command also implicitly invokes the cmake_policy command so cmake behavior is as the requested version was used.

cmake_minimum_required(VERSION 3.11)

    • Scope

      • CMake has a directory-based scoping. Setting a variable in a cmakelist file will set the variable for that file and for all subdirectories.

      • Cmake functions have their own scope, macros do not.

    • Control Flow

      • Cmake flow blocks do not have their own scope. Variables set inside persist after the endif().

      • if, elseif, else, endif:

      • foreach, endforeach

      • while, endwhile:

    • Variables

      • To set a variable use the set command.

      • To dereferences a variable wrap it in ${}.

      • Use PARENT_SCOPE to set the a variable into the parent scope instead of the current scope.

      • Use CACHE to set the variable in the cmake cache. It will not be set if already exist.

      • Use FORCE to force set it in the cache even if it exist.

set(var_name "Hello world")

Display a message

Use the message command to display information to the poor person that try to use your cmake file. The first parameter is the mode and there are a number to choose from such as STATUS, WARNING and FATAL_ERROR.

message(STATUS "Using libs from: ${EXTERNAL_DEPENDENCIES_PATH}")

Solution folders

To enable the use of Solution folders set the global property USE_FOLDERS to ON. Then for each target set the property FOLDER to select what folder or sub folder to put the project in.

SET_PROPERTY(GLOBAL PROPERTY USE_FOLDERS ON)

SET_PROPERTY(TARGET physics PROPERTY FOLDER "Engine")

Custom build types (configurations)

Use CMAKE_CONFIGURATION_TYPES to specify your own custom configuration names. You can then specify per-config properties and variables in the form SOME_VAR_<CONFIG>. So the Developer config properties for CMAKE_RUNTIME_OUTPUT_DIRECTORY can be set with CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEVELOPER. The default configs are DEBUG, RELEASE, MINSIZEREL and RELWITHDEBINFO.

set(CMAKE_CONFIGURATION_TYPES Debug Developer Release CACHE TYPE INTERNAL FORCE)

Create the project

Create the project with the name project() command. It will set the name of the IDE files generated.

project("ZeroFps")

Local Options

For custom options use include() with OPTIONAL. The file can then contain all the custom variables the user wish to add.

include("zerofps_options.txt" OPTIONAL)

Detect 32 vs 64 bit Build

To detect if it's a 32 bit or 64 bit build check the size of CMAKE_SIZEOF_VOID_P. It will be 8 in 64 bit and 4 in 32 bit.

if(CMAKE_SIZEOF_VOID_P MATCHES 8)

MESSAGE(STATUS "Detected 64-bit platform")

else()

MESSAGE(STATUS "Detected 32-bit platform")

endif()

Write to a .bat File

To write to files use the file manipulation command. WRITE creates (overwrites) to a file. APPEND writes more data at the end of a file.

FILE(TO_NATIVE_PATH ${QT_ROOT_PATH} QT_ROOT_PATH)

set(GET_QT_BIN ${EXECUTABLE_OUTPUT_PATH}/_getqt.bat)

file(WRITE ${GET_QT_BIN} "copy ${QT_ROOT_PATH}\\QtCore4.dll .\n")

file(APPEND ${GET_QT_BIN} "copy ${QT_ROOT_PATH}\\QtGui4.dll .\n")

Select Source Files

With the file commands GLOB and GLOB_RECURSE one can get a list of all the files of selected types from a directory and it's sub directory's. Another way is to use the list commands to APPEND the names one select to the list. The list or lists are then used when creating a target, like a exe (see topic below).

file(GLOB EXULT_EXULT_SRC *.cc *.h)

file(GLOB_RECURSE EXULT_FILES_SRC files/*.cc files/*.h)

list(APPEND EXPACK_SRC

files/zip/zip.*

files/zip/unzip.*

data/crc.h

)

Source Folders in a target

To sort files inside sub folders of a target use SOURCE_GROUP. First is the folder and next is the directory name of the source files.

SOURCE_GROUP(views\\ssuw ../views/ssuw)

SOURCE_GROUP(widgets REGULAR_EXPRESSION .*/widgets/.*)

Create a target

A target is file you wish to build from your source code. Each target needs a name that is unique within a project, it will be used as the name of any project file and the name of the file created.

    • add_executable: Creates a executable target.

    • add_library: Create a library target. Listt the type as STATIC, SHARED, or MODULE.

    • add_custom_target: Create a custom build target that do not generate a output file but will always be build. It can run custom commands and sources can be added for convenience in editing them from the IDE even if they have no build rules.

    • add_subdirectory : Includes a cmake file in the selected subdirectory.

add_executable(zerofps ${SRC_FILES})

add_library(component STATIC ${SRC_FILES})

add_subdirectory(graymer)

add_custom_target(

exult_flx

COMMAND nmake /f $(solutionDir)../vs12/Makefile.data build_ex /NOLOGO

WORKING_DIRECTORY ../

SOURCES ${EXULTFLX_SRC} )

Build settings

There are two ways to set the settings for the build, by directory or by target. The target is the more modern way introduced with cmake 3.0 and should be the prefered one. Each command below has two versions, the target one listed first and then the directory based one.

  • For definitions Use the syntax VAR or VAR=value.

  • Relative paths are interpreted as relative to the current source directory.

  • target_compile_options / add_compile_options : Add options to send to the compiler.

  • target_compile_definitions / add_compile_definitions : Add preprocessor definitions to be set by the compiler.

  • target_compile_features / : Add expected compiler features to a target.

    • Select c++ standard with: cxx_std_98, cxx_std_11, cxx_std_14, cxx_std_17 or cxx_std_20.

  • target_include_directories / include_directories : Add directories to those the compiler uses to search for include files.

  • target_link_options / add_link_options : Add options to the link step.

  • target_link_libraries / link_libraries : Link selected libraries .

  • target_link_directories / link_directories : Adds the paths in which the linker should search for libraries.

ADD_DEFINITIONS(-DWIN32_LEAN_AND_MEAN)

ADD_DEFINITIONS(-DZEROFPS_PATH="${ZEROFPS_PATH}")

set(CMAKE_CXX_FLAGS "/D CONFIG_RELEASE /D NDEBUG /MD /O2 /GL")

set(CMAKE_EXE_LINKER_FLAGS "/INCREMENTAL:NO /LTCG")

include_directories(${EXTERNAL_DEPENDENCIES_PATH}/win32/include)

link_directories(${EXTERNAL_DEPENDENCIES_PATH}/win32/lib)

Set Target Build Settings

To change the settings of a selected target use the SET_TARGET_PROPERTIES command.

SET_TARGET_PROPERTIES(expack PROPERTIES COMPILE_FLAGS "/FImsvc_kludges.h")

SET_TARGET_PROPERTIES(exult PROPERTIES COMPILE_DEFINITIONS "EXULT")

Select where to put built files

The four kinds of built files are Archive (.lib), library, runtime (.exe/.dll) and pdb (.pdb files for for visual studio). There is one CMAKE variable for each. When a target is created they will be used to initialize the target property with the same name without the CMAKE_ at the start. So a .exe will have a RUNTIME_OUTPUT_DIRECTORY property.

.lib CMAKE_ARCHIVE_OUTPUT_DIRECTORY

.dll CMAKE_LIBRARY_OUTPUT_DIRECTORY

.exe CMAKE_RUNTIME_OUTPUT_DIRECTORY

.pdb CMAKE_PDB_OUTPUT_DIRECTORY

There is also configuration variables for each of them that have the same name but with _[CONFIG] in the end. So if there is a config called Fish there will be a

CMAKE_RUNTIME_OUTPUT_DIRECTORY_FISH. Multi-configuration generators (like visual studio) append a per-configuration subdirectory to CMAKE_RUNTIME_OUTPUT_DIRECTORY but not to MAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE.

Change settings on a target

set_target_properties( targets PROPERTIES RUNTIME_OUTPUT_DIRECTORY "zerofps/bin")

Reference