[Linux调查局] 编译过程

简介: [Linux调查局] 编译过程

引子

一个程序的编译分为4个部分:


预处理

头文件的展开

条件编译

宏的展开

去掉注释

编译

生成汇编

汇编

生成计算机认识的机器指令, 即二进制文件

链接

将程序和 库 链接

🗨️这里有一个疑问: 在汇编阶段, 已经生成了机器指令. 按理说, 应该就可以结束了, 那为什么还要连链接?


首先, 先明确, 链接阶段是和 库 做链接.

那么, 库又是什么?

库是各种方法的实现方式, 而我们熟知的 头文件是各种方法的声明.

那么, 方法又是什么?

比较常见的, 如: printf, cout, cin … …, 这些我们常常会用到的方法, 就会将它写入库中

在后面的学习中, 我们还知道链接是分 动态链接 和 静态链接的, 它们又有什么区别呢? 咋们后面再说

编译阶段

预处理

gcc -E 源文件 -o 目标文件
  1. -E 是gcc关于预处理的选项, 后面的文件是 源文件
  2. -o 后面是生成的目标文件. 一般预处理的文件后缀是 .i

在预处理过程中是平替过去的, 所以不会有语法检查

4. 条件编译其实在日常生活中是非常常见的. 比如: 拿视频的普通用户 和 VIP用户来说, 其实就是利用条件编译 将VIP用户的部分功能 剪枝 掉, 才有的普通用户的功能, 那么这样就只用维护一段代码就可以了.

汇编

gcc -S 预处理文件/源文件 -o 目标文件
  1. -S 是gcc关于汇编的选项, 后面跟的是 源文件
  2. -o 后面跟的是 目标文件. 一般汇编的目标文件的后缀是 .s

编译

gcc -c 源文件/汇编文件 -o 目标文件
  1. -c 是gcc关于编译的选项, 后面跟的是 源文件
  2. -o 后面跟的是 目标文件. 一般汇编的目标文件的后缀是 .o
  3. 生成的是机器可识别指令, 即二进制文件
  4. 假如 目标文件是 test.o, 我们管 test.o 也叫作 可重定位目标二进制文件, 简称 目标文件. 目标文件不能单独运行, 要通过和 进行链接才能运行👇👇👇
  5. 🗨️有人便会说 权限不够导致的
  • 文件的执行权限是 x, 那我们就给 test.o 文件加入 x 权限👇👇👇
  • 权限是能不能做, 但是你即使可以做, 但是有些人就是不让你做这件事情! 社会就是如此的残酷

链接

gcc 源文件 -o 目标文件
  1. 链接没有选项
  2. -o 后面跟目标文件
总结:
1 . 链接阶段没有选项, 前面的选项依次是ESc
2. 链接阶段没有强调后缀名, 前面的后缀名依次是 iso

🗨️这些选项 ESc 有什么功能啊?


首先, 我们发现 链接阶段 , gcc 源文件 -o 目标文件 是 直接编译完成的

其次, 我们发现, 在我们加入了这些选项之后, gcc好像是遇到了什么阻碍, 翻译到那里就停止了.

由此, 我们便可得出结论:

-E :告诉gcc翻译到预处理就停止翻译

-S : 告诉gcc翻译到汇编就停止翻译

-c : 告诉gcc翻译到编译就停止翻译

链接详解

通过前面的学习, 我们知道了编译的各个阶段以及各个阶段编译器做的事情.

可重定位目标二进制文件不能单独运行, 必须和 库 链接了才能运行.

库是各种方法的实现形式, 头文件的各种方法的声明.


🗨️那么, Linux下库在哪里, 长什么样子?


在这里, 科普一下:

Windows下是有静态库(.lib) 和 动态库(.dll)的,

Linux下也是有静态库(.a) 和 动态库(.so) 的.

Linux下库的 命名规则 — — libname.xxx(后缀), 所以我们查C语言的库就是 libc.so 或 libc.

Linux下库的路径 — — /usr/lib/... ...


我们发现, Linux下C语言库默认是有动态库的, 但是没有静态库, 我们也可以这样理解 C语言的标准库就是动态库, 默认的链接方式是动态链接

由此出现几个问题:

  1. C语言静态库如何安装?
sudo yum -y install glibc-static — — 安装C语言的静态库
sudo yum -y install libstdc+±static — — 安装C++的静态库
  1. 如何使用静态链接?
gcc 源文件 -o 目标文件 -static

为什么C语言库默认是动态库呢?

使用静态库进行的链接是 静态链接, 使用动态库进行的链接是 动态链接

两种链接方式的区别:


动态链接 — — 通过C语言编译器将源文件所需要的动态库的链接告知 可执行程序

静态链接 — — 将源文件所需要的静态库拷贝到可执行程序中.

通过比较两种链接方式, 我们可以得知: 通过动态链接方式, 最后生成的可执行程序的大小 要 小于 通过静态链接方式生成的可执行文件的大小⇒ 这样可以有效地节省空间(磁盘空间, 内存空间, 网络空间等等)👇👇👇

  1. 一个可执行文件是单纯动态链接还是静态链接还是动静态混合链接?在没有静态库的情况下, 那就是动态链接喽在有静态链接的情况下:
  1. 加-static, 那就是强制使用静态链接
  2. 没加-static, 那就是动静态混合链接
file 可执行文件 — — 查看此可执行文件的链接方式

ldd 可执行文件 — — 查看此可执行文件所依赖的动态库

release && debug

在VS上, 默认生成的可执行文件是 debug版本,

而在Linux上, 默认生成的可执行文件是 release版本.

如果要变成debug版本, 那要在编译的时候加 -g


🗨️何为debug版本?


debug版本就是在可执行文件中 添加 了 调试信息

添加, 添加 ⇒ 那就意味着, 最后生成的可执行文件的空间要变大👇👇👇

debug版本 是我们之后学习的 gdb调试 的基础.


相关文章
|
5月前
|
人工智能 Unix Linux
Linux的学习之路:1、发展史与编译环境的搭建
Linux的学习之路:1、发展史与编译环境的搭建
39 0
|
5月前
|
Linux 开发工具 C语言
Linux 安装 gcc 编译运行 C程序
Linux 安装 gcc 编译运行 C程序
103 0
|
4天前
|
Linux API 开发工具
FFmpeg开发笔记(五十九)Linux编译ijkplayer的Android平台so库
ijkplayer是由B站研发的移动端播放器,基于FFmpeg 3.4,支持Android和iOS。其源码托管于GitHub,截至2024年9月15日,获得了3.24万星标和0.81万分支,尽管已停止更新6年。本文档介绍了如何在Linux环境下编译ijkplayer的so库,以便在较新的开发环境中使用。首先需安装编译工具并调整/tmp分区大小,接着下载并安装Android SDK和NDK,最后下载ijkplayer源码并编译。详细步骤包括环境准备、工具安装及库编译等。更多FFmpeg开发知识可参考相关书籍。
22 0
FFmpeg开发笔记(五十九)Linux编译ijkplayer的Android平台so库
|
8天前
|
Linux 编译器 C语言
【Linux快速入门(一)】Linux与ROS学习之编译基础(gcc编译)
【Linux快速入门(一)】Linux与ROS学习之编译基础(gcc编译)
|
13天前
|
Linux 编译器 C语言
Linux c/c++之多文档编译
这篇文章介绍了在Linux操作系统下使用gcc编译器进行C/C++多文件编译的方法和步骤。
18 0
Linux c/c++之多文档编译
|
7天前
|
Linux 开发工具
【Linux快速入门(二)】Linux与ROS学习之编译基础(make编译)
【Linux快速入门(二)】Linux与ROS学习之编译基础(make编译)
|
2月前
|
监控 机器人 Unix
GoLand——windows下如何编译Linux二进制文件
GoLand——windows下如何编译Linux二进制文件
47 1
GoLand——windows下如何编译Linux二进制文件
|
1月前
|
Linux
用clang编译Linux内核
用clang编译Linux内核
|
2月前
|
Linux C语言
深度探索Linux操作系统 —— 编译过程分析
深度探索Linux操作系统 —— 编译过程分析
24 2
|
5月前
|
Linux
Linux编译FFmpeg
Linux编译FFmpeg
139 0