zoukankan      html  css  js  c++  java
  • GCC

    GNU提供的编译工具包括汇编器as、C编译器gcc、C++编译器g++、连接器ld和二进制转换工具objcopy。

    gcc命令提供了非常多的命令选项,但并不是所有都要熟悉,初学时掌握几个常用的就可以了,到后面再

    慢慢学习其它选项,免得因选项太多而打击了学习的信心。

    一. 常用编译命令选项 
    假设源程序文件名为test.c。

    1. 无选项编译链接 
    用法:#gcc test.c 
    作用:将test.c预处理、汇编、编译并链接形成可执行文件。这里未指定输出文件,默认输出为a.out。

    编译成功后可以看到生成了一个a.out的文件。在命令行输入./a.out 执行程序。./表示在当前目录,

    a.out为可执行程序文件名。

    2. 选项 -o 
    用法:#gcc test.c -o test 
    作用:将test.c预处理、汇编、编译并链接形成可执行文件test。-o选项用来指定输出文件的文件名。输

    入./test执行程序。

    3. 选项 -E <大写,注意>
    用法:#gcc -E test.c -o test.i

    or 
    作用:将test.c预处理输出test.i文件。

    4. 选项 -S <大写,注意>
    用法:#gcc -S test.i 
    作用:将预处理输出文件test.i汇编成test.s文件。

    5. 选项 -c 
    用法:#gcc -c test.s 
    作用:将汇编输出文件test.s编译输出test.o文件。

    6. 无选项链接 
    用法:#gcc test.o -o test 
    作用:将编译输出文件test.o链接成最终可执行文件test。输入./test执行程序。

    7. 选项-O 
    用法:#gcc -O1 test.c -o test 
    作用:使用编译优化级别1编译程序。级别为1~3,级别越大优化效果越好,但编译时间越长。输入./test

    执行程序。


    下面是GCC的一些常用选项描述:

    生成特定格式的文件:
    -E          只激活预处理,但不生成文件,需要把它重定向到一个输出文件里面。例子: 
                 gcc -E hello.c > pianoapan.txt 
    -C         在预处理的时候,不删除注释信息,一般和-E使用,有时候用这个分析程序很方便。 
    -S         只激活预处理和编译,就是指把文件编译成为汇编代码。 
      例子: gcc -S hello.c 
    -c          只激活预处理,编译,和汇编,也就是他只把程序做成obj文件 
      例子: gcc -c hello.c 
    -o          指定目标文件名称,例子:
      gcc -o hello hello.c

    -C
    在预处理的时候,不删除注释信息,一般和-E使用,有时候分析程序,用这个很
    方便的

    -M
    生成文件关联的信息。包含目标文件所依赖的所有源代码
    你可以用gcc -M hello.c来测试一下,很简单。

    -MM
    和上面的那个一样,但是它将忽略由#include<file>造成的依赖关系。


    包含头文件和库: 
    -include file 
      包含某个代码,简单来说,就是便以某个文件,需要另一个文件的时候,就可以用它设定,功能就相当于

    在代码中使用#include<filename>,例子用法: 
      gcc hello.c -include /root/pianopan.h 
    -Idir
      指定所需头文件的位置,在使用#include"file"的时候,gcc/g++会先在当前目录查找你所制定的头文

    件,如果没有找到,他回到缺省的头文件目录找,如果使用-I制定了目录,他会先在所指定的目录查找,然后

    再按常规的顺序依次查找。
    -I-                 参数“-Idir”的功能,所以一般在-Idir之后使用。 
    -Ldir 
      指定编译时,库的搜索路径。第三方或自己提供的库,可以用它制定目录,否则编译器将只在标准库

    的目录找。这个dir就是目录的名称。 
    -llibrary 
      制定编译的时候使用的库(指定了路径当然还得指定库名),常用的lib库有lpthread(线程库),

    lm(数学库),lz(zlib库)及lcrypto(linux下的MD5加密库)等,当然可以添加自己或第三方的库文

    件。例子:
      gcc -lncurses hello.c               使用ncurses库编译程序。

    优化选项:-O0/1/2/3/s               介绍如下:
    -O0                  不进行优化处理。
    -O/O1 GCC将执行减少代码尺寸和执行时间的优化,对于那些会严重影响编译时间的优化选项,这个级别

    的优化并不会执行。
    -O2                  在这一级别GCC将会提供所有支持的优化,但这其中并不包括以空间换时间的优化

    手段,例如编译器不会使用循环展开和函数内联。和-O相比,该选项进一步加快了编译时间和生成代码的

    性能。
    -O3                  除了-O2提供的优化选项外,还指定了-finline-functions,-funswitch-loops和

    -fgcse-afer-reload选项,目的只有一个就是全力执行代码优化,但是用"-O3 -fno-inline-functions"

    既可以使用-O3的功能又关闭函数内嵌功能。
    -Os                  这个选项是专门用来优化代码尺寸的,-Os打开了所有-O2级别中不会显著增长代

    码尺寸的优化选项 在用GDB调试优化后的程序时,运行时的指令和你所编写指令就有不一样,也就会出现

    你所想象不到的结果。对付这种情况时,需要在编译程序时关闭编译优化。  

    宏定义:
                       -DMACRO                         以字符串“1”(默认值)定义 MACRO 宏。
                       -DMACRO=DEFN              以字符串“DEFN”定义MACRO 宏,注意中间不能有空

    格。
                       -UMACRO                         取消对 MACRO 宏的定义。

    语言选项(LANGUAGE OPTIONS): 
    -ansi

    支持符合ANSI标准的C程序。

    -frtti    开启RTTI的支持(dynamic_cast和typeid需要用到),和vs c++不同,这在gcc中是默认选项

    。使用"-fno-rtti"将其禁用。

    -fno-builtin

           不接受不是两个下划线开头的内建函数(built-in function).目前受影响的函数有_exit, abort,

    abs, alloca, cos, exit, fabs, labs, memcmp, memcpy, sin, sqrt, strcmp, strcpy,和strlen。有时

    候上面的这些函数在一些地方被built-in后,会产生运算结果和预想的不一样甚至是错误的,比如abs(

    ),会导致-10*abs(x-1)== 10*abs(x-1)的怪异情况,原因是运算被优化而得到错误的结果。

    警告选项:

    -W               编译器的警告设置参数,拥有众多的选项,下面举一些常用的例子:
         -Woption 让编译器给出option指定的编译警告,常用的一些如下:
                       unused-function: 遇到仅声明过但尚未定义的静态函数时发出警告。
                       unused-parameter: 从未用过的函数参数的警告。
                       unused-variable: 在本地声明但从未用过的变量的警告。
                       unused-value: 经计算但从未用过的值得警告。
                       return-type: 对函数返回类型不当的警告。
                       uninitialized:在初始化之前就使用自动变量。
                       float-equal:   比较两个浮点数是否相等。
        -Wall       给出“几乎”所有的编译器警告,注意是“几乎”。下面是一些-Wall没有输出的警告

    类型:
                       sign-compare:将有符号类型和无符号类型数据进行比较时发出警告。
                       unreachable-code:如果发现从未执行的代码时给出警告。
                       inline:如果某函数不能按要求内嵌(inline),则无论是函数声明为inline或者

    是指定了-finline-functions 选项,编译都将发出警告。      
        -Werror               把所有的警告都视为错误处理。
        -Wno-option               如果我们不想输出某些警告信息,可以使用此参数形式,比如:
                       -Wno-unused-function
                       -Wno-unused-variable
                       -Wno-unused-parameter
                       -Wno-uninitialized

    调试和可执行文件形式:
    -g                 指示编译器,在编译的时产生调试信息。 
    -ggdb           此选项将尽可能的生成gdb的可以使用的调试信息(比-g生成的信息更多些)。
    -pg               此选项在运行后生成一个分析文件gmon.out分析每一个模块的运行时间等信息,可以

    用“gprof execname gmon.out”命令打开。
    -static           此选项将禁止使用动态库,编译得到的程序会比较大,但可以自由运行。 
    -share          此选项将尽量使用动态库,所以生成文件比较小,但是需要系统由动态库。

    上面的是一些常用的参数以及对应的选项,如有更细致的需求,可以参考man page。

    附加:使用GCC生成静态链接库或动态链接库
             首先需要目标文件(*.o),用gcc/g++ -c生成,如:gcc -c test1.c test2.c test3.c
    1. 生成静态链接库
             使用ar命令: ar -crv libtest.a test1.o test2.o test3.o 即可产生test.a文件。
             可以用命令 nm test.a 来看里面的目标文件和导出函数(带 T 标记)。
             使用的时候加上:-L(路径) -ltest。注意这里不是llibtest.a或llibtest,-l参数会自动添加

    lib和.a到首尾,然后去-L指定的目录加载.a文件。
    2.生成动态链接库
             用动态库的好处是:更新了动态库之后链结它的程序不用重新编译,但需要运行时链接。
             使用 gcc -o libtest.so -shared -fPIC      test1.o test2.o test3.o
             -fPIC:表示编译为位置独立的代码,不用此选项的话编译后的代码是位置相关的,所以动态载

    入时是通过代码拷贝的方式来满足不同进程需要,而不能达到真正代码段共享的目的。
             可以用命令 nm test.so 来看里面的目标文件和导出函数(带 T 标记)。

             还有一个需要注意的地方,在不同的硬件架构和位宽平台上的.a文件和.so文件不能互用,需要

    重新生成不同平台的.o文件,然后再生成相应的.a文件和.so文件。否则编译会出现“skipping

    incompatible ****.a/so”之类的错误。

    其他的一些工具:
    下面我们来看一些在我们的开发过程中有用的GNU工具。
    首先,我们如何来知道可执行程序或是目标文件的大小?size实用程序可以使我们知道文本尺寸(指令条

    数)以及data和bss段。如下面的例子:
    $ size test.o
    text    data      bss     dec      hex filename
    789     256       4       1049     419 test.o
    在这里我们列出了目标文件test.o的文件大小。我们发现文本尺寸(指令和常量)是789字节,data段是

    256字节,bss段(初始时自动设置为0)是4字节。如果我们要知道更为详细的内容,我们可以使用

    objdump实用程序。我们可以使用-syms参数来知道可执行程序或是目标文件的符号表,如下面的例子:
    $ objdump -syms test.o
    这会产生一个目标文件中可用符号列表,他们的类型(text,bss,data),长度,偏移量等内容。我们

    也可以使用disassemble参数来反汇编程序,如下面的例子:
    # objdump —disassemble test.o
    这会产生一个目标文件中的函数列表,以及由GCC产生的指令。
    最后,nm程序可以用来理解目标文件中的符号。这个程序不仅会列每一个符号以及符号类型的详细信息。

    还有一些其他的选项可用,我们可以从nm的主页中得到更为详细的内容。

  • 相关阅读:
    应用层
    传输层
    一元函数微分学
    函数、极限、连续
    网络层习题与真题
    网络层
    数据链路层习题与真题
    二、使用kubeadm部署k8s
    一、Kubernetes概述
    二、rsync文件同步
  • 原文地址:https://www.cnblogs.com/unixshell/p/3453541.html
Copyright © 2011-2022 走看看