Linux-编译器gcc/g++编译步骤
gcc和g++现在是gnu中最主要和最流行的c&c++编译器。g++是c++的命令,以.cpp为主;对于c语言后缀名一般为.c,这时候命令换做gcc即可。编译器是根据gcc还是g++来确定是按照C标准还是C++标准编译链接。
gcc和g++都是GNU(组织)的一个编译器。但两者有一些区别:后缀为.c的文件gcc把它当做c程序,g++当做c++程序。后缀为c++的两者都当做c++程序。对于cpp程序,无论gcc或者是g++编译阶段都是相同的,都是用的gcc进行编译,但是在链接阶段gcc不能自动和c++程序使用的库连接,如果使用的话,形如下:
gcc helloworld.cpp -lstdc++ -o helloworld
所以我们通常用g++来进行连接(g++会自动连接c++常用库),所以为了使用方便对于cpp程序干脆编译链接统统都使用g++,这样就给人一种错觉,好像cpp只能用g++编译。
一. g++编译步骤
g++在执行编译工作的时候,总共需要以下几步(以源码Test.cpp为例):
1.预处理,生成.i的文件[预处理器cpp]
命令:
g++ -E Test.cpp > Test.i
功能:
输出预处理后的文件,linux下以.i为后缀名。只激活预处理,这个不生成文件,你需要把它重定向到一个输出文件里 。这一步主要做了这些事情:宏的替换,还有注释的消除,还有找到相关的库文件。用编辑器打开Test.i会发现有很多很多代码,你只需要看最后部分就会发现,预处理做了宏的替换,还有注释的消除,可以理解为无关代码的清除。下面是Test.i文件的最后部分,可以看见宏的替换和注释的消除。
2.将预处理后的文件转换成汇编语言,生成文件.s[编译器egcs]
命令:
g++ -S Test.cpp
功能:
会生成Test.s文件,.s文件表示是汇编文件,用编辑器打开就都是汇编指令。
3.由汇编变为目标代码(机器代码)生成.o的文件[汇编器as]
命令:
g++ -c Test.cpp
功能:
.o是GCC生成的目标文件,除非你是做编译器和连接器调试开发的,否则打开这种.o没有任何意义。
4.连接目标代码生成可执行程序[链接器ld]
命令:
g++ Test.o -o Test -l ACE
功能:
将.o文件与所需的库文件链接整合形成可执行文件。至此完成。
二. gcc编译步骤
gcc在执行编译工作的时候,总共需要以下几步(以源码Test.cpp为例):
1.预处理,生成.i的文件
命令:
gcc -E Test.cpp -o Test.i
功能:
预处理阶段过程如下,预处理阶段是进行处理代码中的宏和include指令,并作语法检查。可以看到由于进行了预处理,将include内部的文件进行了替换,预处理后的结果文件显得特别大,所以在以后的程序中,没有用到的头文件最好不要引入,这样会降低处理时间和空间。
2.将预处理后的文件转换成汇编语言,生成文件.s
命令:
gcc -S Test.cpp
功能:
会生成Test.s文件,.s文件表示是汇编文件,用编辑器打开就都是汇编指令。
3.由汇编变为目标代码(机器代码)生成.o的文件
命令:
gcc -c Test.s -o Test.o
功能:
这一步是将汇编的代码进一步进行处理,每一个源程序都会生成相应的目标文件,是以.o为扩展名的文件。
4.连接目标代码生成可执行程序
命令:
gcc Test.o -o Test -l ACE
功能:
将.o文件与所需的库文件链接整合形成可执行文件。至此完成。
三. gcc/g++常用参数说明
-E
只进行预处理选项,不进行汇编、目标文件生成和连接
-S
生成汇编文件后停止,不进行目标文件生成和连接
-c
编译并生成目标文件,不进行连接(compile but not link)
-g
只是编译器,在编译的时候,产生调试信息( insert debugging info in your exutable)
-o
生成指定的输出文件,用在生成可执行文件时(output file)
-static
强制使用静态库
-shared
强制使用共享库
-l library
指定编译的时候使用的库( link a lib)
例子用法:
gcc -lcurses hello.c
这个library就是ncurses库
-L dir
制定编译的时候,搜索库的路径(include and lib paths)。比如你自己的库,可以用它制定目录,不然
编译器将只在标准库的目录找。这个dir就是目录的名称
-fPIC
表示编译为位置独立的代码( position independent code (dosen't work sometimes)),不用此选项的话编译后的代码是位置相关的所以动态载入时是通过代码拷贝的方式来满足不同进程的需要,而不能达到真正代码段共享的目的。
-Wall
表示打开报警提示信息(turn on warnings)