Linux下的编程环境(一)

1、GCC简介

GCC(GNU Compiler Collection,GNU编译器套件):是由GNU开发的编程语言编译器。GCC编译器套件支持多种语言的编译,包括了C、C++、Objective-C、Fortran、Java、Ada和Go语言的前端,也包括了这些语言的库。下面表格中列了些对于C、C++相关的主要软件包: 
名称 功能
cpp C预处理器
gcc C编译器
g++ c++编译器
gccbug 创建BUG报告的shell脚本
gcov 覆盖测试工具,用于分析程序哪里做优化效果最佳
libgcc GCC的运行库
libstdc++ 标准的C++库
libsupc++ 提供支持C++语言的函数库

2、GCC使用方法

2.1、最基本用法

$ gcc [选项扩展名] [文件名]

用于编译和链接C/C++程序所需的选项扩展名及介绍:


表1 C/C++程序常用文件名后缀

选项扩展名 文件内容
.a 静态库,由目标文件构成的文件库
.c C语言源码,必须经过预处理
.C,.cc或.cxx c++源代码文件,必须经过预处理
.h C/C++语言源代码的头文件
.i .c文件经过预处理后得到的C语言源代码
.ii .C,.cc或.cxx文件经过预处理后得到的C语言源代码
.o 目标文件,是编译过程得到的中间文件
.s 汇编语言文件,是.i文件编译后得到的C++源码文件
.so 共享对象库,也称动态库

2.2、GCC编译过程

注:以下列子以hello.c文件进行举例
Linux下的编程环境(一)_第1张图片
(1)、预处理:C编译器对各种预处理命令进行处理,包括头文件包含、宏定义的扩展、条件编译的选择等。
预处理的gcc命令:

$ gcc -E hello.c -o hello.i

(2)、编译:将预处理得到的源代码文件进行”翻译转换”,产生出机器语言的目标程序,得到机器语言的汇编文件。
编译的gcc命令:

$ gcc -S hello.i

(3)、汇编:将汇编代码翻译成机器码,但是还是不可以运行。
汇编的gcc命令:

$ gcc -c hello.s

(4)、链接:处理可重定位文件,把各种符号引用和符号定义转换成为可执行文件中的合适信息,通常是虚拟地址。
链接的gcc命令:

$ gcc hello.o  //默认生成a.out执行文件
$ gcc hello.o -o hello //通过-o参数命令指定生成新的执行文件名

注:链接分为动态链接和静态链接。
a、动态链接:使用动态链接库进行链接,生成的程序在执行的时候需要加载所需要的动态库才能运行。动态链接生成的程序小巧,但是必须依赖动态库,否则无法执行。可以说linux下的动态链接库实际是共享目标文件,一般是.so文件,类似于windows下的.dll文件。
b、静态链接:使用静态库进行链接,生成的程序包含程序运行所需要的全部库,可以直接运行,不过体积较大。linux下静态库是汇编产生的.o文件的集合,一般以.a文件形式出现。
c、gcc默认是动态链接,加上-static参数则采用静态链接。

$gcc hello.o -static -o hello_static

表2 常用的GCC编译控制选项

名称 功能描述
-c 只编译不连接。编译器只是将输入的.c等源代码文件生成.o为后缀的目标文件,通常用于编译不包含主程序的子程序文件
-S 只对文件进行编译,不汇编和链接
-E 只对文件进行预处理,不编译汇编和链接
-o output_filename 确定输出文件的名称为output_filename,这个名称不能和源文件同名,若不给出名称,将默认生成可执行文件a.out
-g 产生符号调试工具(GNU的gdb)所必要的符号信息,要想对源代码进行调试,就必须加入这个选项。g也分等级,默认是-g2,-g1是最基本的,-g3包含宏信息
-DFOO =BAR 在命令行定义预处理宏FOO,值为BAR
-O 对程序进行优化编译、链接。采用这个选项,整个源代码会在编译、链接过程中进行优化处理,这样产生的可执行文件的执行效率可以提高,但是编译、链接的速度就相应地慢一些
-ON 指定代码的优化等级为N,可取值为0,1,2,3;O0没有优化,O3优化级别最高
-Os 使用了-O2的优化部分选项,同时对代码尺寸进行优化
-I dirname 将dirname目录加入到程序头文件搜索目录列表中,是在预编译过程中使用的参数
-L dirname 将dirname目录加入到库文件搜索目录列表中
-l FOO 链接名为libFOO的函数库
-static 链接静态库
-ansi 支持ANSI/ISO C的标准语法,取消GNU语法中与该标准相冲突的部分
-w 关闭所有警告,不建议使用
-W 开启所有gcc能提供的警告
-werror 将所有警告转换为错误,开启该选项,遇到警告都会终止编译
-v 显示gcc执行时的详细过程,GCC及其相关程序的版本号

2.3、头文件的包含

在C程序中头文件的包含有两种方式:

1)、#include2)、#include"stdio.h"

对于(1)使用尖括号的情况,预处理器会在系统预设的头文件包含目录搜索头文件
对于(2)使用双引号的情况,预处理会先在目标文件所在目录进行相应的头文件的搜索,如果当前目录没有,则会到系统预设的头文件包含的目录继续搜索。
注:在编译的时候也可以通过 -I dirname参数命令将指定的目录添加到头文件搜索目录列表中。

$ gcc -v hello.c -I /home/vmuser/hello

2.4、库文件链接

在实际产品开发过程中,往往会对某个产品的一些功能进行封装,以库文件的形式发布,给第三方用户使用。第三方用户拿到这个库文件,就必须在编译的时候将这个库链接到应用程序中。
库文件用法有两种:
(1)、在编译列表中写出库文件全名(可带路径),在这里假设一个静态库文件名为libsos.a/libsos.so,那么链接方式为:

$gcc hello.c libsos.a 
$gcc hello.c libsos.so

(2)、分别用 -L指定库文件路径,并用 -l参数加上FOO名称即可,无需库文件全名。
a、将libsos.so所在目录添加到系统库文件搜索路径中,在编译的时候通过 -L dirname 完成。

$ gcc hello.c -L /home/vmuser/hello

b、指定链接库文件名,在编译的时候可通过 -lFOO参数将libsos.so链接到应用中:

$gcc hello.c -L /home/vmuser/hello -lFOO

注:使用了第三方库动态编译的可执行程序,在运行的时候还需要加载相应的库文件,但库文件的存放路径无需与编译路径一致,只要放在运行系统环境的库文件路径即可。

2.5、静态库和共享库的创建

(1)、静态库是.o文件的集合,这些.o文件是编译器按照常规方法生成的,在Linux下也称文档(archive),用ar工具来管理。
下面以用两个C文件创建静态库为例:在用户主目录下,创建一个libhelloa目录,并在其中创建hello1.c和hello2.c两个文件。
将两个文件编译成目标文件:

$gcc -c hello1.c hello2.c

用ar命令创建静态库文件:

$ar -r libhello.a hello1.o hello2.o

(2)、共享库也是目标文件的集合,但这些文件是由编译器按照特殊方式生成的,对象模块的每个地址(函数调用和变量引用)都是相对地址,允许在运行时被动态加载和运行。
创建共享库首先需要编译对象模块。继续以hello1.c和hello2.c为例进行示范。
在用户主目录下,创建一个libhelloso目录,并在其中创建hello1.c和hello2.c两个文件。

$gcc -c - fpic hello1.c hello2.c

与创建静态库不同,这里加入了-fpic参数,表示生成的对象模块是可重定位的,pic表示位置独立代码。
编译完成,得到了hello1.o和hello2.o两个文件,再用下列命令生成共享库。

$gcc -shared hello1.o hello2.o  -o libhello.so

你可能感兴趣的:(linux)