Commit 2d6cfe26 authored by Sebastian Holtermann's avatar Sebastian Holtermann
Browse files

Autogen: Split initializer main method

parent 84bdae88
......@@ -195,7 +195,6 @@ bool cmQtAutoGenInitializer::InitCustomTargets()
cmGlobalGenerator* globalGen = localGen->GetGlobalGenerator();
// Verbosity
{
this->Verbosity = makefile->GetSafeDefinition("CMAKE_AUTOGEN_VERBOSE");
if (!this->Verbosity.empty()) {
unsigned long iVerb = 0;
......@@ -205,7 +204,6 @@ bool cmQtAutoGenInitializer::InitCustomTargets()
cmSystemTools::IsOn(this->Verbosity.c_str()) ? "1" : "0";
}
}
}
// Configurations
this->MultiConfig = globalGen->IsMultiConfig();
......@@ -247,6 +245,8 @@ bool cmQtAutoGenInitializer::InitCustomTargets()
this->DirBuild += this->AutogenTargetName;
}
cmSystemTools::ConvertToUnixSlashes(this->DirBuild);
// Remove build directories on cleanup
AddCleanFile(makefile, this->DirBuild);
// Working directory
this->DirWork = cbd;
......@@ -268,13 +268,23 @@ bool cmQtAutoGenInitializer::InitCustomTargets()
}
}
// Autogen files
// Autogen info and settings files
{
this->AutogenInfoFile = this->DirInfo;
this->AutogenInfoFile += "/AutogenInfo.cmake";
this->AutogenSettingsFile = this->DirInfo;
this->AutogenSettingsFile += "/AutogenOldSettings.txt";
if (this->MultiConfig) {
for (std::string const& cfg : this->ConfigsList) {
std::string& filename = this->AutogenConfigSettingsFile[cfg];
filename = AppendFilenameSuffix(this->AutogenSettingsFile, "_" + cfg);
AddCleanFile(makefile, filename);
}
} else {
AddCleanFile(makefile, this->AutogenSettingsFile);
}
}
// Autogen target FOLDER property
......@@ -294,60 +304,228 @@ bool cmQtAutoGenInitializer::InitCustomTargets()
}
}
std::set<std::string> autogenDependFiles;
std::set<cmTarget*> autogenDependTargets;
std::vector<std::string> autogenProvides;
if (this->Moc.Enabled || this->Uic.Enabled) {
// Init moc specific settings
if (this->Moc.Enabled && !InitMoc()) {
return false;
}
// Init uic specific settings
if (this->Uic.Enabled && !InitUic()) {
return false;
}
// Remove build directories on cleanup
AddCleanFile(makefile, this->DirBuild);
// Remove old settings on cleanup
// Autogen target: Compute user defined dependencies
{
std::string base = this->DirInfo;
base += "/AutogenOldSettings";
if (this->MultiConfig) {
for (std::string const& cfg : this->ConfigsList) {
std::string filename = base;
filename += '_';
filename += cfg;
filename += ".cmake";
AddCleanFile(makefile, filename);
}
std::string const deps =
this->Target->GetSafeProperty("AUTOGEN_TARGET_DEPENDS");
if (!deps.empty()) {
std::vector<std::string> extraDeps;
cmSystemTools::ExpandListArgument(deps, extraDeps);
for (std::string const& depName : extraDeps) {
// Allow target and file dependencies
auto* depTarget = makefile->FindTargetToUse(depName);
if (depTarget != nullptr) {
this->AutogenDependTargets.insert(depTarget);
} else {
AddCleanFile(makefile, base.append(".cmake"));
this->AutogenDependFiles.insert(depName);
}
}
}
}
}
// Init rcc specific settings
if (this->Rcc.Enabled && !InitRcc()) {
return false;
}
// Add autogen include directory to the origin target INCLUDE_DIRECTORIES
if (this->Moc.Enabled || this->Uic.Enabled ||
(this->Rcc.Enabled && this->MultiConfig)) {
this->Target->AddIncludeDirectory(this->DirInclude, true);
}
if (this->Moc.Enabled && !InitCustomTargetsMoc()) {
// Scan files
if (!this->InitScanFiles()) {
return false;
}
if (this->Uic.Enabled && !InitCustomTargetsUic()) {
// Create autogen target
if ((this->Moc.Enabled || this->Uic.Enabled) && !this->InitAutogenTarget()) {
return false;
}
if (this->Uic.Enabled && !InitCustomTargetsRcc()) {
// Create rcc targets
if (this->Rcc.Enabled && !this->InitRccTargets()) {
return false;
}
// Acquire rcc executable and features
if (this->Rcc.Enabled) {
if (!GetRccExecutable()) {
return true;
}
bool cmQtAutoGenInitializer::InitMoc()
{
cmMakefile* makefile = this->Target->Target->GetMakefile();
cmLocalGenerator* localGen = this->Target->GetLocalGenerator();
// Mocs compilation file
this->Moc.MocsCompilation = this->DirBuild;
this->Moc.MocsCompilation += "/mocs_compilation.cpp";
// Moc predefs command
if (this->Target->GetPropertyAsBool("AUTOMOC_COMPILER_PREDEFINES") &&
this->QtVersionGreaterOrEqual(5, 8)) {
this->Moc.PredefsCmd =
makefile->GetSafeDefinition("CMAKE_CXX_COMPILER_PREDEFINES_COMMAND");
}
// Moc includes
{
auto GetIncludeDirs = [this,
localGen](std::string const& cfg) -> std::string {
// Get the include dirs for this target, without stripping the implicit
// include dirs off, see
// https://gitlab.kitware.com/cmake/cmake/issues/13667
std::vector<std::string> dirs;
localGen->GetIncludeDirectories(dirs, this->Target, "CXX", cfg, false);
return cmJoin(dirs, ";");
};
// Default configuration include directories
this->Moc.Includes = GetIncludeDirs(this->ConfigDefault);
// Other configuration settings
if (this->MultiConfig) {
for (std::string const& cfg : this->ConfigsList) {
std::string dirs = GetIncludeDirs(cfg);
if (dirs != this->Moc.Includes) {
this->Moc.ConfigIncludes[cfg] = std::move(dirs);
}
}
}
}
// Moc compile definitions
{
auto GetCompileDefinitions =
[this, localGen](std::string const& cfg) -> std::string {
std::set<std::string> defines;
localGen->AddCompileDefinitions(defines, this->Target, cfg, "CXX");
return cmJoin(defines, ";");
};
// Default configuration defines
this->Moc.Defines = GetCompileDefinitions(this->ConfigDefault);
// Other configuration defines
if (this->MultiConfig) {
for (std::string const& cfg : this->ConfigsList) {
std::string defines = GetCompileDefinitions(cfg);
if (defines != this->Moc.Defines) {
this->Moc.ConfigDefines[cfg] = std::move(defines);
}
}
}
}
// Moc executable
if (!GetMocExecutable()) {
return false;
}
return true;
}
bool cmQtAutoGenInitializer::InitUic()
{
cmMakefile* makefile = this->Target->Target->GetMakefile();
// Uic search paths
{
std::string const usp =
this->Target->GetSafeProperty("AUTOUIC_SEARCH_PATHS");
if (!usp.empty()) {
cmSystemTools::ExpandListArgument(usp, this->Uic.SearchPaths);
std::string const srcDir = makefile->GetCurrentSourceDirectory();
for (std::string& path : this->Uic.SearchPaths) {
path = cmSystemTools::CollapseFullPath(path, srcDir);
}
}
}
// Uic target options
{
auto UicGetOpts = [this](std::string const& cfg) -> std::string {
std::vector<std::string> opts;
this->Target->GetAutoUicOptions(opts, cfg);
return cmJoin(opts, ";");
};
// Default settings
this->Uic.Options = UicGetOpts(this->ConfigDefault);
// Configuration specific settings
if (this->MultiConfig) {
for (std::string const& cfg : this->ConfigsList) {
std::string options = UicGetOpts(cfg);
if (options != this->Uic.Options) {
this->Uic.ConfigOptions[cfg] = std::move(options);
}
}
}
}
// .ui files skip and options
{
std::string const uiExt = "ui";
std::string pathError;
for (cmSourceFile* sf : makefile->GetSourceFiles()) {
// sf->GetExtension() is only valid after sf->GetFullPath() ...
// Since we're iterating over source files that might be not in the
// target we need to check for path errors (not existing files).
std::string const& fPath = sf->GetFullPath(&pathError);
if (!pathError.empty()) {
pathError.clear();
continue;
}
if (sf->GetExtension() == uiExt) {
std::string const absFile = cmSystemTools::GetRealPath(fPath);
// Check if the .ui file should be skipped
if (sf->GetPropertyAsBool("SKIP_AUTOUIC") ||
sf->GetPropertyAsBool("SKIP_AUTOGEN")) {
this->Uic.Skip.insert(absFile);
}
// Check if the .ui file has uic options
std::string const uicOpts = sf->GetSafeProperty("AUTOUIC_OPTIONS");
if (!uicOpts.empty()) {
// Check if file isn't skipped
if (this->Uic.Skip.count(absFile) == 0) {
this->Uic.FileFiles.push_back(absFile);
std::vector<std::string> optsVec;
cmSystemTools::ExpandListArgument(uicOpts, optsVec);
this->Uic.FileOptions.push_back(std::move(optsVec));
}
}
}
}
}
// Add autogen includes directory to the origin target INCLUDE_DIRECTORIES
if (this->Moc.Enabled || this->Uic.Enabled ||
(this->Rcc.Enabled && this->MultiConfig)) {
this->Target->AddIncludeDirectory(this->DirInclude, true);
// Uic executable
if (!GetUicExecutable()) {
return false;
}
if (this->Moc.Enabled) {
this->AddGeneratedSource(this->Moc.MocsCompilation, GeneratorT::MOC);
autogenProvides.push_back(this->Moc.MocsCompilation);
return true;
}
bool cmQtAutoGenInitializer::InitRcc()
{
if (!GetRccExecutable()) {
return false;
}
return true;
}
// Extract relevant source files
std::vector<std::string> generatedSources;
std::vector<std::string> generatedHeaders;
bool cmQtAutoGenInitializer::InitScanFiles()
{
cmMakefile* makefile = this->Target->Target->GetMakefile();
// Scan through target files
{
std::string const qrcExt = "qrc";
std::vector<cmSourceFile*> srcFiles;
......@@ -372,15 +550,15 @@ bool cmQtAutoGenInitializer::InitCustomTargets()
const bool generated = sf->GetPropertyAsBool("GENERATED");
if (fileType == cmSystemTools::HEADER_FILE_FORMAT) {
if (generated) {
generatedHeaders.push_back(absPath);
this->MocUic.HeadersGenerated.push_back(absPath);
} else {
this->Headers.push_back(absPath);
this->MocUic.Headers.push_back(absPath);
}
} else {
if (generated) {
generatedSources.push_back(absPath);
this->MocUic.SourcesGenerated.push_back(absPath);
} else {
this->Sources.push_back(absPath);
this->MocUic.Sources.push_back(absPath);
}
}
}
......@@ -407,14 +585,16 @@ bool cmQtAutoGenInitializer::InitCustomTargets()
}
}
}
}
// cmGeneratorTarget::GetConfigCommonSourceFiles computes the target's
// sources meta data cache. Clear it so that OBJECT library targets that
// are AUTOGEN initialized after this target get their added
// mocs_compilation.cpp source acknowledged by this target.
this->Target->ClearSourcesCache();
}
// Read skip files from makefile sources
if (this->Moc.Enabled || this->Uic.Enabled) {
// Read skip files from makefile sources
{
std::string pathError;
for (cmSourceFile* sf : makefile->GetSourceFiles()) {
// sf->GetExtension() is only valid after sf->GetFullPath() ...
......@@ -449,7 +629,8 @@ bool cmQtAutoGenInitializer::InitCustomTargets()
}
// Process GENERATED sources and headers
if (!generatedSources.empty() || !generatedHeaders.empty()) {
if (!this->MocUic.SourcesGenerated.empty() ||
!this->MocUic.HeadersGenerated.empty()) {
// Check status of policy CMP0071
bool policyAccept = false;
bool policyWarn = false;
......@@ -472,13 +653,13 @@ bool cmQtAutoGenInitializer::InitCustomTargets()
if (policyAccept) {
// Accept GENERATED sources
for (std::string const& absFile : generatedHeaders) {
this->Headers.push_back(absFile);
autogenDependFiles.insert(absFile);
for (std::string const& absFile : this->MocUic.HeadersGenerated) {
this->MocUic.Headers.push_back(absFile);
this->AutogenDependFiles.insert(absFile);
}
for (std::string const& absFile : generatedSources) {
this->Sources.push_back(absFile);
autogenDependFiles.insert(absFile);
for (std::string const& absFile : this->MocUic.SourcesGenerated) {
this->MocUic.Sources.push_back(absFile);
this->AutogenDependFiles.insert(absFile);
}
} else {
if (policyWarn) {
......@@ -499,10 +680,10 @@ bool cmQtAutoGenInitializer::InitCustomTargets()
}
msg += "For compatibility, CMake is excluding the GENERATED source "
"file(s):\n";
for (const std::string& absFile : generatedHeaders) {
for (const std::string& absFile : this->MocUic.HeadersGenerated) {
msg.append(" ").append(Quoted(absFile)).append("\n");
}
for (const std::string& absFile : generatedSources) {
for (const std::string& absFile : this->MocUic.SourcesGenerated) {
msg.append(" ").append(Quoted(absFile)).append("\n");
}
msg += "from processing by ";
......@@ -518,14 +699,12 @@ bool cmQtAutoGenInitializer::InitCustomTargets()
makefile->IssueMessage(cmake::AUTHOR_WARNING, msg);
}
}
// Clear lists
generatedSources.clear();
generatedHeaders.clear();
}
// Sort headers and sources
if (this->Moc.Enabled || this->Uic.Enabled) {
std::sort(this->Headers.begin(), this->Headers.end());
std::sort(this->Sources.begin(), this->Sources.end());
std::sort(this->MocUic.Headers.begin(), this->MocUic.Headers.end());
std::sort(this->MocUic.Sources.begin(), this->MocUic.Sources.end());
}
}
// Process qrc files
......@@ -576,6 +755,13 @@ bool cmQtAutoGenInitializer::InitCustomTargets()
qrc.SettingsFile = base;
qrc.SettingsFile += "Settings.txt";
if (this->MultiConfig) {
for (std::string const& cfg : this->ConfigsList) {
qrc.ConfigSettingsFile[cfg] =
AppendFilenameSuffix(qrc.SettingsFile, "_" + cfg);
}
}
}
}
}
......@@ -601,120 +787,35 @@ bool cmQtAutoGenInitializer::InitCustomTargets()
RccMergeOptions(opts, qrc.Options, QtV5);
qrc.Options = std::move(opts);
}
// RCC resources
for (Qrc& qrc : this->Rcc.Qrcs) {
// Register file at target
this->AddGeneratedSource(qrc.RccFile, GeneratorT::RCC);
std::vector<std::string> ccOutput;
ccOutput.push_back(qrc.RccFile);
cmCustomCommandLines commandLines;
if (this->MultiConfig) {
// Build for all configurations
for (std::string const& config : this->ConfigsList) {
cmCustomCommandLine currentLine;
currentLine.push_back(cmSystemTools::GetCMakeCommand());
currentLine.push_back("-E");
currentLine.push_back("cmake_autorcc");
currentLine.push_back(qrc.InfoFile);
currentLine.push_back(config);
commandLines.push_back(std::move(currentLine));
if (!qrc.Generated) {
std::string error;
if (!RccListInputs(qrc.QrcFile, qrc.Resources, error)) {
cmSystemTools::Error(error.c_str());
return false;
}
}
} else {
cmCustomCommandLine currentLine;
currentLine.push_back(cmSystemTools::GetCMakeCommand());
currentLine.push_back("-E");
currentLine.push_back("cmake_autorcc");
currentLine.push_back(qrc.InfoFile);
currentLine.push_back("$<CONFIG>");
commandLines.push_back(std::move(currentLine));
}
std::string ccComment = "Automatic RCC for ";
ccComment += FileProjectRelativePath(makefile, qrc.QrcFile);
if (qrc.Generated) {
// Create custom rcc target
std::string ccName;
{
ccName = this->Target->GetName();
ccName += "_arcc_";
ccName += qrc.QrcName;
if (!qrc.Unique) {
ccName += "_";
ccName += qrc.PathChecksum;
}
std::vector<std::string> ccDepends;
// Add the .qrc and info file to the custom target dependencies
ccDepends.push_back(qrc.QrcFile);
ccDepends.push_back(qrc.InfoFile);
cmTarget* autoRccTarget = makefile->AddUtilityCommand(
ccName, cmMakefile::TargetOrigin::Generator, true,
this->DirWork.c_str(), ccOutput, ccDepends, commandLines, false,
ccComment.c_str());
// Create autogen generator target
localGen->AddGeneratorTarget(
new cmGeneratorTarget(autoRccTarget, localGen));
return true;
}
// Set FOLDER property in autogen target
if (!this->AutogenFolder.empty()) {
autoRccTarget->SetProperty("FOLDER", this->AutogenFolder.c_str());
}
}
// Add autogen target to the origin target dependencies
this->Target->Target->AddUtility(ccName, makefile);
} else {
// Create custom rcc command
{
std::vector<std::string> ccByproducts;
std::vector<std::string> ccDepends;
// Add the .qrc and info file to the custom command dependencies
ccDepends.push_back(qrc.QrcFile);
ccDepends.push_back(qrc.InfoFile);
bool cmQtAutoGenInitializer::InitAutogenTarget()
{
cmMakefile* makefile = this->Target->Target->GetMakefile();
cmLocalGenerator* localGen = this->Target->GetLocalGenerator();
cmGlobalGenerator* globalGen = localGen->GetGlobalGenerator();
// Add the resource files to the dependencies
{
std::string error;
if (RccListInputs(qrc.QrcFile, qrc.Resources, error)) {
for (std::string const& fileName : qrc.Resources) {
// Add resource file to the custom command dependencies
ccDepends.push_back(fileName);
}
} else {
cmSystemTools::Error(error.c_str());
return false;
}
}
makefile->AddCustomCommandToOutput(ccOutput, ccByproducts, ccDepends,
/*main_dependency*/ std::string(),
commandLines, ccComment.c_str(),
this->DirWork.c_str());
}
// Reconfigure when .qrc file changes
makefile->AddCMakeDependFile(qrc.QrcFile);
}
}
}
// Register info file as generated by CMake
makefile->AddCMakeOutputFile(this->AutogenInfoFile);
// Create _autogen target
if (this->Moc.Enabled || this->Uic.Enabled) {
// Add user defined autogen target dependencies
{
std::string const deps =
this->Target->GetSafeProperty("AUTOGEN_TARGET_DEPENDS");
if (!deps.empty()) {
std::vector<std::string> extraDeps;
cmSystemTools::ExpandListArgument(deps, extraDeps);
for (std::string const& depName : extraDeps) {
// Allow target and file dependencies
auto* depTarget = makefile->FindTargetToUse(depName);
if (depTarget != nullptr) {
autogenDependTargets.insert(depTarget);
} else {
autogenDependFiles.insert(depName);
}
}
}
// Files provided by the autogen target
std::vector<std::string> autogenProvides;
if (this->Moc.Enabled) {
this->AddGeneratedSource(this->Moc.MocsCompilation, GeneratorT::MOC);
autogenProvides.push_back(this->Moc.MocsCompilation);
}
// Compose target comment
......@@ -760,14 +861,14 @@ bool cmQtAutoGenInitializer::InitCustomTargets()
// Disable PRE_BUILD in some cases
if (usePRE_BUILD) {
// Cannot use PRE_BUILD with file depends
if (!autogenDependFiles.empty()) {
if (!this->AutogenDependFiles.empty()) {
usePRE_BUILD = false;
}
}
// Create the autogen target/command
if (usePRE_BUILD) {
// Add additional autogen target dependencies to origin target
for (cmTarget* depTarget : autogenDependTargets) {
for (cmTarget* depTarget : this->AutogenDependTargets) {
this->Target->Target->AddUtility(depTarget->GetName(), makefile);
}
......@@ -808,7 +909,7 @@ bool cmQtAutoGenInitializer::InitCustomTargets()
}
for (auto const& item : commonTargets) {
if (item.second == this->ConfigsList.size()) {
autogenDependTargets.insert(item.first->Target);
this->AutogenDependTargets.insert(item.first->Target);
}
}
}
......@@ -817,8 +918,8 @@ bool cmQtAutoGenInitializer::InitCustomTargets()
cmTarget* autogenTarget = makefile->AddUtilityCommand(
this->AutogenTargetName, cmMakefile::TargetOrigin::Generator, true,
this->DirWork.c_str(), /*byproducts=*/autogenProvides,
std::vector<std::string>(autogenDependFiles.begin(),
autogenDependFiles.end()),
std::vector<std::string>(this->AutogenDependFiles.begin(),
this->AutogenDependFiles.end()),
commandLines, false, autogenComment.c_str());
// Create autogen generator target
localGen->AddGeneratorTarget(
......@@ -829,7 +930,7 @@ bool cmQtAutoGenInitializer::InitCustomTargets()