通过 CMake 使用预编译标头
我在网上看到了一些关于在 CMake 中对预编译头文件进行一些支持的(旧)帖子。 他们似乎都有点无所不在,每个人都有自己的做法。 目前最好的做法是什么?
I have seen a few (old) posts on the 'net about hacking together some support for pre-compiled headers in CMake. They all seem a bit all-over the place and everyone has their own way of doing it. What is the best way of doing it currently?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(12)
改编自 Dave,但更高效(设置目标属性,而不是针对每个文件):
Adapted from Dave, but more efficient (sets target properties, not for each file):
如果你不想重新发明轮子,只需使用 Cotire 作为最佳答案建议的或更简单的 - cmake-precompiled-header 此处。 要使用它,只需包含该模块并调用:
if you don't wanna reinvent the wheel, just use either Cotire as the top answer suggests or a simpler one - cmake-precompiled-header here. To use it just include the module and call:
使用 cmake 和 Visual Studio 2015 预编译头的示例
“stdafx.h”、“stdafx.cpp”-预编译头名称。
将以下内容放入根 cmake 文件中。
将以下内容放入项目 cmake 文件中。
“src” - 包含源文件的文件夹。
An example of usage precompiled header with cmake and Visual Studio 2015
"stdafx.h", "stdafx.cpp" - precompiled header name.
Put the following below in the root cmake file.
Put the following below in the project cmake file.
"src" - a folder with source files.
恕我直言,最好的方法是为整个项目设置 PCH,正如 martjno 建议的那样,并结合在需要时忽略某些源(例如生成源)的 PCH 的能力:
因此,如果您有一些目标 MY_TARGET 和生成源列表 IGNORE_PCH_SRC_LIST 您'只需这样做:
这种方法经过测试并且效果很好。
IMHO the best way is to set PCH for whole project, as martjno suggested, combined with ability of ignoring PCH for some sources if needed (e.g. generated sources):
So, if you have some target MY_TARGET, and list of generated sources IGNORE_PCH_SRC_LIST you'll simply do:
This aproach is tested and works perfectly.
好吧,当您每次在任何项目文件中更改一行时,在四核机器上构建都会花费 10 分钟以上,它会告诉您是时候为 Windows 添加预编译头了。 在 *nux 上我只会使用 ccache 而不用担心这个。
我已经在我的主应用程序及其使用的一些库中实现了。 到目前为止它的效果很好。 还需要的一件事是您必须创建 pch 源文件和头文件,并在源文件中包含您想要预编译的所有头文件。 我用 MFC 做了这件事 12 年,但我花了几分钟才回想起这一点。
Well when builds take 10+ minutes on a quad core machine every time you change a single line in any of the project files it tells you its time to add precompiled headers for windows. On *nux I would just use ccache and not worry about that.
I have implemented in my main application and a few of the libraries that it uses. It works great to this point. One thing that also is needed is you have to create the pch source and header file and in the source file include all the headers that you want to be precompiled. I did this for 12 years with MFC but it took me a few minutes to recall that..
最干净的方法是将预编译选项添加为全局选项。 在 vcxproj 文件中,这将显示为
Use
并且不会对每个单独的文件执行此操作。然后您需要将
Create
选项添加到StdAfx.cpp中。 以下是我如何使用它:这已经过测试,适用于 MSVC 2010,并将创建一个 MyDll.pch 文件,我不关心使用什么文件名,所以我没有做出任何努力来指定它。
The cleanest way is to add the precompiled option as a global option. In the vcxproj file this will show up as
<PrecompiledHeader>Use</PrecompiledHeader>
and not do this for every individual file.Then you need to add the
Create
option to the StdAfx.cpp. The following is how I use it:This is tested and works for MSVC 2010 and will create a MyDll.pch file, I am not bothered what file name is used so I didn't make any effort to specify it.
由于预编译头选项不适用于 rc 文件,因此我需要调整 jari 提供的宏。
编辑:使用此预编译头将我的主项目的总体构建时间从 4 分钟 30 秒减少到 1 分钟 40 秒。 这对我来说真是一件好事。 预编译头中只有boost/stl/Windows/mfc之类的头。
As the precompiled header option doesnt work for rc files, i needed to adjust the macro supplied by jari.
Edit: The usage of this precompiled headers reduced the Overall build time of my main Project from 4min 30s down to 1min 40s. This is for me a really good thing. In the precompile header are only headers like boost/stl/Windows/mfc.
甚至不要去那里。 预编译标头意味着每当其中一个标头发生更改时,您都必须重建所有内容。 如果您有一个能够实现这一点的构建系统,那么您很幸运。 通常情况下,您的构建会失败,直到您意识到您更改了正在预编译的某些内容,因此您需要进行完全重建。 您可以通过预编译您绝对不会改变的标头来避免这种情况,但这样您也会放弃很大一部分速度增益。
另一个问题是,您的命名空间会被各种您不知道或不关心的符号污染,而这些符号在您使用预编译标头的许多地方都是不知道或不关心的。
Don't even go there. Precompiled headers mean that whenever one of the headers changes, you have to rebuild everything. You're lucky if you have a build system that realizes this. More often than never, your build will just fail until you realize that you changed something that is being precompiled, and therefore you need to do a full rebuild. You can avoid this mostly by precompiling the headers that you are absolutely positive won't change, but then you're giving up a large part of the speed gain as well.
The other problem is that your namespace gets polluted with all kinds of symbols that you don't know or care about in many places where you'd be using the precompiled headers.
CMake 刚刚获得了对 PCH(预编译标头)的支持,可从 3.16 获取(2019 年 10 月发布) 开始:
https://gitlab.kitware.com/ cmake/cmake/merge_requests/3553
通过
REUSE_FROM
关键字支持在目标之间共享 PCH 比如这里。在 https://blog.qt.io/blog/2019/08/01/precompiled-headers-and-unity-jumbo-builds-in-upcoming-cmake/
CMake has just gained support for PCHs (pre-compiled headers), it is available from 3.16 (released October 2019) onwards:
https://gitlab.kitware.com/cmake/cmake/merge_requests/3553
Sharing PCHs between targets is supported via the
REUSE_FROM
keyword such as here.There is some additional context (motivation, numbers) available at https://blog.qt.io/blog/2019/08/01/precompiled-headers-and-unity-jumbo-builds-in-upcoming-cmake/
我使用以下宏来生成和使用预编译头:
假设您有一个包含所有源文件的变量 ${MySources} ,您想要使用的代码将是简单的
代码在非 MSVC 平台上仍然可以正常运行也。 很简约 :)
Im using the following macro to generate and use precompiled headers:
Lets say you have a variable ${MySources} with all your sourcefiles, the code you would want to use would be simply be
The code would still function just fine on non-MSVC platforms too. Pretty neat :)
这是一个代码片段,允许您在项目中使用预编译头。
将以下内容添加到 CMakeLists.txt 中,根据需要替换
myprecompiledheaders
和myproject_SOURCE_FILES
:Here is a code snippet to allow you to use precompiled header for your project.
Add the following to your CMakeLists.txt replacing
myprecompiledheaders
andmyproject_SOURCE_FILES
as appropriate:我最终使用了 larsm 宏的改编版本。 使用 $(IntDir) 作为 pch 路径可以使调试和发布版本的预编译头保持分离。
I ended up using an adapted version of larsm macro. Using $(IntDir) for pch path keeps precompiled headers for debug and release builds separate.