本文共 9630 字,大约阅读时间需要 32 分钟。
CMake的历史
cmake,相当于GNU configure and build systems中的configure工具。
目的是为了支持windows等非unix系统。同时cmake支持多种构建工具,不仅只是支持make。
执行步骤
由Autotools生成 或手动生成,configure
1)./configure
2)make
3)make install
CMake作用
CMake生成Makefile的工具,方便跨平台使用。
同时CMake页包含了,CPack,CTest工具
CPack用于二进制打包,或源代码打包
CTest用于代码黑盒测试。是否可以通过变通的方式,实现白盒测试,还不确定。
CMake使用
cmake的GUI版本,比如ccmake或cmake-gui
指令是大小写无关的,参数和变量是大小写相关的。
命令由命令名称、小括号和参数组成,参数之间使用空格进行间隔。
# 后面的内容被认为是注释。
cmake命令行参数
# 例如, SET(CMAKE_BUILD_TYPE Debug) 等价于 cmake -DCMAKE_BUILD_TYPE=Release
CMakeLists.txt文件内容
- 预定义变量
- 命令 COMMAND(参数1 参数2 ...)
- 流程控制
CMakefile调试
- cmake对配置文件中的内容,不区分大小写。
- 在source code的根目录(CMakeLists.txt在该目录下),建立build子目录,避免污染代码。例如: cd ./build; cmake ../
- 使用命令message
- CMake命令,读取文件名为CMakeLists.txt(大小写敏感),解析该文本中的语法,生成Makefile。
- 解析过程中,会生成中间过程文件CMakeCache.txt,该文件一是,记录解析过程,另一个作用是,用于加速解析。已解析文本的就不再解析。
cmake -D CMAKE_BUILD_TYPE=Release 生成调试版本
cmake --debug-output #打印cmake执行的详细过程。
cmake中调用OS命令
两种方式:一种,EXECUTE_PROCESS;另一种,
例如:
EXECUTE_PROCESS(COMMAND ls “-lt”)
EXECUTE_PROCESS(COMMAND ls “-lt” COMMAND cat “文件名”)
sysroot作用
用于交叉编译时,指定bin ,usr/bin 等路径
涉及的默认变量有:CMAKE_SYSROOT, CMAKE_SYSROOT_COMPILE(仅编译时有效), CMAKE_SYSROOT_LINK(仅链接时有效)。注:这几个变量没有作用。
环境:
问题:is not able to compile a simple test program.
原因:没有指定sysroot路径。SET(CMAKE_SYSROOT /home/sifu/test-yocto/qemuarmdfs),没有指定是该sysroot的设置,针对哪个语言。
solution:CMAKE_C_COMPILER "/交叉编译器路径/xxx-gcc"
CMAKE_C_FLAGS " --sysroot=/交叉编译器路径"
CMAKE_CXX_COMPILER, CMAKE_CXX_FLAGS 同理设置。
例如:
# compiler
set(CMAKE_C_COMPILER /4.14-sumo/sysroots/x86_64-pokysdk-linux/usr/bin/aarch64-poky-linux/aarch64-poky-linux-gcc) set(CMAKE_CXX_COMPILER /4.14-sumo/sysroots/x86_64-pokysdk-linux/usr/bin/aarch64-poky-linux/aarch64-poky-linux-g++) # sysroot location set(MYSYSROOT "/4.14-sumo/sysroots/aarch64-poky-linux") # compiler/linker flags set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} --sysroot=${MYSYSROOT}" CACHE INTERNAL "" FORCE) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --sysroot=${MYSYSROOT}" CACHE INTERNAL "" FORCE)
假如:
SET(CMAKE_C_COMPILER "/4.14-sumo/sysroots/x86_64-pokysdk-linux/usr/bin/aarch64-poky-linux/aarch64-poky-linux-gcc --sysroot=/4.14-sumo/sysroots/aarch64-poky-linux")
SET(CMAKE_CXX_COMPILER "/4.14-sumo/sysroots/x86_64-pokysdk-linux/usr/bin/aarch64-poky-linux/aarch64-poky-linux-g++ --sysroot=/4.14-sumo/sysroots/aarch64-poky-linux")提示 is not a full path to an existing compiler tool.
但是,系统环境变量,设置系统环境变量CC 和CXX为上面的值,则完全正确,不会提示错误。
“is not a full path to an existing compiler tool.”:说明,1)编译器不存在,2)即使存在,但带了参数。
若,将CMAKE_C_COMPILER设置为cache variable,则还是出现相同问题
set(CMAKE_C_COMPILER "${TC_PATH}/4.14-sumo/sysroots/x86_64-pokysdk-linux/usr/bin/aarch64-poky-linux/aarch64-poky-linux-gcc --sysroot=${MYSYSROOT}" CACHE INTERNAL "" FORCE)
set(CMAKE_CXX_COMPILER "${TC_PATH}/4.14-sumo/sysroots/x86_64-pokysdk-linux/usr/bin/aarch64-poky-linux/aarch64-poky-linux-g++ --sysroot=${MYSYSROOT}" CACHE INTERNAL "" FORCE)
CMake 变量
cmake -D=XXX
CMakeLists.txt 中 SET(aa, xxx) , SET(ENV(aa), yyy),FIND_PACKAGE(), OPTION()
环境变量
CMakeCache.txt
cmake内置变量
系统环境变量environment variable
获取当前系统环境变量,或当前运行环境的临时的环境变量(设置的环境变量值,存储在CMakeCache中)。
ENV{环境变量名}
环境变量取值 $ENV{环境变量}
例如:
SET(ENV{PATH} "$ENV{PATH}:/opt/4.14-sumo/sysroots/x86_64-pokysdk-linux/usr/bin/aarch64-poky-linux:/opt/4.14-sumo/sysroots/x86_64-pokysdk-linux/usr/bin/aarch64-poky-linux-musl")
OPTION变量
通过命令 OPTION设置
ON 或 OFF
cache variable
相当于一个全局变量,我们在同一个 cmake 工程中都可以使用。
所有的 Cache 变量都会出现在 CMakeCache.txt 文件中。
Normal variable
作用域属于整个 CMakeLists.txt 文件
CMakeCache.txt
1)存储上次cmake运行时生成的变量。2)CMakeCache.txt中预先设定的变量
目的:加速cmake的运行。
常见错误
1,No CMAKE_CXX_COMPILER could be found
解决方案:1)要么设置环境变量CXX;2)要么cache entry中设置CMAKE_CXX_COMPILER。通过cmake -D实现。
2,cannot find crt1.o: No such file or directory
解决方案:在CMAKE_C_FLAGS 中添加 --sysroot
crt0.s是一个桩(stub)程序,名称中的“crt”是“C run-time”的缩写。该程序的目标文件将被链接在每个用户执行程序的开始部分,主要用于设置一些初始化全局变量。通常使用gcc编译链接生成文件 时,gcc会自动把该文件的代码作为第一个模块链接在可执行程序中。在编译时使用显示详细信息选项“-v”就可以明显地看出这个链接操作过程。因此在通常 的编译过程中,我们无需特别指定stub模块crt0.o。为了使用ELF格式的目标文件以及建立共享库模块文件,现在的编译器已经把crt0扩展成几个 模块:crt1.0、crti.o、crtbegin.o、crtend.o和crtn.o。 这些模块的链接顺序为crt1.o、crti.o、crtbegin.o(crtbeginS.o)、所有程序模块、 crtend.o(crtendS.o)、crtn.o、库模块文件。
常用cmake变量和命令
下面以实例,讲解预定义变量的含义
#cross-toolchain header
INCLUDE_directories(${TG_ROOT}/include) #cross-toolchain lib LINK_directories(${TG_ROOT}/lib) CMAKE_LIBRARY_PATH | library的路径 |
CMAKE_CURRENT_SOURCE_DIR | source code的目录 |
CMAKE_CURRENT_BINARY_DIR | target的编译目录 ? (还是target的存储目录,TBD) ADD_SUBDIRECTORY()可以改变该变量 注: SET(EXECUTABLE_OUTPUT_PATH <新路径>),改变了target存储路径。 |
CMAKE_CURRENT_LIST_FILE | 当前CMakeLists.txt的路径 |
CMAKE_CURRENT_LIST_NAME | 该变量所在的行 |
CMAKE_MODULE_PATH | ? |
PROJECT_SOURCE_DIR | 工程的根目录 |
PROJECT_BINARY_DIR | cmake生成中间过程文件的目录,默认在${PROJECT_SOURCE_DIR}/build |
CMAKE_INCLUDE_PATH | ? |
EXECUTABLE_OUTPUT_PATH | 可执行目标文件的存放位置 |
LIBRARY_OUTPUT_PATH | 目标链接库的存放位置 |
PROJECT_NAME | 项目名称 |
CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS | 控制if-else语句的书写方式 |
CMAKE_MAJOR_VERSION | cmake的主版本号。如5.8.3中的5 |
CMAKE_MINOR_VERSION | cmake的次版本号。如5.8.3中的8 |
CMAKE_PATCH_VERSION | cmake补丁等级。如5.8.3中的3 |
CMAKE_SYSTEM | cmake运行所在的系统。例如:linux-5.1.12 |
CMAKE_SYSTEM_NAME | cmake运行所在的系统名称。例如,SET(CMAKE_SYSTEM_NAME Linux)。 |
CMAKE_SYSTEM_VERSION | cmake运行所在的系统版本。例如5.1.12 |
CMAKE_SYSTEM_PROCESSOR | 处理器名称。例如i686 |
BUILD_SHARED_LIBS | 生成库文件的类型。默认生成静态库。 |
CMAKE_C_FLAGS | 设置c语言编译选项 |
CMAKE_CXX_FLAGS | 设置c++编译选项 |
UNIX | 编译平台为linux,其值为ON。 |
WIN32 | 编译平台为windows,其值为ON。 |
CMAKE_TOOLCHAIN_FILE | 其指定的文件中,包含工具链相关信息。 |
命令
命令 | 说明 | 实例 |
ADD_EXECUTABLE | 指定可执行目标文件 | ADD_EXECUTABLE(hello main.c;func.c) |
PROJECT | 指定工程名称,支持的语言。默认支持所有语言。 | PROJECT(projectname [CXX]) |
SET | 设置变量值 |
|
MESSAGE | 在命令终端显示信息 | MESSAGE([SEND_ERROR | STATUS | FATAL_ERROR] “message to display” …) |
ADD_LIBRARY | 生成库文件 | ADD_LIBRARY(libname [SHARED | STATIC | MODULE] [EXCLUDE_FROM_ALL] SRC_LIST) |
SET_TARGET_PROPERTIES | 设置输出的名称,设置动态库的版本和API版本 |
|
INCLUDE_DIRECTORIES | 向工程添加头文件搜索路径。 路径之间用空格分隔。 如果路径包含空格,可以使用双引号将它括起来。 默认的行为为追加到当前头文件搜索路径的后面。
CMAKE_INCLUDE_DIRECTORIES_BEFORE,通过SET这个cmake变量为on,可以将添加的头文件搜索路径放在已有路径的前面。 通过AFTER或BEFORE参数,也可以控制是追加还是置前。 | INCLUDE_DIRECTORIES([AFTER | BEFORE] [SYSTEM] dir1 dir2 … ) |
LINK_DIRECTORIES | 添加lib搜索路径 | LINK_DIRECTORIES(dir1 dir2 …) |
TARGET_LINK_LIBRARIES | 为target添加要链接的lib | TARGET_LINK_LIBRARIES(target lib1 lib2 …) |
ADD_DEFINITIONS | 向编译器增加,宏定义 | ADD_DEFINITIONS(-DENABLE_DEBUG -DABC),参数之间用空格分隔 |
ADD_DEPENDENCIES | 定义target间的依赖关系 | ADD_DEPENDENCIES(target-name depend-target1 depend-target2 …) |
AUX_SOURCE_DIRECTORY | 将目录下所有源文件名,赋值给一个变量 | AUX_SOURCE_DIRECTORY(dir VAR) |
EXEC_PROGRAM | 在指定的目录下,运行某个程序 | EXEC_PROGRAM(Executable [dir where to run] [ARGS <args>][OUTPUT_VARIABLE <var>] [RETURN_VALUE <value>]) |
INCLUDE | INCLUDE(file [OPTIONAL]) | |
FIND_FILE | 在指定路径下,查找指定文件,并保存到变量中(全路径+文件名)。 | FIND_FILE(<VAR> name path1 path2 …) |
FIND_LIBRARY | 在指定路径下查找库,并保存到变量中(全路径+文件名)。 | FIND_LIBRARY(<VAR> name path1 path2 …) |
FIND_PATH | 查找文件,并将文件路径保存到变量中。 | FIND_PATH(<VAR> name path1 path2 …) |
FIND_PROGRAM | 查找程序,并将文件路径保存到变量中。 | FIND_PROGRAM(<VAR> name path1 path2 …) |
FIND_PACKAGE | 用来调用预定义在CMAKE_MODULE_PATH下的Find<name>.cmake模块。 | FIND_PACKAGE(<name> [major.minor] [QUIET] [NO_MODULE] [[REQUIRED | COMPONENTS] [componets …]]) |
流程控制
if | if else endif
或 if elseif endif
或 if endif | 逻辑表达式 IF (expression), expression不为:空,0,N,NO,OFF,FALSE,NOTFOUND或<var>_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) 此处var可以用var名,也可以用${var} IF (string MATCHES regex)
数值比较 IF (variable LESS number) IF (string LESS number) IF (variable GREATER number) IF (string GREATER number) IF (variable EQUAL number) 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) |
while | while endwhile | WHILE(condition) COMMAND1(ARGS ...) COMMAND2(ARGS ...) ... ENDWHILE(condition) |
foreach | foreach endforeach | FOREACH(loop_var arg1 arg2 ...) COMMAND1(ARGS ...) COMMAND2(ARGS ...) ... ENDFOREACH(loop_var)
或 FOREACH(loop_var RANGE start stop [step]) COMMAND1(ARGS ...) COMMAND2(ARGS ...) ... ENDFOREACH(loop_var) |
其他有项目构建工具
gradle
bazel
buck
please
scons
xmake
emake
:Eric S. Raymond、Timothee Besset、Zed A. Shaw 等大神力荐的项目架构工具。和 CMake 的最大区别是使用 Python 作为执行脚本。
交叉编译CMAKE_TOOLCHAIN_FILE 示例
例1
cmake -DCMAKE_TOOLCHAIN_FILE= 路径/File1 .
文件名File1
# compiler
set(CMAKE_C_COMPILER ${TC_PATH}/4.14-sumo/sysroots/x86_64-pokysdk-linux/usr/bin/aarch64-poky-linux/aarch64-poky-linux-gcc) set(CMAKE_CXX_COMPILER ${TC_PATH}/4.14-sumo/sysroots/x86_64-pokysdk-linux/usr/bin/aarch64-poky-linux/aarch64-poky-linux-g++) # sysroot location set(MYSYSROOT "${TC_PATH}/4.14-sumo/sysroots/aarch64-poky-linux") # compiler/linker flags set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} --sysroot=${MYSYSROOT}" CACHE INTERNAL "" FORCE) #set(CMAKE_C_LINK_FLAGS "${CMAKE_C_LINK_FLAGS} --sysroot=${MYSYSROOT}" CACHE INTERNAL "" FORCE) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --sysroot=${MYSYSROOT}" CACHE INTERNAL "" FORCE) #set(CMAKE_CXX_LINK_FLAGS "${CMAKE_CXX_LINK_FLAGS} --sysroot=${MYSYSROOT}" CACHE INTERNAL "" FORCE)# cmake built-in settings to use find_xxx() functions
#set(CMAKE_FIND_ROOT_PATH "${MYSYSROOT}") #set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) #set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) #set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
例2
SET(TC_PATH "xxx")
# compiler set(MYSYSROOT "${TC_PATH}/4.14-sumo/sysroots/aarch64-poky-linux") set(ENV{CC} "${TC_PATH}/4.14-sumo/sysroots/x86_64-pokysdk-linux/usr/bin/aarch64-poky-linux/aarch64-poky-linux-gcc --sysroot=${MYSYSROOT}") set(ENV{CXX} "${TC_PATH}/4.14-sumo/sysroots/x86_64-pokysdk-linux/usr/bin/aarch64-poky-linux/aarch64-poky-linux-g++ --sysroot=${MYSYSROOT}")
参考:
configure与cmake区别
实例
转载地址:https://chilaidashi.blog.csdn.net/article/details/106867914 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!