确保 config.h 包含一次

2024-05-12

我有一个库项目,正在使用 Linux 中的 autotools 套件移植到该项目。我对自动工具很陌生(本周)。我已经了解了其操作的基础知识。我有一个关于如何保留内容的问题config.h免遭重新定义。

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

正如我所提到的,这段代码是在 Windows 和 Linux 上构建的。因此宏有多种用途,_linux(我并不是说这是最好的名称,但它在任何地方都在使用)将元素引入仅存在于 Linux 中的类。于是,就会出现这样的情况

header.h

#ifndef HEADER1_H
#define HEADER1_H

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

#endif

源文件.cxx

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

一个简单的解决方案是我将标准的独特包装放入config.h.in文件生成后。但是,我想知道是否有更好的方法来处理这个问题?我不是第一个遇到这种情况的人,甚至可能有一种处理方法configure.ac但作为一个完全的新手,我不知道该寻找什么。


我这样做的方式确实是创建一个包装文件(我通常称之为global.h)读起来像这样。

#ifndef MY_PROJECT_GLOBAL_H
#define MY_PROJECT_GLOBAL_H

#include <config.h>

/* Maybe other global definitions… */

#endif

请注意,受到推崇的 https://www.gnu.org/software/autoconf/manual/autoconf.html#Configuration-Headers way to #include the config.h文件是通过<config.h> not "config.h"所以它可以更好地与VPATH builds.

那么,所有的source我的项目中的文件#include this global.h标题作为他们的第一个#include并且不关心config.h. A header文件不应该#include config.h因为这会导致不良名称冲突。实际上,如果您坚持这个准则,您的代码也应该可以在没有#include配置头中的保护。


关于OP评论的更新

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

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

对于内部标头,没有问题。他们只是依赖于宏#defined 没有#include任何东西。如果(按照建议)所有源文件都有效,则此方法有效#include(也许是间接的,如上所示)config.h before任何其他标头。

如果要公开安装标头,这不是一个很好的解决方案。对于那些使用 Autoconf 的用户来说,情况不会那么糟糕,尽管即使是那些人也必须记住要在他们的文件中放置哪些检查。configure.ac文件。对于不使用Autoconf的用户来说,情况会很糟糕。如果您只有几个开关(例如Glibc的fature测试宏 https://www.gnu.org/software/libc/manual/html_node/Feature-Test-Macros.html#Feature-Test-Macros),可以要求您的用户#define他们之前#includeing 你的标题,但如果你需要很多,这不是一个真正的选择。更不用说您将以这种方式向用户公开大量实现细节。

如果您需要做的只是根据您正在构建的平台进行分支,您可以探测一些预定义的宏,例如__linux or _WIN32。有的是升压预定义 http://www.boost.org/doc/libs/1_57_0/libs/predef/doc/html/index.html旨在通过提供更高级别的抽象来使这些检查更加方便的库。该库与 C 和 C++ 类似,但当然,它为您的项目添加了额外的依赖项。

最后,你可以制作一个版本config.h使用特定于您的项目的宏前缀。有贡献 https://www.gnu.org/software/autoconf-archive/ax_prefix_config_h.html在 Autoconf 宏存档中,它正是为您做的。一个最小的例子可能是这样的。



AC_PREREQ([2.69])
AC_INIT([example-project], [1.0], [[email protected] /cdn-cgi/l/email-protection])
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, 下载ax_prefix_config_h.m4来自 Autoconf 宏存档 http://git.savannah.gnu.org/gitweb/?p=autoconf-archive.git;a=blob_plain;f=m4/ax_prefix_config_h.m4并将其放在子目录中m4然后运行autoreconf && ./configure。它将创建正常的config.h另外public_config.h在后一个文件中,所有宏都带有前缀EXAMPLE_PROJECT_。文件public_config.h(其中还有#include顺便说一下,防护装置)可以安装并且#include如果需要的话,可以在项目的公共头文件中添加 d 。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

确保 config.h 包含一次 的相关文章

随机推荐

  • WCF:在 ServiceModel 客户端配置部分中找不到引用协定“IService”的默认端点元素。当托管在 IIS 中时

    我有一个 WCF 服务托管在 IIS 中 我还有一个 WCF 客户端 控制台应用程序 我用过svcutil构建代理类和配置文件 然后将它们添加到我的客户端项目中 它建造得很好 但是当我尝试运行该程序时 它抛出以下异常 在 ServiceMo
  • 动态 GraphQL 模式?

    我有一个突变 将提交表单数据 该数据可能会根据您填写的表单而有所不同 表单将会很多 并且它们将共享相同的 步骤 每个表单由 1 个或多个页面 步骤组成 因此 我们可能有这些可重用的步骤 最喜欢的水果 出生日期 名和姓 还有这两种形式 通用信
  • 如何在 Swift 中编写 Cordova 插件?

    我将现有的自定义插件转换为 Swift 语言 位于Plugins CustomPluginInSwift swift import Foundation class CustomPluginInSwift CDVPlugin func ge
  • 正在搜索 Mercurial 存储库 (TortoiseHG)?

    有什么方法可以输入特定的文件名 例如 xyz txt 并使用 TortoiseHG 在 Mercurial 存储库中搜索该文件的任何签入 如果没有 为什么不呢 这不就是版本控制的用途吗 在 Hg Repository Explorer 窗口
  • SpringMVC form:options items 属性:它到底期望什么?

    我对 SpringMVC 以及 jstl 来说 还是个新手 我正在尝试填充从对象列表中选择的选项 我找到了一种使用 c forEach 来做到这一点的方法 但我一直认为必须有一种方法可以使 form options 方法起作用 我浏览了一下
  • 是否可以在 VC++/CLI 中重写 IEnumerable?

    我有一个返回一个的接口IEnumerable 我想在 VC CLI 中实现这个 因为数据来自第三方非托管 DLL 到目前为止我有 public ref class MyEnumerable IEnumerable
  • netbeans - 调试器退出,代码为 0xc0000135

    我需要在 netbeans 中安装调试器 我已经在 mingw bin 目录中安装了 gdbmingw get exe install gdb 我已经添加了该行C MinGW bin gdb exe 但是 当我运行调试器时 它会给出以下消息
  • 在 UILongPressGestureRecognizer 上,如何检测哪个对象生成了事件?

    我有几个 UIButton 的视图 我已成功使用 UILongPressGestureRecognizer 实现 并使用以下内容作为选择器 void longPress UILongPressGestureRecognizer gestur
  • cmake:设置多个项目以及它们之间的依赖关系

    我需要帮助为 C 项目编写一个好的 CMakeLists txt 我寻找答案 但我发现了什么 这是我的项目结构 MainProj ProjLib include proj lib h src proj lib cc CMakeLists t
  • LazyColumn - Items 关键参数的用途?

    有人可以解释一下它的主要目的是什么吗 key LazyListScope 的 items itemsIndexed 函数内的参数 如果我们指定该参数 我们会得到什么或不会得到什么 我不确定我是否理解与此参数相关的官方文档 key 代表该项目
  • C++中的虚继承是什么

    假设我有这样的代码 class A class B virtual public A class C virtual public A class D public B public C virtual public A If D继承B a
  • 导入 python 模块的特殊性?

    我一直在使用 python 的 PySerial 库pyserial API http pyserial sourceforge net pyserial api html 我似乎无法理解为什么我必须专门导入模块的某个部分 这会给我一个错误
  • 为 Eclipse 安装 Mercurial 插件时出错

    我刚刚为 Eclipse 安装了一个 Mercurial 插件 安装过程很顺利 但是安装后 当我重新启动 eclipse 时 显示错误 错误说 发生了多个 Mercurial 错误 请检查错误日志视图以获取详细信息 命令行 hg y deb
  • Twilio webRTC 通话在 10 分钟后中断

    使用 Twilio js 使用 webRTC 录制通话 工作正常 但在 10 分钟时 完全正确 电话挂断 TwiML 上的最大记录时间设置为 7200 秒 浏览器的控制台显示 Twilio PeerConnection signalingS
  • 让按钮更容易点击

    我有一个按钮 在某些手机上由于尺寸太大而很难点击 但让它变大会破坏布局 可以向视图解释它有一个比其可见区域更大的 点击框 吗 不确定这是否有帮助 如果您使用没有背景的 ImageButton 并设置 Padding 值 您的按钮将具有更大的
  • 如何在 Bootstrap 4 中隐藏和替换 navbar-toggler-icon?

    如何隐藏和替换 Bootstrap 4 中的导航栏切换图标 现在 下面的代码只是将 X 放在汉堡菜单下方
  • 是否可以共享 Symfony2 安装(一台服务器上的多个网站 [域])

    我想在一个根 服务器 下托管多个基于 Symfony2 的网站 是否可以共享 symfony 自己的文件 供应商等 有人知道教程吗 管理起来困难吗 AFAIK Symfony 安装大约有 600MB 我不想以冗余方式保存它 我看起来确实有可
  • ModuleNotFoundError:没有名为“pdfminer.high_level”的模块

    我在 pycharm 中从事项目 我想使用 pdfminer 将 pdf 文件转换为文本文件 我的问题是 当我运行该应用程序时 它无法工作 并且显示此错误消息 ModuleNotFoundError 没有名为 pdfminer high l
  • JS - 不可破坏空间的转换   [关闭]

    很难说出这里问的是什么 这个问题是含糊的 模糊的 不完整的 过于宽泛的或修辞性的 无法以目前的形式得到合理的回答 如需帮助澄清此问题以便重新打开 访问帮助中心 help reopen questions 我正在从 HTML 元素中读出文本并
  • 确保 config.h 包含一次

    我有一个库项目 正在使用 Linux 中的 autotools 套件移植到该项目 我对自动工具很陌生 本周 我已经了解了其操作的基础知识 我有一个关于如何保留内容的问题config h免遭重新定义 我惊讶地发现生成的config h文件也没