From 07cfa57ec5f9f906e075512646100719a0a615aa Mon Sep 17 00:00:00 2001 From: Brad King Date: Fri, 5 Nov 2010 08:33:47 -0400 Subject: [PATCH 1/2] Consolidate duplicate link rule make dependency code Factor code previously duplicated for library and executable rules into a common method. --- .../cmMakefileExecutableTargetGenerator.cxx | 27 +--------------- Source/cmMakefileLibraryTargetGenerator.cxx | 25 +-------------- Source/cmMakefileTargetGenerator.cxx | 31 +++++++++++++++++++ Source/cmMakefileTargetGenerator.h | 3 ++ 4 files changed, 36 insertions(+), 50 deletions(-) diff --git a/Source/cmMakefileExecutableTargetGenerator.cxx b/Source/cmMakefileExecutableTargetGenerator.cxx index a5e319dd0..4426241c5 100644 --- a/Source/cmMakefileExecutableTargetGenerator.cxx +++ b/Source/cmMakefileExecutableTargetGenerator.cxx @@ -82,34 +82,9 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink) { std::vector commands; - std::string relPath = this->LocalGenerator->GetHomeRelativeOutputPath(); - std::string objTarget; - // Build list of dependencies. std::vector depends; - for(std::vector::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::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; diff --git a/Source/cmMakefileLibraryTargetGenerator.cxx b/Source/cmMakefileLibraryTargetGenerator.cxx index dff91fe03..049a338c9 100644 --- a/Source/cmMakefileLibraryTargetGenerator.cxx +++ b/Source/cmMakefileLibraryTargetGenerator.cxx @@ -308,33 +308,10 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules // code duplication. std::vector commands; - std::string relPath = this->LocalGenerator->GetHomeRelativeOutputPath(); - std::string objTarget; - // Build list of dependencies. std::vector depends; - for(std::vector::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::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); diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx index d5d65852a..0c150df36 100644 --- a/Source/cmMakefileTargetGenerator.cxx +++ b/Source/cmMakefileTargetGenerator.cxx @@ -1505,6 +1505,37 @@ void cmMakefileTargetGenerator } } +//---------------------------------------------------------------------------- +void cmMakefileTargetGenerator +::AppendLinkDepends(std::vector& depends) +{ + // Add dependencies on the compiled object files. + std::string relPath = this->LocalGenerator->GetHomeRelativeOutputPath(); + std::string objTarget; + for(std::vector::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::const_iterator obj + = this->ExternalObjects.begin(); + obj != this->ExternalObjects.end(); ++obj) + { + depends.push_back(*obj); + } +} + //---------------------------------------------------------------------------- void cmMakefileTargetGenerator ::CloseFileStreams() diff --git a/Source/cmMakefileTargetGenerator.h b/Source/cmMakefileTargetGenerator.h index 4ee2b39b6..c9aede2f2 100644 --- a/Source/cmMakefileTargetGenerator.h +++ b/Source/cmMakefileTargetGenerator.h @@ -115,6 +115,9 @@ protected: // append intertarget dependencies void AppendTargetDepends(std::vector& depends); + // Append link rule dependencies (objects, etc.). + void AppendLinkDepends(std::vector& 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 From 95f149e61f1ad8c8cadd74f2dbe36a2613815cc2 Mon Sep 17 00:00:00 2001 From: Brad King Date: Fri, 5 Nov 2010 09:05:08 -0400 Subject: [PATCH 2/2] Define LINK_DEPENDS target property (#11406) Custom Makefile link rules may need to depend on linker scripts. Define this property to allow user-specified link-time dependencies. --- Source/cmMakefileTargetGenerator.cxx | 7 +++++++ Source/cmTarget.cxx | 12 ++++++++++++ Tests/BuildDepends/CMakeLists.txt | 23 +++++++++++++++++++++++ Tests/BuildDepends/Project/CMakeLists.txt | 5 +++++ Tests/BuildDepends/Project/linkdep.cxx | 4 ++++ 5 files changed, 51 insertions(+) create mode 100644 Tests/BuildDepends/Project/linkdep.cxx diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx index 0c150df36..9153f3a6b 100644 --- a/Source/cmMakefileTargetGenerator.cxx +++ b/Source/cmMakefileTargetGenerator.cxx @@ -1534,6 +1534,13 @@ void cmMakefileTargetGenerator { depends.push_back(*obj); } + + // Add user-specified dependencies. + if(const char* linkDepends = + this->Target->GetProperty("LINK_DEPENDS")) + { + cmSystemTools::ExpandListArgument(linkDepends, depends); + } } //---------------------------------------------------------------------------- diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index 538025732..ca61b1fc3 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -531,6 +531,18 @@ void cmTarget::DefineProperties(cmake *cm) "Use the MAP_IMPORTED_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.", diff --git a/Tests/BuildDepends/CMakeLists.txt b/Tests/BuildDepends/CMakeLists.txt index 871464086..31392b5e4 100644 --- a/Tests/BuildDepends/CMakeLists.txt +++ b/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() diff --git a/Tests/BuildDepends/Project/CMakeLists.txt b/Tests/BuildDepends/Project/CMakeLists.txt index e9d129682..70a2f3701 100644 --- a/Tests/BuildDepends/Project/CMakeLists.txt +++ b/Tests/BuildDepends/Project/CMakeLists.txt @@ -80,3 +80,8 @@ set_property( DIRECTORY PROPERTY IMPLICIT_DEPENDS_INCLUDE_TRANSFORM "ZOT_DIR(%)=" ) + +if(TEST_LINK_DEPENDS) + add_executable(linkdep linkdep.cxx) + set_property(TARGET linkdep PROPERTY LINK_DEPENDS ${TEST_LINK_DEPENDS}) +endif() diff --git a/Tests/BuildDepends/Project/linkdep.cxx b/Tests/BuildDepends/Project/linkdep.cxx new file mode 100644 index 000000000..f8b643afb --- /dev/null +++ b/Tests/BuildDepends/Project/linkdep.cxx @@ -0,0 +1,4 @@ +int main() +{ + return 0; +}