Autogen: Process .hh headers based on new policy CMP0100 settings

Reintroduces .hh header processing in AUTOMOC and AUTOUIC based on the new
policy CMP0100 setting.

Fixes: #13904 CMAKE_AUTOMOC misses headers with ".hh" extension
This commit is contained in:
Sebastian Holtermann
2019-12-30 14:22:28 +01:00
parent 4db1463e05
commit abad139c99
6 changed files with 140 additions and 41 deletions

View File

@@ -57,6 +57,7 @@ Policies Introduced by CMake 3.17
.. toctree::
:maxdepth: 1
CMP0100: Let AUTOMOC and AUTOUIC process .hh header files. </policy/CMP0100>
CMP0099: Link properties are transitive over private dependency on static libraries. </policy/CMP0099>
CMP0098: FindFLEX runs flex in CMAKE_CURRENT_BINARY_DIR when executing. </policy/CMP0098>

40
Help/policy/CMP0100.rst Normal file
View File

@@ -0,0 +1,40 @@
CMP0100
-------
Let :prop_tgt:`AUTOMOC` and :prop_tgt:`AUTOUIC` process
header files that end with a ``.hh`` extension.
Since version 3.17, CMake processes header files that end with a
``.hh`` extension in :prop_tgt:`AUTOMOC` and :prop_tgt:`AUTOUIC`.
In earlier CMake versions, these header files were ignored by
:prop_tgt:`AUTOMOC` and :prop_tgt:`AUTOUIC`.
This policy affects how header files that end with a ``.hh`` extension
get treated in :prop_tgt:`AUTOMOC` and :prop_tgt:`AUTOUIC`.
The ``OLD`` behavior for this policy is to ignore ``.hh`` header files
in :prop_tgt:`AUTOMOC` and :prop_tgt:`AUTOUIC`.
The ``NEW`` behavior for this policy is to process ``.hh`` header files
in :prop_tgt:`AUTOMOC` and :prop_tgt:`AUTOUIC` just like other header files.
.. note::
To silence the ``CMP0100`` warning source files can be excluded from
:prop_tgt:`AUTOMOC` and :prop_tgt:`AUTOUIC` processing by setting the
source file properties :prop_sf:`SKIP_AUTOMOC`, :prop_sf:`SKIP_AUTOUIC` or
:prop_sf:`SKIP_AUTOGEN`.
.. code-block:: cmake
# Source skip example:
set_property(SOURCE /path/to/file1.hh PROPERTY SKIP_AUTOMOC ON)
set_property(SOURCE /path/to/file2.hh PROPERTY SKIP_AUTOUIC ON)
set_property(SOURCE /path/to/file3.hh PROPERTY SKIP_AUTOGEN ON)
This policy was introduced in CMake version 3.17.0. CMake version
|release| warns when the policy is not set and uses ``OLD`` behavior.
Use the :command:`cmake_policy` command to set it to ``OLD`` or ``NEW``
explicitly.
.. include:: DEPRECATED.txt

View File

@@ -0,0 +1,6 @@
autogen_hh_headers
------------------
* :prop_tgt:`AUTOMOC` and :prop_tgt:`AUTOUIC` learned to process headers with
a ``.hh`` extension. The new behavior is enabled by policy
:policy:`CMP0100`.

View File

@@ -297,7 +297,9 @@ class cmMakefile;
SELECT(POLICY, CMP0099, \
"Link properties are transitive over private dependency on static " \
"libraries.", \
3, 17, 0, cmPolicies::WARN)
3, 17, 0, cmPolicies::WARN) \
SELECT(POLICY, CMP0100, "Let AUTOMOC and AUTOUIC process .hh files.", 3, \
17, 0, cmPolicies::WARN)
#define CM_SELECT_ID(F, A1, A2, A3, A4, A5, A6) F(A1)
#define CM_FOR_EACH_POLICY_ID(POLICY) \

View File

@@ -42,6 +42,7 @@
#include "cmSourceGroup.h"
#include "cmState.h"
#include "cmStateTypes.h"
#include "cmString.hxx"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmTarget.h"
@@ -354,24 +355,38 @@ bool cmQtAutoGenInitializer::InitCustomTargets()
}
}
// Check status of policy CMP0071
{
cmPolicies::PolicyStatus const CMP0071_status =
this->Makefile->GetPolicyStatus(cmPolicies::CMP0071);
switch (CMP0071_status) {
case cmPolicies::WARN:
this->CMP0071Warn = true;
CM_FALLTHROUGH;
case cmPolicies::OLD:
// Ignore GENERATED file
break;
case cmPolicies::REQUIRED_IF_USED:
case cmPolicies::REQUIRED_ALWAYS:
case cmPolicies::NEW:
// Process GENERATED file
this->CMP0071Accept = true;
break;
}
// Check status of policy CMP0071 regarding handling of GENERATED files
switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0071)) {
case cmPolicies::WARN:
// Ignore GENERATED files but warn
this->CMP0071Warn = true;
CM_FALLTHROUGH;
case cmPolicies::OLD:
// Ignore GENERATED files
break;
case cmPolicies::REQUIRED_IF_USED:
case cmPolicies::REQUIRED_ALWAYS:
case cmPolicies::NEW:
// Process GENERATED files
this->CMP0071Accept = true;
break;
}
// Check status of policy CMP0100 regarding handling of .hh headers
switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0100)) {
case cmPolicies::WARN:
// Ignore but .hh files but warn
this->CMP0100Warn = true;
CM_FALLTHROUGH;
case cmPolicies::OLD:
// Ignore .hh files
break;
case cmPolicies::REQUIRED_IF_USED:
case cmPolicies::REQUIRED_ALWAYS:
case cmPolicies::NEW:
// Process .hh file
this->CMP0100Accept = true;
break;
}
// Common directories
@@ -733,15 +748,26 @@ bool cmQtAutoGenInitializer::InitScanFiles()
return muf;
};
auto addMUFile = [&](MUFileHandle&& muf, bool isHeader) {
auto addMUHeader = [this](MUFileHandle&& muf, cm::string_view extension) {
cmSourceFile* sf = muf->SF;
const bool muIt = (muf->MocIt || muf->UicIt);
if (this->CMP0100Accept || (extension != "hh")) {
// Accept
if (muIt && muf->Generated) {
this->AutogenTarget.FilesGenerated.emplace_back(muf.get());
}
this->AutogenTarget.Headers.emplace(sf, std::move(muf));
} else if (muIt && this->CMP0100Warn) {
// Store file for warning message
this->AutogenTarget.CMP0100HeadersWarn.push_back(sf);
}
};
auto addMUSource = [this](MUFileHandle&& muf) {
if ((muf->MocIt || muf->UicIt) && muf->Generated) {
this->AutogenTarget.FilesGenerated.emplace_back(muf.get());
}
if (isHeader) {
this->AutogenTarget.Headers.emplace(muf->SF, std::move(muf));
} else {
this->AutogenTarget.Sources.emplace(muf->SF, std::move(muf));
}
this->AutogenTarget.Sources.emplace(muf->SF, std::move(muf));
};
// Scan through target files
@@ -763,11 +789,10 @@ bool cmQtAutoGenInitializer::InitScanFiles()
// Register files that will be scanned by moc or uic
if (this->MocOrUicEnabled()) {
// FIXME: Add a policy to include .hh files.
if (cm->IsHeaderExtension(extLower) && extLower != "hh") {
addMUFile(makeMUFile(sf, fullPath, true), true);
if (cm->IsHeaderExtension(extLower)) {
addMUHeader(makeMUFile(sf, fullPath, true), extLower);
} else if (cm->IsSourceExtension(extLower)) {
addMUFile(makeMUFile(sf, fullPath, true), false);
addMUSource(makeMUFile(sf, fullPath, true));
}
}
@@ -801,8 +826,6 @@ bool cmQtAutoGenInitializer::InitScanFiles()
// For source files find additional headers and private headers
if (this->MocOrUicEnabled()) {
std::vector<MUFileHandle> extraHeaders;
extraHeaders.reserve(this->AutogenTarget.Sources.size() * 2);
// Header search suffixes and extensions
static std::initializer_list<cm::string_view> const suffixes{ "", "_p" };
auto const& exts = cm->GetHeaderExtensions();
@@ -847,16 +870,12 @@ bool cmQtAutoGenInitializer::InitScanFiles()
if (!muf.UicIt) {
eMuf->UicIt = false;
}
extraHeaders.emplace_back(std::move(eMuf));
addMUHeader(std::move(eMuf), ext);
}
}
}
}
}
// Move generated files to main headers list
for (auto& eMuf : extraHeaders) {
addMUFile(std::move(eMuf), true);
}
}
// Scan through all source files in the makefile to extract moc and uic
@@ -876,19 +895,18 @@ bool cmQtAutoGenInitializer::InitScanFiles()
std::string const& extLower =
cmSystemTools::LowerCase(sf->GetExtension());
// FIXME: Add a policy to include .hh files.
if (cm->IsHeaderExtension(extLower) && extLower != "hh") {
if (cm->IsHeaderExtension(extLower)) {
if (!cmContains(this->AutogenTarget.Headers, sf)) {
auto muf = makeMUFile(sf, fullPath, false);
if (muf->SkipMoc || muf->SkipUic) {
this->AutogenTarget.Headers.emplace(sf, std::move(muf));
addMUHeader(std::move(muf), extLower);
}
}
} else if (cm->IsSourceExtension(extLower)) {
if (!cmContains(this->AutogenTarget.Headers, sf)) {
if (!cmContains(this->AutogenTarget.Sources, sf)) {
auto muf = makeMUFile(sf, fullPath, false);
if (muf->SkipMoc || muf->SkipUic) {
this->AutogenTarget.Sources.emplace(sf, std::move(muf));
addMUSource(std::move(muf));
}
}
} else if (this->Uic.Enabled && (extLower == kw.ui)) {
@@ -946,6 +964,35 @@ bool cmQtAutoGenInitializer::InitScanFiles()
}
}
// Generate CMP0100 warning
if (this->MocOrUicEnabled() &&
!this->AutogenTarget.CMP0100HeadersWarn.empty()) {
cm::string_view property;
if (this->Moc.Enabled && this->Uic.Enabled) {
property = "SKIP_AUTOGEN";
} else if (this->Moc.Enabled) {
property = "SKIP_AUTOMOC";
} else if (this->Uic.Enabled) {
property = "SKIP_AUTOUIC";
}
std::string files;
for (cmSourceFile* sf : this->AutogenTarget.CMP0100HeadersWarn) {
files += cmStrCat(" ", Quoted(sf->GetFullPath()), '\n');
}
this->Makefile->IssueMessage(
MessageType::AUTHOR_WARNING,
cmStrCat(
cmPolicies::GetPolicyWarning(cmPolicies::CMP0100), '\n',
"For compatibility, CMake is excluding the header file(s):\n", files,
"from processing by ",
cmQtAutoGen::Tools(this->Moc.Enabled, this->Uic.Enabled, false),
". If any of the files should be processed, set CMP0100 to NEW. "
"If any of the files should not be processed, "
"explicitly exclude them by setting the source file property ",
property, ":\n set_property(SOURCE file.hh PROPERTY ", property,
" ON)\n"));
}
// Process qrc files
if (!this->Rcc.Qrcs.empty()) {
const bool modernQt = (this->QtVersion.Major >= 5);

View File

@@ -159,6 +159,8 @@ private:
bool MultiConfig = false;
bool CMP0071Accept = false;
bool CMP0071Warn = false;
bool CMP0100Accept = false;
bool CMP0100Warn = false;
std::string ConfigDefault;
std::vector<std::string> ConfigsList;
std::string TargetsFolder;
@@ -192,6 +194,7 @@ private:
std::unordered_map<cmSourceFile*, MUFileHandle> Headers;
std::unordered_map<cmSourceFile*, MUFileHandle> Sources;
std::vector<MUFile*> FilesGenerated;
std::vector<cmSourceFile*> CMP0100HeadersWarn;
} AutogenTarget;
/** moc variables. */