Commit bab7ec3c authored by Brad King's avatar Brad King Committed by Kitware Robot

Merge topic 'pch-generate'

36ded610 PCH: Generate sources during Compute step
Acked-by: Kitware Robot's avatarKitware Robot <kwrobot@kitware.com>
Merge-request: !3890
parents 0d1bf3f6 36ded610
Pipeline #148107 failed with stage
in 0 seconds
......@@ -869,6 +869,32 @@ CompileData Target::BuildCompileData(cmSourceFile* sf)
fd.Flags.emplace_back(this->ToJBT(opt));
}
// Add precompile headers compile options.
const std::string pchSource =
this->GT->GetPchSource(this->Config, fd.Language);
if (!pchSource.empty() && !sf->GetProperty("SKIP_PRECOMPILE_HEADERS")) {
std::string pchOptions;
if (sf->GetFullPath() == pchSource) {
pchOptions =
this->GT->GetPchCreateCompileOptions(this->Config, fd.Language);
} else {
pchOptions =
this->GT->GetPchUseCompileOptions(this->Config, fd.Language);
}
BT<std::string> tmpOpt(pchOptions);
tmpOpt.Value = genexInterpreter.Evaluate(tmpOpt.Value, COMPILE_OPTIONS);
// After generator evaluation we need to use the AppendCompileOptions
// method so we handle situations where backtrace entries have lists
// and properly escape flags.
std::string tmp;
lg->AppendCompileOptions(tmp, tmpOpt.Value);
BT<std::string> opt(tmp, tmpOpt.Backtrace);
fd.Flags.emplace_back(this->ToJBT(opt));
}
// Add include directories from source file properties.
{
const std::string INCLUDE_DIRECTORIES("INCLUDE_DIRECTORIES");
......
......@@ -3486,6 +3486,92 @@ std::string cmGeneratorTarget::GetPchFileObject(const std::string& config,
return inserted.first->second;
}
std::string cmGeneratorTarget::GetPchFile(const std::string& config,
const std::string& language)
{
const auto inserted =
this->PchFiles.insert(std::make_pair(language + config, ""));
if (inserted.second) {
std::string& pchFile = inserted.first->second;
const std::string pchExtension =
this->Makefile->GetSafeDefinition("CMAKE_PCH_EXTENSION");
if (this->Makefile->IsOn("CMAKE_LINK_PCH")) {
auto replaceExtension = [](const std::string& str,
const std::string& ext) -> std::string {
auto dot_pos = str.rfind('.');
std::string result;
if (dot_pos != std::string::npos) {
result = str.substr(0, dot_pos);
}
result += ext;
return result;
};
cmGeneratorTarget* generatorTarget = this;
const char* pchReuseFrom =
generatorTarget->GetProperty("PRECOMPILE_HEADERS_REUSE_FROM");
if (pchReuseFrom) {
generatorTarget =
this->GetGlobalGenerator()->FindGeneratorTarget(pchReuseFrom);
}
const std::string pchFileObject =
generatorTarget->GetPchFileObject(config, language);
if (!pchExtension.empty()) {
pchFile = replaceExtension(pchFileObject, pchExtension);
}
} else {
pchFile = this->GetPchHeader(config, language);
pchFile += pchExtension;
}
}
return inserted.first->second;
}
std::string cmGeneratorTarget::GetPchCreateCompileOptions(
const std::string& config, const std::string& language)
{
const auto inserted = this->PchCreateCompileOptions.insert(
std::make_pair(language + config, ""));
if (inserted.second) {
std::string& createOptionList = inserted.first->second;
const std::string createOptVar =
cmStrCat("CMAKE_", language, "_COMPILE_OPTIONS_CREATE_PCH");
createOptionList = this->Makefile->GetSafeDefinition(createOptVar);
const std::string pchHeader = this->GetPchHeader(config, language);
const std::string pchFile = this->GetPchFile(config, language);
cmSystemTools::ReplaceString(createOptionList, "<PCH_HEADER>", pchHeader);
cmSystemTools::ReplaceString(createOptionList, "<PCH_FILE>", pchFile);
}
return inserted.first->second;
}
std::string cmGeneratorTarget::GetPchUseCompileOptions(
const std::string& config, const std::string& language)
{
const auto inserted =
this->PchUseCompileOptions.insert(std::make_pair(language + config, ""));
if (inserted.second) {
std::string& useOptionList = inserted.first->second;
const std::string useOptVar =
cmStrCat("CMAKE_", language, "_COMPILE_OPTIONS_USE_PCH");
useOptionList = this->Makefile->GetSafeDefinition(useOptVar);
const std::string pchHeader = this->GetPchHeader(config, language);
const std::string pchFile = this->GetPchFile(config, language);
cmSystemTools::ReplaceString(useOptionList, "<PCH_HEADER>", pchHeader);
cmSystemTools::ReplaceString(useOptionList, "<PCH_FILE>", pchFile);
}
return inserted.first->second;
}
void cmGeneratorTarget::GetLinkOptions(std::vector<std::string>& result,
const std::string& config,
const std::string& language) const
......
......@@ -464,6 +464,12 @@ public:
const std::string& language) const;
std::string GetPchFileObject(const std::string& config,
const std::string& language);
std::string GetPchFile(const std::string& config,
const std::string& language);
std::string GetPchCreateCompileOptions(const std::string& config,
const std::string& language);
std::string GetPchUseCompileOptions(const std::string& config,
const std::string& language);
bool IsSystemIncludeDirectory(const std::string& dir,
const std::string& config,
......@@ -883,6 +889,9 @@ private:
mutable std::map<std::string, std::string> PchHeaders;
mutable std::map<std::string, std::string> PchSources;
mutable std::map<std::string, std::string> PchObjectFiles;
mutable std::map<std::string, std::string> PchFiles;
mutable std::map<std::string, std::string> PchCreateCompileOptions;
mutable std::map<std::string, std::string> PchUseCompileOptions;
void ExpandLinkItems(std::string const& prop, std::string const& value,
std::string const& config,
......
......@@ -1562,6 +1562,7 @@ bool cmGlobalGenerator::AddAutomaticSources()
continue;
}
lg->AddUnityBuild(gt);
lg->AddPchDependencies(gt);
}
}
return true;
......
......@@ -827,6 +827,11 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateXCodeSourceFile(
genexInterpreter.Evaluate(compile_defs, COMPILE_DEFINITIONS).c_str(),
true);
}
if (sf->GetPropertyAsBool("SKIP_PRECOMPILE_HEADERS")) {
this->AppendDefines(flagsBuild, "CMAKE_SKIP_PRECOMPILE_HEADERS", true);
}
if (!flagsBuild.IsEmpty()) {
if (!flags.empty()) {
flags += ' ';
......@@ -2827,8 +2832,6 @@ bool cmGlobalXCodeGenerator::CreateGroups(
continue;
}
generator->AddPchDependencies(gtgt, "");
auto addSourceToGroup = [this, mf, gtgt,
&sourceGroups](std::string const& source) {
cmSourceGroup* sourceGroup = mf->FindSourceGroup(source, sourceGroups);
......
......@@ -45,7 +45,6 @@
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <functional>
#include <initializer_list>
#include <iterator>
#include <sstream>
......@@ -2255,9 +2254,13 @@ void cmLocalGenerator::AppendFlagEscape(std::string& flags,
this->AppendFlags(flags, this->EscapeForShell(rawFlag));
}
void cmLocalGenerator::AddPchDependencies(cmGeneratorTarget* target,
const std::string& config)
void cmLocalGenerator::AddPchDependencies(cmGeneratorTarget* target)
{
// FIXME: Handle all configurations in multi-config generators.
std::string config;
if (!this->GetGlobalGenerator()->IsMultiConfig()) {
config = this->Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE");
}
const std::string buildType = cmSystemTools::UpperCase(config);
std::vector<cmSourceFile*> sources;
......@@ -2266,7 +2269,8 @@ void cmLocalGenerator::AddPchDependencies(cmGeneratorTarget* target,
for (const std::string& lang : { "C", "CXX" }) {
auto langSources =
std::count_if(sources.begin(), sources.end(), [lang](cmSourceFile* sf) {
return lang == sf->GetLanguage();
return lang == sf->GetLanguage() &&
!sf->GetProperty("SKIP_PRECOMPILE_HEADERS");
});
if (langSources == 0) {
continue;
......@@ -2279,20 +2283,10 @@ void cmLocalGenerator::AddPchDependencies(cmGeneratorTarget* target,
continue;
}
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()) {
if (pchExtension.empty()) {
continue;
}
......@@ -2301,31 +2295,17 @@ void cmLocalGenerator::AddPchDependencies(cmGeneratorTarget* target,
auto pch_sf = this->Makefile->GetOrCreateSource(
pchSource, false, cmSourceFileLocationKind::Known);
std::string pchFile = pchHeader;
if (!this->GetGlobalGenerator()->IsXcode()) {
if (!pchReuseFrom) {
target->AddSource(pchSource, true);
}
const std::string pchFile = target->GetPchFile(config, lang);
// Exclude the pch files from linking
if (this->Makefile->IsOn("CMAKE_LINK_PCH")) {
auto replaceExtension = [](const std::string& str,
const std::string& ext) -> std::string {
auto dot_pos = str.rfind('.');
std::string result;
if (dot_pos != std::string::npos) {
result = str.substr(0, dot_pos);
}
result += ext;
return result;
};
if (!pchReuseFrom) {
std::string pchSourceObj = target->GetPchFileObject(config, lang);
pchFile = replaceExtension(pchSourceObj, pchExtension);
pch_sf->SetProperty("OBJECT_OUTPUTS", pchFile.c_str());
} else {
auto reuseTarget =
......@@ -2406,14 +2386,13 @@ void cmLocalGenerator::AddPchDependencies(cmGeneratorTarget* target,
reuseTarget->GetPchFileObject(config, lang);
// Link to the pch object file
target->Target->SetProperty(
target->Target->AppendProperty(
"LINK_FLAGS",
this->ConvertToOutputFormat(pchSourceObj, SHELL).c_str());
pchFile = replaceExtension(pchSourceObj, pchExtension);
cmStrCat(" ", this->ConvertToOutputFormat(pchSourceObj, SHELL))
.c_str(),
true);
}
} else {
pchFile += pchExtension;
pch_sf->SetProperty("PCH_EXTENSION", pchExtension.c_str());
}
......@@ -2424,34 +2403,6 @@ void cmLocalGenerator::AddPchDependencies(cmGeneratorTarget* target,
std::string err;
pchHeader_sf->ResolveFullPath(&err);
target->AddSource(pchHeader);
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());
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->AppendProperty("OBJECT_DEPENDS", pchFile.c_str());
sf->AppendProperty("OBJECT_DEPENDS", pchHeader.c_str());
sf->SetProperty("COMPILE_OPTIONS", useOptionList.c_str());
}
}
}
}
......
......@@ -126,8 +126,7 @@ public:
const std::vector<BT<std::string>>& newFlags) const;
virtual void AppendFlagEscape(std::string& flags,
const std::string& rawFlag) const;
void AddPchDependencies(cmGeneratorTarget* target,
const std::string& config);
void AddPchDependencies(cmGeneratorTarget* target);
void AddUnityBuild(cmGeneratorTarget* target);
void AppendIPOLinkerFlags(std::string& flags, cmGeneratorTarget* target,
const std::string& config,
......
......@@ -1317,8 +1317,6 @@ void cmLocalVisualStudio7Generator::WriteVCProjFile(std::ostream& fout,
const std::string& libName,
cmGeneratorTarget* target)
{
this->AddPchDependencies(target, "");
std::vector<std::string> configs;
this->Makefile->GetConfigurations(configs);
......@@ -1456,6 +1454,22 @@ cmLocalVisualStudio7GeneratorFCInfo::cmLocalVisualStudio7GeneratorFCInfo(
fc.CompileFlags, genexInterpreter.Evaluate(coptions, COMPILE_OPTIONS));
needfc = true;
}
// Add precompile headers compile options.
const std::string pchSource = gt->GetPchSource(config, lang);
if (!pchSource.empty() && !sf.GetProperty("SKIP_PRECOMPILE_HEADERS")) {
std::string pchOptions;
if (sf.GetFullPath() == pchSource) {
pchOptions = gt->GetPchCreateCompileOptions(config, lang);
} else {
pchOptions = gt->GetPchUseCompileOptions(config, lang);
}
lg->AppendCompileOptions(
fc.CompileFlags,
genexInterpreter.Evaluate(pchOptions, COMPILE_OPTIONS));
needfc = true;
}
if (lg->FortranProject) {
switch (cmOutputConverter::GetFortranFormat(
sf.GetProperty("Fortran_FORMAT"))) {
......
......@@ -40,8 +40,6 @@ cmMakefileExecutableTargetGenerator::cmMakefileExecutableTargetGenerator(
this->OSXBundleGenerator =
cm::make_unique<cmOSXBundleGenerator>(target, this->ConfigName);
this->OSXBundleGenerator->SetMacContentFolders(&this->MacContentFolders);
this->LocalGenerator->AddPchDependencies(target, this->ConfigName);
}
cmMakefileExecutableTargetGenerator::~cmMakefileExecutableTargetGenerator() =
......
......@@ -42,8 +42,6 @@ cmMakefileLibraryTargetGenerator::cmMakefileLibraryTargetGenerator(
this->OSXBundleGenerator =
cm::make_unique<cmOSXBundleGenerator>(target, this->ConfigName);
this->OSXBundleGenerator->SetMacContentFolders(&this->MacContentFolders);
this->LocalGenerator->AddPchDependencies(target, this->ConfigName);
}
cmMakefileLibraryTargetGenerator::~cmMakefileLibraryTargetGenerator() =
......
......@@ -464,6 +464,19 @@ void cmMakefileTargetGenerator::WriteObjectBuildFile(
// generate the depend scanning rule
this->WriteObjectDependRules(source, depends);
std::string config = this->LocalGenerator->GetConfigName();
std::string configUpper = cmSystemTools::UpperCase(config);
// Add precompile headers dependencies
const std::string pchSource =
this->GeneratorTarget->GetPchSource(config, lang);
if (!pchSource.empty() && !source.GetProperty("SKIP_PRECOMPILE_HEADERS")) {
depends.push_back(this->GeneratorTarget->GetPchHeader(config, lang));
if (source.GetFullPath() != pchSource) {
depends.push_back(this->GeneratorTarget->GetPchFile(config, lang));
}
}
std::string relativeObj =
cmStrCat(this->LocalGenerator->GetHomeRelativeOutputPath(), obj);
// Write the build rule.
......@@ -475,8 +488,6 @@ void cmMakefileTargetGenerator::WriteObjectBuildFile(
std::string langFlags = cmStrCat("$(", lang, "_FLAGS)");
this->LocalGenerator->AppendFlags(flags, langFlags);
std::string config = this->LocalGenerator->GetConfigName();
std::string configUpper = cmSystemTools::UpperCase(config);
cmGeneratorExpressionInterpreter genexInterpreter(
this->LocalGenerator, config, this->GeneratorTarget, lang);
......@@ -506,6 +517,26 @@ void cmMakefileTargetGenerator::WriteObjectBuildFile(
<< "\n";
}
// Add precompile headers compile options.
if (!pchSource.empty() && !source.GetProperty("SKIP_PRECOMPILE_HEADERS")) {
std::string pchOptions;
if (source.GetFullPath() == pchSource) {
pchOptions =
this->GeneratorTarget->GetPchCreateCompileOptions(config, lang);
} else {
pchOptions =
this->GeneratorTarget->GetPchUseCompileOptions(config, lang);
}
const std::string& evaluatedFlags =
genexInterpreter.Evaluate(pchOptions, COMPILE_OPTIONS);
this->LocalGenerator->AppendCompileOptions(flags, evaluatedFlags);
*this->FlagFileStream << "# PCH options: " << relativeObj
<< "_OPTIONS = " << evaluatedFlags << "\n"
<< "\n";
}
// Add include directories from source file properties.
std::vector<std::string> includes;
......
......@@ -25,8 +25,6 @@ cmMakefileUtilityTargetGenerator::cmMakefileUtilityTargetGenerator(
this->OSXBundleGenerator =
cm::make_unique<cmOSXBundleGenerator>(target, this->ConfigName);
this->OSXBundleGenerator->SetMacContentFolders(&this->MacContentFolders);
this->LocalGenerator->AddPchDependencies(target, this->ConfigName);
}
cmMakefileUtilityTargetGenerator::~cmMakefileUtilityTargetGenerator() =
......
......@@ -61,8 +61,6 @@ cmNinjaNormalTargetGenerator::cmNinjaNormalTargetGenerator(
this->OSXBundleGenerator =
cm::make_unique<cmOSXBundleGenerator>(target, this->GetConfigName());
this->OSXBundleGenerator->SetMacContentFolders(&this->MacContentFolders);
GetLocalGenerator()->AddPchDependencies(target, this->GetConfigName());
}
cmNinjaNormalTargetGenerator::~cmNinjaNormalTargetGenerator() = default;
......
......@@ -141,6 +141,7 @@ std::string cmNinjaTargetGenerator::ComputeFlagsForObject(
cmSourceFile const* source, const std::string& language)
{
std::string flags = this->GetFlags(language);
const std::string configName = this->LocalGenerator->GetConfigName();
// Add Fortran format flags.
if (language == "Fortran") {
......@@ -149,8 +150,7 @@ std::string cmNinjaTargetGenerator::ComputeFlagsForObject(
// Add source file specific flags.
cmGeneratorExpressionInterpreter genexInterpreter(
this->LocalGenerator, this->LocalGenerator->GetConfigName(),
this->GeneratorTarget, language);
this->LocalGenerator, configName, this->GeneratorTarget, language);
const std::string COMPILE_FLAGS("COMPILE_FLAGS");
if (const char* cflags = source->GetProperty(COMPILE_FLAGS)) {
......@@ -164,6 +164,24 @@ std::string cmNinjaTargetGenerator::ComputeFlagsForObject(
flags, genexInterpreter.Evaluate(coptions, COMPILE_OPTIONS));
}
// Add precompile headers compile options.
const std::string pchSource =
this->GeneratorTarget->GetPchSource(configName, language);
if (!pchSource.empty() && !source->GetProperty("SKIP_PRECOMPILE_HEADERS")) {
std::string pchOptions;
if (source->GetFullPath() == pchSource) {
pchOptions = this->GeneratorTarget->GetPchCreateCompileOptions(
configName, language);
} else {
pchOptions =
this->GeneratorTarget->GetPchUseCompileOptions(configName, language);
}
this->LocalGenerator->AppendCompileOptions(
flags, genexInterpreter.Evaluate(pchOptions, COMPILE_OPTIONS));
}
return flags;
}
......@@ -984,8 +1002,27 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement(
objBuild.ExplicitDeps.push_back(sourceFileName);
// Add precompile headers dependencies
std::vector<std::string> depList;
const std::string pchSource =
this->GeneratorTarget->GetPchSource(this->GetConfigName(), language);
if (!pchSource.empty() && !source->GetProperty("SKIP_PRECOMPILE_HEADERS")) {
depList.push_back(
this->GeneratorTarget->GetPchHeader(this->GetConfigName(), language));
if (source->GetFullPath() != pchSource) {
depList.push_back(
this->GeneratorTarget->GetPchFile(this->GetConfigName(), language));
}
}
if (const char* objectDeps = source->GetProperty("OBJECT_DEPENDS")) {
std::vector<std::string> depList = cmExpandedList(objectDeps);
std::vector<std::string> objDepList = cmExpandedList(objectDeps);
std::copy(objDepList.begin(), objDepList.end(),
std::back_inserter(depList));
}
if (!depList.empty()) {
for (std::string& odi : depList) {
if (cmSystemTools::FileIsFullPath(odi)) {
odi = cmSystemTools::CollapseFullPath(odi);
......
......@@ -250,8 +250,6 @@ cmVisualStudio10TargetGenerator::cmVisualStudio10TargetGenerator(
this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget);
this->InSourceBuild = (this->Makefile->GetCurrentSourceDirectory() ==
this->Makefile->GetCurrentBinaryDirectory());
this->LocalGenerator->AddPchDependencies(target, "");
}
cmVisualStudio10TargetGenerator::~cmVisualStudio10TargetGenerator()
......@@ -2330,10 +2328,28 @@ void cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags(
cmGeneratorExpression::Find(ccdefs) != std::string::npos;
configDefines += ccdefs;
}
// Add precompile headers compile options.
std::string customAndPchOptions = options;
const std::string pchSource =
this->GeneratorTarget->GetPchSource(config, lang);
if (!pchSource.empty() && !sf.GetProperty("SKIP_PRECOMPILE_HEADERS")) {
std::string pchOptions;
if (sf.GetFullPath() == pchSource) {
pchOptions =
this->GeneratorTarget->GetPchCreateCompileOptions(config, lang);
} else {
pchOptions =
this->GeneratorTarget->GetPchUseCompileOptions(config, lang);
}
customAndPchOptions += pchOptions;
}
// if we have flags or defines for this config then
// use them
if (!flags.empty() || !options.empty() || !configDefines.empty() ||
!includes.empty() || compileAs || noWinRT) {
!includes.empty() || compileAs || noWinRT ||
!customAndPchOptions.empty()) {
cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator;
cmIDEFlagTable const* flagtable = nullptr;
const std::string& srclang = source->GetLanguage();
......@@ -2366,14 +2382,15 @@ void cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags(
} else {
clOptions.Parse(flags);
}
if (!options.empty()) {
if (!customAndPchOptions.empty()) {
std::string expandedOptions;
if (configDependentOptions) {
this->LocalGenerator->AppendCompileOptions(
expandedOptions,
genexInterpreter.Evaluate(options, "COMPILE_OPTIONS"));
genexInterpreter.Evaluate(customAndPchOptions, "COMPILE_OPTIONS"));
} else {
this->LocalGenerator->AppendCompileOptions(expandedOptions, options);
this->LocalGenerator->AppendCompileOptions(expandedOptions,
customAndPchOptions);
}
clOptions.Parse(expandedOptions);
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment