一篇文章搞懂CMake(gcc、g++、cmake解释)

这篇具有很好参考价值的文章主要介绍了一篇文章搞懂CMake(gcc、g++、cmake解释)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一篇文章搞懂CMake (gcc、g++、cmake解释)

gcc

gcc命令来自英文词组“GNU Compiler Collection”的缩写,其功能是用于C/C++语言编译器。原文链接:https://www.linuxcool.com/gcc

GCC 的编译流程包括以下几个阶段:

  • 预处理(Preprocessing):对源代码进行宏替换、头文件展开等操作,生成预处理文件(.i 文件)。
  • 编译(Compilation):将预处理文件转换为汇编代码(.s 文件)。
  • 汇编(Assembly):将汇编代码转换为目标文件(.o 文件)。
  • 链接(Linking):将目标文件与库文件等链接起来,生成可执行文件。

下面是一个简单的示例,以 C 语言为例:

#include <stdio.h>

int main() {
    printf("Hello, world!\n");
    return 0;
}

我们可以使用以下命令编译:

gcc hello.c -o hello

这个命令将进行以下几个步骤:

  1. 预处理,还是c语言文件,但是对头文件(<stdio.h>)和宏会进行展开
gcc -E hello.c > hello.i # 和 gcc -E hello.c -o hello.i 效果是一样的
  1. 编译,由c文件变成汇编文件
gcc -S hello.i -o hello.s
  1. 汇编,生成目标文件,即二进制文件,但是此时的文件是没有链接的,不可以执行
gcc -c hello.s -o hello.o
  1. 链接,生成可执行文件
gcc hello.o -o hello

运行该文件会输出 “Hello, world!”。

g++

gcc和g++是两个不同的编译器,gcc主要用于编译C语言代码,g++则主要用于编译C++代码

虽然gcc也可以编译C++代码,但是使用g++更为方便。因为g++可以自动链接C++标准库,而gcc需要手动链接C++标准库。此外,g++还能够自动识别C++代码,并调用相应的编译器。

在使用g++编译C++代码时,需要使用“.cpp”作为文件扩展名。如果使用“.c”作为文件扩展名,g++会将代码识别为C语言代码进行编译,而不是C++代码。

参考: https://www.cnblogs.com/lulipro/p/6661763.html

编译流程和 gcc 是一样的,只需要把 gcc 换成 g++ 即可

  • -save-temps 保留编译产生的中间文件,使用这个参数,就没必要将前面的参数 -E -S -c 一个一个地使用了
g++ -save-temps -o hello hello.cpp 
  • 优化器
g++ -O2 hello.cpp -o hello

-O0: 不进行优化,编译速度最快,但是生成的可执行文件执行速度最慢。
-O1: 开启一些简单的优化,会消耗更多的编译时间,但是可以稍微提高可执行文件的执行速度。
-O2: 开启更多的优化,可以提高可执行文件的执行速度,但是编译时间也会更长。
-O3: 开启大部分优化,可以极大地提高可执行文件的执行速度,但是编译时间也会非常长。
-Os: 优化可执行文件的大小,尽可能减小生成的可执行文件的体积。

一般用O2就够了,可以看到下面的这段代码,写的非常不合理,但是经过优化之后效率高了很多

  • -w
    编译时,不显示任何警告消息。

  • -Wall
    编译时,显示所有出现的警告消息。

cmake

CMake是一个跨平台的自动化构建系统,可以根据不同的平台、不同的编译器,生成相应的构建文件(如Makefile或Visual Studio项目文件等),以便进行编译、链接等操作。CMake通过CMakeLists.txt 文件来描述项目的构建过程,用户可以在这个文件中定义源代码、库、头文件、编译选项等信息,从而让CMake自动生成相应的构建文件。

举个例子: 比如说有一个项目需要跨平台,windows 下用 VS 编译,linux 下用 makefiles 或者 xcode 编译。如果这时候需要添加一个 bar.cpp 文件,一般做法就是每个IDE的项目文件中依次添加,但是如果工程太大,这种做法就很麻烦了,因此引入cmake就是为了方便,只需要把 bar.cpp 添加到 CMakeLists.txt 文件中即可。

1. CMake 流程

在 gcc小节 中给出了程序生成可执行文件的流程,但是如果程序很多的时候,这种方式就显得太繁琐了。因此就需要用到 makefile,makefile 是一种能够自动化构建和编译项目的文本文件。简单来说只要存在 makefile文件, make 一下就能完成项目的编译工作。

但是夸平台的话,新的矛盾就会显现出来,makefile 通常依赖于当前的编译平台,而且编写 makefile 的工作量比较大,解决依赖关系时也容易出错。

因此 CMake 能够解决该问题,它能跟据不同的编译平台,自动生成 Makefile 文件,流程如下:

如何使用cmake?

简单的CMake.txt文件

CMake 最基本的步骤是以下三步:

# 最低 CMake 版本要求:指定项目所需的最低 CMake 版本
cmake_minimum_required(VERSION 3.12)

# 项目名称:使用 project() 命令设置项目的名称
project(MyProject)

# 将源文件添加到项目中
add_executable(myapp main.cpp)

举个例子

创建以下几个文件

add.c

#include <stdio.h>
#include "head.h"

int add(int a, int b)
{
    return a+b;
}

div.c

#include <stdio.h>
#include "head.h"

double divide(int a, int b)
{
    return (double)a/b;
}

head.h

#ifndef _HEAD_H
#define _HEAD_H
// 加法
int add(int a, int b);
// 减法
int subtract(int a, int b);
// 乘法
int multiply(int a, int b);
// 除法
double divide(int a, int b);
#endif

main.c

#include <stdio.h>
#include "head.h"

int main()
{
    int a = 20;
    int b = 12;
    printf("a = %d, b = %d\n", a, b);
    printf("a + b = %d\n", add(a, b));
    printf("a - b = %d\n", subtract(a, b));
    printf("a * b = %d\n", multiply(a, b));
    printf("a / b = %f\n", divide(a, b));
    return 0;
}

head.h

#include <stdio.h>
#include "head.h"

int multiply(int a, int b)
{
    return a*b;
}

sub.c

#include <stdio.h>
#include "head.h"

// 你好
int subtract(int a, int b)
{
    return a-b;
}

建立相关文件并保存

在同一目录下新建一个 CMakeLists.txt 文件
输入下面内容并保存:

# 最小版本
cmake_minimum_required(VERSION 3.0)
# 工程名
project(Test)
# 将所有相关文件都添加进来,用于编译
add_executable(myapp add.c div.c main.c mult.c sub.c)

文件结构如下:

我们在当前文件下执行下面的操作:

1.建立一个文件夹,因为cmake之后会生成很多文件

mkdir bulid

2.进入到新建文件夹中

cd bulid

3.执行 cmake 生成 Makefile

cmake ..

cmake指令需要在和 CMakeLists.txt 文件同一个目录下执行,因此需要…

cmake之后我们发现在build文件夹下多了 Makefile 以及其他文件

4.执行 make 指令生成可执行文件

make

5.执行文件,测试是否编译成功

至此一个简单的 cmake 编译过程就结束了。

参考

[1] https://subingwen.cn/cmake/CMake-primer/?highlight=cmake文章来源地址https://www.toymoban.com/news/detail-472536.html

到了这里,关于一篇文章搞懂CMake(gcc、g++、cmake解释)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 搞懂TVS管,有这篇文章就够了

    摘要:本文主要介绍TVS的工作原理、关键参数和选型。 TVS(Transient Voltage Suppressors,瞬态电压抑制器)又称雪崩击穿二极管,是一种高效电路保护器件,主要是保护电路不受瞬态高压尖峰脉冲(静电或雷击浪涌)的冲击。 TVS是采用半导体工艺制成的单个PN结或多个PN结集成的器件,

    2023年04月08日
    浏览(54)
  • 一篇文章带你搞懂前端Cookie

    浏览器Cookie相信各位点进这篇文章的小伙伴应该不陌生了,它是前端领域中一个非常重要的内容,当然也是面试的一个考点,不知道各位小伙伴是否真正掌握了Cookie呢?当然没有掌握也是没有关系的,可以跟着小编的脚步一起来学习一下前端Cookie,没有熟练掌握的小伙伴看完这

    2024年02月04日
    浏览(46)
  • 一篇文章带你搞懂stm32工程文件

    本文以stm32f4为例,讲解stm32标准库工程中各个文件的作用,学艺不精,如有错误,望大家私信或评论指出。 先看思维导图 startup_stm32f427xx.s  该文件是stm32的启动文件,由汇编语言编写,主要是做stm32上电时的配置设置(如堆栈指针,时钟数)并跳转到main函数中,执行c代码。

    2024年02月21日
    浏览(53)
  • 一篇文章搞懂前端sso需要做什么

    父域 Cookie 认证中心 LocalStorage 跨域 一般情况下,用户的登录状态是记录在 Session 中的,要实现共享登录状态,就要先共享 Session,但是由于不同的应用系统有着不同的域名,尽管 Session 共享了,但是由于 SessionId 是往往保存在浏览器 Cookie 中的,因此存在作用域的限制,无法

    2024年02月20日
    浏览(48)
  • 一篇文章让你搞懂自定义类型-----结构体

    结构是一些值的集合,这些值称为成员变量。结构的每个成员可以是不同类型的变量 例如描述一个学生 在声明结构的时候,可以不完全的声明 比如 上面的两个结构在声明的时候省略掉了结构体标签(tag) 那么问题来了 警告: 编译器会把上面的两个声明当成完全不同的两个

    2024年02月16日
    浏览(53)
  • 一篇文章带你搞懂GIT、Github、Gitee

    本文介绍了GIt,GitHub,Gitee的使用,与IDEA的Git配置,跟着文章来做你很快就能学会操作Git,利用其进行版本控制与代码托管,学习Git的使用、Git常用命令、Git分支,分支是团队协作的基础,介绍了团队内,外协作和Github远程仓库的操作、使用IDEA中的Git、IDEA中GIt的使用、在I

    2023年04月19日
    浏览(54)
  • 什么是区块链?一篇文章搞懂区块链本质

    鉴于我对区块链的关注,以及很多关注我的朋友们,并不是很清楚区块链的本质和潜力点,所以今天在地铁里疏离了一下,并分享给大家。 你见过钱吗?我相信你是没见过真正的钱的。 这是钱吗? 这是“钞票”,而不是钱!这不是抠字眼,且听我细细道来。 别人管你借钱的

    2024年01月22日
    浏览(46)
  • Unity/C#------委托与事件(一篇文章彻底搞懂...)

            所有的代码语言创造者母语都是英语,我们从英语翻译到中文的过程中难免会存在一些不太能还原本意的词,比如我之前一直不理解构造函数和析构函数,只知道这俩货作用相反,直到我看到了它的英文意思,Construstor/Distructor,我才彻底理解了他们的作用。      

    2024年02月06日
    浏览(51)
  • 一篇文章搞懂BUCK开关电源基础理论(上)

    欢迎关注我的公众号,每周电路与硬件知识分享↓ 在硬件开发的过程中,BUCK拓扑的开关电源是很常见的,相比于LDO的降压方式 BUCK降压的效率大大提高(尤其是在压差高、输出电流大的情况)。虽然BUCK降压电路有一些缺点,比如引入开关噪声、EMI、输出电压纹波相比于LDO偏

    2024年02月13日
    浏览(46)
  • 还没搞懂重写和重载吗?这篇文章可以帮助你

    首先,会大致介绍一下什么叫做向上转型,方便后续的理解 提示:以下是本篇文章正文内容,下面案例可供参考 向上转型是Java的一个多态性的表现形式。指的是一个子类的对象赋值给父类类型的引用变量。换句话说,它是将一个对象转换为它的父类类型。 在上述示例中,

    2024年02月06日
    浏览(55)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包