对于我的小型(5-6000行代码)C ++程序,我使用了VS 2015和2017,我的构建时间大约是2分钟。这显然非常缓慢,但我不确定为什么。在工具 - >选项 - >项目和解决方案 - >构建和运行 - 我已经设置了"最大数量的并行项目构建"到8但没有发生变化。
是否有任何其他设置或一般规则可用于缩短构建时间?
答案 0 :(得分:6)
编译需要时间......这是一个复杂的过程,尤其是在包含许多文件和项目的大型解决方案中。 但是有一些东西可以减少Visual Studio的编译时间。
具有足够空闲空间,良好的多核处理器和足够RAM的SSD始终是快速编译的良好基础。
预编译头文件可以大大加快构建过程。如果在项目创建期间没有自动创建它们,则设置起来有点复杂,但在许多情况下它绝对值得付出努力。 以下是如何开启它们的方法:
pch.h包含您希望在项目中常用的所有定义和标题,例如
#ifdef _WIN32
# define _WIN32_WINNT 0x0502
# define WIN32_LEAN_AND_MEAN
# define VC_EXTRALEAN
# define NOMINMAX
#endif
#include <windows.h>
#define OIS_DYNAMIC_LIB
#include "OgreVector3.h"
#include <string>
#include <vector>
etc. pp.
pch.cpp只包含一行:
#include "pch.h"
它有一个特殊用途(见下文)。
现在为项目中的每个cpp添加一个#include "pch.h"
,位于cpp文件的VERY TOP位置。这对于预编译的头文件是必需的。
接下来是在项目中启用预编译的头文件。 打开您的项目属性,然后输入所有配置和所有平台,他们应该&#34;使用&#34;预编译的头文件:
这告诉项目您要将pch.h用作预编译头文件。
最后一步是将pch.cpp的文件属性更改为&#34; create&#34; (这是特殊目的):
这意味着pch.cpp将从现在开始创建Visual Studio所需的二进制预编译头文件。
通常,将所有内容放在一个大项目中并从每个文件调用每个文件都不是一个好主意,既不是编译时也不是设计。 您应该将解决方案拆分为某个&#34;级别的静态库。
最低级别可能是是一个基本的网络库,IO库,包装器,标准改进,便利助手等。
中等水平可以是例如一个专门的线程库(它使用较低级别,如网络,IO等)
最高级别是您的申请。
较高级别可以访问较低级别(最好是直接在下面的级别),但较低级别永远不能访问较高级别(如果需要,除了通过接口)。 这可以确保 - 在您处理应用程序时 - 只需要重建应用程序,而不是整个项目。
当然,您需要仅限标题的课程,例如STL。而且模板只能在header-only-classes中使用。 但是如果你要编写一个非模板类,它应该经典地分成cpp和header来改善编译时间。此外,只应在标题中实现简短的方法(例如,普通的getter和setter)。
我们假设您在较低级别的标题中有一个类:
#include "my_template_lib_which_takes_ages_to_compile.h"
namespace LowLevel {
class MySuperHelper {
my_template<int> m_bla;
public:
MySuperHelper();
virtual ~MySuperHelper();
void doSomething();
};
}
并且您希望将此类的引用或(智能)指针存储在更高级别的类标题中:
#include "lowlevel.h"
namespace MediumLevel {
class MyMediumClass {
std::unique_ptr<LowLevel::MySuperHelper> m_helperRef;
public:
MyMediumClass(); //constructor initializes the smart pointer in cpp
virtual ~MyMediumClass();
void work(); // works with the smart pointer in cpp
};
}
当然这是有效的代码,但编译可能会很慢。 MySuperHelper使用慢速编译模板lib来实例化其成员,从而包含其标题。如果现在包含lowlevel.h,则还将包含慢速模板库。如果更高的类包含您的中类标题,它将包括中级标题,低级标题和模板标题......等等。
你可以通过前向声明来避免这种情况。
namespace LowLevel {
class MySuperHelper;
}
namespace MyMediumLevel {
class MyMediumClass {
std::unique_ptr<LowLevel::MySuperHelper> m_helperRef;
public:
MyMediumClass(); //constructor initializes the smart pointer in cpp
virtual ~MyMediumClass();
void work(); // works with the smart pointer in cpp
};
}
无需包含整个标题!由于m_helperRef不是一个完整的实例化类对象,而只是一个智能指针,并且该智能指针仅用于CPP,因此标题不需要知道MySuperHelper究竟是什么,它只需要一个前向声明。只有CPP - 直接实例化和使用MySuperHelper - 需要确切地知道它是什么,因此必须#include "lowlevel.h"
这可以加快编译速度。一个非常好的库/引擎是Ogre;如果您#include <ogre.h>
,您将只包含一个前向声明列表,可以快速编译。如果您想使用Ogre的类,那么您可以在CPP中包含特定的标题。
就像我说的那样,编译是一个非常复杂的过程,我必须承认我在如何改进并行编译的秘密方面不是很好(可能是其他人可以提供帮助)。在许多情况下,编译是依赖性的顺序过程。尽管如此,有些情况可以在没有更深入了解的情况下并行编译,Visual Studio有一些选项可以这样做。
在Tools/Options/Build and Run
下,您可以输入要同时构建的最大项目数。
但这些只是并行构建的项目。项目本身仍将按顺序编译。但是这也可以在项目本身的项目设置中进行更改(您必须为每个项目执行此操作)
然而,不要期望并行编译有任何奇迹。还有很多案例需要按顺序处理。
您可以打开&#34;显示包含&#34;,它将为您提供构建输出中包含的头文件的列表: (当然这个功能应该只是暂时打开,因为它会极大地减慢构建过程 - 这与你想要的相反;)) 在构建之后,您可以分析输出,或者找到一些您可以删除的不必要的标头。 AFAIK也有一些工具,可以自动为你做,但还没有自己尝试过。 Here这是一篇帖子,其中指出ReSharper C++提供了删除未使用标头的功能(也是我尚未尝试过)
在构建期间,将创建大量文件。如果病毒扫描程序在构建期间访问这些文件,则可能导致严重减速。至少从病毒扫描程序访问中排除临时构建文件夹。