From 972cfd1bc393c56d249f1a2fbb8602e5d0c5bb07 Mon Sep 17 00:00:00 2001 From: Orkun Tokdemir Date: Tue, 4 Jul 2023 12:12:42 +0200 Subject: cmCustomCommandGenerator: Fix GetInternalDepfile on moved instance Previously the constructor captured `this` in a lambda used by the `GetInternalDepfile` method, but the pointer is invalidated when the instance moves. --- Source/cmCustomCommandGenerator.cxx | 13 +++++-------- Source/cmCustomCommandGenerator.h | 3 ++- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/Source/cmCustomCommandGenerator.cxx b/Source/cmCustomCommandGenerator.cxx index 2c1480a..634b63b 100644 --- a/Source/cmCustomCommandGenerator.cxx +++ b/Source/cmCustomCommandGenerator.cxx @@ -174,12 +174,6 @@ cmCustomCommandGenerator::cmCustomCommandGenerator( , EmulatorsWithArguments(cc.GetCommandLines().size()) , ComputeInternalDepfile(std::move(computeInternalDepfile)) { - if (!this->ComputeInternalDepfile) { - this->ComputeInternalDepfile = - [this](const std::string& cfg, const std::string& file) -> std::string { - return this->GetInternalDepfileName(cfg, file); - }; - } cmGeneratorExpression ge(*lg->GetCMakeInstance(), cc.GetBacktrace()); cmGeneratorTarget const* target{ lg->FindGeneratorTargetToUse( @@ -445,7 +439,7 @@ std::string cmCustomCommandGenerator::GetFullDepfile() const } std::string cmCustomCommandGenerator::GetInternalDepfileName( - const std::string& /*config*/, const std::string& depfile) + const std::string& /*config*/, const std::string& depfile) const { cmCryptoHash hash(cmCryptoHash::AlgoSHA256); std::string extension; @@ -469,7 +463,10 @@ std::string cmCustomCommandGenerator::GetInternalDepfile() const return ""; } - return this->ComputeInternalDepfile(this->OutputConfig, depfile); + if (this->ComputeInternalDepfile) { + return this->ComputeInternalDepfile(this->OutputConfig, depfile); + } + return this->GetInternalDepfileName(this->OutputConfig, depfile); } cm::optional cmCustomCommandGenerator::GetComment() const diff --git a/Source/cmCustomCommandGenerator.h b/Source/cmCustomCommandGenerator.h index 4453654..43bdd10 100644 --- a/Source/cmCustomCommandGenerator.h +++ b/Source/cmCustomCommandGenerator.h @@ -20,7 +20,8 @@ class cmLocalGenerator; class cmCustomCommandGenerator { - std::string GetInternalDepfileName(const std::string&, const std::string&); + std::string GetInternalDepfileName(const std::string&, + const std::string&) const; cmCustomCommand const* CC; std::string OutputConfig; -- cgit v0.12 From 6d54c368599e379208f8f8e057a1724ac785d151 Mon Sep 17 00:00:00 2001 From: Orkun Tokdemir Date: Wed, 14 Jun 2023 17:32:02 +0200 Subject: Autogen: Fix typo --- Source/cmQtAutoGenInitializer.cxx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Source/cmQtAutoGenInitializer.cxx b/Source/cmQtAutoGenInitializer.cxx index b1d90ee..6ba5116 100644 --- a/Source/cmQtAutoGenInitializer.cxx +++ b/Source/cmQtAutoGenInitializer.cxx @@ -1240,15 +1240,15 @@ bool cmQtAutoGenInitializer::InitAutogenTarget() bool constexpr stdPipesUTF8 = true; cmCustomCommandLines commandLines; if (this->Makefile->GetSafeDefinition("CMAKE_CROSS_CONFIGS").empty()) { - std::string autugenInfoFileconfig; + std::string autogenInfoFileConfig; if (this->MultiConfig) { - autugenInfoFileconfig = "$"; + autogenInfoFileConfig = "$"; } else { - autugenInfoFileconfig = configs[0]; + autogenInfoFileConfig = configs[0]; } commandLines.push_back(cmMakeCommandLine( { cmSystemTools::GetCMakeCommand(), "-E", "cmake_autogen", - this->AutogenTarget.InfoFile, autugenInfoFileconfig })); + this->AutogenTarget.InfoFile, autogenInfoFileConfig })); } else { for (auto const& config : configs) { -- cgit v0.12 From 94c4c1cb2810d15cb1cfe706e4c9afef84560d04 Mon Sep 17 00:00:00 2001 From: Orkun Tokdemir Date: Thu, 6 Jul 2023 17:42:22 +0200 Subject: cmQtAutoGenInitializer: Improve Const-Correctness --- Source/cmQtAutoGenInitializer.cxx | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Source/cmQtAutoGenInitializer.cxx b/Source/cmQtAutoGenInitializer.cxx index 6ba5116..a0308ce 100644 --- a/Source/cmQtAutoGenInitializer.cxx +++ b/Source/cmQtAutoGenInitializer.cxx @@ -904,13 +904,13 @@ bool cmQtAutoGenInitializer::InitScanFiles() if (muf.MocIt || muf.UicIt) { // Search for the default header file and a private header std::string const& srcFullPath = muf.SF->ResolveFullPath(); - std::string basePath = cmStrCat( + std::string const basePath = cmStrCat( cmQtAutoGen::SubDirPrefix(srcFullPath), cmSystemTools::GetFilenameWithoutLastExtension(srcFullPath)); for (auto const& suffix : suffixes) { std::string const suffixedPath = cmStrCat(basePath, suffix); for (auto const& ext : exts) { - std::string fullPath = cmStrCat(suffixedPath, '.', ext); + std::string const fullPath = cmStrCat(suffixedPath, '.', ext); auto constexpr locationKind = cmSourceFileLocationKind::Known; cmSourceFile* sf = @@ -1535,7 +1535,8 @@ bool cmQtAutoGenInitializer::InitRccTargets() cmMakeCommandLine({ cmSystemTools::GetCMakeCommand(), "-E", "cmake_autorcc", qrc.InfoFile, "$" })); } - std::string ccComment = + + std::string const ccComment = cmStrCat("Automatic RCC for ", FileProjectRelativePath(this->Makefile, qrc.QrcFile)); -- cgit v0.12 From 0bf49d557981af4c79955791fe7c463d14fa460b Mon Sep 17 00:00:00 2001 From: Orkun Tokdemir Date: Thu, 6 Jul 2023 17:44:24 +0200 Subject: cmQtAutoGenInitializer: Remove no-op call --- Source/cmQtAutoGenInitializer.cxx | 3 --- 1 file changed, 3 deletions(-) diff --git a/Source/cmQtAutoGenInitializer.cxx b/Source/cmQtAutoGenInitializer.cxx index a0308ce..bf48dbb 100644 --- a/Source/cmQtAutoGenInitializer.cxx +++ b/Source/cmQtAutoGenInitializer.cxx @@ -1584,8 +1584,6 @@ bool cmQtAutoGenInitializer::InitRccTargets() } else { // Create custom rcc command { - std::vector ccByproducts; - // Add the resource files to the dependencies for (std::string const& fileName : qrc.Resources) { // Add resource file to the custom command dependencies @@ -1595,7 +1593,6 @@ bool cmQtAutoGenInitializer::InitRccTargets() ccDepends.push_back(this->Rcc.ExecutableTargetName); } cc->SetOutputs(ccOutput); - cc->SetByproducts(ccByproducts); cc->SetDepends(ccDepends); this->LocalGen->AddCustomCommandToOutput(std::move(cc)); } -- cgit v0.12 From d4889361f0a52632ba2b22710348f1dc2f9fb807 Mon Sep 17 00:00:00 2001 From: Orkun Tokdemir Date: Fri, 7 Jul 2023 00:18:10 +0200 Subject: cmQtAutoGenInitializer: Reduce string copies --- Source/cmQtAutoGenInitializer.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/cmQtAutoGenInitializer.cxx b/Source/cmQtAutoGenInitializer.cxx index bf48dbb..4db6e1d 100644 --- a/Source/cmQtAutoGenInitializer.cxx +++ b/Source/cmQtAutoGenInitializer.cxx @@ -1451,7 +1451,7 @@ bool cmQtAutoGenInitializer::InitAutogenTarget() // Alter variables for the autogen target which now merely wraps the // custom command dependencies.clear(); - dependencies.push_back(outputFile); + dependencies.emplace_back(std::move(outputFile)); commandLines.clear(); autogenComment.clear(); } -- cgit v0.12 From cac2e029f02213648699665a962def96d41b2b05 Mon Sep 17 00:00:00 2001 From: Orkun Tokdemir Date: Thu, 29 Jun 2023 17:00:36 +0200 Subject: cmQtAutoGenInitializer: Define CrossConfig variable --- Source/cmQtAutoGenInitializer.cxx | 10 +++++----- Source/cmQtAutoGenInitializer.h | 1 + 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/Source/cmQtAutoGenInitializer.cxx b/Source/cmQtAutoGenInitializer.cxx index 4db6e1d..b78d557 100644 --- a/Source/cmQtAutoGenInitializer.cxx +++ b/Source/cmQtAutoGenInitializer.cxx @@ -332,6 +332,8 @@ cmQtAutoGenInitializer::cmQtAutoGenInitializer( this->Uic.Enabled = uicEnabled; this->Rcc.Enabled = rccEnabled; this->Rcc.GlobalTarget = globalAutoRccTarget; + this->CrossConfig = + !this->Makefile->GetSafeDefinition("CMAKE_CROSS_CONFIGS").empty(); } bool cmQtAutoGenInitializer::InitCustomTargets() @@ -1026,8 +1028,7 @@ bool cmQtAutoGenInitializer::InitScanFiles() if (this->MocOrUicEnabled() && !this->AutogenTarget.FilesGenerated.empty()) { if (this->CMP0071Accept) { // Let the autogen target depend on the GENERATED files - if (this->MultiConfig && - this->Makefile->GetSafeDefinition("CMAKE_CROSS_CONFIGS").empty()) { + if (this->MultiConfig && !this->CrossConfig) { for (MUFile const* muf : this->AutogenTarget.FilesGenerated) { if (muf->Configs.empty()) { this->AutogenTarget.DependFiles.insert(muf->FullPath); @@ -1190,8 +1191,7 @@ bool cmQtAutoGenInitializer::InitAutogenTarget() if (this->Moc.Enabled) { this->AddGeneratedSource(this->Moc.CompilationFile, this->Moc, true); if (useDepfile) { - if (this->MultiConfig && - !this->Makefile->GetSafeDefinition("CMAKE_CROSS_CONFIGS").empty() && + if (this->MultiConfig && this->CrossConfig && this->GlobalGen->GetName().find("Ninja") != std::string::npos) { // Make all mocs_compilation_.cpp files byproducts of the // ${target}_autogen/timestamp custom command. @@ -1239,7 +1239,7 @@ bool cmQtAutoGenInitializer::InitAutogenTarget() this->GlobalGen->GetQtAutoGenConfigs(configs); bool constexpr stdPipesUTF8 = true; cmCustomCommandLines commandLines; - if (this->Makefile->GetSafeDefinition("CMAKE_CROSS_CONFIGS").empty()) { + if (!this->CrossConfig) { std::string autogenInfoFileConfig; if (this->MultiConfig) { autogenInfoFileConfig = "$"; diff --git a/Source/cmQtAutoGenInitializer.h b/Source/cmQtAutoGenInitializer.h index 6d5261a..a44d33f 100644 --- a/Source/cmQtAutoGenInitializer.h +++ b/Source/cmQtAutoGenInitializer.h @@ -167,6 +167,7 @@ private: IntegerVersion QtVersion; unsigned int Verbosity = 0; bool MultiConfig = false; + bool CrossConfig = false; bool CMP0071Accept = false; bool CMP0071Warn = false; bool CMP0100Accept = false; -- cgit v0.12 From 10b09647f2699b32c3d243f595437cb1c63049e2 Mon Sep 17 00:00:00 2001 From: Orkun Tokdemir Date: Fri, 23 Jun 2023 20:31:40 +0200 Subject: RunCMake: Add RunCMake_TEST_EXPECT_RESULT --- Tests/RunCMake/RunCMake.cmake | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Tests/RunCMake/RunCMake.cmake b/Tests/RunCMake/RunCMake.cmake index baeb9ca..8939cb7 100644 --- a/Tests/RunCMake/RunCMake.cmake +++ b/Tests/RunCMake/RunCMake.cmake @@ -24,6 +24,8 @@ function(run_cmake test) if(EXISTS ${top_src}/${test}-result.txt) file(READ ${top_src}/${test}-result.txt expect_result) string(REGEX REPLACE "\n+$" "" expect_result "${expect_result}") + elseif(DEFINED RunCMake_TEST_EXPECT_RESULT) + set(expect_result "${RunCMake_TEST_EXPECT_RESULT}") else() set(expect_result 0) endif() -- cgit v0.12 From fddd0f0443b4ce81d61f15ee1b2f13105967b25a Mon Sep 17 00:00:00 2001 From: Orkun Tokdemir Date: Wed, 14 Jun 2023 13:10:03 +0200 Subject: Autogen: AUTO*_EXECUTABLE: add support for per-config values * Per-config values were added to `AUTO*_EXECUTABLE`. * Dependency order was refactored for `cmake_autogen` and `cmake_autorcc` to avoid unnecessary rebuilds. * A new parameter was added for `cmake_autogen` and `cmake_autorcc` to specify the config name of the `auto*_executable` to be used. * The timestamp target was split into three targets for per-config to avoid redundant `mocs_compilation` builds. * Per-config `DEP_FILE_RULE_NAME` values were added to `AutogenInfo.json` for `CMAKE_CROSS_CONFIG` usage. * Some functions were refactored to avoid code duplication. Fixes: #20074 --- Source/cmQtAutoGen.h | 17 + Source/cmQtAutoGenGlobalInitializer.cxx | 91 ++++-- Source/cmQtAutoGenGlobalInitializer.h | 10 +- Source/cmQtAutoGenInitializer.cxx | 359 +++++++++++++++------ Source/cmQtAutoGenInitializer.h | 34 +- Source/cmQtAutoGenerator.cxx | 4 +- Source/cmQtAutoGenerator.h | 8 +- Source/cmQtAutoMocUic.cxx | 38 ++- Source/cmQtAutoMocUic.h | 3 +- Source/cmQtAutoRcc.cxx | 36 ++- Source/cmQtAutoRcc.h | 3 +- Source/cmcmd.cxx | 8 +- .../RunCMake/Autogen/AutoMocExecutableConfig.cmake | 24 ++ .../RunCMake/Autogen/AutoRccExecutableConfig.cmake | 24 ++ .../RunCMake/Autogen/AutoUicExecutableConfig.cmake | 24 ++ Tests/RunCMake/Autogen/RunCMakeTest.cmake | 164 ++++++++++ Tests/RunCMake/Autogen/data.qrc | 4 + Tests/RunCMake/Autogen/example.cpp | 5 + Tests/RunCMake/Autogen/example.h | 12 + Tests/RunCMake/Autogen/example_ui.cpp | 5 + Tests/RunCMake/Autogen/example_ui.h | 14 + Tests/RunCMake/Autogen/exe.cpp | 4 + Tests/RunCMake/Autogen/exe_common.h | 48 +++ Tests/RunCMake/Autogen/exe_debug.cpp | 10 + Tests/RunCMake/Autogen/exe_release.cpp | 10 + Tests/RunCMake/Autogen/exe_relwithdebinfo.cpp | 10 + Tests/RunCMake/Autogen/uiA.ui | 24 ++ 27 files changed, 819 insertions(+), 174 deletions(-) create mode 100644 Tests/RunCMake/Autogen/AutoMocExecutableConfig.cmake create mode 100644 Tests/RunCMake/Autogen/AutoRccExecutableConfig.cmake create mode 100644 Tests/RunCMake/Autogen/AutoUicExecutableConfig.cmake create mode 100644 Tests/RunCMake/Autogen/data.qrc create mode 100644 Tests/RunCMake/Autogen/example.cpp create mode 100644 Tests/RunCMake/Autogen/example.h create mode 100644 Tests/RunCMake/Autogen/example_ui.cpp create mode 100644 Tests/RunCMake/Autogen/example_ui.h create mode 100644 Tests/RunCMake/Autogen/exe.cpp create mode 100644 Tests/RunCMake/Autogen/exe_common.h create mode 100644 Tests/RunCMake/Autogen/exe_debug.cpp create mode 100644 Tests/RunCMake/Autogen/exe_release.cpp create mode 100644 Tests/RunCMake/Autogen/exe_relwithdebinfo.cpp create mode 100644 Tests/RunCMake/Autogen/uiA.ui diff --git a/Source/cmQtAutoGen.h b/Source/cmQtAutoGen.h index d111422..2e750b6 100644 --- a/Source/cmQtAutoGen.h +++ b/Source/cmQtAutoGen.h @@ -6,6 +6,7 @@ #include #include +#include #include #include @@ -16,6 +17,22 @@ class cmQtAutoGen { public: + /** String value with per configuration variants. */ + class ConfigString + { + public: + std::string Default; + std::unordered_map Config; + }; + + /** String values with per configuration variants. */ + template + class ConfigStrings + { + public: + C Default; + std::unordered_map Config; + }; /** Integer version. */ struct IntegerVersion { diff --git a/Source/cmQtAutoGenGlobalInitializer.cxx b/Source/cmQtAutoGenGlobalInitializer.cxx index 1da8847..214df25 100644 --- a/Source/cmQtAutoGenGlobalInitializer.cxx +++ b/Source/cmQtAutoGenGlobalInitializer.cxx @@ -213,24 +213,81 @@ void cmQtAutoGenGlobalInitializer::AddToGlobalAutoRcc( } } -cmQtAutoGen::CompilerFeaturesHandle +cmQtAutoGen::ConfigStrings cmQtAutoGenGlobalInitializer::GetCompilerFeatures( - std::string const& generator, std::string const& executable, - std::string& error) + std::string const& generator, cmQtAutoGen::ConfigString const& executable, + std::string& error, bool const isMultiConfig) { + cmQtAutoGen::ConfigStrings res; + if (isMultiConfig) { + for (auto const& config : executable.Config) { + auto const exe = config.second; + // Check if we have cached features + { + auto it = this->CompilerFeatures_.Config[config.first].find(exe); + if (it != this->CompilerFeatures_.Config[config.first].end()) { + res.Config[config.first] = it->second; + continue; + } + } + + // Check if the executable exists + if (!cmSystemTools::FileExists(exe, true)) { + error = cmStrCat("The \"", generator, "\" executable ", + cmQtAutoGen::Quoted(exe), " does not exist."); + res.Config[config.first] = {}; + continue; + } + + // Test the executable + std::string stdOut; + { + std::string stdErr; + std::vector command; + command.emplace_back(exe); + command.emplace_back("-h"); + int retVal = 0; + const bool runResult = cmSystemTools::RunSingleCommand( + command, &stdOut, &stdErr, &retVal, nullptr, + cmSystemTools::OUTPUT_NONE, cmDuration::zero(), + cmProcessOutput::Auto); + if (!runResult) { + error = cmStrCat("Test run of \"", generator, "\" executable ", + cmQtAutoGen::Quoted(exe), " failed.\n", + cmQtAutoGen::QuotedCommand(command), '\n', stdOut, + '\n', stdErr); + res.Config[config.first] = {}; + continue; + } + } + + // Create valid handle + res.Config[config.first] = + std::make_shared(); + res.Config[config.first]->HelpOutput = std::move(stdOut); + + // Register compiler features + this->CompilerFeatures_.Config[config.first].emplace( + exe, res.Config[config.first]); + } + return res; + } + // Check if we have cached features { - auto it = this->CompilerFeatures_.find(executable); - if (it != this->CompilerFeatures_.end()) { - return it->second; + auto it = this->CompilerFeatures_.Default.find(executable.Default); + if (it != this->CompilerFeatures_.Default.end()) { + res.Default = it->second; + return res; } } // Check if the executable exists - if (!cmSystemTools::FileExists(executable, true)) { - error = cmStrCat("The \"", generator, "\" executable ", - cmQtAutoGen::Quoted(executable), " does not exist."); - return cmQtAutoGen::CompilerFeaturesHandle(); + if (!cmSystemTools::FileExists(executable.Default, true)) { + error = + cmStrCat("The \"", generator, "\" executable ", + cmQtAutoGen::Quoted(executable.Default), " does not exist."); + return cmQtAutoGen::ConfigStrings(); } // Test the executable @@ -238,7 +295,7 @@ cmQtAutoGenGlobalInitializer::GetCompilerFeatures( { std::string stdErr; std::vector command; - command.emplace_back(executable); + command.emplace_back(executable.Default); command.emplace_back("-h"); int retVal = 0; const bool runResult = cmSystemTools::RunSingleCommand( @@ -246,20 +303,18 @@ cmQtAutoGenGlobalInitializer::GetCompilerFeatures( cmDuration::zero(), cmProcessOutput::Auto); if (!runResult) { error = cmStrCat("Test run of \"", generator, "\" executable ", - cmQtAutoGen::Quoted(executable), " failed.\n", + cmQtAutoGen::Quoted(executable.Default), " failed.\n", cmQtAutoGen::QuotedCommand(command), '\n', stdOut, '\n', stdErr); - return cmQtAutoGen::CompilerFeaturesHandle(); + return cmQtAutoGen::ConfigStrings(); } } - // Create valid handle - cmQtAutoGen::CompilerFeaturesHandle res = - std::make_shared(); - res->HelpOutput = std::move(stdOut); + res.Default = std::make_shared(); + res.Default->HelpOutput = std::move(stdOut); // Register compiler features - this->CompilerFeatures_.emplace(executable, res); + this->CompilerFeatures_.Default.emplace(executable.Default, res.Default); return res; } diff --git a/Source/cmQtAutoGenGlobalInitializer.h b/Source/cmQtAutoGenGlobalInitializer.h index e8569a5..5ea5997 100644 --- a/Source/cmQtAutoGenGlobalInitializer.h +++ b/Source/cmQtAutoGenGlobalInitializer.h @@ -66,14 +66,16 @@ private: void AddToGlobalAutoRcc(cmLocalGenerator* localGen, std::string const& targetName); - cmQtAutoGen::CompilerFeaturesHandle GetCompilerFeatures( - std::string const& generator, std::string const& executable, - std::string& error); + cmQtAutoGen::ConfigStrings + GetCompilerFeatures(std::string const& generator, + cmQtAutoGen::ConfigString const& executable, + std::string& error, bool isMultiConfig); std::vector> Initializers_; std::map GlobalAutoGenTargets_; std::map GlobalAutoRccTargets_; - std::unordered_map + cmQtAutoGen::ConfigStrings< + std::unordered_map> CompilerFeatures_; Keywords const Keywords_; }; diff --git a/Source/cmQtAutoGenInitializer.cxx b/Source/cmQtAutoGenInitializer.cxx index b78d557..d6d3999 100644 --- a/Source/cmQtAutoGenInitializer.cxx +++ b/Source/cmQtAutoGenInitializer.cxx @@ -2,6 +2,7 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmQtAutoGenInitializer.h" +#include #include #include #include @@ -17,6 +18,7 @@ #include #include #include +#include #include #include @@ -301,15 +303,22 @@ bool InfoWriter::Save(std::string const& filename) return fileStream.Close(); } -void AddAutogenExecutableToDependencies( - cmQtAutoGenInitializer::GenVarsT const& genVars, - std::vector& dependencies) +cmQtAutoGen::ConfigStrings> generateListOptions( + cmQtAutoGen::ConfigStrings const& + executableFeatures, + bool IsMultiConfig) { - if (genVars.ExecutableTarget != nullptr) { - dependencies.push_back(genVars.ExecutableTarget->Target->GetName()); - } else if (!genVars.Executable.empty()) { - dependencies.push_back(genVars.Executable); + cmQtAutoGen::ConfigStrings> tempListOptions; + if (IsMultiConfig) { + for (auto const& executableFeature : executableFeatures.Config) { + tempListOptions.Config[executableFeature.first] = + executableFeature.second->ListOptions; + } + } else { + tempListOptions.Default = executableFeatures.Default->ListOptions; } + + return tempListOptions; } } // End of unnamed namespace @@ -336,6 +345,34 @@ cmQtAutoGenInitializer::cmQtAutoGenInitializer( !this->Makefile->GetSafeDefinition("CMAKE_CROSS_CONFIGS").empty(); } +void cmQtAutoGenInitializer::AddAutogenExecutableToDependencies( + cmQtAutoGenInitializer::GenVarsT const& genVars, + std::vector& dependencies) const +{ + if (genVars.ExecutableTarget != nullptr) { + dependencies.push_back(genVars.ExecutableTarget->Target->GetName()); + } else if (this->MultiConfig) { + cm::string_view const& configGenexWithCommandConfig = + "$CrossConfig ? configGenexWithCommandConfig : configGenex; + auto genexEnd = + this->CrossConfig ? configGenexEndWithCommandConfig : configGenexEnd; + for (auto const& config : genVars.Executable.Config) { + auto executableWithConfig = + cmStrCat(genexBegin, config.first, ">:", config.second, genexEnd); + dependencies.emplace_back(std::move(executableWithConfig)); + } + } else { + if (!genVars.Executable.Default.empty()) { + dependencies.push_back(genVars.Executable.Default); + } + } +} + bool cmQtAutoGenInitializer::InitCustomTargets() { // Configurations @@ -779,18 +816,30 @@ bool cmQtAutoGenInitializer::InitRcc() return false; } // Evaluate test output on demand - CompilerFeatures& features = *this->Rcc.ExecutableFeatures; - if (!features.Evaluated) { - // Look for list options - if (this->QtVersion.Major == 5 || this->QtVersion.Major == 6) { - if (features.HelpOutput.find("--list") != std::string::npos) { - features.ListOptions.emplace_back("--list"); - } else if (features.HelpOutput.find("-list") != std::string::npos) { - features.ListOptions.emplace_back("-list"); + auto& features = this->Rcc.ExecutableFeatures; + auto checkAndAddOptions = [this](CompilerFeaturesHandle& feature) { + if (!feature->Evaluated) { + // Look for list options + if (this->QtVersion.Major == 5 || this->QtVersion.Major == 6) { + static std::array const listOptions{ { "--list", + "-list" } }; + for (std::string const& opt : listOptions) { + if (feature->HelpOutput.find(opt) != std::string::npos) { + feature->ListOptions.emplace_back(opt); + break; + } + } } + // Evaluation finished + feature->Evaluated = true; } - // Evaluation finished - features.Evaluated = true; + }; + if (this->MultiConfig) { + for (auto const& config : this->ConfigsList) { + checkAndAddOptions(features.Config[config]); + } + } else { + checkAndAddOptions(features.Default); } } @@ -1126,8 +1175,13 @@ bool cmQtAutoGenInitializer::InitScanFiles() // Path checksum qrc.QrcPathChecksum = this->PathCheckSum.getPart(qrc.QrcFile); // Output file name - qrc.OutputFile = cmStrCat(this->Dir.Build, '/', qrc.QrcPathChecksum, - "/qrc_", qrc.QrcName, ".cpp"); + if (this->CrossConfig) { + qrc.OutputFile = cmStrCat(this->Dir.Build, '/', qrc.QrcPathChecksum, + "_$", "/qrc_", qrc.QrcName, ".cpp"); + } else { + qrc.OutputFile = cmStrCat(this->Dir.Build, '/', qrc.QrcPathChecksum, + "/qrc_", qrc.QrcName, ".cpp"); + } std::string const base = cmStrCat(this->Dir.Info, "/AutoRcc_", qrc.QrcName, '_', qrc.QrcPathChecksum); qrc.LockFile = cmStrCat(base, "_Lock.lock"); @@ -1159,11 +1213,25 @@ bool cmQtAutoGenInitializer::InitScanFiles() for (Qrc& qrc : this->Rcc.Qrcs) { if (!qrc.Generated) { std::string error; - RccLister const lister(this->Rcc.Executable, - this->Rcc.ExecutableFeatures->ListOptions); - if (!lister.list(qrc.QrcFile, qrc.Resources, error)) { - cmSystemTools::Error(error); - return false; + if (this->MultiConfig) { + for (auto const& config : this->ConfigsList) { + RccLister const lister( + this->Rcc.Executable.Config[config], + this->Rcc.ExecutableFeatures.Config[config]->ListOptions); + if (!lister.list(qrc.QrcFile, qrc.Resources.Config[config], + error)) { + cmSystemTools::Error(error); + return false; + } + } + } else { + RccLister const lister( + this->Rcc.Executable.Default, + this->Rcc.ExecutableFeatures.Default->ListOptions); + if (!lister.list(qrc.QrcFile, qrc.Resources.Default, error)) { + cmSystemTools::Error(error); + return false; + } } } } @@ -1191,18 +1259,7 @@ bool cmQtAutoGenInitializer::InitAutogenTarget() if (this->Moc.Enabled) { this->AddGeneratedSource(this->Moc.CompilationFile, this->Moc, true); if (useDepfile) { - if (this->MultiConfig && this->CrossConfig && - this->GlobalGen->GetName().find("Ninja") != std::string::npos) { - // Make all mocs_compilation_.cpp files byproducts of the - // ${target}_autogen/timestamp custom command. - // We cannot just use Moc.CompilationFileGenex here, because that - // custom command runs cmake_autogen for each configuration. - for (const auto& p : this->Moc.CompilationFile.Config) { - timestampByproducts.push_back(p.second); - } - } else { - timestampByproducts.push_back(this->Moc.CompilationFileGenex); - } + timestampByproducts.push_back(this->Moc.CompilationFileGenex); } else { autogenByproducts.push_back(this->Moc.CompilationFileGenex); } @@ -1235,28 +1292,11 @@ bool cmQtAutoGenInitializer::InitAutogenTarget() // Compose command lines // FIXME: Take advantage of our per-config mocs_compilation_$.cpp // instead of fiddling with the include directories - std::vector configs; - this->GlobalGen->GetQtAutoGenConfigs(configs); + bool constexpr stdPipesUTF8 = true; cmCustomCommandLines commandLines; - if (!this->CrossConfig) { - std::string autogenInfoFileConfig; - if (this->MultiConfig) { - autogenInfoFileConfig = "$"; - } else { - autogenInfoFileConfig = configs[0]; - } - commandLines.push_back(cmMakeCommandLine( - { cmSystemTools::GetCMakeCommand(), "-E", "cmake_autogen", - this->AutogenTarget.InfoFile, autogenInfoFileConfig })); - - } else { - for (auto const& config : configs) { - commandLines.push_back(cmMakeCommandLine( - { cmSystemTools::GetCMakeCommand(), "-E", "cmake_autogen", - this->AutogenTarget.InfoFile, config })); - } - } + AddCMakeProcessToCommandLines(this->AutogenTarget.InfoFile, "cmake_autogen", + commandLines); // Use PRE_BUILD on demand bool usePRE_BUILD = false; @@ -1424,18 +1464,47 @@ bool cmQtAutoGenInitializer::InitAutogenTarget() AddAutogenExecutableToDependencies(this->Moc, dependencies); AddAutogenExecutableToDependencies(this->Uic, dependencies); - + std::string outputFile; + std::string depFile; // Create the custom command that outputs the timestamp file. - const char timestampFileName[] = "timestamp"; - const std::string outputFile = - cmStrCat(this->Dir.Build, "/", timestampFileName); - this->AutogenTarget.DepFile = cmStrCat(this->Dir.Build, "/deps"); - this->AutogenTarget.DepFileRuleName = - cmStrCat(this->Dir.RelativeBuild, "/", timestampFileName); - commandLines.push_back(cmMakeCommandLine( - { cmSystemTools::GetCMakeCommand(), "-E", "touch", outputFile })); - - this->AddGeneratedSource(outputFile, this->Moc); + if (this->MultiConfig && this->CrossConfig) { + // create timestamp file with $ in the name so that + // every cmake_autogen target has its own timestamp file + std::string const configView = "$"; + std::string const timestampFileWithoutConfig = "timestamp_"; + std::string const depFileWithoutConfig = + cmStrCat(this->Dir.Build, "/deps_"); + std::string const timestampFileName = + timestampFileWithoutConfig + configView; + outputFile = cmStrCat(this->Dir.Build, "/", timestampFileName); + auto const depFileWithConfig = + cmStrCat(depFileWithoutConfig, configView); + depFile = depFileWithConfig; + commandLines.push_back(cmMakeCommandLine( + { cmSystemTools::GetCMakeCommand(), "-E", "touch", outputFile })); + + ConfigString outputFileWithConfig; + for (std::string const& config : this->ConfigsList) { + auto tempTimestampFileName = timestampFileWithoutConfig + config; + auto tempDepFile = depFileWithoutConfig + config; + outputFileWithConfig.Config[config] = tempTimestampFileName; + this->AutogenTarget.DepFileRuleName.Config[config] = + cmStrCat(this->Dir.RelativeBuild, "/", tempTimestampFileName); + this->AutogenTarget.DepFile.Config[config] = tempDepFile; + } + this->AddGeneratedSource(outputFileWithConfig, this->Moc); + } else { + cm::string_view const timestampFileName = "timestamp"; + outputFile = cmStrCat(this->Dir.Build, "/", timestampFileName); + this->AutogenTarget.DepFile.Default = + cmStrCat(this->Dir.Build, "/deps"); + depFile = this->AutogenTarget.DepFile.Default; + this->AutogenTarget.DepFileRuleName.Default = + cmStrCat(this->Dir.RelativeBuild, "/", timestampFileName); + commandLines.push_back(cmMakeCommandLine( + { cmSystemTools::GetCMakeCommand(), "-E", "touch", outputFile })); + this->AddGeneratedSource(outputFile, this->Moc); + } cc = cm::make_unique(); cc->SetOutputs(outputFile); cc->SetByproducts(timestampByproducts); @@ -1444,12 +1513,9 @@ bool cmQtAutoGenInitializer::InitAutogenTarget() cc->SetComment(autogenComment.c_str()); cc->SetWorkingDirectory(this->Dir.Work.c_str()); cc->SetEscapeOldStyle(false); - cc->SetDepfile(this->AutogenTarget.DepFile); + cc->SetDepfile(depFile); cc->SetStdPipesUTF8(stdPipesUTF8); this->LocalGen->AddCustomCommandToOutput(std::move(cc)); - - // Alter variables for the autogen target which now merely wraps the - // custom command dependencies.clear(); dependencies.emplace_back(std::move(outputFile)); commandLines.clear(); @@ -1503,6 +1569,29 @@ bool cmQtAutoGenInitializer::InitAutogenTarget() return true; } +void cmQtAutoGenInitializer::AddCMakeProcessToCommandLines( + std::string const& infoFile, std::string const& processName, + cmCustomCommandLines& commandLines) +{ + if (this->CrossConfig) { + commandLines.push_back(cmMakeCommandLine( + { cmSystemTools::GetCMakeCommand(), "-E", processName, infoFile, + "$", "$>" })); + } else { + std::string autoInfoFileConfig; + if (this->MultiConfig) { + autoInfoFileConfig = "$"; + } else { + std::vector configs; + this->GlobalGen->GetQtAutoGenConfigs(configs); + autoInfoFileConfig = configs[0]; + } + commandLines.push_back( + cmMakeCommandLine({ cmSystemTools::GetCMakeCommand(), "-E", processName, + infoFile, autoInfoFileConfig })); + } +} + bool cmQtAutoGenInitializer::InitRccTargets() { for (Qrc const& qrc : this->Rcc.Qrcs) { @@ -1523,18 +1612,7 @@ bool cmQtAutoGenInitializer::InitRccTargets() ccDepends.push_back(qrc.InfoFile); cmCustomCommandLines commandLines; - if (this->MultiConfig) { - // Build for all configurations - for (std::string const& config : this->ConfigsList) { - commandLines.push_back( - cmMakeCommandLine({ cmSystemTools::GetCMakeCommand(), "-E", - "cmake_autorcc", qrc.InfoFile, config })); - } - } else { - commandLines.push_back( - cmMakeCommandLine({ cmSystemTools::GetCMakeCommand(), "-E", - "cmake_autorcc", qrc.InfoFile, "$" })); - } + AddCMakeProcessToCommandLines(qrc.InfoFile, "cmake_autorcc", commandLines); std::string const ccComment = cmStrCat("Automatic RCC for ", @@ -1585,13 +1663,28 @@ bool cmQtAutoGenInitializer::InitRccTargets() // Create custom rcc command { // Add the resource files to the dependencies - for (std::string const& fileName : qrc.Resources) { - // Add resource file to the custom command dependencies - ccDepends.push_back(fileName); + if (this->MultiConfig) { + for (auto const& config : this->ConfigsList) { + // Add resource file to the custom command dependencies + auto resourceFilesWithConfig = cmStrCat( + "$<$:", cmList{ qrc.Resources.Config.at(config) }.to_string(), + ">"); + ccDepends.emplace_back(std::move(resourceFilesWithConfig)); + } + } else { + for (std::string const& fileName : qrc.Resources.Default) { + // Add resource file to the custom command dependencies + ccDepends.push_back(fileName); + } } + if (!this->Rcc.ExecutableTargetName.empty()) { ccDepends.push_back(this->Rcc.ExecutableTargetName); } + + AddAutogenExecutableToDependencies(this->Rcc, ccDepends); + cc->SetOutputs(ccOutput); cc->SetDepends(ccDepends); this->LocalGen->AddCustomCommandToOutput(std::move(cc)); @@ -1691,6 +1784,7 @@ bool cmQtAutoGenInitializer::SetupWriteAutogenInfo() // General info.SetBool("MULTI_CONFIG", this->MultiConfig); + info.SetBool("CROSS_CONFIG", this->CrossConfig); info.SetUInt("PARALLEL", this->AutogenTarget.Parallel); info.SetUInt("VERBOSITY", this->Verbosity); @@ -1704,14 +1798,14 @@ bool cmQtAutoGenInitializer::SetupWriteAutogenInfo() 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.SetConfig("QT_MOC_EXECUTABLE", this->Moc.Executable); + info.SetConfig("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.SetConfig("DEP_FILE", this->AutogenTarget.DepFile); + info.SetConfig("DEP_FILE_RULE_NAME", this->AutogenTarget.DepFileRuleName); info.SetArray("CMAKE_LIST_FILES", this->Makefile->GetListFiles()); info.SetArray("HEADER_EXTENSIONS", this->Makefile->GetCMakeInstance()->GetHeaderExtensions()); @@ -1838,6 +1932,7 @@ bool cmQtAutoGenInitializer::SetupWriteRccInfo() // General info.SetBool("MULTI_CONFIG", this->MultiConfig); + info.SetBool("CROSS_CONFIG", this->CrossConfig); info.SetUInt("VERBOSITY", this->Verbosity); // Files @@ -1853,16 +1948,17 @@ bool cmQtAutoGenInitializer::SetupWriteRccInfo() info.SetConfig("INCLUDE_DIR", this->Dir.Include); // rcc executable - info.Set("RCC_EXECUTABLE", this->Rcc.Executable); - info.SetArray("RCC_LIST_OPTIONS", - this->Rcc.ExecutableFeatures->ListOptions); + info.SetConfig("RCC_EXECUTABLE", this->Rcc.Executable); + info.SetConfigArray( + "RCC_LIST_OPTIONS", + generateListOptions(this->Rcc.ExecutableFeatures, this->MultiConfig)); // qrc file info.Set("SOURCE", qrc.QrcFile); info.Set("OUTPUT_CHECKSUM", qrc.QrcPathChecksum); info.Set("OUTPUT_NAME", cmSystemTools::GetFilenameName(qrc.OutputFile)); info.SetArray("OPTIONS", qrc.Options); - info.SetArray("INPUTS", qrc.Resources); + info.SetConfigArray("INPUTS", qrc.Resources); info.Save(qrc.InfoFile); } @@ -2206,16 +2302,32 @@ bool cmQtAutoGenInitializer::GetQtExecutable(GenVarsT& genVars, cmListFileBacktrace lfbt = this->Makefile->GetBacktrace(); cmGeneratorExpression ge(*this->Makefile->GetCMakeInstance(), lfbt); std::unique_ptr cge = ge.Parse(val); - genVars.Executable = cge->Evaluate(this->LocalGen, ""); + if (this->MultiConfig) { + for (auto const& config : this->ConfigsList) { + genVars.Executable.Config[config] = + cge->Evaluate(this->LocalGen, config); + } + } else { + genVars.Executable.Default = cge->Evaluate(this->LocalGen, ""); + } } - if (genVars.Executable.empty() && !ignoreMissingTarget) { + + if (genVars.Executable.Default.empty() && + genVars.Executable.Config.empty() && !ignoreMissingTarget) { print_err(prop + " evaluates to an empty value"); return false; } // Create empty compiler features. - genVars.ExecutableFeatures = - std::make_shared(); + if (this->MultiConfig) { + for (auto const& config : this->ConfigsList) { + genVars.ExecutableFeatures.Config[config] = + std::make_shared(); + } + } else { + genVars.ExecutableFeatures.Default = + std::make_shared(); + } return true; } } @@ -2240,15 +2352,39 @@ bool cmQtAutoGenInitializer::GetQtExecutable(GenVarsT& genVars, genVars.ExecutableTargetName = targetName; genVars.ExecutableTarget = genTarget; if (genTarget->IsImported()) { - genVars.Executable = genTarget->ImportedGetLocation(""); + if (this->MultiConfig) { + for (auto const& config : this->ConfigsList) { + genVars.Executable.Config[config] = + genTarget->ImportedGetLocation(config); + } + } else { + genVars.Executable.Default = + genTarget->ImportedGetLocation(this->ConfigDefault); + } + } else { - genVars.Executable = genTarget->GetLocation(""); + if (this->MultiConfig) { + for (auto const& config : this->ConfigsList) { + genVars.Executable.Config[config] = genTarget->GetLocation(config); + } + } else { + genVars.Executable.Default = + genTarget->GetLocation(this->ConfigDefault); + } } } else { if (ignoreMissingTarget) { // Create empty compiler features. - genVars.ExecutableFeatures = - std::make_shared(); + if (this->MultiConfig) { + for (auto const& config : this->ConfigsList) { + genVars.ExecutableFeatures.Config[config] = + std::make_shared(); + } + } else { + genVars.ExecutableFeatures.Default = + std::make_shared(); + } + return true; } print_err(cmStrCat("Could not find ", executable, " executable target ", @@ -2261,10 +2397,21 @@ bool cmQtAutoGenInitializer::GetQtExecutable(GenVarsT& genVars, { std::string err; genVars.ExecutableFeatures = this->GlobalInitializer->GetCompilerFeatures( - executable, genVars.Executable, err); - if (!genVars.ExecutableFeatures) { - print_err(err); - return false; + executable, genVars.Executable, err, this->MultiConfig); + if (this->MultiConfig) { + for (auto const& config : this->ConfigsList) { + if (!genVars.ExecutableFeatures.Config[config]) { + if (!genVars.ExecutableFeatures.Config[config]) { + print_err(err); + return false; + } + } + } + } else { + if (!genVars.ExecutableFeatures.Default) { + print_err(err); + return false; + } } } diff --git a/Source/cmQtAutoGenInitializer.h b/Source/cmQtAutoGenInitializer.h index a44d33f..ee37d2f 100644 --- a/Source/cmQtAutoGenInitializer.h +++ b/Source/cmQtAutoGenInitializer.h @@ -18,6 +18,7 @@ #include "cmFilePathChecksum.h" #include "cmQtAutoGen.h" +class cmCustomCommandLines; class cmGeneratorTarget; class cmGlobalGenerator; class cmLocalGenerator; @@ -32,23 +33,6 @@ class cmTarget; class cmQtAutoGenInitializer : public cmQtAutoGen { public: - /** String value with per configuration variants. */ - class ConfigString - { - public: - std::string Default; - std::unordered_map Config; - }; - - /** String values with per configuration variants. */ - template - class ConfigStrings - { - public: - C Default; - std::unordered_map Config; - }; - /** rcc job. */ class Qrc { @@ -63,7 +47,7 @@ public: bool Generated = false; bool Unique = false; std::vector Options; - std::vector Resources; + ConfigStrings> Resources; }; /** moc and/or uic file. */ @@ -90,8 +74,8 @@ public: // Executable std::string ExecutableTargetName; cmGeneratorTarget* ExecutableTarget = nullptr; - std::string Executable; - CompilerFeaturesHandle ExecutableFeatures; + ConfigString Executable; + ConfigStrings ExecutableFeatures; GenVarsT(GenT gen) : Gen(gen) @@ -141,6 +125,9 @@ private: GenVarsT const& genVars, bool prepend = false); void AddToSourceGroup(std::string const& fileName, cm::string_view genNameUpper); + void AddCMakeProcessToCommandLines(std::string const& infoFile, + std::string const& processName, + cmCustomCommandLines& commandLines); void AddCleanFile(std::string const& fileName); void ConfigFileNames(ConfigString& configString, cm::string_view prefix, @@ -155,6 +142,9 @@ private: bool ignoreMissingTarget) const; void handleSkipPch(cmSourceFile* sf); + void AddAutogenExecutableToDependencies( + cmQtAutoGenInitializer::GenVarsT const& genVars, + std::vector& dependencies) const; cmQtAutoGenGlobalInitializer* GlobalInitializer = nullptr; cmGeneratorTarget* GenTarget = nullptr; @@ -202,8 +192,8 @@ private: bool DependOrigin = false; std::set DependFiles; std::set DependTargets; - std::string DepFile; - std::string DepFileRuleName; + ConfigString DepFile; + ConfigString DepFileRuleName; // Sources to process std::unordered_map Headers; std::unordered_map Sources; diff --git a/Source/cmQtAutoGenerator.cxx b/Source/cmQtAutoGenerator.cxx index c048312..ebdec12 100644 --- a/Source/cmQtAutoGenerator.cxx +++ b/Source/cmQtAutoGenerator.cxx @@ -430,10 +430,12 @@ std::string cmQtAutoGenerator::MessagePath(cm::string_view path) const return cmQtAutoGen::Quoted(res); } -bool cmQtAutoGenerator::Run(cm::string_view infoFile, cm::string_view config) +bool cmQtAutoGenerator::Run(cm::string_view infoFile, cm::string_view config, + cm::string_view executableConfig) { // Info config this->InfoConfig_ = std::string(config); + this->ExecutableConfig_ = std::string(executableConfig); // Info file this->InfoFile_ = std::string(infoFile); diff --git a/Source/cmQtAutoGenerator.h b/Source/cmQtAutoGenerator.h index 5c3a8ad..4b15fc7 100644 --- a/Source/cmQtAutoGenerator.h +++ b/Source/cmQtAutoGenerator.h @@ -90,6 +90,10 @@ public: std::string const& InfoDir() const { return this->InfoDir_; } cmFileTime const& InfoFileTime() const { return this->InfoFileTime_; } std::string const& InfoConfig() const { return this->InfoConfig_; } + std::string const& ExecutableConfig() const + { + return this->ExecutableConfig_; + } // -- Info file parsing /** Info file reader class. */ @@ -151,7 +155,8 @@ public: std::string MessagePath(cm::string_view path) const; // -- Run - bool Run(cm::string_view infoFile, cm::string_view config); + bool Run(cm::string_view infoFile, cm::string_view config, + cm::string_view executableConfig); protected: // -- Abstract processing interface @@ -170,6 +175,7 @@ private: std::string InfoDir_; cmFileTime InfoFileTime_; std::string InfoConfig_; + std::string ExecutableConfig_; // -- Directories ProjectDirsT ProjectDirs_; }; diff --git a/Source/cmQtAutoMocUic.cxx b/Source/cmQtAutoMocUic.cxx index ece657d..68d2897 100644 --- a/Source/cmQtAutoMocUic.cxx +++ b/Source/cmQtAutoMocUic.cxx @@ -170,6 +170,7 @@ public: // -- Attributes // - Config bool MultiConfig = false; + bool CrossConfig = false; IntegerVersion QtVersion = { 4, 0 }; unsigned int ThreadCount = 0; // - Directories @@ -2372,6 +2373,7 @@ bool cmQtAutoMocUicT::InitFromInfo(InfoT const& info) { // -- Required settings if (!info.GetBool("MULTI_CONFIG", this->BaseConst_.MultiConfig, true) || + !info.GetBool("CROSS_CONFIG", this->BaseConst_.CrossConfig, true) || !info.GetUInt("QT_VERSION_MAJOR", this->BaseConst_.QtVersion.Major, true) || !info.GetUInt("QT_VERSION_MINOR", this->BaseConst_.QtVersion.Minor, @@ -2384,19 +2386,34 @@ bool cmQtAutoMocUicT::InitFromInfo(InfoT const& info) true) || !info.GetStringConfig("PARSE_CACHE_FILE", this->BaseConst_.ParseCacheFile, true) || - !info.GetString("DEP_FILE", this->BaseConst_.DepFile, false) || - !info.GetString("DEP_FILE_RULE_NAME", this->BaseConst_.DepFileRuleName, - false) || + !info.GetStringConfig("DEP_FILE", this->BaseConst_.DepFile, false) || + !info.GetStringConfig("DEP_FILE_RULE_NAME", + this->BaseConst_.DepFileRuleName, false) || !info.GetStringConfig("SETTINGS_FILE", this->SettingsFile_, true) || !info.GetArray("CMAKE_LIST_FILES", this->BaseConst_.ListFiles, true) || !info.GetArray("HEADER_EXTENSIONS", this->BaseConst_.HeaderExtensions, - true) || - !info.GetString("QT_MOC_EXECUTABLE", this->MocConst_.Executable, - false) || - !info.GetString("QT_UIC_EXECUTABLE", this->UicConst_.Executable, - false)) { + true)) { return false; } + if (this->BaseConst_.CrossConfig) { + std::string const mocExecutableWithConfig = + "QT_MOC_EXECUTABLE_" + this->ExecutableConfig(); + std::string const uicExecutableWithConfig = + "QT_UIC_EXECUTABLE_" + this->ExecutableConfig(); + if (!info.GetString(mocExecutableWithConfig, this->MocConst_.Executable, + false) || + !info.GetString(uicExecutableWithConfig, this->UicConst_.Executable, + false)) { + return false; + } + } else { + if (!info.GetStringConfig("QT_MOC_EXECUTABLE", this->MocConst_.Executable, + false) || + !info.GetStringConfig("QT_UIC_EXECUTABLE", this->UicConst_.Executable, + false)) { + return false; + } + } // -- Checks if (!this->BaseConst_.CMakeExecutableTime.Load( @@ -3063,7 +3080,8 @@ std::string cmQtAutoMocUicT::AbsoluteIncludePath( } // End of unnamed namespace -bool cmQtAutoMocUic(cm::string_view infoFile, cm::string_view config) +bool cmQtAutoMocUic(cm::string_view infoFile, cm::string_view config, + cm::string_view executableConfig) { - return cmQtAutoMocUicT().Run(infoFile, config); + return cmQtAutoMocUicT().Run(infoFile, config, executableConfig); } diff --git a/Source/cmQtAutoMocUic.h b/Source/cmQtAutoMocUic.h index 20f9d6e..5cb4ff1 100644 --- a/Source/cmQtAutoMocUic.h +++ b/Source/cmQtAutoMocUic.h @@ -10,4 +10,5 @@ * Process AUTOMOC and AUTOUIC * @return true on success */ -bool cmQtAutoMocUic(cm::string_view infoFile, cm::string_view config); +bool cmQtAutoMocUic(cm::string_view infoFile, cm::string_view config, + cm::string_view executableConfig); diff --git a/Source/cmQtAutoRcc.cxx b/Source/cmQtAutoRcc.cxx index e288645..488f704 100644 --- a/Source/cmQtAutoRcc.cxx +++ b/Source/cmQtAutoRcc.cxx @@ -53,6 +53,7 @@ private: // -- Config settings bool MultiConfig_ = false; + bool CrossConfig_ = false; // -- Directories std::string AutogenBuildDir_; std::string IncludeDir_; @@ -92,26 +93,44 @@ bool cmQtAutoRccT::InitFromInfo(InfoT const& info) { // -- Required settings if (!info.GetBool("MULTI_CONFIG", this->MultiConfig_, true) || + !info.GetBool("CROSS_CONFIG", this->CrossConfig_, true) || !info.GetString("BUILD_DIR", this->AutogenBuildDir_, true) || !info.GetStringConfig("INCLUDE_DIR", this->IncludeDir_, true) || - !info.GetString("RCC_EXECUTABLE", this->RccExecutable_, true) || - !info.GetArray("RCC_LIST_OPTIONS", this->RccListOptions_, false) || + !info.GetArrayConfig("RCC_LIST_OPTIONS", this->RccListOptions_, false) || !info.GetString("LOCK_FILE", this->LockFile_, true) || !info.GetStringConfig("SETTINGS_FILE", this->SettingsFile_, true) || !info.GetString("SOURCE", this->QrcFile_, true) || !info.GetString("OUTPUT_CHECKSUM", this->RccPathChecksum_, true) || !info.GetString("OUTPUT_NAME", this->RccFileName_, true) || !info.GetArray("OPTIONS", this->Options_, false) || - !info.GetArray("INPUTS", this->Inputs_, false)) { + !info.GetArrayConfig("INPUTS", this->Inputs_, false)) { return false; } + if (this->CrossConfig_) { + std::string const rccExecutableWithConfig = + "RCC_EXECUTABLE_" + this->ExecutableConfig(); + if (!info.GetString(rccExecutableWithConfig, this->RccExecutable_, true)) { + return false; + } + } else { + if (!info.GetStringConfig("RCC_EXECUTABLE", this->RccExecutable_, true)) { + return false; + } + } + // -- Derive information this->QrcFileName_ = cmSystemTools::GetFilenameName(this->QrcFile_); this->QrcFileDir_ = cmSystemTools::GetFilenamePath(this->QrcFile_); - this->RccFilePublic_ = - cmStrCat(this->AutogenBuildDir_, '/', this->RccPathChecksum_, '/', - this->RccFileName_); + if (this->CrossConfig_) { + this->RccFilePublic_ = + cmStrCat(this->AutogenBuildDir_, '/', this->RccPathChecksum_, "_", + this->InfoConfig(), '/', this->RccFileName_); + } else { + this->RccFilePublic_ = + cmStrCat(this->AutogenBuildDir_, '/', this->RccPathChecksum_, '/', + this->RccFileName_); + } // rcc output file name if (this->IsMultiConfig()) { @@ -520,7 +539,8 @@ bool cmQtAutoRccT::GenerateWrapper() } // End of unnamed namespace -bool cmQtAutoRcc(cm::string_view infoFile, cm::string_view config) +bool cmQtAutoRcc(cm::string_view infoFile, cm::string_view config, + cm::string_view executableConfig) { - return cmQtAutoRccT().Run(infoFile, config); + return cmQtAutoRccT().Run(infoFile, config, executableConfig); } diff --git a/Source/cmQtAutoRcc.h b/Source/cmQtAutoRcc.h index d525efa..9c0a4e9 100644 --- a/Source/cmQtAutoRcc.h +++ b/Source/cmQtAutoRcc.h @@ -10,4 +10,5 @@ * Process AUTORCC * @return true on success */ -bool cmQtAutoRcc(cm::string_view infoFile, cm::string_view config); +bool cmQtAutoRcc(cm::string_view infoFile, cm::string_view config, + cm::string_view executableConfig); diff --git a/Source/cmcmd.cxx b/Source/cmcmd.cxx index 94f4d38..431ffbf 100644 --- a/Source/cmcmd.cxx +++ b/Source/cmcmd.cxx @@ -1435,13 +1435,17 @@ int cmcmd::ExecuteCMakeCommand(std::vector const& args, if ((args[1] == "cmake_autogen") && (args.size() >= 4)) { cm::string_view const infoFile = args[2]; cm::string_view const config = args[3]; - return cmQtAutoMocUic(infoFile, config) ? 0 : 1; + cm::string_view const executableConfig = + (args.size() >= 5) ? cm::string_view(args[4]) : cm::string_view(); + return cmQtAutoMocUic(infoFile, config, executableConfig) ? 0 : 1; } if ((args[1] == "cmake_autorcc") && (args.size() >= 3)) { cm::string_view const infoFile = args[2]; cm::string_view const config = (args.size() > 3) ? cm::string_view(args[3]) : cm::string_view(); - return cmQtAutoRcc(infoFile, config) ? 0 : 1; + cm::string_view const executableConfig = + (args.size() >= 5) ? cm::string_view(args[4]) : cm::string_view(); + return cmQtAutoRcc(infoFile, config, executableConfig) ? 0 : 1; } #endif diff --git a/Tests/RunCMake/Autogen/AutoMocExecutableConfig.cmake b/Tests/RunCMake/Autogen/AutoMocExecutableConfig.cmake new file mode 100644 index 0000000..fd3614c --- /dev/null +++ b/Tests/RunCMake/Autogen/AutoMocExecutableConfig.cmake @@ -0,0 +1,24 @@ +enable_language(CXX) + +set(CMAKE_CXX_STANDARD 11) +find_package(Qt${with_qt_version} REQUIRED COMPONENTS Core Widgets Gui) + +if(NOT TARGET Qt${with_qt_version}::moc) + message(FATAL_ERROR "Qt${with_qt_version}::moc not found") +endif() + +add_library(dummy STATIC example.cpp) +target_link_libraries(dummy Qt${with_qt_version}::Core + Qt${with_qt_version}::Widgets + Qt${with_qt_version}::Gui) + +get_target_property(moc_location Qt${with_qt_version}::moc IMPORTED_LOCATION) +set_target_properties(dummy PROPERTIES AUTOMOC_MOC_OPTIONS "EXE_PATH=${moc_location}") + +add_executable(mymoc $<$:exe_debug.cpp> + $<$:exe_release.cpp> + $<$:exe_relwithdebinfo.cpp> +) + +set_target_properties(dummy PROPERTIES AUTOMOC_EXECUTABLE $ + AUTOMOC ON) diff --git a/Tests/RunCMake/Autogen/AutoRccExecutableConfig.cmake b/Tests/RunCMake/Autogen/AutoRccExecutableConfig.cmake new file mode 100644 index 0000000..a0e9ce9 --- /dev/null +++ b/Tests/RunCMake/Autogen/AutoRccExecutableConfig.cmake @@ -0,0 +1,24 @@ +enable_language(CXX) + +set(CMAKE_CXX_STANDARD 11) +find_package(Qt${with_qt_version} REQUIRED COMPONENTS Core Widgets Gui) + +if(NOT TARGET Qt${with_qt_version}::rcc) + message(FATAL_ERROR "Qt${with_qt_version}::rcc not found") +endif() + +add_library(dummy STATIC example.cpp data.qrc) +target_link_libraries(dummy Qt${with_qt_version}::Core + Qt${with_qt_version}::Widgets + Qt${with_qt_version}::Gui) + +get_target_property(rcc_location Qt${with_qt_version}::rcc IMPORTED_LOCATION) +set_target_properties(dummy PROPERTIES AUTORCC_OPTIONS "EXE_PATH=${rcc_location}") + +add_executable(myrcc $<$:exe_debug.cpp> + $<$:exe_release.cpp> + $<$:exe_relwithdebinfo.cpp> +) + +set_target_properties(dummy PROPERTIES AUTORCC_EXECUTABLE $ + AUTORCC ON) diff --git a/Tests/RunCMake/Autogen/AutoUicExecutableConfig.cmake b/Tests/RunCMake/Autogen/AutoUicExecutableConfig.cmake new file mode 100644 index 0000000..ce7675e --- /dev/null +++ b/Tests/RunCMake/Autogen/AutoUicExecutableConfig.cmake @@ -0,0 +1,24 @@ +enable_language(CXX) + +set(CMAKE_CXX_STANDARD 11) +find_package(Qt${with_qt_version} REQUIRED COMPONENTS Core Widgets Gui) + +if(NOT TARGET Qt${with_qt_version}::uic) + message(FATAL_ERROR "Qt${with_qt_version}::uic not found") +endif() + +add_library(dummy STATIC example_ui.cpp uiA.ui) +target_link_libraries(dummy Qt${with_qt_version}::Core + Qt${with_qt_version}::Widgets + Qt${with_qt_version}::Gui) + +get_target_property(uic_location Qt${with_qt_version}::uic IMPORTED_LOCATION) +set_target_properties(dummy PROPERTIES AUTOUIC_OPTIONS "EXE_PATH=${uic_location}") + +add_executable(myuic $<$:exe_debug.cpp> + $<$:exe_release.cpp> + $<$:exe_relwithdebinfo.cpp> +) + +set_target_properties(dummy PROPERTIES AUTOUIC_EXECUTABLE $ + AUTOUIC ON) diff --git a/Tests/RunCMake/Autogen/RunCMakeTest.cmake b/Tests/RunCMake/Autogen/RunCMakeTest.cmake index 886065a..12a8f8e 100644 --- a/Tests/RunCMake/Autogen/RunCMakeTest.cmake +++ b/Tests/RunCMake/Autogen/RunCMakeTest.cmake @@ -173,4 +173,168 @@ Automatic MOC for target sub_exe_2") endif() endblock() endif() + + function(run_make_program dir) + execute_process( + COMMAND "${RunCMake_MAKE_PROGRAM}" ${ARGN} + WORKING_DIRECTORY "${dir}" + OUTPUT_VARIABLE make_program_stdout + ERROR_VARIABLE make_program_stderr + RESULT_VARIABLE make_program_result + ) + if (NOT DEFINED RunMakeProgram_expected_result) + set(RunMakeProgram_expected_result 0) + endif() + if(NOT "${make_program_result}" MATCHES "${RunMakeProgram_expected_result}") + message(STATUS " +============ beginning of ${RunCMake_MAKE_PROGRAM}'s stdout ============ +${make_program_stdout} +=============== end of ${RunCMake_MAKE_PROGRAM}'s stdout =============== +") + message(STATUS " +============ beginning of ${RunCMake_MAKE_PROGRAM}'s stderr ============ +${make_program_stderr} +=============== end of ${RunCMake_MAKE_PROGRAM}'s stderr =============== +") + message(FATAL_ERROR + "top ${RunCMake_MAKE_PROGRAM} build failed exited with status ${make_program_result}") + endif() + set(make_program_stdout "${make_program_stdout}" PARENT_SCOPE) + endfunction(run_make_program) + + function(count_substring STRING SUBSTRING COUNT_VAR) + string(LENGTH "${STRING}" STRING_LENGTH) + string(LENGTH "${SUBSTRING}" SUBSTRING_LENGTH) + if (SUBSTRING_LENGTH EQUAL 0) + message(FATAL_ERROR "SUBSTRING_LENGTH is 0") + endif() + + if (STRING_LENGTH EQUAL 0) + message(FATAL_ERROR "STRING_LENGTH is 0") + endif() + + if (STRING_LENGTH LESS SUBSTRING_LENGTH) + message(FATAL_ERROR "STRING_LENGTH is less than SUBSTRING_LENGTH") + endif() + + set(COUNT 0) + string(FIND "${STRING}" "${SUBSTRING}" SUBSTRING_START) + while(SUBSTRING_START GREATER_EQUAL 0) + math(EXPR COUNT "${COUNT} + 1") + math(EXPR SUBSTRING_START "${SUBSTRING_START} + ${SUBSTRING_LENGTH}") + string(SUBSTRING "${STRING}" ${SUBSTRING_START} -1 STRING) + string(FIND "${STRING}" "${SUBSTRING}" SUBSTRING_START) + endwhile() + + set(${COUNT_VAR} ${COUNT} PARENT_SCOPE) + endfunction() + + function(expect_only_once make_program_stdout expected_output test_name) + count_substring("${make_program_stdout}" "${expected_output}" count) + if(NOT count EQUAL 1) + message(STATUS "${test_name}-expect_only_once - FAILED") + message(FATAL_ERROR "Expected to find ${expected_output} exactly once in ${make_program_stdout} but found ${count} occurrences of ${expected_output}") + else() + message(STATUS "${test_name}-expect_only_once - PASSED") + endif() + endfunction() + + function(not_expect make_program_stdout unexpected_output test_name) + count_substring("${make_program_stdout}" "${unexpected_output}" count) + if(NOT count EQUAL 0) + message(STATUS "${test_name}-not_expect - FAILED") + message(FATAL_ERROR "Expected to find ${unexpected_output} exactly 0 times in ${make_program_stdout} but found ${count} occurrences of ${unexpected_output}") + else() + message(STATUS "${test_name}-not_expect - PASSED") + endif() + endfunction() + + if (QtCore_VERSION VERSION_GREATER_EQUAL 5.15.0) + foreach(exe IN ITEMS Moc Uic Rcc) + if(RunCMake_GENERATOR MATCHES "Ninja Multi-Config") + block() + set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/Auto${exe}ExecutableConfig-build) + run_cmake_with_options(Auto${exe}ExecutableConfig ${RunCMake_TEST_OPTIONS} -DCMAKE_AUTOGEN_VERBOSE=ON) + foreach(config IN ITEMS Debug Release RelWithDebInfo) + block() + run_make_program(${RunCMake_TEST_BINARY_DIR} --verbose -f build-${config}.ninja) + + set(expected_output "running_exe_${config}") + expect_only_once("${make_program_stdout}" "${expected_output}" "Auto${exe}ExecutableConfig-${config}-${expected_output}") + + foreach(sub_config IN ITEMS Debug Release RelWithDebInfo) + if(NOT sub_config STREQUAL config) + set(unexpected_output "running_exe_${sub_config}") + not_expect("${make_program_stdout}" "${unexpected_output}" "Auto${exe}ExecutableConfig-${config}-${unexpected_output}") + endif() + endforeach() + + if (exe STREQUAL "Moc" OR exe STREQUAL "Uic") + set(expected_output "cmake_autogen") + else() + set(expected_output "cmake_autorcc") + endif() + expect_only_once("${make_program_stdout}" "${expected_output}" "Auto${exe}ExecutableConfig-${config}-${expected_output}") + endblock() + endforeach() + endblock() + block() + foreach(ninja_config IN ITEMS Debug Release RelWithDebInfo) + foreach(target_config IN ITEMS Debug Release RelWithDebInfo) + block() + set(TEST_SUFFIX "-CrossConfig-${ninja_config}-${target_config}") + set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/Auto${exe}ExecutableConfig${TEST_SUFFIX}-build) + set(RunCMake_TEST_VARIANT_DESCRIPTION ${TEST_SUFFIX}) + run_cmake_with_options(Auto${exe}ExecutableConfig ${RunCMake_TEST_OPTIONS} -DCMAKE_CROSS_CONFIGS=all -DCMAKE_DEFAULT_BUILD_TYPE=${ninja_config}) + unset(RunCMake_TEST_VARIANT_DESCRIPTION) + + run_make_program(${RunCMake_TEST_BINARY_DIR} --verbose -f build-${ninja_config}.ninja dummy:${target_config}) + + set(expected_output "running_exe_${ninja_config}") + expect_only_once("${make_program_stdout}" "${expected_output}" "Auto${exe}ExecutableConfig${TEST_SUFFIX}-${expected_output}") + + foreach(sub_config IN ITEMS Debug Release RelWithDebInfo) + if(NOT sub_config STREQUAL ninja_config) + set(unexpected_output "running_exe_${sub_config}") + not_expect("${make_program_stdout}" "${unexpected_output}" "Auto${exe}ExecutableConfig${TEST_SUFFIX}-${unexpected_output}") + endif() + endforeach() + + if (exe STREQUAL "Moc" OR exe STREQUAL "Uic") + set(expected_output "cmake_autogen") + else() + set(expected_output "cmake_autorcc") + endif() + expect_only_once("${make_program_stdout}" "${expected_output}" "Auto${exe}ExecutableConfig${TEST_SUFFIX}-${expected_output}") + endblock() + endforeach() + endforeach() + endblock() + block() + foreach(ninja_config IN ITEMS Debug Release RelWithDebInfo) + set(TEST_SUFFIX "-CrossConfig-${ninja_config}-all-all") + set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/Auto${exe}ExecutableConfig${TEST_SUFFIX}-build) + set(RunCMake_TEST_VARIANT_DESCRIPTION ${TEST_SUFFIX}) + run_cmake_with_options(Auto${exe}ExecutableConfig ${RunCMake_TEST_OPTIONS} -DCMAKE_CROSS_CONFIGS=all) + unset(RunCMake_TEST_VARIANT_DESCRIPTION) + run_make_program(${RunCMake_TEST_BINARY_DIR} --verbose -f build-${ninja_config}.ninja all:all) + endforeach() + endblock() + elseif (RunCMake_GENERATOR MATCHES "Ninja|Make") + block() + set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/Auto${exe}ExecutableConfig-build) + foreach(config IN ITEMS Debug Release RelWithDebInfo) + block() + set(RunCMake_TEST_VARIANT_DESCRIPTION "-${config}") + run_cmake_with_options(Auto${exe}ExecutableConfig ${RunCMake_TEST_OPTIONS} -DCMAKE_BUILD_TYPE=${config} -DCMAKE_AUTOGEN_VERBOSE=ON) + unset(RunCMake_TEST_VARIANT_DESCRIPTION) + set(RunCMake_TEST_NO_CLEAN 1) + set(RunCMake_TEST_EXPECT_stdout ".*running_exe_${config}*") + run_cmake_command(Auto${exe}ExecutableConfig-${config}-build ${CMAKE_COMMAND} --build .) + endblock() + endforeach() + endblock() + endif() + endforeach() + endif() endif () diff --git a/Tests/RunCMake/Autogen/data.qrc b/Tests/RunCMake/Autogen/data.qrc new file mode 100644 index 0000000..9bd068c --- /dev/null +++ b/Tests/RunCMake/Autogen/data.qrc @@ -0,0 +1,4 @@ + + + + diff --git a/Tests/RunCMake/Autogen/example.cpp b/Tests/RunCMake/Autogen/example.cpp new file mode 100644 index 0000000..7f1a781 --- /dev/null +++ b/Tests/RunCMake/Autogen/example.cpp @@ -0,0 +1,5 @@ +#include "example.h" + +Example::Example() +{ +} diff --git a/Tests/RunCMake/Autogen/example.h b/Tests/RunCMake/Autogen/example.h new file mode 100644 index 0000000..e8bfa42 --- /dev/null +++ b/Tests/RunCMake/Autogen/example.h @@ -0,0 +1,12 @@ +#ifndef EXAMPLE_H +#define EXAMPLE_H + +#include + +class Example : public QObject +{ + Q_OBJECT + Example(); +}; + +#endif diff --git a/Tests/RunCMake/Autogen/example_ui.cpp b/Tests/RunCMake/Autogen/example_ui.cpp new file mode 100644 index 0000000..fb97c32 --- /dev/null +++ b/Tests/RunCMake/Autogen/example_ui.cpp @@ -0,0 +1,5 @@ +#include "example_ui.h" + +Example::Example() +{ +} diff --git a/Tests/RunCMake/Autogen/example_ui.h b/Tests/RunCMake/Autogen/example_ui.h new file mode 100644 index 0000000..d691133 --- /dev/null +++ b/Tests/RunCMake/Autogen/example_ui.h @@ -0,0 +1,14 @@ +#ifndef EXAMPLE_UI_H +#define EXAMPLE_UI_H + +#include + +#include "ui_uiA.h" + +class Example : public QObject +{ + Q_OBJECT + Example(); +}; + +#endif diff --git a/Tests/RunCMake/Autogen/exe.cpp b/Tests/RunCMake/Autogen/exe.cpp new file mode 100644 index 0000000..f8b643a --- /dev/null +++ b/Tests/RunCMake/Autogen/exe.cpp @@ -0,0 +1,4 @@ +int main() +{ + return 0; +} diff --git a/Tests/RunCMake/Autogen/exe_common.h b/Tests/RunCMake/Autogen/exe_common.h new file mode 100644 index 0000000..15311c6 --- /dev/null +++ b/Tests/RunCMake/Autogen/exe_common.h @@ -0,0 +1,48 @@ +#ifndef EXE_COMMON_H +#define EXE_COMMON_H + +#include +#include +#include +#include + +inline int runRealExe(const int argc, char** argv) +{ + std::vector args; + std::string realMocPath; + std::string const pathArg = "EXE_PATH="; + std::string cmd; + if (argc > 1) { + for (int i = 1; i < argc; ++i) { + std::string const arg = argv[i]; + if (arg.find(pathArg) != std::string::npos) { + realMocPath = arg.substr(pathArg.length()); + // if EXE_PATH contains spaces, wrap it in quotes + if (realMocPath.find(" ") != std::string::npos) { + realMocPath = "\"" + realMocPath + "\""; + } + } else { + args.push_back(arg); + } + } + } +#ifdef _WIN32 + cmd += "cmd /C \""; +#endif + cmd += realMocPath + " "; + for (auto arg : args) { + // if arg contains spaces, wrap it in quotes + if (arg.find(' ') != std::string::npos) { + cmd += " \"" + arg + "\""; + } else { + cmd += " " + arg; + } + } +#ifdef _WIN32 + cmd += "\""; +#endif + std::cout << "Running real exe:" << cmd << std::endl; + return std::system(cmd.c_str()); +} + +#endif diff --git a/Tests/RunCMake/Autogen/exe_debug.cpp b/Tests/RunCMake/Autogen/exe_debug.cpp new file mode 100644 index 0000000..ae5185b --- /dev/null +++ b/Tests/RunCMake/Autogen/exe_debug.cpp @@ -0,0 +1,10 @@ +#include +#include + +#include "exe_common.h" + +int main(int argc, char* argv[]) +{ + std::cout << "running_exe_Debug\n"; + return runRealExe(argc, argv); +} diff --git a/Tests/RunCMake/Autogen/exe_release.cpp b/Tests/RunCMake/Autogen/exe_release.cpp new file mode 100644 index 0000000..384c992 --- /dev/null +++ b/Tests/RunCMake/Autogen/exe_release.cpp @@ -0,0 +1,10 @@ +#include +#include + +#include "exe_common.h" + +int main(int argc, char* argv[]) +{ + std::cout << "running_exe_Release\n"; + return runRealExe(argc, argv); +} diff --git a/Tests/RunCMake/Autogen/exe_relwithdebinfo.cpp b/Tests/RunCMake/Autogen/exe_relwithdebinfo.cpp new file mode 100644 index 0000000..aa6c558 --- /dev/null +++ b/Tests/RunCMake/Autogen/exe_relwithdebinfo.cpp @@ -0,0 +1,10 @@ +#include +#include + +#include "exe_common.h" + +int main(int argc, char* argv[]) +{ + std::cout << "running_exe_RelWithDebInfo\n"; + return runRealExe(argc, argv); +} diff --git a/Tests/RunCMake/Autogen/uiA.ui b/Tests/RunCMake/Autogen/uiA.ui new file mode 100644 index 0000000..4c5762e --- /dev/null +++ b/Tests/RunCMake/Autogen/uiA.ui @@ -0,0 +1,24 @@ + + + UiA + + + + 0 + 0 + 400 + 300 + + + + Form + + + + + + + + + + -- cgit v0.12 From e454314daaed0ab5f86bba0015747eb296efb8da Mon Sep 17 00:00:00 2001 From: Orkun Tokdemir Date: Wed, 5 Jul 2023 12:12:50 +0200 Subject: NinjaMultiConfig: Update tests for the new dependency change --- .../QtX-debug-in-release-graph-build-check.cmake | 7 ----- Tests/RunCMake/NinjaMultiConfig/QtX.cmake | 21 ++++++------- Tests/RunCMake/NinjaMultiConfig/RunCMakeTest.cmake | 34 ++++++++++++++++++---- 3 files changed, 40 insertions(+), 22 deletions(-) delete mode 100644 Tests/RunCMake/NinjaMultiConfig/QtX-debug-in-release-graph-build-check.cmake diff --git a/Tests/RunCMake/NinjaMultiConfig/QtX-debug-in-release-graph-build-check.cmake b/Tests/RunCMake/NinjaMultiConfig/QtX-debug-in-release-graph-build-check.cmake deleted file mode 100644 index 2d8df13..0000000 --- a/Tests/RunCMake/NinjaMultiConfig/QtX-debug-in-release-graph-build-check.cmake +++ /dev/null @@ -1,7 +0,0 @@ -check_files("${RunCMake_TEST_BINARY_DIR}" - INCLUDE - ${AUTOGEN_FILES} - - ${TARGET_FILE_exe_Debug} - ${TARGET_OBJECT_FILES_exe_Debug} - ) diff --git a/Tests/RunCMake/NinjaMultiConfig/QtX.cmake b/Tests/RunCMake/NinjaMultiConfig/QtX.cmake index 130f883..dded383 100644 --- a/Tests/RunCMake/NinjaMultiConfig/QtX.cmake +++ b/Tests/RunCMake/NinjaMultiConfig/QtX.cmake @@ -19,16 +19,17 @@ if(${QtX}Core_VERSION VERSION_GREATER_EQUAL "5.15.0") set(moc_writes_depfiles 1) endif() -set(autogen_files) -if(moc_writes_depfiles) - list(APPEND autogen_files "${CMAKE_BINARY_DIR}/exe_autogen/deps") - list(APPEND autogen_files "${CMAKE_BINARY_DIR}/exe_autogen/timestamp") -endif() -foreach(c IN LISTS CMAKE_CONFIGURATION_TYPES) - list(APPEND autogen_files "${CMAKE_BINARY_DIR}/exe_autogen/mocs_compilation_${c}.cpp") - list(APPEND autogen_files "${CMAKE_BINARY_DIR}/exe_autogen/include_${c}/moc_qt5.cpp") +foreach(CONFIG IN LISTS CMAKE_CONFIGURATION_TYPES) + set(autogen_files) if(moc_writes_depfiles) - list(APPEND autogen_files "${CMAKE_BINARY_DIR}/exe_autogen/include_${c}/moc_qt5.cpp.d") + list(APPEND autogen_files "${CMAKE_BINARY_DIR}/exe_autogen/deps_${CONFIG}") + list(APPEND autogen_files "${CMAKE_BINARY_DIR}/exe_autogen/timestamp_${CONFIG}") endif() + list(APPEND autogen_files "${CMAKE_BINARY_DIR}/exe_autogen/mocs_compilation_${CONFIG}.cpp") + list(APPEND autogen_files "${CMAKE_BINARY_DIR}/exe_autogen/include_${CONFIG}/moc_qt5.cpp") + if(moc_writes_depfiles) + list(APPEND autogen_files "${CMAKE_BINARY_DIR}/exe_autogen/include_${CONFIG}/moc_qt5.cpp.d") + endif() + file(APPEND "${CMAKE_BINARY_DIR}/target_files.cmake" "set(AUTOGEN_FILES_${CONFIG} [==[${autogen_files}]==])\n") + unset(autogen_files) endforeach() -file(APPEND "${CMAKE_BINARY_DIR}/target_files.cmake" "set(AUTOGEN_FILES [==[${autogen_files}]==])\n") diff --git a/Tests/RunCMake/NinjaMultiConfig/RunCMakeTest.cmake b/Tests/RunCMake/NinjaMultiConfig/RunCMakeTest.cmake index 47f5eee..7128aaf 100644 --- a/Tests/RunCMake/NinjaMultiConfig/RunCMakeTest.cmake +++ b/Tests/RunCMake/NinjaMultiConfig/RunCMakeTest.cmake @@ -486,11 +486,35 @@ if(CMake_TEST_Qt_version) "-D${QtX}Core_DIR=${${QtX}Core_DIR}" "-DCMAKE_PREFIX_PATH:STRING=${CMAKE_PREFIX_PATH}" ) - run_cmake_configure(QtX) - unset(RunCMake_TEST_OPTIONS) - include(${RunCMake_TEST_BINARY_DIR}/target_files.cmake) - run_cmake_build(QtX debug-in-release-graph Release exe:Debug) + + foreach(target_config IN ITEMS Debug Release RelWithDebInfo) + foreach(ninja_config IN ITEMS Debug Release RelWithDebInfo) + block() + run_cmake_configure(QtX) + include(${RunCMake_TEST_BINARY_DIR}/target_files.cmake) + run_cmake_build(QtX ${target_config}-in-${ninja_config}-graph ${ninja_config} exe:${target_config}) + check_files("${RunCMake_TEST_BINARY_DIR}" + INCLUDE + "${AUTOGEN_FILES_${target_config}}" + "${TARGET_FILE_exe_${target_config}}" + "${TARGET_OBJECT_FILES_exe_${target_config}}" + ) + if (DEFINED RunCMake_TEST_FAILED AND NOT RunCMake_TEST_FAILED STREQUAL "") + message(FATAL_ERROR "RunCMake_TEST_FAILED:${RunCMake_TEST_FAILED}") + endif() + + check_file_contents("${RunCMake_TEST_BINARY_DIR}/exe_autogen/deps_${target_config}" "exe_autogen/timestamp_${target_config}") + if (DEFINED RunCMake_TEST_FAILED AND NOT RunCMake_TEST_FAILED STREQUAL "") + message(FATAL_ERROR "RunCMake_TEST_FAILED:${RunCMake_TEST_FAILED}") + endif() + endblock() + endforeach() + endforeach() if(CMake_TEST_${QtX}Core_Version VERSION_GREATER_EQUAL 5.15.0) - run_ninja(QtX automoc-check build-Debug.ninja -t query exe_autogen/timestamp) + foreach(target_config IN ITEMS Debug Release RelWithDebInfo) + foreach(ninja_config IN ITEMS Debug Release RelWithDebInfo) + run_ninja(QtX automoc-check-${target_config} build-${ninja_config}.ninja -t query exe_autogen/timestamp_${target_config}) + endforeach() + endforeach() endif() endif() -- cgit v0.12