编译

来源:互联网 发布:中国穷人 知乎 编辑:程序博客网 时间:2024/05/17 20:22

在Linux下进行C语言编程,必然要采用GNU GCC来编译C源代码生成可执行程序。Gcc指令的一般格式为:
Gcc [选项] 要编译的文件 [选项] [目标文件]。其中,目标文件可缺省,Gcc默认生成可执行的文件名为:编译文件.out
看一下经典入门程序"Hello World!"
# vi hello.c ,编辑如下:
#include <stdlib.h>
#include <stdio.h>
void main(void)
{
       printf("hello world!/r/n");
}
用gcc编译成执行程序。#gcc hello.c,该命令将hello.c直接生成最终二进制可执行程序a.out。./a.out就可以执行。
      这条命令隐含执行了(1)预处理、(2)汇编、(3)编译、(4)链接,形成最终的二进制可执行程序。现在我们就用GCC的命令选项来逐个剖析GCC过程。
1),预处理(Pre-processing)。在该阶段,编译器将C源代码中的包含的头文件如stdio.h编译进来,用户可以使用gcc的选项”- E”进行查看。用法:#gcc -E hello.c -o hello.i,作用:将hello.c预处理输出hello.i文件。通过vi hello.i可以看到预处理过程信息。
2),编译阶段(Compiling)。在这个阶段中,Gcc首先要检查代码的规范性、是否有语法错误等,以确定代码的实际要做的工作,在检查无误后,Gcc把代码翻译成汇编语言。用户可以使用”-S”选项来进行查看,生成汇编代码。
用法:[root]# gcc –S hello.i –o hello.s
3),汇编阶段(Assembling)。汇编阶段是把编译阶段生成的”.s”文件转成二进制目标代码。用法:[root]# gcc –c hello.s –o hello.o
4),链接阶段(Link)。用法:[root]# gcc hello.o –o hello.exe,作用:将编译输出文件hello.o链接成最终可执行文件hello.exe。

       函数库一般分为静态库和动态库两种。静态库是指编译链接时,把库文件的代码全部加入到可执行文件中,因此生成的文件比较大,但在运行时也就不再需要库文件 了。其后缀名一般为“.a”。动态库与之相反,在编译链接时并没有把库文件的代码加入到可执行文件中,而是在程序执行时由运行时链接文件加载库,这样可以 节省系统的开销。动态库一般后缀名为”.so”,如前面所述的libc.so.6就是动态库。gcc在编译时默认使用动态库。

 

=====================================================
      ln:该命令在文件之间创建链接。这种操作实际上是给系统中已有的某个文件指定另外一个可用于访问它的名称。对于这个新的文件名,我们可以为之指定不同的 访问权限,以控制对信息的共享和安全性的问题。如果链接指向目录,用户就可以利用该链接直接进入被链接的目录而不用打一大堆的路径名。而且,即使我们删除 这个链接,也不会破坏原来的目录。
      格式:ln [选项] 目标 目录
      链接有两种,一种被称为硬链接(Hard Link),另一种被称为符号链接(Symbolic Link)。建立硬链接时,链接文件和被链接文件必须位于同一个文件系统中,并且不能建立指向目录的硬链接。而对符号链接,则不存在这个问题。默认情况 下,ln产生硬链接。如果给ln命令加上- s选项,则建立符号链接。
      硬链接只能引用同一文件系统中的文件。它引用的是文件在文件系统中的物理索引( inode)。当移动或删除原始文件时,硬链接不会被破坏,因为它所引用的是文件的物理数据而不是文件在文件结构中的位置。
      符号链接是一个指针,指向文件在文件系统中的位置。符号链接可以跨文件系统,甚至可以指向远程文件系统中的文件。符号链接只是指明了原始文件的位置,用户 需要对原始文件的位置有访问权限才可以使用链接。如果原始文件被删除,所有指向它的符号链接也就都被破坏了。它们会指向文件系统中并不存在的一个位 置。(删除符号链接并不会删除原文件)

 

Linux GCC 编译过程


目 前Linux下最常用的C语言编译器是GCC(GNU Compiler Collection),它是GNU项目中符合ANSI C标准的编译系统,能够编译用C、C++和Object C等语言编写的程序.GCC不仅功能非常强大,结构也异常灵活.最值得称道的一点就是它可以通过不同的前端模块来支持各种语言,如Java、 Fortran、Pascal、Modula-3和Ada等.
Linux系统下的gcc(GNU C Compiler)是GNU推出的功能强大、性能优越的多平台编译器,是GNU的代表作品之一。gcc是可以在多种硬体平台上编译出可执行程序的超级编译器,其执行效率与一般的编译器相比平均效率要高20%~30%。
使用GCC编译程序时,编译过程可以被细分为四个阶段:
◆ 预处理(Pre-Processing)
◆ 编译(Compiling)
◆ 汇编(Assembling)
◆ 链接(Linking)
.c为后缀的文件,C语言源代码文件;
.a为后缀的文件,是由目标文件构成的档案库文件;
.C,.cc或.cxx 为后缀的文件,是C++源代码文件;
.h为后缀的文件,是程序所包含的头文件;
.i 为后缀的文件,是已经预处理过的C源代码文件;
.ii为后缀的文件,是已经预处理过的C++源代码文件;
.m为后缀的文件,是Objective-C源代码文件;
.o为后缀的文件,是编译后的目标文件;
.s为后缀的文件,是汇编语言源代码文件;
.S为后缀的文件,是经过预编译的汇编语言源代码文件。
命 令gcc首先调用cpp进行预处理,在预处理过程中,对源代码文件中的文件包含(include)、预编译语句(如宏定义define等)进行分析。接着 调用cc1进行编译,这个阶段根据输入文件生成以.o为后缀的目标文件。汇编过程是针对汇编语言的步骤,调用as进行工作,一般来讲,.S为后缀的汇编语 言源代码文件和汇编、.s为后缀的汇编语言文件经过预编译和汇编之后都生成以.o为后缀的目标文件。当所有的目标文件都生成之后,gcc就调用ld来完成 最后的关键性工作,这个阶段就是连接。在连接阶段,所有的目标文件被安排在可执行程序中的恰当的位置,同时,该程序所调用到的库函数也从各自所在的档案库 中连到合适的地方。
例程1:hello.c
#include
int main(void)
{
printf ("Hello world, Linux programming!/n");
return 0;
}
然后执行下面的命令编译和运行这段程序:
# gcc hello.c -o hello
# ./hello
Hello world, Linux programming!
首先,GCC需要调用预处理程序cpp,由它负责展开在源文件中定义的宏,并向其中插入“#include”语句所包含的内容;接着,GCC会调用ccl和as将处理后的源代码编译成目标代码;最后,GCC会调用链接程序ld,把生成的目标代码链接成一个可执行程序.
◆ 预处理(Pre-Processing)
使用-E参数可以让GCC在预处理结束后停止编译过程:
# gcc -E hello.c -o hello.cpp
◆ 编译(Compiling)
下一步是将hello.i编译为目标代码,这可以通过使用-c参数来完成:
# gcc -x cpp-output hello.cpp -o hello.o
或者
# gcc -c hello.cpp -o hello.o
◆ 汇编(Assembling)
◆ 链接(Linking)
# gcc hello.o -o hello
汇编应该调用as,这里应该是一起完成了
gcc主要参数:
-o 定义输出文件
-E 完成预处理/预编译停止
-c 只编译生成.o,不连接
-x 指定编译步骤
-g gdb调试用,在可执行程序中包含标准调试信息
-O,O1,O2,O3,O4,O5 优化级别
-w 关闭所有警告
-Wall 允许所有有用的警告
-DFOO=BAR 定义预处理宏FOO的值为BAR
-IDIRNAME 将DIRNAME加入到包含文件的搜索目录中去
-LDIRNAME 将DIRNAME加入到库文件文件的搜索目录中去
-static 静态链接库
-lFOO 动态连接库,名为libFOO.o/libFOO.so(2.4/2.6)
-mcpu=CPU TYPE 针对不同CPU作不同的优化,比如-m386,-mpentiumpro

原创粉丝点击