Browse Source

cmTarget: Don't allow relative paths in INTERFACE_SOURCES

Follow the pattern of checks that are made for INTERFACE_INCLUDE_DIRECTORIES.
Existence is already checked by cmSourceFile::GetFullPath.  Add a check
to disallow relative paths in source directories. Otherwise code such as

 target_sources(lib1 INTERFACE foo.cpp)

would fail if consumed by a target in a different directory.

Unlike the INTERFACE_INCLUDE_DIRECTORIES behavior, we don't care whether
the entry comes from an IMPORTED target or not.  In the include directories
case, the directory for a non-imported target might not exist yet but
might be created.  In the sources case, a file which does not yet
exist in the filesystem must be explicitly marked with the GENERATED
property.

Adjust existing tests and add a new test for the error.
Stephen Kelly 11 years ago
parent
commit
bb5905bb13

+ 23 - 3
Source/cmTarget.cxx

@@ -649,6 +649,8 @@ static bool processSources(cmTarget const* tgt,
   for (std::vector<cmTargetInternals::TargetPropertyEntry*>::const_iterator
       it = entries.begin(), end = entries.end(); it != end; ++it)
     {
+    cmLinkImplItem const& item = (*it)->LinkImplItem;
+    std::string const& targetName = item;
     std::vector<std::string> entrySources;
     cmSystemTools::ExpandListArgument((*it)->ge->Evaluate(mf,
                                               config,
@@ -667,11 +669,10 @@ static bool processSources(cmTarget const* tgt,
         i != entrySources.end(); ++i)
       {
       std::string& src = *i;
-
       cmSourceFile* sf = mf->GetOrCreateSource(src);
       std::string e;
-      src = sf->GetFullPath(&e);
-      if(src.empty())
+      std::string fullPath = sf->GetFullPath(&e);
+      if(fullPath.empty())
         {
         if(!e.empty())
           {
@@ -681,6 +682,25 @@ static bool processSources(cmTarget const* tgt,
           }
         return contextDependent;
         }
+
+      if (!targetName.empty() && !cmSystemTools::FileIsFullPath(src.c_str()))
+        {
+        cmOStringStream err;
+        if (!targetName.empty())
+          {
+          err << "Target \"" << targetName << "\" contains relative "
+            "path in its INTERFACE_SOURCES:\n"
+            "  \"" << src << "\"";
+          }
+        else
+          {
+          err << "Found relative path while evaluating sources of "
+          "\"" << tgt->GetName() << "\":\n  \"" << src << "\"\n";
+          }
+        tgt->GetMakefile()->IssueMessage(cmake::FATAL_ERROR, err.str());
+        return contextDependent;
+        }
+      src = fullPath;
       }
     std::string usedSources;
     for(std::vector<std::string>::iterator

+ 3 - 3
Tests/ConfigSources/CMakeLists.txt

@@ -5,9 +5,9 @@ project(ConfigSources)
 
 add_library(iface INTERFACE)
 set_property(TARGET iface PROPERTY INTERFACE_SOURCES
-  iface_src.cpp
-  $<$<CONFIG:Debug>:iface_debug_src.cpp>
-  $<$<CONFIG:Release>:does_not_exist.cpp>
+  "${CMAKE_CURRENT_SOURCE_DIR}/iface_src.cpp"
+  "$<$<CONFIG:Debug>:${CMAKE_CURRENT_SOURCE_DIR}/iface_debug_src.cpp>"
+  "$<$<CONFIG:Release>:${CMAKE_CURRENT_SOURCE_DIR}/does_not_exist.cpp>"
 )
 
 add_executable(ConfigSources

+ 1 - 1
Tests/RunCMake/TargetSources/OriginDebug.cmake

@@ -7,7 +7,7 @@ set(CMAKE_DEBUG_TARGET_PROPERTIES SOURCES)
 
 add_library(iface INTERFACE)
 set_property(TARGET iface PROPERTY INTERFACE_SOURCES
-  empty_1.cpp
+  "${CMAKE_CURRENT_SOURCE_DIR}/empty_1.cpp"
 )
 
 add_library(OriginDebug empty_2.cpp)

+ 1 - 0
Tests/RunCMake/TargetSources/RelativePathInInterface-result.txt

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

+ 4 - 0
Tests/RunCMake/TargetSources/RelativePathInInterface-stderr.txt

@@ -0,0 +1,4 @@
+CMake Error in CMakeLists.txt:
+  Target "iface" contains relative path in its INTERFACE_SOURCES:
+
+    "empty_1.cpp"

+ 6 - 0
Tests/RunCMake/TargetSources/RelativePathInInterface.cmake

@@ -0,0 +1,6 @@
+
+add_library(iface INTERFACE)
+target_sources(iface INTERFACE empty_1.cpp)
+
+add_executable(main main.cpp)
+target_link_libraries(main iface)

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

@@ -8,3 +8,4 @@ else()
 endif()
 
 run_cmake(CMP0026-LOCATION)
+run_cmake(RelativePathInInterface)

+ 5 - 0
Tests/RunCMake/TargetSources/main.cpp

@@ -0,0 +1,5 @@
+
+int main()
+{
+  return 0;
+}

+ 3 - 1
Tests/SourcesProperty/CMakeLists.txt

@@ -4,7 +4,9 @@ cmake_minimum_required(VERSION 3.0)
 project(SourcesProperty)
 
 add_library(iface INTERFACE)
-set_property(TARGET iface PROPERTY INTERFACE_SOURCES iface.cpp)
+set_property(TARGET iface PROPERTY INTERFACE_SOURCES
+  "${CMAKE_CURRENT_SOURCE_DIR}/iface.cpp"
+)
 
 add_executable(SourcesProperty main.cpp)
 target_link_libraries(SourcesProperty iface)