CMake

  • in-source make
  • out-of-source make

Write Basic CMakeLists.txt

  • common head

    1
    2
    PROJECT(projectname [CXX] [C] [Java]) # project name
    cmake_minimum_required(VERSION 2.8.12) # minimum cmake version
  • variable assignment

    1
    SET(VAR [VALUE] [CACHE TYPE DOCSTRING [FORCE]])

    variable should be used by ${VAR} except for IF condition.
    commonly used path variables are listed as follows:

    1
    2
    3
    4
    <projectname>_BINARY_DIR = PROJECT_BINARY_DIR=CMAKE_BINARY_DIR
    <projectname>_SOURCE_DIR = PROJECT__SOURCE_DIR=CMAKE_SOURCE_DIR
    SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)
    SET(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib)
  • display message

    1
    MESSAGE([SEND_ERROR | STATUS | FATAL_ERROR] "message to display")
  • generate output binary/library

    1
    2
    3
    4
    5
    6
    7
    8
    ADD_EXECUTABLE(hello ${SRC_LIST})
    ADD_LIBRARY(libname [SHARED|STATIC|MODULE] [EXCLUDE_FROM_ALL] source1 source2 ... sourceN)
    TARGET_LINK_LIBRARIES(target library1 <debug | optimized> library2 ...) /#target-specific

    // change the name, version, and so on of the output (*e.g.*, library, binary)
    SET_TARGET_PROPERTIES(target1 target2 ...
    PROPERTIES prop1 value1
    prop2 value2 ...)

Finding

  • search source

    1
    2
    INCLUDE_DIRECTORIES([AFTER|BEFORE] [SYSTEM] dir1 dir2 ...) #include files
    LINK_DIRECTORIES(directory1 directory2 ...)

    CMAKE_INCLUDE_PATH, CMAKE_LIBRARY_PATH, CMAKE_MODULE_PATH are environment variables instead of CMake variables. when using FIND_***, CMAKE_INCLUDE_PATH, the above paths will be searched.

    1
    2
    3
    4
    FIND_PATH(myHeader hello.h)
    IF(myHeader)
    INCLUDE_DIRECTORIES(${myHeader})
    ENDIF(myHeader)
  • search commands

    1
    2
    3
    4
    5
    FIND_FILE(<VAR> name1 path1 path2 ...)
    FIND_LIBRARY(<VAR> name1 path1 path2 ...)
    FIND_PATH(<VAR> name1 path1 path2 ...)
    FIND_PROGRAM(<VAR> name1 path1 path2 ...)
    FIND_PACKAGE(<name> [major.minor] [QUIET] [NO_MODULE] [[REQUIRED|COMPONENTS] [componets...]]) # find \*.cmake

Compactness

  • include the content of other files

    1
    include(FILE) # load the content of FILE
  • hierarchical binary tree

    1
    ADD_SUBDIRECTORY(source_dir [binary_dir][EXCLUDE_FROM_ALL])
  • macro definition

    1
    2
    3
    4
    MACRO(add_example name)
    ADD_EXECUTABLE(${name} ${name}.cpp)
    TARGET_LINK_LIBRARIES(${name} dlib::dlib )
    ENDMACRO()

CMake Module

  • define FindHELLO.cmake module
    1
    2
    3
    4
    5
    6
    7
    8
    FIND_PATH(HELLO_INCLUDE_DIR hello.h /usr/include/hello /usr/local/include/hello)
    FIND_LIBRARY(HELLO_LIBRARY NAMES hello PATH /usr/lib/usr/local/lib)
    IF (HELLO_INCLUDE_DIR AND HELLO_LIBRARY)
    SET(HELLO_FOUND TRUE)
    ENDIF (HELLO_INCLUDE_DIR AND HELLO_LIBRARY)
    IF (HELLO_FOUND)
    IF (NOT HELLO_FIND_QUIETLY)
    MESSAGE(STATUS "Found Hello: ${HELLO_LIBRARY}")

Installation

cmake -DCMAKE_INSTALL_PREFIX=/usr # the default install target is /usr/local

  • install library and binary

    1
    2
    3
    4
    5
    6
    7
    8
    9
    INSTALL(TARGETS targets...
    [[ARCHIVE|LIBRARY|RUNTIME]
    [DESTINATION <dir>]
    [PERMISSIONS permissions...]
    [CONFIGURATIONS
    [Debug|Release|...]]
    [COMPONENT <component>]
    [OPTIONAL]
    ] [...])

    ARCHIVE is static library *.a; LIBRARY is dynamic library *.so; RUNTIME is executable binary

  • install regular file

    1
    2
    3
    4
    5
    INSTALL(FILES files... DESTINATION <dir>
    [PERMISSIONS permissions...]
    [CONFIGURATIONS [Debug|Release|...]]
    [COMPONENT <component>]
    [RENAME <name>] [OPTIONAL])
  • install script file (e.g., *.sh), almost the same with installing files except for permission

    1
    2
    3
    4
    5
    INSTALL(PROGRAMS files... DESTINATION <dir>
    [PERMISSIONS permissions...]
    [CONFIGURATIONS [Debug|Release|...]]
    [COMPONENT <component>]
    [RENAME <name>] [OPTIONAL])
  • install folders

    1
    2
    3
    4
    5
    6
    7
    8
    INSTALL(DIRECTORY dirs... DESTINATION <dir>
    [FILE_PERMISSIONS permissions...]
    [DIRECTORY_PERMISSIONS permissions...]
    [USE_SOURCE_PERMISSIONS]
    [CONFIGURATIONS [Debug|Release|...]]
    [COMPONENT <component>]
    [[PATTERN <pattern> | REGEX <regex>]
    [EXCLUDE] [PERMISSIONS permissions...]] [...])
  • install *.cmake

    1
    INSTALL([[SCRIPT <file>] [CODE <code>]] [...])

Testing

1
2
ADD_TEST(mytest ${PROJECT_BINARY_DIR}/bin/main)
ENABLE_TESTING()

After generating Makefile, run make test