浏览代码

Merge topic 'external-link-depends'

95f149e Define LINK_DEPENDS target property (#11406)
07cfa57 Consolidate duplicate link rule make dependency code
David Cole 15 年之前
父节点
当前提交
c8f6c33ec8

+ 1 - 26
Source/cmMakefileExecutableTargetGenerator.cxx

@@ -82,34 +82,9 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
 {
   std::vector<std::string> commands;
 
-  std::string relPath = this->LocalGenerator->GetHomeRelativeOutputPath();
-  std::string objTarget;
-
   // Build list of dependencies.
   std::vector<std::string> depends;
-  for(std::vector<std::string>::const_iterator obj = this->Objects.begin();
-      obj != this->Objects.end(); ++obj)
-    {
-    objTarget = relPath;
-    objTarget += *obj;
-    depends.push_back(objTarget);
-    }
-
-  // Add dependencies on targets that must be built first.
-  this->AppendTargetDepends(depends);
-
-  // Add a dependency on the rule file itself.
-  this->LocalGenerator->AppendRuleDepend(depends,
-                                         this->BuildFileNameFull.c_str());
-
-  for(std::vector<std::string>::const_iterator obj =
-        this->ExternalObjects.begin();
-      obj != this->ExternalObjects.end(); ++obj)
-    {
-    depends.push_back(*obj);
-    }
-
-  // from here up is the same for exe or lib
+  this->AppendLinkDepends(depends);
 
   // Get the name of the executable to generate.
   std::string targetName;

+ 1 - 24
Source/cmMakefileLibraryTargetGenerator.cxx

@@ -308,33 +308,10 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules
   // code duplication.
   std::vector<std::string> commands;
 
-  std::string relPath = this->LocalGenerator->GetHomeRelativeOutputPath();
-  std::string objTarget;
-
   // Build list of dependencies.
   std::vector<std::string> depends;
-  for(std::vector<std::string>::const_iterator obj = this->Objects.begin();
-      obj != this->Objects.end(); ++obj)
-    {
-    objTarget = relPath;
-    objTarget += *obj;
-    depends.push_back(objTarget);
-    }
+  this->AppendLinkDepends(depends);
 
-  // Add dependencies on targets that must be built first.
-  this->AppendTargetDepends(depends);
-
-  // Add a dependency on the rule file itself.
-  this->LocalGenerator->AppendRuleDepend(depends, 
-                                         this->BuildFileNameFull.c_str());
-  
-  for(std::vector<std::string>::const_iterator obj 
-        = this->ExternalObjects.begin();
-      obj != this->ExternalObjects.end(); ++obj)
-    {
-    depends.push_back(*obj);
-    }
-  
   // Get the language to use for linking this library.
   const char* linkLanguage =
     this->Target->GetLinkerLanguage(this->ConfigName);

+ 38 - 0
Source/cmMakefileTargetGenerator.cxx

@@ -1505,6 +1505,44 @@ void cmMakefileTargetGenerator
     }
 }
 
+//----------------------------------------------------------------------------
+void cmMakefileTargetGenerator
+::AppendLinkDepends(std::vector<std::string>& depends)
+{
+  // Add dependencies on the compiled object files.
+  std::string relPath = this->LocalGenerator->GetHomeRelativeOutputPath();
+  std::string objTarget;
+  for(std::vector<std::string>::const_iterator obj = this->Objects.begin();
+      obj != this->Objects.end(); ++obj)
+    {
+    objTarget = relPath;
+    objTarget += *obj;
+    depends.push_back(objTarget);
+    }
+
+  // Add dependencies on targets that must be built first.
+  this->AppendTargetDepends(depends);
+
+  // Add a dependency on the rule file itself.
+  this->LocalGenerator->AppendRuleDepend(depends,
+                                         this->BuildFileNameFull.c_str());
+
+  // Add dependencies on the external object files.
+  for(std::vector<std::string>::const_iterator obj
+        = this->ExternalObjects.begin();
+      obj != this->ExternalObjects.end(); ++obj)
+    {
+    depends.push_back(*obj);
+    }
+
+  // Add user-specified dependencies.
+  if(const char* linkDepends =
+     this->Target->GetProperty("LINK_DEPENDS"))
+    {
+    cmSystemTools::ExpandListArgument(linkDepends, depends);
+    }
+}
+
 //----------------------------------------------------------------------------
 void cmMakefileTargetGenerator
 ::CloseFileStreams()

+ 3 - 0
Source/cmMakefileTargetGenerator.h

@@ -115,6 +115,9 @@ protected:
   // append intertarget dependencies
   void AppendTargetDepends(std::vector<std::string>& depends);
 
+  // Append link rule dependencies (objects, etc.).
+  void AppendLinkDepends(std::vector<std::string>& depends);
+
   /** In order to support parallel builds for custom commands with
       multiple outputs the outputs are given a serial order, and only
       the first output actually has the build rule.  Other outputs

+ 12 - 0
Source/cmTarget.cxx

@@ -531,6 +531,18 @@ void cmTarget::DefineProperties(cmake *cm)
      "Use the MAP_IMPORTED_CONFIG_<CONFIG> property to map imported "
      "configurations explicitly.");
 
+  cm->DefineProperty
+    ("LINK_DEPENDS", cmProperty::TARGET,
+     "Additional files on which a target binary depends for linking.",
+     "Specifies a semicolon-separated list of full-paths to files on which "
+     "the link rule for this target depends.  "
+     "The target binary will be linked if any of the named files is newer "
+     "than it."
+     "\n"
+     "This property is ignored by non-Makefile generators.  "
+     "It is intended to specify dependencies on \"linker scripts\" for "
+     "custom Makefile link rules.");
+
   cm->DefineProperty
     ("LINK_INTERFACE_LIBRARIES", cmProperty::TARGET,
      "List public interface libraries for a shared library or executable.",

+ 23 - 0
Tests/BuildDepends/CMakeLists.txt

@@ -34,6 +34,12 @@ if(WIN32 AND "${CMAKE_CXX_COMPILER_ID}" MATCHES "Intel")
   set(_cmake_options "-DCMAKE_EXE_LINKER_FLAGS=")
 endif()
 
+if("${CMAKE_GENERATOR}" MATCHES "Make")
+  set(TEST_LINK_DEPENDS ${BuildDepends_BINARY_DIR}/Project/linkdep.txt)
+  file(WRITE ${TEST_LINK_DEPENDS} "1")
+endif()
+list(APPEND _cmake_options "-DTEST_LINK_DEPENDS=${TEST_LINK_DEPENDS}")
+
 file(MAKE_DIRECTORY ${BuildDepends_BINARY_DIR}/Project)
 message("Creating Project/foo.cxx")
 write_file(${BuildDepends_BINARY_DIR}/Project/foo.cxx 
@@ -131,6 +137,10 @@ file(WRITE ${BuildDepends_BINARY_DIR}/Project/zot_macro_dir.hxx
 file(WRITE ${BuildDepends_BINARY_DIR}/Project/zot_macro_tgt.hxx
   "static const char* zot_macro_tgt = \"zot_macro_tgt changed\";\n")
 
+if(TEST_LINK_DEPENDS)
+  file(WRITE ${TEST_LINK_DEPENDS} "2")
+endif()
+
 help_xcode_depends()
 
 message("Building project second time")
@@ -194,3 +204,16 @@ if("${out}" STREQUAL "${VALUE_CHANGED}")
 else("${out}" STREQUAL "${VALUE_CHANGED}")
   message(SEND_ERROR "Project did not rebuild properly!")
 endif("${out}" STREQUAL "${VALUE_CHANGED}")
+
+if(TEST_LINK_DEPENDS)
+  set(linkdep ${BuildDepends_BINARY_DIR}/Project/linkdep${CMAKE_EXECUTABLE_SUFFIX})
+  if(${linkdep} IS_NEWER_THAN ${TEST_LINK_DEPENDS})
+    message("LINK_DEPENDS worked")
+  else()
+    message(SEND_ERROR "LINK_DEPENDS failed.  Executable
+  ${linkdep}
+is not newer than dependency
+  ${TEST_LINK_DEPENDS}
+")
+  endif()
+endif()

+ 5 - 0
Tests/BuildDepends/Project/CMakeLists.txt

@@ -80,3 +80,8 @@ set_property(
   DIRECTORY
   PROPERTY IMPLICIT_DEPENDS_INCLUDE_TRANSFORM "ZOT_DIR(%)=<zot_%_dir.hxx>"
   )
+
+if(TEST_LINK_DEPENDS)
+  add_executable(linkdep linkdep.cxx)
+  set_property(TARGET linkdep PROPERTY LINK_DEPENDS ${TEST_LINK_DEPENDS})
+endif()

+ 4 - 0
Tests/BuildDepends/Project/linkdep.cxx

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