Commit e89ad0f9 authored by Zack Galbreath's avatar Zack Galbreath

install: Allow installing targets created in another directory

Previously, `install(TARGETS)` would only accept targets created in the same
directory scope.  Relax this restriction by searching the global scope when
determining whether or not a target exists.

Fixes: #14444
parent b0b99d87
......@@ -280,6 +280,14 @@ targets that link to the object libraries in their implementation.
Installing a target with the :prop_tgt:`EXCLUDE_FROM_ALL` target property
set to ``TRUE`` has undefined behavior.
:command:`install(TARGETS)` can install targets that were created in
other directories. When using such cross-directory install rules, running
``make install`` (or similar) from a subdirectory will not guarantee that
targets from other directories are up-to-date. You can use
:command:`target_link_libraries` or :command:`add_dependencies`
to ensure that such out-of-directory targets are built before the
subdirectory-specific install rules are run.
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.
......
subdirectory-installing
-----------------------
* The :command:`install(TARGETS)` command may now be used
to install targets created outside the current directory.
......@@ -362,7 +362,12 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
return false;
}
// Lookup this target in the current directory.
if (cmTarget* target = this->Makefile->FindLocalNonAliasTarget(tgt)) {
cmTarget* target = this->Makefile->FindLocalNonAliasTarget(tgt);
if (!target) {
// If no local target has been found, find it in the global scope.
target = this->Makefile->GetGlobalGenerator()->FindTarget(tgt, true);
}
if (target) {
// Found the target. Check its type.
if (target->GetType() != cmStateEnums::EXECUTABLE &&
target->GetType() != cmStateEnums::STATIC_LIBRARY &&
......@@ -381,8 +386,7 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
} else {
// Did not find the target.
std::ostringstream e;
e << "TARGETS given target \"" << tgt
<< "\" which does not exist in this directory.";
e << "TARGETS given target \"" << tgt << "\" which does not exist.";
this->SetError(e.str());
return false;
}
......
......@@ -440,7 +440,13 @@ std::string cmInstallTargetGenerator::GetInstallFilename(
void cmInstallTargetGenerator::Compute(cmLocalGenerator* lg)
{
// Lookup this target in the current directory.
this->Target = lg->FindLocalNonAliasGeneratorTarget(this->TargetName);
if (!this->Target) {
// If no local target has been found, find it in the global scope.
this->Target =
lg->GetGlobalGenerator()->FindGeneratorTarget(this->TargetName);
}
}
void cmInstallTargetGenerator::AddTweak(std::ostream& os, Indent indent,
......
......@@ -72,6 +72,8 @@ if(NOT RunCMake_GENERATOR STREQUAL "Xcode" OR NOT "$ENV{CMAKE_OSX_ARCHITECTURES}
run_install_test(FILES-TARGET_OBJECTS)
endif()
run_install_test(TARGETS-InstallFromSubDir)
set(run_install_test_components 1)
run_install_test(FILES-EXCLUDE_FROM_ALL)
run_install_test(TARGETS-EXCLUDE_FROM_ALL)
......
check_installed([[^bin;bin/myexe(\.exe)?;bin/subexe(\.exe)?$]])
enable_language(C)
add_executable(myexe main.c)
add_subdirectory(TARGETS-InstallFromSubDir)
install(TARGETS myexe subexe DESTINATION bin)
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment