cmake
Syntax
  • #, comment
  • ${var}, access value defined in the variable "var"
  • CMake Directory Variables
  • CMAKE_SOURCE_DIR, the directory that contains the top-level CMakeLists.txt file
  • CMAKE_CURRENT_SOURCE_DIR, the directory containing the CMakeLists.txt file that is currently being processed
  • CMAKE_BINARY_DIR, the path to the top level of the build tree
  • CMAKE_CURRENT_BINARY_DIR, the path to the binary directory currently being processed
  • PROJECT_SOURCE_DIR, top level source directory for the current project
  • projectName_SOURCE_DIR, source directory for the named project
  • PROJECT_BINARY_DIR, top level binary directory for the current project
  • projectName_BINARY_DIR, binary directory for the named project
  • CMAKE_C_COMPILER, C compiler
  • CMAKE_CXX_COMPILTER, C++ compiler
  • CMAKE_C_FLAGS, C flags
  • CMAKE_CXX_FLAGS, C++ flags
  • EXECUTABLE_OUTPUT_PATH, output path for executable program
  • LIBRARY_OUTPUT_PATH, output path for libraries
  • CMAKE_BUILD_TYPE, figure out build type, [Debug|Release]
  • BUILD_SHARED_LIBS, figure out library build model, [OFF|ON]
  • Example 1

    // main.c
    #include <stdio.h>
    
    int main()
    {
    	printf("Hello World!\n");
    
    	return 0;
    }
    		
    // CMakeLists.txt 1
    cmake_minimum_required (VERSION 2.6)
    project (Hello)
    add_subdirectory(src)
    		
    // CMakeLists.txt 2
    add_executable(Hello main.c)
    		
  • cd build
  • cmake ..
  • make, generate executable file "Hello" in build/src
  • Example 2

    // util.h
    #ifndef UTIL_H
    #define UTIL_H
    
    void hello();
    void world();
    void disp();
    
    #endif
    		
    // hello.c
    #include <stdio.h>
    #include "util.h"
    
    void hello()
    {
    	printf("Hello ");
    }
    		
    // util.c
    #include <stdio.h>
    #include "util.h"
    
    void disp()
    {
    	hello();
    	world();
    }
    		
    // world.c
    #include <stdio.h>
    #include "util.h"
    
    void world()
    {
    	printf("World!\n");
    }
    		
    // main.c
    #include <util.h>
    #include "util.h"
    
    int main()
    {
    	disp();
    
    	return 0;
    }
    		
    Using include_directories
    # CMakeLists.txt 1
    cmake_minimum_required(VERSION 2.6)
    
    project(c1)
    
    include_directories(${PROJECT_SOURCE_DIR}/include) # add before adding subdirectory
    add_subdirectory (src)
    
    add_executable(Hello main.c)
    target_link_libraries(Hello mylib)
    		
    # CMakeLists.txt 2
    aux_source_directory(. SRC_LIST)
    add_library(mylib ${SRC_LIST})
    		
    Using target_include_directories
    # CMakeLists.txt 1
    cmake_minimum_required(VERSION 2.6)
    
    project(c1)
    
    add_subdirectory (src)
    
    add_executable(Hello main.c)
    target_include_directories (Hello PUBLIC ${PROJECT_SOURCE_DIR}/include)
    target_link_libraries(Hello mylib)
    		
    # CMakeLists.txt 2
    aux_source_directory(. SRC_LIST)
    add_library(mylib ${SRC_LIST})
    target_include_directories(mylib PUBLIC ${PROJECT_SOURCE_DIR}/include)
    		
  • cd build
  • cmake ..
  • make, generate executable file "Hello" in build, generate libmylib.a in build/src
  • Example 3

    // hello.h
    #ifndef HELLO_H
    #define HELLO_H
    
    void hello();
    
    #endif
    		
    // util.h
    #ifndef UTIL_H
    #define UTIL_H
    
    void disp();
    
    #endif
    		
    // world.h
    #ifndef WORLD_H
    #define WORLD_H
    
    void world();
    
    #endif
    		
    // main.c
    #include "util.h"
    
    int main()
    {
    	disp();
    
    	return 0;
    }
    		
    // util.c
    #include <stdio.h>
    #include "util.h"
    #include "hello.h"
    #include "world.h"
    
    void disp()
    {
    	hello();
    	world();
    }
    		
    // hello.c
    #include <stdio.h>
    #include "hello.h"
    
    void hello()
    {
    	printf("Hello ");
    }
    		
    // world.c
    #include <stdio.h>
    #include "world.h"
    
    void world()
    {
    	printf("World!\n");
    }
    		
    # CMakeLists.txt 1
    cmake_minimum_required(VERSION 2.6)
    
    project(c3)
    
    include_directories(${PROJECT_SOURCE_DIR}/include)
    add_subdirectory (src)
    		
    # CMakeLists.txt 2
    aux_source_directory(. SRC_LIST)
    
    add_subdirectory(hello)
    add_subdirectory(world)
    
    add_executable(Hello.e ${SRC_LIST})
    target_link_libraries(Hello.e hello world)
    		
    # CMakeLists.txt 3
    aux_source_directory(. HELLO_LIST)
    add_library(hello ${HELLO_LIST})
    		
    # CMakeLists.txt 4
    aux_source_directory(. WORLD_LIST)
    add_library(world ${WORLD_LIST})
    		
  • cd build
  • cmake ..
  • make, generate executable file "Hello.e" in build/src, generate libhello.a in build/src/hello, generate libworld.a in build/src/world
  • Example 4

    Code is same as above
    // CMakeLists.txt 1
    cmake_minimum_required(VERSION 2.6)
    
    project(c3)
    
    include_directories(${PROJECT_SOURCE_DIR}/include)
    add_subdirectory (src)
    		
    // CMakeLists.txt 2
    aux_source_directory(. SRC_LIST)
    
    add_subdirectory(hello)
    add_subdirectory(world)
    add_subdirectory(util)
    
    add_executable(Hello.e ${SRC_LIST})
    target_link_libraries(Hello.e util)
    		
    // CMakeLists.txt 3
    aux_source_directory(. UTIL_LIST)
    
    add_library(util ${UTIL_LIST})
    target_link_libraries(util hello world)
    		
    // CMakeLists.txt 4
    aux_source_directory(. HELLO_LIST)
    add_library(hello ${HELLO_LIST})
    		
    // CMakeLists.txt 5
    aux_source_directory(. WORLD_LIST)
    add_library(world ${WORLD_LIST})
    		
    It is like the code is organized as the following

    Functions
  • cmake_minimum_required(VERSION major.minor), set the minimum required version of cmake
  • project(name, version, language), set a name, version, and enable languages for the entire project
  • aux_source_directory(dir, var), collects the names of all the source files in the specified directory and stores the list in the "var" provided, "var" should be unique
  • add_library(libName, [STATIC|SHARED|MODULE], source)
  • add_executable(name, source), add an executable to the project using the specified source files
  • add_subdirectory(dir), add a subdirectory to the build
  • include_directories(dir), add the given directories to those the compiler uses to search for include files, relative paths are interpreted as relative to the current source directory, affects directory scope, all targets in this CMakeList, as well as those in all subdirectories added after the point of its call
  • target_include_directories(target, INTERFACE|PUBLIC|PRIVATE, dir), specify include directories or targets to use when compiling a given target
  • set(variable, value), set a CMake, cache or environment variable to a given value
  • file(GLOB variable value), GLOB will generate a list of all files that match the globbing expressions and store it into the variable
  • file(GLOB_RECURSE variable value), traverse all the subdirectories of the matched directory and match the files
  • find_library(variable libName), this command is used to find a library
  • target_link_libraries(target libName), specify libraries or flags to use when linking a given target, cmake like to use full path of libraries
  • message("Code: " ${c_files}), print information
  • Publish

    // test.c
    #include "util.h"
     
    int main()
    {
    	disp();
     
    	return 0;
    }
    		
    # CMakeLists.txt 1
    # set up the minimum version of camke
    cmake_minimum_required(VERSION 2.6)
    
    # project name
    project(c6)
    
    # set up the path for compiled static libraries and dynamic library
    set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/build/lib)
    set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/build/bin)
    
    # figure out the path of header files
    include_directories(${PROJECT_SOURCE_DIR}/include)
    
    # figure out the path of compiled libries
    link_directories(${PROJECT_SOURCE_DIR}/build/lib)
    
    # add sub directories
    add_subdirectory(src)
    add_subdirectory(test)
    
    # set up install directory, default is /usr/local
    # set(CMAKE_INSTALL_PREFIX ${PROJECT_SOURCE_DIR}/install)
    
    # copy readme.md and license to the install directory
    file(COPY ${PROJECT_SOURCE_DIR}/README.md DESTINATION ${CMAKE_INSTALL_PREFIX})
    file(COPY ${PROJECT_SOURCE_DIR}/LICENSE DESTINATION ${CMAKE_INSTALL_PREFIX})
    		
    # CMakeLists.txt 2
    # recursive search *.c file and save names to a variable
    file(GLOB_RECURSE c_files "*.c")
    
    # turn off MACOSX_RPATH warning
    set(CMAKE_MACOSX_RPATH 1)
    # create a static library "libhelloworld.a" and a dynamic library "libhelloworld.so"
    # dynamic library will be "libhelloworld.dylib" on Mac
    add_library(helloworld_lib_shared  SHARED ${c_files})
    add_library(helloworld_lib_static STATIC ${c_files})
    set_target_properties(helloworld_lib_shared PROPERTIES OUTPUT_NAME "helloworld")
    set_target_properties(helloworld_lib_static PROPERTIES OUTPUT_NAME "helloworld")
    set_target_properties(helloworld_lib_shared PROPERTIES VERSION 1.2 SOVERSION 1)
    
    # create an executable program
    add_executable(Hello.e main.c)
    target_link_libraries(Hello.e helloworld)
    
    # install executable program to folder "bin" in the install directory
    # install dynamic library to folder "lib" in the install directory
    # install static library to folder "lib" in the install directory
    INSTALL(TARGETS Hello.e helloworld_lib_shared helloworld_lib_static
    	RUNTIME DESTINATION bin
         	LIBRARY DESTINATION lib
         	ARCHIVE DESTINATION lib)
    
    # install header files to folder "include" in the install directory
    INSTALL(DIRECTORY ${PROJECT_SOURCE_DIR}/include/ DESTINATION include)
    		
    # CMakeLists.txt 3
    # recursively find *.c files
    file(GLOB_RECURSE c_files *.c)
    # print out a list of source files
    message("test code: " ${c_files})
    
    # create executable test program
    add_executable(mytest ${c_files})
    target_link_libraries(mytest helloworld)
    
    # install executable test program to folder "bin" in the install directory
    INSTALL(TARGETS mytest
    	RUNTIME DESTINATION bin)
    		
  • cd build
  • cmake ..
  • make, generate executable files in build/src, generate libraries in build/lib
  • make install, install executable programs to inallPath/bin, install libraries to installPath/lib, install header files to installPath/include
  • General
  • How to collect source files with CMake without globbing?
  • Install to a different directory
  • CMake-GUI

  • Download
  • Reference
  • IBM Tutorial
  • Documentation
  • Brief Tutorial