目录

一、简介

二、简单编译

1.预处理

2.编译

3.汇编

4.连接

5.执行

三、多个程序文件的编译

四、检错

五、库文件连接

1.编译成可执行文件

2.链接

3.强制链接时使用静态链接库

六、小结

七、参考文献


一、简介

GCC 是编译工具,它的意思是 GNU C Compiler 。经过了这么多年的发展,GCC 已经不仅仅能支持 C 语言;它现在还支持 Ada 语言、C++ 语言、Java 语言、Objective C 语言、Pascal 语言、COBOL语言,以及支持函数式编程和逻辑编程的 Mercury 语言等等。而 GCC 也不再单只是 GNU C 语言编译器的意思了,而是变成了 GNU Compiler Collection 也即是 GNU 编译器家族的意思了。另一方面,说到 GCC 对于操作系统平台及硬件平台支持,概括起来就是一句话:无所不在。

 Binutils是一组二进制程序处理工具,包括:addr2line、ar、objcopy、objdump、as、ld、 ldd、readelf、 size 等,主要作用如下表所示。

addr2line
用 来将程序地址转换成其所对应的程序源文件及所对应的代码行,也可以得到所对应的函数。该工具将帮助调试器在调试的过程中定位对应的源代码位置。
as
主要用于汇编。
ld
主要用于链接。
ar
主要用于创建静态库。
ldd
用于查看一个可执行程序依赖的共享库。
objcopy
将一种对象文件翻译成另一种格式,譬如将.bin 转换成.elf、或
者将.elf 转换成.bin 等。
objdump
主要的作用是反汇编。
readelf
显示有关 ELF 文件的信息。
size
列出可执行文件每个部分的尺寸和总尺寸,代码段、数据段、总大小等。
ELF 文件
格式如下:

 1.ELF 文件的段

位于 ELF Header 和 Section Header Table 之间的都 是段(Section)。一个典型的 ELF 文件包含下面几个段:
  • text:已编译程序的指令代码段。
  • rodata:ro 代表 read only,即只读数据(譬如常数 const)。
  • data:已初始化的 C 程序全局变量和静态局部变量。
  • bss:未初始化的 C 程序全局变量和静态局部变量。
  • debug:调试符号表,调试器用此段的信息帮助调试。

2.反汇编 ELF

由于 ELF 文件无法被当做普通文本文件打开,如果希望直接查看一个 ELF 文件包 含的指令和数据,需要使用反汇编的方法。
例如对一个hello.c文件进行反汇编:
①使用 objdump -D 对其进行反汇编:
objdump -D hello
②使用 objdump -S 将其反汇编并且将其 C 语言源代码混合显示出来:
gcc -o hello -g hello.c //要加上-g 选项
objdump -S hello

二、简单编译

gedit test.c进入文本编译器输入以下代码:

#include <stdio.h>
int main(void)
{printf("Hello World!\n");return 0;
}

接下来输入一步到位的编译命令:

gcc test.c -o test

发现生成了目标文件test,实质上,上述编译过程是分为四个阶段进行的,即预处理(也称预编译,Preprocessing)、编译(Compilation)、汇编 (Assembly)和连接(Linking)。

1.预处理

gcc -E test.c -o test.i

应用vi tset.i打开生成的test.i文件发现里面存放着test.c经预处理之后的代码。

或者

gcc -E test.c

是直接在命令行窗口中输出预处理后的代码。

gcc的-E选项,可以让编译器在预处理后停止,并输出预处理结果。在本例中,预处理结果就是将stdio.h 文件中的内容插入到test.c中了。

2.编译

预处理之后,可直接对生成的test.i文件编译,生成汇编代码:

gcc -S test.i -o test.s

gcc的-s选项,表示在程序编译期间,在生成汇编代码后,停止;-o输出汇编代码文件 。

3.汇编

生成的汇编代码文件test.s,gas汇编器负责将其编译为目标文件,如下:

gcc -c test.s -o test.o

或者使用 Binutils 中的 as 将 hello.s 文件汇编生成目标文件

as -c test.s -o test.o 
注意:test.o 目标文件为 ELF(Executable and Linkable Format)格式的可重定向文件。

4.连接

gcc连接器是gas提供的,负责将程序的目标文件与所需的所有附加的目标文件连接起来,最终生成可执行文件。附加的目标文件包括静态连接库和动态连接库。

将上面生成的test.o文件与C标准输入输出库进行连接,最终生成程序test。

gcc test.o -o test

静态链接是指在编译阶段直接把静态库加入到可执行文件中去,这样可执行 文件会比较大。链接器将函数的代码从其所在地(不同的目标文件或静态链 接库中)拷贝到最终的可执行程序中。为创建可执行文件,链接器必须要完 成的主要任务是:符号解析(把目标文件中符号的定义和引用联系起来)和 重定位(把符号定义和内存地址对应起来然后修改所有对符号的引用)。
动态链接则是指链接阶段仅仅只加入一些描述信息,而程序执行时再从系统 中把相应动态库加载到内存中去。
链接器链接后生成的最终文件为 ELF 格式可执行文件,一个 ELF 可执行文件通常被链接为不同的段,常见的段譬如.text、.data、.rodata、.bss 等段。
生成的 ELF 可执行文件的大小(使用 Binutils 的 size 命令查看)和链接的动态库(使用 Binutils 的 ldd 命令查看)。

5.执行

最后输入./test执行程序,输出结果:

三、多个程序文件的编译

通常整个程序是由多个源文件组成的,相应地也就形成了多个编译单元,使用GCC能够很好地管理这些编译单元。假设有一个由sub1.c、sub2.c和 main2.c三个源文件组成的程序,为了对它们进行编译,并最终生成可执行程序main,可以使用下面这条命令:

gcc sub1.c sub2.c main.c -o main

如果同时处理的文件不止一个,GCC仍然会按照预处理、编译和链接的过程依次进行。

上面这条命令大致相当于依次执行如下四条命令:

gcc -c sub1.c -o sub1.o
gcc -c sub2.c -o sub2.o
gcc -c main.c -o main.o
gcc sub1.o sub2.o main.o -o main

四、检错

gcc -pedantic main.c -o main

 -pedantic编译选项并不能保证被编译程序与ANSI/ISO C标准的完全兼容,它仅仅只能用来帮助Linux程序员离这个目标越来越近。或者换句话说,-pedantic选项能够帮助程序员发现一些不符合 ANSI/ISO C标准的代码,但不是全部,事实上只有ANSI/ISO C语言标准中要求进行编译器诊断的那些情况,才有可能被GCC发现并提出警告。

除了-pedantic之外,GCC还有一些其它编译选项也能够产生有用的警告信息。这些选项大多以-W开头,其中最有价值的当数-Wall了,使用它能够使GCC产生尽可能多的警告信息。

gcc -Wall main.c -o main

GCC给出的警告信息虽然从严格意义上说不能算作错误,但却很可能成为错误的栖身之所。一个优秀的Linux程序员应该尽量避免产生警告信息,使自己的代码始终保持标准、健壮的特性。所以将警告信息当成编码错误来对待,是一种值得赞扬的行为!所以,在编译程序时带上-Werror选项,那么GCC会在所有产生警告的地方停止编译,迫使程序员对自己的代码进行修改,如下:

gcc -Werror main.c -o main

五、库文件连接

开发软件时,完全不使用第三方函数库的情况是比较少见的,通常来讲都需要借助许多函数库的支持才能够完成相应的功能。从程序员的角度看,函数库实际上就是一些头文件(.h)和库文件(so、或lib、dll)的集合。

Linux下的大多数函数都默认将头文件放到/usr/include/目录下,而库文件则放到/usr/lib/目录下;Windows所使用的库文件主要放在Visual Stido的目录下的include和lib,以及系统文件夹下。但也有的时候,我们要用的库不再这些目录下,所以GCC在编译时必须用自己的办法来查找所需要的头文件和库文件。

例如我们的程序test.c是在linux上使用c连接mysql,这个时候我们需要去mysql官网下载MySQL Connectors的C库,下载下来解压之后,有一个include文件夹,里面包含mysql connectors的头文件,还有一个lib文件夹,里面包含二进制so文件libmysqlclient.so

其中inclulde文件夹的路径是/usr/dev/mysql/include,lib文件夹是/usr/dev/mysql/lib。

1.编译成可执行文件

首先我们要进行编译test.c为目标文件,这个时候需要执行

gcc –c –I /usr/dev/mysql/include test.c –o test.o

2.链接

最后我们把所有目标文件链接成可执行文件:

gcc –L /usr/dev/mysql/lib –lmysqlclient test.o –o test

Linux下的库文件分为两大类分别是动态链接库(通常以.so结尾)和静态链接库(通常以.a结尾),二者的区别仅在于程序执行时所需的代码是在运行时动态加载的,还是在编译时静态加载的。

3.强制链接时使用静态链接库

默认情况下, GCC在链接时优先使用动态链接库,只有当动态链接库不存在时才考虑使用静态链接库,如果需要的话可以在编译时加上-static选项,强制使用静态链接库。

在/usr/dev/mysql/lib目录下有链接时所需要的库文件libmysqlclient.so和libmysqlclient.a,为了让GCC在链接时只用到静态链接库,可以使用下面的命令:

gcc –L /usr/dev/mysql/lib –static –lmysqlclient test.o –o test

静态库链接时搜索路径顺序:

1. ld会去找GCC命令中的参数-L
2. 再找gcc的环境变量LIBRARY_PATH
3. 再找内定目录 /lib /usr/lib /usr/local/lib 这是当初compile gcc时写在程序内的

动态链接时、执行时搜索路径顺序:

1. 编译目标代码时指定的动态库搜索路径
2. 环境变量LD_LIBRARY_PATH指定的动态库搜索路径
3. 配置文件/etc/ld.so.conf中指定的动态库搜索路径
4. 默认的动态库搜索路径/lib
5. 默认的动态库搜索路径/usr/lib

有关环境变量:
LIBRARY_PATH环境变量:指定程序静态链接库文件搜索路径
LD_LIBRARY_PATH环境变量:指定程序动态链接库文件搜索路径

六、小结

Linux系统下的Gcc是GNU推出的功能强大、性能优越的多平台编译器。Gcc编译器能将C、C++语言源程序、汇程式化序和目标程序编译、连接成可执行文件,如果没有给出可执行文件的名字,gcc将生成一个名为a.out的文件。同时Gcc还能进行多文件同时编译,大大提高了程序运行的效率。

七、参考文献

Linux GCC常用命令 - ggjucheng - 博客园1简介2简单编译2.1预处理2.2编译为汇编代码(Compilation)2.3汇编(Assembly)2.4连接(Linking)3多个程序文件的编译4检错5库文件连接5.1编译成可执行文件5.2链https://www.cnblogs.com/ggjucheng/archive/2011/12/14/2287738.html

Linux中gcc的常用命令相关推荐

  1. Linux中vi的常用命令和快捷键使用

    Linux中vi的常用命令和快捷键使用 文章目录: 一.VI简单介绍 二.VI三种模式的使用 1.VI底行模式的使用 2.VI编辑模式的使用 3.VI一般模式的使用 1)移动光标 2)删除.复制和粘贴 ...

  2. linux中强大且常用命令:find、grep

    为什么80%的码农都做不了架构师?>>>    linux中强大且常用命令:find.grep 转载于:https://my.oschina.net/michao/blog/7752 ...

  3. 【日常小记】linux中强大且常用命令:find、grep

    在linux下面工作,有些命令能够大大提高效率.本文就向大家介绍find.grep命令,他哥俩可以算是必会的linux命令,我几乎每天都要用到他们.本文结构如下: find命令 find命令的一般形式 ...

  4. linux命令冒号加叹号,Linux中的叹号命令

    在shell环境下操作,需要积累点快捷输入的小技巧: 最常用的技巧恐怕就是Tab自动补全以及上方向键来回退上几条历史命令了,这些对于csh,bash,ksh,zsh都适用. 最近还找到一种快速回退上一 ...

  5. linux中如何用ftp命令下载文件,linux中ftp下载文件命令的用法

    linxu下的ftp命令是用来下载文件或者上传文件的,下面由学习啦小编为大家整理了linux的ftp下载文件命令的用法的相关知识,希望对大家有帮助! 一.linux中的ftp下载文件命令的用法 从远程 ...

  6. linux mkdir -m权限,Linux中mkdir和touch命令区别

    一.目的 本文将介绍linux下新建文件或文件夹.删除文件或文件夹命令.         touch能够新建文件,mkdir用来新建文件夹.rm用来删除文件或文件夹.         本文将选取ubu ...

  7. linux 移动剪切命令,Linux中vi的复制命令的用法详解

    在Linux系统中,使用VI编辑的时候经常用到的操作就是复制粘贴,那么下面由学习啦小编为大家整理了linux中vi的复制命令的用法详解的相关知识,希望对大家有帮助! Linux中vi的复制命令的用法详 ...

  8. linux gst-launch 播放视频旋转,【视频开发】Gstreamer中一些gst-launch常用命令

    GStreamer是著名的开源多媒体框架,功能强大,其命令行程序 gst-launch 可以实现很多常规测试.播放等,作为系统调试等是非常方便的. 1.摄像头测试 gst-launch v4l2src ...

  9. Linux中gcc的编译、静态库和动态库的制作

    欢迎大家关注笔者,你的关注是我持续更博的最大动力 Linux中gcc的编译.静态库.动态库 文章目录: 1 gcc的编译过程 1.1 gcc的编译过程 1.2 gcc的常用参数 2 gcc 静态库的制 ...

  10. Linux中GCC编译工具集中个软件的用途、gcc的简单编译以及ELF文件格式

    文章目录 一.gcc编译工具集中各软件的用途 1.1 GCC 1.2 Binutils 1.3 C运行库 二.简单编译 2.1 代码编译过程 2.2 多个程序文件的编译 2.3 检错 2.4 库文件连 ...

最新文章

  1. Python 程序员最常犯的十个错误
  2. call、apply、bind
  3. 无盘中用户数据的保存
  4. oeasy php,oeasy教您玩转linux010106这儿都有啥 ls
  5. 【openCV学习笔记】在Mac上配置openCV步骤详解
  6. java 索引排序_Java培训MySQL之排序分组优化索引的选择
  7. 10 张图带你深入理解Docker容器和镜像
  8. 【shell】Shell编程的前篇以及通过编程实现,jdk的安装
  9. 本地Nginx+Hosts配置本地前端代码和后端代码联调
  10. POJ1011 Sticks
  11. Google Protocol Buffer学习笔记(一)
  12. PySpark︱pyspark.ml 相关模型实践
  13. 转帖:django中操作mysql
  14. spec.fne病毒
  15. Windows服务器高并发处理IOCP(完成端口)详细说明
  16. [Node.js] rsaaes 加密解密
  17. python控制多个屏幕_使用Python控制屏幕
  18. 教育的真谛 [英] 尼古拉斯·泰特 读书摘录
  19. 蓝旭暑期培训——DOM事件+正则表达式
  20. AI人工智能入门—知识地图

热门文章

  1. do还是doing imagine加to_do还是doing imagine加to_do、to do、doing用法全汇总,再也不用担心选错啦(收藏)......
  2. Excel2007无法卸载:安装程序包的语言不受系统支持。微软的卸载程序也不行。——只能手工删除
  3. 校招,面试,学习路线,这个编程学习网站,我爱了
  4. chrome安装crx文件
  5. 均值不等式中考_中考数学解题技巧方法
  6. JVM学习笔记(4)-运行时数据区详解之程序计数器与虚拟机栈
  7. 手把手教你用小米手机OTG功能连接打印机
  8. web前端学习34(表格标签 小说排行榜案例)
  9. js中三大特殊数据underfined,null,NaN
  10. Cosy V3.1.3 简洁大气WordPress博客主题自适应个人自媒体网站模板(含积木部分插件)