cmake基础知识

编译器

将.cpp文件转换成.out文件(可执行的汇编文件)

多文件编译与链接

一个.cpp文件太大时---->不利于模块化和理解
—> 分成多个文件编译成.o文件(不可执行的汇编文件)----》在合成.out文件
cmake基础知识_第1张图片

构建系统

一个个调用g++太慢了----------->make程序----->在定义依赖关系后,能自动实现多文件编译和链接
在改动一个文件后只会编译更改过的文件
问题:
cmake基础知识_第2张图片
解决:(cmake)
1.只要自己定义cmakelists.txt文件就能,自动生成当前系统所支持的构建系统
cmake基础知识_第3张图片
2.cmake可以自动检测出源文件和头文件的依赖关系,输出到makefile里
3.cmake有内置函数能处理一些常见需求
4.cmake可以自动检测当前编译器,需要添加那些flag

cmake的命令行调用

cmake基础知识_第4张图片

库的使用

  • 有时候我们会有多个可执行文件,他们之间用到的某些功能是相同的,我们想把这些共用的功能做成一个库,方便大家一起共享。
  • 库中的函数可以被可执行文件调用,也可以被其他库文件调用。
  • 库文件又分为静态库文件和动态库文件。
  • 其中静态库相当于直接把代码插入到生成的可执行文件中,会导致体积变大,但是只需要一个文件即可运行。
  • 而动态库则只在生成的可执行文件中生成“插桩”函数,当可执行文件被加载时会读取指定目录中的.dll文件,加载到内存中空闲的位置,并且替换相应的“插桩”指向的地址为加载后的地址,这个过程称为重定向。这样以后函数被调用就会跳转到动态加载的地址去。
  • Windows:可执行文件同目录,其次是环境变量%PATH%
  • Linux:ELF格式可执行文件的RPATH,其次是/usr/lib等

cmake基础知识_第5张图片
在CMakeLists.txt中生成动态库和静态库:
add_library(test STATIC source1.cpp source2.cpp) # 生成静态库 libtest.a
add_library(test SHARED source1.cpp source2.cpp) # 生成动态库 libtest.so
cmake基础知识_第6张图片

为什么C++需要声明

cmake基础知识_第7张图片

  • 在多文件编译章中,说到了需要在 main.cpp 声明 hello() 才能引用。为什么?
    1.因为需要知道函数的参数和返回值类型:这样才能支持重载,隐式类型转换等特性。例如 show(3),如果声明了 void show(float x),那么编译器知道把 3 转换成 3.0f 才能调用。
    2.让编译器知道 hello 这个名字是一个函数,不是一个变量或者类的名字:这样当我写下 hello() 的时候,他知道我是想调用 hello 这个函数,而不是创建一个叫 hello 的类的对象。

头文件的使用

cmake基础知识_第8张图片
既然每个 .cpp 文件的这个部分是一模一样的,不如我把 hello() 的声明放到单独一个文件 hello.h 里,然后在需要用到 hello() 这个声明的地方,打上一个记号,#include “hello.h” 。然后用一个小程序,自动在编译前把引号内的文件名 hello.h 的内容插入到记号所在的位置,这样不就只用编辑 hello.h 一次了嘛~

"hello.h"代表优先搜索当前目录
用< cstdio >可以改成“ cstdio ”,但是不能轻易回用

  • 递归地使用头文件
    cmake基础知识_第9张图片

但是这样造成一个问题,就是如果多个头文件都引用了 MyClass.h,那么 MyClass 会被重复定义两遍:
cmake基础知识_第10张图片

  • 解决方案:在头文件前面加上一行:#pragma once
  • 这样当预处理器第二次读到同一个文件时,就会自动跳过
  • 通常头文件都不想被重复导入,因此建议在每个头文件前加上这句话

CMake 中的子模块

复杂的工程中,我们需要划分子模块,通常一个库一个目录
cmake基础知识_第11张图片

  • hellolib 文件夹里面的 CMakeLists.txt 定义了 hellolib 的生成规则
  • 要在根目录使用他,可以用 CMake 的 add_subdirectory 添加子目录,子目录也包含一个 CMakeLists.txt,其中定义的库在 add_subdirectory 之后就可以在外面使用。
    cmake基础知识_第12张图片
    因为 hello.h 被移到了 hellolib 子文件夹里,因此 main.cpp 里也要改成
    cmake基础知识_第13张图片
    如果要避免修改代码,我们可以通过 target_include_directories 指定a.out 的头文件搜索目录:(其中第一个 hellolib 是库名,第二个是目录)
    在这里插入图片描述
    这样甚至可以用 来引用这个头文件了,因为通过 target_include_directories 指定的路径会被视为与系统路径等价:
    cmake基础知识_第14张图片
    但是这样如果另一个 b.out 也需要用 hellolib 这个库,难道也得再指定一遍搜索路径吗?
    不需要,其实我们只需要定义 hellolib 的头文件搜索路径,引用他的可执行文件 CMake 会自动添加这个路径:
    cmake基础知识_第15张图片
  • 这里用了 . 表示当前路径,因为子目录里的路径是相对路径,类似还有 … 表示上一层目录。
  • 此外,如果不希望让引用 hellolib 的可执行文件自动添加这个路径,把 PUBLIC 改成 PRIVATE 即可。这就是他们的用途:决定一个属性要不要在被 link 的时候传播。

你可能感兴趣的:(linux,服务器,运维)