mirror of
https://github.com/reactos/CMake.git
synced 2025-01-07 11:40:23 +00:00
75819b8626
Adds the new base class `cmQtAutoGenerator` which contains common variables and methods used by `cmQtAutoGeneratorMocUic` and `cmQtAutoGeneratorRcc`.
321 lines
9.0 KiB
C++
321 lines
9.0 KiB
C++
/* 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));
|
|
}
|