g++重要编译参数

一、预处理、编译、汇编、链接

1、预处理

-E 参数使g++执行预处理操作。对源文件中的伪指令和特殊符号进行处理,生成处理后的文件。
e.g. g++ -E test.cpp -o test.i

2、编译

-S 参数使g++执行预处理和编译操作。对源文件进行预处理,并对预处理后的文件进行编译,生成汇编文件;或者对已经预处理过的文件进行编译,生成汇编文件。
e.g. g++ -S test.i -o test.s

3、汇编

-c 参数使g++执行预处理、编译和汇编操作。操作的对象可以是源文件或者经过上文预处理/汇编的文件,生成机器码文件。
e.g. g++ -c test.s -o test.o

4、链接

由汇编程序生成的目标文件并不能立即就被执行,其中可能还有许多没有解决的问题。例如,某个源文件中的函数可能引用了另一个源文件中定义的某个符号(如变量或者函数调用等);在程序中可能调用了某个库文件中的函数,等等。所有的这些问题,都需要经链接程序的处理方能得以解决。

链接程序的主要工作就是将有关的目标文件彼此相连接,也即将在一个文件中引用的符号同该符号在另外一个文件中的定义连接起来,使得所有的这些目标文件成为一个能够被操作系统装入执行的统一整体。

根据开发人员指定的同库函数的链接方式的不同,链接处理可分为两种:

静态链接
在这种链接方式下,函数的代码将从其所在的静态链接库中被拷贝到最终的可执行程序中。这样该程序在被执行时这些代码将被装入到该进程的虚拟地址空间中。静态链接库实际上是一个目标文件的集合,其中的每个文件含有库中的一个或者一组相关函数的代码。

动态链接
在此种方式下,函数的代码被放到称作是动态链接库或共享对象的某个目标文件中。链接程序此时所作的只是在最终的可执行程序中记录下共享对象的名字以及其它少量的登记信息。在此可执行文件被执行时,动态链接库的全部内容将被映射到运行时相应进程的虚地址空间。动态链接程序将根据可执行程序中记录的信息找到相应的函数代码。

对于可执行文件中的函数调用,可分别采用动态链接或静态链接的方法。使用动态链接能够使最终的可执行文件比较短小,并且当共享对象被多个进程使用时能节约一些内存,因为在内存中只需要保存一份此共享对象的代码。但并不是使用动态链接就一定比使用静态链接要优越。在某些情况下动态链接可能带来一些性能上损害。

链接操作没有固定的参数。若要对源码(以test.cpp为例)进行包括链接在内的全套编译操作,则命令为“g++ test.cpp”。实际上,前文介绍的-E、-S、-c都是在对编译过程进行限制,使其不能完成整个流程。当这些参数缺省时,编译器自然可以跑完全程。

链接时可能用到的参数如下。

-I 参数(大写i)指定的路径会被添加到编译器的头文件搜索路径列表中。该参数支持绝对路径和相对路径。该参数指定的路径优先级高于g++默认搜索的路径,g++会优先在-I指定的路径中寻找头文件。
e.g. g++ -I./include src/test.cpp

-l 参数(小写L)用于指定程序要链接的库,该库必须位于/lib或/usr/lib或/usr/local/lib目录下,该库可以是静态库也可以是动态库。
e.g. g++ -lglog test.cpp
上面的例子中,程序与名为glog的库相链接。

-L 参数也用于指定程序要链接的库所在的目录,该库位于/lib或/usr/lib或/usr/local/lib之外的目录下,该库可以是静态库也可以是动态库。-L与-l配合使用,以指定目录+库名。
e.g. g++ -L/home/usr/mylibfolder/ -lmytest test.cpp
上面的例子中,程序与/home/usr/mylibfolder/目录下的mytest库相链接。

-shared 参数用于编译动态库,常和-fPIC一同使用。

-fPIC 参数作用于编译阶段,使编译器编译的结果变为位置无关代码(Position-Independent Code)。此类代码中,没有绝对地址,全部使用相对地址。故代码被加载到内存的任意位置时,都可以正确的执行(共享库被加载时,在内存的位置不是固定的,故需要-fPIC)。
e.g. g++ -shared -fPIC test.cpp -o libtestlib.so
上面的例子中,将test.cpp编译为了名为testlib的动态库文件.

ar cqs 这不是g++命令的参数,而是生成静态库的命令。格式为“ar cqs lib+静态库的名称 用于生成静态库的目标文件的名称”。
e.g. ar cqs libmylib.a test.o
上面的例子中,用test.o生成了静态库mylib

-static g++在编译时默认使用动态链接。当存在同名的静态库和动态库时,若要使用静态链接,则要使用-static参数来将静态链接的优先级提高至动态链接之前。
e.g. g++ -static -la test.cpp -o teststatic

-Wl,-rpath -Wl表示编译器将后面的参数传递给链接器ld。-rpath有三个作用:添加一个文件夹作为运行时库的搜索路径。在将ELF可执行文件与共享对象链接时使用此选项;在链接时,一些动态库明确的链接了其他动态库, 则-rpath选项也可用于定位这些链接的动态库;在运行链接时,会优先搜索-rpath的路径,再去搜索LD_RUN_PATH的路径。将这两个参数同时使用,用于指定程序运行时查找动态链接库的路径,多个路径是使用冒号隔开,这样就不用添加路径到 /etc/ld.so.conf 文件中或者环境变量LD_LIBRARY_PATH了,在需要多个so版本共存时很有用。使用方法:将"-Wl,-rpath=你的路径"置于原本的链接命令之后即可。

二、其他常用编译参数

-g 参数使g++生成可被GDB使用的调试信息,用以调试程序。
e.g. g++ -g test.cpp

-O# 参数使g++根据#的取值来优化源代码。#的取值可为0到3,共四级。从0到3,优化程度在上一级的基础上依次提高。O0表示不做优化;O1为默认优化;O2除了默认优化以外,还做一些额外调整工作,例如指令调整等;O3包括循环展开和其他一些处理特性相关的优化工作。使用此类参数可能导致奇怪的问题,优化级别越高,出错可能性也越高。
e.g. g++ -O2 test.cpp

-Wall 参数可打印出来自g++的警告信息。
e.g. g++ -Wall test.cpp

-w 参数可关闭来自g++的警告信息。
e.g. g++ -w test.cpp

-std 参数可指定编译使用的语言标准。
e.g. g++ -std=c++11 test.cpp

-D 定义宏。-Dname表示对名称为name的宏进行定义,定义的内容默认为字符串“1”。
e.g. g++ -DDEBUG main.cpp

三、其他可能用到的Linux命令

1、file

file命令用于查看可执行程序使用的是动态链接还是静态链接。

2、ldd

ldd命令用于查看文件依赖的动态库。
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值