【前言】火影中让我念念不忘的是赤砂之蝎,他不是个正面人物,出场次数也不太多。这个同学有一种说不出的含义,不是出场时傀儡的凶悍,也不是后来本体的单纯。
【原文】
http://lveyo.javaeye.com/blog/240578
http://blog.csdn.net/fuliangliang/archive/2005/10/02/494348.aspx
http://www.linuxsky.org/doc/dev/200805/305.html
GNU编译器集(其前身为GNU C编译器)诞生于1987年。当时Richard Stallman(GNU项目的创办人)想要创建一个编译器,它可以满足他定义的“自由软件”概念,并可用来编译GNU项目发布的其他软件。GNU C编译器迅速在自由软件社区中流行开来,而且以其健壮性和可移植性而闻名。它已成为许多集成开发工具的基础,被世界各地的发行商应用在Linux和其他操作系统之上。
GCC已不再是主要针对GNU项目自身的软件的小型C语言编译器了。如今,它已支持了许多不同的语言,包括C、C++、Ada、Fortran、Objective C,甚至还有Java。事实上,现代Linux系统除了可以自豪地炫耀那些由GNU工具直接支持的语言以外,它还支持大量其他语言。日益流行的脚本语言Perl、Python和Ruby,以及正在不断发展的mono 可移植C#实现的确有助于冲淡人们对Linux编程的传统看法,但这完全是另外一个问题了。
Linux内核和许多其他自由软件以及开放源码应用程序都是用C语言编写并使用GCC编译的。
1. 编译单个源文件
为了进行测试,你可以创建“Hello World”程序:
- #include <stdio.h>
- #include <stdlib.h>
- int main(int argc, char **argv)
- {
- printf("Hello world!/n");
- exit(0);
- }
使用如下命令编译并测试这个代码:
# ./hello
Hello wordl!
在默认情况下产生的可执行程序名为a.out,但你通常可以通过gcc的“-o”选项来指定自己的可执行程序名称。
2. 编译多个源文件
源文件message.c包含一个简单的消息打印函数:
- #include <stdio.h>
- void goodbye_world(void)
- {
- printf("Goodbye, world!/n");
- }
使用gcc的“-c”标记来编译支持库代码:
这一过程的输出结果是一个名为message.o的文件,它包含适合连接到一个较大程序的已编译目标代码。
创建一个简单的示例程序,它包含一个调用goodbye_world的main函数
- #include <stdlib.h>
- void goodbye_world(void):
- int main(int argc, char **argv)
- {
- goodbye_world();
- exit(0);
- }
现在有了两个目标文件:message.o和main.o。它们包含能够被Linux执行的目标代码。要从这个目标代码创建Linux可执行程序,需要再一次调用GCC来执行连接阶段的工作:
运行编译结果:
Goodbye, world!
前面这些单独的步骤也可以简化为一个命令,这是因为GCC对如何将多个源文件编译为一个可执行程序有内置的规则。
# ./goodbye
Goodbye, world!
3. 使用外部函数库
GCC常常与包含标准例程的外部软件库结合使用,几乎每一个Linux应用程序都依赖于由GNU C函数库GLIBC。
应用外部函数库的例子:
- #include <stdio.h>
- #include <stdlib.h>
- #include <math.h>
- #define MAX_INPUT 25
- int main(int agrc, char **argv)
- {
- char input[MAX_INPUT];
- double angle;
- printf("Give me an angle (in radians) ==>");
- if(!fgets(input, MAX_INPUT, stdin)){
- perror("an error occurred./n");
- }
- angle = strtod(input, NULL);
- printf("sin(%e) = %e/n", angle, sin(angle));
- return 0;
- }
GCC的"-lm"选项,它告诉GCC查看系统提供的数学库(libm)。因为Linux和UNIX的系统函数库通常以"lib"为前缀,所以我们假设它存在。真正的函数库位置随系统的不同而不同,但它一般会位于目录/lib或/usr/lib中,在这些目录中还有数以百计的其他必需的系统函数库。
4. 共享函数库与静态函数库
Linux系统上的函数库分为两种不同的类型:共享的和静态的
静态函数库:每次当应用程序和静态连接的函数库一起编译时,任何引用的库函数中的代码都会被直接包含进最终的二进制程序。
共享函数库:包含每个库函数的单一全局版本,它在所有应用程序之间共享。这一过程背后所涉及的机制相当复杂,但主要依靠的是现代计算机的虚拟内存能力,它允许包含库函数的物理内存安全地在多个独立用户程序之间共享。
使用共享函数库不仅减少了文件的容量和Linux应用程序在内存中覆盖的区域,而且它还提高了系统的安全性。一个被许多不同程序同时调用的共享函数库很可能会驻留在内存中,以在需要使用它时被立即使用,而不是位于磁盘的交换分区中。这有助于进一步减少一些大型Linux应用程序的装载时间。
将上面的message.c作为共享库函数使用的例子:
“PIC”命令行标记告诉GCC产生的代码不要包含对函数和变量具体内存位置的引用,这是因为现在还无法知道使用该消息代码的应用程序会将它连接到哪一段内存地址空间。这样编译输出的文件message.o可以被用于建立共享函数库,我们只需使用gcc的“- shared”标记即可:
将上面的mian.c使用共享库函数ligmessage.so编译:
此时运行编译好的goodbye会提示找不到共享函数库:
./goodbye: error while loading shared libraries: libmessage.so: cannot open shared object file: No such file or directory
可以使用命令 ldd来发现一个特定应用程序需要使用的函数库。ldd搜索标准系统函数库路径并显示一个特定程序使用的函数库版本。
linux-gate.so.1 => (0x00493000)
libmessage.so => not found
libc.so.6 => /lib/libc.so.6 (0x0097c000)
/lib/ld-linux.so.2 (0x0095a000)
库文件libmessage.so不能在任何一个标准搜索路径中找到,而且系统提供的配置文件/etc/ld.so.conf也没有包含一个额外的条目来指定包含该库文件的目录。
需要设置一个环境变量LD_LIBRARY_PATH来制定额外的共享函数库搜索路径,
# ldd goodbye
linux-gate.so.1 => (0x002ce000)
libmessage.so => /tmp/cpro/libmessage.so (0x00b0f000)
libc.so.6 => /lib/libc.so.6 (0x0097c000)
/lib/ld-linux.so.2 (0x0095a000)
Goodbye, world!
执行文件. 这些选项中最典型的是-O 和 -O2 选项.
如下命令 gcc -c -g hello.c
关于ggc的详细信息可用man gcc来查看
7。 gcc的-llibrary选项
-llibrary
连接名为library的库文件.
连接器在标准搜索目录中寻找这个库文件,库文件的真正名字是`liblibrary.a'.连接器会当做文件名得到准确说明一样引用这个文件.
搜索目录除了一些系统标准目录外,还包括用户以`-L'选项指定的路径.
一般说来用这个方法找到的文件是库文件---即由目标文件组成的归档文件(archive file).连接器处理归档文件的 方法是:扫描归档文件,寻找某些成员,这些成员的符号目前已被引用,不过还没有被定义.但是,如果连接器找到普通的 目标文件,而不是库文件,就把这个目标文件按平常方式连接进来.指定`-l'选项和指定文件名的唯一区别是, `-l选项用`lib'和`.a'把library包裹起来,而且搜索一些目录.
本文详细介绍了GCC编译器集的历史、功能和使用方法,包括编译单个源文件、多个源文件、使用外部函数库、共享函数库与静态函数库、优化选项等关键内容。此外,文章还解释了在Linux环境下gcc编译中关于头文件与库文件搜索路径的相关问题,并提供了使用GCC编译C代码的示例。
1万+

被折叠的 条评论
为什么被折叠?



