summaryrefslogtreecommitdiffstats
path: root/Source
diff options
context:
space:
mode:
authorCristian Adam <cristian.adam@gmail.com>2019-07-13 10:07:30 (GMT)
committerBrad King <brad.king@kitware.com>2019-08-28 15:47:40 (GMT)
commitb8626261e95e0f99c9227d619671822f9a60ef1a (patch)
treebb3b915854ac4ff9b01515642521b2940b02ec38 /Source
parent375d01c6808713a0cfeef9ea092c8236ba063525 (diff)
downloadCMake-b8626261e95e0f99c9227d619671822f9a60ef1a.zip
CMake-b8626261e95e0f99c9227d619671822f9a60ef1a.tar.gz
CMake-b8626261e95e0f99c9227d619671822f9a60ef1a.tar.bz2
Precompile headers: Add methods to generate PCH sources
Co-Author: Daniel Pfeifer <daniel@pfeifer-mail.de>
Diffstat (limited to 'Source')
-rw-r--r--Source/cmGeneratorTarget.cxx110
-rw-r--r--Source/cmGeneratorTarget.h5
-rw-r--r--Source/cmLocalGenerator.cxx83
-rw-r--r--Source/cmLocalGenerator.h2
-rw-r--r--Source/cmMakefileExecutableTargetGenerator.cxx2
-rw-r--r--Source/cmMakefileLibraryTargetGenerator.cxx2
-rw-r--r--Source/cmMakefileTargetGenerator.cxx20
-rw-r--r--Source/cmMakefileUtilityTargetGenerator.cxx2
-rw-r--r--Source/cmNinjaNormalTargetGenerator.cxx2
-rw-r--r--Source/cmNinjaTargetGenerator.cxx16
10 files changed, 240 insertions, 4 deletions
diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx
index 9e20b66..04738d8 100644
--- a/Source/cmGeneratorTarget.cxx
+++ b/Source/cmGeneratorTarget.cxx
@@ -21,6 +21,7 @@
#include "cmCustomCommand.h"
#include "cmCustomCommandGenerator.h"
#include "cmCustomCommandLines.h"
+#include "cmGeneratedFileStream.h"
#include "cmGeneratorExpression.h"
#include "cmGeneratorExpressionContext.h"
#include "cmGeneratorExpressionDAGChecker.h"
@@ -3355,6 +3356,115 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetPrecompileHeaders(
return list;
}
+std::string cmGeneratorTarget::GetPchHeader(const std::string& config,
+ const std::string& language) const
+{
+ if (language != "C" && language != "CXX") {
+ return std::string();
+ }
+ if (this->GetPropertyAsBool("DISABLE_PRECOMPILE_HEADERS")) {
+ return std::string();
+ }
+ const auto inserted =
+ this->PchHeaders.insert(std::make_pair(language + config, ""));
+ if (inserted.second) {
+ const std::vector<BT<std::string>> headers =
+ this->GetPrecompileHeaders(config, language);
+ if (headers.empty()) {
+ return std::string();
+ }
+ std::string& filename = inserted.first->second;
+
+ if (this->GetGlobalGenerator()->IsMultiConfig()) {
+ filename =
+ cmStrCat(this->LocalGenerator->GetCurrentBinaryDirectory(), "/");
+ } else {
+ // For GCC we need to have the header file .h[xx]
+ // next to the .h[xx].gch file
+ filename = this->ObjectDirectory;
+ }
+
+ filename = cmStrCat(filename, "CMakeFiles/", this->GetName(),
+ ".dir/cmake_pch", ((language == "C") ? ".h" : ".hxx"));
+
+ const std::string filename_tmp = cmStrCat(filename, ".tmp");
+ {
+ auto pchPrologue = this->Makefile->GetDefinition("CMAKE_PCH_PROLOGUE");
+ auto pchEpilogue = this->Makefile->GetDefinition("CMAKE_PCH_EPILOGUE");
+
+ cmGeneratedFileStream file(
+ filename_tmp, false,
+ this->GetGlobalGenerator()->GetMakefileEncoding());
+ file << "/* generated by CMake */\n\n";
+ if (pchPrologue) {
+ file << pchPrologue << "\n";
+ }
+ if (this->GetGlobalGenerator()->IsXcode()) {
+ file << "#ifndef CMAKE_SKIP_PRECOMPILE_HEADERS\n";
+ }
+ if (language == "CXX") {
+ file << "#ifdef __cplusplus\n";
+ }
+ for (auto const& header_bt : headers) {
+ if (header_bt.Value.empty()) {
+ continue;
+ }
+ if (header_bt.Value[0] == '<' || header_bt.Value[0] == '"') {
+ file << "#include " << header_bt.Value << "\n";
+ } else {
+ file << "#include \"" << header_bt.Value << "\"\n";
+ }
+ }
+ if (language == "CXX") {
+ file << "#endif // __cplusplus\n";
+ }
+ if (this->GetGlobalGenerator()->IsXcode()) {
+ file << "#endif // CMAKE_SKIP_PRECOMPILE_HEADERS\n";
+ }
+ if (pchEpilogue) {
+ file << pchEpilogue << "\n";
+ }
+ }
+ cmSystemTools::CopyFileIfDifferent(filename_tmp, filename);
+ cmSystemTools::RemoveFile(filename_tmp);
+ }
+ return inserted.first->second;
+}
+
+std::string cmGeneratorTarget::GetPchSource(const std::string& config,
+ const std::string& language) const
+{
+ if (language != "C" && language != "CXX") {
+ return std::string();
+ }
+ const auto inserted =
+ this->PchSources.insert(std::make_pair(language + config, ""));
+ if (inserted.second) {
+ const std::string pchHeader = this->GetPchHeader(config, language);
+ if (pchHeader.empty()) {
+ return std::string();
+ }
+ std::string& filename = inserted.first->second;
+ filename = cmStrCat(this->LocalGenerator->GetCurrentBinaryDirectory(),
+ "/CMakeFiles/", this->GetName(), ".dir/cmake_pch");
+
+ // For GCC the source extension will be tranformed into .h[xx].gch
+ if (!this->Makefile->IsOn("CMAKE_LINK_PCH")) {
+ filename += ((language == "C") ? ".h.c" : ".hxx.cxx");
+ } else {
+ filename += ((language == "C") ? ".c" : ".cxx");
+ }
+ const std::string filename_tmp = cmStrCat(filename, ".tmp");
+ {
+ cmGeneratedFileStream file(filename_tmp);
+ file << "/* generated by CMake */\n";
+ }
+ cmSystemTools::CopyFileIfDifferent(filename_tmp, filename);
+ cmSystemTools::RemoveFile(filename_tmp);
+ }
+ return inserted.first->second;
+}
+
void cmGeneratorTarget::GetLinkOptions(std::vector<std::string>& result,
const std::string& config,
const std::string& language) const
diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h
index 9d422ee..4701071 100644
--- a/Source/cmGeneratorTarget.h
+++ b/Source/cmGeneratorTarget.h
@@ -458,6 +458,11 @@ public:
std::vector<BT<std::string>> GetPrecompileHeaders(
const std::string& config, const std::string& language) const;
+ std::string GetPchHeader(const std::string& config,
+ const std::string& language) const;
+ std::string GetPchSource(const std::string& config,
+ const std::string& language) const;
+
bool IsSystemIncludeDirectory(const std::string& dir,
const std::string& config,
const std::string& language) const;
diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx
index 57dabd1..d6d2f73 100644
--- a/Source/cmLocalGenerator.cxx
+++ b/Source/cmLocalGenerator.cxx
@@ -18,6 +18,7 @@
#include "cmRulePlaceholderExpander.h"
#include "cmSourceFile.h"
#include "cmSourceFileLocation.h"
+#include "cmSourceFileLocationKind.h"
#include "cmState.h"
#include "cmStateDirectory.h"
#include "cmStateTypes.h"
@@ -37,6 +38,7 @@
#include <algorithm>
#include <assert.h>
+#include <functional>
#include <initializer_list>
#include <iterator>
#include <memory>
@@ -2113,6 +2115,82 @@ void cmLocalGenerator::AppendFlagEscape(std::string& flags,
this->AppendFlags(flags, this->EscapeForShell(rawFlag));
}
+void cmLocalGenerator::AddPchDependencies(cmGeneratorTarget* target,
+ const std::string& config)
+{
+ const std::string lang = target->GetLinkerLanguage(config);
+ const std::string buildType = cmSystemTools::UpperCase(config);
+ const std::string pchSource = target->GetPchSource(config, lang);
+ const std::string pchHeader = target->GetPchHeader(config, lang);
+
+ if (pchSource.empty() || pchHeader.empty()) {
+ return;
+ }
+
+ const std::string createOptVar =
+ cmStrCat("CMAKE_", lang, "_COMPILE_OPTIONS_CREATE_PCH");
+ std::string createOptionList =
+ this->Makefile->GetSafeDefinition(createOptVar);
+
+ const std::string useOptVar =
+ cmStrCat("CMAKE_", lang, "_COMPILE_OPTIONS_USE_PCH");
+ std::string useOptionList = this->Makefile->GetSafeDefinition(useOptVar);
+
+ const std::string pchExtension =
+ this->Makefile->GetSafeDefinition("CMAKE_PCH_EXTENSION");
+
+ if (createOptionList.empty() || useOptionList.empty() ||
+ pchExtension.empty()) {
+ return;
+ }
+
+ auto pch_sf = this->Makefile->GetOrCreateSource(
+ pchSource, false, cmSourceFileLocationKind::Known);
+ std::string pchFile = pchHeader;
+
+ if (!this->GetGlobalGenerator()->IsXcode()) {
+ // Exclude the pch files from linking
+ if (this->Makefile->IsOn("CMAKE_LINK_PCH")) {
+ cmSystemTools::ReplaceString(pchFile, (lang == "C" ? ".h" : ".hxx"),
+ pchExtension);
+ pch_sf->SetProperty("OBJECT_OUTPUTS", pchFile.c_str());
+ } else {
+ pchFile += pchExtension;
+ pch_sf->SetProperty("PCH_EXTENSION", pchExtension.c_str());
+ }
+
+ target->AddSource(pchSource, true);
+
+ for (auto& str : { std::ref(useOptionList), std::ref(createOptionList) }) {
+ cmSystemTools::ReplaceString(str, "<PCH_HEADER>", pchHeader);
+ cmSystemTools::ReplaceString(str, "<PCH_FILE>", pchFile);
+ }
+ }
+
+ pch_sf->SetProperty("COMPILE_OPTIONS", createOptionList.c_str());
+
+ std::vector<cmSourceFile*> sources;
+ target->GetSourceFiles(sources, buildType);
+ for (cmSourceFile* sf : sources) {
+ if (pch_sf == sf || sf->GetLanguage() != lang) {
+ continue;
+ }
+
+ if (sf->GetPropertyAsBool("SKIP_PRECOMPILE_HEADERS")) {
+ if (this->GetGlobalGenerator()->IsXcode()) {
+ sf->SetProperty("COMPILE_DEFINITIONS",
+ "CMAKE_SKIP_PRECOMPILE_HEADERS");
+ }
+ continue;
+ }
+
+ if (!this->GetGlobalGenerator()->IsXcode()) {
+ sf->SetProperty("OBJECT_DEPENDS", pchFile.c_str());
+ sf->SetProperty("COMPILE_OPTIONS", useOptionList.c_str());
+ }
+ }
+}
+
void cmLocalGenerator::AppendIPOLinkerFlags(std::string& flags,
cmGeneratorTarget* target,
const std::string& config,
@@ -2705,6 +2783,11 @@ std::string cmLocalGenerator::GetObjectFileNameWithoutTarget(
}
}
+ const char* pchExtension = source.GetProperty("PCH_EXTENSION");
+ if (pchExtension) {
+ customOutputExtension = pchExtension;
+ }
+
// Remove the source extension if it is to be replaced.
if (replaceExt || customOutputExtension) {
keptSourceExtension = false;
diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h
index 455e491..f63fe0f 100644
--- a/Source/cmLocalGenerator.h
+++ b/Source/cmLocalGenerator.h
@@ -124,6 +124,8 @@ public:
virtual void AppendFlags(std::string& flags, const char* newFlags) const;
virtual void AppendFlagEscape(std::string& flags,
const std::string& rawFlag) const;
+ void AddPchDependencies(cmGeneratorTarget* target,
+ const std::string& config);
void AppendIPOLinkerFlags(std::string& flags, cmGeneratorTarget* target,
const std::string& config,
const std::string& lang);
diff --git a/Source/cmMakefileExecutableTargetGenerator.cxx b/Source/cmMakefileExecutableTargetGenerator.cxx
index 7bc05b1..bebd5c4 100644
--- a/Source/cmMakefileExecutableTargetGenerator.cxx
+++ b/Source/cmMakefileExecutableTargetGenerator.cxx
@@ -40,6 +40,8 @@ cmMakefileExecutableTargetGenerator::cmMakefileExecutableTargetGenerator(
this->OSXBundleGenerator =
cm::make_unique<cmOSXBundleGenerator>(target, this->ConfigName);
this->OSXBundleGenerator->SetMacContentFolders(&this->MacContentFolders);
+
+ this->LocalGenerator->AddPchDependencies(target, this->ConfigName);
}
cmMakefileExecutableTargetGenerator::~cmMakefileExecutableTargetGenerator() =
diff --git a/Source/cmMakefileLibraryTargetGenerator.cxx b/Source/cmMakefileLibraryTargetGenerator.cxx
index 252279f..4244402 100644
--- a/Source/cmMakefileLibraryTargetGenerator.cxx
+++ b/Source/cmMakefileLibraryTargetGenerator.cxx
@@ -42,6 +42,8 @@ cmMakefileLibraryTargetGenerator::cmMakefileLibraryTargetGenerator(
this->OSXBundleGenerator =
cm::make_unique<cmOSXBundleGenerator>(target, this->ConfigName);
this->OSXBundleGenerator->SetMacContentFolders(&this->MacContentFolders);
+
+ this->LocalGenerator->AddPchDependencies(target, this->ConfigName);
}
cmMakefileLibraryTargetGenerator::~cmMakefileLibraryTargetGenerator() =
diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx
index f99fe4e..90d8ea9 100644
--- a/Source/cmMakefileTargetGenerator.cxx
+++ b/Source/cmMakefileTargetGenerator.cxx
@@ -239,10 +239,15 @@ void cmMakefileTargetGenerator::WriteTargetBuildRules()
this->GeneratorTarget->GetExtraSources(extraSources, config);
this->OSXBundleGenerator->GenerateMacOSXContentStatements(
extraSources, this->MacOSXContentGenerator);
+ const char* pchExtension =
+ this->Makefile->GetDefinition("CMAKE_PCH_EXTENSION");
std::vector<cmSourceFile const*> externalObjects;
this->GeneratorTarget->GetExternalObjects(externalObjects, config);
for (cmSourceFile const* sf : externalObjects) {
- this->ExternalObjects.push_back(sf->GetFullPath());
+ auto const& objectFileName = sf->GetFullPath();
+ if (!cmSystemTools::StringEndsWith(objectFileName, pchExtension)) {
+ this->ExternalObjects.push_back(objectFileName);
+ }
}
std::vector<cmSourceFile const*> objectSources;
this->GeneratorTarget->GetObjectSources(objectSources, config);
@@ -1238,7 +1243,14 @@ void cmMakefileTargetGenerator::WriteObjectsVariable(
if (!lineContinue) {
lineContinue = "\\";
}
+
+ const char* pchExtension =
+ this->Makefile->GetDefinition("CMAKE_PCH_EXTENSION");
+
for (std::string const& obj : this->Objects) {
+ if (cmSystemTools::StringEndsWith(obj, pchExtension)) {
+ continue;
+ }
*this->BuildFileStream << " " << lineContinue << "\n";
*this->BuildFileStream
<< cmLocalUnixMakefileGenerator3::ConvertToQuotedOutputPath(
@@ -1331,10 +1343,16 @@ private:
void cmMakefileTargetGenerator::WriteObjectsStrings(
std::vector<std::string>& objStrings, std::string::size_type limit)
{
+ const char* pchExtension =
+ this->Makefile->GetDefinition("CMAKE_PCH_EXTENSION");
+
cmMakefileTargetGeneratorObjectStrings helper(
objStrings, this->LocalGenerator,
this->LocalGenerator->GetStateSnapshot().GetDirectory(), limit);
for (std::string const& obj : this->Objects) {
+ if (cmSystemTools::StringEndsWith(obj, pchExtension)) {
+ continue;
+ }
helper.Feed(obj);
}
for (std::string const& obj : this->ExternalObjects) {
diff --git a/Source/cmMakefileUtilityTargetGenerator.cxx b/Source/cmMakefileUtilityTargetGenerator.cxx
index 8ed6be5..556191f 100644
--- a/Source/cmMakefileUtilityTargetGenerator.cxx
+++ b/Source/cmMakefileUtilityTargetGenerator.cxx
@@ -25,6 +25,8 @@ cmMakefileUtilityTargetGenerator::cmMakefileUtilityTargetGenerator(
this->OSXBundleGenerator =
cm::make_unique<cmOSXBundleGenerator>(target, this->ConfigName);
this->OSXBundleGenerator->SetMacContentFolders(&this->MacContentFolders);
+
+ this->LocalGenerator->AddPchDependencies(target, this->ConfigName);
}
cmMakefileUtilityTargetGenerator::~cmMakefileUtilityTargetGenerator() =
diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx
index 2841245..462746a 100644
--- a/Source/cmNinjaNormalTargetGenerator.cxx
+++ b/Source/cmNinjaNormalTargetGenerator.cxx
@@ -59,6 +59,8 @@ cmNinjaNormalTargetGenerator::cmNinjaNormalTargetGenerator(
this->OSXBundleGenerator =
cm::make_unique<cmOSXBundleGenerator>(target, this->GetConfigName());
this->OSXBundleGenerator->SetMacContentFolders(&this->MacContentFolders);
+
+ GetLocalGenerator()->AddPchDependencies(target, this->GetConfigName());
}
cmNinjaNormalTargetGenerator::~cmNinjaNormalTargetGenerator() = default;
diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx
index 3d3d80d..29e8b74 100644
--- a/Source/cmNinjaTargetGenerator.cxx
+++ b/Source/cmNinjaTargetGenerator.cxx
@@ -790,10 +790,16 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatements()
extraSources, this->MacOSXContentGenerator.get());
}
{
+ const char* pchExtension =
+ GetMakefile()->GetDefinition("CMAKE_PCH_EXTENSION");
+
std::vector<cmSourceFile const*> externalObjects;
this->GeneratorTarget->GetExternalObjects(externalObjects, config);
for (cmSourceFile const* sf : externalObjects) {
- this->Objects.push_back(this->GetSourceFilePath(sf));
+ const auto objectFileName = this->GetSourceFilePath(sf);
+ if (!cmSystemTools::StringEndsWith(objectFileName, pchExtension)) {
+ this->Objects.push_back(objectFileName);
+ }
}
}
@@ -955,8 +961,12 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement(
vars["FLAGS"], vars["DEFINES"], vars["INCLUDES"]);
objBuild.Outputs.push_back(objectFileName);
- // Add this object to the list of object files.
- this->Objects.push_back(objectFileName);
+ const char* pchExtension =
+ this->GetMakefile()->GetDefinition("CMAKE_PCH_EXTENSION");
+ if (!cmSystemTools::StringEndsWith(objectFileName, pchExtension)) {
+ // Add this object to the list of object files.
+ this->Objects.push_back(objectFileName);
+ }
objBuild.ExplicitDeps.push_back(sourceFileName);