Browse Source

Merge topic 'imported-promotion'

6a3922be Add new target-property `IMPORTED_GLOBAL`.
854e482a cmTarget: Simplified and fixed a string-comparision.

Acked-by: Kitware Robot <[email protected]>
Merge-request: !1254
Brad King 8 years ago
parent
commit
30fcf13be6

+ 1 - 0
Help/manual/cmake-properties.7.rst

@@ -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 - 0
Help/prop_tgt/IMPORTED_GLOBAL.rst

@@ -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 - 0
Help/release/dev/imported-promotion.rst

@@ -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!

+ 54 - 1
Source/cmTarget.cxx

@@ -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
 {
@@ -1157,11 +1200,16 @@ void cmTarget::CheckProperty(const std::string& prop,
       cmTargetCheckLINK_INTERFACE_LIBRARIES(prop, value, context, true);
     }
   }
-  if (cmHasLiteralPrefix(prop, "INTERFACE_LINK_LIBRARIES")) {
+  if (prop == "INTERFACE_LINK_LIBRARIES") {
     if (const char* value = this->GetProperty(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();
     }

+ 1 - 0
Source/cmTargetPropertyComputer.cxx

@@ -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 - 1
Tests/RunCMake/get_property/target_properties-stderr.txt

@@ -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<--$

+ 7 - 0
Tests/RunCMake/get_property/target_properties.cmake

@@ -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 - 0
Tests/RunCMake/set_property/IMPORTED_GLOBAL-result.txt

@@ -0,0 +1 @@
+1

+ 61 - 0
Tests/RunCMake/set_property/IMPORTED_GLOBAL-stderr.txt

@@ -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 - 0
Tests/RunCMake/set_property/IMPORTED_GLOBAL-stdout.txt

@@ -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 - 0
Tests/RunCMake/set_property/IMPORTED_GLOBAL.cmake

@@ -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)

+ 8 - 0
Tests/RunCMake/set_property/IMPORTED_GLOBAL/CMakeLists.txt

@@ -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)

+ 1 - 0
Tests/RunCMake/set_property/RunCMakeTest.cmake

@@ -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 - 0
Tests/RunCMake/set_property/test.cpp