如何使用 C 预处理器找到库的完整路径?
Posted
技术标签:
【中文标题】如何使用 C 预处理器找到库的完整路径?【英文标题】:How to find the whole path to a library using the C preprocessor? 【发布时间】:2020-07-23 11:00:48 【问题描述】:我正在寻找一个简单的 bash 脚本,当给定系统标头的名称时,它将返回其完整路径,在 #include <header>
语句中将从该路径中读取它。我已经有了一个类似的东西来查找链接器使用的库存档。
ld -verbose -lz -L/some/other/dir | grep succeeded | sed -e 's/^\s*attempt to open //' -e 's/ succeeded\s*$//'
例如,这将返回 libz
存档的路径(/lib/x86_64-linux-gnu/libz.so
在我的系统上)。
对于请求的脚本,我知道我可以获取 gcc
使用的包含目录列表并自己搜索文件,但我正在寻找对预处理器内部发生的事情的更准确模拟(除非它是就这么简单)。
【问题讨论】:
I already have an analogous
唯一类似的是“发现”部分..
构建一个包含标头的存根程序并运行gcc -E
,或者只是echo '#include <stdio.h>' | gcc -E -
请注意,系统头文件(带有<...>
的头文件)不一定在磁盘上有物理文件。我相信gcc
实现只有系统头文件作为磁盘上的文件,但谁知道他们是否会在未来的版本中改变它?或者如果你切换编译器?也许您想要实现的目标可以在不知道系统标头的位置(或物理存在)的情况下完成?
【参考方案1】:
将输入传送到预处理器,然后处理输出。 Gcc 预处理器输出插入您可以解析的#
lines with information and flags。
$ f=stdlib.h
$ echo "#include <$f>" | gcc -xc -E - | sed '\~# [0-9]* "\([^"]*/'"$f"'\)" 1 .*~!d; s//\1/'
/usr/include/stdlib.h
它可以输出多个文件,因为gcc
具有#include_next
,并且在一些复杂的情况下可以不正确地检测到多个文件名包含同名的复杂情况,例如f=limits.h
。所以你也可以准确过滤第二行,知道第一行总是stdc-predef.h
:
$ f=limits.h; echo "#include <$f>" | gcc -xc -E - | sed '/# [0-9]* "\([^"]*\)" 1 .*/!d;s//\1/' | sed '2!d'
/usr/lib/gcc/x86_64-pc-linux-gnu/10.1.0/include-fixed/limits.h
但真正自己搜索包含路径,并不难:
$ f=limits.h; echo | gcc -E -Wp,-v - 2>&1 | sed '\~^ /~!d; s/ //' | while IFS= read -r path; do if [[ -e "$path/$f" ]]; then echo "$path/$f"; break; fi; done
/usr/lib/gcc/x86_64-pc-linux-gnu/10.1.0/include-fixed/limits.h
【讨论】:
【参考方案2】:您可以使用预处理器来完成这项工作:
user@host:~$ echo "#include <stdio.h>" > testx.c && gcc -M testx.c | grep 'stdio.h'
testx.o: testx.c /usr/include/stdc-predef.h /usr/include/stdio.h \
你可以加一点bash-fu来剪切你感兴趣的部分
【讨论】:
以上是关于如何使用 C 预处理器找到库的完整路径?的主要内容,如果未能解决你的问题,请参考以下文章