注:一般Cmake编译会用out-of-source,就是新建一个build文件
1. 预定义变量
PROJECT_SOURCE_DIR:工程的根目录
PROJECT_BINARY_DIR:运行 cmake 命令的目录,通常是 ${PROJECT_SOURCE_DIR}/build
PROJECT_NAME:返回通过 project 命令定义的项目名称
CMAKE_CURRENT_SOURCE_DIR:当前处理的 CMakeLists.txt 所在的路径
就是source所在路径,以上都是基于out-of-source进行解释
CMAKE_CURRENT_BINARY_DIR:target 编译目录(build)
CMAKE_CURRENT_LIST_DIR:CMakeLists.txt 的完整路径
CMAKE_CURRENT_LIST_LINE:当前所在的行
CMAKE_MODULE_PATH:定义自己的 cmake 模块所在的路径,
SET(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake),然后可以用INCLUDE命令来调用自己的模块
EXECUTABLE_OUTPUT_PATH:重新定义目标二进制可执行文件的输出位置
LIBRARY_OUTPUT_PATH:重新定义目标链接库文件的输出位置
例如:set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)
4.生成库文件
add_library 默认生成静态库
aux_source_directory(dir VAR) 发现一个目录下所有的源代码文件并将列表存储在一个变量中。
aux_source_directory(. SRC_LIST) # 搜索当前目录下的所有.cpp文件
add_library(demo ${SRC_LIST})
5. 查找指定的库文件
find_library(VAR name path)查找到指定的预编译库,并将它的路径存储在变量中。
默认的搜索路径为 cmake 包含的系统库,因此如果是 NDK 的公共库只需要指定库的 name 即可。
find_file() 重点:找到文件的全路径(包含文件名)(查找需要全称),默认路径是CMAKE_INCLUDE_PATH
find_path() 重点:找到文件的文件夹路径(查找需要全称),默认路径是CMAKE_INCLUDE_PATH
find_library() 重点:找到文件的全路径(包含文件名)(查找不需要全称),默认路径是CMAKE_LIBRARY_PATH
find_library(TESTFUNC_LIB testFunc HINTS ${PROJECT_SOURCE_DIR}/testFunc/lib)
find_library: 在指定目录下查找指定库,并把库的绝对路径存放到变量里,其第一个参数是变量名称,第二个参数是库名称,第三个参数是HINTS,第4个参数是路径,其它用法可以参考cmake文档
HINTS表示在默认搜索路径之前搜索
注:HINTS 与 PATHS
Long story short: Hints get searched before the system paths, and
should only be set by some source of knowledge (location of other
files, etc) and not populated with "guesses" or default locations.
Paths get searched after system locations, and is the place to put
default locations.
find_library( # Sets the name of the path variable.
log-lib
# Specifies the name of the NDK library that
# you want CMake to locate.
log )
类似的命令还有 find_file()、find_path()、find_program()、find_package()。
6. 设置包含的目录
设置头文件的目录
相当于指定g++编译器的-I参数 是i
include_directories(
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_BINARY_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/include
)
Linux 下还可以通过如下方式设置包含的目录
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -I${CMAKE_CURRENT_SOURCE_DIR}")
7. 设置链接库搜索目录
该指令的作用主要是指定要链接的库文件的路径,该指令有时候不一定需要。因为find_package和find_library指令可以得到库文件的绝对路径。不过你自己写的动态库文件放在自己新建的目录下时,可以用该指令指定该目录的路径以便工程能够找到。
相当于指定g++编译器的-L参数
link_directories(
${CMAKE_CURRENT_SOURCE_DIR}/libs
)
Linux 下还可以通过如下方式设置包含的目录
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -L${CMAKE_CURRENT_SOURCE_DIR}/libs")
8. 设置 target 需要链接的库
相同于指定g++编译器-l参数 target_link_libraries
target_link_libraries( # 目标库
demo
# 目标库需要链接的库
# log-lib 是上面 find_library 指定的变量名
${log-lib} )
该指令的作用为将目标文件与库文件进行链接。该指令的语法如下:
target_link_libraries(<target> [item1] [item2] [...] [[debug|optimized|general] <item>] ...)
上述指令中的<target>是指通过add_executable()和add_library()指令生成已经创建的目标文件。而[item]表示没有后缀的库文件名字。
注:为什么可以用于add_library(),也不是很明白,感觉add_library()就是生成库用的
主要用法:
target_link_libraries(可执行文件,库名)
例子:
在 Windows 下,系统会根据链接库目录,搜索xxx.lib 文件,Linux 下会搜索 xxx.so 或者 xxx.a 文件,如果都存在会优先链接动态库(so 后缀)。
8.1 指定链接动态库或静态库
target_link_libraries(demo libface.a) # 链接libface.a
target_link_libraries(demo libface.so) # 链接libface.so
8.2 指定全路径
target_link_libraries(demo ${CMAKE_CURRENT_SOURCE_DIR}/libs/libface.a)
target_link_libraries(demo ${CMAKE_CURRENT_SOURCE_DIR}/libs/libface.so)
8.3 指定链接多个库
target_link_libraries(demo
${CMAKE_CURRENT_SOURCE_DIR}/libs/libface.a
boost_system.a
boost_thread
pthread)
9. 设置变量
9.1 set 直接设置变量的值
set(SRC_LIST main.cpp test.cpp)
add_executable(demo ${SRC_LIST})
9.2 set 追加设置变量的值
set(SRC_LIST main.cpp)
set(SRC_LIST ${SRC_LIST} test.cpp)
add_executable(demo ${SRC_LIST})
9.3 list 追加或者删除变量的值
set(SRC_LIST main.cpp)
list(APPEND SRC_LIST test.cpp)
list(REMOVE_ITEM SRC_LIST main.cpp)
add_executable(demo ${SRC_LIST})
10. 条件控制
10.1 if…elseif…else…endif
逻辑判断和比较:
if (expression):expression 不为空(0,N,NO,OFF,FALSE,NOTFOUND)时为真
if (not exp):与上面相反
if (var1 AND var2)
if (var1 OR var2)
if (COMMAND cmd):如果 cmd 确实是命令并可调用为真
if (EXISTS dir) if (EXISTS file):如果目录或文件存在为真
if (file1 IS_NEWER_THAN file2):当 file1 比 file2 新,或 file1/file2 中有一个不存在时为真,文件名需使用全路径
if (IS_DIRECTORY dir):当 dir 是目录时为真
if (DEFINED var):如果变量被定义为真
if (var MATCHES regex):给定的变量或者字符串能够匹配正则表达式 regex 时为真,此处 var 可以用 var 名,也可以用 ${var}
if (string MATCHES regex)
数字比较:
if (variable LESS number):LESS 小于
if (string LESS number)
if (variable GREATER number):GREATER 大于
if (string GREATER number)
if (variable EQUAL number):EQUAL 等于
if (string EQUAL number)
字母表顺序比较:
if (variable STRLESS string)
if (string STRLESS string)
if (variable STRGREATER string)
if (string STRGREATER string)
if (variable STREQUAL string)
if (string STREQUAL string)
示例:
if(MSVC)
set(LINK_LIBS common)
else()
set(boost_thread boost_log.a boost_system.a)
endif()
target_link_libraries(demo ${LINK_LIBS})
# 或者
if(UNIX)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -fpermissive -g")
else()
add_definitions(-D_SCL_SECURE_NO_WARNINGS
D_CRT_SECURE_NO_WARNINGS
-D_WIN32_WINNT=0x601
-D_WINSOCK_DEPRECATED_NO_WARNINGS)
endif()
if(${CMAKE_BUILD_TYPE} MATCHES "debug")
...
else()
...
endif()
10.2 while…endwhile
while(condition)
...
endwhile()
10.3 foreach…endforeach
foreach(loop_var RANGE start stop [step])
...
endforeach(loop_var)
start 表示起始数,stop 表示终止数,step 表示步长,示例:
foreach(i RANGE 1 9 2)
message(${i})
endforeach(i)
# 输出:13579
11. 打印信息
message(${PROJECT_SOURCE_DIR})
message("build with debug mode")
message(WARNING "this is warnning message")
message(FATAL_ERROR "this build has many error") # FATAL_ERROR 会导致编译失败
12 主要开关选项
可以参考文档
BUILD_SHARED_LIBS:这个开关用来控制默认的库编译方式,如果不进行设置,使用 add_library 又没有指定库类型的情况下,默认编译生成的库都是静态库。如果 set(BUILD_SHARED_LIBS ON) 后,默认生成的为动态库
CMAKE_C_FLAGS:设置 C 编译选项,也可以通过指令 add_definitions() 添加
CMAKE_CXX_FLAGS:设置 C++ 编译选项,也可以通过指令 add_definitions() 添加
参考博客
https://www.cnblogs.com/coderfenghc/archive/2012/06/23/2559603.html