Autogen: Improved multi-config include scheme

For multi configuration generators AUTOMOC generates the
moc files that are included in `mocs_compilation.cpp`
in `AUTOGEN_BUILD_DIR/include_$<CONFIG>/`. By doing so each
configuration reads different moc files when compiling
`mocs_compilation.cpp`. Since we do not (need to) rewrite
`mocs_compilation.cpp` on a configuration change anymore,
the files also does not need to be recompiled anymore.
Not having to rewrite and recompile `mocs_compilation.cpp`
on a configuration change anymore was the main objective of
this patch.

In a similar fashion AUTORCC generates a `qrc_BASE_CMAKE.cpp`
file below `AUTOGEN_BUILD_DIR/include_$<CONFIG>/` and
`qrc_BASE.cpp` becomes a mere wrapper that includes this
actuall rcc output file (when using multi configuration
generators).

The template files `Modules/AutoRccInfo.cmake.in` and
`Modules/AutogenInfo.cmake.in` were removed in favor
of writing the info `.cmake` files manually.

Closes #17230
This commit is contained in:
Sebastian Holtermann 2018-01-31 13:54:37 +01:00
parent 5a16e762e2
commit a8ee7406a7
10 changed files with 421 additions and 510 deletions

View File

@ -1,7 +0,0 @@
# Meta
set(ARCC_MULTI_CONFIG @_multi_config@)
# Directories and files
set(ARCC_BUILD_DIR @_build_dir@)
# Qt environment
set(ARCC_RCC_EXECUTABLE @_qt_rcc_executable@)
set(ARCC_RCC_LIST_OPTIONS @_qt_rcc_list_options@)

View File

@ -1,32 +0,0 @@
# Meta
set(AM_MULTI_CONFIG @_multi_config@)
set(AM_PARALLEL @_parallel@)
# Directories and files
set(AM_CMAKE_BINARY_DIR "@CMAKE_BINARY_DIR@/")
set(AM_CMAKE_SOURCE_DIR "@CMAKE_SOURCE_DIR@/")
set(AM_CMAKE_CURRENT_SOURCE_DIR "@CMAKE_CURRENT_SOURCE_DIR@/")
set(AM_CMAKE_CURRENT_BINARY_DIR "@CMAKE_CURRENT_BINARY_DIR@/")
set(AM_CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE "@CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE@")
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_MOC_EXECUTABLE @_qt_moc_executable@)
set(AM_QT_UIC_EXECUTABLE @_qt_uic_executable@)
# MOC settings
set(AM_MOC_SKIP @_moc_skip@)
set(AM_MOC_DEFINITIONS @_moc_compile_defs@)
set(AM_MOC_INCLUDES @_moc_include_dirs@)
set(AM_MOC_OPTIONS @_moc_options@)
set(AM_MOC_RELAXED_MODE @_moc_relaxed_mode@)
set(AM_MOC_MACRO_NAMES @_moc_macro_names@)
set(AM_MOC_DEPEND_FILTERS @_moc_depend_filters@)
set(AM_MOC_PREDEFS_CMD @_moc_predefs_cmd@)
# UIC settings
set(AM_UIC_SKIP @_uic_skip@)
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@)

View File

@ -17,10 +17,6 @@ std::string const genNameMoc = "AutoMoc";
std::string const genNameUic = "AutoUic";
std::string const genNameRcc = "AutoRcc";
std::string const mcNameSingle = "SINGLE";
std::string const mcNameWrapper = "WRAPPER";
std::string const mcNameMulti = "MULTI";
// - Static functions
/// @brief Merges newOpts into baseOpts
@ -102,30 +98,6 @@ std::string cmQtAutoGen::GeneratorNameUpper(GeneratorT genType)
return cmSystemTools::UpperCase(cmQtAutoGen::GeneratorName(genType));
}
std::string const& cmQtAutoGen::MultiConfigName(MultiConfigT config)
{
switch (config) {
case MultiConfigT::SINGLE:
return mcNameSingle;
case MultiConfigT::WRAPPER:
return mcNameWrapper;
case MultiConfigT::MULTI:
return mcNameMulti;
}
return mcNameWrapper;
}
cmQtAutoGen::MultiConfigT cmQtAutoGen::MultiConfigType(std::string const& name)
{
if (name == mcNameSingle) {
return MultiConfigT::SINGLE;
}
if (name == mcNameMulti) {
return MultiConfigT::MULTI;
}
return MultiConfigT::WRAPPER;
}
std::string cmQtAutoGen::Quoted(std::string const& text)
{
static const char* rep[18] = { "\\", "\\\\", "\"", "\\\"", "\a", "\\a",

View File

@ -28,25 +28,12 @@ public:
RCC
};
/// @brief Multiconfiguration type
enum class MultiConfigT
{
SINGLE, // Single configuration
WRAPPER, // Multi configuration using wrapper files
MULTI // Multi configuration using per config sources
};
public:
/// @brief Returns the generator name
static std::string const& GeneratorName(GeneratorT genType);
/// @brief Returns the generator name in upper case
static std::string GeneratorNameUpper(GeneratorT genType);
/// @brief Returns the multi configuration name string
static std::string const& MultiConfigName(MultiConfigT config);
/// @brief Returns the multi configuration type
static MultiConfigT MultiConfigType(std::string const& name);
/// @brief Returns a the string escaped and enclosed in quotes
static std::string Quoted(std::string const& text);

View File

@ -68,43 +68,6 @@ static std::size_t GetParallelCPUCount()
return count;
}
static void AddDefinitionEscaped(cmMakefile* makefile, const char* key,
std::string const& value)
{
makefile->AddDefinition(key,
cmOutputConverter::EscapeForCMake(value).c_str());
}
static void AddDefinitionEscaped(cmMakefile* makefile, const char* key,
const std::vector<std::string>& values)
{
makefile->AddDefinition(
key, cmOutputConverter::EscapeForCMake(cmJoin(values, ";")).c_str());
}
static void AddDefinitionEscaped(cmMakefile* makefile, const char* key,
const std::set<std::string>& values)
{
makefile->AddDefinition(
key, cmOutputConverter::EscapeForCMake(cmJoin(values, ";")).c_str());
}
static void AddDefinitionEscaped(
cmMakefile* makefile, const char* key,
const std::vector<std::vector<std::string>>& lists)
{
std::vector<std::string> seplist;
for (const std::vector<std::string>& list : lists) {
std::string blist = "{";
blist += cmJoin(list, ";");
blist += "}";
seplist.push_back(std::move(blist));
}
makefile->AddDefinition(key, cmOutputConverter::EscapeForCMake(
cmJoin(seplist, cmQtAutoGen::ListSep))
.c_str());
}
static bool AddToSourceGroup(cmMakefile* makefile, std::string const& fileName,
cmQtAutoGen::GeneratorT genType)
{
@ -234,8 +197,8 @@ cmQtAutoGenInitializer::cmQtAutoGenInitializer(
, MocEnabled(mocEnabled)
, UicEnabled(uicEnabled)
, RccEnabled(rccEnabled)
, MultiConfig(false)
, QtVersionMajor(qtVersionMajor)
, MultiConfig(MultiConfigT::WRAPPER)
{
this->QtVersionMinor =
cmQtAutoGenInitializer::GetQtMinorVersion(target, this->QtVersionMajor);
@ -248,30 +211,12 @@ void cmQtAutoGenInitializer::InitCustomTargets()
cmGlobalGenerator* globalGen = localGen->GetGlobalGenerator();
// Configurations
this->MultiConfig = globalGen->IsMultiConfig();
this->ConfigDefault = makefile->GetConfigurations(this->ConfigsList);
if (this->ConfigsList.empty()) {
this->ConfigsList.push_back(this->ConfigDefault);
}
// Multi configuration
{
if (!globalGen->IsMultiConfig()) {
this->MultiConfig = MultiConfigT::SINGLE;
}
// FIXME: Xcode does not support per-config sources, yet.
// (EXCLUDED_SOURCE_FILE_NAMES)
// if (globalGen->GetName().find("Xcode") != std::string::npos) {
// return MultiConfigT::MULTI;
//}
// FIXME: Visual Studio does not support per-config sources, yet.
// (EXCLUDED_SOURCE_FILE_NAMES)
// if (globalGen->GetName().find("Visual Studio") != std::string::npos) {
// return MultiConfigT::MULTI;
//}
}
// Autogen target name
this->AutogenTargetName = this->Target->GetName();
this->AutogenTargetName += "_autogen";
@ -285,7 +230,7 @@ void cmQtAutoGenInitializer::InitCustomTargets()
// Autogen info dir
this->DirInfo = cbd;
this->DirInfo += makefile->GetCMakeInstance()->GetCMakeFilesDirectory();
this->DirInfo += "/";
this->DirInfo += '/';
this->DirInfo += this->AutogenTargetName;
this->DirInfo += ".dir";
cmSystemTools::ConvertToUnixSlashes(this->DirInfo);
@ -294,7 +239,7 @@ void cmQtAutoGenInitializer::InitCustomTargets()
this->DirBuild = GetSafeProperty(this->Target, "AUTOGEN_BUILD_DIR");
if (this->DirBuild.empty()) {
this->DirBuild = cbd;
this->DirBuild += "/";
this->DirBuild += '/';
this->DirBuild += this->AutogenTargetName;
}
cmSystemTools::ConvertToUnixSlashes(this->DirBuild);
@ -340,32 +285,32 @@ void cmQtAutoGenInitializer::InitCustomTargets()
{
std::string base = this->DirInfo;
base += "/AutogenOldSettings";
if (this->MultiConfig == MultiConfigT::SINGLE) {
AddCleanFile(makefile, base.append(".cmake"));
} else {
if (this->MultiConfig) {
for (std::string const& cfg : this->ConfigsList) {
std::string filename = base;
filename += "_";
filename += '_';
filename += cfg;
filename += ".cmake";
AddCleanFile(makefile, filename);
}
} else {
AddCleanFile(makefile, base.append(".cmake"));
}
}
// Add moc compilation to generated files list
if (this->MocEnabled) {
std::string const mocsComp = this->DirBuild + "/mocs_compilation.cpp";
auto files = this->AddGeneratedSource(mocsComp, GeneratorT::MOC);
for (std::string& file : files) {
autogenProvides.push_back(std::move(file));
}
std::string mocsComp = this->DirBuild + "/mocs_compilation.cpp";
this->AddGeneratedSource(mocsComp, GeneratorT::MOC);
autogenProvides.push_back(std::move(mocsComp));
}
// Add autogen includes directory to the origin target INCLUDE_DIRECTORIES
if (this->MocEnabled || this->UicEnabled) {
std::string includeDir = this->DirBuild + "/include";
if (this->MultiConfig != MultiConfigT::SINGLE) {
if (this->MocEnabled || this->UicEnabled ||
(this->RccEnabled && this->MultiConfig)) {
std::string includeDir = this->DirBuild;
includeDir += "/include";
if (this->MultiConfig) {
includeDir += "_$<CONFIG>";
}
this->Target->AddIncludeDirectory(includeDir, true);
@ -674,9 +619,10 @@ void cmQtAutoGenInitializer::InitCustomTargets()
}
for (Qrc& qrc : this->Qrcs) {
// Register file at target
std::vector<std::string> const ccOutput =
this->AddGeneratedSource(qrc.RccFile, GeneratorT::RCC);
this->AddGeneratedSource(qrc.RccFile, GeneratorT::RCC);
std::vector<std::string> ccOutput;
ccOutput.push_back(qrc.RccFile);
cmCustomCommandLines commandLines;
{
cmCustomCommandLine currentLine;
@ -905,51 +851,6 @@ void cmQtAutoGenInitializer::SetupCustomTargets()
{
cmMakefile* makefile = this->Target->Target->GetMakefile();
// forget the variables added here afterwards again:
cmMakefile::ScopePushPop varScope(makefile);
static_cast<void>(varScope);
// Configuration suffixes
std::map<std::string, std::string> configSuffixes;
for (std::string const& cfg : this->ConfigsList) {
std::string& suffix = configSuffixes[cfg];
suffix = "_";
suffix += cfg;
}
// Basic setup
AddDefinitionEscaped(makefile, "_multi_config",
MultiConfigName(this->MultiConfig));
AddDefinitionEscaped(makefile, "_build_dir", this->DirBuild);
{
std::string parallel = GetSafeProperty(this->Target, "AUTOGEN_PARALLEL");
// Autodetect number of CPUs
if (parallel.empty() || (parallel == "AUTO")) {
parallel = std::to_string(GetParallelCPUCount());
}
AddDefinitionEscaped(makefile, "_parallel", parallel);
}
if (this->MocEnabled || this->UicEnabled) {
AddDefinitionEscaped(makefile, "_qt_version_major", this->QtVersionMajor);
AddDefinitionEscaped(makefile, "_settings_file",
this->AutogenSettingsFile);
AddDefinitionEscaped(makefile, "_sources", this->Sources);
AddDefinitionEscaped(makefile, "_headers", this->Headers);
if (this->MocEnabled) {
this->SetupCustomTargetsMoc();
}
if (this->UicEnabled) {
this->SetupCustomTargetsUic();
}
}
if (this->RccEnabled) {
AddDefinitionEscaped(makefile, "_qt_rcc_executable", this->RccExecutable);
AddDefinitionEscaped(makefile, "_qt_rcc_list_options",
this->RccListOptions);
}
// Create info directory on demand
if (!cmSystemTools::MakeDirectory(this->DirInfo)) {
std::string emsg = ("Could not create directory: ");
@ -957,21 +858,33 @@ void cmQtAutoGenInitializer::SetupCustomTargets()
cmSystemTools::Error(emsg.c_str());
}
auto ReOpenInfoFile = [](cmsys::ofstream& ofs,
std::string const& fileName) -> bool {
// Configuration include directories
std::string includeDir = "include";
std::map<std::string, std::string> includeDirs;
for (std::string const& cfg : this->ConfigsList) {
std::string& dir = includeDirs[cfg];
dir = "include_";
dir += cfg;
}
auto OpenInfoFile = [](cmsys::ofstream& ofs,
std::string const& fileName) -> bool {
// Ensure we have write permission
mode_t perm = 0;
if (cmSystemTools::FileExists(fileName)) {
mode_t perm = 0;
#if defined(_WIN32) && !defined(__CYGWIN__)
mode_t mode_write = S_IWRITE;
mode_t mode_write = S_IWRITE;
#else
mode_t mode_write = S_IWUSR;
mode_t mode_write = S_IWUSR;
#endif
cmSystemTools::GetPermissions(fileName, perm);
if (!(perm & mode_write)) {
cmSystemTools::SetPermissions(fileName, perm | mode_write);
cmSystemTools::GetPermissions(fileName, perm);
if (!(perm & mode_write)) {
cmSystemTools::SetPermissions(fileName, perm | mode_write);
}
}
ofs.open(fileName.c_str(), std::ios::app);
ofs.open(fileName.c_str(),
(std::ios::out | std::ios::binary | std::ios::trunc));
if (!ofs) {
// File open error
std::string error = "Internal CMake error when trying to open file: ";
@ -984,88 +897,177 @@ void cmQtAutoGenInitializer::SetupCustomTargets()
// Generate autogen target info file
if (this->MocEnabled || this->UicEnabled) {
{
std::string infoFileIn = cmSystemTools::GetCMakeRoot();
infoFileIn += "/Modules/AutogenInfo.cmake.in";
makefile->ConfigureFile(
infoFileIn.c_str(), this->AutogenInfoFile.c_str(), false, true, false);
if (this->MocEnabled) {
this->SetupCustomTargetsMoc();
}
if (this->UicEnabled) {
this->SetupCustomTargetsUic();
}
// Parallel processing
this->Parallel = GetSafeProperty(this->Target, "AUTOGEN_PARALLEL");
if (this->Parallel.empty() || (this->Parallel == "AUTO")) {
// Autodetect number of CPUs
this->Parallel = std::to_string(GetParallelCPUCount());
}
// Append custom definitions to info file
// --------------------------------------
cmsys::ofstream ofs;
if (ReOpenInfoFile(ofs, this->AutogenInfoFile)) {
auto OfsWriteMap = [&ofs](
const char* key, std::map<std::string, std::string> const& map) {
if (OpenInfoFile(ofs, this->AutogenInfoFile)) {
// Utility lambdas
auto CWrite = [&ofs](const char* key, std::string const& value) {
ofs << "set(" << key << " " << cmOutputConverter::EscapeForCMake(value)
<< ")\n";
};
auto CWriteList = [&CWrite](const char* key,
std::vector<std::string> const& list) {
CWrite(key, cmJoin(list, ";"));
};
auto CWriteNestedLists = [&CWrite](
const char* key, std::vector<std::vector<std::string>> const& lists) {
std::vector<std::string> seplist;
for (const std::vector<std::string>& list : lists) {
std::string blist = "{";
blist += cmJoin(list, ";");
blist += "}";
seplist.push_back(std::move(blist));
}
CWrite(key, cmJoin(seplist, cmQtAutoGen::ListSep));
};
auto CWriteSet = [&CWrite](const char* key,
std::set<std::string> const& list) {
CWrite(key, cmJoin(list, ";"));
};
auto CWriteMap = [&ofs](const char* key,
std::map<std::string, std::string> const& map) {
for (auto const& item : map) {
ofs << "set(" << key << "_" << item.first << " "
<< cmOutputConverter::EscapeForCMake(item.second) << ")\n";
}
};
ofs << "# Configurations options\n";
OfsWriteMap("AM_CONFIG_SUFFIX", configSuffixes);
OfsWriteMap("AM_MOC_DEFINITIONS", this->ConfigMocDefines);
OfsWriteMap("AM_MOC_INCLUDES", this->ConfigMocIncludes);
OfsWriteMap("AM_UIC_TARGET_OPTIONS", this->ConfigUicOptions);
// Settings files (only require for multi configuration generators)
if (this->MultiConfig != MultiConfigT::SINGLE) {
auto MfDef = [makefile](const char* key) {
return std::string(makefile->GetSafeDefinition(key));
};
// Write
ofs << "# Meta\n";
CWrite("AM_MULTI_CONFIG", this->MultiConfig ? "TRUE" : "FALSE");
CWrite("AM_PARALLEL", this->Parallel);
ofs << "# Directories\n";
CWrite("AM_CMAKE_SOURCE_DIR", MfDef("CMAKE_SOURCE_DIR"));
CWrite("AM_CMAKE_BINARY_DIR", MfDef("CMAKE_BINARY_DIR"));
CWrite("AM_CMAKE_CURRENT_SOURCE_DIR", MfDef("CMAKE_CURRENT_SOURCE_DIR"));
CWrite("AM_CMAKE_CURRENT_BINARY_DIR", MfDef("CMAKE_CURRENT_BINARY_DIR"));
CWrite("AM_CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE",
MfDef("CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE"));
CWrite("AM_BUILD_DIR", this->DirBuild);
if (this->MultiConfig) {
CWriteMap("AM_INCLUDE_DIR", includeDirs);
} else {
CWrite("AM_INCLUDE_DIR", includeDir);
}
ofs << "# Files\n";
CWriteList("AM_SOURCES", this->Sources);
CWriteList("AM_HEADERS", this->Headers);
if (this->MultiConfig) {
std::map<std::string, std::string> settingsFiles;
for (std::string const& cfg : this->ConfigsList) {
settingsFiles[cfg] =
AppendFilenameSuffix(this->AutogenSettingsFile, "_" + cfg);
}
OfsWriteMap("AM_SETTINGS_FILE", settingsFiles);
CWriteMap("AM_SETTINGS_FILE", settingsFiles);
} else {
CWrite("AM_SETTINGS_FILE", this->AutogenSettingsFile);
}
ofs << "# Qt\n";
CWrite("AM_QT_VERSION_MAJOR", this->QtVersionMajor);
CWrite("AM_QT_MOC_EXECUTABLE", this->MocExecutable);
CWrite("AM_QT_UIC_EXECUTABLE", this->UicExecutable);
if (this->MocEnabled) {
ofs << "# MOC settings\n";
CWriteSet("AM_MOC_SKIP", this->MocSkip);
CWrite("AM_MOC_DEFINITIONS", this->MocDefines);
CWriteMap("AM_MOC_DEFINITIONS", this->MocDefinesConfig);
CWrite("AM_MOC_INCLUDES", this->MocIncludes);
CWriteMap("AM_MOC_INCLUDES", this->MocIncludesConfig);
CWrite("AM_MOC_OPTIONS",
GetSafeProperty(this->Target, "AUTOMOC_MOC_OPTIONS"));
CWrite("AM_MOC_RELAXED_MODE", MfDef("CMAKE_AUTOMOC_RELAXED_MODE"));
CWrite("AM_MOC_MACRO_NAMES",
GetSafeProperty(this->Target, "AUTOMOC_MACRO_NAMES"));
CWrite("AM_MOC_DEPEND_FILTERS",
GetSafeProperty(this->Target, "AUTOMOC_DEPEND_FILTERS"));
CWrite("AM_MOC_PREDEFS_CMD", this->MocPredefsCmd);
}
if (this->UicEnabled) {
ofs << "# UIC settings\n";
CWriteSet("AM_UIC_SKIP", this->UicSkip);
CWrite("AM_UIC_TARGET_OPTIONS", this->UicOptions);
CWriteMap("AM_UIC_TARGET_OPTIONS", this->UicOptionsConfig);
CWriteList("AM_UIC_OPTIONS_FILES", this->UicFileFiles);
CWriteNestedLists("AM_UIC_OPTIONS_OPTIONS", this->UicFileOptions);
CWriteList("AM_UIC_SEARCH_PATHS", this->UicSearchPaths);
}
}
}
// Generate auto RCC info files
if (this->RccEnabled) {
std::string infoFileIn = cmSystemTools::GetCMakeRoot();
infoFileIn += "/Modules/AutoRccInfo.cmake.in";
for (Qrc const& qrc : this->Qrcs) {
// Configure info file
makefile->ConfigureFile(infoFileIn.c_str(), qrc.InfoFile.c_str(), false,
true, false);
// Append custom definitions to info file
// --------------------------------------
cmsys::ofstream ofs;
if (ReOpenInfoFile(ofs, qrc.InfoFile)) {
{
ofs << "# Job\n";
auto OfsWrite = [&ofs](const char* key, std::string const& value) {
ofs << "set(" << key << " "
<< cmOutputConverter::EscapeForCMake(value) << ")\n";
};
OfsWrite("ARCC_SETTINGS_FILE", qrc.SettingsFile);
OfsWrite("ARCC_SOURCE", qrc.QrcFile);
OfsWrite("ARCC_OUTPUT", qrc.RccFile);
OfsWrite("ARCC_OPTIONS", cmJoin(qrc.Options, ";"));
OfsWrite("ARCC_INPUTS", cmJoin(qrc.Resources, ";"));
}
{
ofs << "# Configurations options\n";
auto OfsWriteMap = [&ofs](
const char* key, std::map<std::string, std::string> const& map) {
for (auto const& item : map) {
ofs << "set(" << key << "_" << item.first << " "
<< cmOutputConverter::EscapeForCMake(item.second) << ")\n";
}
};
OfsWriteMap("ARCC_CONFIG_SUFFIX", configSuffixes);
// Settings files (only require for multi configuration generators)
if (this->MultiConfig != MultiConfigT::SINGLE) {
std::map<std::string, std::string> settingsFiles;
for (std::string const& cfg : this->ConfigsList) {
settingsFiles[cfg] =
AppendFilenameSuffix(qrc.SettingsFile, "_" + cfg);
}
OfsWriteMap("ARCC_SETTINGS_FILE", settingsFiles);
if (OpenInfoFile(ofs, qrc.InfoFile)) {
// Utility lambdas
auto CWrite = [&ofs](const char* key, std::string const& value) {
ofs << "set(" << key << " "
<< cmOutputConverter::EscapeForCMake(value) << ")\n";
};
auto CWriteMap = [&ofs](
const char* key, std::map<std::string, std::string> const& map) {
for (auto const& item : map) {
ofs << "set(" << key << "_" << item.first << " "
<< cmOutputConverter::EscapeForCMake(item.second) << ")\n";
}
};
// Write
ofs << "# Configurations\n";
CWrite("ARCC_MULTI_CONFIG", this->MultiConfig ? "TRUE" : "FALSE");
ofs << "# Settings file\n";
if (this->MultiConfig) {
std::map<std::string, std::string> settingsFiles;
for (std::string const& cfg : this->ConfigsList) {
settingsFiles[cfg] =
AppendFilenameSuffix(qrc.SettingsFile, "_" + cfg);
}
CWriteMap("ARCC_SETTINGS_FILE", settingsFiles);
} else {
CWrite("ARCC_SETTINGS_FILE", qrc.SettingsFile);
}
ofs << "# Directories\n";
CWrite("ARCC_BUILD_DIR", this->DirBuild);
if (this->MultiConfig) {
CWriteMap("ARCC_INCLUDE_DIR", includeDirs);
} else {
CWrite("ARCC_INCLUDE_DIR", includeDir);
}
ofs << "# Rcc executable\n";
CWrite("ARCC_RCC_EXECUTABLE", this->RccExecutable);
CWrite("ARCC_RCC_LIST_OPTIONS", cmJoin(this->RccListOptions, ";"));
ofs << "# Rcc job\n";
CWrite("ARCC_SOURCE", qrc.QrcFile);
CWrite("ARCC_OUTPUT_CHECKSUM", qrc.PathChecksum);
CWrite("ARCC_OUTPUT_NAME",
cmSystemTools::GetFilenameName(qrc.RccFile));
CWrite("ARCC_OPTIONS", cmJoin(qrc.Options, ";"));
CWrite("ARCC_INPUTS", cmJoin(qrc.Resources, ";"));
} else {
break;
}
@ -1078,25 +1080,13 @@ void cmQtAutoGenInitializer::SetupCustomTargetsMoc()
cmLocalGenerator* localGen = this->Target->GetLocalGenerator();
cmMakefile* makefile = this->Target->Target->GetMakefile();
AddDefinitionEscaped(makefile, "_moc_skip", this->MocSkip);
AddDefinitionEscaped(makefile, "_moc_options",
GetSafeProperty(this->Target, "AUTOMOC_MOC_OPTIONS"));
AddDefinitionEscaped(makefile, "_moc_relaxed_mode",
makefile->IsOn("CMAKE_AUTOMOC_RELAXED_MODE") ? "TRUE"
: "FALSE");
AddDefinitionEscaped(makefile, "_moc_macro_names",
GetSafeProperty(this->Target, "AUTOMOC_MACRO_NAMES"));
AddDefinitionEscaped(
makefile, "_moc_depend_filters",
GetSafeProperty(this->Target, "AUTOMOC_DEPEND_FILTERS"));
// Compiler predefines
// Moc predefs command
if (this->Target->GetPropertyAsBool("AUTOMOC_COMPILER_PREDEFINES") &&
this->QtVersionGreaterOrEqual(5, 8)) {
AddDefinitionEscaped(
makefile, "_moc_predefs_cmd",
makefile->GetSafeDefinition("CMAKE_CXX_COMPILER_PREDEFINES_COMMAND"));
this->MocPredefsCmd =
makefile->GetSafeDefinition("CMAKE_CXX_COMPILER_PREDEFINES_COMMAND");
}
// Moc includes and compile definitions
{
auto GetIncludeDirs = [this,
@ -1117,25 +1107,23 @@ void cmQtAutoGenInitializer::SetupCustomTargetsMoc()
};
// Default configuration settings
std::string const includeDirs = GetIncludeDirs(this->ConfigDefault);
std::string const compileDefs = GetCompileDefinitions(this->ConfigDefault);
this->MocIncludes = GetIncludeDirs(this->ConfigDefault);
this->MocDefines = GetCompileDefinitions(this->ConfigDefault);
// Other configuration settings
for (std::string const& cfg : this->ConfigsList) {
{
std::string const configIncludeDirs = GetIncludeDirs(cfg);
if (configIncludeDirs != includeDirs) {
this->ConfigMocIncludes[cfg] = configIncludeDirs;
if (configIncludeDirs != this->MocIncludes) {
this->MocIncludesConfig[cfg] = configIncludeDirs;
}
}
{
std::string const configCompileDefs = GetCompileDefinitions(cfg);
if (configCompileDefs != compileDefs) {
this->ConfigMocDefines[cfg] = configCompileDefs;
if (configCompileDefs != this->MocDefines) {
this->MocDefinesConfig[cfg] = configCompileDefs;
}
}
}
AddDefinitionEscaped(makefile, "_moc_include_dirs", includeDirs);
AddDefinitionEscaped(makefile, "_moc_compile_defs", compileDefs);
}
// Moc executable
@ -1162,7 +1150,7 @@ void cmQtAutoGenInitializer::SetupCustomTargetsMoc()
}
if (err.empty()) {
AddDefinitionEscaped(makefile, "_qt_moc_executable", mocExec);
this->MocExecutable = mocExec;
} else {
err += " (";
err += this->Target->GetName();
@ -1178,19 +1166,15 @@ void cmQtAutoGenInitializer::SetupCustomTargetsUic()
// Uic search paths
{
std::vector<std::string> uicSearchPaths;
{
std::string const usp =
GetSafeProperty(this->Target, "AUTOUIC_SEARCH_PATHS");
if (!usp.empty()) {
cmSystemTools::ExpandListArgument(usp, uicSearchPaths);
std::string const srcDir = makefile->GetCurrentSourceDirectory();
for (std::string& path : uicSearchPaths) {
path = cmSystemTools::CollapseFullPath(path, srcDir);
}
std::string const usp =
GetSafeProperty(this->Target, "AUTOUIC_SEARCH_PATHS");
if (!usp.empty()) {
cmSystemTools::ExpandListArgument(usp, this->UicSearchPaths);
std::string const srcDir = makefile->GetCurrentSourceDirectory();
for (std::string& path : this->UicSearchPaths) {
path = cmSystemTools::CollapseFullPath(path, srcDir);
}
}
AddDefinitionEscaped(makefile, "_uic_search_paths", uicSearchPaths);
}
// Uic target options
{
@ -1201,60 +1185,51 @@ void cmQtAutoGenInitializer::SetupCustomTargetsUic()
};
// Default settings
std::string const uicOpts = UicGetOpts(this->ConfigDefault);
AddDefinitionEscaped(makefile, "_uic_target_options", uicOpts);
this->UicOptions = UicGetOpts(this->ConfigDefault);
// Configuration specific settings
for (std::string const& cfg : this->ConfigsList) {
std::string const configUicOpts = UicGetOpts(cfg);
if (configUicOpts != uicOpts) {
this->ConfigUicOptions[cfg] = configUicOpts;
if (configUicOpts != this->UicOptions) {
this->UicOptionsConfig[cfg] = configUicOpts;
}
}
}
// .ui files skip and options
{
std::vector<std::string> uiFileFiles;
std::vector<std::vector<std::string>> uiFileOptions;
{
std::string const uiExt = "ui";
std::string pathError;
for (cmSourceFile* sf : makefile->GetSourceFiles()) {
// sf->GetExtension() is only valid after sf->GetFullPath() ...
// Since we're iterating over source files that might be not in the
// target we need to check for path errors (not existing files).
std::string const& fPath = sf->GetFullPath(&pathError);
if (!pathError.empty()) {
pathError.clear();
continue;
std::string const uiExt = "ui";
std::string pathError;
for (cmSourceFile* sf : makefile->GetSourceFiles()) {
// sf->GetExtension() is only valid after sf->GetFullPath() ...
// Since we're iterating over source files that might be not in the
// target we need to check for path errors (not existing files).
std::string const& fPath = sf->GetFullPath(&pathError);
if (!pathError.empty()) {
pathError.clear();
continue;
}
if (sf->GetExtension() == uiExt) {
std::string const absFile = cmSystemTools::GetRealPath(fPath);
// Check if the .ui file should be skipped
if (sf->GetPropertyAsBool("SKIP_AUTOUIC") ||
sf->GetPropertyAsBool("SKIP_AUTOGEN")) {
this->UicSkip.insert(absFile);
}
if (sf->GetExtension() == uiExt) {
std::string const absFile = cmSystemTools::GetRealPath(fPath);
// Check if the .ui file should be skipped
if (sf->GetPropertyAsBool("SKIP_AUTOUIC") ||
sf->GetPropertyAsBool("SKIP_AUTOGEN")) {
this->UicSkip.insert(absFile);
}
// Check if the .ui file has uic options
std::string const uicOpts = GetSafeProperty(sf, "AUTOUIC_OPTIONS");
if (!uicOpts.empty()) {
// Check if file isn't skipped
if (this->UicSkip.count(absFile) == 0) {
uiFileFiles.push_back(absFile);
std::vector<std::string> optsVec;
cmSystemTools::ExpandListArgument(uicOpts, optsVec);
uiFileOptions.push_back(std::move(optsVec));
}
// Check if the .ui file has uic options
std::string const uicOpts = GetSafeProperty(sf, "AUTOUIC_OPTIONS");
if (!uicOpts.empty()) {
// Check if file isn't skipped
if (this->UicSkip.count(absFile) == 0) {
this->UicFileFiles.push_back(absFile);
std::vector<std::string> optsVec;
cmSystemTools::ExpandListArgument(uicOpts, optsVec);
this->UicFileOptions.push_back(std::move(optsVec));
}
}
}
}
AddDefinitionEscaped(makefile, "_qt_uic_options_files", uiFileFiles);
AddDefinitionEscaped(makefile, "_qt_uic_options_options", uiFileOptions);
}
AddDefinitionEscaped(makefile, "_uic_skip", this->UicSkip);
// Uic executable
{
std::string err;
@ -1280,7 +1255,7 @@ void cmQtAutoGenInitializer::SetupCustomTargetsUic()
}
if (err.empty()) {
AddDefinitionEscaped(makefile, "_qt_uic_executable", uicExec);
this->UicExecutable = uicExec;
} else {
err += " (";
err += this->Target->GetName();
@ -1290,45 +1265,22 @@ void cmQtAutoGenInitializer::SetupCustomTargetsUic()
}
}
std::vector<std::string> cmQtAutoGenInitializer::AddGeneratedSource(
std::string const& filename, GeneratorT genType)
void cmQtAutoGenInitializer::AddGeneratedSource(std::string const& filename,
GeneratorT genType)
{
std::vector<std::string> genFiles;
// Register source file in makefile and source group
if (this->MultiConfig != MultiConfigT::MULTI) {
genFiles.push_back(filename);
} else {
for (std::string const& cfg : this->ConfigsList) {
genFiles.push_back(AppendFilenameSuffix(filename, "_" + cfg));
}
}
// Register source file in makefile
cmMakefile* makefile = this->Target->Target->GetMakefile();
{
cmMakefile* makefile = this->Target->Target->GetMakefile();
for (std::string const& genFile : genFiles) {
{
cmSourceFile* gFile = makefile->GetOrCreateSource(genFile, true);
gFile->SetProperty("GENERATED", "1");
gFile->SetProperty("SKIP_AUTOGEN", "On");
}
AddToSourceGroup(makefile, genFile, genType);
}
cmSourceFile* gFile = makefile->GetOrCreateSource(filename, true);
gFile->SetProperty("GENERATED", "1");
gFile->SetProperty("SKIP_AUTOGEN", "On");
}
// Add source file to source group
AddToSourceGroup(makefile, filename, genType);
// Add source file to target
if (this->MultiConfig != MultiConfigT::MULTI) {
this->Target->AddSource(filename);
} else {
for (std::string const& cfg : this->ConfigsList) {
std::string src = "$<$<CONFIG:";
src += cfg;
src += ">:";
src += AppendFilenameSuffix(filename, "_" + cfg);
src += ">";
this->Target->AddSource(src);
}
}
return genFiles;
this->Target->AddSource(filename);
}
std::string cmQtAutoGenInitializer::GetQtMajorVersion(
@ -1400,7 +1352,8 @@ bool cmQtAutoGenInitializer::RccListInputs(std::string const& fileName,
return false;
}
// Run rcc list command in the directory of the qrc file with the pathless
// Run rcc list command in the directory of the qrc file with the
// pathless
// qrc file name argument. This way rcc prints relative paths.
// This avoids issues on Windows when the qrc file is in a path that
// contains non-ASCII characters.

View File

@ -21,6 +21,7 @@ public:
static std::string GetQtMinorVersion(cmGeneratorTarget const* target,
std::string const& qtVersionMajor);
/// @brief Rcc job information
class Qrc
{
public:
@ -55,8 +56,7 @@ private:
void SetupCustomTargetsMoc();
void SetupCustomTargetsUic();
std::vector<std::string> AddGeneratedSource(std::string const& filename,
GeneratorT genType);
void AddGeneratedSource(std::string const& filename, GeneratorT genType);
bool QtVersionGreaterOrEqual(unsigned long requestMajor,
unsigned long requestMinor) const;
@ -70,15 +70,18 @@ private:
bool MocEnabled;
bool UicEnabled;
bool RccEnabled;
bool MultiConfig;
// Qt
std::string QtVersionMajor;
std::string QtVersionMinor;
std::string MocExecutable;
std::string UicExecutable;
std::string RccExecutable;
std::vector<std::string> RccListOptions;
// Configurations
std::string ConfigDefault;
std::vector<std::string> ConfigsList;
MultiConfigT MultiConfig;
std::string Parallel;
// Names
std::string AutogenTargetName;
std::string AutogenFolder;
@ -91,11 +94,21 @@ private:
// Sources
std::vector<std::string> Headers;
std::vector<std::string> Sources;
// Moc
std::string MocPredefsCmd;
std::set<std::string> MocSkip;
std::string MocIncludes;
std::map<std::string, std::string> MocIncludesConfig;
std::string MocDefines;
std::map<std::string, std::string> MocDefinesConfig;
// Uic
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<std::string> UicSearchPaths;
std::string UicOptions;
std::map<std::string, std::string> UicOptionsConfig;
std::vector<std::string> UicFileFiles;
std::vector<std::vector<std::string>> UicFileOptions;
// Rcc
std::vector<Qrc> Qrcs;
};

View File

@ -672,19 +672,24 @@ void cmQtAutoGeneratorMocUic::JobMocT::Process(WorkerT& wrk)
{
// Compute build file name
if (!IncludeString.empty()) {
BuildFile = wrk.Base().AutogenIncludeDirAbs;
BuildFile = wrk.Base().AutogenIncludeDir;
BuildFile += '/';
BuildFile += IncludeString;
} else {
std::string buildRel = wrk.Base().FilePathChecksum.getPart(SourceFile);
buildRel += '/';
buildRel += "moc_";
buildRel += cmSystemTools::GetFilenameWithoutLastExtension(SourceFile);
if (wrk.Base().MultiConfig != MultiConfigT::SINGLE) {
buildRel += wrk.Base().ConfigSuffix;
std::string rel = wrk.Base().FilePathChecksum.getPart(SourceFile);
rel += "/moc_";
rel += cmSystemTools::GetFilenameWithoutLastExtension(SourceFile);
rel += ".cpp";
// Register relative file path
wrk.Gen().ParallelMocAutoRegister(rel);
// Absolute build path
if (wrk.Base().MultiConfig) {
BuildFile = wrk.Base().AutogenIncludeDir;
BuildFile += '/';
BuildFile += rel;
} else {
BuildFile = wrk.Base().AbsoluteBuildPath(rel);
}
buildRel += ".cpp";
wrk.Gen().ParallelMocAutoRegister(buildRel);
BuildFile = wrk.Base().AbsoluteBuildPath(buildRel);
}
if (UpdateRequired(wrk)) {
@ -871,7 +876,8 @@ void cmQtAutoGeneratorMocUic::JobMocT::GenerateMoc(WorkerT& wrk)
void cmQtAutoGeneratorMocUic::JobUicT::Process(WorkerT& wrk)
{
// Compute build file name
BuildFile = wrk.Base().AutogenIncludeDirAbs;
BuildFile = wrk.Base().AutogenIncludeDir;
BuildFile += '/';
BuildFile += IncludeString;
if (UpdateRequired(wrk)) {
@ -1208,20 +1214,7 @@ bool cmQtAutoGeneratorMocUic::Init(cmMakefile* makefile)
}
// -- Meta
Base_.MultiConfig = MultiConfigType(InfoGet("AM_MULTI_CONFIG"));
Base_.ConfigSuffix = InfoGetConfig("AM_CONFIG_SUFFIX");
if (Base_.ConfigSuffix.empty()) {
Base_.ConfigSuffix = "_";
Base_.ConfigSuffix += InfoConfig();
}
SettingsFile_ = InfoGetConfig("AM_SETTINGS_FILE");
if (SettingsFile_.empty()) {
Log().ErrorFile(GeneratorT::GEN, InfoFile(), "Settings file name missing");
return false;
}
Base_.MultiConfig = InfoGetBool("AM_MULTI_CONFIG");
{
unsigned long num = Base_.NumThreads;
if (cmSystemTools::StringToULong(InfoGet("AM_PARALLEL"), &num)) {
@ -1244,6 +1237,23 @@ bool cmQtAutoGeneratorMocUic::Init(cmMakefile* makefile)
"Autogen build directory missing");
return false;
}
// include directory
{
std::string dirRel = InfoGetConfig("AM_INCLUDE_DIR");
if (dirRel.empty()) {
Log().ErrorFile(GeneratorT::GEN, InfoFile(),
"Autogen include directory missing");
return false;
}
Base_.AutogenIncludeDir = Base_.AbsoluteBuildPath(dirRel);
}
// - Files
SettingsFile_ = InfoGetConfig("AM_SETTINGS_FILE");
if (SettingsFile_.empty()) {
Log().ErrorFile(GeneratorT::GEN, InfoFile(), "Settings file name missing");
return false;
}
// - Qt environment
{
@ -1438,30 +1448,17 @@ bool cmQtAutoGeneratorMocUic::Init(cmMakefile* makefile)
Base().CurrentSourceDir, Base().CurrentBinaryDir, Base().ProjectSourceDir,
Base().ProjectBinaryDir);
// include directory
Base_.AutogenIncludeDirRel = "include";
if (Base().MultiConfig != MultiConfigT::SINGLE) {
Base_.AutogenIncludeDirRel += Base().ConfigSuffix;
}
Base_.AutogenIncludeDirRel += "/";
Base_.AutogenIncludeDirAbs =
Base_.AbsoluteBuildPath(Base().AutogenIncludeDirRel);
// Moc variables
if (Moc().Enabled) {
// Mocs compilation file
Moc_.CompFileRel = "mocs_compilation";
if (Base_.MultiConfig == MultiConfigT::MULTI) {
Moc_.CompFileRel += Base().ConfigSuffix;
}
Moc_.CompFileRel += ".cpp";
Moc_.CompFileAbs = Base_.AbsoluteBuildPath(Moc().CompFileRel);
Moc_.CompFileAbs = Base().AbsoluteBuildPath("mocs_compilation.cpp");
// Moc predefs file
if (!Moc_.PredefsCmd.empty()) {
Moc_.PredefsFileRel = "moc_predefs";
if (Base_.MultiConfig != MultiConfigT::SINGLE) {
Moc_.PredefsFileRel += Base().ConfigSuffix;
if (Base_.MultiConfig) {
Moc_.PredefsFileRel += '_';
Moc_.PredefsFileRel += InfoConfig();
}
Moc_.PredefsFileRel += ".h";
Moc_.PredefsFileAbs = Base_.AbsoluteBuildPath(Moc().PredefsFileRel);
@ -1731,7 +1728,7 @@ void cmQtAutoGeneratorMocUic::SettingsFileWrite()
void cmQtAutoGeneratorMocUic::CreateDirectories()
{
// Create AUTOGEN include directory
if (!FileSys().MakeDirectory(GeneratorT::GEN, Base().AutogenIncludeDirAbs)) {
if (!FileSys().MakeDirectory(GeneratorT::GEN, Base().AutogenIncludeDir)) {
RegisterJobError();
}
}
@ -1980,9 +1977,10 @@ void cmQtAutoGeneratorMocUic::ParallelMocAutoUpdated()
void cmQtAutoGeneratorMocUic::MocGenerateCompilation()
{
std::lock_guard<std::mutex> mocLock(JobsMutex_);
if (!JobThreadsAbort_ && Moc().Enabled) {
// Compose mocs compilation file content
if (!JobError_ && Moc().Enabled) {
// Write mocs compilation build file
{
// Compose mocs compilation file content
std::string content =
"// This file is autogenerated. Changes will be overwritten.\n";
if (MocAutoFiles_.empty()) {
@ -1992,19 +1990,22 @@ void cmQtAutoGeneratorMocUic::MocGenerateCompilation()
content += "enum some_compilers { need_more_than_nothing };\n";
} else {
// Valid content
char const sbeg = Base().MultiConfig ? '<' : '"';
char const send = Base().MultiConfig ? '>' : '"';
for (std::string const& mocfile : MocAutoFiles_) {
content += "#include \"";
content += "#include ";
content += sbeg;
content += mocfile;
content += "\"\n";
content += send;
content += '\n';
}
}
std::string const& compRel = Moc().CompFileRel;
std::string const& compAbs = Moc().CompFileAbs;
if (FileSys().FileDiffers(compAbs, content)) {
// Actually write mocs compilation file
if (Log().Verbose()) {
Log().Info(GeneratorT::MOC, "Generating MOC compilation " + compRel);
Log().Info(GeneratorT::MOC, "Generating MOC compilation " + compAbs);
}
if (!FileSys().FileWrite(GeneratorT::MOC, compAbs, content)) {
Log().ErrorFile(GeneratorT::MOC, compAbs,
@ -2015,10 +2016,13 @@ void cmQtAutoGeneratorMocUic::MocGenerateCompilation()
} else if (MocAutoFileUpdated_) {
// Only touch mocs compilation file
if (Log().Verbose()) {
Log().Info(GeneratorT::MOC, "Touching mocs compilation " + compRel);
Log().Info(GeneratorT::MOC, "Touching mocs compilation " + compAbs);
}
FileSys().Touch(compAbs);
}
}
// Write mocs compilation wrapper file
if (Base().MultiConfig) {
}
}
}

View File

@ -68,7 +68,7 @@ public:
public:
// -- Volatile methods
BaseSettingsT(FileSystem* fileSystem)
: MultiConfig(MultiConfigT::WRAPPER)
: MultiConfig(false)
, IncludeProjectDirsBefore(false)
, QtVersionMajor(4)
, NumThreads(1)
@ -83,8 +83,7 @@ public:
// -- Attributes
// - Config
std::string ConfigSuffix;
MultiConfigT MultiConfig;
bool MultiConfig;
bool IncludeProjectDirsBefore;
unsigned int QtVersionMajor;
unsigned int NumThreads;
@ -94,8 +93,7 @@ public:
std::string CurrentSourceDir;
std::string CurrentBinaryDir;
std::string AutogenBuildDir;
std::string AutogenIncludeDirRel;
std::string AutogenIncludeDirAbs;
std::string AutogenIncludeDir;
// - Files
cmFilePathChecksum FilePathChecksum;
std::vector<std::string> HeaderExtensions;
@ -128,7 +126,6 @@ public:
bool SettingsChanged = false;
bool RelaxedMode = false;
std::string Executable;
std::string CompFileRel;
std::string CompFileAbs;
std::string PredefsFileRel;
std::string PredefsFileAbs;

View File

@ -14,8 +14,8 @@
// -- Class methods
cmQtAutoGeneratorRcc::cmQtAutoGeneratorRcc()
: SettingsChanged_(false)
, MultiConfig_(MultiConfigT::WRAPPER)
: MultiConfig_(false)
, SettingsChanged_(false)
, Stage_(StageT::SETTINGS_READ)
, Error_(false)
, Generate_(false)
@ -31,16 +31,18 @@ cmQtAutoGeneratorRcc::~cmQtAutoGeneratorRcc()
bool cmQtAutoGeneratorRcc::Init(cmMakefile* makefile)
{
// Utility lambdas
auto InfoGet = [makefile](const char* key) {
// -- Utility lambdas
auto InfoGet = [makefile](std::string const& key) {
return makefile->GetSafeDefinition(key);
};
auto InfoGetList = [makefile](const char* key) -> std::vector<std::string> {
auto InfoGetList =
[makefile](std::string const& 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 {
auto InfoGetConfig = [makefile,
this](std::string const& key) -> std::string {
const char* valueConf = nullptr;
{
std::string keyConf = key;
@ -54,7 +56,7 @@ bool cmQtAutoGeneratorRcc::Init(cmMakefile* makefile)
return std::string(valueConf);
};
auto InfoGetConfigList =
[&InfoGetConfig](const char* key) -> std::vector<std::string> {
[&InfoGetConfig](std::string const& key) -> std::vector<std::string> {
std::vector<std::string> list;
cmSystemTools::ExpandListArgument(InfoGetConfig(key), list);
return list;
@ -66,20 +68,23 @@ bool cmQtAutoGeneratorRcc::Init(cmMakefile* makefile)
return false;
}
// -- Meta
MultiConfig_ = MultiConfigType(InfoGet("ARCC_MULTI_CONFIG"));
ConfigSuffix_ = InfoGetConfig("ARCC_CONFIG_SUFFIX");
if (ConfigSuffix_.empty()) {
ConfigSuffix_ = "_";
ConfigSuffix_ += InfoConfig();
// - Configurations
MultiConfig_ = makefile->IsOn("ARCC_MULTI_CONFIG");
// - Directories
AutogenBuildDir_ = InfoGet("ARCC_BUILD_DIR");
if (AutogenBuildDir_.empty()) {
Log().ErrorFile(GeneratorT::RCC, InfoFile(), "Build directory empty");
return false;
}
SettingsFile_ = InfoGetConfig("ARCC_SETTINGS_FILE");
IncludeDir_ = InfoGetConfig("ARCC_INCLUDE_DIR");
if (IncludeDir_.empty()) {
Log().ErrorFile(GeneratorT::RCC, InfoFile(), "Include directory empty");
return false;
}
// - Files and directories
AutogenBuildDir_ = InfoGet("ARCC_BUILD_DIR");
// - Qt environment
// - Rcc executable
RccExecutable_ = InfoGet("ARCC_RCC_EXECUTABLE");
RccListOptions_ = InfoGetList("ARCC_RCC_LIST_OPTIONS");
@ -87,10 +92,14 @@ bool cmQtAutoGeneratorRcc::Init(cmMakefile* makefile)
QrcFile_ = InfoGet("ARCC_SOURCE");
QrcFileName_ = cmSystemTools::GetFilenameName(QrcFile_);
QrcFileDir_ = cmSystemTools::GetFilenamePath(QrcFile_);
RccFile_ = InfoGet("ARCC_OUTPUT");
RccPathChecksum_ = InfoGet("ARCC_OUTPUT_CHECKSUM");
RccFileName_ = InfoGet("ARCC_OUTPUT_NAME");
Options_ = InfoGetConfigList("ARCC_OPTIONS");
Inputs_ = InfoGetList("ARCC_INPUTS");
// - Settings file
SettingsFile_ = InfoGetConfig("ARCC_SETTINGS_FILE");
// - Validity checks
if (SettingsFile_.empty()) {
Log().ErrorFile(GeneratorT::RCC, InfoFile(), "Settings file name missing");
@ -109,7 +118,7 @@ bool cmQtAutoGeneratorRcc::Init(cmMakefile* makefile)
Log().ErrorFile(GeneratorT::RCC, InfoFile(), "rcc input file missing");
return false;
}
if (RccFile_.empty()) {
if (RccFileName_.empty()) {
Log().ErrorFile(GeneratorT::RCC, InfoFile(), "rcc output file missing");
return false;
}
@ -117,22 +126,21 @@ bool cmQtAutoGeneratorRcc::Init(cmMakefile* makefile)
// Init derived information
// ------------------------
RccFilePublic_ = AutogenBuildDir_;
RccFilePublic_ += '/';
RccFilePublic_ += RccPathChecksum_;
RccFilePublic_ += '/';
RccFilePublic_ += RccFileName_;
// Compute rcc output file name
{
std::string suffix;
switch (MultiConfig_) {
case MultiConfigT::SINGLE:
break;
case MultiConfigT::WRAPPER:
suffix = "_CMAKE";
suffix += ConfigSuffix_;
suffix += "_";
break;
case MultiConfigT::MULTI:
suffix = ConfigSuffix_;
break;
}
RccFileBuild_ = AppendFilenameSuffix(RccFile_, suffix);
if (IsMultiConfig()) {
RccFileOutput_ = AutogenBuildDir_;
RccFileOutput_ += '/';
RccFileOutput_ += IncludeDir_;
RccFileOutput_ += '/';
RccFileOutput_ += MultiConfigOutput();
} else {
RccFileOutput_ = RccFilePublic_;
}
return true;
@ -234,6 +242,16 @@ void cmQtAutoGeneratorRcc::SetStage(StageT stage)
}
}
std::string cmQtAutoGeneratorRcc::MultiConfigOutput() const
{
static std::string const suffix = "_CMAKE_";
std::string res;
res += RccPathChecksum_;
res += '/';
res += AppendFilenameSuffix(RccFileName_, suffix);
return res;
}
void cmQtAutoGeneratorRcc::SettingsFileRead()
{
// Compose current settings strings
@ -248,7 +266,9 @@ void cmQtAutoGeneratorRcc::SettingsFileRead()
str += sep;
str += QrcFile_;
str += sep;
str += RccFile_;
str += RccPathChecksum_;
str += sep;
str += RccFileName_;
str += sep;
str += cmJoin(Options_, ";");
str += sep;
@ -302,10 +322,10 @@ bool cmQtAutoGeneratorRcc::TestQrcRccFiles()
// Do basic checks if rcc generation is required
// Test if the rcc output file exists
if (!FileSys().FileExists(RccFileBuild_)) {
if (!FileSys().FileExists(RccFileOutput_)) {
if (Log().Verbose()) {
std::string reason = "Generating ";
reason += Quoted(RccFileBuild_);
reason += Quoted(RccFileOutput_);
reason += " from its source file ";
reason += Quoted(QrcFile_);
reason += " because it doesn't exist";
@ -319,7 +339,7 @@ bool cmQtAutoGeneratorRcc::TestQrcRccFiles()
if (SettingsChanged_) {
if (Log().Verbose()) {
std::string reason = "Generating ";
reason += Quoted(RccFileBuild_);
reason += Quoted(RccFileOutput_);
reason += " from ";
reason += Quoted(QrcFile_);
reason += " because the RCC settings changed";
@ -334,7 +354,7 @@ bool cmQtAutoGeneratorRcc::TestQrcRccFiles()
bool isOlder = false;
{
std::string error;
isOlder = FileSys().FileIsOlderThan(RccFileBuild_, QrcFile_, &error);
isOlder = FileSys().FileIsOlderThan(RccFileOutput_, QrcFile_, &error);
if (!error.empty()) {
Log().ErrorFile(GeneratorT::RCC, QrcFile_, error);
Error_ = true;
@ -343,7 +363,7 @@ bool cmQtAutoGeneratorRcc::TestQrcRccFiles()
if (isOlder) {
if (Log().Verbose()) {
std::string reason = "Generating ";
reason += Quoted(RccFileBuild_);
reason += Quoted(RccFileOutput_);
reason += " because it is older than ";
reason += Quoted(QrcFile_);
Log().Info(GeneratorT::RCC, reason);
@ -437,10 +457,10 @@ bool cmQtAutoGeneratorRcc::TestResources()
break;
}
// Check if the resource file is newer than the build file
if (FileSys().FileIsOlderThan(RccFileBuild_, resFile, &error)) {
if (FileSys().FileIsOlderThan(RccFileOutput_, resFile, &error)) {
if (Log().Verbose()) {
std::string reason = "Generating ";
reason += Quoted(RccFileBuild_);
reason += Quoted(RccFileOutput_);
reason += " from ";
reason += Quoted(QrcFile_);
reason += " because it is older than ";
@ -469,7 +489,7 @@ void cmQtAutoGeneratorRcc::TestInfoFile()
bool isOlder = false;
{
std::string error;
isOlder = FileSys().FileIsOlderThan(RccFileBuild_, InfoFile(), &error);
isOlder = FileSys().FileIsOlderThan(RccFileOutput_, InfoFile(), &error);
if (!error.empty()) {
Log().ErrorFile(GeneratorT::RCC, QrcFile_, error);
Error_ = true;
@ -478,13 +498,13 @@ void cmQtAutoGeneratorRcc::TestInfoFile()
if (isOlder) {
if (Log().Verbose()) {
std::string reason = "Touching ";
reason += Quoted(RccFileBuild_);
reason += Quoted(RccFileOutput_);
reason += " because it is older than ";
reason += Quoted(InfoFile());
Log().Info(GeneratorT::RCC, reason);
}
// Touch build file
FileSys().Touch(RccFileBuild_);
FileSys().Touch(RccFileOutput_);
BuildFileChanged_ = true;
}
}
@ -493,7 +513,7 @@ void cmQtAutoGeneratorRcc::TestInfoFile()
void cmQtAutoGeneratorRcc::GenerateParentDir()
{
// Make sure the parent directory exists
if (!FileSys().MakeParentDirectory(GeneratorT::RCC, RccFileBuild_)) {
if (!FileSys().MakeParentDirectory(GeneratorT::RCC, RccFileOutput_)) {
Error_ = true;
}
}
@ -521,7 +541,7 @@ bool cmQtAutoGeneratorRcc::GenerateRcc()
std::string emsg = "The rcc process failed to compile\n ";
emsg += Quoted(QrcFile_);
emsg += "\ninto\n ";
emsg += Quoted(RccFileBuild_);
emsg += Quoted(RccFileOutput_);
if (ProcessResult_.error()) {
emsg += "\n";
emsg += ProcessResult_.ErrorMessage;
@ -529,7 +549,7 @@ bool cmQtAutoGeneratorRcc::GenerateRcc()
Log().ErrorCommand(GeneratorT::RCC, emsg, Process_->Setup().Command,
ProcessResult_.StdOut);
}
FileSys().FileRemove(RccFileBuild_);
FileSys().FileRemove(RccFileOutput_);
Error_ = true;
}
// Clean up
@ -545,7 +565,7 @@ bool cmQtAutoGeneratorRcc::GenerateRcc()
cmd.push_back(RccExecutable_);
cmd.insert(cmd.end(), Options_.begin(), Options_.end());
cmd.push_back("-o");
cmd.push_back(RccFileBuild_);
cmd.push_back(RccFileOutput_);
cmd.push_back(QrcFile_);
// We're done here if the process fails to start
return !StartProcess(AutogenBuildDir_, cmd, true);
@ -557,32 +577,34 @@ bool cmQtAutoGeneratorRcc::GenerateRcc()
void cmQtAutoGeneratorRcc::GenerateWrapper()
{
// Generate a wrapper source file on demand
if (MultiConfig_ == MultiConfigT::WRAPPER) {
// Wrapper file name
std::string const& wrapperAbs = RccFile_;
if (IsMultiConfig()) {
// Wrapper file content
std::string content = "// This is an autogenerated configuration "
"wrapper file. Changes will be overwritten.\n"
"#include \"";
content += cmSystemTools::GetFilenameName(RccFileBuild_);
content += "\"\n";
std::string content;
content += "// This is an autogenerated configuration wrapper file.\n";
content += "// Changes will be overwritten.\n";
content += "#include <";
content += MultiConfigOutput();
content += ">\n";
// Write content to file
if (FileSys().FileDiffers(wrapperAbs, content)) {
if (FileSys().FileDiffers(RccFilePublic_, content)) {
// Write new wrapper file
if (Log().Verbose()) {
Log().Info(GeneratorT::RCC, "Generating RCC wrapper " + wrapperAbs);
Log().Info(GeneratorT::RCC,
"Generating RCC wrapper file " + RccFilePublic_);
}
if (!FileSys().FileWrite(GeneratorT::RCC, wrapperAbs, content)) {
Log().ErrorFile(GeneratorT::RCC, wrapperAbs,
if (!FileSys().FileWrite(GeneratorT::RCC, RccFilePublic_, content)) {
Log().ErrorFile(GeneratorT::RCC, RccFilePublic_,
"RCC wrapper file writing failed");
Error_ = true;
}
} else if (BuildFileChanged_) {
// Just touch the wrapper file
if (Log().Verbose()) {
Log().Info(GeneratorT::RCC, "Touching RCC wrapper " + wrapperAbs);
Log().Info(GeneratorT::RCC,
"Touching RCC wrapper file " + RccFilePublic_);
}
FileSys().Touch(wrapperAbs);
FileSys().Touch(RccFilePublic_);
}
}
}

View File

@ -5,7 +5,6 @@
#include "cmConfigure.h" // IWYU pragma: keep
#include "cmQtAutoGen.h"
#include "cmQtAutoGenerator.h"
#include "cm_uv.h"
@ -26,7 +25,7 @@ private:
// -- Types
/// @brief Processing stage
enum class StageT
enum class StageT : unsigned char
{
SETTINGS_READ,
TEST_QRC_RCC_FILES,
@ -62,17 +61,18 @@ private:
void GenerateWrapper();
// -- Utility
bool IsMultiConfig() const { return MultiConfig_; }
std::string MultiConfigOutput() const;
bool StartProcess(std::string const& workingDirectory,
std::vector<std::string> const& command,
bool mergedOutput);
private:
// -- Config settings
bool SettingsChanged_;
std::string ConfigSuffix_;
MultiConfigT MultiConfig_;
bool MultiConfig_;
// -- Directories
std::string AutogenBuildDir_;
std::string IncludeDir_;
// -- Qt environment
std::string RccExecutable_;
std::vector<std::string> RccListOptions_;
@ -80,9 +80,10 @@ private:
std::string QrcFile_;
std::string QrcFileName_;
std::string QrcFileDir_;
std::string RccFile_;
std::string RccFileWrapper_;
std::string RccFileBuild_;
std::string RccPathChecksum_;
std::string RccFileName_;
std::string RccFileOutput_;
std::string RccFilePublic_;
std::vector<std::string> Options_;
std::vector<std::string> Inputs_;
// -- Subprocess
@ -91,6 +92,7 @@ private:
// -- Settings file
std::string SettingsFile_;
std::string SettingsString_;
bool SettingsChanged_;
// -- libuv loop
StageT Stage_;
bool Error_;