首页 > 其他分享 >cmake笔记

cmake笔记

时间:2024-04-10 22:22:37浏览次数:22  
标签:SRC cmake list 笔记 PROJECT SOURCE cpp DIR

demo1

cmake_minimum_required(VERSION 2.8) #cmake的最低版本
project(test) #定义工程名称


add_executable(main add.cpp sub.cpp mul.cpp div.cpp main.cpp) 
#定义工程会生成一个可执行程序,格式:add_executable(可执行程序名 源文件名称)
#这里的可执行程序名和project中的项目名没有任何关系

set(CMAKE_CXX_STANDARD 11) #增加std=c++11/14/17

set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)
#指定可执行文件生成的位置,PROJECT_SOURCE_DIR为CMakeLists.txt所在目录


demo2

cmake_minimum_required(VERSION 2.8) #cmake的最低版本
project(test) #定义工程名称

set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED True)

#增加std=c++11/14/17,注意:必须在add_executable前

set(SRC add.cpp sub.cpp mul.cpp div.cpp main.cpp)
add_executable(main ${SRC})
#定义工程会生成一个可执行程序,格式:add_executable(可执行程序名 源文件名称)
#这里的可执行程序名和project中的项目名没有任何关系



set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)
#指定可执行文件生成的位置,PROJECT_SOURCE_DIR为CMakeLists.txt所在目录


搜索文件

aux_source_directory(${PROJECT_SOURCE_DIR} SRC)
#aux_source_directory(<dir> <var>) 搜索dir路径中所有文件,并命名为var

file(GLOB SRC ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp)
file(GLOB HEAD ${CMAKE_CURRENT_SOURCE_DIR}/*.h)
#file(GLOB/GLOB_RECURSE 变量名 要搜索的文件路径和文件类型)

注意:PROJECT_SOURCE_DIR和CMAKE_CURRENT_SOURCE_DIR在嵌套cmake下不同,一般情况下相同

指定头文件目录

include_directories(${PROJECT_SOURCE_DIR}/include)
#指定包含头文件的目录 include_directories(headpath)

项目结构

image

通过Cmake制作库文件 demo2

set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib)
#指定动态库/静态库生成的位置

add_library(库名称 STATIC 源文件1 [源文件2] ...)


eg.
add_library(calc_shared SHARED ${SRC})
#制作名称为calc的动态库(.so)

add_library(calc_static STATIC ${SRC})
# #制作名称为calc的静态库(.a)

注意:cmake后需要make才会生成库文件

在程序中链接静态库 场景:源文件较少 demo3

link_directories(<lib path>) #指定链接库的目录
link_libraries(<static lib> [<static lib>...]) #指定出要链接的静态库的名字
eg.
include_directories(${PROJECT_SOURCE_DIR}/include)
#指定包含头文件的目录 include_directories(headpath)

file(GLOB SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp)

link_directories(${PROJECT_SOURCE_DIR}/lib)
#指定静态库的路径,否则自定义的链接库找不到
link_libraries(libcalc_static.a)
#指定静态库,可以全名,也可以掐头去尾
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)
#指定可执行文件生成的位置,PROJECT_SOURCE_DIR为CMakeLists.txt所在目录
add_executable(main ${SRC})

注意:可以是全名libxxx.a,也可以是掐头(lib)去尾(.a)之后的名字xxx

项目结构

image

在程序中链接动态库 场景:源文件较多 demo4

target_link_libraries(
    <target> 
    <PRIVATE|PUBLIC|INTERFACE> <item>... 
    [<PRIVATE|PUBLIC|INTERFACE> <item>...]...)
  • target指定要加载动态库的文件的名字
    该文件可能是一个源文件
    该文件可能是一个动态库文件
    该文件可能是一个可执行文件
  • PRIVATE|PUBLIC|INTERFACE:动态库的访问权限,默认为PUBLIC
    如果各个动态库之间没有依赖关系,无需做任何设置,三者没有没有区别,一般无需指定,使用默认的 PUBLIC 即可。
  • 动态库的链接具有传递性,如果动态库 A 链接了动态库B、C,动态库D链接了动态库A,此时动态库D相当于也链接了动态库B、C,并可以使用动态库B、C中定义的方法。
    PUBLIC:在public后面的库会被Link到前面的target中,并且里面的符号也会被导出,提供给第三方使用。
    PRIVATE:在private后面的库仅被link到前面的target中,并且终结掉,第三方不能感知你调了啥库。(只传递一次)
    INTERFACE:在interface后面引入的库不会被链接到前面的target中,只会导出符号。(不发生传递)
include_directories(${PROJECT_SOURCE_DIR}/include)
#指定包含头文件的目录 include_directories(headpath)

file(GLOB SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp)

link_directories(${PROJECT_SOURCE_DIR}/lib)
#指定动态库的路径,否则自定义的链接库找不到

set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)
#指定可执行文件生成的位置,PROJECT_SOURCE_DIR为CMakeLists.txt所在目录
add_executable(main ${SRC})
target_link_libraries(main libcalc_shared.so)
#指定动态库,可以全名,也可以掐头去尾,注意:需要放在脚本末尾

日志

message([STATUS|WARNING|AUTHOR_WARNING|FATAL_ERROR|SEND_ERROR] "message to display" ...)

(无) :重要消息
STATUS :非重要消息
WARNING:CMake 警告, 会继续执行
AUTHOR_WARNING:CMake 警告 (dev), 会继续执行
SEND_ERROR:CMake 错误, 继续执行,但是会跳过生成的步骤
FATAL_ERROR:CMake 错误, 终止所有处理过程

变量操作 demo5

使用set进行拼接

set(变量名1 ${变量名1} ${变量名2} ...)

关于上面的命令其实就是将从第二个参数开始往后所有的字符串进行拼接,最后将结果存储到第一个参数中,如果第一个参数中原来有数据会对原数据就行覆盖。

使用list进行拼接

list(APPEND <list> [<element> ...])

list命令的功能比set要强大,字符串拼接只是它的其中一个功能,所以需要在它第一个参数的位置指定出我们要做的操作,APPEND表示进行数据追加,后边的参数和set就一样了。

set(TEMP "abc" "123")
file(GLOB SRC ${PROJECT_SOURCE_DIR}/src/*.cpp)
set(RES1 ${SRC} ${TEMP})
list(APPEND RES2 ${SRC} ${TEMP})
message(STATUS "message:${RES1}")
message(STATUS "message:${RES2}")

注意:file得到的是绝对路径

字符串移除

我们在通过file搜索某个目录就得到了该目录下所有的源文件,但是其中有些源文件并不是我们所需要的,在当前这么目录有五个源文件,其中main.cpp是一个测试文件。如果我们想要把计算器相关的源文件生成一个动态库给别人使用,那么只需要add.cpp、div.cp、mult.cpp、sub.cpp这四个源文件就可以了。此时,就需要将main.cpp从搜索到的数据中剔除出去,想要实现这个功能,也可以使用list

list(REMOVE_ITEM <list> <value> [<value> ...])

eg.

aux_source_directory(${PROJECT_SOURCE_DIR}/src SRC)

message(${SRC})

list(REMOVE_ITEM SRC ${PROJECT_SOURCE_DIR}/src/main.cpp)

message(${SRC})

set(str1 "123" "abc")
set(str2 "456" "def")
list(APPEND SRC ${str1} ${str2})
message(${SRC})

list的其它操作 demo5

获取list长度

list(LENGTH <list> <output variable>)
LENGTH:子命令LENGTH用于读取列表长度
<list>:当前操作的列表
<output variable>:新创建的变量,用于存储列表的长度。

读取列表中指定索引的的元素,可以指定多个索引

list(GET <list> <element index> [<element index> ...] <output variable>)
<list>:当前操作的列表
<element index>:列表元素的索引
从0开始编号,索引0的元素为列表中的第一个元素;
索引也可以是负数,-1表示列表的最后一个元素,-2表示列表倒数第二个元素,以此类推
当索引(不管是正还是负)超过列表的长度,运行会报错
<output variable>:新创建的变量,存储指定索引元素的返回结果,也是一个列表。

将列表中的元素用连接符(字符串)连接起来组成一个字符串

list (JOIN <list> <glue> <output variable>)
<list>:当前操作的列表
<glue>:指定的连接符(字符串)
<output variable>:新创建的变量,存储返回的字符串

查找列表是否存在指定的元素,若未找到,返回-1

list(FIND <list> <value> <output variable>)
<list>:当前操作的列表
<value>:需要再列表中搜索的元素
<output variable>:新创建的变量
如果列表<list>中存在<value>,那么返回<value>在列表中的索引
如果未找到则返回-1。

在list中指定的位置之前插入若干元素

list(INSERT <list> <element_index> <element> [<element> ...])

将元素插入到列表的0索引位置

list (PREPEND <list> [<element> ...])

将列表中最后元素移除

list (POP_BACK <list> [<out-var>...])

将列表中第一个元素移除

list (POP_FRONT <list> [<out-var>...])

将指定的元素从列表中移除

list (REMOVE_ITEM <list> <value> [<value> ...])

将指定索引的元素从列表中移除

list (REMOVE_AT <list> <index> [<index> ...])

移除列表中的重复元素

list (REMOVE_DUPLICATES <list>)

列表翻转

list(REVERSE <list>)

列表排序

list (SORT <list> [COMPARE <compare>] [CASE <case>] [ORDER <order>])

COMPARE:指定排序方法。有如下几种值可选:

  • STRING:按照字母顺序进行排序,为默认的排序方法
  • FILE_BASENAME:如果是一系列路径名,会使用basename进行排序
  • NATURAL:使用自然数顺序排序

CASE:指明是否大小写敏感。有如下几种值可选:

  • SENSITIVE: 按照大小写敏感的方式进行排序,为默认值
  • INSENSITIVE:按照大小写不敏感方式进行排序

ORDER:指明排序的顺序。有如下几种值可选:

  • ASCENDING:按照升序排列,为默认值
  • DESCENDING:按照降序排列

宏定义 demo6

在进行程序测试的时候,我们可以在代码中添加一些宏定义,通过这些宏来控制这些代码是否生效,如下所示:

#include <stdio.h>
#define NUMBER  3

int main()
{
    int a = 10;
#ifdef DEBUG
    printf("我是一个程序猿, 我不会爬树...\n");
#endif
    for(int i=0; i<NUMBER; ++i)
    {
        printf("hello, GCC!!!\n");
    }
    return 0;
}

在程序的第七行对DEBUG宏进行了判断,如果该宏被定义了,那么第八行就会进行日志输出,如果没有定义这个宏,第八行就相当于被注释掉了,因此最终无法看到日志输入出(上述代码中并没有定义这个宏)。
在gcc/g++命令中通过参数 -D指定出要定义的宏的名字,这样就相当于在代码中定义了一个宏,其名字为DEBUG。

在CMake中我们也可以做类似的事情,对应的命令叫做add_definitions:

add_definitions(-D宏名称)

eg.

int main()
{
    int a = 20,b = 12;
    printf("a = %d,b = %d\n",a,b);
    printf("a + b = %d\n",add(a,b));
    printf("a - b = %d\n",sub(a,b));
    
    printf("a * b = %d\n",mul(a,b));
    
    printf("a / b = %.3lf\n",div(a,b));
    
    #ifdef DEBUG
    printf("调试信息:xxxxx\n");
    #endif
    return 0;
}
add_definitions(-DDEBUG)

aux_source_directory(${PROJECT_SOURCE_DIR}/src SRC)

include_directories(${PROJECT_SOURCE_DIR}/include)

set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)

add_executable(main ${SRC})

嵌套的CMake 源代码见demo7

image

静态库中链接静态库 demo8

静态库中链接动态库 demo9

标签:SRC,cmake,list,笔记,PROJECT,SOURCE,cpp,DIR
From: https://www.cnblogs.com/zjq182/p/18124611

相关文章

  • C/C++学习笔记-eclipse不支持C++11问题
    转 https://blog.csdn.net/qq_35703954/article/details/81540315std::thread的使用,结果编译报错信息如下: 问题分析:查看错误提示,发现thread不是命名空间std的一个成员,那么我们知道thread很明显是std的成员,那么久只有一种可能:即没有引入相关的头文件,但是检查发现,头文件也有。又......
  • C语言笔记二的补充(实例应用)——猜数游戏的简单实现
    猜数字游戏要求:电脑自动生成1~100的随机数玩家猜数字,猜数字的过程中,根据猜测数据的大小给出反馈,直至才对,游戏结束。基础知识搭建:随机数的生成使用rand函数intrand(void);rand函数会返回一个伪随机数,这个随机数的范围是在0~RAND_MAX之间,这个RAND_MAX的大小是依赖编......
  • C语言笔记二——分支和循环(上)
    分支和循环1.if语句1.1if语句的语法形式如下:if(表达式)语句表达式成立(为真)语句执行;表达式不成立(为假)语句不执行。在C语言中,0为假,非0为真。//instance#include<stdio.h>intmain(){  intnum=0;  scanf("%d",&num);  if(num%2==1){   ......
  • 【学习笔记】线段树(待补)
    零、写在前面的话我发现学习笔记是真的有必要的。很多比赛甚至做题的时候,学过的算法就出现在题目里面,然而我却忘记了之前对这个算法的深入理解,甚至忘了这个算法怎么打,更甚者,看不出来这个题目可以使用这种算法解决。为了防止这种情况再度出现,我决定对自己的任何学过的算法写笔记,......
  • 【学习笔记】树链剖分
    一、重链剖分1.定义&作用树链剖分用于解决在树上执行的操作,将树上操作变为区间操作。用区间来维护。2.主要思想&实现有一棵树然后,我们把边区分一下,有一些边是“重边”,其余的是“轻边”,像这样:(红边为重边,黑边为轻)重边和轻边如何确定呢?看每一个结点旁的红色数字,代表他......
  • 【学习笔记】好题
    常来看看。Antiluna好闪,拜谢Antiluna。1.奖金每位参加会谈的代表提出了自己的意见:“我认为员工a的奖金应该比b高!”Mr.Z决定要找出一种奖金方案,满足各位代表的意见,且同时使得总奖金数最少。每位员工奖金最少为100元,且必须是整数。1≤n≤10000,1≤m≤20000。......
  • 【学习笔记】dijkstra
    一、dijkstra1.定义&作用很简单。一个单源最短路算法。2.思想&实现我觉得sm的图已经够了。二、堆优化dijkstra1.先来认识一下proirity_queue2.如何使用proirity_queue对dijkstra优化?每一步,我们都需要找到\(d\)值最小的节点(即\(......
  • 【学习笔记】spfa
    一、spfa模板:voidspfa(intx){ for(inti=1;i<=n;i++) vis[i]=0,dis[i]=inf; dis[1]=0,f[1]=1; q.push(1); while(!q.empty()) { intt=q.front(); q.pop(); vis[t]=0; for(inti=first[t];i;i=e[i].next) { intto=e[i].to; if(dis[t]+e[i].v<......
  • 【学习笔记】并查集
    一、普通并查集1.定义&作用并查集是管理元素分组的算法,可以高效对元素分组(合并为一组)以及查询两个元素是否在一组。2.主要思想&实现对于每一个组,设置一个“组长”,每一次合并时只需要将其中一组的组长设为另一组的组长,查询时只需要查询组长是否相同。每一个组都可以理解......
  • SQL SERVER 从入门到精通 第5版 第二篇 第9章 视图的使用 读书笔记
      第9章视图的使用视图是一种常用的数据库对象,它将查询的结果以虚拟表的形式存储在数据中,视图并不在数据库中以存储数据集的形式存在.视图的结构和内容是建立在对表的查询基础之上的,和表一样包括行和列,这些行,列数据都来源于其所引用的表,并且是在引用视图过程中动......