mirror of
https://github.com/Kitware/CMake.git
synced 2026-02-17 12:40:40 -06:00
Autogen: Pass explicit predefines header to moc if possible
Qt is relying on whoever calls moc to include a file with the predefined values that will be used by the compiler, otherwise moc takes wrong paths and weird things happen. Instead, generate an include file and feed it to all mocs to make sure it's generating correct code. Co-Author: Sebastian Holtermann <sebholt@xwmw.org> Fixes: #16640
This commit is contained in:
@@ -21,6 +21,7 @@ set(AM_MOC_INCLUDES @_moc_incs@)
|
|||||||
set(AM_MOC_OPTIONS @_moc_options@)
|
set(AM_MOC_OPTIONS @_moc_options@)
|
||||||
set(AM_MOC_RELAXED_MODE @_moc_relaxed_mode@)
|
set(AM_MOC_RELAXED_MODE @_moc_relaxed_mode@)
|
||||||
set(AM_MOC_DEPEND_FILTERS @_moc_depend_filters@)
|
set(AM_MOC_DEPEND_FILTERS @_moc_depend_filters@)
|
||||||
|
set(AM_MOC_PREDEFS_CMD @_moc_predefs_cmd@)
|
||||||
# UIC settings
|
# UIC settings
|
||||||
set(AM_UIC_SKIP @_uic_skip@)
|
set(AM_UIC_SKIP @_uic_skip@)
|
||||||
set(AM_UIC_TARGET_OPTIONS @_uic_target_options@)
|
set(AM_UIC_TARGET_OPTIONS @_uic_target_options@)
|
||||||
|
|||||||
@@ -22,5 +22,7 @@ else()
|
|||||||
string(APPEND CMAKE_${lang}_FLAGS_MINSIZEREL_INIT " -Os")
|
string(APPEND CMAKE_${lang}_FLAGS_MINSIZEREL_INIT " -Os")
|
||||||
string(APPEND CMAKE_${lang}_FLAGS_RELEASE_INIT " -O3")
|
string(APPEND CMAKE_${lang}_FLAGS_RELEASE_INIT " -O3")
|
||||||
string(APPEND CMAKE_${lang}_FLAGS_RELWITHDEBINFO_INIT " -O2 -g")
|
string(APPEND CMAKE_${lang}_FLAGS_RELWITHDEBINFO_INIT " -O2 -g")
|
||||||
|
|
||||||
|
set(CMAKE_${lang}_COMPILER_PREDEFINES_COMMAND "${CMAKE_${lang}_COMPILER}" "-QdM" "-P" "-Za" "${CMAKE_ROOT}/Modules/CMakeCXXCompilerABI.cpp")
|
||||||
endmacro()
|
endmacro()
|
||||||
endif()
|
endif()
|
||||||
|
|||||||
@@ -12,4 +12,5 @@ macro(__linux_compiler_gnu lang)
|
|||||||
# We pass this for historical reasons. Projects may have
|
# We pass this for historical reasons. Projects may have
|
||||||
# executables that use dlopen but do not set ENABLE_EXPORTS.
|
# executables that use dlopen but do not set ENABLE_EXPORTS.
|
||||||
set(CMAKE_SHARED_LIBRARY_LINK_${lang}_FLAGS "-rdynamic")
|
set(CMAKE_SHARED_LIBRARY_LINK_${lang}_FLAGS "-rdynamic")
|
||||||
|
set(CMAKE_${lang}_COMPILER_PREDEFINES_COMMAND "${CMAKE_${lang}_COMPILER}" "-dM" "-E" "-c" "${CMAKE_ROOT}/Modules/CMakeCXXCompilerABI.cpp")
|
||||||
endmacro()
|
endmacro()
|
||||||
|
|||||||
@@ -96,6 +96,41 @@ static std::string GetQtMajorVersion(cmGeneratorTarget const* target)
|
|||||||
return qtMajorVersion;
|
return qtMajorVersion;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static std::string GetQtMinorVersion(cmGeneratorTarget const* target,
|
||||||
|
const std::string& qtMajorVersion)
|
||||||
|
{
|
||||||
|
cmMakefile* makefile = target->Target->GetMakefile();
|
||||||
|
std::string qtMinorVersion;
|
||||||
|
if (qtMajorVersion == "5") {
|
||||||
|
qtMinorVersion = makefile->GetSafeDefinition("Qt5Core_VERSION_MINOR");
|
||||||
|
}
|
||||||
|
if (qtMinorVersion.empty()) {
|
||||||
|
qtMinorVersion = makefile->GetSafeDefinition("QT_VERSION_MINOR");
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* targetQtVersion =
|
||||||
|
target->GetLinkInterfaceDependentStringProperty("QT_MINOR_VERSION", "");
|
||||||
|
if (targetQtVersion != CM_NULLPTR) {
|
||||||
|
qtMinorVersion = targetQtVersion;
|
||||||
|
}
|
||||||
|
return qtMinorVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool QtVersionGreaterOrEqual(const std::string& major,
|
||||||
|
const std::string& minor,
|
||||||
|
unsigned long requestMajor,
|
||||||
|
unsigned long requestMinor)
|
||||||
|
{
|
||||||
|
unsigned long majorUL(0);
|
||||||
|
unsigned long minorUL(0);
|
||||||
|
if (cmSystemTools::StringToULong(major.c_str(), &majorUL) &&
|
||||||
|
cmSystemTools::StringToULong(minor.c_str(), &minorUL)) {
|
||||||
|
return (majorUL > requestMajor) ||
|
||||||
|
(majorUL == requestMajor && minorUL >= requestMinor);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
static void GetCompileDefinitionsAndDirectories(
|
static void GetCompileDefinitionsAndDirectories(
|
||||||
cmGeneratorTarget const* target, const std::string& config,
|
cmGeneratorTarget const* target, const std::string& config,
|
||||||
std::string& incs, std::string& defs)
|
std::string& incs, std::string& defs)
|
||||||
@@ -258,6 +293,12 @@ static void MocSetupAutoTarget(
|
|||||||
AddDefinitionEscaped(makefile, "_moc_depend_filters",
|
AddDefinitionEscaped(makefile, "_moc_depend_filters",
|
||||||
GetSafeProperty(target, "AUTOMOC_DEPEND_FILTERS"));
|
GetSafeProperty(target, "AUTOMOC_DEPEND_FILTERS"));
|
||||||
|
|
||||||
|
if (QtVersionGreaterOrEqual(
|
||||||
|
qtMajorVersion, GetQtMinorVersion(target, qtMajorVersion), 5, 8)) {
|
||||||
|
AddDefinitionEscaped(
|
||||||
|
makefile, "_moc_predefs_cmd",
|
||||||
|
makefile->GetSafeDefinition("CMAKE_CXX_COMPILER_PREDEFINES_COMMAND"));
|
||||||
|
}
|
||||||
// Moc includes and compile definitions
|
// Moc includes and compile definitions
|
||||||
{
|
{
|
||||||
std::string _moc_incs;
|
std::string _moc_incs;
|
||||||
|
|||||||
@@ -360,6 +360,8 @@ bool cmQtAutoGenerators::ReadAutogenInfoFile(
|
|||||||
InfoGet(makefile, "AM_QT_MOC_EXECUTABLE", this->MocExecutable);
|
InfoGet(makefile, "AM_QT_MOC_EXECUTABLE", this->MocExecutable);
|
||||||
InfoGet(makefile, "AM_QT_UIC_EXECUTABLE", this->UicExecutable);
|
InfoGet(makefile, "AM_QT_UIC_EXECUTABLE", this->UicExecutable);
|
||||||
InfoGet(makefile, "AM_QT_RCC_EXECUTABLE", this->RccExecutable);
|
InfoGet(makefile, "AM_QT_RCC_EXECUTABLE", this->RccExecutable);
|
||||||
|
|
||||||
|
InfoGet(makefile, "AM_MOC_PREDEFS_CMD", this->MocPredefsCmd);
|
||||||
// Check Qt version
|
// Check Qt version
|
||||||
if ((this->QtMajorVersion != "4") && (this->QtMajorVersion != "5")) {
|
if ((this->QtMajorVersion != "4") && (this->QtMajorVersion != "5")) {
|
||||||
this->LogError("AutoGen: Error: Unsupported Qt version: " +
|
this->LogError("AutoGen: Error: Unsupported Qt version: " +
|
||||||
@@ -579,6 +581,12 @@ void cmQtAutoGenerators::Init(cmMakefile* makefile)
|
|||||||
|
|
||||||
this->MocCppFilenameAbs = this->CurrentBinaryDir + this->MocCppFilenameRel;
|
this->MocCppFilenameAbs = this->CurrentBinaryDir + this->MocCppFilenameRel;
|
||||||
|
|
||||||
|
// Moc predefs file
|
||||||
|
if (!this->MocPredefsCmd.empty()) {
|
||||||
|
this->MocPredefsFileRel = this->AutogenBuildSubDir + "moc_predefs.h";
|
||||||
|
this->MocPredefsFileAbs = this->CurrentBinaryDir + this->MocPredefsFileRel;
|
||||||
|
}
|
||||||
|
|
||||||
// Init file path checksum generator
|
// Init file path checksum generator
|
||||||
fpathCheckSum.setupParentDirs(this->CurrentSourceDir, this->CurrentBinaryDir,
|
fpathCheckSum.setupParentDirs(this->CurrentSourceDir, this->CurrentBinaryDir,
|
||||||
this->ProjectSourceDir,
|
this->ProjectSourceDir,
|
||||||
@@ -1142,6 +1150,50 @@ bool cmQtAutoGenerators::MocGenerateAll(
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Generate moc_predefs
|
||||||
|
if (!this->MocPredefsCmd.empty()) {
|
||||||
|
if (!this->MakeParentDirectory(this->MocPredefsFileAbs)) {
|
||||||
|
this->LogError("AutoMoc: Error creating directory for " +
|
||||||
|
this->MocPredefsFileRel);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
this->LogBold("Generating MOC predefs " + this->MocPredefsFileRel);
|
||||||
|
|
||||||
|
std::vector<std::string> cmd = this->MocPredefsCmd;
|
||||||
|
cmd.insert(cmd.end(), this->MocIncludes.begin(), this->MocIncludes.end());
|
||||||
|
for (std::vector<std::string>::const_iterator it =
|
||||||
|
this->MocDefinitions.begin();
|
||||||
|
it != this->MocDefinitions.end(); ++it) {
|
||||||
|
cmd.push_back("-D" + (*it));
|
||||||
|
}
|
||||||
|
cmd.insert(cmd.end(), this->MocOptions.begin(), this->MocOptions.end());
|
||||||
|
|
||||||
|
std::string output;
|
||||||
|
bool moc_predefsGenerated = this->RunCommand(cmd, output, false);
|
||||||
|
if (!moc_predefsGenerated) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// actually write the file
|
||||||
|
cmsys::ofstream outfile;
|
||||||
|
outfile.open(this->MocPredefsFileAbs.c_str(), std::ios::trunc);
|
||||||
|
if (!outfile) {
|
||||||
|
moc_predefsGenerated = false;
|
||||||
|
this->LogError("AutoMoc: Error opening " + this->MocPredefsFileRel);
|
||||||
|
} else {
|
||||||
|
outfile << output;
|
||||||
|
// Check for write errors
|
||||||
|
if (!outfile.good()) {
|
||||||
|
moc_predefsGenerated = false;
|
||||||
|
this->LogError("AutoMoc: Error writing " + this->MocPredefsFileRel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!moc_predefsGenerated) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool mocCompFileGenerated = false;
|
bool mocCompFileGenerated = false;
|
||||||
bool mocCompChanged = false;
|
bool mocCompChanged = false;
|
||||||
|
|
||||||
@@ -1305,6 +1357,10 @@ bool cmQtAutoGenerators::MocGenerateFile(
|
|||||||
cmd.push_back("-D" + (*it));
|
cmd.push_back("-D" + (*it));
|
||||||
}
|
}
|
||||||
cmd.insert(cmd.end(), this->MocOptions.begin(), this->MocOptions.end());
|
cmd.insert(cmd.end(), this->MocOptions.begin(), this->MocOptions.end());
|
||||||
|
if (!this->MocPredefsFileAbs.empty()) {
|
||||||
|
cmd.push_back("--include");
|
||||||
|
cmd.push_back(this->MocPredefsFileAbs);
|
||||||
|
}
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
cmd.push_back("-DWIN32");
|
cmd.push_back("-DWIN32");
|
||||||
#endif
|
#endif
|
||||||
@@ -1805,7 +1861,7 @@ bool cmQtAutoGenerators::MakeParentDirectory(const std::string& filename) const
|
|||||||
* @return True on success
|
* @return True on success
|
||||||
*/
|
*/
|
||||||
bool cmQtAutoGenerators::RunCommand(const std::vector<std::string>& command,
|
bool cmQtAutoGenerators::RunCommand(const std::vector<std::string>& command,
|
||||||
std::string& output) const
|
std::string& output, bool verbose) const
|
||||||
{
|
{
|
||||||
// Log command
|
// Log command
|
||||||
if (this->Verbose) {
|
if (this->Verbose) {
|
||||||
@@ -1813,8 +1869,9 @@ bool cmQtAutoGenerators::RunCommand(const std::vector<std::string>& command,
|
|||||||
}
|
}
|
||||||
// Execute command
|
// Execute command
|
||||||
int retVal = 0;
|
int retVal = 0;
|
||||||
bool res =
|
bool res = cmSystemTools::RunSingleCommand(
|
||||||
cmSystemTools::RunSingleCommand(command, &output, &output, &retVal);
|
command, &output, &output, &retVal, CM_NULLPTR,
|
||||||
|
verbose ? cmSystemTools::OUTPUT_MERGE : cmSystemTools::OUTPUT_NONE);
|
||||||
return (res && (retVal == 0));
|
return (res && (retVal == 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -142,8 +142,8 @@ private:
|
|||||||
const char* basePrefix,
|
const char* basePrefix,
|
||||||
const char* baseSuffix) const;
|
const char* baseSuffix) const;
|
||||||
bool MakeParentDirectory(const std::string& filename) const;
|
bool MakeParentDirectory(const std::string& filename) const;
|
||||||
bool RunCommand(const std::vector<std::string>& command,
|
bool RunCommand(const std::vector<std::string>& command, std::string& output,
|
||||||
std::string& output) const;
|
bool verbose = true) const;
|
||||||
|
|
||||||
bool FindHeader(std::string& header, const std::string& testBasePath) const;
|
bool FindHeader(std::string& header, const std::string& testBasePath) const;
|
||||||
|
|
||||||
@@ -176,6 +176,8 @@ private:
|
|||||||
// - Moc
|
// - Moc
|
||||||
std::string MocCppFilenameRel;
|
std::string MocCppFilenameRel;
|
||||||
std::string MocCppFilenameAbs;
|
std::string MocCppFilenameAbs;
|
||||||
|
std::string MocPredefsFileRel;
|
||||||
|
std::string MocPredefsFileAbs;
|
||||||
std::vector<std::string> MocSkipList;
|
std::vector<std::string> MocSkipList;
|
||||||
std::vector<std::string> MocIncludePaths;
|
std::vector<std::string> MocIncludePaths;
|
||||||
std::vector<std::string> MocIncludes;
|
std::vector<std::string> MocIncludes;
|
||||||
@@ -197,6 +199,8 @@ private:
|
|||||||
MacroFilter MacroFilters[2];
|
MacroFilter MacroFilters[2];
|
||||||
cmsys::RegularExpression RegExpMocInclude;
|
cmsys::RegularExpression RegExpMocInclude;
|
||||||
cmsys::RegularExpression RegExpUicInclude;
|
cmsys::RegularExpression RegExpUicInclude;
|
||||||
|
// - moc_predefs
|
||||||
|
std::vector<std::string> MocPredefsCmd;
|
||||||
// - Flags
|
// - Flags
|
||||||
bool IncludeProjectDirsBefore;
|
bool IncludeProjectDirsBefore;
|
||||||
bool Verbose;
|
bool Verbose;
|
||||||
|
|||||||
Reference in New Issue
Block a user