Browse Source

Consider targets with double colons to be IMPORTED or ALIAS targets.

Introduce a policy to control the behavior.

The AliasTargets unit test already tests that using a
double-semicolon in the name is not an error. Change the ExportImport
test to use a namespace with a double-semicolon too.
Stephen Kelly 12 years ago
parent
commit
f063c45589

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

@@ -37,3 +37,4 @@ All Policies
    /policy/CMP0025
    /policy/CMP0025
    /policy/CMP0026
    /policy/CMP0026
    /policy/CMP0027
    /policy/CMP0027
+   /policy/CMP0028

+ 23 - 0
Help/policy/CMP0028.rst

@@ -0,0 +1,23 @@
+CMP0028
+-------
+
+Double colon in target name means ALIAS or IMPORTED target.
+
+CMake 2.8.12 and lower allowed the use of targets and files with double
+colons in target_link_libraries, with some buildsystem generators.
+
+The use of double-colons is a common pattern used to namespace IMPORTED
+targets and ALIAS targets.  When computing the link dependencies of a target,
+the name of each dependency could either be a target, or a file on disk.
+Previously, if a target was not found with a matching name, the name was
+considered to refer to a file on disk.  This can lead to confusing error
+messages if there is a typo in what should be a target name.
+
+The OLD behavior for this policy is to search for targets, then files on disk,
+even if the search term contains double-colons.  The NEW behavior for this
+policy is to issue a FATAL_ERROR if a link dependency contains
+double-colons but is not an IMPORTED target or an ALIAS target.
+
+This policy was introduced in CMake version 3.0.0.  CMake version
+|release| warns when the policy is not set and uses OLD behavior.  Use
+the cmake_policy command to set it to OLD or NEW explicitly.

+ 5 - 0
Source/cmPolicies.cxx

@@ -241,6 +241,11 @@ cmPolicies::cmPolicies()
     CMP0027, "CMP0027",
     CMP0027, "CMP0027",
     "Conditionally linked imported targets with missing include directories.",
     "Conditionally linked imported targets with missing include directories.",
     3,0,0,0, cmPolicies::WARN);
     3,0,0,0, cmPolicies::WARN);
+
+  this->DefinePolicy(
+    CMP0028, "CMP0028",
+    "Double colon in target name means ALIAS or IMPORTED target.",
+    3,0,0,0, cmPolicies::WARN);
 }
 }
 
 
 cmPolicies::~cmPolicies()
 cmPolicies::~cmPolicies()

+ 1 - 0
Source/cmPolicies.h

@@ -79,6 +79,7 @@ public:
     CMP0026, ///< Disallow use of the LOCATION target property.
     CMP0026, ///< Disallow use of the LOCATION target property.
     CMP0027, ///< Conditionally linked imported targets with missing include
     CMP0027, ///< Conditionally linked imported targets with missing include
     /// directories.
     /// directories.
+    CMP0028, ///< Double colon in target name means ALIAS or IMPORTED target.
 
 
     /** \brief Always the last entry.
     /** \brief Always the last entry.
      *
      *

+ 40 - 0
Source/cmTarget.cxx

@@ -5483,6 +5483,46 @@ void cmTarget::ComputeLinkImplementation(const char* config,
       {
       {
       continue;
       continue;
       }
       }
+    cmTarget *tgt = this->Makefile->FindTargetToUse(li->c_str());
+
+    if(!tgt && std::string(item).find("::") != std::string::npos)
+      {
+      bool noMessage = false;
+      cmake::MessageType messageType = cmake::FATAL_ERROR;
+      cmOStringStream e;
+      switch(this->Makefile->GetPolicyStatus(cmPolicies::CMP0028))
+        {
+        case cmPolicies::WARN:
+          {
+          e << (this->Makefile->GetPolicies()
+                ->GetPolicyWarning(cmPolicies::CMP0028)) << "\n";
+          messageType = cmake::AUTHOR_WARNING;
+          }
+          break;
+        case cmPolicies::OLD:
+          noMessage = true;
+        case cmPolicies::REQUIRED_IF_USED:
+        case cmPolicies::REQUIRED_ALWAYS:
+        case cmPolicies::NEW:
+          // Issue the fatal message.
+          break;
+        }
+
+      if(!noMessage)
+        {
+        e << "Target \"" << this->GetName() << "\" links to target \"" << item
+          << "\" but the target was not found.  Perhaps a find_package() "
+          "call is missing for an IMPORTED target, or a ALIAS target is "
+          "missing?";
+        this->Makefile->GetCMakeInstance()->IssueMessage(messageType,
+                                                      e.str(),
+                                                      this->GetBacktrace());
+        if (messageType == cmake::FATAL_ERROR)
+          {
+          return;
+          }
+        }
+      }
     // The entry is meant for this configuration.
     // The entry is meant for this configuration.
     impl.Libraries.push_back(item);
     impl.Libraries.push_back(item);
     }
     }

+ 2 - 2
Tests/ExportImport/Export/Interface/CMakeLists.txt

@@ -24,7 +24,7 @@ add_library(sharediface INTERFACE)
 target_link_libraries(sharediface INTERFACE sharedlib)
 target_link_libraries(sharediface INTERFACE sharedlib)
 
 
 export(TARGETS sharediface sharedlib headeronly
 export(TARGETS sharediface sharedlib headeronly
-  NAMESPACE bld_
+  NAMESPACE bld::
   FILE ../ExportInterfaceBuildTree.cmake
   FILE ../ExportInterfaceBuildTree.cmake
 )
 )
 
 
@@ -46,4 +46,4 @@ install(FILES
   DESTINATION include/sharedlib
   DESTINATION include/sharedlib
 )
 )
 
 
-install(EXPORT expInterface NAMESPACE exp_ DESTINATION lib/exp)
+install(EXPORT expInterface NAMESPACE exp:: DESTINATION lib/exp)

+ 9 - 9
Tests/ExportImport/Import/Interface/CMakeLists.txt

@@ -10,18 +10,18 @@ set_property(TARGET define_iface PROPERTY
   INTERFACE_COMPILE_DEFINITIONS DEFINE_IFACE_DEFINE)
   INTERFACE_COMPILE_DEFINITIONS DEFINE_IFACE_DEFINE)
 
 
 add_executable(headeronlytest_bld headeronlytest.cpp)
 add_executable(headeronlytest_bld headeronlytest.cpp)
-target_link_libraries(headeronlytest_bld bld_headeronly)
+target_link_libraries(headeronlytest_bld bld::headeronly)
 
 
-set_property(TARGET bld_sharediface APPEND PROPERTY INTERFACE_LINK_LIBRARIES define_iface)
+set_property(TARGET bld::sharediface APPEND PROPERTY INTERFACE_LINK_LIBRARIES define_iface)
 
 
 add_executable(interfacetest_bld interfacetest.cpp)
 add_executable(interfacetest_bld interfacetest.cpp)
-target_link_libraries(interfacetest_bld bld_sharediface)
+target_link_libraries(interfacetest_bld bld::sharediface)
 
 
 include(CheckCXXSourceCompiles)
 include(CheckCXXSourceCompiles)
 
 
 macro(do_try_compile prefix)
 macro(do_try_compile prefix)
 
 
-  set(CMAKE_REQUIRED_LIBRARIES ${prefix}headeronly)
+  set(CMAKE_REQUIRED_LIBRARIES ${prefix}::headeronly)
   check_cxx_source_compiles(
   check_cxx_source_compiles(
     "
     "
   #include \"headeronly.h\"
   #include \"headeronly.h\"
@@ -42,14 +42,14 @@ macro(do_try_compile prefix)
   endif()
   endif()
 endmacro()
 endmacro()
 
 
-do_try_compile(bld_)
+do_try_compile(bld)
 
 
 add_executable(headeronlytest_exp headeronlytest.cpp)
 add_executable(headeronlytest_exp headeronlytest.cpp)
-target_link_libraries(headeronlytest_exp exp_headeronly)
+target_link_libraries(headeronlytest_exp exp::headeronly)
 
 
-set_property(TARGET exp_sharediface APPEND PROPERTY INTERFACE_LINK_LIBRARIES define_iface)
+set_property(TARGET exp::sharediface APPEND PROPERTY INTERFACE_LINK_LIBRARIES define_iface)
 
 
 add_executable(interfacetest_exp interfacetest.cpp)
 add_executable(interfacetest_exp interfacetest.cpp)
-target_link_libraries(interfacetest_exp exp_sharediface)
+target_link_libraries(interfacetest_exp exp::sharediface)
 
 
-do_try_compile(exp_)
+do_try_compile(exp)

+ 1 - 0
Tests/RunCMake/CMP0028/CMP0028-NEW-result.txt

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

+ 6 - 0
Tests/RunCMake/CMP0028/CMP0028-NEW-stderr.txt

@@ -0,0 +1,6 @@
+CMake Error at CMP0028-NEW.cmake:4 \(add_library\):
+  Target "foo" links to target "External::Library" but the target was not
+  found.  Perhaps a find_package\(\) call is missing for an IMPORTED target, or
+  a ALIAS target is missing\?
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)

+ 5 - 0
Tests/RunCMake/CMP0028/CMP0028-NEW.cmake

@@ -0,0 +1,5 @@
+
+cmake_policy(SET CMP0028 NEW)
+
+add_library(foo empty.cpp)
+target_link_libraries(foo PRIVATE External::Library)

+ 1 - 0
Tests/RunCMake/CMP0028/CMP0028-OLD-result.txt

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

+ 1 - 0
Tests/RunCMake/CMP0028/CMP0028-OLD-stderr.txt

@@ -0,0 +1 @@
+^$

+ 5 - 0
Tests/RunCMake/CMP0028/CMP0028-OLD.cmake

@@ -0,0 +1,5 @@
+
+cmake_policy(SET CMP0028 OLD)
+
+add_library(foo empty.cpp)
+target_link_libraries(foo PRIVATE External::Library)

+ 1 - 0
Tests/RunCMake/CMP0028/CMP0028-WARN-result.txt

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

+ 11 - 0
Tests/RunCMake/CMP0028/CMP0028-WARN-stderr.txt

@@ -0,0 +1,11 @@
+CMake Warning \(dev\) at CMP0028-WARN.cmake:2 \(add_library\):
+  Policy CMP0028 is not set: Double colon in target name means ALIAS or
+  IMPORTED target.  Run "cmake --help-policy CMP0028" for policy details.
+  Use the cmake_policy command to set the policy and suppress this warning.
+
+  Target "foo" links to target "External::Library" but the target was not
+  found.  Perhaps a find_package\(\) call is missing for an IMPORTED target, or
+  a ALIAS target is missing\?
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)
+This warning is for project developers.  Use -Wno-dev to suppress it.

+ 3 - 0
Tests/RunCMake/CMP0028/CMP0028-WARN.cmake

@@ -0,0 +1,3 @@
+
+add_library(foo empty.cpp)
+target_link_libraries(foo PRIVATE External::Library)

+ 3 - 0
Tests/RunCMake/CMP0028/CMakeLists.txt

@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 2.8.4)
+project(${RunCMake_TEST} CXX)
+include(${RunCMake_TEST}.cmake NO_POLICY_SCOPE)

+ 5 - 0
Tests/RunCMake/CMP0028/RunCMakeTest.cmake

@@ -0,0 +1,5 @@
+include(RunCMake)
+
+run_cmake(CMP0028-NEW)
+run_cmake(CMP0028-OLD)
+run_cmake(CMP0028-WARN)

+ 0 - 0
Tests/RunCMake/CMP0028/empty.cpp


+ 1 - 0
Tests/RunCMake/CMakeLists.txt

@@ -55,6 +55,7 @@ add_RunCMake_test(CMP0019)
 add_RunCMake_test(CMP0022)
 add_RunCMake_test(CMP0022)
 add_RunCMake_test(CMP0026)
 add_RunCMake_test(CMP0026)
 add_RunCMake_test(CMP0027)
 add_RunCMake_test(CMP0027)
+add_RunCMake_test(CMP0028)
 add_RunCMake_test(CTest)
 add_RunCMake_test(CTest)
 if(UNIX AND "${CMAKE_TEST_GENERATOR}" MATCHES "Unix Makefiles")
 if(UNIX AND "${CMAKE_TEST_GENERATOR}" MATCHES "Unix Makefiles")
   add_RunCMake_test(CompilerChange)
   add_RunCMake_test(CompilerChange)