【问题标题】:Instruct compiler to ignore header prefix found in a #include指示编译器忽略在#include 中找到的标头前缀
【发布时间】:2015-06-25 19:48:44
【问题描述】:

[正如 Cornstalks 在下面解释的那样,我正在尝试去除 #include 中使用的标头前缀。所以看来这个问题不是How to make g++ search for header files in a specific directory?的重复问题]

我正在对库进行一些更改。我在本地有这个库,所以它没有安装在它惯用的系统位置。

我有一个测试源文件,它与库并排。测试文件有很多包括:

#include <foo/libfoo.h>

而且它还有一堆习惯性的包含,比如:

#include <iostream>

我正在尝试使用以下方法编译测试文件:

$ g++ ecies-test.c++ -I. -o ecies-test.exe ./libcryptopp.a

并且(-iquote . 之间的空格似乎没有区别):

$ g++ ecies-test.c++ -I. -iquote . -o ecies-test.exe ./libcryptopp.a

我遇到的问题是我不知道如何告诉 g++ &lt;foo/libfoo.h&gt; 意味着 "./libfoo.h"。实际上,我正在尝试去除用于包含标题的前缀。我查看了2.3 Search Path 下的手册,但它并没有真正讨论这种情况。

我有大约 60 个额外的测试文件用于库。并且每个都有 10 或 20 个这样的包含。所以我无法在 500 或 600 个位置将 #include &lt;foo/libfoo.h&gt; 更改为 #include "./libfoo.h"

我通过创建虚构的目录结构尝试了@rici 的工作,但它破坏了 GDB 调试。 GDB 找不到类成员的符号,所以我无法设置断点来调试我试图修改的代码。

我如何告诉编译器在 PWD 中查找系统包含?


下面是一个典型的错误。 ECIES_FIPS 在我本地的图书馆副本中。

$ g++ -DNDEBUG=1 -g3 -Os -Wall -Wextra -I. -iquote . ecies-test.c++ -o ecies-test.exe ./libcryptopp.a
ecies-test.c++:29:17: error: no member named 'ECIES_FIPS' in namespace
      'CryptoPP'
using CryptoPP::ECIES_FIPS;
      ~~~~~~~~~~^
ecies-test.c++:44:5: error: use of undeclared identifier 'ECIES_FIPS'
    ECIES_FIPS<ECP>::Decryptor decryptor(prng, ASN1::secp256r1());
    ^
ecies-test.c++:44:16: error: 'ECP' does not refer to a value
    ECIES_FIPS<ECP>::Decryptor decryptor(prng, ASN1::secp256r1());
               ^
/usr/local/include/cryptopp/ecp.h:30:20: note: declared here
class CRYPTOPP_DLL ECP : public AbstractGroup<ECPPoint>
    ...

如果重要的话:

$ g++ --version
Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/usr/include/c++/4.2.1
Apple LLVM version 5.1 (clang-503.0.40) (based on LLVM 3.4svn)
Target: x86_64-apple-darwin12.6.0
Thread model: posix

【问题讨论】:

  • 当前目录(.)是否命名为foo?如果是这样,您可以将其更改为-I..。或者,您可以将foo 符号链接到.。我不知道如何告诉编译器将路径foo/* 映射到./*,但这些可能是可行的解决方法。
  • “I”选项应该可以满足您的需求。这是以前的 SO 问题,可能会有所帮助:stackoverflow.com/questions/12654013/…
  • 谢谢@Cubia - 我不知道为什么搜索没有发现这个问题。我投了第一次接近重复的投票。
  • @Cornstalks - 我愿意,但我有一个名为 foo 的真正库。
  • @jww 是否可以只添加一个名为“foo”的文件夹并将“libfoo.h”文件放入其中?虽然标题前缀仍然存在,但您不必更改任何代码。

标签: c++ g++ include-path


【解决方案1】:

使用-I 选项将当前文件夹添加为包含目录,您可以在当前目录中创建一个名为“foo”的文件夹并将libfoo.h 文件放入其中。

显然,这不会去掉 #include 中的“foo”前缀,但这是一种解决方法。

【讨论】:

  • 谢谢@Cubia。一些背景故事是我需要用测试文件生成一个svn diff 的更改。本质上,我将对测试文件执行svn add。更改目录结构会使事情变得复杂。
【解决方案2】:

没有选项告诉 gcc 忽略包含路径中的目录前缀。如果您的程序包含#include &lt;foo/header.h&gt;,则包含列表中必须有一些path_prefix,以便path_prefix/foo/header.h 解析为所需的文件。

虽然您不能将 gcc 配置为忽略 foo,但您当然可以随意修改文件系统。您所需要的只是某个目录foo 映射到存储头文件的目录。然后你可以将该目录的父目录添加到搜索路径中。

例如:

mkdir /tmp/fake
ln -s /path/to/directory/containing/header /tmp/fake/foo
gcc -I /tmp/fake ...             # Ta-daa!

【讨论】:

  • 谢谢@rici。我试过这个,它破坏了 GDB 调试。 GDB 找不到符号来在我要修改的类成员上设置断点。稍后,我需要在执行svn add 后生成统一的差异。这真的很不方便:(
  • @jww:最简单的方法无疑是复制你的目录结构。尽管如此,我不明白为什么 gdb 无法找到符号,只要符号链接仍然存在。 (使用 /tmp 可能不是保证:) 的最佳方式)你确定类成员存在于编译代码中吗?
【解决方案3】:

我有大约 60 个额外的测试文件用于库。并且每个都有 10 或 20 个这样的包含。所以我无法在 500 或 600 个地方将 #include 更改为 #include "./libfoo.h"。

如果上述标准只是为了方便起见,那么可以使用像sed 这样的工具来完成所有工作。类似的东西

$ sed -i 's/\(^\s*#include\s*[<"]\)foo\/\([^>"]*[>"]\s*$\)/\1\2\t\/\/ This line was replaced/' *

会将所有出现的#include &lt;foo/file.h&gt; 替换为#include &lt;file.h&gt;(您可能需要稍微调整一下,我目前在Windows 机器上,无法对其进行测试)。如果所有文件都在 PWD 中,这将起作用。如果有更复杂的文件结构,那么可以结合grepxargs使用。

注意:确保使用时忽略 svn 目录。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-09-23
    • 2019-05-22
    • 1970-01-01
    • 2019-10-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-30
    相关资源
    最近更新 更多