前言前言首先,可以思考一下,如果我们要去管理一堆文件,那么我们需要以何种关系结构去处理呢?如果这个问题换做是管理员工,管理学生呢?
其实这就是 CMake 文件的联系关系的思想,通过分层管理来间接获取到每一个文件,类似于框架图
介绍介绍所以我们首先需要定义一个最顶层的 CMakelist,管理版本号,以及多个
类似于
一层
CMakelist
二层
项目 1
CMakelist
项目 1_1
CMakelist
项目 1_2
CMakelist
项目 2
CMakelist
项目 3
CMakelist
项目 4
CMakelist其中通过 add_subdirectory 让上层知道下层的目录位置例如在寻找库的过程 (只是举个例子先不要在意库是什么):
实操实操对于第一次编译 add. cpp 文件的过程进行扩展,结构如下其中最底下的 CMakelists.txt 是顶层,sub 实现的是减法,mul 乘法在 add 子目录,和之前的加法实现就基本上一样,这里给出 CMakelists.txt 的配置顶层 CMakelists.txt
123456 ...
格式格式Message(模式+“${自定义/系统变量} hello world” …)其中空格也可以用 ; ,我会比较习惯用空格
普通模式普通模式模式默认空,放着不写就行
特殊模式特殊模式STATUS输出状态信息WARNING当用户错误运行时的错误信息AUTHOR_WARNING开发的时候当日志来用SEND_ERROR发送一个错误信息,但是不终止FATAL_ERROR发送一个错误信息,并且终止
STATUS可以看到前面多加了两个 - 和下面的配置和生成构建文件消息提示是一样的状态信息
WARNING此消息会提示报错行:104 行报错信息是:HELLO WORLD
AUTHOR_WARNING和 WARNING 不同的是多了一行只能由开发者去解决的报错提示 此警告适用于项目开发人员。 使用 -Wno-dev 来抑制它。
SEND_ERROR和上面的 WARNING 的差别在于输出的报错信息是和 WARNING 相似的但是下面的配置,生成,构建均不成功
FATAL_ERROR和 SEND_ERROR 类似,但是会直接终止下面的构建,可以看到本一个出现的分割线没有输出了
以上是各个模式下出现 ...
CMake
未读语法条件语句条件语句在 CMake 中,你可以使用 if、elseif、else 和 endif 来进行条件控制:
1234if( ) # 执行当条件为真时的命令elseif( ) # 执行当第一个条件为假而这个条件为真时的命令 else() # 执行当所有条件都为假时的命令 endif()
条件可以基于变量的值、是否定义了变量、文件是否存在等条件。
循环循环CMake 支持 foreach 循环和 while 循环。
其中 CMake 3.0以及更高版本中,你可以使用 IN LISTS 或 IN ITEMS 语法来明确指示 foreach 循环应该遍历的是列表变量或者是后面直接指定的项,使得 CMake 脚本更易读、写和维护。
使用 foreach 循环遍历列表中的每个项:如果有需要遍历自己定义的变量那么
12foreach(loop_var IN [LISTS <list...>] [ITEMS <items...>]...) # 对列表中的每个项执行命令 注意ITEMS项要在LISTS后面 endforeach()
例如:混用的时候作用 ...
总体流程总体流程CMake 的流程有以下的步骤了解过程会更好地帮助我们去理解整个 cmake 在干什么,debug 的时候更容易去定位错误
例如当对于任意合法的 CMakelist.txt 执行 cmake --build .Configuring done 配置完成Generating done 生成完成Build files have been written to… 构建文件已写入…(说明构建成功)如果构建不合法则会出现如果是配置和生成出现错误,那么就一定是 CMake 配置或 CMakelist 配置没有配置好
编译过程编译过程事实上,CMake 只是处理配置和生成两个阶段,换一句话说 CMake 的配置和生成都是 cmake 自己的事情,而到了编译阶段则是调用其他的工具来进行编译 CMake 可以通过特定的命令(如 cmake --build .)来调用这些工具,但本质上它是在为这些工具提供参数,实际的编译工作是由那些如 make, ninja 工具完成的。(区分好各司什么职很重要)
以下是编译过程:
接下来我们通过 g++来来看看具体是怎么样处理的
预处理预处理g++ -E ...
CMake
未读前言前言本文分享的是关于如何去最简单地通过 CMake 去编译一个文件。
准备阶段准备阶段首先先编写一个 .cpp 文件和 .hh 头文件内容如下和可执行文件 .main
编写 CMakelists编写 CMakelists在 main 的同级目录下创建一个 CMakelist.txt 的文件编译如下
12project(cmake_study)#定义一个项目名add_executable(lesson1_1 main.cpp add.hh add.cpp)#把需要的文件交给cmake进行编译
然后我们就可以看到构建出来的文件然后我们 cd 到 build 目录下运行 .\lesson1_1.exe(在 win 下的指令,如果是在 linux 系统下要用 ./lesson1_1.exe)然后我们就得到输出的结果
这就是已经可以最简单去编译一个 .cpp 文件了
一些优化一些优化然后我们也可以把头文件通过 include_directories(头文件绝对路径) 的形式引入,或者更好的方式是 target_include_directories() 这样我们就可以只 add_execu ...
CMake
未读开始开始原始的文件如下 :
我们新建一个 Makefile
123main: main.cpp add.cpp g++ main.cpp add.cpp -o main
然后再同级目录下就可以调用 make 文件来生成可执行文件了,cs 144 中 lab 0 也是如此,其中 make 的动作用处就是制作可执行文件 webget,然后传入两个参数的同时调用程序
回到我们刚刚的代码,这里我们同级目录下 make出现可执行文件:
那么怎么方便的 Makefile 为什么我们还需要使用 CMake?
统一了编译流程统一了编译流程虽然 Makefile 直接通过 make 就可以编译,似乎很简单,但是遇到的问题就是在于无法跨平台使用(假设只能在 win 上使用 visualstudio)所以 CMake 就起到了统一的作用
如何通过 CMake 来编译可执行文件如何通过 CMake 来编译可执行文件编译过程由于我们的编译文件都在同级所以要先移动到 build 文件下cmake .. 后面一个参数-B 的作用是指定 Makelists.txt 的位置可以看到 build 文件夹下就有我 ...
CMake
未读CMake 是什么CMake 是什么是一个工具集,用来生成构建工具脚本,例如 ninja(跨平台),make(linux),visual studio(win),xcode(mac)就像一个厨师,你把菜递给他,他选择用什么样的工具帮您编译。
CMake 的作用CMake 的作用总得来说
作用是:编译+测试+打包
生成构建工具,构建源码
单元测试
打包(编译构建工具,或者是源码)比如说做成 rpm 包之类的,就是给人的印象很好,因为是适配平台的直接安装的过程,而则需要用到打包
为什么需要 CMake为什么需要 CMake使用便利其实从最大的用处上来说,他们就是提供了一个平台,实现编译期大部分跨平台的功能(如果调用了系统的 API 可能跨不了)。如果你学会 CMake,那么就无需纠结你是在什么平台下去编译,而额外学习一门新的工具,真正做到了一站式通用。例如可以看这一篇: 从Makefile到CMake
历史原因CMake 的产生可以追溯到20世纪90年代末期。当时,为了提高软件跨平台的构建效率,Kitware的团队开始开发一个名为CMake(Cross-platform Make) ...
CMake
未读主体思路本系列会采用自顶向下的想法来给大家分享学习的 CMake过程中会举简单的例子,例子会通过图片的形式,或是理清楚结构,或是给于相对应的代码-打印给一个直观的表现。
CMake 章节
引入
CMake学习分享-前言
CMake是一个怎么样的工具
从Makefile到CMake
开始·
如何编译一个.cpp文件
CMake 处理项目流程(处理项目时究竟干了些什么事情)
CMake 语法
CMake_流程控制,函数和宏
CMake_message,set,list的用法
进一步
如何统一编译管理多个.cpp文件
CMake 库
CMake 静态库
CMake 动态库
CMake 平台差异
优化
CMake 降低耦合
CMake常用指令推荐
CMake优雅地使用环境变量
更进一步
通过CMake使用opencv-lesson 2_CMake
心路历程学习 CMake 我也是学习不久,很多方面都是在 b 站看“简明教程“和“比飞鸟贵重的多_HKL”两位 up 主的教学,我想做到的是能够把这两位 up 主讲的汇总在一起,并且通过我的理解,告诉大家。从项目接触 ...
CS144-5test1 1前言cmake --build build --target check4如下就可以开始代码了
</div>这一次是要实现一个路由表的功能,你需要去做一个存储路由的功能。
我使用的结构体加vector的组合来实现这一部分,当然你可以自己想一个合适的,我选择这种组合的原因是,用map来实现的话那么用什么来映射呢,又如何知道哪一个是最优的匹配路径,只能通过遍历,然后再通过算法去实现查询,我目前的思路是这样的,所以选择能支持快速增删的简单结构
其中实现的重点在于寻求最优匹配,这一部分涉及到网络掩码的内容,如果不懂这一部分的友友,可以去b站搜搜看,大概的意思就是多少位是一样的,剩下的这可变化的区域作为子网段,掩码的作用就是规定了这个范围,同时也告诉我们匹配的长度,用于后续求最优的依据。
test1 1实验开始我阅读完文档可以罗列出的思路是这样的
</div>实现完代码后的思路是这样的
</div>以上就是我整体的思路
难的是匹配路由表的函数,这个函数是需要通过提供的匹配长度,然后推算出当前是否是匹配的路由,后面我们可以通过这个匹配 ...
CS144-4test1 1test1 2前言cmake - - build build - - target check3如下就可以开始lab4了
</div>做着这部分最好的就是了解一下报文的类型,和结构关系。我当时做的时候在里面绕了很多弯,比如说误以为ARP以太网包是带普通数据报的,当时想是ARP顺便发过去,后面发现不是,ARP以太网包只含ARP,普通数据以太网包只含普通数据报文(IPV4)。
其中的我整理的以太网头部对应的数据类型信息如下
test1 1test1 2test1 3test1 4实验开始鉴于之前我思路不清晰导致一个lab就在调试方面浪费太多太多时间,我后面使用一些图的关系来表示当时的思路
如何去广播?
其中会遇到的问题1:包有两种那么他们的一个关系是如何的?ARP 包和 ipv 4 包,最大的不同其实也就是以太网包的东西不同,以太网有一个以太网头部和以太网主体部分,以太网头部存储的只有 mac 地址(发送和接收,Ip 的部分分析是由主体部分进行一个拆包实现的,对其包涵的东西进行一个拆包,但是主体仍然存在 mac 地址,这个 mac 地址才是真正需 ...