Linux下gcc相关

a.gcc工作流程

预处理: 宏定义替换, 头文件展开, 去掉注释, 条件编译不会进行语法检查, C文件->C文件 xxx.i  命令: gcc -E

编译: 语法检查, 生成汇编文件 xxx.s 命令: gcc -S (用时最长)

汇编: 将汇编文件生成二进制文件 xxx.o 命令: gcc -c

链接: 将二进制文件插入启动代码生成可执行文件 命令: gcc 默认生成a.out

b.gcc常用参数

  -v/-version 查看版本号

  -l 编译的时候指定头文件目录. include "head.h" 默认是在当前目录中找, 如果头文件不在当前目录,则需要-l来指定头文件的目录

  -E 预处理, 生成xxx.i; -S 编译, 生成xxx.s; -c 汇编, 生成xxx.o; -o 指定生成的文件名字

  -g 生成可执行程序中添加调试信息(有源码, 方便调试, 文件一般比较大)

  -D 编译的时候指定宏, 一般用在调试时, 假如宏做命令的参数

  -Wall 添加警告信息, 可理解为严格编译, n = 0, 1, 2, 3 一般默认为O1

  -On 设置代码的优先级别

c.gcc--动态库静态库 -- 二进制文件

  静态库: (不过一般使用在makefile中)

    命名规则: libxxx.a

    制作步骤:

      1:生成对应的.o文件 gcc -c *.c(将所有的.c文件编译成.o文件)

      2:将.o打包成静态库 ar rcs libxxx.a *.o

        参数r:在库中插入模块(替换)。当插入的模块名已经在库中存在,则替换同名的模块。如果若干模块中有一个模块在库中不存在,ar显示一个错误消息,并不替换其            他同名模块。默认的情况下,新的成员增加在库的结尾处,可以使用其他任选项来改变增加的位置
        参数c:创建一个库。不管库是否存在,都将创建
        参数s:创建目标文件索引,这在创建较大的库时能加快时间。(补充:如果不需要创建索引,可改成大写S参数;如果。a文件缺少索引,可以使用ranlib命令添加)

      3:使用 gcc main.c -l 头文件路径 -L 库的路径 -l 库的名字(xxx)

  动态库:

    命名规则: libxxx.so

    制作步骤:

      1: 生成.o文件 gcc -c -fpic(fPIC) *.c

      2: 将.o文件打包 gcc -shared *.o -o libxxx.so

      3: 使用 gcc main.c -l 头文件路径 -L 库的路径 -l 库的名字(xxx) 

        此时是无法运行的(ldd 可执行程序(查看链接)), 因为静态库也称之为共享库, 并且是在程序使用时编译进去, 所以编译时会检测有没有包含动态库

        如果有的话, 虽然使用时指定了库的名字, 但是还要指定其路径, 此时就需要系统动态载入器(dynamic linker/loader)

        对于elf格式的可执行程序,是由ld-linux.so*来完成的,它先后搜索elf文件的 DT_RPATH段 — 环境变量LD_LIBRARY_PATH — /etc/ld.so.cache        文件列表 — /lib/, /usr/lib目录找到库文件后将其载入内存

      解决:

    1. 拷贝自己制作的共享库到/lib或者/usr/lib
    2. 临时设置(环境变量)LD_LIBRARY_PATH

    命令: LD_LIBRARY_PATH=目录:$LD_LIBRARY_PATH
          export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:库路径
      永久设置,把export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:库路径,设置到∼/.bashrc或者 /etc/profile文件中, 然后source(.) ~/.bashrc

    /etc/profile 对所有用户生效,  ~/.bashrc 对当前用户有效
    3. 将其添加到 /etc/ld.so.cache文件中
       编辑/etc/ld.so.conf文件 : sudo vi ld.so.conf

   加入库文件所在目录的绝对路径 /home/guofu/code.....
       运行sudo ldconfig -v ,该命令会重建/etc/ld.so.cache文件

        其他方法:  dlopen/dlsys/dlclose

  • 动态库静态库总结:
    •  静态库: 在程序编译时会被连接到目标代码中,程序运行时将不再需要该静态库。

       动态库:在程序编译时并不会被连接到目标代码中,而是在程序运行是才被载入,因此在程序运行时还需要动态库存在。

       但是如果对库进行更改, 静态库则需要重新编译, 而动态库则不需要.

原文地址:https://www.cnblogs.com/guofuzhang/p/6102898.html