最近新参加的一项目是C++项目,新项目使用的原来老项目的代码来作开发,两个项目不管是Windows还是Linux都是没使用预编译技术,导致编译时间很长。

我发现我参加工作以来经历过几个别人已经写成型的C++项目,包括Windows的、Linux的以及跨Windows与Linux的,这些项目无一例外的都没有使用预编译技术来加快编译,导致整个项目的编译时间很长,有十几二十分钟的,更有三四十分钟,甚至更长时间的。对于这样长的编译时间,我无一例外的都是无法忍受,这很影响开发效率和我的心情,也不知道之前参与这些项目的开发人员是如何能忍受这样的编译时长的。既然自己参与到项目中了,无法忍受那就努力改变它,使用预编译技术来加快项目的编译速度,缩短编译时间。

这几个C++项目经过我对项目配置的一番修改,都有效地加快了编译速度,大幅地减少了编译时间,极大地提高了开发效率。原来需要三四十分钟的优化后变为4,5分钟;十几二十分钟的优化后变为1,2分钟,提升之明显,所以在此再写一博文来详细介绍一下相关设置,希望能帮助大家节省开发时间,提高开发效率。

这里之所以说是再谈,是因为前面有写过或者转过关于预编译技术的博文: 在VisualGDB中配置预编译头加快编译速度 使用 GNU CC 的预编译头文件加快编译速度 C/C++通用Makefile

Visual C++中使用预编译技术

其实在Windows平台,Visual C++中使用预编译技术是非常方便的,也很简单;相对而言,Linux下GCC使用预编译技术则要复杂许多。

我们平常在新建一个项目时,Visual C++会默认使用预编译技术来帮助我们加快编译速度。

下图是我们使用Visual C++新建的一个控制台项目时的向导,我们可以看到默认是勾选了“预编译头”的。

在新生成的项目中有如下文件

我们可以看到有一个stdafx.h和stdafx.cpp,这两个文件就是预编译技术需要使用的相关文件。只要我们把系统头文件以及项目引用比较多的头文件放进stdafx.h中,就可以加快编译了。 Visual C++是如何设置的呢?可以打开项目属性页面,看如下图所示配置

可以看到整个项目都使用了预编译头。要使用预编译头,就需要先创建预编译头,可以查看stdafx.cpp文件的属性

我们可以看到,这里预编译头不是“使用”,而是“创建”。整个项目在编译时,是最先编译stdafx.cpp来预编译stdafx.h文件中所包含的头文件,会生成一个预文件文件,比如VS2015生成的是一个ipch文件,生成后该文件后,在编译项目中的其它文件时,则会优先使用该文件中的解析结果。

上面这种设置适合新项目,需要在项目所有源文件(非头文件)中第一个包含预编译头文件(stdafx.h)。当然,stdafx.h和stdafx.cpp这两个文件名都可以任意取,关键是需要在项目中设置为使用预编译头,并拿一个源文件来创建预编译头即可

如果遇到老项目,项目中已经有成百上千个文件了,这些源文件不一定是第一个包含预编译头文件的,也许根本就没有统一包含某一个头文件。此时我们只需要设置为让项目所有源文件都强制包含预编译头文件即可:

这样设置后,老项目也可以尽情享受预编译技术带来的加速了。

Linux下GCC使用预编译技术

在Linux下常常使用Makefile来编译项目,可以直接写Makefile,也可以使用其它工具来生成Makefile,比如cmake,qmake等等。

Makefile

如果是手动编写Makefile,如何添加预编译头,可以参考: 使用 GNU CC 的预编译头文件加快编译速度 C/C++通用Makefile

老项目添加预编译 如果是老项目,我们只需要在 使用 GNU CC 的预编译头文件加快编译速度一文所言的CFLAGS和CXXFLAGS宏后添加 -include Prec.h 强制包含预编译头文件即可(Prec.h为预编译头文件)。

VisualGDB

参见: 在VisualGDB中配置预编译头加快编译速度

CMake

cmake作为一个开源的跨平台构建工具,由于其功能强大且简单易用,越来越受到大家的青睐,目前很多开源项目都使用cmake来构建。

使用cotire

cmake在3.16之前并不直接支持预编译,但是有一个开源项目 cotire对cmake提供了预编译支持。

1.首先把 cotire.cmake放在项目的根目录(顶层目录) 2.然后在项目根目录的CMakeLists.txt中添加如下配置:

set (CMAKE_MODULE_PATH “.”) include(cotire)

3.在设置链接的CMakeLists.txt中添加:

set_target_properties(MyTarget PROPERTIES COTIRE_CXX_PREFIX_HEADER_INIT “Prec.h”) cotire(MyTarget)

其中,MyTarget是项目链接的目标文件,Prec.h是预编译头文件。

使用target_precompile_headers

在CMake 3.16之后添加了对预编译的直接支持:

target_precompile_headers( <INTERFACE|PUBLIC|PRIVATE> [header1…] [<INTERFACE|PUBLIC|PRIVATE> [header2…] …])

参见: target_precompile_headers

但是对生成的Visual Studio项目无效,貌似只对Makeilfe类的有效,其它的没测试过。 注意:这个命令必须在指定了目标之后使用,即需要在add_executable() 或者add_library()后

The command adds header files to the PRECOMPILE_HEADERS and/or > INTERFACE_PRECOMPILE_HEADERS target properties of . The named must have been created by a command such as add_executable() or add_library() and must not be an ALIAS target.

示例:

1cmake_minimum_required(VERSION 3.16.0)
2project(main VERSION 0.1.0)
3
4add_executable(main main.cpp)
5
6target_precompile_headers(main PRIVATE prec.h)

祝玩得开心!