快捷搜索:
来自 67677新澳门手机版 2019-09-01 06:23 的文章
当前位置: 67677新澳门手机版 > 67677新澳门手机版 > 正文

Linux系统平台下关于GCC编写翻译及使用的艺术,


 

今天偶然看到这篇文章,做个入门了解还是不错的。

编译:


第一步、是进行预编译,使用-E参数可以让GCC在预处理结束后停止编译过程:

前一阵子在QQ上和朋友聊天的时候,总会看到有人说Linux上的应用程序开发是高手才可以完成的,而且这种“迷信”在目前似乎还很普遍。然而,情况并不是这样的,从程序库的支持方面,Linux平台为用户级应用程序的开发提供了很多功能强大且丰富的程序库,而且它们大部分是跨平台的(Boost、OpenGL、STL、Qt、Java等)和基于POSIX标准的(glibc等),同时Linux内核还为驱动程序的开发提供了功能完备的内核接口,从开发工具方面,Linux提供了功能强大的编译器GCC和调试器GDB,借助它们的帮助,我们可以很轻松的在Linu x上开发出可移植性的应用程序。既然如此,“迷信”又源于何来呢?我想,一方面由于详细介绍Linux各种开发的书籍较少,各种Linux应用在国内仍不普及,另一方面则是由于很多人在安装好一个Linux后,苦于找不到一个得心应手的IDE环境,从而感到不知所措,毕竟,我们很多人都习惯了写好程序后,按下F5,剩下的任务就让IDE全权代理了。其实想在Linux下如此这般当然也没问题。既然说到了IDE,就让我们从它开始吧,相信选择一个好的IDE环境是你整个学习过程的一个不错的开始。

gcc -E hello.c -o hello.i

 

预处理的宏定义插入到hello.i中


第二步、是将hello.i编译为目标代码,这可以通过使用-c参数来完成:

 

gcc -c hello.i -o hello.o

工欲善其事 必先利其器——IDE篇

也可以通过源文件直接生成

其实Linux下有许多功能强大的IDE环境,因为从某种意义上说,Linux是专为开发者准备的操作系统,这个东西当然少不了,在这里为读者介绍一些比较常用的IDE。

gcc -c hello.c

KDevelop

第三步、是将生成的目标文件链接成可执行文件:

这是一个用Qt开发的IDE,其主要支持的语言是C / C ,

gcc hello.o -o hello

Eclipse

也可以通过源文件直接生成

67677新澳门手机版 ,近年来,eclipse可以说发展极为迅速,它不仅是一个以java为主的开发平台,其功能强大的插件体系结构使得它可以被当作各种应用程序来使用。作为各种插件的载体,eclipse提供了完整的GUI接口,用户完全可以借助eclipse来只关心自己想做的工作。

gcc -o hello hello.c

Emacs

警告:

VIM

1、-pedantic 选项,那么使用了扩展语法的地方将产生相应的警告信息


2、-Wall 使用它能够使GCC产生尽可能多的警告信息

山高月晓 水落石出——IDE后台的故事 GCC篇

3、-Werror,它要求GCC将所有的警告当成错误进行处理

前面我们简要介绍了一些IDE环境,其中所有C/C 相关程序的编译都是由GCC来完成的,而IDE只不过起到了一个收集编译信息和为我们的项目生成makefile等作用(后面我们会提到)。出于目前Linux开发的特点,C仍是系统开发的主流语言。所以,对GCC有一个全面的了解是很有必要的,一旦IDE不能满足你的需求,我们要有手工打造程序的能力,而且出于学习的目的,我们往往不需要IDE生成的那些复杂的文件,为一个Hello world生成2M多的文件显然是多余的。

库依赖:

GCC的全称是GNU Compiler Collection,从这个名字我们不难看出,GCC代表着一个编译器的集合,目前GCC可以支持C, C , Objective-C, Objective-C , Fortran, Java, and Ada等语言。但是出于一般性考虑,我们这里只讨论GCC中的C/C 部分。

1、Linux下的大多数函数都默认:

目前GCC的最新发布版是4.0.0,但是这个版本由于使用了新技术和新的编码规范,很多旧的代码都需要修改才可以通过编译,所以并不推荐使用这个版本。而相对稳定的新版本目前是3.4.4,大家可以到GNU的主页上更新下载。那么究竟GCC强大在哪里,如何使用?下面我就通过几个简单而实际的例子带你看看GCC提供的强大功能。

头文件放到/usr/include/目录下


而库文件则放到/usr/lib/目录下

 

2、GCC在编译时必须有自己的办法来查找所需要的头文件和库文件。

通过Helloworld的编译熟悉GCC的基本使用方法

-I选项可以向GCC的头文件搜索路径中添加新的目录。

似乎为所有新语言提供一个Hello World样本程序已经成为了一种不成文的标准,人们通过它来认识语言的一些基本要素。在这里,我们使用一个Hello World来看看如何用GCC生成可执行文件。

例如,如果在/home/xiaowp/include/目录下有编译时所需要的头文件,为了让GCC能够顺利地找到它们,就可以使用-I选项:

1 #include<stdio.h>
2 
3 int main()
4 {
5     printf("hello world!rn");
6     return 0;
7 }

gcc -o test test.c -I /home/xiaowp/include

把上面的文件存成helloworld.c,之后打开控制台,输入如下的命令

-L选项向GCC的库文件搜索路径中添加新的目录

gcc helloworld.c –o helloworld

例如,如果在/home/xiaowp/lib/目录下有链接时所需要的库文件libfoo.so,为了让GCC能够顺利地找到它,可以使用下面的命令

如果一切正常的话,你的控制台上应该没有任何输出。用ls查看你的工作目录,你会发现目录下多了一个名为helloworld的可执行文件,之后,执行

gcc -o test test.c -L /home/xiaowp/lib -lfoo

./hellworld

值得好好解释一下的是-l选项,它指示GCC去连接库文件libfoo.so。

就会看到这个程序的输出了

Linux下的库文件在命名时有一个约定,那就是应该以lib三个字母开头,由于所有的库文件都遵循了同样的规范,因此在用-l选项指定链接的库文件名时可以省去lib三个字母,也就是说GCC在对-lfoo进行处理时,会自动去链接名为libfoo.so的文件。

很简单不是吗?但是学过计算机的朋友都应该知道,程序的编译过程要分为下图所示的过程而GCC的强大之处就在于它允许你在上面所示的任何一个过程中停下来查看中间结果,并对其加以控制。

-static选项,强制使用静态链接库

1. 预处理

如果在/home/xiaowp/lib/目录下有链接时所需要的库文件libfoo.so和libfoo.a

首先是预处理过程,GCC的-E选项可以让GCC在预处理后停止编译,并向标准输出打印预处理过后的文件。下面的-o用于指定输出文件的文件名。

为了让GCC在链接时只用到静态链接库,可以使用下面的命令:

gcc –E hellowrold.c –o helloworld.cpp

gcc -o test test.c -L /home/xiaowp/lib -static -lfoo

下面是helloworld.cpp的一部分的内容,我们看到,文件已经包含了stdio.h中的内容。

选项-O可以告诉GCC同时减小代码的长度和执行时间,其效果等价于-O1。

如果我们想执行下一步的编译过程,可以继续使用GCC的-x <language type>选项,该选项用于显示指定文件的后缀名(而不是让编译器根据后缀来自行判断)。我们比较常用的language type有如下几种,(如果读者想获得更为完整参数说名,请参考GCC manual):

在这一级别上能够进行的优化类型虽然取决于目标处理器,但一般都会包括线程跳转(Thread Jump)和延迟退栈(Deferred Stack Pops)两种优化。

l         c c-header c-cpp-output

选项-O2告诉GCC除了完成所有-O1级别的优化之外,同时还要进行一些额外的调整工作,如处理器指令调度等。

l         c c -header c -cpp-output

选项-O3则除了完成所有-O2级别的优化之外,还包括循环展开和其它一些与处理器特性相关的优化工作。

l         assembler assembler-with-cpp

通常来说,数字越大优化的等级越高,同时也就意味着程序的运行速度越快。

另外,下表列出了常用的GCC后缀名

许多Linux程序员都喜欢使用-O2选项,因为它在优化长度、编译时间和代码大小之间,取得了一个比较理想的平衡点。

文件后缀

注释

.c

需要经过预处理的C代码文件

.i

不需要经过预处理的C代码文件

.ii

不需要经过预处理的C 代码文件

.h

需要被预编译的C, C , Objective-C头文件

.cc .cp .cxx .cpp .CPP .c .C

需要被预处理的C 程序文件

.hh .H

需要被预编译的C 头文件

.s

汇编代码文件

.S

需要被预处理的汇编文件

time ./test 查看程序执行时间

 

优化虽然能够给程序带来更好的执行性能,但在如下一些场合中应该避免优化代码:

 

程序开发的时候优化等级越高,消耗在编译上的时间就越长,因此在开发的时候最好不要使用优化选项,只有到软件发行或开发结束的时候,才考虑对最终生成的代码进行优化。

当然,你也可以省略掉language type的部分,这时候GCC会根据文件的后缀名自行判断,就像你没有使用该选项一样。

资源受限的时候一些优化选项会增加可执行代码的体积,如果程序在运行时能够申请到的内存资源非常紧张(如一些实时嵌入式设备),那就不要对代码进行优化,因为由这带来的负面影响可能会产生非常严重的后果。

下面继续我们的编译过程

跟踪调试的时候在对代码进行优化的时候,某些代码可能会被删除或改写,或者为了取得更佳的性能而进行重组,从而使跟踪和调试变得异常困难。

2. 编译

加速:

如果我们想获得编译后的源文件可以使用-S选项,该选项让gcc只执行编译(生成汇编文件)而不进行汇编(生成目标文件),此时,我们可以用-o选项指定输出的汇编文件的名称。

使用管道代替编译中临时文件,

gcc –S helloworld.cpp –o hellowrld.S

-pipe 加速编译

3. 汇编

gcc -pipe foo.c -o foo

另外,我们还可以使用GCC的-c选项来编译和汇编源文件而不链接,此时-o指定的输出文件就是编译后的目标文件名

GCC常用选项

gcc –x c -c helloworld.cpp –o helloworld.o

-c 通知GCC取消链接步骤,即编译源码并在最后生成目标文件;

4. 链接

-Dmacro 定义指定的宏,使它能够通过源码中的#ifdef进行检验;

最后,我们可以利用GCC来把我们刚才生成的.o文件链接成可执行程序

-E 不经过编译预处理程序的输出而输送至标准输出;

gcc helloworld.o –o helloworld

-g3 获得有关调试程序的详细信息,它不能与-o选项联合使用;

这一次,我们使用了-o选项指定了可执行文件名,也就是说,根据输入文件类型的不同,-o有着不同的含义。

-Idirectory 在包含文件搜索路径的起点处添加指定目录;

5. 函数库的链接和包含文件

-llibrary 提示链接程序在创建最终可执行文件时包含指定的库;

对于我们编写的任和一个程序,没有库函数的支持是不可想象的,而当我们要使用的头文件和函数库不在GCC默认的搜索路径下的时候(例如OpenGL、Qt、KDE、Boost等),我们就需要手工来告诉GCC他们的位置。

-O、-O2、-O3 将优化状态打开,该选项不能与-g选项联合使用;

先来看头文件路径的指定。我们可以利用-I<dir_name>来指定我们希望GCC去搜索的头文件目录,例如我们要使用X11的程序,我们就要使用下面的选项

-S 要求编译程序生成来自源代码的汇编程序输出;

再来看库函数的设置:我们通过-L<dir_name>和-l<lib_name>两个命令行选项完成任务。其中-L用于告诉GCC在<dir_name>中去寻找函数库,而-l选项则告诉GCC使用用户指定的程序库。在Linux中,函数库的命名是遵循UNIX约定的,即lib{lib name},例如libsocket.so,所以当你需要告诉GCC使用这些库的时候,你就可以使用-lsocket选项。通常,这两个命令是结合在一起使用的,例如引用X11程序库的时候,我们可以这样:

-v 启动所有警报;

–L/usr/X11R6/lib –lX11

-Wall 在发生警报时取消编译操作,即将警报看作是错误;

另外,GCC在默认情况下使用共享库来链接程序,而当你想链接静态库的时候,一定要使用-static选项,例如-lncurses -static

-Werror 在发生警报时取消编译操作,即把报警当作是错误;

在这一部分的最后,我们对编译时用到的GCC常用命令做一个简要的总结

-w 禁止所有的报警。

 

第一步、是进行预编译,使用-E参数可以让GCC在预处理结束后停止编译过程: gcc -E hello.c -o hello.i 预处理的宏定义插入到hello.i中 第...

命令

说明

-x <language type>

显示指定输入文件的格式

-c

编译和汇编源文件,但不链接,输出为.o文件格式

-S

编译源文件,但不汇编,输出为.S文件格式

-E

只对源文件进行预处理,并不编译,输出为经过预处理的源代码

我们可以利用上面的-x和-c / –S / –E的组合来控制GCC的整个编译过程,其中-x用于告诉GCC我们从哪里开始,而-c / -S / -E用来告诉GCC在那里结束。

-o output-file

用来指定输出文件,该选项可以指定很多种输出文件,例如:可执行文件、目标文件、汇编文件或者是预处理过的程序代码等,这要根据具体的命令行参数而定。当然,GCC还提供了默认的-o选项,其中,默认的可执行文件是a.out,目标文件是<file_name>.o,汇编文件是<file_name>.s,预编译头文件的格式是<file_name>.suffix.gch

-I<dir name>

告诉GCC在<dir name>中去寻找头文件

-L<dir name>

告诉GCC在<dir name>中去寻找库文件

-l<lib name>

使用名为lib<lib name>.so的程序库

-static

通知GCC链接静态库

 

 

本文由67677新澳门手机版发布于67677新澳门手机版,转载请注明出处:Linux系统平台下关于GCC编写翻译及使用的艺术,

关键词: