summaryrefslogtreecommitdiffstats
path: root/Source/cmQtAutoGenInitializer.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'Source/cmQtAutoGenInitializer.cxx')
-rw-r--r--Source/cmQtAutoGenInitializer.cxx297
1 files changed, 209 insertions, 88 deletions
diff --git a/Source/cmQtAutoGenInitializer.cxx b/Source/cmQtAutoGenInitializer.cxx
index 5eb04f7..629367d 100644
--- a/Source/cmQtAutoGenInitializer.cxx
+++ b/Source/cmQtAutoGenInitializer.cxx
@@ -25,7 +25,6 @@
#include "cmAlgorithms.h"
#include "cmCustomCommand.h"
#include "cmCustomCommandLines.h"
-#include "cmCustomCommandTypes.h"
#include "cmGeneratedFileStream.h"
#include "cmGeneratorExpression.h"
#include "cmGeneratorTarget.h"
@@ -355,24 +354,38 @@ bool cmQtAutoGenInitializer::InitCustomTargets()
}
}
- // Check status of policy CMP0071
- {
- cmPolicies::PolicyStatus const CMP0071_status =
- this->Makefile->GetPolicyStatus(cmPolicies::CMP0071);
- switch (CMP0071_status) {
- case cmPolicies::WARN:
- this->CMP0071Warn = true;
- CM_FALLTHROUGH;
- case cmPolicies::OLD:
- // Ignore GENERATED file
- break;
- case cmPolicies::REQUIRED_IF_USED:
- case cmPolicies::REQUIRED_ALWAYS:
- case cmPolicies::NEW:
- // Process GENERATED file
- this->CMP0071Accept = true;
- break;
- }
+ // Check status of policy CMP0071 regarding handling of GENERATED files
+ switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0071)) {
+ case cmPolicies::WARN:
+ // Ignore GENERATED files but warn
+ this->CMP0071Warn = true;
+ CM_FALLTHROUGH;
+ case cmPolicies::OLD:
+ // Ignore GENERATED files
+ break;
+ case cmPolicies::REQUIRED_IF_USED:
+ case cmPolicies::REQUIRED_ALWAYS:
+ case cmPolicies::NEW:
+ // Process GENERATED files
+ this->CMP0071Accept = true;
+ break;
+ }
+
+ // Check status of policy CMP0100 regarding handling of .hh headers
+ switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0100)) {
+ case cmPolicies::WARN:
+ // Ignore but .hh files but warn
+ this->CMP0100Warn = true;
+ CM_FALLTHROUGH;
+ case cmPolicies::OLD:
+ // Ignore .hh files
+ break;
+ case cmPolicies::REQUIRED_IF_USED:
+ case cmPolicies::REQUIRED_ALWAYS:
+ case cmPolicies::NEW:
+ // Process .hh file
+ this->CMP0100Accept = true;
+ break;
}
// Common directories
@@ -734,15 +747,26 @@ bool cmQtAutoGenInitializer::InitScanFiles()
return muf;
};
- auto addMUFile = [&](MUFileHandle&& muf, bool isHeader) {
+ auto addMUHeader = [this](MUFileHandle&& muf, cm::string_view extension) {
+ cmSourceFile* sf = muf->SF;
+ const bool muIt = (muf->MocIt || muf->UicIt);
+ if (this->CMP0100Accept || (extension != "hh")) {
+ // Accept
+ if (muIt && muf->Generated) {
+ this->AutogenTarget.FilesGenerated.emplace_back(muf.get());
+ }
+ this->AutogenTarget.Headers.emplace(sf, std::move(muf));
+ } else if (muIt && this->CMP0100Warn) {
+ // Store file for warning message
+ this->AutogenTarget.CMP0100HeadersWarn.push_back(sf);
+ }
+ };
+
+ auto addMUSource = [this](MUFileHandle&& muf) {
if ((muf->MocIt || muf->UicIt) && muf->Generated) {
this->AutogenTarget.FilesGenerated.emplace_back(muf.get());
}
- if (isHeader) {
- this->AutogenTarget.Headers.emplace(muf->SF, std::move(muf));
- } else {
- this->AutogenTarget.Sources.emplace(muf->SF, std::move(muf));
- }
+ this->AutogenTarget.Sources.emplace(muf->SF, std::move(muf));
};
// Scan through target files
@@ -764,11 +788,10 @@ bool cmQtAutoGenInitializer::InitScanFiles()
// Register files that will be scanned by moc or uic
if (this->MocOrUicEnabled()) {
- // FIXME: Add a policy to include .hh files.
- if (cm->IsHeaderExtension(extLower) && extLower != "hh") {
- addMUFile(makeMUFile(sf, fullPath, true), true);
+ if (cm->IsHeaderExtension(extLower)) {
+ addMUHeader(makeMUFile(sf, fullPath, true), extLower);
} else if (cm->IsSourceExtension(extLower)) {
- addMUFile(makeMUFile(sf, fullPath, true), false);
+ addMUSource(makeMUFile(sf, fullPath, true));
}
}
@@ -802,8 +825,6 @@ bool cmQtAutoGenInitializer::InitScanFiles()
// For source files find additional headers and private headers
if (this->MocOrUicEnabled()) {
- std::vector<MUFileHandle> extraHeaders;
- extraHeaders.reserve(this->AutogenTarget.Sources.size() * 2);
// Header search suffixes and extensions
static std::initializer_list<cm::string_view> const suffixes{ "", "_p" };
auto const& exts = cm->GetHeaderExtensions();
@@ -848,16 +869,12 @@ bool cmQtAutoGenInitializer::InitScanFiles()
if (!muf.UicIt) {
eMuf->UicIt = false;
}
- extraHeaders.emplace_back(std::move(eMuf));
+ addMUHeader(std::move(eMuf), ext);
}
}
}
}
}
- // Move generated files to main headers list
- for (auto& eMuf : extraHeaders) {
- addMUFile(std::move(eMuf), true);
- }
}
// Scan through all source files in the makefile to extract moc and uic
@@ -865,7 +882,7 @@ bool cmQtAutoGenInitializer::InitScanFiles()
// The reason is that their file names might be discovered from source files
// at generation time.
if (this->MocOrUicEnabled()) {
- for (cmSourceFile* sf : this->Makefile->GetSourceFiles()) {
+ for (const auto& sf : this->Makefile->GetSourceFiles()) {
// sf->GetExtension() is only valid after sf->ResolveFullPath() ...
// Since we're iterating over source files that might be not in the
// target we need to check for path errors (not existing files).
@@ -877,19 +894,18 @@ bool cmQtAutoGenInitializer::InitScanFiles()
std::string const& extLower =
cmSystemTools::LowerCase(sf->GetExtension());
- // FIXME: Add a policy to include .hh files.
- if (cm->IsHeaderExtension(extLower) && extLower != "hh") {
- if (!cmContains(this->AutogenTarget.Headers, sf)) {
- auto muf = makeMUFile(sf, fullPath, false);
+ if (cm->IsHeaderExtension(extLower)) {
+ if (!cmContains(this->AutogenTarget.Headers, sf.get())) {
+ auto muf = makeMUFile(sf.get(), fullPath, false);
if (muf->SkipMoc || muf->SkipUic) {
- this->AutogenTarget.Headers.emplace(sf, std::move(muf));
+ addMUHeader(std::move(muf), extLower);
}
}
} else if (cm->IsSourceExtension(extLower)) {
- if (!cmContains(this->AutogenTarget.Headers, sf)) {
- auto muf = makeMUFile(sf, fullPath, false);
+ if (!cmContains(this->AutogenTarget.Sources, sf.get())) {
+ auto muf = makeMUFile(sf.get(), fullPath, false);
if (muf->SkipMoc || muf->SkipUic) {
- this->AutogenTarget.Sources.emplace(sf, std::move(muf));
+ addMUSource(std::move(muf));
}
}
} else if (this->Uic.Enabled && (extLower == kw.ui)) {
@@ -947,6 +963,35 @@ bool cmQtAutoGenInitializer::InitScanFiles()
}
}
+ // Generate CMP0100 warning
+ if (this->MocOrUicEnabled() &&
+ !this->AutogenTarget.CMP0100HeadersWarn.empty()) {
+ cm::string_view property;
+ if (this->Moc.Enabled && this->Uic.Enabled) {
+ property = "SKIP_AUTOGEN";
+ } else if (this->Moc.Enabled) {
+ property = "SKIP_AUTOMOC";
+ } else if (this->Uic.Enabled) {
+ property = "SKIP_AUTOUIC";
+ }
+ std::string files;
+ for (cmSourceFile* sf : this->AutogenTarget.CMP0100HeadersWarn) {
+ files += cmStrCat(" ", Quoted(sf->GetFullPath()), '\n');
+ }
+ this->Makefile->IssueMessage(
+ MessageType::AUTHOR_WARNING,
+ cmStrCat(
+ cmPolicies::GetPolicyWarning(cmPolicies::CMP0100), '\n',
+ "For compatibility, CMake is excluding the header file(s):\n", files,
+ "from processing by ",
+ cmQtAutoGen::Tools(this->Moc.Enabled, this->Uic.Enabled, false),
+ ". If any of the files should be processed, set CMP0100 to NEW. "
+ "If any of the files should not be processed, "
+ "explicitly exclude them by setting the source file property ",
+ property, ":\n set_property(SOURCE file.hh PROPERTY ", property,
+ " ON)\n"));
+ }
+
// Process qrc files
if (!this->Rcc.Qrcs.empty()) {
const bool modernQt = (this->QtVersion.Major >= 5);
@@ -1045,9 +1090,16 @@ bool cmQtAutoGenInitializer::InitAutogenTarget()
}
// Compose command lines
- cmCustomCommandLines commandLines = cmMakeSingleCommandLine(
- { cmSystemTools::GetCMakeCommand(), "-E", "cmake_autogen",
- this->AutogenTarget.InfoFile, "$<CONFIGURATION>" });
+ // TODO: Refactor autogen to output a per-config mocs_compilation.cpp instead
+ // of fiddling with the include directories
+ std::vector<std::string> configs;
+ this->GlobalGen->GetQtAutoGenConfigs(configs);
+ cmCustomCommandLines commandLines;
+ for (auto const& config : configs) {
+ commandLines.push_back(cmMakeCommandLine(
+ { cmSystemTools::GetCMakeCommand(), "-E", "cmake_autogen",
+ this->AutogenTarget.InfoFile, config }));
+ }
// Use PRE_BUILD on demand
bool usePRE_BUILD = false;
@@ -1073,7 +1125,7 @@ bool cmQtAutoGenInitializer::InitAutogenTarget()
if (usePRE_BUILD) {
// Add additional autogen target dependencies to origin target
for (cmTarget* depTarget : this->AutogenTarget.DependTargets) {
- this->GenTarget->Target->AddUtility(depTarget->GetName(),
+ this->GenTarget->Target->AddUtility(depTarget->GetName(), false,
this->Makefile);
}
@@ -1084,8 +1136,8 @@ bool cmQtAutoGenInitializer::InitAutogenTarget()
// PRE_BUILD does not support file dependencies!
const std::vector<std::string> no_output;
const std::vector<std::string> no_deps;
- cmCustomCommand cc(this->Makefile, no_output, autogenProvides, no_deps,
- commandLines, autogenComment.c_str(),
+ cmCustomCommand cc(no_output, autogenProvides, no_deps, commandLines,
+ this->Makefile->GetBacktrace(), autogenComment.c_str(),
this->Dir.Work.c_str());
cc.SetEscapeOldStyle(false);
cc.SetEscapeAllowMakeVars(true);
@@ -1119,35 +1171,83 @@ bool cmQtAutoGenInitializer::InitAutogenTarget()
}
}
+ std::vector<std::string> dependencies(
+ this->AutogenTarget.DependFiles.begin(),
+ this->AutogenTarget.DependFiles.end());
+
+ const bool useNinjaDepfile = this->QtVersion >= IntegerVersion(5, 15) &&
+ this->GlobalGen->GetName().find("Ninja") != std::string::npos;
+ if (useNinjaDepfile) {
+ // Create a custom command that generates a timestamp file and
+ // has a depfile assigned. The depfile is created by JobDepFilesMergeT.
+
+ // Add additional autogen target dependencies
+ for (const cmTarget* t : this->AutogenTarget.DependTargets) {
+ dependencies.push_back(t->GetName());
+ }
+ const char timestampFileName[] = "timestamp";
+ const std::string outputFile =
+ cmStrCat(this->Dir.Build, "/", timestampFileName);
+ this->AutogenTarget.DepFile = cmStrCat(this->Dir.Build, "/deps");
+ auto relativeBinaryDir = cmSystemTools::RelativePath(
+ this->LocalGen->GetBinaryDirectory(),
+ this->LocalGen->GetCurrentBinaryDirectory());
+ if (!relativeBinaryDir.empty()) {
+ relativeBinaryDir = cmStrCat(relativeBinaryDir, "/");
+ }
+ this->AutogenTarget.DepFileRuleName =
+ cmStrCat(relativeBinaryDir, this->GenTarget->GetName(), "_autogen/",
+ timestampFileName);
+ commandLines.push_back(cmMakeCommandLine(
+ { cmSystemTools::GetCMakeCommand(), "-E", "touch", outputFile }));
+
+ this->AddGeneratedSource(outputFile, this->Moc);
+ const std::string no_main_dependency;
+ this->LocalGen->AddCustomCommandToOutput(
+ outputFile, dependencies, no_main_dependency, commandLines,
+ autogenComment.c_str(), this->Dir.Work.c_str(), /*replace=*/false,
+ /*escapeOldStyle=*/false,
+ /*uses_terminal=*/false,
+ /*command_expand_lists=*/false, this->AutogenTarget.DepFile);
+
+ // Alter variables for the autogen target which now merely wraps the
+ // custom command
+ dependencies.clear();
+ dependencies.push_back(outputFile);
+ commandLines.clear();
+ autogenComment.clear();
+ }
+
// Create autogen target
- cmTarget* autogenTarget = this->Makefile->AddUtilityCommand(
- this->AutogenTarget.Name, cmCommandOrigin::Generator, true,
- this->Dir.Work.c_str(), /*byproducts=*/autogenProvides,
- std::vector<std::string>(this->AutogenTarget.DependFiles.begin(),
- this->AutogenTarget.DependFiles.end()),
- commandLines, false, autogenComment.c_str());
+ cmTarget* autogenTarget = this->LocalGen->AddUtilityCommand(
+ this->AutogenTarget.Name, true, this->Dir.Work.c_str(),
+ /*byproducts=*/autogenProvides,
+ /*depends=*/dependencies, commandLines, false, autogenComment.c_str());
// Create autogen generator target
this->LocalGen->AddGeneratorTarget(
- new cmGeneratorTarget(autogenTarget, this->LocalGen));
+ cm::make_unique<cmGeneratorTarget>(autogenTarget, this->LocalGen));
// Forward origin utilities to autogen target
if (this->AutogenTarget.DependOrigin) {
- for (BT<std::string> const& depName : this->GenTarget->GetUtilities()) {
- autogenTarget->AddUtility(depName.Value, this->Makefile);
+ for (BT<std::pair<std::string, bool>> const& depName :
+ this->GenTarget->GetUtilities()) {
+ autogenTarget->AddUtility(depName.Value.first, false, this->Makefile);
}
}
- // Add additional autogen target dependencies to autogen target
- for (cmTarget* depTarget : this->AutogenTarget.DependTargets) {
- autogenTarget->AddUtility(depTarget->GetName(), this->Makefile);
+ if (!useNinjaDepfile) {
+ // Add additional autogen target dependencies to autogen target
+ for (cmTarget* depTarget : this->AutogenTarget.DependTargets) {
+ autogenTarget->AddUtility(depTarget->GetName(), false, this->Makefile);
+ }
}
// Set FOLDER property in autogen target
if (!this->TargetsFolder.empty()) {
- autogenTarget->SetProperty("FOLDER", this->TargetsFolder.c_str());
+ autogenTarget->SetProperty("FOLDER", this->TargetsFolder);
}
// Add autogen target to the origin target dependencies
- this->GenTarget->Target->AddUtility(this->AutogenTarget.Name,
+ this->GenTarget->Target->AddUtility(this->AutogenTarget.Name, false,
this->Makefile);
// Add autogen target to the global autogen target dependencies
@@ -1205,25 +1305,25 @@ bool cmQtAutoGenInitializer::InitRccTargets()
ccName += cmStrCat('_', qrc.QrcPathChecksum);
}
- cmTarget* autoRccTarget = this->Makefile->AddUtilityCommand(
- ccName, cmCommandOrigin::Generator, true, this->Dir.Work.c_str(),
- ccOutput, ccDepends, commandLines, false, ccComment.c_str());
+ cmTarget* autoRccTarget = this->LocalGen->AddUtilityCommand(
+ ccName, true, this->Dir.Work.c_str(), ccOutput, ccDepends,
+ commandLines, false, ccComment.c_str());
// Create autogen generator target
this->LocalGen->AddGeneratorTarget(
- new cmGeneratorTarget(autoRccTarget, this->LocalGen));
+ cm::make_unique<cmGeneratorTarget>(autoRccTarget, this->LocalGen));
// Set FOLDER property in autogen target
if (!this->TargetsFolder.empty()) {
- autoRccTarget->SetProperty("FOLDER", this->TargetsFolder.c_str());
+ autoRccTarget->SetProperty("FOLDER", this->TargetsFolder);
}
if (!this->Rcc.ExecutableTargetName.empty()) {
- autoRccTarget->AddUtility(this->Rcc.ExecutableTargetName,
+ autoRccTarget->AddUtility(this->Rcc.ExecutableTargetName, false,
this->Makefile);
}
}
// Add autogen target to the origin target dependencies
- this->GenTarget->Target->AddUtility(ccName, this->Makefile);
+ this->GenTarget->Target->AddUtility(ccName, false, this->Makefile);
// Add autogen target to the global autogen target dependencies
if (this->Rcc.GlobalTarget) {
@@ -1244,7 +1344,7 @@ bool cmQtAutoGenInitializer::InitRccTargets()
}
std::string no_main_dependency;
cmImplicitDependsList no_implicit_depends;
- this->Makefile->AddCustomCommandToOutput(
+ this->LocalGen->AddCustomCommandToOutput(
ccOutput, ccByproducts, ccDepends, no_main_dependency,
no_implicit_depends, commandLines, ccComment.c_str(),
this->Dir.Work.c_str());
@@ -1356,12 +1456,15 @@ bool cmQtAutoGenInitializer::SetupWriteAutogenInfo()
info.SetConfig("INCLUDE_DIR", this->Dir.Include);
info.SetUInt("QT_VERSION_MAJOR", this->QtVersion.Major);
+ info.SetUInt("QT_VERSION_MINOR", this->QtVersion.Minor);
info.Set("QT_MOC_EXECUTABLE", this->Moc.Executable);
info.Set("QT_UIC_EXECUTABLE", this->Uic.Executable);
info.Set("CMAKE_EXECUTABLE", cmSystemTools::GetCMakeCommand());
info.SetConfig("SETTINGS_FILE", this->AutogenTarget.SettingsFile);
info.SetConfig("PARSE_CACHE_FILE", this->AutogenTarget.ParseCacheFile);
+ info.Set("DEP_FILE", this->AutogenTarget.DepFile);
+ info.Set("DEP_FILE_RULE_NAME", this->AutogenTarget.DepFileRuleName);
info.SetArray("HEADER_EXTENSIONS",
this->Makefile->GetCMakeInstance()->GetHeaderExtensions());
info.SetArrayArray(
@@ -1528,8 +1631,8 @@ void cmQtAutoGenInitializer::AddToSourceGroup(std::string const& fileName,
void cmQtAutoGenInitializer::AddCleanFile(std::string const& fileName)
{
- this->GenTarget->Target->AppendProperty("ADDITIONAL_CLEAN_FILES",
- fileName.c_str(), false);
+ this->GenTarget->Target->AppendProperty("ADDITIONAL_CLEAN_FILES", fileName,
+ false);
}
void cmQtAutoGenInitializer::ConfigFileNames(ConfigString& configString,
@@ -1632,21 +1735,39 @@ std::string cmQtAutoGenInitializer::GetMocBuildPath(MUFile const& muf)
if (!muf.MocIt) {
return res;
}
- {
- std::string const basePath =
- cmStrCat(this->PathCheckSum.getPart(muf.FullPath), "/moc_",
- FileNameWithoutLastExtension(muf.FullPath));
- std::string suffix;
- constexpr std::size_t num_tries_max = 256;
- for (std::size_t ii = 0; ii != num_tries_max; ++ii) {
- res = cmStrCat(basePath, suffix, ".cpp");
- if (this->Moc.EmittedBuildPaths.emplace(res).second) {
- break;
- }
- // Compute new suffix
- suffix = cmStrCat('_', ii + 1);
+
+ std::string basePath =
+ cmStrCat(this->PathCheckSum.getPart(muf.FullPath), "/moc_",
+ FileNameWithoutLastExtension(muf.FullPath));
+
+ res = cmStrCat(basePath, ".cpp");
+ if (this->Moc.EmittedBuildPaths.emplace(res).second) {
+ return res;
+ }
+
+ // File name already emitted.
+ // Try appending the header suffix to the base path.
+ basePath = cmStrCat(basePath, '_', muf.SF->GetExtension());
+ res = cmStrCat(basePath, ".cpp");
+ if (this->Moc.EmittedBuildPaths.emplace(res).second) {
+ return res;
+ }
+
+ // File name with header extension already emitted.
+ // Try adding a number to the base path.
+ constexpr std::size_t number_begin = 2;
+ constexpr std::size_t number_end = 256;
+ for (std::size_t ii = number_begin; ii != number_end; ++ii) {
+ res = cmStrCat(basePath, '_', ii, ".cpp");
+ if (this->Moc.EmittedBuildPaths.emplace(res).second) {
+ return res;
}
}
+
+ // Output file name conflict (unlikely, but still...)
+ cmSystemTools::Error(
+ cmStrCat("moc output file name conflict for ", muf.FullPath));
+
return res;
}