C 宏 - 动态#include
我试图弄清楚如何使用 GCC 为 #include 语句构建变量字符串。
我的想法是,对于我编写的每个源模块,我希望包含一个动态生成的 C 源代码作为标头,该源代码是在构建过程的早期创建的。
生成此文件不是问题。不幸的是,包括它。
到目前为止我所拥有的是(identities.h):
// identities.h
# define PASTER2(str) #str
# define PASTER(str) PASTER2(str ## .iden)
# define EVALUATOR(x) PASTER(x)
# define IDENTITIES_FILE EVALUATOR(__FILE__)
# include IDENTITIES_FILE
理想情况下,这将像这样使用(main.c):
//main.c
# include "identities.h"
int main() {return 0;}
在编译之前,它将由预处理器在一次传递中扩展以产生:
//main.c (preprocessed)
# include "main.c.iden"
int main() {return 0;}
我的两个间接级别使用(PASTER 和 EVALUATOR)是 这篇文章。
不幸的是,这不起作用,我留下了错误:
obj/win32/dbg/main.o
In file included from main.c:1:0:
identities.h:42:1: error: #include expects "FILENAME" or <FILENAME>
我认为问题是 include 语句缺少引号..有什么想法吗?
I'm trying to figure out how to build a variable string for the #include statement using GCC.
The idea is that for each source module I have written, I want to include as a header, a dynamically generated C source, that was created earlier in the build process.
Generating this file is not an issue. Including it, unfortunately, is.
What I have so far is (identities.h):
// identities.h
# define PASTER2(str) #str
# define PASTER(str) PASTER2(str ## .iden)
# define EVALUATOR(x) PASTER(x)
# define IDENTITIES_FILE EVALUATOR(__FILE__)
# include IDENTITIES_FILE
Ideally, this would be used like so (main.c):
//main.c
# include "identities.h"
int main() {return 0;}
Which would be expanded in a single pass by the preprocessor before compilation to yield:
//main.c (preprocessed)
# include "main.c.iden"
int main() {return 0;}
The two levels of indirection I'm using (PASTER and EVALUATOR) are a result of this post.
Unfortunately, this is not working and I am left with the error:
obj/win32/dbg/main.o
In file included from main.c:1:0:
identities.h:42:1: error: #include expects "FILENAME" or <FILENAME>
I think the problem is that the include statement is missing quotes.. Any ideas?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
这是在 Linux 源代码树中完成的;请参阅 旧版编译器-gcc.h 的第 125 行。
此标记将 __GNUC__ 的值粘贴到字符串中; "linux/compiler-gcc"
__GNUC__
".h" 然后将结果字符串化。这可能是一个gcc预处理器扩展。这是一个示例,
t1.h
t2.h
a.c
这是两个编译,
任一编译的输出都给出了预期结果。
与 Linux 源一样,您可以关闭 gcc 预定义值。 <代码>回声| g++ -dM -E - 将给出一个列表。
对于您的情况,您可以使用 makefile 将定义传递给编译,以允许动态包含生成的标头而不更改源代码。但是,一个简单的替代方案就是在模板源文件上运行 sed 等,并将其替换为已知的包含名称。
这两种技术都适合生成测试装置等。但是,对于编译器功能发现来说,这是更好的方法。对于使用 IDE 的程序员来说,这可能是他们唯一的选择。
This was done in the Linux source tree; See line 125 of and older compiler-gcc.h.
This token pastes the value of
__GNUC__
to a string; "linux/compiler-gcc"__GNUC__
".h" and then stringifies the result. This maybe a gcc pre-processor extension.Here is an example,
t1.h
t2.h
a.c
Here are two compiles,
The output of either compile gives expected result.
As with the Linux source, you can key off of gcc pre-defined values.
echo | g++ -dM -E -
will give a list.For your case, you can use the makefile to pass a define to the compile to allow dynamic inclusion of the generated header without altering the source. But then a simple alternative is just to run
sed
, etc on a template source file and replace it with the known include name.Either technique is good for generating test fixtures, etc. However, for compiler feature discovery, this is a better method. For programmers who use IDEs, this might be their only choice.
我相当确定你不能做你想做的事,
__FILE__
返回一个字符串,##
适用于令牌,并且没有CPP字符串连接预处理器宏。通常,由于两个连续的字符串(例如)将被 C++ 解析器视为单个字符串,因此可以解决此问题。但是,#include 是预处理器的一部分,因此无法利用这一事实。
旧答案:
你为什么要这样做
我确信这不是预处理器语法;您希望通过此实现什么目标?您是否尝试过:
“{”可以解释您收到的错误。
I am fairly certain you can't do what you want,
__FILE__
returns a string and##
works on tokens and there is no CPP string concat preprocessor macro. Normally this is gotten around due to the fact that two strings in succession e.g.will be treated as a single string by the C++ parser. However,
#include
is part of the preprocessor, and thus cannot take advantage of that fact.Old answer:
Why are you doing this
I'm certain that's not preprocessor syntax; what do you hope to achieve via that? Have you tried just:
A '{' could explain the error you are getting.
暂时跳过整个包含语法的事情,我不明白你的代码想要做什么。你说:
你给它
main.c
并期望"main.c.iden"
,但是返回{"main.c", main.c。伊登}
。相反,您在寻找这个吗?
Skipping the whole inclusion syntax thing for a while, I don't understand what your code is trying to do. You say:
You give it
main.c
and expect"main.c.iden"
, but that returns{"main.c", main.c.iden }
.Are instead you looking for this?
Boost 预处理器库中的 BOOST_PP_STRINGIZE 怎么样?它是专门为在名称周围添加引号而设计的。
What about BOOST_PP_STRINGIZE from the Boost Preprocessor library . It is specifically made to add quotes around a name.
您不能像这样使用预处理器。您必须向 #include 指令提供文件名,它不能是其他宏。
You cannot use preprocessor like this. You have to supply a filename to the #include directive, it can't be some other macro.