确保config.h包含一次

时间:2015-02-20 20:22:36

标签: linux header-files autotools

我有一个库项目,我正在移植到使用Linux中的autotools套件。我对autotools很新(本周)。我已经学会了它的操作基础知识。我有一个关于如何保持config.h的内容不被重新定义的问题。

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

正如我所提到的,这段代码是基于Windows和Linux构建的。因此,有一些宏的使用,_linux(我不是说它是最好的名字,但它在所有地方都在使用)将元素引入到存在的类中。仅限Linux。因此,这将发生

header.h

#ifndef HEADER1_H
#define HEADER1_H

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

#endif

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中处理它,但作为一个完整的新手,我不知道甚至可以搜索什么。< / p>

2 个答案:

答案 0 :(得分:5)

我这样做的方式确实是创建一个包装文件(我通常称之为global.h),其内容如下所示。

#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而不是#include,因此在global.h版本中效果更好。

然后,我的项目#include中的所有文件config.h标题为第一个#include而不关心config.h }。 标头文件永远不应#include configure,因为这会导致错误的名称冲突。实际上,如果您遵守本指南,您的代码也应该在配置标题中没有#define警戒的情况下工作。


关于OP评论的更新

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

如果您的标题需要根据#include脚本的结果声明不同的内容,那么您有许多选项,其中没有一个是完美的。

对于内部标题,没有问题。他们只依赖于#include d的宏而没有config.h任何东西。如果 - 按照建议 - 所有源文件configure.ac(可能间接如上所示)#define 之前任何其他标题,这都可行。

如果要公开安装标头,这不是一个很好的解决方案。对于那些使用Autoconf的用户来说,它并不会那么糟糕,尽管那些人必须记住要在#include文件中放置哪些检查。对于不使用Autoconf的用户来说,这将非常糟糕。如果您只有几个开关(例如recommended),则可以在__linux标题前询问用户_WIN32,但如果您需要很多,则不是实物期权。更不用说你会以这种方式向用户公开大量的实现细节。

如果你需要做的就是根据你正在构建的平台进行分支,你可以探测一些预定义的宏,如config.hconfigure.ac。有Glibc's fature test macros库旨在通过提供更高级别的抽象来使这些检查更方便。该库可以与C和C ++一起使用,但当然,它会为您的项目添加额外的依赖项。

最后,您可以制作使用特定于项目的宏前缀的m4版本。 Autoconf宏归档中有Boost.Predef,它完全适合您。最小的例子看起来像这样。

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

将其保存为autoreconf && ./configurea contribution并将其放在子目录config.h中,然后运行public_config.h。它将创建正常的EXAMPLE_PROJECT_以及public_config.h,在后一个文件中,所有宏都以#include为前缀。如果需要,可以在项目的公共头文件中安装文件#include(顺便说一下也有{{1}}防护)并且{{1}} d。

答案 1 :(得分:0)

使用自动标题,您可以将标题和预告片样板代码添加到 config.h

https://www.gnu.org/software/autoconf/manual/autoconf-2.60/html_node/Autoheader-Macros.html

例如,将以下内容添加到您的 configure.ac

#
# Add include guards to config.h
#
AH_TOP([
#ifndef __CONFIG_H_INCLUDE_GUARD
#define __CONFIG_H_INCLUDE_GUARD
])

AH_BOTTOM([
#endif
])