mirror of
https://github.com/reactos/CMake.git
synced 2024-12-03 17:11:04 +00:00
Autogen: Add AUTOMOC/UIC support for generated source files
Closes #16186 Closes #14379
This commit is contained in:
parent
e3af6bec67
commit
ea3bc1e5b0
@ -45,6 +45,11 @@ static void utilCopyTargetProperty(cmTarget* destinationTarget,
|
||||
}
|
||||
}
|
||||
|
||||
inline static bool PropertyEnabled(cmSourceFile* sourceFile, const char* key)
|
||||
{
|
||||
return cmSystemTools::IsOn(sourceFile->GetPropertyForUser(key));
|
||||
}
|
||||
|
||||
static std::string GetSafeProperty(cmGeneratorTarget const* target,
|
||||
const char* key)
|
||||
{
|
||||
@ -150,18 +155,12 @@ static void AcquireScanFiles(cmGeneratorTarget const* target,
|
||||
!(fileType == cmSystemTools::HEADER_FILE_FORMAT)) {
|
||||
continue;
|
||||
}
|
||||
if (cmSystemTools::IsOn(sf->GetPropertyForUser("GENERATED"))) {
|
||||
continue;
|
||||
}
|
||||
const std::string absFile =
|
||||
cmsys::SystemTools::GetRealPath(sf->GetFullPath());
|
||||
// Skip flags
|
||||
const bool skipAll =
|
||||
cmSystemTools::IsOn(sf->GetPropertyForUser("SKIP_AUTOGEN"));
|
||||
const bool mocSkip =
|
||||
skipAll || cmSystemTools::IsOn(sf->GetPropertyForUser("SKIP_AUTOMOC"));
|
||||
const bool uicSkip =
|
||||
skipAll || cmSystemTools::IsOn(sf->GetPropertyForUser("SKIP_AUTOUIC"));
|
||||
const bool skipAll = PropertyEnabled(sf, "SKIP_AUTOGEN");
|
||||
const bool mocSkip = skipAll || PropertyEnabled(sf, "SKIP_AUTOMOC");
|
||||
const bool uicSkip = skipAll || PropertyEnabled(sf, "SKIP_AUTOUIC");
|
||||
// Add file name to skip lists.
|
||||
// Do this even when the file is not added to the sources/headers lists
|
||||
// because the file name may be extracted from an other file when
|
||||
@ -478,8 +477,8 @@ static void RccSetupAutoTarget(cmGeneratorTarget const* target,
|
||||
fileIt != srcFiles.end(); ++fileIt) {
|
||||
cmSourceFile* sf = *fileIt;
|
||||
if ((sf->GetExtension() == "qrc") &&
|
||||
!cmSystemTools::IsOn(sf->GetPropertyForUser("SKIP_AUTOGEN")) &&
|
||||
!cmSystemTools::IsOn(sf->GetPropertyForUser("SKIP_AUTORCC"))) {
|
||||
!PropertyEnabled(sf, "SKIP_AUTOGEN") &&
|
||||
!PropertyEnabled(sf, "SKIP_AUTORCC")) {
|
||||
const std::string absFile =
|
||||
cmsys::SystemTools::GetRealPath(sf->GetFullPath());
|
||||
// qrc file
|
||||
@ -488,7 +487,7 @@ static void RccSetupAutoTarget(cmGeneratorTarget const* target,
|
||||
{
|
||||
std::string entriesList = "{";
|
||||
// Read input file list only for non generated .qrc files.
|
||||
if (!cmSystemTools::IsOn(sf->GetPropertyForUser("GENERATED"))) {
|
||||
if (!PropertyEnabled(sf, "GENERATED")) {
|
||||
std::string error;
|
||||
std::vector<std::string> files;
|
||||
if (cmQtAutoGeneratorCommon::RccListInputs(
|
||||
@ -555,7 +554,8 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget(
|
||||
cmSystemTools::CollapseFullPath("", makefile->GetCurrentBinaryDirectory());
|
||||
const std::string qtMajorVersion = GetQtMajorVersion(target);
|
||||
const std::string rccCommand = RccGetExecutable(target, qtMajorVersion);
|
||||
std::vector<std::string> autogenOutputFiles;
|
||||
std::vector<std::string> autogenDepends;
|
||||
std::vector<std::string> autogenProvides;
|
||||
|
||||
// Remove old settings on cleanup
|
||||
{
|
||||
@ -565,31 +565,6 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget(
|
||||
false);
|
||||
}
|
||||
|
||||
// Create autogen target build directory and add it to the clean files
|
||||
cmSystemTools::MakeDirectory(autogenBuildDir);
|
||||
makefile->AppendProperty("ADDITIONAL_MAKE_CLEAN_FILES",
|
||||
autogenBuildDir.c_str(), false);
|
||||
|
||||
if (mocEnabled || uicEnabled) {
|
||||
// Create autogen target includes directory and
|
||||
// add it to the origin target INCLUDE_DIRECTORIES
|
||||
const std::string incsDir = autogenBuildDir + "include";
|
||||
cmSystemTools::MakeDirectory(incsDir);
|
||||
target->AddIncludeDirectory(incsDir, true);
|
||||
}
|
||||
|
||||
if (mocEnabled) {
|
||||
// Register moc compilation file as generated
|
||||
autogenOutputFiles.push_back(autogenBuildDir + "moc_compilation.cpp");
|
||||
}
|
||||
|
||||
// Initialize autogen target dependencies
|
||||
std::vector<std::string> depends;
|
||||
if (const char* autogenDepends =
|
||||
target->GetProperty("AUTOGEN_TARGET_DEPENDS")) {
|
||||
cmSystemTools::ExpandListArgument(autogenDepends, depends);
|
||||
}
|
||||
|
||||
// Compose command lines
|
||||
cmCustomCommandLines commandLines;
|
||||
{
|
||||
@ -628,6 +603,24 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget(
|
||||
autogenComment = "Automatic " + tools + " for target " + target->GetName();
|
||||
}
|
||||
|
||||
// Create autogen target build directory and add it to the clean files
|
||||
cmSystemTools::MakeDirectory(autogenBuildDir);
|
||||
makefile->AppendProperty("ADDITIONAL_MAKE_CLEAN_FILES",
|
||||
autogenBuildDir.c_str(), false);
|
||||
|
||||
// Create autogen target includes directory and
|
||||
// add it to the origin target INCLUDE_DIRECTORIES
|
||||
if (mocEnabled || uicEnabled) {
|
||||
const std::string incsDir = autogenBuildDir + "include";
|
||||
cmSystemTools::MakeDirectory(incsDir);
|
||||
target->AddIncludeDirectory(incsDir, true);
|
||||
}
|
||||
|
||||
// Register moc compilation file as generated
|
||||
if (mocEnabled) {
|
||||
autogenProvides.push_back(autogenBuildDir + "moc_compilation.cpp");
|
||||
}
|
||||
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
bool usePRE_BUILD = false;
|
||||
cmGlobalGenerator* gg = lg->GetGlobalGenerator();
|
||||
@ -639,85 +632,122 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget(
|
||||
// This also works around a VS 11 bug that may skip updating the target:
|
||||
// https://connect.microsoft.com/VisualStudio/feedback/details/769495
|
||||
usePRE_BUILD = vsgg->GetVersion() >= cmGlobalVisualStudioGenerator::VS7;
|
||||
if (usePRE_BUILD) {
|
||||
// If the autogen target depends on an other target
|
||||
// don't use PRE_BUILD
|
||||
for (std::vector<std::string>::iterator it = depends.begin();
|
||||
it != depends.end(); ++it) {
|
||||
if (!makefile->FindTargetToUse(it->c_str())) {
|
||||
usePRE_BUILD = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (rccEnabled) {
|
||||
// Initialize autogen target dependencies
|
||||
if (const char* deps = target->GetProperty("AUTOGEN_TARGET_DEPENDS")) {
|
||||
cmSystemTools::ExpandListArgument(deps, autogenDepends);
|
||||
}
|
||||
// Add link library targets to the autogen dependencies
|
||||
{
|
||||
const cmTarget::LinkLibraryVectorType& libVec =
|
||||
target->Target->GetOriginalLinkLibraries();
|
||||
for (cmTarget::LinkLibraryVectorType::const_iterator it = libVec.begin();
|
||||
it != libVec.end(); ++it) {
|
||||
const std::string& libName = it->first;
|
||||
if (makefile->FindTargetToUse(libName) != CM_NULLPTR) {
|
||||
autogenDepends.push_back(libName);
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
cmFilePathChecksum fpathCheckSum(makefile);
|
||||
// Iterate over all source files
|
||||
std::vector<cmSourceFile*> srcFiles;
|
||||
target->GetConfigCommonSourceFiles(srcFiles);
|
||||
for (std::vector<cmSourceFile*>::const_iterator fileIt = srcFiles.begin();
|
||||
fileIt != srcFiles.end(); ++fileIt) {
|
||||
cmSourceFile* sf = *fileIt;
|
||||
if (sf->GetExtension() == "qrc" &&
|
||||
!cmSystemTools::IsOn(sf->GetPropertyForUser("SKIP_AUTOGEN")) &&
|
||||
!cmSystemTools::IsOn(sf->GetPropertyForUser("SKIP_AUTORCC"))) {
|
||||
{
|
||||
if (!PropertyEnabled(sf, "SKIP_AUTOGEN")) {
|
||||
const std::string ext = sf->GetExtension();
|
||||
// Add generated file that will be scanned by moc or uic to
|
||||
// the dependencies
|
||||
if (mocEnabled || uicEnabled) {
|
||||
const cmSystemTools::FileFormat fileType =
|
||||
cmSystemTools::GetFileFormat(ext.c_str());
|
||||
if ((fileType == cmSystemTools::CXX_FILE_FORMAT) ||
|
||||
(fileType == cmSystemTools::HEADER_FILE_FORMAT)) {
|
||||
if (PropertyEnabled(sf, "GENERATED")) {
|
||||
if ((mocEnabled && !PropertyEnabled(sf, "SKIP_AUTOMOC")) ||
|
||||
(uicEnabled && !PropertyEnabled(sf, "SKIP_AUTOUIC"))) {
|
||||
autogenDepends.push_back(
|
||||
cmsys::SystemTools::GetRealPath(sf->GetFullPath()));
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
// Cannot use PRE_BUILD with generated files
|
||||
usePRE_BUILD = false;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Process rcc enabled files
|
||||
if (rccEnabled && (ext == "qrc") &&
|
||||
!PropertyEnabled(sf, "SKIP_AUTORCC")) {
|
||||
const std::string absFile =
|
||||
cmsys::SystemTools::GetRealPath(sf->GetFullPath());
|
||||
|
||||
// Run cmake again when .qrc file changes
|
||||
makefile->AddCMakeDependFile(absFile);
|
||||
// Compose rcc output file name
|
||||
{
|
||||
std::string rccOut = autogenBuildDir;
|
||||
rccOut += fpathCheckSum.getPart(absFile);
|
||||
rccOut += "/qrc_";
|
||||
rccOut +=
|
||||
cmsys::SystemTools::GetFilenameWithoutLastExtension(absFile);
|
||||
rccOut += ".cpp";
|
||||
|
||||
std::string rccOutputFile = autogenBuildDir;
|
||||
rccOutputFile += fpathCheckSum.getPart(absFile);
|
||||
rccOutputFile += "/qrc_";
|
||||
rccOutputFile +=
|
||||
cmsys::SystemTools::GetFilenameWithoutLastExtension(absFile);
|
||||
rccOutputFile += ".cpp";
|
||||
// Register rcc output file as generated
|
||||
autogenProvides.push_back(rccOut);
|
||||
|
||||
// Add rcc output file to origin target sources
|
||||
cmSourceFile* gf = makefile->GetOrCreateSource(rccOutputFile, true);
|
||||
gf->SetProperty("SKIP_AUTOGEN", "On");
|
||||
target->AddSource(rccOutputFile);
|
||||
// Register rcc output file as generated
|
||||
autogenOutputFiles.push_back(rccOutputFile);
|
||||
// Add rcc output file to origin target sources
|
||||
cmSourceFile* gf = makefile->GetOrCreateSource(rccOut, true);
|
||||
gf->SetProperty("SKIP_AUTOGEN", "On");
|
||||
target->AddSource(rccOut);
|
||||
}
|
||||
|
||||
if (lg->GetGlobalGenerator()->GetName() == "Ninja"
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
|| usePRE_BUILD
|
||||
#endif
|
||||
) {
|
||||
if (!cmSystemTools::IsOn(sf->GetPropertyForUser("GENERATED"))) {
|
||||
{
|
||||
std::string error;
|
||||
if (!cmQtAutoGeneratorCommon::RccListInputs(
|
||||
qtMajorVersion, rccCommand, absFile, depends, &error)) {
|
||||
cmSystemTools::Error(error.c_str());
|
||||
}
|
||||
}
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
// Cannot use PRE_BUILD because the resource files themselves
|
||||
// may not be sources within the target so VS may not know the
|
||||
// target needs to re-build at all.
|
||||
usePRE_BUILD = false;
|
||||
#endif
|
||||
if (PropertyEnabled(sf, "GENERATED")) {
|
||||
// Add generated qrc file to the dependencies
|
||||
autogenDepends.push_back(absFile);
|
||||
} else {
|
||||
// Run cmake again when .qrc file changes
|
||||
makefile->AddCMakeDependFile(absFile);
|
||||
|
||||
// Add the qrc input files to the dependencies
|
||||
std::string error;
|
||||
if (!cmQtAutoGeneratorCommon::RccListInputs(
|
||||
qtMajorVersion, rccCommand, absFile, autogenDepends,
|
||||
&error)) {
|
||||
cmSystemTools::Error(error.c_str());
|
||||
}
|
||||
}
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
// Cannot use PRE_BUILD because the resource files themselves
|
||||
// may not be sources within the target so VS may not know the
|
||||
// target needs to re-build at all.
|
||||
usePRE_BUILD = false;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
if (usePRE_BUILD) {
|
||||
// If the autogen target depends on an other target don't use PRE_BUILD
|
||||
for (std::vector<std::string>::iterator it = autogenDepends.begin();
|
||||
it != autogenDepends.end(); ++it) {
|
||||
if (makefile->FindTargetToUse(*it) != CM_NULLPTR) {
|
||||
usePRE_BUILD = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (usePRE_BUILD) {
|
||||
// Add the pre-build command directly to bypass the OBJECT_LIBRARY
|
||||
// rejection in cmMakefile::AddCustomCommandToTarget because we know
|
||||
// PRE_BUILD will work for an OBJECT_LIBRARY in this specific case.
|
||||
std::vector<std::string> no_output;
|
||||
std::vector<std::string> no_byproducts;
|
||||
cmCustomCommand cc(makefile, no_output, no_byproducts, depends,
|
||||
cmCustomCommand cc(makefile, no_output, autogenProvides, autogenDepends,
|
||||
commandLines, autogenComment.c_str(),
|
||||
workingDirectory.c_str());
|
||||
cc.SetEscapeOldStyle(false);
|
||||
@ -728,7 +758,7 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget(
|
||||
{
|
||||
cmTarget* autogenTarget = makefile->AddUtilityCommand(
|
||||
autogenTargetName, true, workingDirectory.c_str(),
|
||||
/*byproducts=*/autogenOutputFiles, depends, commandLines, false,
|
||||
/*byproducts=*/autogenProvides, autogenDepends, commandLines, false,
|
||||
autogenComment.c_str());
|
||||
|
||||
cmGeneratorTarget* gt = new cmGeneratorTarget(autogenTarget, lg);
|
||||
|
Loading…
Reference in New Issue
Block a user