如何在include中使用预处理器宏?

时间:2021-12-28 16:53:45

I am trying to build freetype2 using my own build system (I do not want to use Jam, and I am prepared to put the time into figuring it out). I found something odd in the headers. Freetype defines macros like this:

我正在尝试使用自己的构建系统构建freetype2(我不想使用Jam,我准备花时间去搞清楚)。我在标题中发现了一些奇怪的东西。 Freetype定义了这样的宏:

#define FT_CID_H  <freetype/ftcid.h>

and then uses them later like this:

然后像这样使用它们:

#include FT_CID_H 

I didn't think that this was possible, and indeed Clang 3.9.1 complains:

我不认为这是可能的,确实Clang 3.9.1抱怨:

error: expected "FILENAME" or <FILENAME>
#include FT_CID_H
  • What is the rationale behind these macros?
  • 这些宏背后的基本原理是什么?

  • Is this valid C/C++?
  • 这是有效的C / C ++吗?

  • How can I convince Clang to parse these headers?
  • 我如何说服Clang解析这些标题?


This is related to How to use a macro in an #include directive? but different because the question here is about compiling freetype, not writing new code.

这与如何在#include指令中使用宏有关?但不同,因为这里的问题是关于编译freetype,而不是编写新代码。

2 个解决方案

#1


6  

Is this valid C/C++?

这是有效的C / C ++吗?

The usage is valid C, provided that the macro definition is in scope at the point where the #include directive appears. Specifically, paragraph 6.10.2/4 of C11 says

如果宏定义在#include指令出现的范围内,则用法是有效的C.具体而言,C11第6.10.2 / 4段说

A preprocessing directive of the form

表单的预处理指令

# include pp-tokens new-line

(that does not match one of the two previous forms) is permitted. The preprocessing tokens after include in the directive are processed just as in normal text. (Each identifier currently defined as a macro name is replaced by its replacement list of preprocessing tokens.) The directive resulting after all replacements shall match one of the two previous forms.

(允许与前两种形式中的一种不匹配)。指令中包含的预处理标记的处理方式与普通文本一样。 (当前定义为宏名称的每个标识符将替换为其预处理标记的替换列表。)所有替换后生成的指令应与前两个表单中的一个匹配。

(Emphasis added.) Inasmuch as the preprocessor has the same semantics in C++ as in C, to the best of my knowledge, the usage is also valid in C++.

(强调补充。)因为预处理器在C ++中具有与在C中相同的语义,据我所知,该用法在C ++中也是有效的。

What is the rationale behind these macros?

这些宏背后的基本原理是什么?

I presume it is intended to provide for indirection of the header name or location (by providing alternative definitions of the macro).

我认为它旨在提供标题名称或位置的间接(通过提供宏的替代定义)。

How can I convince Clang to parse these headers?

我如何说服Clang解析这些标题?

Provided, again, that the macro definition is in scope at the point where the #include directive appears, you shouldn't have to do anything. If indeed it is, then Clang is buggy in this regard. In that case, after filing a bug report (if this issue is not already known), you probably need to expand the troublesome macro references manually.

再次提供宏定义在#include指令出现的范围内,你不应该做任何事情。如果确实如此,那么Clang就是这方面的错误。在这种情况下,在提交错误报告后(如果尚未知道此问题),您可能需要手动扩展麻烦的宏引用。

But before you do that, be sure that the macro definitions really are in scope. In particular, they may be guarded by conditional compilation directives -- in that case, the best course of action would probably be to provide whatever macro definition is needed (via the compiler command line) to satisfy the condition. If you are expected to do this manually, then surely the build documentation discusses it. Read the build instructions.

但在此之前,请确保宏定义确实在范围内。特别是,它们可能受条件编译指令的保护 - 在这种情况下,最好的行动方案可能是提供所需的宏定义(通过编译器命令行)以满足条件。如果您希望手动执行此操作,那么构建文档肯定会对其进行讨论。阅读构建说明。

#2


11  

I will address your three questions out of order.

我将不按顺序解决你的三个问题。

Question 2

Is this valid C/C++?

这是有效的C / C ++吗?

Yes, this is indeed valid. Macro expansion can be used to produce the final version of a #include directive. Quoting C++14 (N4140) [cpp.include] 16.2/4:

是的,这确实有效。宏扩展可用于生成#include指令的最终版本。引用C ++ 14(N4140)[cpp.include] 16.2 / 4:

A preprocessing directive of the form

表单的预处理指令

# include pp-tokens new-line

(that does not match one of the two previous forms) is permitted. The preprocessing tokens after include in the directive are processed just as in normal text (i.e., each identifier currently defined as a macro name is replaced by its replacement list of preprocessing tokens). If the directive resulting after all replacements does not match one of the two previous forms, the behavior is undefined.

(允许与前两种形式中的一种不匹配)。在指令中包括之后的预处理令牌被处理,就像在普通文本中一样(即,当前定义为宏名称的每个标识符被其预处理令牌的替换列表替换)。如果在所有替换之后生成的指令与前两个表单中的一个不匹配,则行为未定义。

The "previous forms" mentioned are #include "..." and #include <...>. So yes, it is legal to use a macro which expands to the header/file to include.

提到的“以前的表格”是#include“......”和#include <...>。所以是的,使用扩展到包含的头/文件的宏是合法的。

Question 1

What is the rationale behind these macros?

这些宏背后的基本原理是什么?

I have no idea, as I've never used the freetype2 library. That would be a question best answered by its support channels or community.

我不知道,因为我从未使用过freetype2库。这将是其支持渠道或社区最佳回答的问题。

Question 3

How can I convince Clang to parse these headers?

我如何说服Clang解析这些标题?

Since this is legal C++, you shouldn't have to do anything. Indeed, user @Fanael has demonstrated that Clang is capable of parsing such code. There must be some problem other problem in your setup or something else you haven't shown.

由于这是合法的C ++,你不应该做任何事情。实际上,用户@Fanael已经证明Clang能够解析这样的代码。您的设置中必须存在其他问题或其他未显示的问题。

#1


6  

Is this valid C/C++?

这是有效的C / C ++吗?

The usage is valid C, provided that the macro definition is in scope at the point where the #include directive appears. Specifically, paragraph 6.10.2/4 of C11 says

如果宏定义在#include指令出现的范围内,则用法是有效的C.具体而言,C11第6.10.2 / 4段说

A preprocessing directive of the form

表单的预处理指令

# include pp-tokens new-line

(that does not match one of the two previous forms) is permitted. The preprocessing tokens after include in the directive are processed just as in normal text. (Each identifier currently defined as a macro name is replaced by its replacement list of preprocessing tokens.) The directive resulting after all replacements shall match one of the two previous forms.

(允许与前两种形式中的一种不匹配)。指令中包含的预处理标记的处理方式与普通文本一样。 (当前定义为宏名称的每个标识符将替换为其预处理标记的替换列表。)所有替换后生成的指令应与前两个表单中的一个匹配。

(Emphasis added.) Inasmuch as the preprocessor has the same semantics in C++ as in C, to the best of my knowledge, the usage is also valid in C++.

(强调补充。)因为预处理器在C ++中具有与在C中相同的语义,据我所知,该用法在C ++中也是有效的。

What is the rationale behind these macros?

这些宏背后的基本原理是什么?

I presume it is intended to provide for indirection of the header name or location (by providing alternative definitions of the macro).

我认为它旨在提供标题名称或位置的间接(通过提供宏的替代定义)。

How can I convince Clang to parse these headers?

我如何说服Clang解析这些标题?

Provided, again, that the macro definition is in scope at the point where the #include directive appears, you shouldn't have to do anything. If indeed it is, then Clang is buggy in this regard. In that case, after filing a bug report (if this issue is not already known), you probably need to expand the troublesome macro references manually.

再次提供宏定义在#include指令出现的范围内,你不应该做任何事情。如果确实如此,那么Clang就是这方面的错误。在这种情况下,在提交错误报告后(如果尚未知道此问题),您可能需要手动扩展麻烦的宏引用。

But before you do that, be sure that the macro definitions really are in scope. In particular, they may be guarded by conditional compilation directives -- in that case, the best course of action would probably be to provide whatever macro definition is needed (via the compiler command line) to satisfy the condition. If you are expected to do this manually, then surely the build documentation discusses it. Read the build instructions.

但在此之前,请确保宏定义确实在范围内。特别是,它们可能受条件编译指令的保护 - 在这种情况下,最好的行动方案可能是提供所需的宏定义(通过编译器命令行)以满足条件。如果您希望手动执行此操作,那么构建文档肯定会对其进行讨论。阅读构建说明。

#2


11  

I will address your three questions out of order.

我将不按顺序解决你的三个问题。

Question 2

Is this valid C/C++?

这是有效的C / C ++吗?

Yes, this is indeed valid. Macro expansion can be used to produce the final version of a #include directive. Quoting C++14 (N4140) [cpp.include] 16.2/4:

是的,这确实有效。宏扩展可用于生成#include指令的最终版本。引用C ++ 14(N4140)[cpp.include] 16.2 / 4:

A preprocessing directive of the form

表单的预处理指令

# include pp-tokens new-line

(that does not match one of the two previous forms) is permitted. The preprocessing tokens after include in the directive are processed just as in normal text (i.e., each identifier currently defined as a macro name is replaced by its replacement list of preprocessing tokens). If the directive resulting after all replacements does not match one of the two previous forms, the behavior is undefined.

(允许与前两种形式中的一种不匹配)。在指令中包括之后的预处理令牌被处理,就像在普通文本中一样(即,当前定义为宏名称的每个标识符被其预处理令牌的替换列表替换)。如果在所有替换之后生成的指令与前两个表单中的一个不匹配,则行为未定义。

The "previous forms" mentioned are #include "..." and #include <...>. So yes, it is legal to use a macro which expands to the header/file to include.

提到的“以前的表格”是#include“......”和#include <...>。所以是的,使用扩展到包含的头/文件的宏是合法的。

Question 1

What is the rationale behind these macros?

这些宏背后的基本原理是什么?

I have no idea, as I've never used the freetype2 library. That would be a question best answered by its support channels or community.

我不知道,因为我从未使用过freetype2库。这将是其支持渠道或社区最佳回答的问题。

Question 3

How can I convince Clang to parse these headers?

我如何说服Clang解析这些标题?

Since this is legal C++, you shouldn't have to do anything. Indeed, user @Fanael has demonstrated that Clang is capable of parsing such code. There must be some problem other problem in your setup or something else you haven't shown.

由于这是合法的C ++,你不应该做任何事情。实际上,用户@Fanael已经证明Clang能够解析这样的代码。您的设置中必须存在其他问题或其他未显示的问题。