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

发布于 2024-12-02 12:07:54 字数 1150 浏览 1 评论 0原文

根据 这个答案 boost 和 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 文件中,我应该没问题,并且用户不会收到任何错误。或者,如果一个翻译单元中多次包含相同的标头(有标头防护),我是否会失去速度优势?

感谢您的任何提示!

According to this answer boost and STL headers belong into the precompiled header file (stdafx.h in the MSVC world). So I changed the headers of my dynamic link library project and moved all STL/Boost headers into the stdafx.h of my project.

Before

#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;
  }
}

After

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

Now I have the advantage of decreased compile times, but all the users of my library are getting build errors (e.g. unknown boost::scoped_ptr...) because of the missing includes (which are now moved to my stdafx.h).


What could be a solution for this dilemma?

I want reduced compile times and compile errors after including my headers files are not acceptable for any users of the dll.

Could this help?

  • leave all includes directives as they are but duplicate them in my 'stdafx.h'? Since the stdafx.h is always included first inside any cpp file of my project I should be fine, and the users won't get any errors. Or do I loose the speed advantage if multiple includes of the same header occur in one translation unit (got header guards)?

Thanks for any hints!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

雨夜星沙 2024-12-09 12:07:54

当您将 header-includes 保留在库标头中并将它们另外放入 stdafx.h 中时,您应该会获得几乎相同的速度提升。

或者,您可以添加一个额外的定义(批量外部包含防护

// 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

但我仅当您确信有帮助时才会这样做。只需拿一个秒表并运行一些重新编译即可。 (无需链接。)然后您就会看到是否有任何差异。

除此之外,

我不确定在项目中的某个地方添加所需的所有 boost头是否是一个好主意。我想说 shared_ptr 和朋友,boost/foreach,也许 Boost.Format,...是个好主意,但我已经为 Boost 三思而行了。正则表达式标头。 注意:我没有进行任何速度测量,但我依稀记得 pch 文件的大小和一些编译器故障有关的问题。我真的应该做一些测试

还要检查相关的 Boost 库是否提供转发标头以及您是否应该包含它们。使预编译头文件膨胀也有其缺点。

You should get nearly the same speed increase when you leave the header-includes in place in the library headers and just additionally put them into stdafx.h.

Alternatively, you could add an additional define (a bulk 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

But I would only do that if you are sure it helps. Just take a stopwatch and run a few re-compilations. (No need to link.) Then you'll see if there's any difference.

Aside

I'm not sure if adding all boost headers that are needed somewhere in the project is such a good idea. I'd say shared_ptrand friends, boost/foreach, maybe Boost.Format, ... are a good idea, but I'd already think twice for the Boost.RegExp headers. Note: I did not do any speed measurements, but I dimly remember a problem with the size of the pch file and some compiler hiccup. I really should do some tests.

Also check if the Boost Library in question provides forwarding headers and whether you should include them instead. Bloating the precompiled header file can have it's downsides.

一紙繁鸢 2024-12-09 12:07:54

您可以为此目的创建一个构建配置(调试、发布、检查依赖项)。更改此设置的一个简单方法是使用预处理器根据当前配置包含/排除包含内容。使用它,您可以使用调试或发布(包含更大的包含集)来测试和构建,然后在分发之前构建所有配置。

澄清一下,条件包含 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 附加到预处理器定义列表中在 CheckDependency 配置中。

关于守卫:如果您在正常情况下使用守卫,那么应该不是问题 - 编译器使用优化来检测这些情况,这意味着如果文件被多重包含和保护,它们在许多情况下可以避免打开文件正确。事实上,在这个领域尝试智胜编译器实际上可能会减慢处理速度。我想说,除非你的库/依赖项很大并且你确实有明显的问题,否则就将其保留为典型的。

you could create a build configuration for this purpose (Debug, Release, CheckDependencies). a simple way to change this would be to use the preprocessor to include/exclude the includes based on the current configuration. using this, you can test and build using debug or release (which contains the larger set of includes), then build all configurations before distribution.

to clarify, the conditional include MON_LIBRARY_VALIDATE_DEPENDENCIES is not to be used in the library headers or sources, only in the precompiled header:

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

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

then you would append MON_LIBRARY_VALIDATE_DEPENDENCIES to the list of preprocessor definitions in the CheckDependencies configuration.

regarding guards: it should not be a problem if you are using guards under normal circumstances - compilers use optimizations to detect these cases which means they can avoid opening the file in many cases if it's been multiply included and guarded correctly. in fact, attempts to outsmart the compiler in this arena can actually slow down to process. i'd say just leave it as typical unless your library/dependencies are huge and you really have noticeable problems.

千仐 2024-12-09 12:07:54

使您的编译单元独立(让它们包含它们使用的所有内容)是非常可取的。这将防止其他不使用预编译标头的编译错误,并且正如您所假设的,标头防护将使这些额外包含的成本保持最低。

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

Making your compilation units selfcontained (let them include everything they use) is very desirable. This will prevent compilation errors from others that do not use precompiled headers, and as you assume, header guards will keep the cost of these extra includes minimal.

This will also have the desirable side effect that a glance at the headers will tell the users which other headers are in use in the unit, and the options of doing a compilation of the single unit without any fuzz.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文