• gcc入门


    1 gcc编译流程

    gcc编译程序主要经过四个过程:

    • 预处理(Pre-Processing)
    • 编译 (Compiling)
    • 汇编 (Assembling)
    • 链接 (Linking)

    (1)预处理

    在预处理阶段,编译器主要作加载头文件、宏替换、条件编译的作用。一般处理带“#”的语句。

    我们可以通过gcc 的 -E 选项进行查看,如下所示:

    gcc -E main.c -o main.i
    

    编译器将main.c预处理结果输出 main.i 文件。

    (2)编译

    在编译过程中,编译器主要作语法检查和词法分析。在确认所有指令都符合语法规则之后,将其翻译成等价的中间代码或者是汇编代码。

    gcc -S main.i -o main.s
    

    编译器将预处理结果文件main.i翻译成汇编代码main.s

    (3)汇编

    汇编阶段是把编译阶段生成的”.s”文件转成二进制目标代码。

    gcc -c main.s -o main.o
    

    编译器将main.s文件转化为main.o 文件。

    (4)链接

    在成功编译之后,就进入了链接阶段。链接就是将目标文件、启动代码、库文件链接成可执行文件的过程,这个文件可被加载或拷贝到存储器执行。

    gcc main.o -o main.exe
    

    编译器将main.o链接成最终可执行文件main.exe

    2 gcc常用选项

    选项名 作用 生成
    -o 产生目标 .i、.s、.o、可执行文件等
    -E 只运行C预编译器 .c文件 -> .i文件
    -S 告诉编译器产生汇编程序文件后停止编译 .i文件 -> .s文件
    -c 通知gcc取消连接步骤,即编译源码,并在最后生成目标文件 .s文件 -> .o文件

    现在我们有源文件hello.c,下面是一些gcc的使用示例:

    gcc -E hello.c -o hello.i    对hello.c文件进行预处理,生成了hello.i文件
    gcc -S hello.i -o hello.s    对预处理文件进行编译,生成了汇编文件
    gcc -c hello.s -o hello.o    对汇编文件进行编译,生成了目标文件
    gcc hello.o -o hello         对目标文件进行链接,生成可执行文件
    gcc hello.c -o hello         直接编译链接成可执行目标文件
    gcc -c hello.c 或 gcc -c hello.c -o hello.o 编译生成可重定位目标文件
    

    3 gcc编译多个程序

    // hello.c
    #include<stdio.h>
    #include"hello.h"
    void printHello()
    {
            printf("hello world!\n");
    }
    
    //main.c
    #include<stdio.h>
    #include"hello.h"
    int main()
    {
            printHello();
            return 0;
    }
    //hello.h
    
    //头文件hello.h,仅包含函数声明
    #ifndef _HELLO_
    #define _HELLO_
    void printHello();
    #endif
    

    编译这三个文件,可以一次编译生成可执行文件main

    gcc hello.c main.c -o main
    

    注意若不在同一目录下,需要用-I链接库文件路径(大写i)

    在gcc 的-I参数后加上静态库头文件的路径。(大写i)
    在gcc 的-L参数后加上库文件所在目录
    在gcc 的-l参数后加上库文件名,不过要去掉lib和.a扩展名。(小写L)

    也可以独立编译:

    gcc -Wall -c main.c -o main.o
    gcc -Wall -c hello.c -o hello.o
    gcc -Wall main.o hello.o -o main
    

    -Wall:使gcc对源文件的代码有问题的地方发出警告

    4 生成静态库

    静态库就是一些.o目标文件的集合,以.a结尾

    为了生成.a文件,我们需要先生成.o文件。下面这行命令将我们的hello.o打包成静态库libhello.a

    ar rcs libhello.a hello.o
    

    注: rcs中的r表明将模块hello.o加入到静态库中,c表示创建静态库,s表示生产索引。

    ar是gun归档工具,如果libhello之前存在,将创建新的libhello.a并将其替换。

    然后就可以这样来使用静态库libhello.a

    gcc -Wall main.c libhello.a -o main
    ./main
    

    -L指定路径,-l指定具体库,配合使用

    本例中-L.指示链接库路径(当前路径),-l指定链接库。库名为hello(不指定前缀lib和后缀.a)

    -I参数用来指定头文件目录,用来指定程序要链接的库(库文件在/lib、/usr/lib和/usr/local/lib下)。-l参数紧接着就是库名,那么库名跟真正的库文件名有什么关系呢?就拿数学库来说,他的库名是m,他的库文件名是libm.so,很容易看出,把库文件名的头lib和尾.so去掉就是库名了。好了现在我们知道怎么得到库名了,比如我们自已要用到一个第三方提供的库名字叫libtest.so,那么我们只要把libtest.so拷贝到/usr/lib里,编译时加上-ltest参数,我们就能用上libtest.so库了

    5 生成动态库

    (1)理解动态库

    在Linux系统下,创建动态链接库是件很简单的事情。只要在编译函数库源程序时加上-shared选项即可,这样所生成的执行程序即为动态链接库。从某种意义上来说,动态链接库也是一种执行程序。按一般规则,程序名应带.so后缀。

    gcc -shared -fPIC -o libhello.so hello.c
    

    参考博客:动态库基本原理和使用方法,-fPIC选项的来龙去脉 理解

    (2)创建和使用动态链接库

    gcc -c -fPIC hello.c
    gcc -shared -o libhello.so hello.o
    gcc main.c -L. -lhello
    export LD_LIBRARY_PATH=./
    ./a.out
    

    引用

  • 相关阅读:
    DFS的联通性问题
    Stl-unordered_map 无序关联式容器的基本用法(xmind)
    【图论】匈牙利算法——社会人数规模专家
    AcWing 860. 染色法判定二分图
    AcWing 1227. 分巧克力(二分)
    【图论】【最小生成树】prim【AcWing】局域网&&繁忙的都市
    【图论】拓扑排序
    Stl—bitset用法
    vector< vector<int> > 的初始化
    Floyd——人人都是中间商(50%)
  • 原文地址:https://www.cnblogs.com/cqszxy2020/p/16728641.html
Copyright © 2020-2023  润新知