mirror of
https://github.com/Kitware/CMake.git
synced 2026-01-11 08:20:18 -06:00
Add new target-property IMPORTED_GLOBAL.
The purpose of this new `IMPORTED_GLOBAL` target-property is to prolong the lifetime and scope of `IMPORTED` targets in such a way as if they had been created with the keyword `GLOBAL` in the first place. * It can only be set to `TRUE`. That means, a local `IMPORTED` target can be promoted to global scope but a global `IMPORTED` target cannot be degraded to local scope! * Setting it to `TRUE` only succeeds if done from within the same directory in which the `IMPORTED` target was created in the first place. Fixes #17256.
This commit is contained in:
@@ -184,6 +184,7 @@ Properties on Targets
|
||||
/prop_tgt/HAS_CXX
|
||||
/prop_tgt/IMPLICIT_DEPENDS_INCLUDE_TRANSFORM
|
||||
/prop_tgt/IMPORTED_CONFIGURATIONS
|
||||
/prop_tgt/IMPORTED_GLOBAL
|
||||
/prop_tgt/IMPORTED_IMPLIB_CONFIG
|
||||
/prop_tgt/IMPORTED_IMPLIB
|
||||
/prop_tgt/IMPORTED_LIBNAME_CONFIG
|
||||
|
||||
22
Help/prop_tgt/IMPORTED_GLOBAL.rst
Normal file
22
Help/prop_tgt/IMPORTED_GLOBAL.rst
Normal file
@@ -0,0 +1,22 @@
|
||||
IMPORTED_GLOBAL
|
||||
---------------
|
||||
|
||||
Indication of whether an :ref:`IMPORTED target <Imported Targets>` is
|
||||
globally visible.
|
||||
|
||||
The boolean value of this property is True for targets created with the
|
||||
``IMPORTED`` ``GLOBAL`` options to :command:`add_executable()` or
|
||||
:command:`add_library()`. It is always False for targets built within the
|
||||
project.
|
||||
|
||||
For targets created with the ``IMPORTED`` option to
|
||||
:command:`add_executable()` or :command:`add_library()` but without the
|
||||
additional option ``GLOBAL`` this is False, too. However, setting this
|
||||
property for such a locally ``IMPORTED`` target to True promotes that
|
||||
target to global scope. This promotion can only be done in the same
|
||||
directory where that ``IMPORTED`` target was created in the first place.
|
||||
|
||||
Once an imported target has been made global, it cannot be changed back to
|
||||
non-global. Therefore, if a project sets this property, it may only
|
||||
provide a value of True. CMake will issue an error if the project tries to
|
||||
set the property to a non-True value, even if the value was already False.
|
||||
15
Help/release/dev/imported-promotion.rst
Normal file
15
Help/release/dev/imported-promotion.rst
Normal file
@@ -0,0 +1,15 @@
|
||||
imported-promotion
|
||||
------------------
|
||||
|
||||
* Added new target-property :prop_tgt:`IMPORTED_GLOBAL` which
|
||||
indicates if an :ref:`IMPORTED target <Imported Targets>` is
|
||||
globally visible.
|
||||
It will be set automatically if such an imported target is
|
||||
created with the ``GLOBAL`` flag.
|
||||
|
||||
* Additionally, it is now also possible to promote a local imported
|
||||
target to become globally visible by setting its
|
||||
:prop_tgt:`IMPORTED_GLOBAL` property to `TRUE`. (However, this
|
||||
promotion can only succeed if it is done from within the same
|
||||
directory where the imported target was created in the first
|
||||
place.) Setting it to `FALSE` is not supported!
|
||||
@@ -884,6 +884,13 @@ void cmTarget::SetProperty(const std::string& prop, const char* value)
|
||||
this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
|
||||
return;
|
||||
}
|
||||
if (prop == "IMPORTED_GLOBAL" && !this->IsImported()) {
|
||||
std::ostringstream e;
|
||||
e << "IMPORTED_GLOBAL property can't be set on non-imported targets (\""
|
||||
<< this->Name << "\")\n";
|
||||
this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
|
||||
return;
|
||||
}
|
||||
|
||||
if (prop == "INCLUDE_DIRECTORIES") {
|
||||
this->Internal->IncludeDirectoriesEntries.clear();
|
||||
@@ -933,6 +940,19 @@ void cmTarget::SetProperty(const std::string& prop, const char* value)
|
||||
this->Internal->SourceEntries.push_back(value);
|
||||
this->Internal->SourceBacktraces.push_back(lfbt);
|
||||
}
|
||||
} else if (prop == "IMPORTED_GLOBAL") {
|
||||
if (!cmSystemTools::IsOn(value)) {
|
||||
std::ostringstream e;
|
||||
e << "IMPORTED_GLOBAL property can't be set to FALSE on targets (\""
|
||||
<< this->Name << "\")\n";
|
||||
this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
|
||||
return;
|
||||
}
|
||||
/* no need to change anything if value does not change */
|
||||
if (!this->ImportedGloballyVisible) {
|
||||
this->ImportedGloballyVisible = true;
|
||||
this->GetGlobalGenerator()->IndexTarget(this);
|
||||
}
|
||||
} else if (cmHasLiteralPrefix(prop, "IMPORTED_LIBNAME") &&
|
||||
!this->CheckImportedLibName(prop, value ? value : "")) {
|
||||
/* error was reported by check method */
|
||||
@@ -977,6 +997,14 @@ void cmTarget::AppendProperty(const std::string& prop, const char* value,
|
||||
this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
|
||||
return;
|
||||
}
|
||||
if (prop == "IMPORTED_GLOBAL") {
|
||||
std::ostringstream e;
|
||||
e << "IMPORTED_GLOBAL property can't be appended, only set on imported "
|
||||
"targets (\""
|
||||
<< this->Name << "\")\n";
|
||||
this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
|
||||
return;
|
||||
}
|
||||
if (prop == "INCLUDE_DIRECTORIES") {
|
||||
if (value && *value) {
|
||||
this->Internal->IncludeDirectoriesEntries.push_back(value);
|
||||
@@ -1143,6 +1171,21 @@ static void cmTargetCheckINTERFACE_LINK_LIBRARIES(const char* value,
|
||||
context->IssueMessage(cmake::FATAL_ERROR, e.str());
|
||||
}
|
||||
|
||||
static void cmTargetCheckIMPORTED_GLOBAL(const cmTarget* target,
|
||||
cmMakefile* context)
|
||||
{
|
||||
std::vector<cmTarget*> targets = context->GetOwnedImportedTargets();
|
||||
std::vector<cmTarget*>::const_iterator it =
|
||||
std::find(targets.begin(), targets.end(), target);
|
||||
if (it == targets.end()) {
|
||||
std::ostringstream e;
|
||||
e << "Attempt to promote imported target \"" << target->GetName()
|
||||
<< "\" to global scope (by setting IMPORTED_GLOBAL) "
|
||||
"which is not built in this directory.";
|
||||
context->IssueMessage(cmake::FATAL_ERROR, e.str());
|
||||
}
|
||||
}
|
||||
|
||||
void cmTarget::CheckProperty(const std::string& prop,
|
||||
cmMakefile* context) const
|
||||
{
|
||||
@@ -1162,6 +1205,11 @@ void cmTarget::CheckProperty(const std::string& prop,
|
||||
cmTargetCheckINTERFACE_LINK_LIBRARIES(value, context);
|
||||
}
|
||||
}
|
||||
if (prop == "IMPORTED_GLOBAL") {
|
||||
if (this->IsImported()) {
|
||||
cmTargetCheckIMPORTED_GLOBAL(this, context);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const char* cmTarget::GetComputedProperty(
|
||||
@@ -1182,6 +1230,7 @@ const char* cmTarget::GetProperty(const std::string& prop) const
|
||||
MAKE_STATIC_PROP(COMPILE_OPTIONS);
|
||||
MAKE_STATIC_PROP(COMPILE_DEFINITIONS);
|
||||
MAKE_STATIC_PROP(IMPORTED);
|
||||
MAKE_STATIC_PROP(IMPORTED_GLOBAL);
|
||||
MAKE_STATIC_PROP(MANUALLY_ADDED_DEPENDENCIES);
|
||||
MAKE_STATIC_PROP(NAME);
|
||||
MAKE_STATIC_PROP(BINARY_DIR);
|
||||
@@ -1196,6 +1245,7 @@ const char* cmTarget::GetProperty(const std::string& prop) const
|
||||
specialProps.insert(propCOMPILE_OPTIONS);
|
||||
specialProps.insert(propCOMPILE_DEFINITIONS);
|
||||
specialProps.insert(propIMPORTED);
|
||||
specialProps.insert(propIMPORTED_GLOBAL);
|
||||
specialProps.insert(propMANUALLY_ADDED_DEPENDENCIES);
|
||||
specialProps.insert(propNAME);
|
||||
specialProps.insert(propBINARY_DIR);
|
||||
@@ -1264,6 +1314,9 @@ const char* cmTarget::GetProperty(const std::string& prop) const
|
||||
if (prop == propIMPORTED) {
|
||||
return this->IsImported() ? "TRUE" : "FALSE";
|
||||
}
|
||||
if (prop == propIMPORTED_GLOBAL) {
|
||||
return this->IsImportedGloballyVisible() ? "TRUE" : "FALSE";
|
||||
}
|
||||
if (prop == propNAME) {
|
||||
return this->GetName().c_str();
|
||||
}
|
||||
|
||||
@@ -57,6 +57,7 @@ bool cmTargetPropertyComputer::WhiteListedInterfaceProperty(
|
||||
builtIns.insert("COMPATIBLE_INTERFACE_STRING");
|
||||
builtIns.insert("EXPORT_NAME");
|
||||
builtIns.insert("IMPORTED");
|
||||
builtIns.insert("IMPORTED_GLOBAL");
|
||||
builtIns.insert("NAME");
|
||||
builtIns.insert("TYPE");
|
||||
}
|
||||
|
||||
@@ -7,4 +7,10 @@ get_property: --><--
|
||||
get_target_property: -->(.*)/Tests/RunCMake/get_property<--
|
||||
get_property: -->(.*)/Tests/RunCMake/get_property<--
|
||||
get_target_property: -->(.*)/Tests/RunCMake/get_property/target_properties-build<--
|
||||
get_property: -->(.*)/Tests/RunCMake/get_property/target_properties-build<--$
|
||||
get_property: -->(.*)/Tests/RunCMake/get_property/target_properties-build<--
|
||||
get_target_property: -->FALSE<--
|
||||
get_property: -->FALSE<--
|
||||
get_target_property: -->FALSE<--
|
||||
get_property: -->FALSE<--
|
||||
get_target_property: -->TRUE<--
|
||||
get_property: -->TRUE<--$
|
||||
|
||||
@@ -16,3 +16,10 @@ check_target_property(tgt custom)
|
||||
check_target_property(tgt noexist)
|
||||
check_target_property(tgt SOURCE_DIR)
|
||||
check_target_property(tgt BINARY_DIR)
|
||||
|
||||
add_library(imported_local_tgt SHARED IMPORTED)
|
||||
add_library(imported_global_tgt SHARED IMPORTED GLOBAL)
|
||||
|
||||
check_target_property(tgt IMPORTED_GLOBAL)
|
||||
check_target_property(imported_local_tgt IMPORTED_GLOBAL)
|
||||
check_target_property(imported_global_tgt IMPORTED_GLOBAL)
|
||||
|
||||
1
Tests/RunCMake/set_property/IMPORTED_GLOBAL-result.txt
Normal file
1
Tests/RunCMake/set_property/IMPORTED_GLOBAL-result.txt
Normal file
@@ -0,0 +1 @@
|
||||
1
|
||||
61
Tests/RunCMake/set_property/IMPORTED_GLOBAL-stderr.txt
Normal file
61
Tests/RunCMake/set_property/IMPORTED_GLOBAL-stderr.txt
Normal file
@@ -0,0 +1,61 @@
|
||||
^CMake Error at IMPORTED_GLOBAL.cmake:9 \(set_property\):
|
||||
IMPORTED_GLOBAL property can't be set to FALSE on targets
|
||||
\(\"ImportedGlobalTarget\"\)
|
||||
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists.txt:3 \(include\)
|
||||
|
||||
|
||||
CMake Error at IMPORTED_GLOBAL.cmake:16 \(set_property\):
|
||||
IMPORTED_GLOBAL property can't be appended, only set on imported targets
|
||||
\(\"ImportedGlobalTarget\"\)
|
||||
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists.txt:3 \(include\)
|
||||
|
||||
|
||||
CMake Error at IMPORTED_GLOBAL.cmake:26 \(set_property\):
|
||||
IMPORTED_GLOBAL property can't be set to FALSE on targets
|
||||
\(\"ImportedLocalTarget\"\)
|
||||
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists.txt:3 \(include\)
|
||||
|
||||
|
||||
CMake Error at IMPORTED_GLOBAL.cmake:32 \(set_property\):
|
||||
IMPORTED_GLOBAL property can't be set on non-imported targets
|
||||
\(\"NonImportedTarget\"\)
|
||||
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists.txt:3 \(include\)
|
||||
|
||||
|
||||
CMake Error at IMPORTED_GLOBAL/CMakeLists.txt:8 \(set_property\):
|
||||
Attempt to promote imported target \"ImportedLocalTarget2\" to global scope
|
||||
\(by setting IMPORTED_GLOBAL\) which is not built in this directory.
|
||||
|
||||
|
||||
CMake Error in IMPORTED_GLOBAL/CMakeLists.txt:
|
||||
IMPORTED_GLOBAL property can't be set to FALSE on targets
|
||||
\(\"ImportedSubdirTarget1\"\)
|
||||
|
||||
|
||||
|
||||
CMake Error at IMPORTED_GLOBAL.cmake:50 \(set_property\):
|
||||
Attempt to promote imported target \"ImportedSubdirTarget1\" to global scope
|
||||
\(by setting IMPORTED_GLOBAL\) which is not built in this directory.
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists.txt:3 \(include\)
|
||||
|
||||
|
||||
CMake Error in IMPORTED_GLOBAL/CMakeLists.txt:
|
||||
IMPORTED_GLOBAL property can't be set to FALSE on targets
|
||||
\(\"ImportedSubdirTarget2\"\)
|
||||
|
||||
|
||||
|
||||
CMake Error at IMPORTED_GLOBAL.cmake:52 \(set_property\):
|
||||
Attempt to promote imported target \"ImportedSubdirTarget2\" to global scope
|
||||
\(by setting IMPORTED_GLOBAL\) which is not built in this directory.
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists.txt:3 \(include\)$
|
||||
17
Tests/RunCMake/set_property/IMPORTED_GLOBAL-stdout.txt
Normal file
17
Tests/RunCMake/set_property/IMPORTED_GLOBAL-stdout.txt
Normal file
@@ -0,0 +1,17 @@
|
||||
-- ImportedGlobalTarget: Target IMPORTED_GLOBAL is 'TRUE'
|
||||
-- ImportedGlobalTarget: Target IMPORTED_GLOBAL is 'TRUE'
|
||||
-- ImportedGlobalTarget: Target IMPORTED_GLOBAL is 'TRUE'
|
||||
-- ImportedGlobalTarget: Target IMPORTED_GLOBAL is 'TRUE'
|
||||
-- ImportedGlobalTarget: Target IMPORTED_GLOBAL is 'TRUE'
|
||||
-- ImportedLocalTarget: Target IMPORTED_GLOBAL is 'FALSE'
|
||||
-- ImportedLocalTarget: Target IMPORTED_GLOBAL is 'TRUE'
|
||||
-- ImportedLocalTarget: Target IMPORTED_GLOBAL is 'TRUE'
|
||||
-- ImportedLocalTarget: Target IMPORTED_GLOBAL is 'TRUE'
|
||||
-- NonImportedTarget: Target IMPORTED_GLOBAL is 'FALSE'
|
||||
-- NonImportedTarget: Target IMPORTED_GLOBAL is 'FALSE'
|
||||
-- ImportedLocalTarget2: Target IMPORTED_GLOBAL is 'FALSE'
|
||||
-- ImportedLocalTarget2: Target IMPORTED_GLOBAL is 'TRUE'
|
||||
-- ImportedSubdirTarget1: Target IMPORTED_GLOBAL is 'TRUE'
|
||||
-- ImportedSubdirTarget2: Target IMPORTED_GLOBAL is 'TRUE'
|
||||
-- ImportedSubdirTarget1: Target IMPORTED_GLOBAL is 'TRUE'
|
||||
-- ImportedSubdirTarget2: Target IMPORTED_GLOBAL is 'TRUE'
|
||||
53
Tests/RunCMake/set_property/IMPORTED_GLOBAL.cmake
Normal file
53
Tests/RunCMake/set_property/IMPORTED_GLOBAL.cmake
Normal file
@@ -0,0 +1,53 @@
|
||||
macro(print_property TARGET PROP)
|
||||
get_property(val TARGET ${TARGET} PROPERTY ${PROP})
|
||||
message(STATUS "${TARGET}: Target ${PROP} is '${val}'")
|
||||
endmacro()
|
||||
|
||||
# Changing property on IMPORTED target created with `GLOBAL` option.
|
||||
add_library(ImportedGlobalTarget SHARED IMPORTED GLOBAL)
|
||||
print_property(ImportedGlobalTarget IMPORTED_GLOBAL)
|
||||
set_property(TARGET ImportedGlobalTarget PROPERTY IMPORTED_GLOBAL FALSE)
|
||||
print_property(ImportedGlobalTarget IMPORTED_GLOBAL)
|
||||
set_property(TARGET ImportedGlobalTarget PROPERTY IMPORTED_GLOBAL TRUE)
|
||||
print_property(ImportedGlobalTarget IMPORTED_GLOBAL)
|
||||
set_property(TARGET ImportedGlobalTarget PROPERTY IMPORTED_GLOBAL TRUE)
|
||||
print_property(ImportedGlobalTarget IMPORTED_GLOBAL)
|
||||
# Appending property is never allowed!
|
||||
set_property(TARGET ImportedGlobalTarget APPEND PROPERTY IMPORTED_GLOBAL TRUE)
|
||||
print_property(ImportedGlobalTarget IMPORTED_GLOBAL)
|
||||
|
||||
# Changing property on IMPORTED target created without `GLOBAL` option.
|
||||
add_library(ImportedLocalTarget SHARED IMPORTED)
|
||||
print_property(ImportedLocalTarget IMPORTED_GLOBAL)
|
||||
set_property(TARGET ImportedLocalTarget PROPERTY IMPORTED_GLOBAL TRUE)
|
||||
print_property(ImportedLocalTarget IMPORTED_GLOBAL)
|
||||
set_property(TARGET ImportedLocalTarget PROPERTY IMPORTED_GLOBAL TRUE)
|
||||
print_property(ImportedLocalTarget IMPORTED_GLOBAL)
|
||||
set_property(TARGET ImportedLocalTarget PROPERTY IMPORTED_GLOBAL FALSE)
|
||||
print_property(ImportedLocalTarget IMPORTED_GLOBAL)
|
||||
|
||||
# Setting property on non-IMPORTED target is never allowed!
|
||||
add_library(NonImportedTarget SHARED test.cpp)
|
||||
print_property(NonImportedTarget IMPORTED_GLOBAL)
|
||||
set_property(TARGET NonImportedTarget PROPERTY IMPORTED_GLOBAL TRUE)
|
||||
print_property(NonImportedTarget IMPORTED_GLOBAL)
|
||||
|
||||
# Local IMPORTED targets can only be promoted from same directory!
|
||||
add_library(ImportedLocalTarget2 SHARED IMPORTED)
|
||||
print_property(ImportedLocalTarget2 IMPORTED_GLOBAL)
|
||||
add_subdirectory(IMPORTED_GLOBAL)
|
||||
# Note: The value should not have changed. However, it does change because the
|
||||
# check for the same directory comes after it was changed! (At least, that is
|
||||
# not really bad because the generation will fail due to this error.)
|
||||
print_property(ImportedLocalTarget2 IMPORTED_GLOBAL)
|
||||
|
||||
# Global IMPORTED targets from subdir are always visible
|
||||
# no matter how they became global.
|
||||
print_property(ImportedSubdirTarget1 IMPORTED_GLOBAL)
|
||||
print_property(ImportedSubdirTarget2 IMPORTED_GLOBAL)
|
||||
|
||||
# Changing property on IMPORTED target from subdir is never possible.
|
||||
set_property(TARGET ImportedSubdirTarget1 PROPERTY IMPORTED_GLOBAL FALSE)
|
||||
print_property(ImportedSubdirTarget1 IMPORTED_GLOBAL)
|
||||
set_property(TARGET ImportedSubdirTarget2 PROPERTY IMPORTED_GLOBAL FALSE)
|
||||
print_property(ImportedSubdirTarget2 IMPORTED_GLOBAL)
|
||||
@@ -0,0 +1,8 @@
|
||||
add_library(ImportedSubdirTarget1 SHARED IMPORTED GLOBAL)
|
||||
add_library(ImportedSubdirTarget2 SHARED IMPORTED)
|
||||
|
||||
# Extend visibility of ImportedSubdirTarget2 to global scope.
|
||||
set_property(TARGET ImportedSubdirTarget2 PROPERTY IMPORTED_GLOBAL TRUE)
|
||||
|
||||
# Only targets from the same directory can be promoted.
|
||||
set_property(TARGET ImportedLocalTarget2 PROPERTY IMPORTED_GLOBAL TRUE)
|
||||
@@ -3,6 +3,7 @@ include(RunCMake)
|
||||
run_cmake(COMPILE_DEFINITIONS)
|
||||
run_cmake(COMPILE_FEATURES)
|
||||
run_cmake(COMPILE_OPTIONS)
|
||||
run_cmake(IMPORTED_GLOBAL)
|
||||
run_cmake(INCLUDE_DIRECTORIES)
|
||||
run_cmake(LINK_LIBRARIES)
|
||||
run_cmake(SOURCES)
|
||||
|
||||
0
Tests/RunCMake/set_property/test.cpp
Normal file
0
Tests/RunCMake/set_property/test.cpp
Normal file
Reference in New Issue
Block a user