一、 Cmake介绍
Cmake是一种与平台无关的自动控制项目编译过程的工具(自动生成makefile文档)。只需要配置CMakeList.txt就可以自动的根据平台生成Makefile,方便的跨越多个平台进行编译。
CMakeList.txt注意大小写和s不然识别不成功
cmake是什么?cmake的特性和编译原理(cmake原理和cmake编译过程)
【C++】Cmake使用教程(看这一篇就够了)-CSDN博客
不是已经有了makefile去实现编译控制,为什么还需要Cmake?
Maybe:控制编译的对象范围不同?
Answer:Cmake为了方便的自动生成可以跨平台的makefile,直接写makefile可以实现但是复杂。最重要的,Makefile不像人读的。
二、 Cmake的常用语法
一般的,Cmake的编写分为几个部分:初始化、
1. 初始化:
添加cmake版本要求, 添加project名称和版本号
cmake_minimum_required (VERSION 2.8)
project (project_name VERSION 1.0)
2. 设置头文件路径:
指定头文件搜索路径:
include_directories (test_func test_func1)
3. 添加编译选项:
add_compile_options(-std=c++11 -Wall)
或者使用set设置变量CMAKE_CXX_FLAGS或CMAKE_C_FLAGS
set(CMAKE_CXX_FLAGS "-Wall")
4. 编译可执行文件:
4.1 直接编译.c文件
add_executable(main main.c testFunc.c)
4.2 将目录中的所有源文件存在变量中
一般的,Cmake中变量名称使用大写字符表示,
${VAR}取出变量的值
aux_source_directory(. SRC_LIST)
add_executable(main ${SRC_LIST})
4.3 设置二进制文件的输出位置:
set (EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)
还可以使用
SET_TARGET_PROPERTIES设置单个编译对象的输出路径,路径更精细。设置输出路径的颗粒度可以精细到每个编译的对象
5. 编译库文件:
5.1 编译源代码归档成动态库(SHARED)或静态库(STATIC)
add_library (libname SHARED ${SRC_LIST})
add_library (libname STATIC ${SRC_LIST})
5.2 设置最终生成的库的名字
set_target_properties (libname PROPERTIES OUTPUT_NAME "libname ")
5.3 设置库的输出路径
set (LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib)
同样可以使用
SET_TARGET_PROPERTIES设置输出路径
6. 链接库:
6.1 在路径下查找库并把绝对路径存放在变量中
find_library(LIB_PATH libname HINTS ${PROJECT_SOURCE_DIR}/lib)
6.2 链接目标文件和库文件
target_link_libraries (target_file ${LIB_PATH})
7. 添加编译子目录(可选):
add_subdirectory(source_dir [binary_dir] [EXCLUDE_FROM_ALL])
-
source_dir 源代码目录 指定一个具有cmakelist和源代码的目录,将其作为编译的子目录
-
binary_dir 二进制代码目录 指定cmake输出的二进制文件所在的目录
-
EXCLUDE_FROM_ALL标记 指定将添加的子目录从make all 中移除
添加编译子目录是为了让源码的编译结构更加清晰,可以更好的使用选项管理编译过程。新的目录路径下建立一个新的CMakeLists。
8. 安装规则(可选):
在编译完成之后,可以使用以下命令将编译好的源文件、头文件、测试用例等资源安装到Cmake指定的位置。
make install
8.1 安装动态库
install(TARGETS mylib
LIBRARY DESTINATION lib
)
8.2 安装可执行文件
install(TARGETS test_mylib
RUNTIME DESTINATION bin
)
8.3 安装头文件
install(FILES myheader.h
DESTINATION include
)
9. 测试(可选)
CMake 提供了内建的测试功能,可以帮助开发者验证项目是否正确构建以及是否通过了各种测试。CMake 的测试功能依赖于 CTest,这是一个 CMake 的测试驱动工具,通常用于执行项目中的单元测试、集成测试等。以下是关于 CMake 测试的主要概念和使用方法。
9.1 启用测试
要启用 CMake 测试功能,首先需要在 CMakeLists.txt 文件中调用 enable_testing()。这将启用 ctest 测试命令。一旦启用测试,您就可以通过 add_test() 命令定义具体的测试。
enable_testing()
9.2 添加测试
使用 add_test() 命令来定义测试。该命令接受两个参数:测试名称和要执行的命令。
add_test(NAME MyTest COMMAND MyExecutable)
这个命令将会添加一个名为 MyTest 的测试,它会运行 MyExecutable 可执行文件。如果 MyExecutable 执行成功,测试将通过。
9.3 测试命令的参数
在 add_test() 命令中,您可以传递多个参数,供测试命令使用。例如,如果您的程序需要一些命令行参数,您可以这样做:
add_test(NAME TestWithArguments COMMAND MyExecutable arg1 arg2)
这样在运行测试时,MyExecutable 将以 arg1 和 arg2 作为参数执行。
9.4 测试期望的返回值
默认情况下,CMake 假定测试程序成功执行时返回 0,如果返回非 0 值,则认为测试失败。如果您的测试需要特定的返回值来表示成功,可以使用 add_test() 的第三个参数指定期望的返回值:
add_test(NAME TestWithExpectedReturnValue COMMAND MyExecutable)
set_tests_properties(TestWithExpectedReturnValue PROPERTIES WILL_FAIL TRUE)
9.5 测试输出
CTest 会捕获测试的标准输出(stdout)和标准错误(stderr)。如果您希望在测试中检查输出内容,可以使用 add_test() 的 –output-on-failure 标志来显示失败的输出。
ctest --output-on-failure
这样,如果测试失败,你将看到每个失败测试的详细输出。
9.6 测试属性
使用 set_tests_properties() 可以设置测试的额外属性。例如,您可以将某个测试标记为“预期失败”(WILL_FAIL),或者设置测试的超时时间(TIMEOUT)等。
set_tests_properties(MyTest PROPERTIES TIMEOUT 30)
set_tests_properties(MyTest PROPERTIES WILL_FAIL TRUE)
- TIMEOUT:指定测试的超时时间(以秒为单位)。如果测试在此时间内没有结束,将被视为失败。
- WILL_FAIL:标记该测试为预期失败。
10.Cmake其他操作
10.1 文件操作file
file MAKE_DIRECTORY path/to/directory)
10.2 判断语句 if
10.3 循环语句 foreach
foreach(ITEM ${LIST})
dosomething
endforeach()
10.4 设置目标属性 SET_TARGET_PROPERTIES
SET_TARGET_PROPERTIES是 CMake 中的一个重要指令,用于设置目标(target)的各种属性,这里的目标可以是库(静态库、动态库),也可以是可执行文件。其基本语法如下:
SET_TARGET_PROPERTIES(target1 target2... PROPERTIES
property1 value1
property2 value2
...
)
常见属性及用途:
-
ARCHIVE_OUTPUT_DIRECTORY: 设置静态库的输出目录。例如:
SET_TARGET_PROPERTIES(mylib PROPERTIES ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib )这会将名为 mylib 的静态库输出到
${CMAKE_BINARY_DIR}/lib目录下。 -
LIBRARY_OUTPUT_DIRECTORY: 用于指定动态库的输出目录,用法和静态库类似:
SET_TARGET_PROPERTIES(mylib PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib ) -
RUNTIME_OUTPUT_DIRECTORY: 设定可执行文件的输出目录。比如:
SET_TARGET_PROPERTIES(myapp PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin ) -
POSITION_INDEPENDENT_CODE: 对于生成动态库或者希望被动态链接的目标很有用,设置为 ON 表示生成位置无关代码(PIC)。这是共享库编译时的常见需求,因为共享库需要能被加载到内存的不同位置,代码必须是位置无关的:
SET_TARGET_PROPERTIES(mylib PROPERTIES POSITION_INDEPENDENT_CODE ON ) -
INSTALL_RPATH: 正如前面提到的,和运行时库路径相关,用于设置安装后的可执行文件搜索动态库的路径。”$ORIGIN” 是一个常用值,表示可执行文件所在目录:
SET_TARGET_PROPERTIES(test_mylib PROPERTIES INSTALL_RPATH "$ORIGIN" ) -
INTERFACE_INCLUDE_DIRECTORIES: 在创建库时,用于指定库的使用者需要包含的头文件目录,方便其他项目链接该库时能正确找到头文件:
SET_TARGET_PROPERTIES(mylib PROPERTIES INTERFACE_INCLUDE_DIRECTORIES ${CMAKE_CURRENT_SOURCE_DIR}/include )
三、Cmake使用
使用cmakelist宏变量和make的命令选项显示make的详细内容
cmake -DCMAKE_VERBOSE_MAKEFILE=ON ..
make VERBOSE=1