场景 一: 查找头文件路径.

代码 使用了 msgpack库,但makefile 没有指定 msgpack的头文件所在位置,也可以编译通过。


可以得出 一定是在系统的某个位置 安装了 msgpack,并且被找到。


但具体头文件在哪个位置呢?


从网上 搜到 看到 都是 gcc/g++ 头文件的 搜索路径,-I指定头文件的搜索路径。 知道了搜索路径,那我 需要 遍历 搜索路径上的每个目录 去查找, 这样比较费时, 但也是最容易想到的。


但可以通过 gcc 编译程序的 过程,让 gcc 自己列出所在位置.


gcc 由源码到可执行二进制程序包含了:预处理,编译,汇编,链接,四个阶段;其对应gcc -E -S -c ,链接阶段没有特殊参数表示。


先说下gcc -o,这里o代表 output,即指定输出文件。

1.预处理阶段:gcc -E test.c -o test.i,

-E参数指定处理到预处理阶段停止,并输出预处理结果,这里指定输出文件-o 是因为指定的话会直接输出到标准输出,

2.编译阶段:gcc -S test.i -o test.s

这个阶段会把test.s 编译成 汇编代码

3.汇编阶段:gcc -c test.s test.o

这个阶段,把汇编代码,汇编成 二进制代码

4.链接阶段:gcc test.o -o test

和其他库一起 链接生成 可执行文件 test



可以利用预处理阶段 找到 xx.h


  1. make, 让makefile 生成  gcc 指令,因为可能包含了其他的 库 头文件,

  2. gcc -E test.c |grep xx.h


场景二: 查找库的 搜索路径和 最终位置

  1 #include "expat.h"
  2 
  3 int main()
  4 {
  5 }

gcc -c my.c -o my.o

ld --verbose -o my my.o -lexpat --entry main

输出

attempt to open my.o succeeded
my.o
attempt to open /usr/x86_64-redhat-linux/lib64/libexpat.so failed
attempt to open /usr/x86_64-redhat-linux/lib64/libexpat.a failed
attempt to open /usr/local/lib64/libexpat.so failed
attempt to open /usr/local/lib64/libexpat.a failed
attempt to open /lib64/libexpat.so failed
attempt to open /lib64/libexpat.a failed
attempt to open /usr/lib64/libexpat.so failed
attempt to open /usr/lib64/libexpat.a failed
attempt to open /usr/x86_64-redhat-linux/lib/libexpat.so failed
attempt to open /usr/x86_64-redhat-linux/lib/libexpat.a failed
attempt to open /usr/lib64/libexpat.so failed
attempt to open /usr/lib64/libexpat.a failed
attempt to open /usr/local/lib/libexpat.so succeeded
-lexpat (/usr/local/lib/libexpat.so)
libc.so.6 needed by /usr/local/lib/libexpat.so
found libc.so.6 at /lib64/libc.so.6
ld-linux-x86-64.so.2 needed by /lib64/libc.so.6
found ld-linux-x86-64.so.2 at /lib64/ld-linux-x86-64.so.2

man ld

--verbose Display the version number for ld and list the linker emulations supported.  Display which input files can and cannot be opened.  Display the linker script being used by the linker.


如果有很多未定义的符号,为了不影响 查看库的搜索路径,

--unresolved-symbols=ignore-all

ignore-all Do not report any unresolved symbols.



可以用 链接阶段查看 库的 搜索路径

ld --verbose --unresolved-symbols=ignore-all  -o my my.o -lexpat --entry=main