diff options
author | Joerg Bornemann <joerg.bornemann@qt.io> | 2021-04-20 19:17:50 (GMT) |
---|---|---|
committer | Joerg Bornemann <joerg.bornemann@qt.io> | 2021-04-23 08:49:07 (GMT) |
commit | 5b0ea5874a3322e57156b329b340bf283673c207 (patch) | |
tree | ee25d305166e04e92251c847bf502846b69780e4 /Source/cmQtAutoGenInitializer.cxx | |
parent | 63ffe210365ce2d1dd67fcabcc67e20913f320a8 (diff) | |
download | CMake-5b0ea5874a3322e57156b329b340bf283673c207.zip CMake-5b0ea5874a3322e57156b329b340bf283673c207.tar.gz CMake-5b0ea5874a3322e57156b329b340bf283673c207.tar.bz2 |
AutoGen: Retrieve Qt version from moc as fallback
Consider the case where the find_package call for QtCore is wrapped in a
function call. Then AutoGen cannot determine the Qt version, because it
only looks at variables and directory properties. The former don't leave
the function scope and the latter are not set by default.
As a fallback, locate the moc executable via its target and call it with
the --version argument to determine the Qt version.
Issue: #22028
Diffstat (limited to 'Source/cmQtAutoGenInitializer.cxx')
-rw-r--r-- | Source/cmQtAutoGenInitializer.cxx | 74 |
1 files changed, 72 insertions, 2 deletions
diff --git a/Source/cmQtAutoGenInitializer.cxx b/Source/cmQtAutoGenInitializer.cxx index 3adeb1a..148591c 100644 --- a/Source/cmQtAutoGenInitializer.cxx +++ b/Source/cmQtAutoGenInitializer.cxx @@ -6,8 +6,8 @@ #include <deque> #include <initializer_list> #include <map> -#include <ostream> #include <set> +#include <sstream> // for basic_ios, istringstream #include <string> #include <unordered_set> #include <utility> @@ -1833,8 +1833,63 @@ void cmQtAutoGenInitializer::ConfigFileClean(ConfigString& configString) } } +static cmQtAutoGen::IntegerVersion parseMocVersion(std::string str) +{ + cmQtAutoGen::IntegerVersion result; + + static const std::string prelude = "moc "; + size_t pos = str.find(prelude); + if (pos == std::string::npos) { + return result; + } + + str.erase(0, prelude.size() + pos); + std::istringstream iss(str); + std::string major; + std::string minor; + if (!std::getline(iss, major, '.') || !std::getline(iss, minor, '.')) { + return result; + } + + result.Major = static_cast<unsigned int>(std::stoi(major)); + result.Minor = static_cast<unsigned int>(std::stoi(minor)); + return result; +} + +static cmQtAutoGen::IntegerVersion GetMocVersion( + const std::string& mocExecutablePath) +{ + std::string capturedStdOut; + int exitCode; + if (!cmSystemTools::RunSingleCommand({ mocExecutablePath, "--version" }, + &capturedStdOut, nullptr, &exitCode, + nullptr, cmSystemTools::OUTPUT_NONE)) { + return {}; + } + + if (exitCode != 0) { + return {}; + } + + return parseMocVersion(capturedStdOut); +} + +static std::string FindMocExecutableFromMocTarget(cmMakefile* makefile, + unsigned int qtMajorVersion) +{ + std::string result; + const std::string mocTargetName = + "Qt" + std::to_string(qtMajorVersion) + "::moc"; + cmTarget* mocTarget = makefile->FindTargetToUse(mocTargetName); + if (mocTarget) { + result = mocTarget->GetSafeProperty("IMPORTED_LOCATION"); + } + return result; +} + std::pair<cmQtAutoGen::IntegerVersion, unsigned int> -cmQtAutoGenInitializer::GetQtVersion(cmGeneratorTarget const* target) +cmQtAutoGenInitializer::GetQtVersion(cmGeneratorTarget const* target, + std::string mocExecutable) { // Converts a char ptr to an unsigned int value auto toUInt = [](const char* const input) -> unsigned int { @@ -1909,6 +1964,21 @@ cmQtAutoGenInitializer::GetQtVersion(cmGeneratorTarget const* target) } } } + + if (res.first.Major == 0) { + // We could not get the version number from variables or directory + // properties. This might happen if the find_package call for Qt is wrapped + // in a function. Try to find the moc executable path from the available + // targets and call "moc --version" to get the Qt version. + if (mocExecutable.empty()) { + mocExecutable = + FindMocExecutableFromMocTarget(target->Makefile, res.second); + } + if (!mocExecutable.empty()) { + res.first = GetMocVersion(mocExecutable); + } + } + return res; } |