初识Linux下的gcc与makefile

2023-10-31

推荐文章:https://blog.csdn.net/chenlong_cxy/article/details/119183448
最近在学linux相关的操作,接触到makefile文件,在此做个笔记

gcc

在这里插入图片描述
gcc常用命令选项:
在这里插入图片描述

刚接触linux时,关于gcc编译器只会用形如 gcc hello.c 的命令来对代码进行编译(实际上这个命令是一键完成上面四个编译过程的),对整个编译过程还不了解,以至于后面在接触makefile的编写时出问题。现在先来看一看gcc的基础知识:
如上图所示,c程序的编译过程分为以上四个步骤,这四个步骤在c基础中也学过,但过于理论导致一知半解:

  1. 预处理:包括(宏替换,头文件展开,去掉注释),生成.i文件,(看内容实际上也是.c文件)
  2. 编译 :检查代码规范,语法错误等,生成汇编文件
  3. 汇编:转成二进制目标代码
  4. 链接:生成最终可执行文件
1.预处理

使用命令:gcc -E hello.c –o hello.i,得到预处理后的文件,这里的-o是重命名的意思。如下
在这里插入图片描述
可以用vim打开hello.i文件,可看到源代码本只有几行,经过预处理后得到几百行。
在这里插入图片描述

2. 编译

使用命令:gcc -S hello.i -o hello.s,生成汇编文件。
在这里插入图片描述
用vim打开可见:
在这里插入图片描述

3.汇编

使用命令:gcc -c hello.s -o hello.o,生成二进制文件,但还不能直接运行,这里-c命令是将代码转换为二进制语言,不进行链接。
在这里插入图片描述
关于-c这个命令,参考gcc 和 gcc -c有什么区别呢
在这里插入图片描述

4.链接

使用命令:gcc hello.o。尽管3中得到了二进制文件,但还是不能直接执行,需要通过链接,得到a.out文件,才能运行。
在这里插入图片描述

makefile

了解了上述gcc编译过程之后,接下来就可学习makefile了。
先给出测试例子–三个.c文件:
main.c :

#include <stdio.h>
extern void fun1();
extern void fun2();
int main()
{
        printf("main\n");
        fun1();
        fun2();
        return 0;
}

fun1.c:

#include <stdio.h>
void fun1()
{
        printf("fun1()\n");
}

fun2.c:

#include <stdio.h>
void fun1()
{
        printf("fun2()\n");
}
不使用makefile

单纯的在shell界面用gcc,可以做到对以上三个文件的一起编译,如下图:
在这里插入图片描述
但是,假如我只对其中的某一个文件进行修改,再次编译时仍然需要对以上三个文件都重新编译,当文件数特别多的时候,这将做很多重复工作,花很大时间。

makefile格式
1 target: prerequisites
2         commands    //注意这里为Tab缩进

翻译一下就是
目标文件 :依赖项
      命令

**即是用依赖项生成对应的目标文件,而依赖项是通过下面的命令生成的。

在这里插入图片描述

第一个makefile

先看最简单的一种情形**,新建一个名为makefile文件,输入以下内容:
在这里插入图片描述
再在终端输入make后得到以下结果:
在这里插入图片描述
可看出,这种makefile文件同只有gcc的一样,是对所有的文件进行编译,特别耗时。

常用规则

注意到,上述第一个makefile文件是直接使用 gcc 指令对多个.c源文件直接生成源文件,这在实际中用的很少。一般是先用源文件汇编生成对应的.o二进制文件(前面有介绍),再将多个二进制文件链接生成可执行文件。

看第二个makefile

通过拆分,现在想,修改哪个文件,就只编译哪个文件,未修改的不参加编译。如下图,第一个目标cpp为终极目标,下面的为子目标。当我们想利用依赖项生成目标cpp时,会先查找后面的依赖项main.o ,没有就会向下查找对应的规则生成main.o依赖项。后面同理。即makefile向下检索,子目标是用来生成终极目标的依赖项,然后依次往上执行命令。
在这里插入图片描述
终端执行后可看到其执行顺序为:

在这里插入图片描述
这时修改fun2.c文件中一点点内容,重新make,可看到只是编译了fun2.c文件。原因在于
makefile更新目标文件是比较时间的,即比较依赖项和目标文件的修改时间,依赖文件修改时间新于目标文件,则更新目标文件
在这里插入图片描述
以fun2.c为例,如上图,fun2.c变化前,fun2.o生成时间是晚于fun2.c; fun2.c变化后,通过比较修改时间,发现fun2.o的时间是早于fun2.c,这时说明fun2.c已修改,就需要执行上图所示命令生成新的子目标文件fun2.o,即重新编译fun2.c文件。而其他的文件对应的.c和.o时间无变化,故不需要重新编译。参考视频:C++ linux 服务器开发基础—makefile工作原理
在这里插入图片描述
上述makefile代码冗余还很严重,可以通过变量简化该代码,具体的可见视频。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

初识Linux下的gcc与makefile 的相关文章

  • 为 Linux 编译 Objective-C 应用程序(API 覆盖范围)

    我可能在这里问一些奇怪的问题 但我不确定从哪里开始 问题是我正在考虑使用 Obj C 和 Foundation 类在 Mac 上编写一个命令行工具 但存在一个非常大的风险 那就是我希望能够为不同的 Linux 发行版编译它 以便将来作为服务
  • Linux无法删除文件

    当我找到文件时 我在删除它们时遇到问题 任务 必须找到带有空格的文件并将其删除 我的尝试 rm find L root grep i 但我有错误 rm cannot remove root test No such file or dire
  • 为什么 fork 炸弹没有使 android 崩溃?

    这是最简单的叉子炸弹 我在许多 Linux 发行版上执行了它 但它们都崩溃了 但是当我在 android 终端中执行此操作时 即使授予后也没有效果超级用户权限 有什么解释为什么它没有使 Android 系统崩溃吗 一句话 ulimit Li
  • awk 在循环中使用时不打印任何内容[重复]

    这个问题在这里已经有答案了 我有一堆使用 file 1 a 1 txt 格式的文件 如下所示 A 1 B 2 C 3 D 4 并使用以下命令添加包含每个文件名称的新列 awk print FILENAME NF t 0 file 1 a 1
  • SSH,运行进程然后忽略输出

    我有一个命令可以使用 SSH 并在 SSH 后运行脚本 该脚本运行一个二进制文件 脚本完成后 我可以输入任意键 本地终端将恢复到正常状态 但是 由于该进程仍在我通过 SSH 连接的计算机中运行 因此任何时候它都会登录到stdout我在本地终
  • docker 非 root 绑定安装权限,WITH --userns-remap

    all 尝试让绑定安装权限正常工作 我的目标是在容器中绑定安装卷 以便 a 容器不以 root 用户身份运行入口点 二 docker daemon 配置了 userns remap 这样容器 主机上没有 root c 我可以绑定挂载和读 写
  • Google BQ:运行参数化查询,其中参数变量是 BQ 表目标

    我正在尝试从 Linux 命令行为 BQ 表目标运行 SQL 此 SQL 脚本将用于多个日期 客户端和 BQ 表目标 因此这需要在我的 BQ API 命令行调用中使用参数 标志 parameter 现在 我已经点击此链接来了解参数化查询 h
  • 在 .gitconfig 中隐藏 GitHub 令牌

    我想将所有点文件存储在 GitHub 上 包括 gitconfig 这需要我将 GitHub 令牌隐藏在 gitconfig 中 为此 我有一个 gitconfig hidden token 文件 这是我打算编辑并放在隐藏令牌的 git 下
  • python获取上传/下载速度

    我想在我的计算机上监控上传和下载速度 一个名为 conky 的程序已经在 conky conf 中执行了以下操作 Connection quality alignr wireless link qual perc wlan0 downspe
  • 使用 \r 并打印一些文本后如何清除控制台中的一行?

    对于我当前的项目 有一些代码很慢并且我无法使其更快 为了获得一些关于已完成 必须完成多少的反馈 我创建了一个进度片段 您可以在下面看到 当你看到最后一行时 sys stdout write r100 80 n I use 80覆盖最终剩余的
  • 在centos中安装sqlite3 dev和其他包

    我正在尝试使用 cpanel 在 centos 机器上安装 sqlite dev 和其他库 以便能够编译应用程序 我对 debian 比 centos 更熟悉 我知道我需要的库是 libsqlite3 dev libkrb5 dev lib
  • 在 Linux 上以编程方式设置 DNS 名称服务器

    我希望能够通过我的 C C 程序为 Linux 上的 DNS 名称服务器添加 IP 地址 我在一个带有只读 etc resolv conf 的嵌入式平台上 这意味着我不能简单地将 nameserver xxx xxx xxx xxx 行添加
  • linux-x64 二进制文件无法在 linuxmusl-x64 平台上使用错误

    我正在安装Sharp用于使用 package json 的 Nodejs 项目的 docker 映像上的映像压缩包 当我创建容器时 我收到有关 Sharp 包的以下错误 app node modules sharp lib libvips
  • 尽管 if 语句,Visual Studio 仍尝试包含 Linux 标头

    我正在尝试创建一个强大的头文件 无需更改即可在 Windows 和 Linux 上进行编译 为此 我的包含内容中有一个 if 语句 如下所示 if defined WINDOWS include
  • 为什么 fopen("any_path_name",'r') 不给出 NULL 作为返回值?

    在调试一些代码时 我得到如下内容 include
  • CMake 链接 glfw3 lib 错误

    我正在使用 CLion 并且正在使用 glfw3 库编写一个程序 http www glfw org docs latest http www glfw org docs latest 我安装并正确执行了库中的所有操作 我有 a 和 h 文
  • 如何使用waf构建共享库?

    我想使用构建一个共享库waf http code google com p waf 因为它看起来比 GNU 自动工具更容易 更简洁 到目前为止 我实际上有几个与我开始编写的 wscript 有关的问题 VERSION 0 0 1 APPNA
  • 内核的panic()函数是否完全冻结所有其他进程?

    我想确认内核的panic 功能和其他类似kernel halt and machine halt 一旦触发 保证机器完全冻结 那么 所有的内核和用户进程都被冻结了吗 是panic 可以被调度程序中断吗 中断处理程序仍然可以执行吗 用例 如果
  • 如何在 *nix 中登录时运行脚本?

    我知道我曾经知道如何做到这一点 但是 如何在 unix 中登录时运行脚本 bash 可以 From 维基百科 Bash http en wikipedia org wiki Bash 28Unix shell 29 当 Bash 启动时 它
  • Linux 为一组进程保留一个处理器(动态)

    有没有办法将处理器排除在正常调度之外 也就是说 使用sched setaffinity我可以指示线程应该在哪个处理器上运行 但我正在寻找相反的情况 也就是说 我想从正常调度中排除给定的处理器 以便只有已明确调度的进程才能在那里运行 我还知道

随机推荐

  • ESP8266 WIFI模块学习之路(7)——自写Android手机APP接受单片机数据

    上一篇是写关于自写Android手机APP给单片机下发数据的 这次我将写一下APP如何接受单片机数据 其实使用调试助手 或者别人开的的APP同样能够实现接受单片机数据 但想学习的 我还是建议能够自己写一个Android软件 这样从底层到上层
  • 中间件的介绍

    1 1 什么是中间件 中间件是介于应用系统和系统软件之间的一类软件 他使用系统软件所提供的基础服务 衔接网络上应用系统的各个部分或不同的应用 能够达到资源共享 功能共享的目的 例如MySQL就可以看作是具备中间件特性的一种技术 中间件技术必
  • mysql8查看用户密码_mysql8用户管理

    查看当前登录用户 创建用户 create user 用户名 主机地址 identified with mysql native password by 密码 修改密码 alter user 用户名 主机地址 identified with
  • cnocr避坑指南

    今天用我的win7电脑运行我的一个python程序 让我安装cnocr 于是我就pip install cnocr 安装成功 继续运行 却出现mxnet的问题 一堆它的 dll文件没有 反复卸载重装 没得救 看了一个文章 也是这个问题 就想
  • Java教程:如何读取服务器文件并推送到前端并下载,图片格式以浏览器渲染模式

    起因 在我们做文件上传时 通常会保存文件的相对路径在数据库中 然后返回前端http访问路径 来对文件进行下载或图片预览功能 但是有时候我们并不想直接返回文件访问地址给前端 这就用到了Java当中的文件输入输出流 将文件以流的方式响应给浏览器
  • 【C语言】详解qsort函数使用和模拟实现

    一 qsort函数的使用 qsort的功能 qsort函数是C语言标准提供的排序函数 使用qsort函数需要引用头文件 include
  • h5 video方法,事件,属性详解

    闲下来的的时间里 我一直总结之前学习过的知识 今天到video 发现对它还是不够熟悉 于是重新学习一遍 举个例子
  • [云原生专题-37]:K8S - 核心概念 - 存储抽象- 搭建NFS网络文件系统与常见操作命令

    作者主页 文火冰糖的硅基工坊 文火冰糖 王文兵 的博客 文火冰糖的硅基工坊 CSDN博客 本文网址 https blog csdn net HiWangWenBing article details 122828322 目录 第1步 NFS
  • 怎样用python通达信接口写一个股票自动买卖的程序?

    方法一 前期的数据抓取和分析python都写好了 所以就差交易指令接口了 对于散户投资者来说 正规的法子是愿意给接口的券商 但是需要很高的开户费 而且只有lts ctp这样的c 接口 没有python版就需要用户自己去封装 方法二 wind
  • js抽奖(随机抽奖

    js抽奖 随机抽奖 默认抽奖结果 效果示例图 代码块 效果示例图 代码块
  • R语言函数

    R语言实际上是函数的集合 用户可以使用base stats等包中的基本函数 也可以自己编写函数完成一定的功能 但是初学者往往认为编写R函数十分困难 或者难以理解 这里对如何编写R函数进行简要的介绍 函数是对一些程序语句的封装 换句话说 编写
  • 乐高机器人投篮编程_乐高机器人WeDo编程和EV3编程课能学到什么

    乐高机器人WeDo编程和EV3编程课能学到什么 智能机器人WeDo编程课能学点啥 智能机器人WeDo编程 游戏乐园 适合年龄 一年级至二年级 课程简介 设计搭建复杂机器人 运行编程程序 感受机械运动的神奇 完成一个星际战机主题的机器人搭建及
  • 区块链与物联网的结合应用

    最近一个新闻 IBM中国研究院全面关闭 个人技术公众号 解决方案工程师 欢迎同领域的朋友关注 相互交流 最近一个新闻 IBM中国研究院全面关闭 原因也是多方面的 其中 新闻中这句话我倒是十分感兴趣 2014年初 IBM中国研究院提出了 物联
  • Qt学习七——qcustomplot(1)

    好久没有更新了 把最近学习到的东西做一个简单的总结 一 qcustomplot是什么 在没有接触qt之前 各种奇怪的图到底怎么画出来的还是觉得很厉害的 但是当你拥有了qcustomplot 你就拥有了整个世界 可以说qcustomplot算
  • arthas启动-服务端启动流程

    从前面介绍的arthas启动 agent初始化一文中我们看到了AgentBootstrap bind函数 该函数的实现就是使用反射创建一个ArthasBootstrap对象 传入关键信息Instrumentation 以及启动参数 我们就关
  • 三太子敖丙-帅丙的文章目录

    三太子敖丙 帅丙的文章目录
  • [蓝桥杯2022初赛] 消除游戏

    题目 来源 P2045 蓝桥杯2022初赛 消除游戏 New Online Judge ecustacm cn 分析 首先 可以明确一件事情 不管怎么删除 都要在遍历完字符串后在删除 然后 新生成的字符串再进行重复操作 题目中虽然给了次数
  • 使用MATLAB将Excel里面的数据导入,并且将MATLAB数据导入到Excel里面的命令介绍

    系列文章目录 Matlab中求解线性方程组 高斯消元法 LU分解法 QR分解法 SVD分解法 迭代法等 MATLAB迭代的三种方式以及相关案例举例 MATLAB矩阵的分解函数与案例举例 MATLAB当中线性方程组 不定方程组 奇异方程组 超
  • docker部署LTC v0.18.1版本开发网

    文章目录 一 LTC镜像生成 二 LTC容器生成 三 查看bsv服务是否部署成功 四 常用接口使用 昨天部署了比特现金开发网节点 今天做个莱特币的开发网试试 一 LTC镜像生成 1 下载基础镜像 docker pull buildpack
  • 初识Linux下的gcc与makefile

    推荐文章 https blog csdn net chenlong cxy article details 119183448 最近在学linux相关的操作 接触到makefile文件 在此做个笔记 文章目录 gcc 1 预处理 2 编译