我有一个库项目,我正在移植到使用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>
答案 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
警戒的情况下工作。
或者:如何在标题中使用配置结果?
如果您的标题需要根据#include
脚本的结果声明不同的内容,那么您有许多选项,其中没有一个是完美的。
对于内部标题,没有问题。他们只依赖于#include
d的宏而没有config.h
任何东西。如果 - 按照建议 - 所有源文件configure.ac
(可能间接如上所示)#define
之前任何其他标题,这都可行。
如果要公开安装标头,这不是一个很好的解决方案。对于那些使用Autoconf的用户来说,它并不会那么糟糕,尽管那些人必须记住要在#include
文件中放置哪些检查。对于不使用Autoconf的用户来说,这将非常糟糕。如果您只有几个开关(例如recommended),则可以在__linux
标题前询问用户_WIN32
,但如果您需要很多,则不是实物期权。更不用说你会以这种方式向用户公开大量的实现细节。
如果你需要做的就是根据你正在构建的平台进行分支,你可以探测一些预定义的宏,如config.h
或configure.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 && ./configure
,a 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
])