Linux系统下利用cmake工具进行C++的编译

前言

  在Linux|Ubuntu系统下利用cmake工具进行C++的编译,我们需要掌握一些基本知识:

  • Linux系统的一些基本命令行语句
  • cmake工具的使用方法
  • C++的编译流程

1.Linux|Ubuntu系统的基本命令行语句

  在Ubuntu系统中,我们需要掌握一些常用的命令行语句,因为我们并不搞Linux系统的运维工作,所以只需要知道一些基础的足够我们应用的命令行语句即可,真正需要用到其他的再上网查找即可。
  笔者列出了如下一些比较基础的命令行语句:

命令作用
cd (目录名)打开目录
cat (文件名)在终端查看文本内容(不能修改)
ls -l (目录名)以长格式显示文件的目录和详细信息、权限、所有者、大小、修改日期
ls -a (目录名)显示所有文件和目录,包括以点开头的隐藏文件
ls -h (目录名)显示单位大小
stat (目录名/文件名)显示目录/文件的详细信息
tree (目录名)树状表的形式显示目录和文件
mkdir (目录名)创建一个新的目录
touch (文件名)创建一个新的文件
rm (文件名)删除文件
rm -r (目录名)删除目录
rm -f (目录名)强制删除,不带提示
rmdir (目录名)删除目录
mv (文件/目录名)(目录)移动(文件/目录名)到(目录),加 -i ,同名文件询问是否覆盖
mv (旧名称)(新名称)重命名,加 -i ,同名文件询问是否覆盖
cp (旧文件名)(新文件名)复制文件, -i ,同名文件询问是否覆盖
cp -r (旧目录名)(新目录名)复制目录, -i ,同名文件询问是否覆盖

  这些是笔者认为非常基础的命令,当然还有一些文件查找以及线程的命令就不一一列举了,除此以外,文件权限也是需要了解的一项内容:

权限类型作用
r可读,可进入目录/可读取普通文件内容
w可写,(前提是有r权限先进入)可在目录中创建或删除目录或文件,可修改目录下的普通文件
x可执行/切换目录,(前提是有r权限先进入)可访问目录下的文件或子目录或可执行文件
-无权限

  例d rwx rwx rwx是一个文件或目录的权限信息:第一项为文件类型,第一组的三个参数为所有者的权限,第二组的三个参数为用户组的权限,第三组的三个参数为其他人的权限。
  apt是Ubuntu中自带的一个软件包管理工具,可以自动解决软件的依赖问题,是一个必须要了解的工具。

2.cmake工具

  在Ubuntu终端中输入sudo apt install cmake ,下载cmake工具,首先我们需要了解为什么需要cmake工具,cmake工具是干嘛用的。
  笔者喜欢使用C++进行程序编写,所以要用到g++编译器,在工程比较小的时候,可以手动使用g++对源码文件进行编译,但工程量一旦增加,需要对大量的源码文件进行编译,而且在进行编译的时候,需要链接很多额外的库,这是一件非常麻烦的事情,因此不知道哪位大佬想到了去执行一个配置文件,在配置文件中提前写好要进行的编译过程,这个配置文件就叫做makefile,去执行这个makefile的工具叫做make,但是随着时间的流逝,大家发现makefile也挺麻烦的,还存在代码跨平台的一些问题,就又有大佬想到了,去写一个比较简单的CMakeLists.txt文件,然后用cmake工具去执行CMakeLists.txt文件,生成makefile文件,再用make工具执行这个利用CMakeLists.txt文件生成的makefile文件,所以对于现在的程序猿来说,去写一个简单的CMakeLists.txt文件,就可以很方便的对代码进行编译。因此我们需要掌握如何写一个CMakeLists.txt文件,这是一件很重要的事情!!!
  cmake就是一种语言,他有自己的函数,就像c++一样,每一个函数都有自己的目的,cmake不像c++那样具有大量灵活的函数,可以执行各种不同的功能,cmake的函数目标明确,生成可执行文件或者

生成可执行文件:生成可执行文件,必要的两点:
1.链接源码文件
2.链接库文件(很简单的代码,没有库文件则不用链接,但一般我们接触到的代码都要链接库,第三方库也好,自己做的库也好)
3.包含头文件目录
为什么只包含头文件的目录呢?而不是像包含库文件一样,包含具体的头文件。
  包含头文件的实际操作是在源代码中使用 #include 预处理指令来引用特定的头文件,当编译器在编译源代码时遇到 #include 指令,它会根据包含的头文件目录查找相应具体的头文件。因此在源代码中使用 #include 指令时,只需要提供头文件的相对路径。
  只要知道库文件所在目录需要链接的库文件头文件所在目录就可以完成可执行文件的生成,除此以外,我们还需要知道生成的这些文件应该保存到哪里,在做这些工作之前,我们应该先了解一下cmake函数的一些常见的预定义的变量(在cmake刚刚开始执行的时候,cmake自动设置生成的一些变量)

生成库文件:必要的一点:
链接源码文件


1. CMAKE_SOURCE_DIR:
  这是一个非常重要的预定义变量,默认值是CMakeLists.txt文件所在目录的绝对路径。

2. CMAKE_BINARY_DIR:
   默认值是当前cmake的工作路径,在哪个路径执行的cmake命令,工作路径就是哪个位置,一般是在与CMakeLists.txt文件同目录中创建一个build文件夹,在build中执行cmake命令,当然也可以在其他位置,建其他名称的文件夹,主要是存放cmake以及make时产生的一些文件,有用的,没用的,不知道是啥的一堆,后面要设置参数把有用的找出来。

3. CMAKE_LIBRARY_OUTPUT_DIRECTORY:
  这是动态库的输出路径,默认是在CMAKE_BINARY_DIR这里面,我们一般都是要自己去设置这个值的,放在自己“喜欢”的地方(第三方依赖库会有明确的设置放在哪里,cmake内置了一些第三方库的一些默认安装位置,自己不要乱改)。(有一个老版本的参数叫做LIBRARY_OUTPUT_PATH,都一样)

4. CMAKE_ARCHIVE_OUTPUT_DIRECTORY:
  这是静态库的输出路径,默认是在CMAKE_BINARY_DIR这里面(同上)。(有一个老版本的参数叫做ARCHIVE_OUTPUT_PATH,都一样)

5. CMAKE_RUNTIME_OUTPUT_DIRECTORY:
  这是可执行文件的输出路径,默认是在CMAKE_BINARY_DIR这里面的,自己可以修改位置。(有一个老版本的参数叫做EXECUTABLE_OUTPUT_PATH,都一样)

6.CMAKE_INCLUDE_CURRENT_DIR:
  是否将 CMAKE_SOURCE_DIR当作头文件的目录包含到全局(这里提到包含到全局,是因为还有与之对应的,只将头文件的目录包含的目标文件上,而不是作用到全局所有目标文件上)

这里笔者展示一个函数 set(),是用来改变这些变量的值的。


  • 生成可执行文件


1.链接源码函数:

add_executable(目标 源码文件)
源码文件可以用相对路径,CMAKE_SOURCE_DIR/…,如果源码文件就在CMAKE_SOURCE_DIR路径(源码文件和CMakeLists.txt文件在一层目录),那么直接写源码文件的文件名即可,如果源码文件在src目录中(src与CMakeLists.txt文件在一层目录),那么必须写成src/源码文件,CMAKE_SOURCE_DIR是可以省略的,因为cmake默认在CMAKE_SOURCE_DIR路径下查找。

2.链接库文件函数:

target_link_directories(目标 库文件所在目录)
连接库文件所在目录到指定目标,链接库文件时从此目录查找,同样的,如果只写了库文件名称,那么cmake也会默认在CMAKE_SOURCE_DIR路径搜索该库文件,当库文件在其他位置时,需要使用绝对路径。

target_link_libraries(目标 库文件)
链接库文件到指定目标,同样的,如果只写了库文件名称,没有进行上一个函数设置库文件所在目录,那么cmake也会默认在CMAKE_SOURCE_DIR路径搜索该库文件,如果库文件正好在CMAKE_SOURCE_DIR路径,则链接成功,否则链接失败。

3.包含头文件目录函数:

target_include_directories(目标 头文件所在目录)
包含头文件的目录到指定目标。

include_directories(头文件所在的目录)
不指定目标,对整个项目中的目标都包含这个头文件目录。


  • 生成库文件

add_library(库名 SHARED 源码文件)生成动态库
add_library(库名 STATIC 源码文件)生成静态库
不指定参数,则默认设置为静态库,同样的,如果源码文件在CMAKE_SOURCE_DIR路径,则直接写源码文件名称,否则需要源码文件的绝对路径,如果想连续两次使用此函数,去输出一个静态库和一个动态库,库名不能设置为相同(我也不清楚为啥,这么干就完了,后面我们还可以用其他的函数再改名称)。
set_target_properties()该函数可以改名称。


笔者根据自己的了解去大概解释一下静态库和动态库

静态库:在编译时,编译器将目标可执行文件需要链接的静态库文件复制一份,打包到可执行程序中,这样会让可执行程序很臃肿,运行速度也会降低

动态库:在编译时,将一个配置文件写入到可执行文件中,在可执行文件要运行的时候,解析编译文件,找到需要链接的动态库的目录,在运行过程中链接动态库


补充两个函数:
  findpackage(),该函数可以用来寻找一些标准第三方库的配置文件,并解析该配置文件,得到这种标准第三方库的库文件,头文件等绝对路径信息,方便使用者更容易地配置第三方库,列如opencv,这种配置文件一般叫做OpenCVConfig.cmake。

  还有一个更重的是add_subdirectory(),添加子目录,一个项目并不是只能有一个CMakeLists.txt文件,可以有很多目录,每个目录中都可以有一个CMakeLists.txt文件,cmake工具就像一个组织者,对于一个庞大的项目,分块组织代码们,最后再聚拢到主CMakeLists.txt文件中,说的很抽象,不想继续解释这里了,笔者的表述能力比较差,如果读者希望了解更多的,笔者熬夜给你造出来!
  笔者上文中提到的内容不太完整,但cmake的大致思路就是这样,具体的一些小细节大家自己查查资料,还是很容易查到的。

3.C++的编译调试

直接偷的图
在这里插入图片描述
  笔者在上文大概只是说了链接相关的部分,因为笔者认为这部分是我们更应该掌握的,预处理阶段也应该了解一下,但对于编译和汇编部分,生成的是啥我都不清楚,我也没用到他们产生的文件,实在不想看了,
  我们在写代码的时候不可能写完就是完全正确的,编译链接就能运行,一定会产生错误,因此我们需要进行调试,这就产生了,调试和发布两个版本的可执行文件,调试版本就是我们调试代码,寻找错误的一种方式,是一种半成品,发布版本是我们的代码可以正常运行了,让编译器自动优化一下代码,产生一个发布版本,这是成品。

设置构建类型为 Debug 或 Release
set(CMAKE_BUILD_TYPE "Debug或 "Release")
  CMAKE_CXX_FLAGS_DEBUG 是一个 CMake 变量,用于设置在 Debug 构建类型下 C++ 编译器的编译选项。在 CMake 中,CMAKE_CXX_FLAGS_DEBUG 变量用于指定 Debug 构建类型时要传递给 C++ 编译器的选项。通过修改这个变量,您可以在 Debug 构建中设置特定的编译选项。通常,CMAKE_CXX_FLAGS_DEBUG 变量的默认值为空,可以通过在 CMakeLists.txt 文件中设置该变量来添加您需要的选项。例如:

set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -O0 -g")


优化选项:

-O0、-O1、-O2、-O3:指定不同级别的优化。-O0 表示不进行优化,-O1 表示基本优化,-O2 表示更高级别的优化,-O3 表示最大程度的优化。
-Os:优化代码大小,尽量减小可执行文件的大小。
-Ofast:启用更高级别的优化,可能牺牲一些严格的标准兼容性。


调试选项:

-g:生成调试信息,用于调试可执行文件。
-ggdb:生成更详细的调试信息,用于使用 GDB 进行调试。


警告选项:

-Wall:启用常见的编译警告。
-Werror:将警告视为错误,导致编译过程中出现警告时中止编译。
-Wextra:启用额外的编译警告。
-Wno-:禁用特定的警告。


代码生成选项:

-std=:指定要使用的 C++ 标准版本,如 -std=c++11、-std=c++14、-std=c++17 等。
-fPIC:生成位置无关代码,用于共享库。
-fno-exceptions:禁用 C++ 异常处理。
-fno-rtti:禁用运行时类型信息。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值