Quick Start

cmake 最低版本
cmake project名称,CXX意思是c++
add_executable 创建可执行程序

1
2
3
4
5
6
7
8
9
cmake_minimum_required(VERSION 3.10)
project(project_name CXX)

add_executable(exec_name
sorce
file
list
)

简单的程序,输出程序名和项目名一样,直接用宏PROJECT_NAME做名字也行

1
2
project (hello_cmake)
add_executable(${PROJECT_NAME} main.cpp)

设置编译参数

1
2
3
4
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3 -fPIC -std=c++11")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -O0 -g")
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -O0")

变量

使用目录变量来指定文件

More

  • CMAKE_SOURCE_DIR The root source directory
  • CMAKE_CURRENT_SOURCE_DIR The current source directory if using sub-projects and directories.
  • PROJECT_SOURCE_DIR The source directory of the current cmake project.
  • CMAKE_BINARY_DIR The root binary / build directory. This is the directory where you ran the cmake command.
  • CMAKE_CURRENT_BINARY_DIR The build directory you are currently in.
    -PROJECT_BINARY_DIR The build directory for the current project.

设置变量set

1
2
3
4
5
set(
HELLO_SOURCE_FILE
${PROJECT_SOURCE_DIR}/src/main.cpp
${PROJECT_SOURCE_DIR}/include/main.h
)

现代CMake不推荐使用set直接设置源文件变量,直接使用add_xxx函数会更加方便。

String and list

1
2
set(MyString "Hello world")
set(MyList Hello world)

List append something

1
LIST(APPEND MyList append_value1 append_value2 append_value3)

获取目录下所有文件aux_source_directory,参数第一个是目标目录,第二个是list名,得到一个list ${SRC_HELLO_FILES}

1
aux_source_directory(${CMAKE_SOURCE_DIR}/src/hello_dir SRC_HELLO_FILES)

头文件

头文件和源文件不在一起,用target_include_directories指定header files。(PRIVATE意思是私有范围,此include不会被include到其他target)

1
2
3
4
5
target_include_directories(
hello_cmake
PRIVATE
${PROJECT_SOURCE_DIR}/include
)

作用域:

  • PRIVATE 目录被添加到目标的包含目录中
  • INTERFACE 目录被添加所有链接这个库的目标的包含目录
  • PUBLIC 综合PRIVATE和PUBLIC,目录被添加到目标包含目录和链接这个库的目标的包含目录

add_executabel一样,输出一个binary,但是这个binary是一个lib,并且多了第二个参数是 STATIC静态库/SHARED动态库。后面是源文件list

1
2
3
4
add_library(hello_library
STATIC
src/hello.cpp
)

add_library后,就可以操作hello_library了

1
2
3
4
5
target_include_directories(
hello_library
PUBLIC
${PROJECT_SOURCE_DIR}/include
)

使用PUBLIC会导致其中的包含目录用于以下地方:

  • 编译这个库时。
  • 编译链接了这个库的目标时。

然后把executable链接到库

1
2
3
4
5
6
7
add_executable(hello_binary
src/main.cpp
)
target_link_libraries(hello_binary
PRIVATE
hello_library
)

message

输出一个字符串/变量

1
message("hello world")

dependencies

add_subdirectory vs include

添加子目录,子目录中也要有一个cmake,可以作为一个被引用的项目
include 的文件位置无要求,可以在项目外

1
2
add_subdirectory(sub_hello_world)
include(${CMAKE_DIR}/test.cmake)

find_package

find_package查找指定package,可以不加REQUIRED

1
find_package(OpenCV REQUIRED)

find_package结果在OpenCV_FOUND

Regardless of the mode used, a _FOUND variable will be set to indicate whether the package was found. When the package is found, package-specific information may be provided through other variables and Imported Targets documented by the package itself. The QUIET option disables informational messages, including those indicating that the package cannot be found if it is not REQUIRED. The REQUIRED option stops processing with an error message if the package cannot be found.

查找package除了一些PATH,还可以指定目录
search 顺序(部分,具体看文档)

  1. package_ROOT (new in VERSION 3.12)
  2. cmake-specific variables
    • CMAKE_PREFIX_PATH
    • CMAKE_FRAMEWORK_PATH
    • CMAKE_APPBUNDLE_PATH
  3. package_DIR
  4. PATH

FetchContent

cmake version > 3.11

FetchContent可以拉取依赖,可以是来自目录,可以来自link,可以来自git,可以是个zip

1
2
3
4
5
6
7
8
9
10
11
12
FetchContent_Declare(
googletest
GIT_REPOSITORY https://github.com/google/googletest.git
GIT_TAG 703bd9caab50b139428cea1aaff9974ebee5742e # release-1.10.0
)
FetchContent_Declare(
myCompanyIcons
URL https://intranet.mycompany.com/assets/iconset_1.12.tar.gz
URL_HASH MD5=5588a7b18261c20068beabfb4f530b87
)

FetchContent_MakeAvailable(googletest myCompanyIcons)

macro

macro,可以当作定义函数用

1
2
3
4
5
6
7
8
9
10
11
12
13
macro(ncnn_add_example name)
add_executable(${name} ${name}.cpp)
if(OpenCV_FOUND)
target_include_directories(${name} PRIVATE ${OpenCV_INCLUDE_DIRS})
target_link_libraries(${name} PRIVATE ncnn ${OpenCV_LIBS})
elseif(NCNN_SIMPLEOCV)
target_compile_definitions(${name} PUBLIC USE_NCNN_SIMPLEOCV)
target_link_libraries(${name} PRIVATE ncnn)
endif()

# add test to a virtual project group
set_property(TARGET ${name} PROPERTY FOLDER "examples")
endmacro()

使用如ncnn_add_example(yolo)

Macro vs Function

逻辑

设置一个Option,三个参数:option name,help string,default value(ON/OFF)

1
OPTION(MY_CUSTOM_OPTION "HINT, help string for this option" ON)

if(变量/OPTION)

1
2
3
if(MY_CUSTOM_OPTION)
# do something
endif()