install: Allow generator expressions in TARGETS DESTINATION (#14317)
This will allow per-config destinations for targets in EXPORT sets. Using multiple install(TARGETS) with separate CONFIGURATIONS is rejected as a target appearing more than once in an export set. Now instead one can write install(TARGETS foo EXPORT exp DESTINATION lib/$<CONFIG>) to get a single logical membership of the target in the export set while still having a per-config destination.
This commit is contained in:
parent
7607c3d16a
commit
f30022eb07
|
@ -159,6 +159,10 @@ file itself, call ``install(EXPORT)``, documented below.
|
|||
Installing a target with the :prop_tgt:`EXCLUDE_FROM_ALL` target property
|
||||
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
|
||||
^^^^^^^^^^^^^^^^
|
||||
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
install-DESTINATION-genex
|
||||
-------------------------
|
||||
|
||||
* The :command:`install(TARGETS)` command learned to support
|
||||
generator expressions in the ``DESTINATION`` value.
|
|
@ -398,7 +398,7 @@ cmExportInstallFileGenerator
|
|||
cmTarget* target = itgen->GetTarget();
|
||||
|
||||
// Construct the installed location of the target.
|
||||
std::string dest = itgen->GetDestination();
|
||||
std::string dest = itgen->GetDestination(config);
|
||||
std::string value;
|
||||
if(!cmSystemTools::FileIsFullPath(dest.c_str()))
|
||||
{
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include "cmInstallTargetGenerator.h"
|
||||
|
||||
#include "cmComputeLinkInformation.h"
|
||||
#include "cmGeneratorExpression.h"
|
||||
#include "cmGlobalGenerator.h"
|
||||
#include "cmLocalGenerator.h"
|
||||
#include "cmMakefile.h"
|
||||
|
@ -78,7 +79,7 @@ void cmInstallTargetGenerator::GenerateScriptForConfig(std::ostream& os,
|
|||
fromDirConfig += "/";
|
||||
}
|
||||
std::string toDir =
|
||||
this->ConvertToAbsoluteDestination(this->Destination);
|
||||
this->ConvertToAbsoluteDestination(this->GetDestination(config));
|
||||
toDir += "/";
|
||||
|
||||
// Compute the list of files to install for this target.
|
||||
|
@ -323,7 +324,7 @@ void cmInstallTargetGenerator::GenerateScriptForConfig(std::ostream& os,
|
|||
const char* no_dir_permissions = 0;
|
||||
const char* no_rename = 0;
|
||||
bool optional = this->Optional || this->ImportLibrary;
|
||||
this->AddInstallRule(os, this->Destination,
|
||||
this->AddInstallRule(os, this->GetDestination(config),
|
||||
type, filesFrom, optional,
|
||||
this->FilePermissions.c_str(), no_dir_permissions,
|
||||
no_rename, literal_args.c_str(),
|
||||
|
@ -334,6 +335,15 @@ void cmInstallTargetGenerator::GenerateScriptForConfig(std::ostream& os,
|
|||
&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
|
||||
cmInstallTargetGenerator::GetInstallFilename(const std::string& config) const
|
||||
|
|
|
@ -60,8 +60,7 @@ public:
|
|||
cmTarget* GetTarget() const { return this->Target; }
|
||||
bool IsImportLibrary() const { return this->ImportLibrary; }
|
||||
|
||||
std::string const& GetDestination() const
|
||||
{ return this->Destination; }
|
||||
std::string GetDestination(std::string const& config) const;
|
||||
|
||||
protected:
|
||||
virtual void GenerateScript(std::ostream& os);
|
||||
|
|
|
@ -68,6 +68,11 @@ add_library(testLib5 SHARED testLib5.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.
|
||||
set(VS6)
|
||||
if("${CMAKE_GENERATOR}" MATCHES "Visual Studio 6")
|
||||
|
@ -446,9 +451,9 @@ install(
|
|||
cmp0022NEW cmp0022OLD
|
||||
systemlib
|
||||
EXPORT exp
|
||||
RUNTIME DESTINATION bin
|
||||
LIBRARY DESTINATION lib NAMELINK_SKIP
|
||||
ARCHIVE DESTINATION lib
|
||||
RUNTIME DESTINATION $<1:bin>
|
||||
LIBRARY DESTINATION $<1:lib> NAMELINK_SKIP
|
||||
ARCHIVE DESTINATION $<1:lib>
|
||||
FRAMEWORK DESTINATION Frameworks
|
||||
BUNDLE DESTINATION Applications
|
||||
)
|
||||
|
@ -503,6 +508,7 @@ export(TARGETS testExe1 testLib1 testLib2 testLib3
|
|||
export(TARGETS testExe2 testLib4 testLib5 testLib6 testExe3 testExe2lib
|
||||
testLib4lib testLib4libdbg testLib4libopt
|
||||
testLibCycleA testLibCycleB
|
||||
testLibPerConfigDest
|
||||
NAMESPACE bld_
|
||||
APPEND FILE ExportBuildTree.cmake
|
||||
)
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
int testLibPerConfigDest(void) { return 0; }
|
|
@ -34,6 +34,7 @@ target_link_libraries(imp_testExe1
|
|||
exp_testLib5
|
||||
exp_testLib6
|
||||
exp_testLibCycleA
|
||||
exp_testLibPerConfigDest
|
||||
)
|
||||
|
||||
# Try building a plugin to an executable imported from the install tree.
|
||||
|
@ -66,6 +67,7 @@ target_link_libraries(imp_testExe1b
|
|||
bld_testLib5
|
||||
bld_testLib6
|
||||
bld_testLibCycleA
|
||||
bld_testLibPerConfigDest
|
||||
)
|
||||
|
||||
add_custom_target(check_testLib1_genex ALL
|
||||
|
|
|
@ -7,6 +7,7 @@ extern int testLib4lib();
|
|||
extern int testLib5();
|
||||
extern int testLib6();
|
||||
extern int testLibCycleA1();
|
||||
extern int testLibPerConfigDest();
|
||||
|
||||
/* Switch a symbol between debug and optimized builds to make sure the
|
||||
proper library is found from the testLib4 link interface. */
|
||||
|
@ -21,5 +22,6 @@ int main()
|
|||
{
|
||||
return (testLib2() + generated_by_testExe1() + testLib3() + testLib4()
|
||||
+ testLib5() + testLib6() + testLibCycleA1()
|
||||
+ testLibPerConfigDest()
|
||||
+ generated_by_testExe3() + testLib4lib() + testLib4libcfg());
|
||||
}
|
||||
|
|
|
@ -6,3 +6,4 @@ run_cmake(DIRECTORY-message-lazy)
|
|||
run_cmake(SkipInstallRulesWarning)
|
||||
run_cmake(SkipInstallRulesNoWarning1)
|
||||
run_cmake(SkipInstallRulesNoWarning2)
|
||||
run_cmake(TARGETS-DESTINATION-bad)
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
1
|
|
@ -0,0 +1,6 @@
|
|||
CMake Error:
|
||||
Error evaluating generator expression:
|
||||
|
||||
\$<NOTAGENEX>
|
||||
|
||||
Expression did not evaluate to a known generator expression
|
|
@ -0,0 +1,3 @@
|
|||
enable_language(C)
|
||||
add_library(empty empty.c)
|
||||
install(TARGETS empty DESTINATION $<NOTAGENEX>)
|
Loading…
Reference in New Issue