Commit 75819b86 authored by Sebastian Holtermann's avatar Sebastian Holtermann
Browse files

Autogen: Add and use cmQtAutoGenerator base class

Adds the new base class `cmQtAutoGenerator` which contains common
variables and methods used by `cmQtAutoGeneratorMocUic` and
`cmQtAutoGeneratorRcc`.
parent 27ed3b35
......@@ -9,6 +9,7 @@ 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@)
......
......@@ -312,6 +312,8 @@ set(SRCS
cmQtAutoGen.cxx
cmQtAutoGen.h
cmQtAutoGenDigest.h
cmQtAutoGenerator.cxx
cmQtAutoGenerator.h
cmQtAutoGeneratorInitializer.cxx
cmQtAutoGeneratorInitializer.h
cmQtAutoGeneratorMocUic.cxx
......
/* 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));
}
/* 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
......@@ -1061,7 +1061,7 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget(
currentLine.push_back(cmSystemTools::GetCMakeCommand());
currentLine.push_back("-E");
currentLine.push_back("cmake_autogen");
currentLine.push_back(autogenInfoDir);
currentLine.push_back(autogenInfoDir + "/AutogenInfo.cmake");
currentLine.push_back("$<CONFIGURATION>");
commandLines.push_back(std::move(currentLine));
}
......@@ -1197,12 +1197,19 @@ void cmQtAutoGeneratorInitializer::SetupAutoGenerateTarget(
cmQtAutoGen::MultiConfigName(multiConfig));
AddDefinitionEscaped(makefile, "_build_dir",
GetAutogenTargetBuildDir(target));
AddDefinitionEscaped(makefile, "_sources", digest.Sources);
AddDefinitionEscaped(makefile, "_headers", digest.Headers);
AddDefinitionEscaped(makefile, "_qt_version_major", digest.QtVersionMajor);
AddDefinitionEscaped(makefile, "_qt_version_minor", digest.QtVersionMinor);
{
if (digest.MocEnabled || digest.UicEnabled) {
{
std::string settingsFile = GetAutogenTargetFilesDir(target);
cmSystemTools::ConvertToUnixSlashes(settingsFile);
settingsFile += "/AutogenOldSettings.cmake";
AddDefinitionEscaped(makefile, "_settings_file", settingsFile);
}
AddDefinitionEscaped(makefile, "_sources", digest.Sources);
AddDefinitionEscaped(makefile, "_headers", digest.Headers);
SetupAcquireSkipFiles(digest, setup);
if (digest.MocEnabled) {
SetupAutoTargetMoc(digest, configDefault, configsList, setup);
......
This diff is collapsed.
......@@ -7,6 +7,7 @@
#include "cmFilePathChecksum.h"
#include "cmQtAutoGen.h"
#include "cmQtAutoGenerator.h"
#include "cmsys/RegularExpression.hxx"
#include <map>
......@@ -17,12 +18,11 @@
class cmMakefile;
class cmQtAutoGeneratorMocUic
class cmQtAutoGeneratorMocUic : public cmQtAutoGenerator
{
CM_DISABLE_COPY(cmQtAutoGeneratorMocUic)
public:
cmQtAutoGeneratorMocUic();
bool Run(std::string const& targetDirectory, std::string const& config);
private:
// -- Types
......@@ -81,8 +81,7 @@ private:
};
// -- Initialization
bool InitInfoFile(cmMakefile* makefile, std::string const& targetDirectory,
std::string const& config);
bool InitInfoFile(cmMakefile* makefile);
// -- Settings file
void SettingsFileRead(cmMakefile* makefile);
......@@ -93,7 +92,7 @@ private:
}
// -- Central processing
bool Process();
bool Process(cmMakefile* makefile) override;
// -- Source parsing
bool ParseSourceFile(std::string const& absFilename, const SourceJob& job);
......@@ -136,45 +135,14 @@ private:
bool UicGenerateAll();
bool UicGenerateFile(const UicJob& uicJob);
// -- 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;
......
......@@ -3,146 +3,22 @@
#include "cmQtAutoGen.h"
#include "cmQtAutoGeneratorRcc.h"
#include "cmsys/FStream.hxx"
#include "cmsys/Terminal.h"
#include "cmAlgorithms.h"
#include "cmCryptoHash.h"
#include "cmFilePathChecksum.h"
#include "cmGlobalGenerator.h"
#include "cmMakefile.h"
#include "cmOutputConverter.h"
#include "cmStateDirectory.h"
#include "cmStateSnapshot.h"
#include "cmSystemTools.h"
#include "cmake.h"
#if defined(__APPLE__)
#include <unistd.h>
#endif
// -- Static variables
static const char* SettingsKeyRcc = "ARCC_SETTINGS_HASH";
// -- 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;
}
static bool ReadFile(std::string& content, std::string const& filename,
std::string* error = nullptr)
{
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();