如何解决依赖包含顺序问题?

How to solve dependencies inclusion order issues?

我正在尝试重新编译一个有两个依赖项的项目:Qt 和 X11。

X11 在全局命名空间中定义以下符号:

// Xlib.h
#define Bool int
#define Status int
#define True 1
#define False 0

// X.h
#define None 0L

但是,这些符号(可能更多)也用于 Qt(例如枚举)。正如我们在 qcoreevent.h 中看到的那样:

enum Type {
    /*
      If you get a strange compiler error on the line with None,
      it's probably because you're also including X11 headers,
      which #define the symbol None. Put the X11 includes after
      the Qt includes to solve this problem.
    */
    None = 0,    
 ...   

Qt提供的解决方案很简单:最后包含X11。但我遇到以下情况时遇到了麻烦:

File1.hpp

#include <SomeQtHeader.h>
#include <SomeX11Header.h> // Ok, X11 is included after Qt
... some classes ...

File2.hpp

#include <SomeOtherQtHeader.h>
#include <SomeX11Header.h> // Ok, X11 is included after Qt
... some classes ...

但是,有些文件是这样的:

File3.hpp

#include "File1.hpp"
#include "File2.hpp"

所以在预处理过程中的某个时刻,我假设它被转换成

// #include "File1.hpp" ->
#include <SomeQtHeader.h>
#include <SomeX11Header.h> // X11 ends up included before Qt

// #include "File2.hpp" ->
#include <SomeOtherQtHeader.h>
#include <SomeX11Header.h> 

我想过使用前向声明,但一些结构和 类 没有用作指针,其中很多甚至是类型定义的,所以我最终前向声明了用户使用的原始内部结构不应该使用,总的来说是一团糟。

我应该如何有效地处理这个问题,而不滥用前向声明和指针的使用?

你必须处理邪恶的宏,你可以将 X11 库包装成类似

的东西
// X11wrapper.h
#ifndef X11Wrapper_H
#define X11Wrapper_H

#include <X11/Xlib.h>
#undef None
constexpr auto None = 0L;

#endif

并使用该包装器 header 而不是官方包装器。

按照@Jarod42 的回答,这是我的完整包装器,其中包含我必须取消定义并正确重新定义的所有定义,按照它们在编译器错误日志中出现的顺序排列:

#ifndef WRAPPER_HPP
#define WRAPPER_HPP

#include <X11/Xlib.h>

#undef None
constexpr auto None = 0L;

#undef KeyPress
constexpr auto KeyPress = 2;

#undef KeyRelease
constexpr auto KeyRelease = 2;

#undef FocusIn
constexpr auto FocusIn = 9;

#undef FocusOut
constexpr auto FocusOut = 10;

#undef FontChange
constexpr auto FontChange = 255;

#undef Expose
constexpr auto Expose = 12;

#undef False
constexpr auto False = 0;

#undef True
constexpr auto True = 1;

#undef Status
typedef int Status;

#undef Unsorted
constexpr auto Unsorted = 0;

#undef Bool
typedef int Bool;

#endif // WRAPPER_HPP