Ubuntu GCC简介和安装编译环境

来源:互联网 发布:cf辅助源码怎么用 编辑:程序博客网 时间:2024/05/22 18:06

【原文地址】:http://blog.sina.com.cn/s/blog_68e596750100jwtu.html

GCC简介

Linux系统下的gccGNU CCompiler)是GNU推出的功能强 大、性能优越的多平台编译器,是GNU的代表作品之一。gcc是可以在多种硬体平台上编译出可执行程序的超级编译器,其执行效率与一般的编译器相比平均效率要高20%~30%

gcc 编译器能将CC++语言源程序、汇程式化序和目标程序编译、连接成可执行文件,如果没有给出可执行文件的名字,gcc将生成一个名为a.out的文件。 在Linux系统中,可执行文件没有统一的后缀,系统从文件的属性来区分可执行文件和不可执行文件。而gcc则通过后缀来区别输入文件的类别,下面我们来介绍gcc所 遵循的部分约定规则。

 

.c为后缀的文件: C语言源代码文件;

.a为后缀的文件: 是由目标文件构成的档案库文件;

.C.cc.cxx为后缀的文件:   C++源代码文件;

.h为后缀的文件: 是程序所包含的头文件;

.i 为后缀的文件:是已经预处理过的C源代码文件;

.ii为后缀的文件:是已经预处理过的C++源代码文件;

.m为后缀的文件: Objective-C源代码文件;

.o为后缀的文件: 是编译后的目标文件;

.s为后缀的文件: 是汇编语言源代码文件;

.S为后缀的文件: 是经过预编译的汇编语言源代码文件。

 

gcc的执行过程

虽然我们称gccC语言的编译器,但使用gccC语言源代码文件生成可执行文件的过程不仅仅是编译的过程,而是要经历四个相互关联的步骤预处理(也 称预编译,Preprocessing)、编译(Compilation)、 汇编(Assembly)和连接(Linking)

命令gcc首先调用cpp进行预处理,在预处理过程中,对源代码文件中的文件包含(include)、预编译语句(如宏定义define)进行分析。接着调 用cc1进行编译,这个阶段根据输入文件生成以.o为后缀 的目标文件。汇编过程是针对汇编语言的步骤,调用as进行工作,一般来讲,.S为后缀的汇编语言 源代码文件和汇编、.s为后缀的 汇编语言文件经过预编译和汇编之后都生成以.o为后缀的目标文件。当所有的目标文件都生成之后,gcc就调用ld来完成最后的关键性工作,这个阶段就是连接。在连接阶段,所有的目标文件被安排在可执行程序中的恰当的位置,同时,该程序所调用到的库函数也从各自所在的档案库中连到合适的地方。

gcc的基本用法和选项

在使用gcc编 译器的时候,我们必须给出一系列必要的调用参数和文件名称。gcc编译器的调用参数大约有100多个,其中多数参数我们可能根本就用不到,这里只介绍其中最基本、最常用的参数。

gcc最基本的用法是∶gcc [options] [filenames]

其中options就 是编译器所需要的参数,filenames给出相关的文件名称。其中[options]的值可以为下列值:

-c,只编译,不连接成为可执行文件,编译器只是由输入的.c等源代码文件生成.o为后缀的目标文件,通常用于 编译不包含主程序的子程序文件。

-o output_filename,确 定输出文件的名称为output_filename,同时这个名称不能和源文件同名。如果不给出这个选项,gcc就给出预设的可执行文件a.out

-g,产生符号调试工具(GNUgdb)所必要的符号资讯,要想对源代码进行调试,我们就必须加入这个选项。

-O,对程序进行优化编译、连接,采用这个选项,整个源代码会在编译、连接过程中进行优化处理,这样产生的可执行文件的执行效率可以提高,但是,编译、连接的速度就相应地要慢一些。

-O2,比-O更 好的优化编译、连接,当然整个编译、连接过程会更慢。

-Idirname,将dirname所指出的目录加入到程序头文件目录列表中,是在预编译过程中使用的参数。C程序中的头文件包含两种情 况

A)#include

B)#include “myinc.h”

其中,A类使用尖括号(<>)B类使用双引号(“”)。对于A类,预处理程序cpp在系统预设包含文件目录(/usr/include)中搜寻相应的文件,而 对于B类,cpp在当前目录中搜寻头文件, 这个选项的作用是告诉cpp,如果在当前目录中没有找到需要的文件,就到指定的dirname目录中去寻找。在程序设计中,如果我们需要的这种包含文件分别分布在不同的目录中,就需要逐个使用-I选项给出搜索路径。

-Ldirname,将dirname所 指出的目录加入到程序函数档案库文件的目录列表中,是在连接过程中使用的参数。在预设状态下,连接程序ld在 系统的预设路径中(/usr/lib)寻 找所需要的档案库文件,这个选项 告诉连接程序,首先到-L指定的目录中去寻找,然后到系统预设路径中寻找,如果函数库存放在多个目录下,就需要依次使用这个选项,给出相应的存放目录。

-lname,在连接时,装载名字为“libname.a”的函数库,该函数库位于系统预设的目录或者由-L选项确定的目录下。例如,-lm表示连接名为“libm.a”的数学函数库。

上面我们简要介绍了gcc编译器最常用的功能和主要参数选项,更为详尽的资料可以参看Linux系 统的联机帮助。

 

为了更加详细的说明GCC参数极其相关的使用方法,我们再换一种方式来说明,以下为自问自答的十个问题:

1gcc包含的c/c++编 译器

gccccc++g++gcccc是一样的,c++g++是一样的,一般c程序就用gcc编译,c++程序就用g++编译

2gcc的基本用法

gcc test.c这样将编译出一个名为a.out的程序,gcc test.c -o test这样将编译出一个名为test的程序,-o参数用来指定生成程序的名字。

3、为什么会出现undefined reference to'xxxxx'错误?

首先这是链接错误,不是编译错误,也就是说如果只有这个错误,说明你的程序源码本身没有问题,是你用编译器编译时参数用得不对,你没有指定链接程序要用到得库,比如你的程序里用到了一些数学函数,那么你就要在编译参数里指定程序要链接数学库,方法是在编译命令行里加入-lm

4-l参数和-L参数

-l参数就是用来指定程序要链接的库,-l参数紧接着就是库名,那么库名跟真正的库文件名有什么关系呢?就拿数学库来说,他的库名是m,他的库文件名是libm.so, 很容易看出,把库文件名的头lib和尾.so去掉就是库名了。

好了现在我们知道怎么得到库名,当我们自已要用到一个第三方提供的库名字libtest.so,那么我们只要把libtest.so拷贝到/usr/lib里,编 译时加上-ltest参数,我们就能用上libtest.so库 了(当然要用libtest.so库里的函数,我们还需要与libtest.so配套的头文件)。

放在/lib/usr/lib/usr/local/lib里的库直接用-l参数就能链接了,但如果库文件没放在这三个目录里,而是放在其他目录里,这时我们只用-l参数的话,链接还 是会出错,出错信息大概是:“/usr/bin/ld: cannot find -lxxx”,也就是链接程序ld在那3个目录里找不到libxxx.so,这时另外一个参数-L就派上用场 了,比如常用的X11的库,它在/usr/X11R6/lib目录下,我们编译时就要用-L/usr/X11R6/lib -lX11参数,-L参数跟着的是库文件所在的目录名。再比如我们把libtest.so放在/aaa/bbb/ccc目录 下,那链接参数就是- L/aaa/bbb/ccc –ltest

另外,大部分libxxxx.so只是一个链接,以RH9为例,比 如libm.so它链接到/lib/libm.so.x/lib/libm.so.6又链接到/lib/libm-2.3.2.so,如果没有这样的链接,还是会出错,因为ld只会找libxxxx.so,所以如果你要用到xxxx
库,而只有libxxxx.so.x或 者libxxxx-x.x.x.so,做一个链接就可以了

ln -s libxxxx-x.x.x.solibxxxx.so

手工来写链接参数总是很麻烦的,还好很多库开发包提供了生成链接参数的程序,名字一般叫xxxx-config,一 般放在/usr/bin目录下,比如gtk1.2的 链接参数生成程序是gtk-config,执行gtk-config --libs就能得到以下输出"-L/usr/lib -L/usr/X11R6/lib -lgtk -lgdk-rdynamic

-lgmodule -lglib -ldl -lXi -lXext-lX11 -lm",这就是编译一个gtk1.2程 序所需的gtk链接参数,xxx-config除 了--libs参数外还有一个参数是--cflags用 来生成头文件包含目录的,也就是-I参数,在下面我们将会讲到。你可以试试执行gtk-config --libs --cflags,看看输出结果。

现在的问题就是怎样用这些输出结果了,最笨的方法就是复制粘贴或者照抄,聪明的办法是在编译命令行里加入这个`xxxx-config --libs--cflags`,比如编译一个gtk程序:gccgtktest.c `gtk-config --libs --cflags`这样
就差不多了。注意`不是单 引号,而是1键左边那个键。

除了xxx-config以外,现在新的开发包一般都用pkg-config来 生成链接参数,使用方法跟xxx-config类似,但xxx-config是 针对特定的开发包,但pkg-config包含很多开发包的链接参数的生成,用pkg-config--list-all命令可以列出所支持的所有开发包,pkg-config的用法就是pkg -config pagName --libs--cflags,其中pagName是包名,是pkg-config--list-all里列出名单中的一个,比如gtk1.2的 名字就是gtk+pkg-config gtk+ --libs --cflags的作用跟gtk-config --libs --cflags是一样的。比如:

gcc gtktest.c `pkg-config gtk+ --libs--cflags`

5-include-I参 数

-include用来包含头文件,但一般情况下包含头文件都在源码里用#include xxxxxx实 现,-include参数很少用。-I参数 是用来指定头文件目录,/usr/include目录一般是不用指定的,gcc知道去那里找,但是如果头文件不在/usr/include里 我们就要用-I参数指定了,比如头文件放在/myinclude目 录里,那编译命令行就要加上- I/myinclude参数了,如果不加你会得到一个"xxxx.h: No such file ordirectory"的错误。-I参数可以用相对路径,比如头文件在当前目录,可以用-I.来 指定。上面我们提到的--cflags参数就是用来生成-I 参数的

6-O参数

这是一个程序优化 参数,一般用-O2就是,用来优化程序用的,比如gcc test.c-O2,优化得到的程序比没优化的要小,执行速度可能也有所提高

7-shared参数

编译动态库时要用 到,比如gcc -shared test.c -olibtest.so

8、几个相关的环境变量

PKG_CONFIG_PATH:用来指定pkg-config用到的pc文件的路径,默认是/usr/lib/pkgconfigpc文件是文本文件,扩展名是.pc,里面定义开发包 的安装路径,Libs参数和Cflags参 数等等。

CC:用 来指定c编译器

CXX: 用来指定cxx编译器

LIBS: 跟上面的--libs作用差不多

CFLAGS:跟上面的--cflags作用差不多

CCCXXLIBSCFLAGS手动编译时一般用不上,在做configure时 有时用到,一般情况下不用管。

环境变量设定方 法:exportENV_NAME=xxxxxxxxxxxxxxxxx

9、关于交叉编译

交叉编译通俗地讲就是在一种平台上编译出能运行在体系结构不同的另一种平台上,比如在我们地PC平台(X86CPU)上编译出能运行在sparcCPU平 台上的程序,编译得到的程序在X86CPU平台上是不能运行的,必须放到sparcCPU平台上才能运行。当然两个平台用的都是linux,这种方法在异平台移植和嵌入式开发时用得非常普遍。相对与交叉编译,我们平常做的编译就叫本地编译,也就是在当前平台编译,编译得到的程序也是在本地执行。用来编译这种程序的编译器就叫交叉编译器,相对来说,用来做本地编译的就叫本地编译器,一般用的都是gcc, 但这种gcc跟本地的gcc编译器是不一样 的,需要在编译gcc时用特定的configure参 数才能得到支持交叉编译的gcc。为了不跟本地编译器混淆,交叉编译器的名字一般都有前缀,比如sparc-xxxx-linux-gnu-gccsparc-xxxx-linux-gnu-g++ 等等。

10、交叉编译器的使用方法

使用方法跟本地的gcc差不多,但有一点特殊的是:必须用-L-I参数指定编译器用sparc系统的库和头文件, 不能用本地(X86)的库(头文件有时可以用本地的)

例子:

sparc-xxxx-linux-gnu-gcc test.c-L/path/to/sparcLib

 -I/path/to/sparcInclude

 

gcc的错误类型及对策

 

gcc 编译器如果发现源程序中有错误,就无法继续进行,也无法生成最终的可执行文件。为了便于修改,gcc给出错误资讯,我们必须对这些错误资讯逐个进行分析、处理,并修改相应的语言,才能保证源代码的正确编译连接。gcc给出的错误资讯一般可以分为四大 类,下面我们分别讨论其产生的原因和对策。

第一类∶C语 法错误

错误资讯文件source.c中第n行有语法错误(syntexerrror)。这种类 型的错误,一般都是C语言的语法错误,应该仔细检查源代码文件中第n行及该行之前的程序,有时也需要对该文件所包含的头文件进行检查。有些情况下,一个很简单的语法错误,gcc会给出一大堆错误,我们最主要的是要保持清醒的头脑,不要被其吓倒,必要的时候再参考一下C语言的基本教 材。

第二类头 文件错误

错误资讯找不到头文件head.h(Can not find include filehead.h)。这类错误是源代码文件中的包含头文件有问题,可能的原因有头文件名错误、指定的头文件所在目录名错误等,也可能是错误地使用了双引号和尖括号。

第三类档 案库错误

错误资讯连接程序找不到所需的函数库,例如

ld: -lm: No such file or directory

这类错误是与目标文件相连接的函数库有错误,可能的原因是函数库名错误、指定的函数库所在目录名称错误等,检查的方法是使用find命令在可能的目录中寻找相应的函数库名,确定档案库及目录的名称并修改程序中及编译选项中的名称。

第四类未 定义符号

错误资讯有未定义的符号(Undefined symbol)。这类错误是在连接过程中出现的,可能有两种原因一是使用者自己定义的函数或者全局变量所在源代码 文件,没有被编译、连接,或者干脆还没有定义,这需要使用者根据实际情况修改源程序,给出全局变量或者函数的定义体;二是未定义的符号是一个标准的库函数,在源程序中使用了该库函数,而连接过程中还没有给定相应的函数库的名称,或者是该档案库的目录名称有问题,这时需要使用档案库维护命令ar检 查我们需要的库函数到底位于哪一个函数库中,确定之后,修改gcc连接选项中的-l-L项。

排除编译、连接过程中的错误,应该说这只是程序设计中最简单、最基本的一个步骤,可以说 只是开了个头。这个过程中的错误,只是我们在使用C语言描述一个算法中所产生的错误,是比较容易排除的。我们写一个程序,到编译、连接通过为止,应该说刚刚开始,程序在运行过程中所出现的问题,是算法设计有问题,说得更玄点是对问题的认识和理解不够,还需要更加深入地测试、调试和修改。一个程序,稍为复杂的程序,往往要经过多次的编译、连接和测试、修改。下面我们学习的程序维护、调试工具和版本维护就是在程序调试、测试过程中使用的,用来解决调测阶段所出现的问题。

GCC编译环境的安装
执行以下命令:
sudo apt-get install build-essentialGCC编译环境的安装1)创建hello.c文件sudo gedit hello.cUbuntu <wbr>GCC简介和安装编译环境2)编译文件$ gcc -g -Wall hello.c -o hello3)运行$ ./hello Hello, world!
0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 车子前保护杠塑料刮花了怎么办 糖猫电话手表关机了找不到了怎么办 小天才电话手表被洗衣机洗了怎么办 小天才电话手表放洗衣机洗了怎么办 小天才电话手表泡水了怎么办 小天才电话手表联不上网怎么办 肺炎用激素治疗后肚子大了怎么办 8岁以下儿童总是低烧不退怎么办? 微博里面的视频不能改变方向怎么办 朗逸导航倒车一体机死机了怎么办 乐淘乐电话手表的二维码没了怎么办 艾蔻儿童手表二维码丢了怎么办 糖猫儿童智能手表二维码丢了怎么办 海信电视用遥控器关了打不开怎么办 创维4k电视遥控器按键坏了怎么办 大疆3s云台陀螺仪错误怎么办 无线路由我用手机上网网速慢怎么办 下载的软件安装包以丢失怎么办 战舰世界航母的飞机恐惧状态怎么办 cad打开图纸不显示轴号怎么办 若背包忘在服务区没拿怎么办 使劲擤鼻涕耳朵耳朵疼了怎么办 用力擤鼻涕一侧的脸肿了怎么办 擦鼻涕太用力耳朵塞住了怎么办 宝宝鼻腔里有鼻涕呼呼响怎么办 黏痰在嗓子眼很干出不来怎么办 宝宝生病好了不久突然又咳嗽怎么办 7个月的宝宝经常生病怎么办 擤鼻涕鼻子周围红肿爆皮怎么办 洗衣机有鼻涕虫洗过的衣服怎么办 手机丢了里边有穿内衣照片怎么办 脸上不知是过敏还是湿疹流水怎么办 一个月的宝宝鼻子不通气怎么办 六个月的宝宝有清水鼻涕怎么办 一岁三个月宝宝流清鼻涕怎么办 宝宝流清水鼻涕怎么办最简单方法 8个月宝宝流清鼻涕怎么办 7个月宝宝流清鼻涕怎么办 9个月宝宝流清鼻涕怎么办 十一个月宝宝流清鼻涕怎么办 18个月宝宝咳嗽有痰怎么办