CMake

简介

官网 : https://cmake.org/cmake/help/v3.15/

CMake是跨平台的 免费和开源软件,用于使用独立于编译器的方法构建自动化、测试、打包和安装软件。CMake 本身并不是一个构建系统;它生成另一个系统的构建文件。它支持目录层次结构和依赖于多个库的应用程序。它与原生构建环境结合使用,例如Make、Qt Creator、Ninja、Android Studio、Apple 的Xcode和Microsoft Visual Studio。(摘自Wiki)

CMakeLists.txt

常用命令

  1. cmake要求最低版本(选择性添加)

    cmake_minimum_required(VERSION 3.0.0)
    
  2. 编译工程名

    project(xxx)
    //会自动创建两个变量,PROJECT_SOURCE_DIR和PROJECT_NAME
    //${PROJECT_SOURCE_DIR}:本CMakeLists.txt所在的文件夹路径
    //${PROJECT_NAME}:本CMakeLists.txt的project名称
    
  3. 给部分文件或路径组合起别名, 通过${变量}获取变量内容

    set(变量 文件名/路径/...)
    
  4. 设置c / c++ 编译编译参数

    set (CMAKE_C_FLAGS -Wall -O2)
    set (CMAKE_CXX_FLAGS -Wall -std=C++11)
    add_compile_options( -Wall )				//该命令译选项是针对所有编译器的(包括c和c++编译器)
    
  5. 为当前路径以及子目录的源文件加入由-D引入的define flag

    add_definitions(-DFOO -DDEBUG ...)
    
  6. 对子文件夹进行cmake编译

    add_subdirectory(子文件夹名) 
    
  7. 打印信息

    message() 			//直接添加打印的内容和变量即可,不需要双引号
    message("PROJECT_SOURCE_DIR = ${PROJECT_SOURCE_DIR}")
    
  8. 帮助信息

    1. 查看cmake默认变量		cmake --help-variable-list
    

判断语句

用法:根据某个宏确定编译内容。比较字符串,相同返回true

if (CPU_PLATFORM_BIT STREQUAL "64")
    add_library(mylib generic_64bit.c)
else()
    add_library(mylib generic_32bit.c)
endif()  

编译目标

二进制文件

add_executable(目标文件名字xxx 源文件)
//example: add_executable(${PROJECT_NAME} example_person.cpp)

动态 / 静态库

将指定的源文件生成链接文件,然后添加到工程中去

add_library(<name> [STATIC | SHARED | MODULE]
[EXCLUDE_FROM_ALL]
[source1] [source2] [...])

//<name>表示库文件的名字,该库文件会根据命令里列出的源文件来创建。生成的库自动补全,如libxxx.so 
//STATIC、SHARED和MODULE的作用是指定生成的库文件的类型。STATIC库是目标文件的归档文件,在链接其它目标的时候使用。SHARED库会被	动态链接(动态链接库),在运行时会被加载。MODULE库是一种不会被链接到其它目标中的插件,但是可能会在运行时使用dlopen-系列的函数	。默认状态下,库文件将会在于源文件目录树的构建目录树的位置被创建,该命令也会在这里被调用。
//source1 source2分别表示各个源文件

链接/路径

头文件路径

添加头文件的查找路径, 相当于命令行的 -l 参数

include_directories(../thirdparty/comm/include)

链接库路径

添加需要链接的库文件目录, 相当于命令行 -L 参数

link_directories("/home/server/third/lib")

链接库

将目标文件与库文件进行链接

target_link_libraries(<target> [item1] [item2] [...] [[debug|optimized|general] <item>] ...)
 
//<target>是指通过add_executable()和add_library()指令生成已经创建的目标文件
//[item]表示库文件没有后缀的名字。默认情况下,库依赖项是传递的。当这个目标链接到另一个目标时,链接到这个目标的库也会出现在另一个目标的连接线上。这个传递的接口存储在interface_link_libraries的目标属性中,可以通过设置该属性直接重写传递接口。

安装(Install)

  • 详情参考:https://cmake.org/cmake/help/v3.22/command/install.html
  • 作用:用于定义安装规则,安装内容包括可执行文件,静态库,动态库以及文件,目录,脚本等
  • 使用方法:make install
  • 目标安装路径:${CMAKE_INSTALL_PREFIX}指定,默认/usr/local

目标文件安装

目标文件指的是我们通过 add_executable / add_library 得到的二进制文件或者库,只有这些文件才可以通过该命令装载到相应的位置

  • 可执行文件:RUNTIME
  • 动态库:LIBRARY
  • 静态库:ARCHIVE
install(TARGETS targets... [EXPORT <export-name>]
        [RUNTIME_DEPENDENCIES args...|RUNTIME_DEPENDENCY_SET <set-name>]
        [[ARCHIVE|LIBRARY|RUNTIME|OBJECTS|FRAMEWORK|BUNDLE|
          PRIVATE_HEADER|PUBLIC_HEADER|RESOURCE]
         [DESTINATION <dir>]
         [PERMISSIONS permissions...]
         [CONFIGURATIONS [Debug|Release|...]]
         [COMPONENT <component>]
         [NAMELINK_COMPONENT <component>]
         [OPTIONAL] [EXCLUDE_FROM_ALL]
         [NAMELINK_ONLY|NAMELINK_SKIP]
        ] [...]
        [INCLUDES DESTINATION [<dir> ...]]
        )
        
// example:
install(TARGETS mybin mystaiclib mydynamiclib
        RUNTIME DESTINATION bin
        ARCHIVE DESTINATION lib
        LIBRARY DESTINATION lib)

普通文件安装

普通文件即需要导出的头文件、依赖的三方库等等,该命令同时可以指定导出文件的权限(默认644)

install(<FILES|PROGRAMS> files...
        TYPE <type> | DESTINATION <dir>
        [PERMISSIONS permissions...]
        [CONFIGURATIONS [Debug|Release|...]]
        [COMPONENT <component>]
        [RENAME <name>] [OPTIONAL] [EXCLUDE_FROM_ALL])
        
// example
install(FILES mylib.h DESTINATION include)

目录安装

参数介绍:

  • DIRECTORY:后面连接的是所在Source目录的相对路径(结尾是否是"/"对拷贝结果有一定影响)
  • PATTERN:使用正则表达式进行过滤
  • PERMISSIONS:指定PATTERN过滤后的文件权限。
install(DIRECTORY dirs...
        TYPE <type> | DESTINATION <dir>
        [FILE_PERMISSIONS permissions...]
        [DIRECTORY_PERMISSIONS permissions...]
        [USE_SOURCE_PERMISSIONS] [OPTIONAL] [MESSAGE_NEVER]
        [CONFIGURATIONS [Debug|Release|...]]
        [COMPONENT <component>] [EXCLUDE_FROM_ALL]
        [FILES_MATCHING]
        [[PATTERN <pattern> | REGEX <regex>]
         [EXCLUDE] [PERMISSIONS permissions...]] [...])

// example
install(DIRECTORY src/ DESTINATION include/myproj  FILES_MATCHING PATTERN "*.h")

Q&A

  1. Q: 编译参数添加了-lpthread 参数, 但是还是报undefined reference to `pthread_create’

    A : 需要使用target_link_libraries( target thread) 在这里链接thread库

  2. Q: 如果在多级的目录下编译, 始终找不到问题报 undefine的问题 ?

    A : 看一下是不是链接的库或目标文件格式不同, 一个c 一个c++ , 这样就会导致找不到符号错误

  3. Q: undefined reference to `typeinfo for xxxBase_class’ ?

    A: 基类的构造和析构函数需要加{ }; 否则就会报这个问题

Makefile

通配符

通配符使用说明
*匹配0个或者是任意个字符
?匹配任意一个字符
[]我们可以指定匹配的字符放在 “[]” 中
%匹配任意个字符

自动化变量

自动化变量说明
$@表示规则的目标文件名。如果目标是一个文档文件(Linux 中,一般成 .a 文件为文档文件,也成为静态的库文件), 那么它代表这个文档的文件名。在多目标模式规则中,它代表的是触发规则被执行的文件名。
$%当目标文件是一个静态库文件时,代表静态库的一个成员名。
$<规则的第一个依赖的文件名。如果是一个目标文件使用隐含的规则来重建,则它代表由隐含规则加入的第一个依赖文件。
$?所有比目标文件更新的依赖文件列表,空格分隔。如果目标文件时静态库文件,代表的是库文件(.o 文件)。
$^代表的是所有依赖文件列表,使用空格分隔。如果目标是静态库文件,它所代表的只能是所有的库成员(.o 文件)名。 一个文件可重复的出现在目标的依赖中,变量“ ”只记录它的第一次引用的情况。就是说变量“ ”只记录它的第一次引用的情况。就是说变量“ 只记录它的第一次引用的情况。就是说变量”会去掉重复的依赖文件。
$+类似“$^”,但是它保留了依赖文件中重复出现的文件。主要用在程序链接时库的交叉引用场合。
$*在模式规则和静态模式规则中,代表“茎”。“茎”是目标模式中“%”所代表的部分(当文件名中存在目录时, “茎”也包含目录部分)。

特殊函数

添加前缀

  • 函数名:addprefix( )
  • 语法:$(addprefix PREFIX/,${NAME…})
  • 函数功能:为“NAMES…”中的每一个文件名添加前缀“PREFIX”。参数“NAMES…”是空格分割的文件名序列,将“PREFIX”添加到此序列的每一个文件名之前。
  • 返回值:以单空格分割的添加了前缀“PREFIX”的文件名序列。
$(addprefix src/,foo bar)
//返回值为“src/foo src/bar”

过滤器

  • 函数名:filter( )
  • 语法:$(filter SUFFIX…,$(SOURCES))
  • 作用:保留字串 " $(SOURCES)" 中所有符合模式 “ SUFFIX ” 的单词
sources := main.c AT.txt
foo : $(sources)
    cc $(filter %.c,%.s,$(sources)) -o foo

打印

用于Makefile的Debug,打印分为三个等级:info、warning、error

$(info SRC = $(SRC))
$(warning INC = $(INC))
//注意:执行到error会直接stop退出
$(error INC = $(INC))

Linux相关更多内容请关注 yanglieee.com,讲持续发布!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值