【Bash百宝箱】gcc命令

GCC即GNU Compiler Collection,GNU编译套件,支持C、C++等多种语言。在使用GCC的时候,我们必须给出一系列必要的参数选项和文件名称。参数选项分几类,包括总体选项、语言选项、预处理选项、汇编选项、链接选项、目录选项、警告选项、调试选项、优化选项、目标选项、机器相关选项、代码生成选项等。

1、下面介绍一些最基本、最常用的选项。

       gcc [-c|-S|-E] [-std=standard]
           [-g] [-pg] [-Olevel]
           [-Wwarn...] [-Wpedantic]
           [-Idir...] [-Ldir...]
           [-Dmacro[=defn]...] [-Umacro]
           [-foption...] [-mmachine-option...]
           [-o outfile] [@file] infile...

上面列出了gcc的常用选项,其用法可概括为:

gcc [options] <filenames>

其中,options就是gcc所需要的选项,filenames给出相关的文件名称。
-c:只编译或汇编源文件,但不进行链接,输出文件的后缀为.o
-S:gcc在编译后停止,不进行汇编,输出文件的后缀为.s
-E:gcc在预处理后停止,并输出预处理结果。
-std=standard:指定C、C++标准,如c11c++14gnu11gnu++14等。
-g:产生调试信息,信息格式(如stabs、COFF、XCOFF、DWARF 2)因操作系统而不同。
-p:生成额外的代码用以对prof程序进行性能分析,编译和链接时都要使用这个选项。
-pg:生成额外的代码用以对pgrof程序进行性能分析,编译和链接时都要使用这个选项。
-Olevel:指定优化程序的等级level,可以是1、2、3、0、s、fast、g,省略level时为1,优化之后,提高了程序执行效率,但编译速度会降低。
-w:禁止所有警告信息。
-Wwarn:警告相关,warn并不是关键字,它有许多候选项,如all表示产生大部分警告信息(一部分是很容易避免的),error表示把警告信息当作错误来处理并停止gcc编译。
-Wpedantic、-pedantic:输出ISO C/C++严格标准的所有警告,拒绝使用了禁用扩展的所有程序和一些不符合ISO C/C++规范的程序。
-Idir:添加头文件的搜索目录dir,先于系统目录。
-Ldir:添加库文件的搜索目录dir。
-Dmacro[=defn]:定义宏macro,其值为defn或者省略。
-Umacro:取消宏macro定义。
-foption:通过-f指定一些常用选项option,如-fsigned-char意思是把字符类型char当作带符号的即signed char
-mmachine-option:通过-m指定机器相关的选项machine-option,如-march=armv8-a+crc意思是指定ARM的架构。
-o outfile:指定输出文件的名称为outfile,不指定时根据编译规则作默认处理。
@file:从文件file中读取gcc命令行选项,这个选项使用时要谨慎。
infile:指定gcc将要处理的文件。
-llibrary:链接时搜索名字为library的库文件,如动态库libc.so,对应的选项为-lc
-static:在支持动态链接的系统上有效,链接时使用静态库(.a,相关的环境变量是LIBRARY_PATH),而不是默认的动态库(.so,相关的环境变量是LD_LIBRARY_PATH)。
-shared:在某些系统上有效,生成动态库,与选项-fpic一起使用。
-fpic:意为位置独立代码,指示编译程序生成的代码要适合共享库的内容,这样的代码能够根据载入内存的位置计算内部地址。
-fPIC:与-fpic不同的是链接的可执行文件的GOT(global offset table)没有最大长度的限制。
-v:打印gcc执行时执行的详细过程及其相关程序的版本号。

2、gcc根据文件名称的不同后缀做不同的事情。

.c:C源码,必须预处理。
.i:C源码,不用预处理,已经预处理过了。
.ii:C++源码,不用预处理,已经预处理过了。
.h:C、C++头文件。
.cc、.cp、.cxx、.cpp、.CPP、.c++、.C:这些都是C++源码,必须预处理。
.hh、.hp、hxx、.hpp、.HPP、.h++、.H:这些都是C++头文件。
.s:汇编代码。
.sx、.S:同样是汇编代码,但必须预处理。
另外,.a为静态库,.so为动态库,.o为编译后的目标文件。

3、gcc编译的几个阶段,并通过file命令查看各阶段编译结果的文件格式。

// main.c
#include <stdio.h>

int main()
{
    printf("hello world\n");

    return 0;
}

第一,预编译过程,这个过程处理宏定义和include,并做语法检查。

$ gcc –E main.c –o main.i
$ file main.c
main.c: C source, ASCII text
$ file main.i
main.i: C source, ASCII text

第二,编译过程,这个过程生成汇编代码i(main.s)。

$ gcc –S main.i
$ file main.s
main.s: assembler source, ASCII text

第三,汇编过程,这个过程生成目标代码(main.o)。

$ gcc –c main.s
$ file main.o
main.o: ELF 64-bit LSB relocatable, x86-64, version 1 (SYSV), not stripped

第四,链接过程,这个过程生成可执行代码。

$ gcc main.o –o main
file main
main: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=b27595ba2689cec1a5180a5f18ff9cd19930ac3c, not stripped

最后,运行程序。

$ ./main
hello world

另外,我们可以使用命令strip去除可执行文件的符号信息。

$ strip main
$ file main
main: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=b27595ba2689cec1a5180a5f18ff9cd19930ac3c, stripped

4、编译静态库和动态库。

例子,将hello.c和hello2.c分别编译成静态库libhello.a和动态库libhello.so。

第一,编译静态库。

$ gcc –c hello.c hello2.c
$ ar –r libhello.a hello.o hello2.o

ar是个文件打包工具。

第二,编译动态库。

$ gcc –c –fpic hello.c hello2.c
$ gcc –shared hello.o hello2.o -o libhello.so

查看.o文件、可执行文件、库文件的信息可使用如下命令:

nm - list symbols from object files.
objdump - display information from object files.
readelf - Displays information about ELF files.

5、查看预处理阶段使用了哪些宏。

gcc在预处理阶段会展开宏定义,使用如下两条命令都可以查看foo.c在预处理阶段使用了哪些宏,包括gcc内置宏和用户自定义宏。

$ gcc -E -dM foo.c
$ cpp -dM foo.c
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值