项目构建工具 - CMake (1)初识
发布日期:2021-06-29 14:21:03 浏览次数:3 分类:技术文章

本文共 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文件内容

  1. 预定义变量
  2. 命令  COMMAND(参数1 参数2 ...)
  3. 流程控制

CMakefile调试

  1. cmake对配置文件中的内容,不区分大小写。
  2. 在source code的根目录(CMakeLists.txt在该目录下),建立build子目录,避免污染代码。例如: cd ./build; cmake ../
  3. 使用命令message
  4. CMake命令,读取文件名为CMakeLists.txt(大小写敏感),解析该文本中的语法,生成Makefile。
  5. 解析过程中,会生成中间过程文件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 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:项目构建工具 - CMake (2)查找 3rd library
下一篇:AI人工智能 - 矩阵matrix - 卷积 - Neural Network神经网络 - Deep Learning深度学习 - 应用(图像识别,语音识别,文本识别)

发表评论

最新留言

留言是一种美德,欢迎回访!
[***.207.175.100]2024年04月04日 14时15分44秒