我有一个非常大的代码库(即:数千个模块),其中的代码在众多项目之间共享,这些项目都运行在具有不同 C++ 编译器的不同操作系统上。 不用说,维护构建过程可能是一件很苦差事。
如果当前文件夹中不存在该文件,只要有一种方法可以让预处理器忽略某些#includes
,代码库中的多个位置就会大幅清理代码。 有谁知道如何实现这一目标?
目前,我们在共享文件中的 #include
周围使用 #ifdef
,并使用第二个特定于项目的文件 #defines 是否包含 #include< /code> 存在于项目中。 这可行,但很丑。 人们在从项目中添加或删除文件时经常忘记正确更新定义。 我曾考虑编写一个预构建工具来保持此文件最新,但如果有一种独立于平台的方法可以使用预处理器来执行此操作,我宁愿这样做。 有任何想法吗?
I have a very large codebase (read: thousands of modules) that has code shared across numerous projects that all run on different operating systems with different C++ compilers. Needless to say, maintaining the build process can be quite a chore.
There are several places in the codebase where it would clean up the code substantially if only there were a way to make the pre-processor ignore certain #includes
if the file didn't exist in the current folder. Does anyone know a way to achieve that?
Presently, we use an #ifdef
around the #include
in the shared file, with a second project-specific file that #defines whether or not the #include
exists in the project. This works, but it's ugly. People often forget to properly update the definitions when they add or remove files from the project. I've contemplated writing a pre-build tool to keep this file up to date, but if there's a platform-independent way to do this with the preprocessor I'd much rather do it that way instead. Any ideas?
发布评论
评论(9)
为丢失的标头创建一个特殊文件夹,并让该文件夹最后被搜索
(这是编译器特定的 - “INCLUDES”环境变量中的最后一项,类似的东西)
然后,如果某些 header1.h 可能丢失,请在该文件夹中创建一个存根
header1.h:
现在您可以随时写
Create a special folder for missing headers, and make that folder to be searched last
(that is compliler specific - last item in "INCLUDES" environment variable, something like that)
Then if some header1.h can be missing, create in that folder a stub
header1.h:
Now you can always write
通常,这是通过使用尝试运行预处理器以尝试包含文件的脚本来完成的。 根据预处理器是否返回错误,脚本会使用适当的#define(或#undef)更新生成的.h 文件。 在 bash 中,脚本可能看起来像这样:
一个非常全面的框架,用于可移植性检查(以及数千个其他),是 autoconf。
Generally this is done by using a script that tries running the preprocessor on an attempt at including the file. Depending on if the preprocessor returns an error, the script updates a generated .h file with an appropriate #define (or #undef). In bash, the script might look vaguely like this:
A pretty thorough framework for portably working with portability checks like this (as well as thousands others) is autoconf.
您可以运行一个预构建步骤,生成一个包含文件,其中包含表示当前目录中存在的文件名称的 #define 列表:
然后,从源代码中包含该文件,然后您的源代码就可以测试
EXISTS_*
定义以查看文件是否存在。You could have a pre-build step run that generates an include file that contains a list of #defines that represent the names of the files existing in the current directory:
Then, include that file from within your source code, and then your source can test the
EXISTS_*
defines to see whether a file exists or not.另一种可能性:在某个目录中填充您希望包含的所有标头的零长度版本。 将 -I 参数传递给此目录作为 last 此类选项。
GCC cpp 按顺序搜索其包含目录,如果它在较早的目录中找到头文件,它将使用它。 否则,它最终会找到零长度文件,并且会很高兴。
我认为其他 cpp 实现也会按指定的顺序搜索其包含目录。
Another possibility: populate a directory somewhere with zero-length versions of all of the headers you wish to optionally include. Pass a -I argument to this directory as the last such option.
The GCC cpp searches its include directories in order, if it finds a header file in an earlier directory it will use it. Otherwise, it will eventually find the zero-length file, and be happy.
I presume that other cpp implementations also search their include directories in the order specified.
预处理器本身无法识别文件的存在,但您当然可以使用构建环境来执行此操作。 我最熟悉 make,它允许您在 makefile 中执行类似的操作:
当然,您必须在 VisualStudio 等其他构建环境中找到与此类似的内容,但我确信它们存在。
The preprocessor itself cannot identify the existence of files but you certainly can use the build environment to do so. I'm mostly familiar with make, which would allow you to do something like this in your makefile:
Of course, you'd have to find an analog to this in other build environments like VisualStudio, but I'm sure they exist.
据我所知,cpp 没有关于文件存在的指令。
如果您跨平台使用相同的 make,则可以借助 Makefile 的一些帮助来完成此任务。 您可以检测 Makefile 中文件的存在:
正如 @Greg Hewgill 提到的,然后您可以使 #includes 成为有条件的:
So far as I know cpp does not have a directive regarding the existence of a file.
You might be able to accomplish this with a bit of help from the Makefile, if you're using the same make across platforms. You can detect the presence of a file in the Makefile:
As @Greg Hewgill mentions, you can then make your #includes be conditional:
与此处和互联网上的一些说法相反,Visual Studio 2015 不支持
__has_include
功能 - 至少根据我的经验。 使用 Update 3 进行测试。谣言可能源于 VS 2017 也被称为“版本 15”; VS 2015 被称为“版本 14”。 对该功能的支持似乎已在“Visual Studio 2017 Version 15.3”中正式引入。
Contrary to some claims here and on the internet, Visual Studio 2015 does NOT support the
__has_include
feature - at least according to my experience. Tested with Update 3.The rumors may have arisen from the fact that VS 2017 is also referred to as "Version 15"; VS 2015 is instead referred to as "Version 14". Support for the feature seems to have been officially introduced with "Visual Studio 2017 Version 15.3".
我必须为 Symbian 操作系统做类似的事情。 我就是这样做的:
假设您想要检查文件“file_strange.h”是否存在,并且想要根据该文件的存在包含一些标头或链接到一些库。
首先创建一个小批处理文件进行检查该文件的存在。
autoconf 很好,但对于许多小项目来说却是过头了。
----------check.bat
----------check.bat 结束
然后我创建了一个 gnumake 文件
---------- checkmedialist.mk
----------check.mk 结束
将 check.mk 文件包含在您的 bld.inf 文件中,它必须位于 MMP 文件之前
现在正在编译文件
file_strange_supported.h
将设置适当的标志。您可以在 cpp 文件甚至 mmp 文件中使用此标志
例如在mmp
和.cpp中
I had to do something similar for the Symbian OS. This is how i did it:
lets say you want to check if the file "file_strange.h" exists and you want to include some headers or link to some libraries depending on the existance of that file.
first creat a small batch file for checking the existence of that file.
autoconf is good but an over kill for many small projects.
----------check.bat
----------check.bat ends
then i created a gnumake file
----------checkmedialist.mk
----------check.mk ends
include the check.mk file in your bld.inf file, it MUST be before your MMP files
now at compile time the file
file_strange_supported.h
will have an appropriate flag set.you can use this flag in your cpp files or even in the mmp file
for example in mmp
and in .cpp
一些更新
一些编译器可能支持
__has_include ( header-name )
。该扩展已添加到 C++17 标准 (P0061R1)。
来自 VS2015 Update 2 的 5.X Visual Studio 的编译器支持
示例(来自 clang 网站):
来源
Little Update
Some compilers might support
__has_include ( header-name )
.The extension was added to the C++17 standard (P0061R1).
Compiler Support
Example (from clang website):
Sources