如何避免公共头中#define编译时间过长
How to avoid long compilation time for #define in common header
我想知道是否有一种优雅的方法可以解决这个问题。假设有一个共同的标题,例如
// common.h
#ifndef COMMON_H
#define COMMON_H
#define ENABLE_SOMETHING
//#define ENABLE_SOMETHING_ELSE
#define ENABLE_WHATEVER
// many others
#endif
现在这个文件包含在100个其他头文件中,各种#define
用于启用或禁用代码的某些部分,这些部分仅限于1-2个文件。
每次更改单个#define
时,整个项目似乎都会重新构建(我正在开发Xcode 5.1(,这是有意义的,因为它必须在代码的各个部分进行替换,而且编译器无法先验地知道它在哪里使用。
我正试图找到一种更好的方法来管理它,以避免长的编译时间,因为这些定义确实更改了很多次。将每个定义拆分到相应的文件中可能是一种解决方案,但我希望以实用的方式将所有内容打包在一起。
所以我想知道是否有一种模式通常用于解决这个问题,我正在考虑使用
// common.h
class Enables
{
static const bool feature;
};
// common..cpp
bool Enables::feature = false;
在编译优化的二进制文件时,这在语义上是否等效?(例如,false enables中的代码将完全消失(。
这里有两个不同的问题:
将每个定义拆分到相应的文件中可能是一种解决方案,但我希望以实用的方式将所有内容打包在一起。
这是你的第一个问题。如果我没有正确理解,如果你有多个功能区域,你就不想为每个功能区域都包含一个标题(但所有功能都只有一个标题(。
应用以下步骤:
-
do按功能将代码拆分为不同的标头;每个标头应包含(最多(单个
#define FEATURESET
启用的内容(并且完全不知道FEATURESET宏的存在(。 -
确保每个标头只编译一次(在每个特性标头文件的开头添加
#pragma once
( -
添加一个方便的头文件,根据您定义的功能执行
#if
或#ifdef
,并根据需要包括功能文件:// parsers.h // this shouldn't be here: #pragma once #ifdef PARSEQUUX_SAFE #include <QuuxSafe.h> #elif defined PARSEQUUX_FAST #include <QuuxFast.h> #else #include <QuuxSafe.h> #endif // eventually configure static/global class factory here // see explanation below for mentions of class factory
客户代码:
#include <parsers.h> // use default Quux parser
#define PARSEQUUX_SAFE
#include <parsers.h> // use safe (but slower) Quux parser
所以我想知道是否有一种模式通常用于解决这个问题
这是你的第二个问题。
在C++中,通过特性启用功能的规范方法是定义特性API,包括基类、类工厂和对通用接口的编程。
// common.h
#pragma once
#include <Quux.h> // base Quux class
struct QuuxFactory
{
enum QuuxType { Simple, Feathered };
static std::unique_ptr<Quux> CreateQuux(int arg);
static QuuxType type;
};
// common.cpp:
#include <common.h>
#include <SimpleQuux.h> // SimpleQuux: public Quux
#include <FeatheredQuux.h> // FeatheredQuux: public Quux
std::unique_ptr<Quux> QuuxFactory::CreateQuux(int arg)
{
switch(type) {
case Simple:
return std::unique_ptr<Quux>{new SimpleQuux{arg}};
case Feathered:
return std::unique_ptr<Quux>{new FeatheredQuux{arg}};
};
// TODO: handle errors
}
客户代码:
// configure behavior:
QuuxFactory::type = QuuxFactory::FeatheredQuux;
// ...
auto quux = QuuxFactory::CreateQuux(10); // creates a FeatheredQuux in this case
这具有以下优点:
它很简单,不使用宏
它是可重复使用的
它提供了足够的抽象层次
它不使用宏(如在"完全"(
假设的
Quux
功能的实际实现仅包含在一个文件中(作为实现细节,仅编译一次(。你可以在任何地方包含common.h,它根本不包括SimpleQoux.h和FeaturedQoux.h。
作为通用指南,您应该编写代码,这样就不需要运行宏。如果你这样做了,你会发现你想在上面添加的任何宏都是微不足道的。如果您从一开始就依赖宏来定义API,那么如果没有宏,代码将无法使用(或几乎无法使用(。
有一种方法可以拆分定义,但仍然使用一个中心配置头。
main_config.h
(它不能有包含保护或#pragma once
,因为如果在一个编译单元中多次包含main_config.h
,会导致奇怪的结果(:
#ifdef USES_SOMETHING
#include "something_config.h"
#endif
#ifdef USES_WHATEVER
#include "whatever_config.h"
#endif
something_config.h
(由于与main_config.h
相同的原因,不得包含防护装置(:
#define ENABLE_SOMETHING
所有的源文件和头文件都将只包含#include
和main_config.h
,但在包含之前,它们必须声明它们将引用其中的哪个部分:
some_source.cpp
:
#define USES_SOMETHING
#include "main_config.h"
some_other_file.h
:
#define USES_WHATEVER
#include "main_config.h"
- 使用简单类型列表实现的指数编译时间.为什么
- 在已经使用Git的情况下减少编译时间
- C++常量数组的编译时间较长
- 编译时间文本到数字转换 (atoi)
- 在C++中执行 N 阶乘编译时间的 3 种不同/相同方法
- DLLexport 类模板实例(专用化),减少了仅标头模板库的编译时间
- 替换枚举以最大化编译时间检查的最佳方法
- 不同C++功能的编译时间
- 在预编译标头中实例化模板会缩短编译时间吗?
- 使用 SCons 提取每个编译单元的编译时间
- 将 lambda 函数转换为另一个编译单元中的普通函数会缩短编译时间吗?
- std :: Invoke_result_t编译时间语法错误
- 模板;constexpr;编译时间
- 如何实现声明功能-C 11,编译时间
- 如何减少编译时间:在包含未触及的头文件的情况下
- C++编译时间类型确定
- 特征:返回对具有编译时间尺寸检查的矩阵块的引用
- 在编译时间定义多个派生类
- 在编译时间创建查找表
- C 函数在编译时间返回类型