Commit cd32886b authored by Tobias Hunger's avatar Tobias Hunger Committed by Brad King

Autogen: Add AUTO(MOC|RCC|UIC)_EXECUTABLE target properties

Allow to force moc/rcc/uic compiler used for AUTO(MOC|RCC|UIC).

Setting these properties is only necessary if you are going to do
strange things like build these tools as part of your own build system.

Setting these properties will also prevent cmake from testing the
binary: It is user-provided and assumed to be valid.
parent 9045f6a3
......@@ -129,13 +129,16 @@ Properties on Targets
/prop_tgt/AUTOGEN_TARGET_DEPENDS
/prop_tgt/AUTOMOC_COMPILER_PREDEFINES
/prop_tgt/AUTOMOC_DEPEND_FILTERS
/prop_tgt/AUTOMOC_EXECUTABLE
/prop_tgt/AUTOMOC_MACRO_NAMES
/prop_tgt/AUTOMOC_MOC_OPTIONS
/prop_tgt/AUTOMOC
/prop_tgt/AUTOUIC
/prop_tgt/AUTOUIC_EXECUTABLE
/prop_tgt/AUTOUIC_OPTIONS
/prop_tgt/AUTOUIC_SEARCH_PATHS
/prop_tgt/AUTORCC
/prop_tgt/AUTORCC_EXECUTABLE
/prop_tgt/AUTORCC_OPTIONS
/prop_tgt/BINARY_DIR
/prop_tgt/BUILD_RPATH
......
......@@ -58,6 +58,9 @@ source files at build time and invoke moc accordingly.
This property is initialized by the value of the :variable:`CMAKE_AUTOMOC`
variable if it is set when a target is created.
The ``moc`` executable will be detected automatically, but can be forced to
a certain binary using the :prop_tgt:`AUTOMOC_EXECUTABLE` property.
Additional command line options for ``moc`` can be set via the
:prop_tgt:`AUTOMOC_MOC_OPTIONS` property.
......
AUTOMOC_EXECUTABLE
------------------
:prop_tgt:`AUTOMOC_EXECUTABLE` is file path pointing to the ``moc``
executable to use for :prop_tgt:`AUTOMOC` enabled files. Setting
this property will make CMake skip the automatic detection of the
``moc`` binary as well as the sanity-tests normally run to ensure
that the binary is available and working as expected.
Usually this property does not need to be set. Only consider this
property if auto-detection of ``moc`` can not work -- e.g. because
you are building the ``moc`` binary as part of your project.
See the :manual:`cmake-qt(7)` manual for more information on using CMake
with Qt.
......@@ -21,6 +21,9 @@ If the ``.qrc`` file is :prop_sf:`GENERATED` though, a
Additional command line options for rcc can be set via the
:prop_sf:`AUTORCC_OPTIONS` source file property on the ``.qrc`` file.
The ``rcc`` executable will be detected automatically, but can be forced to
a certain binary using the :prop_tgt:`AUTORCC_EXECUTABLE` property.
The global property :prop_gbl:`AUTOGEN_TARGETS_FOLDER` can be used to group
the autorcc targets together in an IDE, e.g. in MSVS.
......
AUTORCC_EXECUTABLE
------------------
:prop_tgt:`AUTORCC_EXECUTABLE` is file path pointing to the ``rcc``
executable to use for :prop_tgt:`AUTORCC` enabled files. Setting
this property will make CMake skip the automatic detection of the
``rcc`` binary as well as the sanity-tests normally run to ensure
that the binary is available and working as expected.
Usually this property does not need to be set. Only consider this
property if auto-detection of ``rcc`` can not work -- e.g. because
you are building the ``rcc`` binary as part of your project.
See the :manual:`cmake-qt(7)` manual for more information on using CMake
with Qt.
......@@ -30,6 +30,9 @@ Additional command line options for ``uic`` can be set via the
The global property :prop_gbl:`AUTOGEN_TARGETS_FOLDER` can be used to group the
autouic targets together in an IDE, e.g. in MSVS.
The ``uic`` executable will be detected automatically, but can be forced to
a certain binary using the :prop_tgt:`AUTOUIC_EXECUTABLE` property.
Source files can be excluded from :prop_tgt:`AUTOUIC` processing by
enabling :prop_sf:`SKIP_AUTOUIC` or the broader :prop_sf:`SKIP_AUTOGEN`.
......
AUTOUIC_EXECUTABLE
------------------
:prop_tgt:`AUTOUIC_EXECUTABLE` is file path pointing to the ``uic``
executable to use for :prop_tgt:`AUTOUIC` enabled files. Setting
this property will make CMake skip the automatic detection of the
``uic`` binary as well as the sanity-tests normally run to ensure
that the binary is available and working as expected.
Usually this property does not need to be set. Only consider this
property if auto-detection of ``uic`` can not work -- e.g. because
you are building the ``uic`` binary as part of your project.
See the :manual:`cmake-qt(7)` manual for more information on using CMake
with Qt.
AUTO*_EXECUTABLE
----------------
* The :prop_tgt:`AUTOMOC_EXECUTABLE`, :prop_tgt:`AUTORCC_EXECUTABLE` and
:prop_tgt:`AUTOUIC_EXECUTABLE` target properties all take a path to an
executable and force automoc/autorcc/autouic to use this executable.
Setting these will also prevent the configure time testing for these
executables. This is mainly useful when you build these tools yourself.
......@@ -75,14 +75,26 @@ cmQtAutoGenGlobalInitializer::cmQtAutoGenGlobalInitializer(
bool const uic = target->GetPropertyAsBool("AUTOUIC");
bool const rcc = target->GetPropertyAsBool("AUTORCC");
if (moc || uic || rcc) {
// We support Qt4 and Qt5
std::string const mocExec =
target->GetSafeProperty("AUTOMOC_EXECUTABLE");
std::string const uicExec =
target->GetSafeProperty("AUTOUIC_EXECUTABLE");
std::string const rccExec =
target->GetSafeProperty("AUTORCC_EXECUTABLE");
// We support Qt4, Qt5 and Qt6
auto qtVersion = cmQtAutoGenInitializer::GetQtVersion(target);
if ((qtVersion.Major == 4) || (qtVersion.Major == 5) ||
(qtVersion.Major == 6)) {
bool const validQt = (qtVersion.Major == 4) ||
(qtVersion.Major == 5) || (qtVersion.Major == 6);
bool const mocIsValid = moc && (validQt || !mocExec.empty());
bool const uicIsValid = uic && (validQt || !uicExec.empty());
bool const rccIsValid = rcc && (validQt || !rccExec.empty());
if (mocIsValid || uicIsValid || rccIsValid) {
// Create autogen target initializer
Initializers_.emplace_back(cm::make_unique<cmQtAutoGenInitializer>(
this, target, qtVersion, moc, uic, rcc, globalAutoGenTarget,
globalAutoRccTarget));
this, target, qtVersion, mocIsValid, uicIsValid, rccIsValid,
globalAutoGenTarget, globalAutoRccTarget));
}
}
}
......
......@@ -9,6 +9,7 @@
#include "cmCustomCommandLines.h"
#include "cmDuration.h"
#include "cmFilePathChecksum.h"
#include "cmGeneratorExpression.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalGenerator.h"
#include "cmLinkItem.h"
......@@ -398,8 +399,16 @@ bool cmQtAutoGenInitializer::InitCustomTargets()
}
// Init uic specific settings
if (this->Uic.Enabled && !InitUic()) {
return false;
if (this->Uic.Enabled) {
if (InitUic()) {
auto* uicTarget = makefile->FindTargetToUse(
GetQtExecutableTargetName(this->QtVersion, "uic"));
if (uicTarget != nullptr) {
this->AutogenTarget.DependTargets.insert(uicTarget);
}
} else {
return false;
}
}
// Autogen target name
......@@ -440,6 +449,12 @@ bool cmQtAutoGenInitializer::InitCustomTargets()
this->AutogenTarget.DependOrigin =
this->Target->GetPropertyAsBool("AUTOGEN_ORIGIN_DEPENDS");
auto* mocTarget = makefile->FindTargetToUse(
GetQtExecutableTargetName(this->QtVersion, "moc"));
if (mocTarget != nullptr) {
this->AutogenTarget.DependTargets.insert(mocTarget);
}
std::string const deps =
this->Target->GetSafeProperty("AUTOGEN_TARGET_DEPENDS");
if (!deps.empty()) {
......@@ -1095,6 +1110,7 @@ bool cmQtAutoGenInitializer::InitRccTargets()
{
cmMakefile* makefile = this->Target->Target->GetMakefile();
cmLocalGenerator* localGen = this->Target->GetLocalGenerator();
auto rccTargetName = GetQtExecutableTargetName(this->QtVersion, "rcc");
for (Qrc const& qrc : this->Rcc.Qrcs) {
// Register info file as generated by CMake
......@@ -1105,6 +1121,11 @@ bool cmQtAutoGenInitializer::InitRccTargets()
std::vector<std::string> ccOutput;
ccOutput.push_back(qrc.RccFile);
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);
cmCustomCommandLines commandLines;
if (this->MultiConfig) {
// Build for all configurations
......@@ -1140,15 +1161,12 @@ bool cmQtAutoGenInitializer::InitRccTargets()
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->Dir.Work.c_str(), ccOutput, ccDepends, commandLines, false,
ccComment.c_str());
// Create autogen generator target
localGen->AddGeneratorTarget(
new cmGeneratorTarget(autoRccTarget, localGen));
......@@ -1157,6 +1175,9 @@ bool cmQtAutoGenInitializer::InitRccTargets()
if (!this->TargetsFolder.empty()) {
autoRccTarget->SetProperty("FOLDER", this->TargetsFolder.c_str());
}
if (!rccTargetName.empty()) {
autoRccTarget->AddUtility(rccTargetName, makefile);
}
}
// Add autogen target to the origin target dependencies
this->Target->Target->AddUtility(ccName, makefile);
......@@ -1169,16 +1190,15 @@ bool cmQtAutoGenInitializer::InitRccTargets()
// 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);
// 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 (!rccTargetName.empty()) {
ccDepends.push_back(rccTargetName);
}
makefile->AddCustomCommandToOutput(ccOutput, ccByproducts, ccDepends,
/*main_dependency*/ std::string(),
commandLines, ccComment.c_str(),
......@@ -1421,21 +1441,36 @@ std::pair<bool, std::string> GetQtExecutable(
const cmQtAutoGen::IntegerVersion& qtVersion, cmGeneratorTarget* target,
const std::string& executable, bool ignoreMissingTarget, std::string* output)
{
const std::string upperExecutable = cmSystemTools::UpperCase(executable);
std::string result =
target->Target->GetSafeProperty("AUTO" + upperExecutable + "_EXECUTABLE");
if (!result.empty()) {
cmListFileBacktrace lfbt = target->Target->GetMakefile()->GetBacktrace();
cmGeneratorExpression ge(lfbt);
std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(result);
result = cge->Evaluate(target->GetLocalGenerator(), "");
return std::make_pair(true, result);
}
std::string err;
std::string result;
// Find executable
{
const std::string targetName =
GetQtExecutableTargetName(qtVersion, executable);
if (targetName.empty()) {
err = "The AUTOMOC, AUTOUIC and AUTORCC feature ";
err = "The AUTO" + upperExecutable + " feature ";
err += "supports only Qt 4, Qt 5 and Qt 6.";
} else {
cmLocalGenerator* localGen = target->GetLocalGenerator();
cmGeneratorTarget* tgt = localGen->FindGeneratorTargetToUse(targetName);
if (tgt != nullptr) {
result = tgt->ImportedGetLocation("");
if (tgt->IsImported()) {
result = tgt->ImportedGetLocation("");
} else {
result = tgt->GetLocation("");
}
} else {
if (ignoreMissingTarget) {
return std::make_pair(true, "");
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment