mirror of
https://github.com/Kitware/CMake.git
synced 2026-03-05 14:18:35 -06:00
Merge topic 'autogen-rcc-custom-command'
40434631Autogen: Use integers instead of strings for the Qt versionbe11a852Autogen: Use project relative paths in rcc custom command commentab9d5896Autogen: Detect rcc feature once during configuration2a85b5acAutogen: Make cmQtAutoGeneratorInitializer an instantiable class75819b86Autogen: Add and use cmQtAutoGenerator base class27ed3b35Autogen: Rename cmQtAutoGenerators to cmQtAutoGeneratorMocUic1cd285feAutogen: Remove rcc code from cmQtAutoGeneratorsa87f82e0Autogen: Switch to use custom commands for RCC ... Acked-by: Kitware Robot <kwrobot@kitware.com> Merge-request: !1494
This commit is contained in:
11
Modules/AutoRccInfo.cmake.in
Normal file
11
Modules/AutoRccInfo.cmake.in
Normal file
@@ -0,0 +1,11 @@
|
||||
# Meta
|
||||
set(ARCC_MULTI_CONFIG @_multi_config@)
|
||||
# Directories and files
|
||||
set(ARCC_CMAKE_BINARY_DIR "@CMAKE_BINARY_DIR@/")
|
||||
set(ARCC_CMAKE_SOURCE_DIR "@CMAKE_SOURCE_DIR@/")
|
||||
set(ARCC_CMAKE_CURRENT_SOURCE_DIR "@CMAKE_CURRENT_SOURCE_DIR@/")
|
||||
set(ARCC_CMAKE_CURRENT_BINARY_DIR "@CMAKE_CURRENT_BINARY_DIR@/")
|
||||
set(ARCC_BUILD_DIR @_build_dir@)
|
||||
# Qt environment
|
||||
set(ARCC_RCC_EXECUTABLE @_qt_rcc_executable@)
|
||||
set(ARCC_RCC_LIST_OPTIONS @_qt_rcc_list_options@)
|
||||
@@ -9,12 +9,11 @@ set(AM_CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE "@CMAKE_INCLUDE_DIRECTORIES_PROJ
|
||||
set(AM_BUILD_DIR @_build_dir@)
|
||||
set(AM_SOURCES @_sources@)
|
||||
set(AM_HEADERS @_headers@)
|
||||
set(AM_SETTINGS_FILE @_settings_file@)
|
||||
# Qt environment
|
||||
set(AM_QT_VERSION_MAJOR @_qt_version_major@)
|
||||
set(AM_QT_VERSION_MINOR @_qt_version_minor@)
|
||||
set(AM_QT_MOC_EXECUTABLE @_qt_moc_executable@)
|
||||
set(AM_QT_UIC_EXECUTABLE @_qt_uic_executable@)
|
||||
set(AM_QT_RCC_EXECUTABLE @_qt_rcc_executable@)
|
||||
# MOC settings
|
||||
set(AM_MOC_SKIP @_moc_skip@)
|
||||
set(AM_MOC_DEFINITIONS @_moc_compile_defs@)
|
||||
@@ -30,8 +29,3 @@ set(AM_UIC_TARGET_OPTIONS @_uic_target_options@)
|
||||
set(AM_UIC_OPTIONS_FILES @_qt_uic_options_files@)
|
||||
set(AM_UIC_OPTIONS_OPTIONS @_qt_uic_options_options@)
|
||||
set(AM_UIC_SEARCH_PATHS @_uic_search_paths@)
|
||||
# RCC settings
|
||||
set(AM_RCC_SOURCES @_rcc_files@)
|
||||
set(AM_RCC_BUILDS @_rcc_builds@)
|
||||
set(AM_RCC_OPTIONS @_rcc_options@)
|
||||
set(AM_RCC_INPUTS @_rcc_inputs@)
|
||||
|
||||
@@ -311,11 +311,14 @@ set(SRCS
|
||||
cmPropertyMap.h
|
||||
cmQtAutoGen.cxx
|
||||
cmQtAutoGen.h
|
||||
cmQtAutoGenDigest.h
|
||||
cmQtAutoGenerator.cxx
|
||||
cmQtAutoGenerator.h
|
||||
cmQtAutoGeneratorInitializer.cxx
|
||||
cmQtAutoGeneratorInitializer.h
|
||||
cmQtAutoGenerators.cxx
|
||||
cmQtAutoGenerators.h
|
||||
cmQtAutoGeneratorMocUic.cxx
|
||||
cmQtAutoGeneratorMocUic.h
|
||||
cmQtAutoGeneratorRcc.cxx
|
||||
cmQtAutoGeneratorRcc.h
|
||||
cmRST.cxx
|
||||
cmRST.h
|
||||
cmScriptGenerator.h
|
||||
|
||||
@@ -1314,7 +1314,10 @@ bool cmGlobalGenerator::Compute()
|
||||
#ifdef CMAKE_BUILD_WITH_CMAKE
|
||||
// Iterate through all targets and set up automoc for those which have
|
||||
// the AUTOMOC, AUTOUIC or AUTORCC property set
|
||||
cmQtAutoGenDigestUPV autogenDigests = this->CreateQtAutoGeneratorsTargets();
|
||||
auto autogenInits = this->CreateQtAutoGenInitializers();
|
||||
for (auto& autoGen : autogenInits) {
|
||||
autoGen->InitCustomTargets();
|
||||
}
|
||||
#endif
|
||||
|
||||
// Add generator specific helper commands
|
||||
@@ -1335,10 +1338,11 @@ bool cmGlobalGenerator::Compute()
|
||||
}
|
||||
|
||||
#ifdef CMAKE_BUILD_WITH_CMAKE
|
||||
for (cmQtAutoGenDigestUP const& digest : autogenDigests) {
|
||||
cmQtAutoGeneratorInitializer::SetupAutoGenerateTarget(*digest);
|
||||
for (auto& autoGen : autogenInits) {
|
||||
autoGen->SetupCustomTargets();
|
||||
autoGen.reset(nullptr);
|
||||
}
|
||||
autogenDigests.clear();
|
||||
autogenInits.clear();
|
||||
#endif
|
||||
|
||||
for (cmLocalGenerator* localGen : this->LocalGenerators) {
|
||||
@@ -1469,9 +1473,10 @@ bool cmGlobalGenerator::ComputeTargetDepends()
|
||||
return true;
|
||||
}
|
||||
|
||||
cmQtAutoGenDigestUPV cmGlobalGenerator::CreateQtAutoGeneratorsTargets()
|
||||
std::vector<std::unique_ptr<cmQtAutoGeneratorInitializer>>
|
||||
cmGlobalGenerator::CreateQtAutoGenInitializers()
|
||||
{
|
||||
cmQtAutoGenDigestUPV autogenDigests;
|
||||
std::vector<std::unique_ptr<cmQtAutoGeneratorInitializer>> autogenInits;
|
||||
|
||||
#ifdef CMAKE_BUILD_WITH_CMAKE
|
||||
for (cmLocalGenerator* localGen : this->LocalGenerators) {
|
||||
@@ -1507,25 +1512,12 @@ cmQtAutoGenDigestUPV cmGlobalGenerator::CreateQtAutoGeneratorsTargets()
|
||||
continue;
|
||||
}
|
||||
|
||||
{
|
||||
cmQtAutoGenDigestUP digest(new cmQtAutoGenDigest(target));
|
||||
digest->QtVersionMajor = std::move(qtVersionMajor);
|
||||
digest->QtVersionMinor =
|
||||
cmQtAutoGeneratorInitializer::GetQtMinorVersion(
|
||||
target, digest->QtVersionMajor);
|
||||
digest->MocEnabled = mocEnabled;
|
||||
digest->UicEnabled = uicEnabled;
|
||||
digest->RccEnabled = rccEnabled;
|
||||
autogenDigests.emplace_back(std::move(digest));
|
||||
}
|
||||
autogenInits.emplace_back(new cmQtAutoGeneratorInitializer(
|
||||
target, mocEnabled, uicEnabled, rccEnabled, qtVersionMajor));
|
||||
}
|
||||
}
|
||||
// Initialize autogen targets
|
||||
for (const cmQtAutoGenDigestUP& digest : autogenDigests) {
|
||||
cmQtAutoGeneratorInitializer::InitializeAutogenTarget(*digest);
|
||||
}
|
||||
#endif
|
||||
return autogenDigests;
|
||||
return autogenInits;
|
||||
}
|
||||
|
||||
cmLinkLineComputer* cmGlobalGenerator::CreateLinkLineComputer(
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
|
||||
#include "cmCustomCommandLines.h"
|
||||
#include "cmExportSetMap.h"
|
||||
#include "cmQtAutoGenDigest.h"
|
||||
#include "cmStateSnapshot.h"
|
||||
#include "cmSystemTools.h"
|
||||
#include "cmTarget.h"
|
||||
@@ -33,6 +32,7 @@ class cmLinkLineComputer;
|
||||
class cmLocalGenerator;
|
||||
class cmMakefile;
|
||||
class cmOutputConverter;
|
||||
class cmQtAutoGeneratorInitializer;
|
||||
class cmSourceFile;
|
||||
class cmStateDirectory;
|
||||
class cmake;
|
||||
@@ -433,7 +433,8 @@ protected:
|
||||
virtual bool CheckALLOW_DUPLICATE_CUSTOM_TARGETS() const;
|
||||
|
||||
// Qt auto generators
|
||||
cmQtAutoGenDigestUPV CreateQtAutoGeneratorsTargets();
|
||||
std::vector<std::unique_ptr<cmQtAutoGeneratorInitializer>>
|
||||
CreateQtAutoGenInitializers();
|
||||
|
||||
std::string SelectMakeProgram(const std::string& makeProgram,
|
||||
const std::string& makeDefault = "") const;
|
||||
|
||||
@@ -80,16 +80,6 @@ void MergeOptions(std::vector<std::string>& baseOpts,
|
||||
baseOpts.insert(baseOpts.end(), extraOpts.begin(), extraOpts.end());
|
||||
}
|
||||
|
||||
static std::string utilStripCR(std::string const& line)
|
||||
{
|
||||
// Strip CR characters rcc may have printed (possibly more than one!).
|
||||
std::string::size_type cr = line.find('\r');
|
||||
if (cr != std::string::npos) {
|
||||
return line.substr(0, cr);
|
||||
}
|
||||
return line;
|
||||
}
|
||||
|
||||
/// @brief Reads the resource files list from from a .qrc file - Qt4 version
|
||||
/// @return True if the .qrc file was successfully parsed
|
||||
static bool RccListInputsQt4(std::string const& fileName,
|
||||
@@ -107,10 +97,10 @@ static bool RccListInputsQt4(std::string const& fileName,
|
||||
qrcContents = osst.str();
|
||||
} else {
|
||||
if (errorMessage != nullptr) {
|
||||
std::ostringstream ost;
|
||||
ost << "rcc file not readable:\n"
|
||||
<< " " << cmQtAutoGen::Quoted(fileName) << "\n";
|
||||
*errorMessage = ost.str();
|
||||
std::string& err = *errorMessage;
|
||||
err = "rcc file not readable:\n ";
|
||||
err += cmQtAutoGen::Quoted(fileName);
|
||||
err += "\n";
|
||||
}
|
||||
allGood = false;
|
||||
}
|
||||
@@ -146,6 +136,7 @@ static bool RccListInputsQt4(std::string const& fileName,
|
||||
/// @brief Reads the resource files list from from a .qrc file - Qt5 version
|
||||
/// @return True if the .qrc file was successfully parsed
|
||||
static bool RccListInputsQt5(std::string const& rccCommand,
|
||||
std::vector<std::string> const& rccListOptions,
|
||||
std::string const& fileName,
|
||||
std::vector<std::string>& files,
|
||||
std::string* errorMessage)
|
||||
@@ -155,24 +146,6 @@ static bool RccListInputsQt5(std::string const& rccCommand,
|
||||
return false;
|
||||
}
|
||||
|
||||
// Read rcc features
|
||||
bool hasDashDashList = false;
|
||||
{
|
||||
std::vector<std::string> command;
|
||||
command.push_back(rccCommand);
|
||||
command.push_back("--help");
|
||||
std::string rccStdOut;
|
||||
std::string rccStdErr;
|
||||
int retVal = 0;
|
||||
bool result = cmSystemTools::RunSingleCommand(
|
||||
command, &rccStdOut, &rccStdErr, &retVal, nullptr,
|
||||
cmSystemTools::OUTPUT_NONE, 0.0, cmProcessOutput::Auto);
|
||||
if (result && retVal == 0 &&
|
||||
rccStdOut.find("--list") != std::string::npos) {
|
||||
hasDashDashList = true;
|
||||
}
|
||||
}
|
||||
|
||||
std::string const fileDir = cmSystemTools::GetFilenamePath(fileName);
|
||||
std::string const fileNameName = cmSystemTools::GetFilenameName(fileName);
|
||||
|
||||
@@ -184,7 +157,8 @@ static bool RccListInputsQt5(std::string const& rccCommand,
|
||||
{
|
||||
std::vector<std::string> command;
|
||||
command.push_back(rccCommand);
|
||||
command.push_back(hasDashDashList ? "--list" : "-list");
|
||||
command.insert(command.end(), rccListOptions.begin(),
|
||||
rccListOptions.end());
|
||||
command.push_back(fileNameName);
|
||||
result = cmSystemTools::RunSingleCommand(
|
||||
command, &rccStdOut, &rccStdErr, &retVal, fileDir.c_str(),
|
||||
@@ -192,22 +166,32 @@ static bool RccListInputsQt5(std::string const& rccCommand,
|
||||
}
|
||||
if (!result || retVal) {
|
||||
if (errorMessage != nullptr) {
|
||||
std::ostringstream ost;
|
||||
ost << "rcc list process failed for\n " << cmQtAutoGen::Quoted(fileName)
|
||||
<< "\n"
|
||||
<< rccStdOut << "\n"
|
||||
<< rccStdErr << "\n";
|
||||
*errorMessage = ost.str();
|
||||
std::string& err = *errorMessage;
|
||||
err = "rcc list process failed for:\n ";
|
||||
err += cmQtAutoGen::Quoted(fileName);
|
||||
err += "\n";
|
||||
err += rccStdOut;
|
||||
err += "\n";
|
||||
err += rccStdErr;
|
||||
err += "\n";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Lambda to strip CR characters
|
||||
auto StripCR = [](std::string& line) {
|
||||
std::string::size_type cr = line.find('\r');
|
||||
if (cr != std::string::npos) {
|
||||
line = line.substr(0, cr);
|
||||
}
|
||||
};
|
||||
|
||||
// Parse rcc std output
|
||||
{
|
||||
std::istringstream ostr(rccStdOut);
|
||||
std::string oline;
|
||||
while (std::getline(ostr, oline)) {
|
||||
oline = utilStripCR(oline);
|
||||
StripCR(oline);
|
||||
if (!oline.empty()) {
|
||||
files.push_back(oline);
|
||||
}
|
||||
@@ -218,17 +202,17 @@ static bool RccListInputsQt5(std::string const& rccCommand,
|
||||
std::istringstream estr(rccStdErr);
|
||||
std::string eline;
|
||||
while (std::getline(estr, eline)) {
|
||||
eline = utilStripCR(eline);
|
||||
StripCR(eline);
|
||||
if (cmHasLiteralPrefix(eline, "RCC: Error in")) {
|
||||
static std::string searchString = "Cannot find file '";
|
||||
|
||||
std::string::size_type pos = eline.find(searchString);
|
||||
if (pos == std::string::npos) {
|
||||
if (errorMessage != nullptr) {
|
||||
std::ostringstream ost;
|
||||
ost << "rcc lists unparsable output:\n"
|
||||
<< cmQtAutoGen::Quoted(eline) << "\n";
|
||||
*errorMessage = ost.str();
|
||||
std::string& err = *errorMessage;
|
||||
err = "rcc lists unparsable output:\n";
|
||||
err += cmQtAutoGen::Quoted(eline);
|
||||
err += "\n";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -349,25 +333,26 @@ void cmQtAutoGen::RccMergeOptions(std::vector<std::string>& baseOpts,
|
||||
MergeOptions(baseOpts, newOpts, valueOpts, isQt5);
|
||||
}
|
||||
|
||||
bool cmQtAutoGen::RccListInputs(std::string const& qtMajorVersion,
|
||||
std::string const& rccCommand,
|
||||
bool cmQtAutoGen::RccListInputs(std::string const& rccCommand,
|
||||
std::vector<std::string> const& rccListOptions,
|
||||
std::string const& fileName,
|
||||
std::vector<std::string>& files,
|
||||
std::string* errorMessage)
|
||||
{
|
||||
bool allGood = false;
|
||||
if (cmSystemTools::FileExists(fileName.c_str())) {
|
||||
if (qtMajorVersion == "4") {
|
||||
if (rccListOptions.empty()) {
|
||||
allGood = RccListInputsQt4(fileName, files, errorMessage);
|
||||
} else {
|
||||
allGood = RccListInputsQt5(rccCommand, fileName, files, errorMessage);
|
||||
allGood = RccListInputsQt5(rccCommand, rccListOptions, fileName, files,
|
||||
errorMessage);
|
||||
}
|
||||
} else {
|
||||
if (errorMessage != nullptr) {
|
||||
std::ostringstream ost;
|
||||
ost << "rcc file does not exist:\n"
|
||||
<< " " << cmQtAutoGen::Quoted(fileName) << "\n";
|
||||
*errorMessage = ost.str();
|
||||
std::string& err = *errorMessage;
|
||||
err = "rcc resource file does not exist:\n ";
|
||||
err += cmQtAutoGen::Quoted(fileName);
|
||||
err += "\n";
|
||||
}
|
||||
}
|
||||
return allGood;
|
||||
|
||||
@@ -61,9 +61,9 @@ public:
|
||||
|
||||
/// @brief Reads the resource files list from from a .qrc file
|
||||
/// @arg fileName Must be the absolute path of the .qrc file
|
||||
/// @return True if the rcc file was successfully parsed
|
||||
static bool RccListInputs(std::string const& qtMajorVersion,
|
||||
std::string const& rccCommand,
|
||||
/// @return True if the rcc file was successfully read
|
||||
static bool RccListInputs(std::string const& rccCommand,
|
||||
std::vector<std::string> const& rccListOptions,
|
||||
std::string const& fileName,
|
||||
std::vector<std::string>& files,
|
||||
std::string* errorMessage = nullptr);
|
||||
|
||||
@@ -1,64 +0,0 @@
|
||||
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
|
||||
file Copyright.txt or https://cmake.org/licensing for details. */
|
||||
#ifndef cmQtAutoGenDigest_h
|
||||
#define cmQtAutoGenDigest_h
|
||||
|
||||
#include "cmConfigure.h" // IWYU pragma: keep
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
class cmGeneratorTarget;
|
||||
|
||||
class cmQtAutoGenDigestQrc
|
||||
{
|
||||
public:
|
||||
cmQtAutoGenDigestQrc()
|
||||
: Generated(false)
|
||||
, Unique(false)
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
std::string QrcFile;
|
||||
std::string QrcName;
|
||||
std::string PathChecksum;
|
||||
std::string RccFile;
|
||||
bool Generated;
|
||||
bool Unique;
|
||||
std::vector<std::string> Options;
|
||||
std::vector<std::string> Resources;
|
||||
};
|
||||
|
||||
/** \class cmQtAutoGenDigest
|
||||
* \brief Filtered set of QtAutogen variables for a specific target
|
||||
*/
|
||||
class cmQtAutoGenDigest
|
||||
{
|
||||
public:
|
||||
cmQtAutoGenDigest(cmGeneratorTarget* target)
|
||||
: Target(target)
|
||||
, MocEnabled(false)
|
||||
, UicEnabled(false)
|
||||
, RccEnabled(false)
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
cmGeneratorTarget* Target;
|
||||
std::string QtVersionMajor;
|
||||
std::string QtVersionMinor;
|
||||
bool MocEnabled;
|
||||
bool UicEnabled;
|
||||
bool RccEnabled;
|
||||
std::vector<std::string> Headers;
|
||||
std::vector<std::string> Sources;
|
||||
std::vector<cmQtAutoGenDigestQrc> Qrcs;
|
||||
};
|
||||
|
||||
// Utility types
|
||||
typedef std::unique_ptr<cmQtAutoGenDigest> cmQtAutoGenDigestUP;
|
||||
typedef std::vector<cmQtAutoGenDigestUP> cmQtAutoGenDigestUPV;
|
||||
|
||||
#endif
|
||||
320
Source/cmQtAutoGenerator.cxx
Normal file
320
Source/cmQtAutoGenerator.cxx
Normal file
@@ -0,0 +1,320 @@
|
||||
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
|
||||
file Copyright.txt or https://cmake.org/licensing for details. */
|
||||
#include "cmQtAutoGen.h"
|
||||
#include "cmQtAutoGenerator.h"
|
||||
|
||||
#include "cmsys/FStream.hxx"
|
||||
#include "cmsys/Terminal.h"
|
||||
|
||||
#include "cmAlgorithms.h"
|
||||
#include "cmGlobalGenerator.h"
|
||||
#include "cmMakefile.h"
|
||||
#include "cmStateDirectory.h"
|
||||
#include "cmStateSnapshot.h"
|
||||
#include "cmSystemTools.h"
|
||||
#include "cmake.h"
|
||||
|
||||
// -- Static functions
|
||||
|
||||
static std::string HeadLine(std::string const& title)
|
||||
{
|
||||
std::string head = title;
|
||||
head += '\n';
|
||||
head.append(head.size() - 1, '-');
|
||||
head += '\n';
|
||||
return head;
|
||||
}
|
||||
|
||||
static std::string QuotedCommand(std::vector<std::string> const& command)
|
||||
{
|
||||
std::string res;
|
||||
for (std::string const& item : command) {
|
||||
if (!res.empty()) {
|
||||
res.push_back(' ');
|
||||
}
|
||||
std::string const cesc = cmQtAutoGen::Quoted(item);
|
||||
if (item.empty() || (cesc.size() > (item.size() + 2)) ||
|
||||
(cesc.find(' ') != std::string::npos)) {
|
||||
res += cesc;
|
||||
} else {
|
||||
res += item;
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
// -- Class methods
|
||||
|
||||
cmQtAutoGenerator::cmQtAutoGenerator()
|
||||
: Verbose(cmSystemTools::HasEnv("VERBOSE"))
|
||||
, ColorOutput(true)
|
||||
{
|
||||
{
|
||||
std::string colorEnv;
|
||||
cmSystemTools::GetEnv("COLOR", colorEnv);
|
||||
if (!colorEnv.empty()) {
|
||||
this->ColorOutput = cmSystemTools::IsOn(colorEnv.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool cmQtAutoGenerator::Run(std::string const& infoFile,
|
||||
std::string const& config)
|
||||
{
|
||||
// Info settings
|
||||
this->InfoFile = infoFile;
|
||||
cmSystemTools::ConvertToUnixSlashes(this->InfoFile);
|
||||
this->InfoDir = cmSystemTools::GetFilenamePath(infoFile);
|
||||
this->InfoConfig = config;
|
||||
|
||||
cmake cm(cmake::RoleScript);
|
||||
cm.SetHomeOutputDirectory(this->InfoDir);
|
||||
cm.SetHomeDirectory(this->InfoDir);
|
||||
cm.GetCurrentSnapshot().SetDefaultDefinitions();
|
||||
cmGlobalGenerator gg(&cm);
|
||||
|
||||
cmStateSnapshot snapshot = cm.GetCurrentSnapshot();
|
||||
snapshot.GetDirectory().SetCurrentBinary(this->InfoDir);
|
||||
snapshot.GetDirectory().SetCurrentSource(this->InfoDir);
|
||||
|
||||
auto makefile = cm::make_unique<cmMakefile>(&gg, snapshot);
|
||||
gg.SetCurrentMakefile(makefile.get());
|
||||
|
||||
return this->Process(makefile.get());
|
||||
}
|
||||
|
||||
void cmQtAutoGenerator::LogBold(std::string const& message) const
|
||||
{
|
||||
cmSystemTools::MakefileColorEcho(cmsysTerminal_Color_ForegroundBlue |
|
||||
cmsysTerminal_Color_ForegroundBold,
|
||||
message.c_str(), true, this->ColorOutput);
|
||||
}
|
||||
|
||||
void cmQtAutoGenerator::LogInfo(cmQtAutoGen::Generator genType,
|
||||
std::string const& message) const
|
||||
{
|
||||
std::string msg = cmQtAutoGen::GeneratorName(genType);
|
||||
msg += ": ";
|
||||
msg += message;
|
||||
if (msg.back() != '\n') {
|
||||
msg.push_back('\n');
|
||||
}
|
||||
cmSystemTools::Stdout(msg.c_str(), msg.size());
|
||||
}
|
||||
|
||||
void cmQtAutoGenerator::LogWarning(cmQtAutoGen::Generator genType,
|
||||
std::string const& message) const
|
||||
{
|
||||
std::string msg = cmQtAutoGen::GeneratorName(genType);
|
||||
msg += " warning:";
|
||||
if (message.find('\n') == std::string::npos) {
|
||||
// Single line message
|
||||
msg.push_back(' ');
|
||||
} else {
|
||||
// Multi line message
|
||||
msg.push_back('\n');
|
||||
}
|
||||
// Message
|
||||
msg += message;
|
||||
if (msg.back() != '\n') {
|
||||
msg.push_back('\n');
|
||||
}
|
||||
msg.push_back('\n');
|
||||
cmSystemTools::Stdout(msg.c_str(), msg.size());
|
||||
}
|
||||
|
||||
void cmQtAutoGenerator::LogFileWarning(cmQtAutoGen::Generator genType,
|
||||
std::string const& filename,
|
||||
std::string const& message) const
|
||||
{
|
||||
std::string msg = " ";
|
||||
msg += cmQtAutoGen::Quoted(filename);
|
||||
msg.push_back('\n');
|
||||
// Message
|
||||
msg += message;
|
||||
this->LogWarning(genType, msg);
|
||||
}
|
||||
|
||||
void cmQtAutoGenerator::LogError(cmQtAutoGen::Generator genType,
|
||||
std::string const& message) const
|
||||
{
|
||||
std::string msg;
|
||||
msg.push_back('\n');
|
||||
msg += HeadLine(cmQtAutoGen::GeneratorName(genType) + " error");
|
||||
// Message
|
||||
msg += message;
|
||||
if (msg.back() != '\n') {
|
||||
msg.push_back('\n');
|
||||
}
|
||||
msg.push_back('\n');
|
||||
cmSystemTools::Stderr(msg.c_str(), msg.size());
|
||||
}
|
||||
|
||||
void cmQtAutoGenerator::LogFileError(cmQtAutoGen::Generator genType,
|
||||
std::string const& filename,
|
||||
std::string const& message) const
|
||||
{
|
||||
std::string emsg = " ";
|
||||
emsg += cmQtAutoGen::Quoted(filename);
|
||||
emsg += '\n';
|
||||
// Message
|
||||
emsg += message;
|
||||
this->LogError(genType, emsg);
|
||||
}
|
||||
|
||||
void cmQtAutoGenerator::LogCommandError(
|
||||
cmQtAutoGen::Generator genType, std::string const& message,
|
||||
std::vector<std::string> const& command, std::string const& output) const
|
||||
{
|
||||
std::string msg;
|
||||
msg.push_back('\n');
|
||||
msg += HeadLine(cmQtAutoGen::GeneratorName(genType) + " subprocess error");
|
||||
msg += message;
|
||||
if (msg.back() != '\n') {
|
||||
msg.push_back('\n');
|
||||
}
|
||||
msg.push_back('\n');
|
||||
msg += HeadLine("Command");
|
||||
msg += QuotedCommand(command);
|
||||
if (msg.back() != '\n') {
|
||||
msg.push_back('\n');
|
||||
}
|
||||
msg.push_back('\n');
|
||||
msg += HeadLine("Output");
|
||||
msg += output;
|
||||
if (msg.back() != '\n') {
|
||||
msg.push_back('\n');
|
||||
}
|
||||
msg.push_back('\n');
|
||||
cmSystemTools::Stderr(msg.c_str(), msg.size());
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Generates the parent directory of the given file on demand
|
||||
* @return True on success
|
||||
*/
|
||||
bool cmQtAutoGenerator::MakeParentDirectory(cmQtAutoGen::Generator genType,
|
||||
std::string const& filename) const
|
||||
{
|
||||
bool success = true;
|
||||
std::string const dirName = cmSystemTools::GetFilenamePath(filename);
|
||||
if (!dirName.empty()) {
|
||||
if (!cmSystemTools::MakeDirectory(dirName)) {
|
||||
this->LogFileError(genType, filename,
|
||||
"Could not create parent directory");
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Tests if buildFile is older than sourceFile
|
||||
* @return True if buildFile is older than sourceFile.
|
||||
* False may indicate an error.
|
||||
*/
|
||||
bool cmQtAutoGenerator::FileIsOlderThan(std::string const& buildFile,
|
||||
std::string const& sourceFile,
|
||||
std::string* error)
|
||||
{
|
||||
int result = 0;
|
||||
if (cmSystemTools::FileTimeCompare(buildFile, sourceFile, &result)) {
|
||||
return (result < 0);
|
||||
}
|
||||
if (error != nullptr) {
|
||||
error->append(
|
||||
"File modification time comparison failed for the files\n ");
|
||||
error->append(cmQtAutoGen::Quoted(buildFile));
|
||||
error->append("\nand\n ");
|
||||
error->append(cmQtAutoGen::Quoted(sourceFile));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool cmQtAutoGenerator::FileRead(std::string& content,
|
||||
std::string const& filename,
|
||||
std::string* error)
|
||||
{
|
||||
bool success = false;
|
||||
if (cmSystemTools::FileExists(filename)) {
|
||||
std::size_t const length = cmSystemTools::FileLength(filename);
|
||||
cmsys::ifstream ifs(filename.c_str(), (std::ios::in | std::ios::binary));
|
||||
if (ifs) {
|
||||
content.resize(length);
|
||||
ifs.read(&content.front(), content.size());
|
||||
if (ifs) {
|
||||
success = true;
|
||||
} else {
|
||||
content.clear();
|
||||
if (error != nullptr) {
|
||||
error->append("Reading from the file failed.");
|
||||
}
|
||||
}
|
||||
} else if (error != nullptr) {
|
||||
error->append("Opening the file for reading failed.");
|
||||
}
|
||||
} else if (error != nullptr) {
|
||||
error->append("The file does not exist.");
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
bool cmQtAutoGenerator::FileWrite(cmQtAutoGen::Generator genType,
|
||||
std::string const& filename,
|
||||
std::string const& content)
|
||||
{
|
||||
std::string error;
|
||||
// Make sure the parent directory exists
|
||||
if (this->MakeParentDirectory(genType, filename)) {
|
||||
cmsys::ofstream outfile;
|
||||
outfile.open(filename.c_str(),
|
||||
(std::ios::out | std::ios::binary | std::ios::trunc));
|
||||
if (outfile) {
|
||||
outfile << content;
|
||||
// Check for write errors
|
||||
if (!outfile.good()) {
|
||||
error = "File writing failed";
|
||||
}
|
||||
} else {
|
||||
error = "Opening file for writing failed";
|
||||
}
|
||||
}
|
||||
if (!error.empty()) {
|
||||
this->LogFileError(genType, filename, error);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cmQtAutoGenerator::FileDiffers(std::string const& filename,
|
||||
std::string const& content)
|
||||
{
|
||||
bool differs = true;
|
||||
{
|
||||
std::string oldContents;
|
||||
if (this->FileRead(oldContents, filename)) {
|
||||
differs = (oldContents != content);
|
||||
}
|
||||
}
|
||||
return differs;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Runs a command and returns true on success
|
||||
* @return True on success
|
||||
*/
|
||||
bool cmQtAutoGenerator::RunCommand(std::vector<std::string> const& command,
|
||||
std::string& output) const
|
||||
{
|
||||
// Log command
|
||||
if (this->Verbose) {
|
||||
std::string qcmd = QuotedCommand(command);
|
||||
qcmd.push_back('\n');
|
||||
cmSystemTools::Stdout(qcmd.c_str(), qcmd.size());
|
||||
}
|
||||
// Execute command
|
||||
int retVal = 0;
|
||||
bool res = cmSystemTools::RunSingleCommand(
|
||||
command, &output, &output, &retVal, nullptr, cmSystemTools::OUTPUT_NONE);
|
||||
return (res && (retVal == 0));
|
||||
}
|
||||
76
Source/cmQtAutoGenerator.h
Normal file
76
Source/cmQtAutoGenerator.h
Normal file
@@ -0,0 +1,76 @@
|
||||
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
|
||||
file Copyright.txt or https://cmake.org/licensing for details. */
|
||||
#ifndef cmQtAutoGenerator_h
|
||||
#define cmQtAutoGenerator_h
|
||||
|
||||
#include "cmConfigure.h" // IWYU pragma: keep
|
||||
|
||||
#include "cmQtAutoGen.h"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
class cmMakefile;
|
||||
|
||||
class cmQtAutoGenerator
|
||||
{
|
||||
CM_DISABLE_COPY(cmQtAutoGenerator)
|
||||
public:
|
||||
cmQtAutoGenerator();
|
||||
virtual ~cmQtAutoGenerator() = default;
|
||||
bool Run(std::string const& infoFile, std::string const& config);
|
||||
|
||||
std::string const& GetInfoFile() const { return InfoFile; }
|
||||
std::string const& GetInfoDir() const { return InfoDir; }
|
||||
std::string const& GetInfoConfig() const { return InfoConfig; }
|
||||
bool GetVerbose() const { return Verbose; }
|
||||
|
||||
protected:
|
||||
// -- Central processing
|
||||
virtual bool Process(cmMakefile* makefile) = 0;
|
||||
|
||||
// -- Log info
|
||||
void LogBold(std::string const& message) const;
|
||||
void LogInfo(cmQtAutoGen::Generator genType,
|
||||
std::string const& message) const;
|
||||
// -- Log warning
|
||||
void LogWarning(cmQtAutoGen::Generator genType,
|
||||
std::string const& message) const;
|
||||
void LogFileWarning(cmQtAutoGen::Generator genType,
|
||||
std::string const& filename,
|
||||
std::string const& message) const;
|
||||
// -- Log error
|
||||
void LogError(cmQtAutoGen::Generator genType,
|
||||
std::string const& message) const;
|
||||
void LogFileError(cmQtAutoGen::Generator genType,
|
||||
std::string const& filename,
|
||||
std::string const& message) const;
|
||||
void LogCommandError(cmQtAutoGen::Generator genType,
|
||||
std::string const& message,
|
||||
std::vector<std::string> const& command,
|
||||
std::string const& output) const;
|
||||
// -- Utility
|
||||
bool MakeParentDirectory(cmQtAutoGen::Generator genType,
|
||||
std::string const& filename) const;
|
||||
bool FileIsOlderThan(std::string const& buildFile,
|
||||
std::string const& sourceFile,
|
||||
std::string* error = nullptr);
|
||||
bool FileRead(std::string& content, std::string const& filename,
|
||||
std::string* error = nullptr);
|
||||
bool FileWrite(cmQtAutoGen::Generator genType, std::string const& filename,
|
||||
std::string const& content);
|
||||
bool FileDiffers(std::string const& filename, std::string const& content);
|
||||
bool RunCommand(std::vector<std::string> const& command,
|
||||
std::string& output) const;
|
||||
|
||||
private:
|
||||
// -- Info settings
|
||||
std::string InfoFile;
|
||||
std::string InfoDir;
|
||||
std::string InfoConfig;
|
||||
// -- Settings
|
||||
bool Verbose;
|
||||
bool ColorOutput;
|
||||
};
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -4,9 +4,12 @@
|
||||
#define cmQtAutoGeneratorInitializer_h
|
||||
|
||||
#include "cmConfigure.h" // IWYU pragma: keep
|
||||
#include "cmQtAutoGenDigest.h"
|
||||
#include "cmQtAutoGen.h"
|
||||
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
class cmGeneratorTarget;
|
||||
|
||||
@@ -17,8 +20,78 @@ public:
|
||||
static std::string GetQtMinorVersion(cmGeneratorTarget const* target,
|
||||
std::string const& qtVersionMajor);
|
||||
|
||||
static void InitializeAutogenTarget(cmQtAutoGenDigest& digest);
|
||||
static void SetupAutoGenerateTarget(cmQtAutoGenDigest const& digest);
|
||||
class Qrc
|
||||
{
|
||||
public:
|
||||
Qrc()
|
||||
: Generated(false)
|
||||
, Unique(false)
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
std::string QrcFile;
|
||||
std::string QrcName;
|
||||
std::string PathChecksum;
|
||||
std::string InfoFile;
|
||||
std::string SettingsFile;
|
||||
std::string RccFile;
|
||||
bool Generated;
|
||||
bool Unique;
|
||||
std::vector<std::string> Options;
|
||||
std::vector<std::string> Resources;
|
||||
};
|
||||
|
||||
public:
|
||||
cmQtAutoGeneratorInitializer(cmGeneratorTarget* target, bool mocEnabled,
|
||||
bool uicEnabled, bool rccEnabled,
|
||||
std::string const& qtVersionMajor);
|
||||
|
||||
void InitCustomTargets();
|
||||
void SetupCustomTargets();
|
||||
|
||||
private:
|
||||
void SetupCustomTargetsMoc();
|
||||
void SetupCustomTargetsUic();
|
||||
|
||||
std::vector<std::string> AddGeneratedSource(std::string const& filename,
|
||||
cmQtAutoGen::Generator genType);
|
||||
|
||||
bool QtVersionGreaterOrEqual(unsigned long requestMajor,
|
||||
unsigned long requestMinor) const;
|
||||
|
||||
private:
|
||||
cmGeneratorTarget* Target;
|
||||
bool MocEnabled;
|
||||
bool UicEnabled;
|
||||
bool RccEnabled;
|
||||
// Qt
|
||||
std::string QtVersionMajor;
|
||||
std::string QtVersionMinor;
|
||||
std::string RccExecutable;
|
||||
std::vector<std::string> RccListOptions;
|
||||
// Configurations
|
||||
std::string ConfigDefault;
|
||||
std::vector<std::string> ConfigsList;
|
||||
cmQtAutoGen::MultiConfig MultiConfig;
|
||||
// Names
|
||||
std::string AutogenTargetName;
|
||||
std::string AutogenFolder;
|
||||
std::string AutogenInfoFile;
|
||||
std::string AutogenSettingsFile;
|
||||
// Directories
|
||||
std::string DirInfo;
|
||||
std::string DirBuild;
|
||||
std::string DirWork;
|
||||
// Sources
|
||||
std::vector<std::string> Headers;
|
||||
std::vector<std::string> Sources;
|
||||
std::set<std::string> MocSkip;
|
||||
std::set<std::string> UicSkip;
|
||||
std::map<std::string, std::string> ConfigMocIncludes;
|
||||
std::map<std::string, std::string> ConfigMocDefines;
|
||||
std::map<std::string, std::string> ConfigUicOptions;
|
||||
std::vector<Qrc> Qrcs;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,12 +1,13 @@
|
||||
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
|
||||
file Copyright.txt or https://cmake.org/licensing for details. */
|
||||
#ifndef cmQtAutoGenerators_h
|
||||
#define cmQtAutoGenerators_h
|
||||
#ifndef cmQtAutoGeneratorMocUic_h
|
||||
#define cmQtAutoGeneratorMocUic_h
|
||||
|
||||
#include "cmConfigure.h" // IWYU pragma: keep
|
||||
|
||||
#include "cmFilePathChecksum.h"
|
||||
#include "cmQtAutoGen.h"
|
||||
#include "cmQtAutoGenerator.h"
|
||||
#include "cmsys/RegularExpression.hxx"
|
||||
|
||||
#include <map>
|
||||
@@ -17,12 +18,11 @@
|
||||
|
||||
class cmMakefile;
|
||||
|
||||
class cmQtAutoGenerators
|
||||
class cmQtAutoGeneratorMocUic : public cmQtAutoGenerator
|
||||
{
|
||||
CM_DISABLE_COPY(cmQtAutoGenerators)
|
||||
CM_DISABLE_COPY(cmQtAutoGeneratorMocUic)
|
||||
public:
|
||||
cmQtAutoGenerators();
|
||||
bool Run(std::string const& targetDirectory, std::string const& config);
|
||||
cmQtAutoGeneratorMocUic();
|
||||
|
||||
private:
|
||||
// -- Types
|
||||
@@ -80,30 +80,19 @@ private:
|
||||
std::string IncludeString;
|
||||
};
|
||||
|
||||
/// @brief RCC job
|
||||
struct RccJob
|
||||
{
|
||||
std::string QrcFile;
|
||||
std::string RccFile;
|
||||
std::vector<std::string> Options;
|
||||
std::vector<std::string> Inputs;
|
||||
};
|
||||
|
||||
// -- Initialization
|
||||
bool InitInfoFile(cmMakefile* makefile, std::string const& targetDirectory,
|
||||
std::string const& config);
|
||||
bool InitInfoFile(cmMakefile* makefile);
|
||||
|
||||
// -- Settings file
|
||||
void SettingsFileRead(cmMakefile* makefile);
|
||||
bool SettingsFileWrite();
|
||||
bool SettingsChanged() const
|
||||
{
|
||||
return (this->MocSettingsChanged || this->RccSettingsChanged ||
|
||||
this->UicSettingsChanged);
|
||||
return (this->MocSettingsChanged || this->UicSettingsChanged);
|
||||
}
|
||||
|
||||
// -- Central processing
|
||||
bool Process();
|
||||
bool Process(cmMakefile* makefile) override;
|
||||
|
||||
// -- Source parsing
|
||||
bool ParseSourceFile(std::string const& absFilename, const SourceJob& job);
|
||||
@@ -146,54 +135,17 @@ private:
|
||||
bool UicGenerateAll();
|
||||
bool UicGenerateFile(const UicJob& uicJob);
|
||||
|
||||
// -- Rcc
|
||||
bool RccEnabled() const { return !this->RccExecutable.empty(); }
|
||||
bool RccGenerateAll();
|
||||
bool RccGenerateFile(const RccJob& rccJob);
|
||||
|
||||
// -- Log info
|
||||
void LogBold(std::string const& message) const;
|
||||
void LogInfo(cmQtAutoGen::Generator genType,
|
||||
std::string const& message) const;
|
||||
// -- Log warning
|
||||
void LogWarning(cmQtAutoGen::Generator genType,
|
||||
std::string const& message) const;
|
||||
void LogFileWarning(cmQtAutoGen::Generator genType,
|
||||
std::string const& filename,
|
||||
std::string const& message) const;
|
||||
// -- Log error
|
||||
void LogError(cmQtAutoGen::Generator genType,
|
||||
std::string const& message) const;
|
||||
void LogFileError(cmQtAutoGen::Generator genType,
|
||||
std::string const& filename,
|
||||
std::string const& message) const;
|
||||
void LogCommandError(cmQtAutoGen::Generator genType,
|
||||
std::string const& message,
|
||||
std::vector<std::string> const& command,
|
||||
std::string const& output) const;
|
||||
|
||||
// -- Utility
|
||||
bool MakeParentDirectory(cmQtAutoGen::Generator genType,
|
||||
std::string const& filename) const;
|
||||
bool FileDiffers(std::string const& filename, std::string const& content);
|
||||
bool FileWrite(cmQtAutoGen::Generator genType, std::string const& filename,
|
||||
std::string const& content);
|
||||
bool FindHeader(std::string& header, std::string const& testBasePath) const;
|
||||
bool RunCommand(std::vector<std::string> const& command,
|
||||
std::string& output) const;
|
||||
|
||||
// -- Meta
|
||||
std::string InfoFile;
|
||||
std::string ConfigSuffix;
|
||||
cmQtAutoGen::MultiConfig MultiConfig;
|
||||
// -- Settings
|
||||
bool IncludeProjectDirsBefore;
|
||||
bool Verbose;
|
||||
bool ColorOutput;
|
||||
std::string SettingsFile;
|
||||
std::string SettingsStringMoc;
|
||||
std::string SettingsStringUic;
|
||||
std::string SettingsStringRcc;
|
||||
// -- Directories
|
||||
std::string ProjectSourceDir;
|
||||
std::string ProjectBinaryDir;
|
||||
@@ -202,11 +154,9 @@ private:
|
||||
std::string AutogenBuildDir;
|
||||
std::string AutogenIncludeDir;
|
||||
// -- Qt environment
|
||||
std::string QtMajorVersion;
|
||||
std::string QtMinorVersion;
|
||||
unsigned long QtVersionMajor;
|
||||
std::string MocExecutable;
|
||||
std::string UicExecutable;
|
||||
std::string RccExecutable;
|
||||
// -- File lists
|
||||
std::map<std::string, SourceJob> HeaderJobs;
|
||||
std::map<std::string, SourceJob> SourceJobs;
|
||||
@@ -240,9 +190,6 @@ private:
|
||||
std::vector<std::string> UicSearchPaths;
|
||||
cmsys::RegularExpression UicRegExpInclude;
|
||||
std::vector<std::unique_ptr<UicJob>> UicJobs;
|
||||
// -- Rcc
|
||||
bool RccSettingsChanged;
|
||||
std::vector<RccJob> RccJobs;
|
||||
};
|
||||
|
||||
#endif
|
||||
425
Source/cmQtAutoGeneratorRcc.cxx
Normal file
425
Source/cmQtAutoGeneratorRcc.cxx
Normal file
@@ -0,0 +1,425 @@
|
||||
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
|
||||
file Copyright.txt or https://cmake.org/licensing for details. */
|
||||
#include "cmQtAutoGen.h"
|
||||
#include "cmQtAutoGeneratorRcc.h"
|
||||
|
||||
#include "cmAlgorithms.h"
|
||||
#include "cmCryptoHash.h"
|
||||
#include "cmMakefile.h"
|
||||
#include "cmOutputConverter.h"
|
||||
#include "cmSystemTools.h"
|
||||
|
||||
// -- Static variables
|
||||
|
||||
static const char* SettingsKeyRcc = "ARCC_SETTINGS_HASH";
|
||||
|
||||
// -- Class methods
|
||||
|
||||
cmQtAutoGeneratorRcc::cmQtAutoGeneratorRcc()
|
||||
: MultiConfig(cmQtAutoGen::WRAP)
|
||||
, SettingsChanged(false)
|
||||
{
|
||||
}
|
||||
|
||||
bool cmQtAutoGeneratorRcc::InfoFileRead(cmMakefile* makefile)
|
||||
{
|
||||
// Utility lambdas
|
||||
auto InfoGet = [makefile](const char* key) {
|
||||
return makefile->GetSafeDefinition(key);
|
||||
};
|
||||
auto InfoGetList = [makefile](const char* key) -> std::vector<std::string> {
|
||||
std::vector<std::string> list;
|
||||
cmSystemTools::ExpandListArgument(makefile->GetSafeDefinition(key), list);
|
||||
return list;
|
||||
};
|
||||
auto InfoGetConfig = [makefile, this](const char* key) -> std::string {
|
||||
const char* valueConf = nullptr;
|
||||
{
|
||||
std::string keyConf = key;
|
||||
keyConf += '_';
|
||||
keyConf += this->GetInfoConfig();
|
||||
valueConf = makefile->GetDefinition(keyConf);
|
||||
}
|
||||
if (valueConf == nullptr) {
|
||||
valueConf = makefile->GetSafeDefinition(key);
|
||||
}
|
||||
return std::string(valueConf);
|
||||
};
|
||||
auto InfoGetConfigList =
|
||||
[&InfoGetConfig](const char* key) -> std::vector<std::string> {
|
||||
std::vector<std::string> list;
|
||||
cmSystemTools::ExpandListArgument(InfoGetConfig(key), list);
|
||||
return list;
|
||||
};
|
||||
|
||||
// -- Read info file
|
||||
if (!makefile->ReadListFile(this->GetInfoFile().c_str())) {
|
||||
this->LogFileError(cmQtAutoGen::RCC, this->GetInfoFile(),
|
||||
"File processing failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
// -- Meta
|
||||
this->MultiConfig =
|
||||
cmQtAutoGen::MultiConfigType(InfoGet("ARCC_MULTI_CONFIG"));
|
||||
this->ConfigSuffix = InfoGetConfig("ARCC_CONFIG_SUFFIX");
|
||||
if (this->ConfigSuffix.empty()) {
|
||||
this->ConfigSuffix = "_";
|
||||
this->ConfigSuffix += this->GetInfoConfig();
|
||||
}
|
||||
|
||||
this->SettingsFile = InfoGetConfig("ARCC_SETTINGS_FILE");
|
||||
|
||||
// - Files and directories
|
||||
this->ProjectSourceDir = InfoGet("ARCC_CMAKE_SOURCE_DIR");
|
||||
this->ProjectBinaryDir = InfoGet("ARCC_CMAKE_BINARY_DIR");
|
||||
this->CurrentSourceDir = InfoGet("ARCC_CMAKE_CURRENT_SOURCE_DIR");
|
||||
this->CurrentBinaryDir = InfoGet("ARCC_CMAKE_CURRENT_BINARY_DIR");
|
||||
this->AutogenBuildDir = InfoGet("ARCC_BUILD_DIR");
|
||||
|
||||
// - Qt environment
|
||||
this->RccExecutable = InfoGet("ARCC_RCC_EXECUTABLE");
|
||||
this->RccListOptions = InfoGetList("ARCC_RCC_LIST_OPTIONS");
|
||||
|
||||
// - Job
|
||||
this->QrcFile = InfoGet("ARCC_SOURCE");
|
||||
this->RccFile = InfoGet("ARCC_OUTPUT");
|
||||
this->Options = InfoGetConfigList("ARCC_OPTIONS");
|
||||
this->Inputs = InfoGetList("ARCC_INPUTS");
|
||||
|
||||
// - Validity checks
|
||||
if (this->SettingsFile.empty()) {
|
||||
this->LogFileError(cmQtAutoGen::RCC, this->GetInfoFile(),
|
||||
"Settings file name missing");
|
||||
return false;
|
||||
}
|
||||
if (this->AutogenBuildDir.empty()) {
|
||||
this->LogFileError(cmQtAutoGen::RCC, this->GetInfoFile(),
|
||||
"Autogen build directory missing");
|
||||
return false;
|
||||
}
|
||||
if (this->RccExecutable.empty()) {
|
||||
this->LogFileError(cmQtAutoGen::RCC, this->GetInfoFile(),
|
||||
"rcc executable missing");
|
||||
return false;
|
||||
}
|
||||
if (this->QrcFile.empty()) {
|
||||
this->LogFileError(cmQtAutoGen::RCC, this->GetInfoFile(),
|
||||
"rcc input file missing");
|
||||
return false;
|
||||
}
|
||||
if (this->RccFile.empty()) {
|
||||
this->LogFileError(cmQtAutoGen::RCC, this->GetInfoFile(),
|
||||
"rcc output file missing");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Init derived information
|
||||
// ------------------------
|
||||
|
||||
// Init file path checksum generator
|
||||
this->FilePathChecksum.setupParentDirs(
|
||||
this->CurrentSourceDir, this->CurrentBinaryDir, this->ProjectSourceDir,
|
||||
this->ProjectBinaryDir);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void cmQtAutoGeneratorRcc::SettingsFileRead(cmMakefile* makefile)
|
||||
{
|
||||
// Compose current settings strings
|
||||
{
|
||||
cmCryptoHash crypt(cmCryptoHash::AlgoSHA256);
|
||||
std::string const sep(" ~~~ ");
|
||||
{
|
||||
std::string str;
|
||||
str += this->RccExecutable;
|
||||
str += sep;
|
||||
str += cmJoin(this->RccListOptions, ";");
|
||||
str += sep;
|
||||
str += this->QrcFile;
|
||||
str += sep;
|
||||
str += this->RccFile;
|
||||
str += sep;
|
||||
str += cmJoin(this->Options, ";");
|
||||
str += sep;
|
||||
str += cmJoin(this->Inputs, ";");
|
||||
str += sep;
|
||||
this->SettingsString = crypt.HashString(str);
|
||||
}
|
||||
}
|
||||
|
||||
// Read old settings
|
||||
if (makefile->ReadListFile(this->SettingsFile.c_str())) {
|
||||
{
|
||||
auto SMatch = [makefile](const char* key, std::string const& value) {
|
||||
return (value == makefile->GetSafeDefinition(key));
|
||||
};
|
||||
if (!SMatch(SettingsKeyRcc, this->SettingsString)) {
|
||||
this->SettingsChanged = true;
|
||||
}
|
||||
}
|
||||
// In case any setting changed remove the old settings file.
|
||||
// This triggers a full rebuild on the next run if the current
|
||||
// build is aborted before writing the current settings in the end.
|
||||
if (this->SettingsChanged) {
|
||||
cmSystemTools::RemoveFile(this->SettingsFile);
|
||||
}
|
||||
} else {
|
||||
// If the file could not be read re-generate everythiung.
|
||||
this->SettingsChanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
bool cmQtAutoGeneratorRcc::SettingsFileWrite()
|
||||
{
|
||||
bool success = true;
|
||||
// Only write if any setting changed
|
||||
if (this->SettingsChanged) {
|
||||
if (this->GetVerbose()) {
|
||||
this->LogInfo(cmQtAutoGen::RCC, "Writing settings file " +
|
||||
cmQtAutoGen::Quoted(this->SettingsFile));
|
||||
}
|
||||
// Compose settings file content
|
||||
std::string settings;
|
||||
{
|
||||
auto SettingAppend = [&settings](const char* key,
|
||||
std::string const& value) {
|
||||
settings += "set(";
|
||||
settings += key;
|
||||
settings += " ";
|
||||
settings += cmOutputConverter::EscapeForCMake(value);
|
||||
settings += ")\n";
|
||||
};
|
||||
SettingAppend(SettingsKeyRcc, this->SettingsString);
|
||||
}
|
||||
// Write settings file
|
||||
if (!this->FileWrite(cmQtAutoGen::RCC, this->SettingsFile, settings)) {
|
||||
this->LogFileError(cmQtAutoGen::RCC, this->SettingsFile,
|
||||
"Settings file writing failed");
|
||||
// Remove old settings file to trigger a full rebuild on the next run
|
||||
cmSystemTools::RemoveFile(this->SettingsFile);
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
bool cmQtAutoGeneratorRcc::Process(cmMakefile* makefile)
|
||||
{
|
||||
// Read info file
|
||||
if (!this->InfoFileRead(makefile)) {
|
||||
return false;
|
||||
}
|
||||
// Read latest settings
|
||||
this->SettingsFileRead(makefile);
|
||||
// Generate rcc file
|
||||
if (!this->RccGenerate()) {
|
||||
return false;
|
||||
}
|
||||
// Write latest settings
|
||||
if (!this->SettingsFileWrite()) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return True on success
|
||||
*/
|
||||
bool cmQtAutoGeneratorRcc::RccGenerate()
|
||||
{
|
||||
bool success = true;
|
||||
bool rccGenerated = false;
|
||||
|
||||
std::string rccFileAbs;
|
||||
{
|
||||
std::string suffix;
|
||||
switch (this->MultiConfig) {
|
||||
case cmQtAutoGen::SINGLE:
|
||||
break;
|
||||
case cmQtAutoGen::WRAP:
|
||||
suffix = "_CMAKE";
|
||||
suffix += this->ConfigSuffix;
|
||||
suffix += "_";
|
||||
break;
|
||||
case cmQtAutoGen::FULL:
|
||||
suffix = this->ConfigSuffix;
|
||||
break;
|
||||
}
|
||||
rccFileAbs = cmQtAutoGen::AppendFilenameSuffix(this->RccFile, suffix);
|
||||
}
|
||||
std::string const rccFileRel = cmSystemTools::RelativePath(
|
||||
this->AutogenBuildDir.c_str(), rccFileAbs.c_str());
|
||||
|
||||
// Check if regeneration is required
|
||||
bool generate = false;
|
||||
std::string generateReason;
|
||||
if (!cmSystemTools::FileExists(this->QrcFile)) {
|
||||
{
|
||||
std::string error = "Could not find the file\n ";
|
||||
error += cmQtAutoGen::Quoted(this->QrcFile);
|
||||
this->LogError(cmQtAutoGen::RCC, error);
|
||||
}
|
||||
success = false;
|
||||
}
|
||||
if (success && !generate && !cmSystemTools::FileExists(rccFileAbs.c_str())) {
|
||||
if (this->GetVerbose()) {
|
||||
generateReason = "Generating ";
|
||||
generateReason += cmQtAutoGen::Quoted(rccFileAbs);
|
||||
generateReason += " from its source file ";
|
||||
generateReason += cmQtAutoGen::Quoted(this->QrcFile);
|
||||
generateReason += " because it doesn't exist";
|
||||
}
|
||||
generate = true;
|
||||
}
|
||||
if (success && !generate && this->SettingsChanged) {
|
||||
if (this->GetVerbose()) {
|
||||
generateReason = "Generating ";
|
||||
generateReason += cmQtAutoGen::Quoted(rccFileAbs);
|
||||
generateReason += " from ";
|
||||
generateReason += cmQtAutoGen::Quoted(this->QrcFile);
|
||||
generateReason += " because the RCC settings changed";
|
||||
}
|
||||
generate = true;
|
||||
}
|
||||
if (success && !generate) {
|
||||
std::string error;
|
||||
if (FileIsOlderThan(rccFileAbs, this->QrcFile, &error)) {
|
||||
if (this->GetVerbose()) {
|
||||
generateReason = "Generating ";
|
||||
generateReason += cmQtAutoGen::Quoted(rccFileAbs);
|
||||
generateReason += " because it is older than ";
|
||||
generateReason += cmQtAutoGen::Quoted(this->QrcFile);
|
||||
}
|
||||
generate = true;
|
||||
} else {
|
||||
if (!error.empty()) {
|
||||
this->LogError(cmQtAutoGen::RCC, error);
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (success && !generate) {
|
||||
// Acquire input file list
|
||||
std::vector<std::string> readFiles;
|
||||
std::vector<std::string> const* files = nullptr;
|
||||
if (!this->Inputs.empty()) {
|
||||
files = &this->Inputs;
|
||||
} else {
|
||||
// Read input file list from qrc file
|
||||
std::string error;
|
||||
if (cmQtAutoGen::RccListInputs(this->RccExecutable, this->RccListOptions,
|
||||
this->QrcFile, readFiles, &error)) {
|
||||
files = &readFiles;
|
||||
} else {
|
||||
this->LogFileError(cmQtAutoGen::RCC, this->QrcFile, error);
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
// Test if any input file is newer than the build file
|
||||
if (files != nullptr) {
|
||||
std::string error;
|
||||
for (std::string const& resFile : *files) {
|
||||
if (!cmSystemTools::FileExists(resFile.c_str())) {
|
||||
error = "Could not find the file\n ";
|
||||
error += cmQtAutoGen::Quoted(resFile);
|
||||
error += "\nwhich is listed in\n ";
|
||||
error += cmQtAutoGen::Quoted(this->QrcFile);
|
||||
break;
|
||||
}
|
||||
if (FileIsOlderThan(rccFileAbs, resFile, &error)) {
|
||||
if (this->GetVerbose()) {
|
||||
generateReason = "Generating ";
|
||||
generateReason += cmQtAutoGen::Quoted(rccFileAbs);
|
||||
generateReason += " from ";
|
||||
generateReason += cmQtAutoGen::Quoted(this->QrcFile);
|
||||
generateReason += " because it is older than ";
|
||||
generateReason += cmQtAutoGen::Quoted(resFile);
|
||||
}
|
||||
generate = true;
|
||||
break;
|
||||
}
|
||||
if (!error.empty()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Print error
|
||||
if (!error.empty()) {
|
||||
this->LogError(cmQtAutoGen::RCC, error);
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Regenerate on demand
|
||||
if (generate) {
|
||||
// Log
|
||||
if (this->GetVerbose()) {
|
||||
this->LogBold("Generating RCC source " + rccFileRel);
|
||||
this->LogInfo(cmQtAutoGen::RCC, generateReason);
|
||||
}
|
||||
|
||||
// Make sure the parent directory exists
|
||||
if (this->MakeParentDirectory(cmQtAutoGen::RCC, rccFileAbs)) {
|
||||
// Compose rcc command
|
||||
std::vector<std::string> cmd;
|
||||
cmd.push_back(this->RccExecutable);
|
||||
cmd.insert(cmd.end(), this->Options.begin(), this->Options.end());
|
||||
cmd.push_back("-o");
|
||||
cmd.push_back(rccFileAbs);
|
||||
cmd.push_back(this->QrcFile);
|
||||
|
||||
std::string output;
|
||||
if (this->RunCommand(cmd, output)) {
|
||||
// Success
|
||||
rccGenerated = true;
|
||||
} else {
|
||||
{
|
||||
std::string emsg = "rcc failed for\n ";
|
||||
emsg += cmQtAutoGen::Quoted(this->QrcFile);
|
||||
this->LogCommandError(cmQtAutoGen::RCC, emsg, cmd, output);
|
||||
}
|
||||
cmSystemTools::RemoveFile(rccFileAbs);
|
||||
success = false;
|
||||
}
|
||||
} else {
|
||||
// Parent directory creation failed
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Generate a wrapper source file on demand
|
||||
if (success && (this->MultiConfig == cmQtAutoGen::WRAP)) {
|
||||
// Wrapper file name
|
||||
std::string const& wrapperFileAbs = this->RccFile;
|
||||
std::string const wrapperFileRel = cmSystemTools::RelativePath(
|
||||
this->AutogenBuildDir.c_str(), wrapperFileAbs.c_str());
|
||||
// Wrapper file content
|
||||
std::string content = "// This is an autogenerated configuration "
|
||||
"wrapper file. Changes will be overwritten.\n"
|
||||
"#include \"";
|
||||
content += cmSystemTools::GetFilenameName(rccFileRel);
|
||||
content += "\"\n";
|
||||
// Write content to file
|
||||
if (this->FileDiffers(wrapperFileAbs, content)) {
|
||||
// Write new wrapper file
|
||||
if (this->GetVerbose()) {
|
||||
this->LogBold("Generating RCC wrapper " + wrapperFileRel);
|
||||
}
|
||||
if (!this->FileWrite(cmQtAutoGen::RCC, wrapperFileAbs, content)) {
|
||||
this->LogFileError(cmQtAutoGen::RCC, wrapperFileAbs,
|
||||
"rcc wrapper file writing failed");
|
||||
success = false;
|
||||
}
|
||||
} else if (rccGenerated) {
|
||||
// Just touch the wrapper file
|
||||
if (this->GetVerbose()) {
|
||||
this->LogInfo(cmQtAutoGen::RCC,
|
||||
"Touching RCC wrapper " + wrapperFileRel);
|
||||
}
|
||||
cmSystemTools::Touch(wrapperFileAbs, false);
|
||||
}
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
56
Source/cmQtAutoGeneratorRcc.h
Normal file
56
Source/cmQtAutoGeneratorRcc.h
Normal file
@@ -0,0 +1,56 @@
|
||||
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
|
||||
file Copyright.txt or https://cmake.org/licensing for details. */
|
||||
#ifndef cmQtAutoGeneratorRcc_h
|
||||
#define cmQtAutoGeneratorRcc_h
|
||||
|
||||
#include "cmConfigure.h" // IWYU pragma: keep
|
||||
|
||||
#include "cmFilePathChecksum.h"
|
||||
#include "cmQtAutoGen.h"
|
||||
#include "cmQtAutoGenerator.h"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
class cmMakefile;
|
||||
|
||||
class cmQtAutoGeneratorRcc : public cmQtAutoGenerator
|
||||
{
|
||||
CM_DISABLE_COPY(cmQtAutoGeneratorRcc)
|
||||
public:
|
||||
cmQtAutoGeneratorRcc();
|
||||
|
||||
private:
|
||||
// -- Initialization & settings
|
||||
bool InfoFileRead(cmMakefile* makefile);
|
||||
void SettingsFileRead(cmMakefile* makefile);
|
||||
bool SettingsFileWrite();
|
||||
// -- Central processing
|
||||
bool Process(cmMakefile* makefile) override;
|
||||
bool RccGenerate();
|
||||
|
||||
// -- Config settings
|
||||
std::string ConfigSuffix;
|
||||
cmQtAutoGen::MultiConfig MultiConfig;
|
||||
// -- Settings
|
||||
bool SettingsChanged;
|
||||
std::string SettingsFile;
|
||||
std::string SettingsString;
|
||||
// -- Directories
|
||||
std::string ProjectSourceDir;
|
||||
std::string ProjectBinaryDir;
|
||||
std::string CurrentSourceDir;
|
||||
std::string CurrentBinaryDir;
|
||||
std::string AutogenBuildDir;
|
||||
cmFilePathChecksum FilePathChecksum;
|
||||
// -- Qt environment
|
||||
std::string RccExecutable;
|
||||
std::vector<std::string> RccListOptions;
|
||||
// -- Job
|
||||
std::string QrcFile;
|
||||
std::string RccFile;
|
||||
std::vector<std::string> Options;
|
||||
std::vector<std::string> Inputs;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -6,7 +6,8 @@
|
||||
#include "cmGlobalGenerator.h"
|
||||
#include "cmLocalGenerator.h"
|
||||
#include "cmMakefile.h"
|
||||
#include "cmQtAutoGenerators.h"
|
||||
#include "cmQtAutoGeneratorMocUic.h"
|
||||
#include "cmQtAutoGeneratorRcc.h"
|
||||
#include "cmStateDirectory.h"
|
||||
#include "cmStateSnapshot.h"
|
||||
#include "cmSystemTools.h"
|
||||
@@ -992,11 +993,20 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args)
|
||||
}
|
||||
|
||||
#ifdef CMAKE_BUILD_WITH_CMAKE
|
||||
if (args[1] == "cmake_autogen" && args.size() >= 4) {
|
||||
cmQtAutoGenerators autogen;
|
||||
if ((args[1] == "cmake_autogen") && (args.size() >= 4)) {
|
||||
cmQtAutoGeneratorMocUic autoGen;
|
||||
std::string const& infoDir = args[2];
|
||||
std::string const& config = args[3];
|
||||
bool autogenSuccess = autogen.Run(args[2], config);
|
||||
return autogenSuccess ? 0 : 1;
|
||||
return autoGen.Run(infoDir, config) ? 0 : 1;
|
||||
}
|
||||
if ((args[1] == "cmake_autorcc") && (args.size() >= 3)) {
|
||||
cmQtAutoGeneratorRcc autoGen;
|
||||
std::string const& infoFile = args[2];
|
||||
std::string config;
|
||||
if (args.size() > 3) {
|
||||
config = args[3];
|
||||
};
|
||||
return autoGen.Run(infoFile, config) ? 0 : 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
Reference in New Issue
Block a user