首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >【Linux修炼手册】Linux开发工具的使用(二):gcc/g++与make/makefile

【Linux修炼手册】Linux开发工具的使用(二):gcc/g++与make/makefile

作者头像
我想吃余
发布2025-05-13 08:55:13
发布2025-05-13 08:55:13
3440
举报
文章被收录于专栏:C语言学习C语言学习

一、Linux编译器——gcc/g++的使用

  • gcc是编译C语言的工具
  • g++是编译C++的工具,也可以编译C语言,因为C++是兼容C语言的。 gcc与g++的使用方法与原理是相同,本文以gcc为例
代码语言:javascript
复制
gcc [选项] 要编译的文件 [选项] [目标文件]
1. 编译流程概述

GCC/G++ 将源代码转换为可执行文件的过程分为四个阶段:

  1. 预处理(生成 .i 文件)
  • 去注释
  • 宏替换
  • 头文件展开
  • 条件编译
代码语言:javascript
复制
gcc -E mycode.c -o mycode.i
  • 选项:
    • -E:仅执行预处理。
    • -o:指定输出文件名
  1. 编译(生成 .s 汇编文件):将预处理后的代码转换为汇编语言。
代码语言:javascript
复制
gcc -S mycode.i -o mycode.s
  • 选项:
    • -S:编译到汇编语言(不汇编、不链接)
  1. 汇编(生成 .o 目标文件):将汇编代码转换为机器码。
代码语言:javascript
复制
gcc -c mycode.s -o mycode.o
  • 选项:
    • -c:编译到目标文件(机器码,未链接)。

注意:目标文件.o不可以独立执行,尽管他已经是二进制文件了。

  1. 链接(生成可执行文件):将可重定位的目标二进制文件和库进行链接形成可执行程序。

💡:记忆小技巧:

  1. 当我们记不住-E、-S、-c选项时,看看键盘左上角的Esc键,另外注意S要大写。
  2. 记不住临时文件后缀?记住.iso即可,它也是镜像文件的后缀。
2. 静态链接与动态链接
2.1 什么是库?

我们都知道,头文件.h中提供的是方法声明。那么,真正的方法在哪里呢? 没错,就是在库中: 头文件 + 库 + 你的代码 = 你的软件

库:经过一定的翻译,然后打包的源文件。

为什么要翻译打包?

  • 只需提供一个文件即可,避免了提供太多的源文件
  • 达到隐藏源文件的目的
2.2 目标文件与库是如何链接的呢?
  1. 动态链接:在可执行文件中保留动态库引用信息,在可执行文件运行时由系统跳转加载到动态库中执行。
  2. 静态链接:将静态库的代码直接拷贝到可执行文件中,一般静态链接的可执行文件大小会比较大

从这两种链接的原理我们可以发现:

  • 动态库不能缺失,一旦对应的动态库缺失,会导致很多的程序都无法正常运行。
  • 通过静态链接生成点的程序将不再依赖静态库。

注意:在Linux中,默认的链接方式是动态链接

如果需要静态链接的方式,使用选项-static来提供静态库:

代码语言:javascript
复制
gcc mycode.c -o mytest -static

其实-static的本质就是改变优先级 💡:

  1. 如果没有静态库,还要使用-static是不行的
  2. 如果没有动态库,只有静态库,gcc会自动使用静态库
  3. 链接的方式不一定是纯的静态链接或者动态链接,也可以是混合链接。
2. 动态库vs静态库

动态库:

  • 优点:由于动态库是共享库,可以有效的节省资源(磁盘空间、内存空间、网络空间等)
  • 缺点:一旦丢失,会导致各个程序瘫痪

静态库:

  • 优点:不依赖库,程序可以独立运行
  • 缺点:体积大,更加消耗资源

二、Linux项目自动化构建工具——make/Makefile

  • make:是一个命令
  • makefile:是一个当前目录下的定义构建规则的文本文件,主要由依赖关系依赖方法组成。
1. 使用方法

基本规则结构

代码语言:javascript
复制
target: dependencies  # 目标对象与依赖对象(依赖关系)
    [tab] command      # 依赖方法必须以 Tab 开头(非空格)

示例:编译 hello.c 生成可执行文件 hello

代码语言:javascript
复制
hello: hello.c       # 目标:hello,依赖:hello.c
    gcc hello.c -o hello  # 命令:编译命令
2. makefile的自动化推导

我们来输入以下内容:

结果:

可以发现:makefile的编译顺序与我们书写的顺序是无关的,它会按照我们书写的第一个目标文件为目标,自动化推导出正确的顺序,生成目标文件。

makefile以第一个目标文件为默认目标文件,使用时只需make即可。其余目标文件使用时均需要make+[目标文件]

3. 如何反复编译?

现在我们只需要输入make,就可以完成编译生成可执行程序了。

但当我们再次输入make,却报错了,为什么呢?

  • 实在是没有必要编译多次,因此提高了编译效率。
3.1 使用.PHONY:伪目标

怎么做到的呢? make会根据源文件和目标文件的新旧,判定是否需要重新执行依赖关系进行编译。 只有可执行文件的修改时间比源文件老,才会重新编译。

所以,依赖关系不一定总是执行的!

若是想让依赖关系总是执行,可以使用.PHONY:伪目标

.PHONY:让make忽略源文件和可执行目标文件的时间对比

.PHONY:伪目标一般用作项目清理

这样我们只需要输入make clean,就可以快速完成项目清理了。

3.2 修改时间
  1. stat命令可以查看文件时间
  • Access:上次的访问时间
  • Modify:上次修改内容的时间
  • Change:上次修改属性的时间

记忆小技巧💡:ACM时间

连锁反应:修改Modify,Change也会改变(文件大小变化)

  1. touch + [已存在的文件],更新时间 如果不加选项,就会更新ACM时间 选项:
  • -a:更新Access时间
  • -c:更新Change时间
  • -m:更新Modify时间
4. 自动变量

常用自动变量:

  • $@目标文件名
  • $^依赖文件名

依据依赖关系自动匹配 示例:

另外,@+依赖方法可以取消回显

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2025-05-12,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、Linux编译器——gcc/g++的使用
    • 1. 编译流程概述
    • 2. 静态链接与动态链接
      • 2.1 什么是库?
      • 2.2 目标文件与库是如何链接的呢?
      • 2. 动态库vs静态库
  • 二、Linux项目自动化构建工具——make/Makefile
    • 1. 使用方法
    • 2. makefile的自动化推导
    • 3. 如何反复编译?
      • 3.1 使用.PHONY:伪目标
      • 3.2 修改时间
    • 4. 自动变量
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档