库构建器的预编译头文件用法

时间:2011-09-02 07:49:26

标签: c++ visual-c++ precompiled-headers

根据this answer提升和STL标头属于预编译头文件(MSVC世界中的stdafx.h)。所以我更改了动态链接库项目的标题,并将所有STL / Boost标题移动到我项目的stdafx.h中。

之前

#include <boost/smart_ptr.hpp>

namespace XXX
{
  class CLASS_DECL_BK CExampleClass // CLASS_DECL_BK is just a standard dll import/export macro
  {
    private:
      boost::scoped_ptr<Replica> m_replica;
  }
}

namespace XXX
{
  class CLASS_DECL_BK CExampleClass
  {
    private:
      boost::scoped_ptr<Replica> m_replica;
  }
}

现在我的优势是减少了编译时间,但是我的库的所有用户都遇到了构建错误(例如未知的boost :: scoped_ptr ...)因为缺少包含(这是现在转到我的stdafx.h)。


什么可以解决这个困境?

我希望减少编译时间编译错误后,包含我的头文件对于dll的任何用户都是不可接受的。

这有用吗?

  • 保留所有包含指令,但在我的'stdafx.h'中复制它们?由于stdafx.h总是首先包含在我项目的任何cpp文件中,我应该没问题,用户也不会收到任何错误。或者,如果在一个翻译单元中出现多个包含相同标题的页面(获得标题保护),我是否会失去速度优势?

感谢任何提示!

3 个答案:

答案 0 :(得分:2)

您可以为此目的创建构建配置(Debug,Release,CheckDependencies)。更改此方法的一种简单方法是使用预处理器根据当前配置包含/排除包含。使用它,您可以使用调试或发布(包含更大的包含集)进行测试和构建,然后在分发之前构建所有配置。

澄清一下,条件包括MON_LIBRARY_VALIDATE_DEPENDENCIES不会在库头文件或源代码中使用,只能在预编译头文件中使用:

// my pch:
#include <file1.hpp>
#include <file2.hpp>
// ...

#if !defined(MON_LIBRARY_VALIDATE_DEPENDENCIES)
#include <boost/stuff.hpp>
// ...
#endif

然后您将MON_LIBRARY_VALIDATE_DEPENDENCIES附加到CheckDependencies配置中的预处理程序定义列表中。

关于警卫:如果你在正常情况下使用警卫, 应该不成问题 - 编译器使用优化来检测这些情况,这意味着如果它已经繁殖,他们可以避免在很多情况下打开文件正确包括和保护。实际上,在这个领域中试图超越编译器的尝试实际上可以减慢 down 来处理。我会说只是把它当作典型的,除非你的库/依赖关系很大并且你确实有明显的问题。

答案 1 :(得分:2)

当你将标题包括在库标题中并且只是将它们放入stdafx.h时,你应该几乎相同的速度增加。

或者,您可以添加其他定义(批量external include guard

// stdafx.h
#define MY_LIB_STD_HEADERS_ALREADY_INCLUDED

// library_file.h
#ifndef MY_LIB_STD_HEADERS_ALREADY_INCLUDED
#include <boost/smart_ptr.hpp>
...
#endif

但是如果你确定它有帮助,我只会这样做。只需要一个秒表并进行一些重新编辑。 (无需链接。)然后你会看到是否有任何不同。

除了

我不确定在项目中添加所有升级标头某处是一个好主意。我会说shared_ptr和朋友,boost/foreach,也许是Boost.Format,...是个好主意,但我已经三思而后行了Boost.RegExp标题。 注意:我did not do any speed measurements,但我模糊地记得pch文件的大小和一些编译器打嗝的问题。我真的should do some tests

同时检查相关的Boost Library是否提供转发标头以及是否应该包含它们。膨胀预编译的头文件可能会有它的缺点。

答案 2 :(得分:1)

让你的编译单元自包含(让它们包括他们使用的所有东西)是非常可取的。这将防止其他不使用预编译头文件的编译错误,并且正如您所假设的那样,标头保护将使这些额外包含的成本保持最小。

这也有一个理想的副作用,一看标题就会告诉用户单位中正在使用哪些其他标题,以及在没有任何模糊的情况下编译单个单位的选项。