add_subdirectory: Run subdirectory install rules in correct order

Before this change, install rules created by add_subdirectory()
would be executed after all of the top-level install rules, even
if they were declared before the top-level rules. This change
adds a new policy, CMP0082, which interleaves the add_subdirectory()
install rules with the other install rules so they are run in the
correct order.
This commit is contained in:
Kyle Edwards
2018-10-02 16:38:26 -04:00
parent 514f0b572e
commit fc8955e889
14 changed files with 235 additions and 19 deletions
+2
View File
@@ -260,6 +260,8 @@ set(SRCS
cmInstallFilesGenerator.cxx
cmInstallScriptGenerator.h
cmInstallScriptGenerator.cxx
cmInstallSubdirectoryGenerator.h
cmInstallSubdirectoryGenerator.cxx
cmInstallTargetGenerator.h
cmInstallTargetGenerator.cxx
cmInstallDirectoryGenerator.h
+13
View File
@@ -22,6 +22,19 @@ cmInstallGenerator::~cmInstallGenerator()
{
}
bool cmInstallGenerator::HaveInstall()
{
return true;
}
void cmInstallGenerator::CheckCMP0082(bool& haveSubdirectoryInstall,
bool& haveInstallAfterSubdirectory)
{
if (haveSubdirectoryInstall) {
haveInstallAfterSubdirectory = true;
}
}
void cmInstallGenerator::AddInstallRule(
std::ostream& os, std::string const& dest, cmInstallType type,
std::vector<std::string> const& files, bool optional /* = false */,
+4
View File
@@ -38,6 +38,10 @@ public:
bool exclude_from_all);
~cmInstallGenerator() override;
virtual bool HaveInstall();
virtual void CheckCMP0082(bool& haveSubdirectoryInstall,
bool& haveInstallAfterSubdirectory);
void AddInstallRule(
std::ostream& os, std::string const& dest, cmInstallType type,
std::vector<std::string> const& files, bool optional = false,
+2 -2
View File
@@ -37,9 +37,9 @@ void cmInstallScriptGenerator::AddScriptInstallRule(std::ostream& os,
std::string const& script)
{
if (this->Code) {
os << indent.Next() << script << "\n";
os << indent << script << "\n";
} else {
os << indent.Next() << "include(\"" << script << "\")\n";
os << indent << "include(\"" << script << "\")\n";
}
}
+77
View File
@@ -0,0 +1,77 @@
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmInstallSubdirectoryGenerator.h"
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
#include "cmPolicies.h"
#include "cmScriptGenerator.h"
#include "cmSystemTools.h"
#include <sstream>
#include <vector>
cmInstallSubdirectoryGenerator::cmInstallSubdirectoryGenerator(
cmMakefile* makefile, const char* binaryDirectory, bool excludeFromAll)
: cmInstallGenerator(nullptr, std::vector<std::string>(), nullptr,
MessageDefault, excludeFromAll)
, Makefile(makefile)
, BinaryDirectory(binaryDirectory)
{
}
cmInstallSubdirectoryGenerator::~cmInstallSubdirectoryGenerator()
{
}
bool cmInstallSubdirectoryGenerator::HaveInstall()
{
for (auto generator : this->Makefile->GetInstallGenerators()) {
if (generator->HaveInstall()) {
return true;
}
}
return false;
}
void cmInstallSubdirectoryGenerator::CheckCMP0082(
bool& haveSubdirectoryInstall, bool& /*unused*/)
{
if (this->HaveInstall()) {
haveSubdirectoryInstall = true;
}
}
void cmInstallSubdirectoryGenerator::Compute(cmLocalGenerator* lg)
{
this->LocalGenerator = lg;
}
void cmInstallSubdirectoryGenerator::GenerateScript(std::ostream& os)
{
if (!this->ExcludeFromAll) {
cmPolicies::PolicyStatus status =
this->LocalGenerator->GetPolicyStatus(cmPolicies::CMP0082);
switch (status) {
case cmPolicies::WARN:
case cmPolicies::OLD:
// OLD behavior is handled in cmLocalGenerator::GenerateInstallRules()
break;
case cmPolicies::NEW:
case cmPolicies::REQUIRED_IF_USED:
case cmPolicies::REQUIRED_ALWAYS: {
Indent indent;
std::string odir = this->BinaryDirectory;
cmSystemTools::ConvertToUnixSlashes(odir);
os << indent << "if(NOT CMAKE_INSTALL_LOCAL_ONLY)\n"
<< indent.Next()
<< "# Include the install script for the subdirectory.\n"
<< indent.Next() << "include(\"" << odir
<< "/cmake_install.cmake\")\n"
<< indent << "endif()\n\n";
} break;
}
}
}
+41
View File
@@ -0,0 +1,41 @@
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmInstallSubdirectoryGenerator_h
#define cmInstallSubdirectoryGenerator_h
#include "cmConfigure.h" // IWYU pragma: keep
#include "cmInstallGenerator.h"
#include <iosfwd>
#include <string>
class cmLocalGenerator;
class cmMakefile;
/** \class cmInstallSubdirectoryGenerator
* \brief Generate target installation rules.
*/
class cmInstallSubdirectoryGenerator : public cmInstallGenerator
{
public:
cmInstallSubdirectoryGenerator(cmMakefile* makefile,
const char* binaryDirectory,
bool excludeFromAll);
~cmInstallSubdirectoryGenerator() override;
bool HaveInstall() override;
void CheckCMP0082(bool& haveSubdirectoryInstall,
bool& haveInstallAfterSubdirectory) override;
void Compute(cmLocalGenerator* lg) override;
protected:
void GenerateScript(std::ostream& os) override;
cmMakefile* Makefile;
std::string BinaryDirectory;
cmLocalGenerator* LocalGenerator;
};
#endif
+47 -16
View File
@@ -517,31 +517,62 @@ void cmLocalGenerator::GenerateInstallRules()
}
// Ask each install generator to write its code.
cmPolicies::PolicyStatus status = this->GetPolicyStatus(cmPolicies::CMP0082);
std::vector<cmInstallGenerator*> const& installers =
this->Makefile->GetInstallGenerators();
for (cmInstallGenerator* installer : installers) {
installer->Generate(fout, config, configurationTypes);
bool haveSubdirectoryInstall = false;
bool haveInstallAfterSubdirectory = false;
if (status == cmPolicies::WARN) {
for (cmInstallGenerator* installer : installers) {
installer->CheckCMP0082(haveSubdirectoryInstall,
haveInstallAfterSubdirectory);
installer->Generate(fout, config, configurationTypes);
}
} else {
for (cmInstallGenerator* installer : installers) {
installer->Generate(fout, config, configurationTypes);
}
}
// Write rules from old-style specification stored in targets.
this->GenerateTargetInstallRules(fout, config, configurationTypes);
// Include install scripts from subdirectories.
std::vector<cmStateSnapshot> children =
this->Makefile->GetStateSnapshot().GetChildren();
if (!children.empty()) {
fout << "if(NOT CMAKE_INSTALL_LOCAL_ONLY)\n";
fout << " # Include the install script for each subdirectory.\n";
for (cmStateSnapshot const& c : children) {
if (!c.GetDirectory().GetPropertyAsBool("EXCLUDE_FROM_ALL")) {
std::string odir = c.GetDirectory().GetCurrentBinary();
cmSystemTools::ConvertToUnixSlashes(odir);
fout << " include(\"" << odir << "/cmake_install.cmake\")"
<< std::endl;
switch (status) {
case cmPolicies::WARN:
if (haveInstallAfterSubdirectory &&
this->Makefile->PolicyOptionalWarningEnabled(
"CMAKE_POLICY_WARNING_CMP0082")) {
std::ostringstream e;
e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0082) << "\n";
this->IssueMessage(cmake::AUTHOR_WARNING, e.str());
}
}
fout << "\n";
fout << "endif()\n\n";
CM_FALLTHROUGH;
case cmPolicies::OLD: {
std::vector<cmStateSnapshot> children =
this->Makefile->GetStateSnapshot().GetChildren();
if (!children.empty()) {
fout << "if(NOT CMAKE_INSTALL_LOCAL_ONLY)\n";
fout << " # Include the install script for each subdirectory.\n";
for (cmStateSnapshot const& c : children) {
if (!c.GetDirectory().GetPropertyAsBool("EXCLUDE_FROM_ALL")) {
std::string odir = c.GetDirectory().GetCurrentBinary();
cmSystemTools::ConvertToUnixSlashes(odir);
fout << " include(\"" << odir << "/cmake_install.cmake\")"
<< std::endl;
}
}
fout << "\n";
fout << "endif()\n\n";
}
} break;
case cmPolicies::REQUIRED_IF_USED:
case cmPolicies::REQUIRED_ALWAYS:
case cmPolicies::NEW:
// NEW behavior is handled in
// cmInstallSubdirectoryGenerator::GenerateScript()
break;
}
// Record the install manifest.
+4
View File
@@ -28,6 +28,7 @@
#include "cmGeneratorExpressionEvaluationFile.h"
#include "cmGlobalGenerator.h"
#include "cmInstallGenerator.h" // IWYU pragma: keep
#include "cmInstallSubdirectoryGenerator.h"
#include "cmListFileCache.h"
#include "cmSourceFile.h"
#include "cmSourceFileLocation.h"
@@ -1669,6 +1670,9 @@ void cmMakefile::AddSubDirectory(const std::string& srcPath,
} else {
this->UnConfiguredDirectories.push_back(subMf);
}
this->AddInstallGenerator(new cmInstallSubdirectoryGenerator(
subMf, binPath.c_str(), excludeFromAll));
}
const std::string& cmMakefile::GetCurrentSourceDirectory() const
+5 -1
View File
@@ -240,7 +240,11 @@ class cmMakefile;
cmPolicies::WARN) \
SELECT(POLICY, CMP0081, \
"Relative paths not allowed in LINK_DIRECTORIES target property.", \
3, 13, 0, cmPolicies::WARN)
3, 13, 0, cmPolicies::WARN) \
SELECT(POLICY, CMP0082, \
"Install rules from add_subdirectory() are interleaved with those " \
"in caller.", \
3, 14, 0, cmPolicies::WARN)
#define CM_SELECT_ID(F, A1, A2, A3, A4, A5, A6) F(A1)
#define CM_FOR_EACH_POLICY_ID(POLICY) \