Merge topic 'install-DESTINATION-genex'

f30022eb install: Allow generator expressions in TARGETS DESTINATION (#14317)
7607c3d1 cmInstallGenerator: Pass destination explicitly to AddInstallRule
ebd556ca cmInstallGenerator: Fix check for absolute install destinations
290ca8e2 cmInstallGenerator: Refactor computation of absolute install dest
f99991db cmInstallGenerator: Move GetDestination to subclasses that need it
This commit is contained in:
Brad King 2015-02-12 11:53:02 -05:00 committed by CMake Topic Stage
commit fc7e15691a
20 changed files with 79 additions and 26 deletions

View File

@ -159,6 +159,10 @@ file itself, call ``install(EXPORT)``, documented below.
Installing a target with the :prop_tgt:`EXCLUDE_FROM_ALL` target property Installing a target with the :prop_tgt:`EXCLUDE_FROM_ALL` target property
set to ``TRUE`` has undefined behavior. set to ``TRUE`` has undefined behavior.
The install destination given to the target install ``DESTINATION`` may
use "generator expressions" with the syntax ``$<...>``. See the
:manual:`cmake-generator-expressions(7)` manual for available expressions.
Installing Files Installing Files
^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^

View File

@ -0,0 +1,5 @@
install-DESTINATION-genex
-------------------------
* The :command:`install(TARGETS)` command learned to support
generator expressions in the ``DESTINATION`` value.

View File

@ -73,8 +73,8 @@ bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os)
// to reference if they are relative to the install prefix. // to reference if they are relative to the install prefix.
std::string installPrefix = std::string installPrefix =
this->IEGen->GetMakefile()->GetSafeDefinition("CMAKE_INSTALL_PREFIX"); this->IEGen->GetMakefile()->GetSafeDefinition("CMAKE_INSTALL_PREFIX");
const char* installDest = this->IEGen->GetDestination(); std::string const& expDest = this->IEGen->GetDestination();
if(cmSystemTools::FileIsFullPath(installDest)) if(cmSystemTools::FileIsFullPath(expDest))
{ {
// The export file is being installed to an absolute path so the // The export file is being installed to an absolute path so the
// package is not relocatable. Use the configured install prefix. // package is not relocatable. Use the configured install prefix.
@ -87,7 +87,7 @@ bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os)
{ {
// Add code to compute the installation prefix relative to the // Add code to compute the installation prefix relative to the
// import file location. // import file location.
std::string absDest = installPrefix + "/" + installDest; std::string absDest = installPrefix + "/" + expDest;
std::string absDestS = absDest + "/"; std::string absDestS = absDest + "/";
os << "# Compute the installation prefix relative to this file.\n" os << "# Compute the installation prefix relative to this file.\n"
<< "get_filename_component(_IMPORT_PREFIX" << "get_filename_component(_IMPORT_PREFIX"
@ -109,7 +109,7 @@ bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os)
"unset(_realOrig)\n" "unset(_realOrig)\n"
"unset(_realCurr)\n"; "unset(_realCurr)\n";
} }
std::string dest = installDest; std::string dest = expDest;
while(!dest.empty()) while(!dest.empty())
{ {
os << os <<
@ -398,7 +398,7 @@ cmExportInstallFileGenerator
cmTarget* target = itgen->GetTarget(); cmTarget* target = itgen->GetTarget();
// Construct the installed location of the target. // Construct the installed location of the target.
std::string dest = itgen->GetDestination(); std::string dest = itgen->GetDestination(config);
std::string value; std::string value;
if(!cmSystemTools::FileIsFullPath(dest.c_str())) if(!cmSystemTools::FileIsFullPath(dest.c_str()))
{ {

View File

@ -44,7 +44,9 @@ cmInstallDirectoryGenerator::GenerateScriptActions(std::ostream& os,
{ {
// Write code to install the directories. // Write code to install the directories.
const char* no_rename = 0; const char* no_rename = 0;
this->AddInstallRule(os, cmInstallType_DIRECTORY, this->AddInstallRule(os,
this->Destination,
cmInstallType_DIRECTORY,
this->Directories, this->Directories,
this->Optional, this->Optional,
this->FilePermissions.c_str(), this->FilePermissions.c_str(),

View File

@ -185,7 +185,8 @@ cmInstallExportGenerator::GenerateScriptConfigs(std::ostream& os,
files.push_back(i->second); files.push_back(i->second);
std::string config_test = this->CreateConfigTest(i->first); std::string config_test = this->CreateConfigTest(i->first);
os << indent << "if(" << config_test << ")\n"; os << indent << "if(" << config_test << ")\n";
this->AddInstallRule(os, cmInstallType_FILES, files, false, this->AddInstallRule(os, this->Destination,
cmInstallType_FILES, files, false,
this->FilePermissions.c_str(), 0, 0, 0, this->FilePermissions.c_str(), 0, 0, 0,
indent.Next()); indent.Next());
os << indent << "endif()\n"; os << indent << "endif()\n";
@ -199,7 +200,7 @@ void cmInstallExportGenerator::GenerateScriptActions(std::ostream& os,
{ {
// Remove old per-configuration export files if the main changes. // Remove old per-configuration export files if the main changes.
std::string installedDir = "$ENV{DESTDIR}"; std::string installedDir = "$ENV{DESTDIR}";
installedDir += this->GetInstallDestination(); installedDir += this->ConvertToAbsoluteDestination(this->Destination);
installedDir += "/"; installedDir += "/";
std::string installedFile = installedDir; std::string installedFile = installedDir;
installedFile += this->FileName; installedFile += this->FileName;
@ -224,6 +225,7 @@ void cmInstallExportGenerator::GenerateScriptActions(std::ostream& os,
// Install the main export file. // Install the main export file.
std::vector<std::string> files; std::vector<std::string> files;
files.push_back(this->MainImportFile); files.push_back(this->MainImportFile);
this->AddInstallRule(os, cmInstallType_FILES, files, false, this->AddInstallRule(os, this->Destination,
cmInstallType_FILES, files, false,
this->FilePermissions.c_str(), 0, 0, 0, indent); this->FilePermissions.c_str(), 0, 0, 0, indent);
} }

View File

@ -41,6 +41,9 @@ public:
const std::string& GetNamespace() const { return this->Namespace; } const std::string& GetNamespace() const { return this->Namespace; }
std::string const& GetDestination() const
{ return this->Destination; }
protected: protected:
virtual void GenerateScript(std::ostream& os); virtual void GenerateScript(std::ostream& os);
virtual void GenerateScriptConfigs(std::ostream& os, Indent const& indent); virtual void GenerateScriptConfigs(std::ostream& os, Indent const& indent);

View File

@ -57,6 +57,7 @@ void cmInstallFilesGenerator::AddFilesInstallRule(
// Write code to install the files. // Write code to install the files.
const char* no_dir_permissions = 0; const char* no_dir_permissions = 0;
this->AddInstallRule(os, this->AddInstallRule(os,
this->Destination,
(this->Programs (this->Programs
? cmInstallType_PROGRAMS ? cmInstallType_PROGRAMS
: cmInstallType_FILES), : cmInstallType_FILES),

View File

@ -37,6 +37,7 @@ cmInstallGenerator
void cmInstallGenerator void cmInstallGenerator
::AddInstallRule( ::AddInstallRule(
std::ostream& os, std::ostream& os,
std::string const& dest,
cmInstallType type, cmInstallType type,
std::vector<std::string> const& files, std::vector<std::string> const& files,
bool optional /* = false */, bool optional /* = false */,
@ -60,7 +61,6 @@ void cmInstallGenerator
case cmInstallType_FILES: stype = "FILE"; break; case cmInstallType_FILES: stype = "FILE"; break;
} }
os << indent; os << indent;
std::string dest = this->GetInstallDestination();
if (cmSystemTools::FileIsFullPath(dest.c_str())) if (cmSystemTools::FileIsFullPath(dest.c_str()))
{ {
os << "list(APPEND CMAKE_ABSOLUTE_DESTINATION_FILES\n"; os << "list(APPEND CMAKE_ABSOLUTE_DESTINATION_FILES\n";
@ -94,7 +94,8 @@ void cmInstallGenerator
<< "${CMAKE_ABSOLUTE_DESTINATION_FILES}\")\n"; << "${CMAKE_ABSOLUTE_DESTINATION_FILES}\")\n";
os << indent << "endif()\n"; os << indent << "endif()\n";
} }
os << "file(INSTALL DESTINATION \"" << dest << "\" TYPE " << stype; std::string absDest = this->ConvertToAbsoluteDestination(dest);
os << "file(INSTALL DESTINATION \"" << absDest << "\" TYPE " << stype;
if(optional) if(optional)
{ {
os << " OPTIONAL"; os << " OPTIONAL";
@ -179,15 +180,16 @@ bool cmInstallGenerator::InstallsForConfig(const std::string& config)
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
std::string cmInstallGenerator::GetInstallDestination() const std::string
cmInstallGenerator::ConvertToAbsoluteDestination(std::string const& dest) const
{ {
std::string result; std::string result;
if(!this->Destination.empty() && if(!dest.empty() &&
!cmSystemTools::FileIsFullPath(this->Destination.c_str())) !cmSystemTools::FileIsFullPath(dest.c_str()))
{ {
result = "${CMAKE_INSTALL_PREFIX}/"; result = "${CMAKE_INSTALL_PREFIX}/";
} }
result += this->Destination; result += dest;
return result; return result;
} }

View File

@ -40,7 +40,9 @@ public:
virtual ~cmInstallGenerator(); virtual ~cmInstallGenerator();
void AddInstallRule( void AddInstallRule(
std::ostream& os, cmInstallType type, std::ostream& os,
std::string const& dest,
cmInstallType type,
std::vector<std::string> const& files, std::vector<std::string> const& files,
bool optional = false, bool optional = false,
const char* permissions_file = 0, const char* permissions_file = 0,
@ -50,12 +52,9 @@ public:
Indent const& indent = Indent() Indent const& indent = Indent()
); );
const char* GetDestination() const
{ return this->Destination.c_str(); }
/** Get the install destination as it should appear in the /** Get the install destination as it should appear in the
installation script. */ installation script. */
std::string GetInstallDestination() const; std::string ConvertToAbsoluteDestination(std::string const& dest) const;
/** Test if this generator installs something for a given configuration. */ /** Test if this generator installs something for a given configuration. */
bool InstallsForConfig(const std::string& config); bool InstallsForConfig(const std::string& config);

View File

@ -12,6 +12,7 @@
#include "cmInstallTargetGenerator.h" #include "cmInstallTargetGenerator.h"
#include "cmComputeLinkInformation.h" #include "cmComputeLinkInformation.h"
#include "cmGeneratorExpression.h"
#include "cmGlobalGenerator.h" #include "cmGlobalGenerator.h"
#include "cmLocalGenerator.h" #include "cmLocalGenerator.h"
#include "cmMakefile.h" #include "cmMakefile.h"
@ -77,7 +78,8 @@ void cmInstallTargetGenerator::GenerateScriptForConfig(std::ostream& os,
fromDirConfig = this->Target->GetDirectory(config, this->ImportLibrary); fromDirConfig = this->Target->GetDirectory(config, this->ImportLibrary);
fromDirConfig += "/"; fromDirConfig += "/";
} }
std::string toDir = this->GetInstallDestination(); std::string toDir =
this->ConvertToAbsoluteDestination(this->GetDestination(config));
toDir += "/"; toDir += "/";
// Compute the list of files to install for this target. // Compute the list of files to install for this target.
@ -322,8 +324,8 @@ void cmInstallTargetGenerator::GenerateScriptForConfig(std::ostream& os,
const char* no_dir_permissions = 0; const char* no_dir_permissions = 0;
const char* no_rename = 0; const char* no_rename = 0;
bool optional = this->Optional || this->ImportLibrary; bool optional = this->Optional || this->ImportLibrary;
this->AddInstallRule(os, type, filesFrom, this->AddInstallRule(os, this->GetDestination(config),
optional, type, filesFrom, optional,
this->FilePermissions.c_str(), no_dir_permissions, this->FilePermissions.c_str(), no_dir_permissions,
no_rename, literal_args.c_str(), no_rename, literal_args.c_str(),
indent); indent);
@ -333,6 +335,15 @@ void cmInstallTargetGenerator::GenerateScriptForConfig(std::ostream& os,
&cmInstallTargetGenerator::PostReplacementTweaks); &cmInstallTargetGenerator::PostReplacementTweaks);
} }
//----------------------------------------------------------------------------
std::string
cmInstallTargetGenerator::GetDestination(std::string const& config) const
{
cmGeneratorExpression ge;
return ge.Parse(this->Destination)
->Evaluate(this->Target->GetMakefile(), config);
}
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
std::string std::string
cmInstallTargetGenerator::GetInstallFilename(const std::string& config) const cmInstallTargetGenerator::GetInstallFilename(const std::string& config) const

View File

@ -60,6 +60,8 @@ public:
cmTarget* GetTarget() const { return this->Target; } cmTarget* GetTarget() const { return this->Target; }
bool IsImportLibrary() const { return this->ImportLibrary; } bool IsImportLibrary() const { return this->ImportLibrary; }
std::string GetDestination(std::string const& config) const;
protected: protected:
virtual void GenerateScript(std::ostream& os); virtual void GenerateScript(std::ostream& os);
virtual void GenerateScriptForConfig(std::ostream& os, virtual void GenerateScriptForConfig(std::ostream& os,

View File

@ -68,6 +68,11 @@ add_library(testLib5 SHARED testLib5.c)
add_library(testLib6 STATIC testLib6.cxx testLib6c.c) add_library(testLib6 STATIC testLib6.cxx testLib6c.c)
add_library(testLibPerConfigDest STATIC testLibPerConfigDest.c)
install(TARGETS testLibPerConfigDest EXPORT exp
DESTINATION lib/$<$<BOOL:$<CONFIG>>:$<CONFIG>>$<$<NOT:$<BOOL:$<CONFIG>>>:NoConfig>
)
# Work-around: Visual Studio 6 does not support per-target object files. # Work-around: Visual Studio 6 does not support per-target object files.
set(VS6) set(VS6)
if("${CMAKE_GENERATOR}" MATCHES "Visual Studio 6") if("${CMAKE_GENERATOR}" MATCHES "Visual Studio 6")
@ -446,9 +451,9 @@ install(
cmp0022NEW cmp0022OLD cmp0022NEW cmp0022OLD
systemlib systemlib
EXPORT exp EXPORT exp
RUNTIME DESTINATION bin RUNTIME DESTINATION $<1:bin>
LIBRARY DESTINATION lib NAMELINK_SKIP LIBRARY DESTINATION $<1:lib> NAMELINK_SKIP
ARCHIVE DESTINATION lib ARCHIVE DESTINATION $<1:lib>
FRAMEWORK DESTINATION Frameworks FRAMEWORK DESTINATION Frameworks
BUNDLE DESTINATION Applications BUNDLE DESTINATION Applications
) )
@ -503,6 +508,7 @@ export(TARGETS testExe1 testLib1 testLib2 testLib3
export(TARGETS testExe2 testLib4 testLib5 testLib6 testExe3 testExe2lib export(TARGETS testExe2 testLib4 testLib5 testLib6 testExe3 testExe2lib
testLib4lib testLib4libdbg testLib4libopt testLib4lib testLib4libdbg testLib4libopt
testLibCycleA testLibCycleB testLibCycleA testLibCycleB
testLibPerConfigDest
NAMESPACE bld_ NAMESPACE bld_
APPEND FILE ExportBuildTree.cmake APPEND FILE ExportBuildTree.cmake
) )

View File

@ -0,0 +1 @@
int testLibPerConfigDest(void) { return 0; }

View File

@ -34,6 +34,7 @@ target_link_libraries(imp_testExe1
exp_testLib5 exp_testLib5
exp_testLib6 exp_testLib6
exp_testLibCycleA exp_testLibCycleA
exp_testLibPerConfigDest
) )
# Try building a plugin to an executable imported from the install tree. # Try building a plugin to an executable imported from the install tree.
@ -66,6 +67,7 @@ target_link_libraries(imp_testExe1b
bld_testLib5 bld_testLib5
bld_testLib6 bld_testLib6
bld_testLibCycleA bld_testLibCycleA
bld_testLibPerConfigDest
) )
add_custom_target(check_testLib1_genex ALL add_custom_target(check_testLib1_genex ALL

View File

@ -7,6 +7,7 @@ extern int testLib4lib();
extern int testLib5(); extern int testLib5();
extern int testLib6(); extern int testLib6();
extern int testLibCycleA1(); extern int testLibCycleA1();
extern int testLibPerConfigDest();
/* Switch a symbol between debug and optimized builds to make sure the /* Switch a symbol between debug and optimized builds to make sure the
proper library is found from the testLib4 link interface. */ proper library is found from the testLib4 link interface. */
@ -21,5 +22,6 @@ int main()
{ {
return (testLib2() + generated_by_testExe1() + testLib3() + testLib4() return (testLib2() + generated_by_testExe1() + testLib3() + testLib4()
+ testLib5() + testLib6() + testLibCycleA1() + testLib5() + testLib6() + testLibCycleA1()
+ testLibPerConfigDest()
+ generated_by_testExe3() + testLib4lib() + testLib4libcfg()); + generated_by_testExe3() + testLib4lib() + testLib4libcfg());
} }

View File

@ -6,3 +6,4 @@ run_cmake(DIRECTORY-message-lazy)
run_cmake(SkipInstallRulesWarning) run_cmake(SkipInstallRulesWarning)
run_cmake(SkipInstallRulesNoWarning1) run_cmake(SkipInstallRulesNoWarning1)
run_cmake(SkipInstallRulesNoWarning2) run_cmake(SkipInstallRulesNoWarning2)
run_cmake(TARGETS-DESTINATION-bad)

View File

@ -0,0 +1 @@
1

View File

@ -0,0 +1,6 @@
CMake Error:
Error evaluating generator expression:
\$<NOTAGENEX>
Expression did not evaluate to a known generator expression

View File

@ -0,0 +1,3 @@
enable_language(C)
add_library(empty empty.c)
install(TARGETS empty DESTINATION $<NOTAGENEX>)

View File