CMake是一个跨平台的自动化构建系统,可以用简单的语句来描述所有平台的编译过程。CMake可以输出各种各样的编译文件,如Makefile、VisualStudio等。
CMake主要是编写CMakeLists.txt文件,然后用cmake命令将CMakeLists.txt文件转化为make所需要的makefile文件,最后用make命令编译源码生成可执行程序或共享库(so (shared object))。
你可以在CMakeLists.txt中指定源文件、头文件、库文件、链接库等信息,然后通过cmake命令生成相应的makefile文件。
1. 单main.c文件输出"hello world"
mian.c
#include <stdio.h>
int main(){
printf("hello world!\n");
return 0;
}
CMakeLists.txt
cmake_minimum_required(VERSION 3.15)
PROJECT(HELLO)
SET(CMAKE_C_COMPILER gcc)
SET(SRC_LIST main.c)
MESSAGE(STATUS "This is BINARY dir" ${HELLO_BINARY_DIR})
MESSAGE(STATUS "This is SOURCE dir" ${HELLO_SOURCE_DIR})
ADD_EXECUTABLE(hello ${SRC_LIST})
-
cmake_minimum_required(VERSION X.X) : 指定cmake的最低版本。
-
project( project_name ) : 指定工程名称,这个指令隐式的指定了两个CMake变量,那就是<project_name>_BINARY_DIR,<project_name>_SOURCE_DIR。在这个例程中,我们命名project_name为HELLO,所以也指定了HELLO_BIARY_DIR和HELLO_SOURCE_DIR。所以当我们更改了工程名之后,<project_name>_BINARY_DIR和<project_name>_SOURCE_DIR也要跟着改变。但是!如果我们使用PROJECT_BINARY_DIR和PROJECT_BINARY_DIR,那么工程名随便改动,这两个变量名会随之改变。
MESSAGE(STATUS "This is BINARY dir" ${PROJECT_BINARY_DIR}) MESSAGE(STATUS "This is SOURCE dir" ${PROJECT_SOURCE_DIR})
-
set(CMAKE_C_COMPILER gcc) : 指定CMake使用gcc编译器来编译C代码
-
SET(SRC_LIST main.c) : SET 还可以显式的定义变量,语法是这样的:
SET(VAR [VALUE] [CACHE TYPE DOCSTRING [FORCE]])
现阶段,你只需要知道SET可以显式的定义变量即可。如果有多个源文件,还可以这样定义:SET(SRC_LIST main.c t1.c t2.c)
-
MESSAGE的语法是这样的:
MESSAGE([SEND_ERROR | STATUS | FATAL_ERROR] "message to display" ...)
这个指令用于向终端输出用户定义的信息,包含了三种类型:
- SEND_ERROR,产生错误,生成过程被跳过。
CMake Error at CMakeLists.txt:6 (MESSAGE):
This is BINARY dir/home/zch/CmakePratice/t1/buildCMake Error at CMakeLists.txt:7 (MESSAGE):
This is SOURCE dir/home/zch/CmakePratice/t1- SATUS,输出前缀为–的信息。
– This is BINARY dir/home/zch/CmakePratice/t1/build
– This is SOURCE dir/home/zch/CmakePratice/t1- FATAL_ERROR,立即终止所有 cmake 过程.
CMake Error at CMakeLists.txt:6 (MESSAGE):
This is BINARY dir/home/zch/CmakePratice/t1/build– Configuring incomplete, errors occurred!
-
ADD_EXECUTABLE(hello ${SRC_LIST})
定义了这个工程会生成一个文件名为 hello 的可执行文件,相关的源文件是 SRC_LIST 中
定义的源文件列表, 本例中你也可以直接写成 ADD_EXECUTABLE(hello main.c)。
2. 使"hello world"更像一个工程文件
命令词典
-
add_definitions()
add_definitions()是CMake中的一个函数,用于向编译器添加预处理器定义。这个命令可以用来添加任何标志,但它的目的是添加预处理器定义。例如,如果你想在编译时定义一个名为DEBUG的宏,你可以使用以下命令:add_definitions(-DDEBUG)。
那么在代码中就可以用到:#ifdef DEBUG do_something(); #else do_other_something(); #endif
-
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -O3 -march=native ")
它设置了C编译器的标志。这个命令告诉CMake在编译时使用-Wall选项来启用所有警告,-O3选项来启用最高级别的优化,并使用-march=native选项来生成针对本地CPU的代码。如果你想设置其他标志,只需将它们添加到这个命令中即可将这些设置加入到CMAKE_C_FLAGS变量中,以便在代码中生效。
-
target_link_libraries()命令和add_executable()命令的执行顺序
在CMake中,target_link_libraries()命令需要放在add_executable()之后。这是因为add_executable()命令定义了要编译的可执行文件,而target_link_libraries()命令指定了要链接到可执行文件中的库。如果你尝试在add_executable()之前使用target_link_libraries()命令,CMake将无法找到要链接的目标,因为它还没有被定义。
相反,link_libraries()命令可以在add_executable()之前使用,但它不如target_link_libraries()命令灵活。link_libraries()命令将库链接到所有目标中,而target_link_libraries()命令只将库链接到指定的目标中。
-
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY)
设置CMake生成的可执行文件的输出目录。这个命令将可执行文件的输出目录设置为指定的目录。例如,如果你想将可执行文件输出到build/bin目录中,你可以使用以下命令:
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
这将把可执行文件输出到build/bin目录中。
-
link_directories(${LINK})
link_directories(${LINK_DIR}) 是 CMake 中的一个命令,用于添加需要链接的库文件目录。它相当于 g++ 命令的 -L 选项的作用,也相当于环境变量中增加 LD_LIBRARY_PATH 的路径的作用。该命令可以指定第三方库所在路径,比如,你的动态库在 /home/myproject/libs 这个路径下,则通过命令:LINK_DIRECTORIES (/home/myproject/libs),把该路径添加到第三方库搜索路径中,这样就可以使用相对路径了,使用 TARGET_LINK_LIBRARIES 的时候,只需要给出动态链接库的名字就行了。