确保一次包含config.h [英] ensure config.h is included once

查看:220
本文介绍了确保一次包含config.h的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个图书馆项目,正在努力移植以使用Linux中的autotools套件.我对自动工具很陌生(本周).我已经了解了其操作的基础知识.我对如何防止重新定义 config.h 的内容有疑问.

I have a library project that I'm working on porting to using the autotools suite in Linux. I'm quite new to autotools (this week). I've learned the basics of its operation. I have a question about how to keep the contents of config.h from being redefined.

我很惊讶地发现生成的 config.h 文件也没有,1)将每个宏包装在 #ifndef 中,或者2)整个文件都没有包装在标准的 #ifndef CONFIG_H 中.

I'm surprised to find that the generated config.h file doesn't either, 1) wrap each macro in a #ifndef or, 2) that the entire file isn't wrapped in the standard #ifndef CONFIG_H.

正如我所提到的,这段代码是在Windows和Linux上构建的.因此,可以使用宏 _linux (我并不是说这是最好的名称,但是它在任何地方都在使用)来将元素引入仅存在于Linux中的类中.因此,这会发生

As I've alluded, this code is built on Windows and Linux. Thus there are several uses of a macro, _linux (I'm not saying that's the best name, but it's in use everywhere) to bring in elements to classes which exist in Linux only. Thus, this will happen

header.h

#ifndef HEADER1_H
#define HEADER1_H

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#endif

source.cxx

source.cxx

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "header.h"  // oops, preprocessor gets excited because of redefs

一个简单的解决方案是在文件生成后,在 config.h.in 中执行标准的唯一包装.但是,我想知道,是否有更好的方法来处理此问题?我不能成为第一个遇到这种情况的人,甚至可能在 configure.ac 中有一种处理它的方法,但是作为一个完整的新手,我什至不知道要寻找什么.

One simple solution is I do that standard unique wrap in config.h.in after the file is generated. However, I was wondering, is there a better way of handling this? I can't be the first to encounter this and there might even be a means of handling it in configure.ac but being a complete neophyte in this, I don't know what to even search for.

推荐答案

我这样做的方法的确是创建一个包装文件(通常称为 global.h ),其内容如下./p>

The way I do this is indeed creating a wrapper file (which I usually call global.h) that reads like this.

#ifndef MY_PROJECT_GLOBAL_H
#define MY_PROJECT_GLOBAL_H

#include <config.h>

/* Maybe other global definitions… */

#endif

请注意,推荐方式 #include config.h 文件是通过< config.h> 而不是"config.h" 使用 VPATH 构建更好.

Note that the recommended way to #include the config.h file is via <config.h> not "config.h" so it works better with VPATH builds.

然后,我项目中的所有 source 文件 #include 这个 global.h 头文件都是它们的第一个 #include ,而不关心 config.h . header 文件绝对不能 #include config.h ,因为这会导致名称冲突.实际上,如果您遵循此准则,那么您的代码也应该在配置标头中没有 #include 防护的情况下工作.

Then, all the source files in my project #include this global.h header as their very first #include and don't care about config.h. A header file should never #include config.h since this would lead to bad name conflicts. Actually, if you stick to this guideline, your code should also work without #include guards in the configuration header.

或者:如何在标头中使用配置结果?

如果您的标头需要根据 configure 脚本的结果声明不同的内容,则您有很多选择,没有一个是完美的.

If your headers need to declare different things depending on the results of the configure script, you have a number of options, none of which is perfect.

对于内部标题,没有问题.他们只是依靠宏定义 #define 而无需 #include 进行任何操作.如果(建议)所有源文件 #include (可能间接显示在上面) config.h 在其他任何标头之前,则此方法有效.

For internal headers, there is no problem. They simply rely on the macros being #defined without #includeing anything. This works if – as is recommended – all source files #include (maybe indirectly as shown above) config.h before any other header.

如果头文件要公开安装,这不是一个很好的解决方案.对于那些使用Autoconf的用户来说,还算不错,尽管即使是那些用户也必须记住要在其 configure.ac 文件中进行哪些检查.对于不使用Autoconf的用户,这将是非常糟糕的.如果您只有几个开关(例如

If the headers are to be installed publicly, this is not such a great solution. For those of your users that use Autoconf, it wouldn't be that bad, although even those would have to remember what checks to place in their configure.ac files. For users who don't use Autoconf, it will be pretty bad. If you only have a few switches (such as Glibc's fature test macros), it is okay to ask your users to #define them before #includeing your headers but if you need many, this is not a real option. Not to mention that you'll expose a lot of implementation details to your users that way.

如果您要做的只是根据要构建的平台进行分支,则可以探究一些预定义的宏,例如 __ linux _WIN32 .有一个 Boost.Predef 库旨在通过提供更高级别的抽象来使这些检查更加方便.该库可与C和C ++一起使用,但是,当然,它为您的项目增加了一个额外的依赖关系.

If all you need to do is branch depending on the platform you are building for, you could probe some of the pre-defined macros like __linux or _WIN32. There is the Boost.Predef library that aims to make these check a little more convenient by providing a higher-level abstraction. The library works with C and C++ alike but, of course, it adds an additional dependency to your project.

最后,您可以使用特定于项目的宏前缀制作 config.h 的版本.Autoconf宏档案中有一个贡献可以为您完成此工作.一个最小的例子可能是这样的.

Finally, you could make a version of your config.h that uses a macro prefix specific to your project. There is a contribution in the Autoconf macro archive that does exactly that for you. A minimal example could look like this.


AC_PREREQ([2.69])
AC_INIT([example-project], [1.0], [bugs@example.org])
AC_CONFIG_SRCDIR([example.c])
AC_CONFIG_MACRO_DIR([m4])
AC_CONFIG_HEADERS([config.h])
AX_PREFIX_CONFIG_H([public_config.h], [EXAMPLE_PROJECT], [config.h])
AC_PROG_CC
AC_OUTPUT

将其另存为 configure.ac

Save this as configure.ac, download ax_prefix_config_h.m4 from the Autoconf macro archive and place it in the sub-directory m4 and then run autoreconf && ./configure. It will create the normal config.h and in addition public_config.h where in the latter file, all macros are prefixed with EXAMPLE_PROJECT_. The file public_config.h (which also has #include guards by the way) can be installed and #included in your project's public header files if need be.

这篇关于确保一次包含config.h的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆