From 33a1d727d5aafeaa0d9e729119d7d43ea9fcb370 Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Sat, 18 Feb 2017 20:12:27 +0100 Subject: Makefile: Allow adding post-build rules to object libraries --- Source/cmGlobalXCodeGenerator.cxx | 3 ++- Source/cmMakefile.cxx | 6 ++++-- Source/cmMakefile.h | 10 +++++++++- 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index 8627cf2..5029a94 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -489,7 +489,8 @@ void cmGlobalXCodeGenerator::AddExtraTargets( std::vector no_byproducts; lg->GetMakefile()->AddCustomCommandToTarget( target->GetName(), no_byproducts, no_depends, commandLines, - cmTarget::POST_BUILD, "Depend check for xcode", dir.c_str()); + cmTarget::POST_BUILD, "Depend check for xcode", dir.c_str(), true, + false, "", false, cmMakefile::AcceptObjectLibraryCommands); } if (target->GetType() != cmStateEnums::INTERFACE_LIBRARY && diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index bdaca97..7f9e6ef 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -684,7 +684,8 @@ void cmMakefile::AddCustomCommandToTarget( const std::vector& depends, const cmCustomCommandLines& commandLines, cmTarget::CustomCommandType type, const char* comment, const char* workingDir, bool escapeOldStyle, - bool uses_terminal, const std::string& depfile, bool command_expand_lists) + bool uses_terminal, const std::string& depfile, bool command_expand_lists, + ObjectLibraryCommands objLibraryCommands) { // Find the target to which to add the custom command. cmTargets::iterator ti = this->Targets.find(target); @@ -724,7 +725,8 @@ void cmMakefile::AddCustomCommandToTarget( return; } - if (ti->second.GetType() == cmStateEnums::OBJECT_LIBRARY) { + if (objLibraryCommands == RejectObjectLibraryCommands && + ti->second.GetType() == cmStateEnums::OBJECT_LIBRARY) { std::ostringstream e; e << "Target \"" << target << "\" is an OBJECT library " diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h index 9d9e90a..4d5ce98 100644 --- a/Source/cmMakefile.h +++ b/Source/cmMakefile.h @@ -119,6 +119,13 @@ public: */ void FinalPass(); + /** How to handle custom commands for object libraries */ + enum ObjectLibraryCommands + { + RejectObjectLibraryCommands, + AcceptObjectLibraryCommands + }; + /** Add a custom command to the build. */ void AddCustomCommandToTarget( const std::string& target, const std::vector& byproducts, @@ -126,7 +133,8 @@ public: const cmCustomCommandLines& commandLines, cmTarget::CustomCommandType type, const char* comment, const char* workingDir, bool escapeOldStyle = true, bool uses_terminal = false, const std::string& depfile = "", - bool command_expand_lists = false); + bool command_expand_lists = false, + ObjectLibraryCommands objLibraryCommands = RejectObjectLibraryCommands); cmSourceFile* AddCustomCommandToOutput( const std::vector& outputs, const std::vector& byproducts, -- cgit v0.12 From 9293e57d9cef75a5abb6f28d5bf712106471a137 Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Sat, 18 Feb 2017 18:23:59 +0100 Subject: Xcode: Collect dummy rules during iteration and emit afterwards --- Source/cmGlobalXCodeGenerator.cxx | 37 +++++++++++++------------------------ 1 file changed, 13 insertions(+), 24 deletions(-) diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index 5029a94..9d5c99e 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -3184,29 +3184,9 @@ void cmGlobalXCodeGenerator::CreateXCodeDependHackTarget( "default:\n" "\techo \"Do not invoke directly\"\n" "\n"; - makefileStream - << "# For each target create a dummy rule " - "so the target does not have to exist\n"; /* clang-format on */ - std::set emitted; - for (std::vector::iterator i = targets.begin(); - i != targets.end(); ++i) { - cmXCodeObject* target = *i; - std::map const& deplibs = - target->GetDependLibraries(); - for (std::map::const_iterator ci = - deplibs.begin(); - ci != deplibs.end(); ++ci) { - for (cmXCodeObject::StringVec::const_iterator d = ci->second.begin(); - d != ci->second.end(); ++d) { - if (emitted.insert(*d).second) { - makefileStream << this->ConvertToRelativeForMake(d->c_str()) - << ":\n"; - } - } - } - } - makefileStream << "\n\n"; + + std::set dummyRules; // Write rules to help Xcode relink things at the right time. /* clang-format off */ @@ -3263,8 +3243,9 @@ void cmGlobalXCodeGenerator::CreateXCodeDependHackTarget( std::vector const& deplibs = x->second; for (std::vector::const_iterator d = deplibs.begin(); d != deplibs.end(); ++d) { - makefileStream << "\\\n\t" - << this->ConvertToRelativeForMake(d->c_str()); + std::string file = this->ConvertToRelativeForMake(d->c_str()); + makefileStream << "\\\n\t" << file; + dummyRules.insert(file); } } // Write the action to remove the target if it is out of date. @@ -3294,6 +3275,14 @@ void cmGlobalXCodeGenerator::CreateXCodeDependHackTarget( } } } + + makefileStream << "\n\n" + << "# For each target create a dummy rule" + << "so the target does not have to exist\n"; + for (std::set::const_iterator it = dummyRules.begin(); + it != dummyRules.end(); ++it) { + makefileStream << *it << ":\n"; + } } void cmGlobalXCodeGenerator::OutputXCodeProject( -- cgit v0.12 From e80ac953035703dde6e03e2c32ba9fded8c69f2a Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Sat, 18 Feb 2017 18:41:03 +0100 Subject: Xcode: Record dependency information also for object libraries Xcode seems to have troubles to track target dependecies to object files. This may lead to stale targets as reported in issue #16615. As a work-around the pre-Xcode 5 dependecy tracker hack with post-build make files is extended to also take object libraries into account. --- Source/cmGlobalXCodeGenerator.cxx | 38 ++++++++++++++++++++++++++++++-------- 1 file changed, 30 insertions(+), 8 deletions(-) diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index 9d5c99e..0a9c7b8 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -477,8 +477,7 @@ void cmGlobalXCodeGenerator::AddExtraTargets( // things are up-to-date if (!makeHelper.empty() && (target->GetType() == cmStateEnums::EXECUTABLE || - // Nope - no post-build for OBJECT_LIRBRARY - // target->GetType() == cmStateEnums::OBJECT_LIBRARY || + target->GetType() == cmStateEnums::OBJECT_LIBRARY || target->GetType() == cmStateEnums::STATIC_LIBRARY || target->GetType() == cmStateEnums::SHARED_LIBRARY || target->GetType() == cmStateEnums::MODULE_LIBRARY)) { @@ -3130,10 +3129,7 @@ bool cmGlobalXCodeGenerator::CreateXCodeObjects( cmXCodeObject* t = *i; this->AddDependAndLinkInformation(t); } - if (this->XcodeVersion < 50) { - // now create xcode depend hack makefile - this->CreateXCodeDependHackTarget(targets); - } + this->CreateXCodeDependHackTarget(targets); // now add all targets to the root object cmXCodeObject* allTargets = this->CreateObject(cmXCodeObject::OBJECT_LIST); for (std::vector::iterator i = targets.begin(); @@ -3205,8 +3201,7 @@ void cmGlobalXCodeGenerator::CreateXCodeDependHackTarget( cmGeneratorTarget* gt = target->GetTarget(); if (gt->GetType() == cmStateEnums::EXECUTABLE || - // Nope - no post-build for OBJECT_LIRBRARY - // gt->GetType() == cmStateEnums::OBJECT_LIBRARY || + gt->GetType() == cmStateEnums::OBJECT_LIBRARY || gt->GetType() == cmStateEnums::STATIC_LIBRARY || gt->GetType() == cmStateEnums::SHARED_LIBRARY || gt->GetType() == cmStateEnums::MODULE_LIBRARY) { @@ -3216,6 +3211,7 @@ void cmGlobalXCodeGenerator::CreateXCodeDependHackTarget( } if (gt->GetType() == cmStateEnums::EXECUTABLE || + gt->GetType() == cmStateEnums::STATIC_LIBRARY || gt->GetType() == cmStateEnums::SHARED_LIBRARY || gt->GetType() == cmStateEnums::MODULE_LIBRARY) { std::string tfull = gt->GetFullPath(configName); @@ -3233,6 +3229,15 @@ void cmGlobalXCodeGenerator::CreateXCodeDependHackTarget( } } + std::vector objlibs; + gt->GetObjectLibrariesCMP0026(objlibs); + for (std::vector::const_iterator it = + objlibs.begin(); + it != objlibs.end(); ++it) { + makefileStream << this->PostBuildMakeTarget((*it)->GetName(), *ct) + << ": " << trel << "\n"; + } + // Create a rule for this target. makefileStream << trel << ":"; @@ -3248,6 +3253,23 @@ void cmGlobalXCodeGenerator::CreateXCodeDependHackTarget( dummyRules.insert(file); } } + + for (std::vector::const_iterator it = + objlibs.begin(); + it != objlibs.end(); ++it) { + + const std::string objLibName = (*it)->GetName(); + std::string d = this->GetObjectsNormalDirectory(this->CurrentProject, + configName, *it); + d += "lib"; + d += objLibName; + d += ".a"; + + std::string dependency = this->ConvertToRelativeForMake(d.c_str()); + makefileStream << "\\\n\t" << dependency; + dummyRules.insert(dependency); + } + // Write the action to remove the target if it is out of date. makefileStream << "\n"; makefileStream << "\t/bin/rm -f " -- cgit v0.12 From 5da9266af50af3c2c1a827a1d162c8a9b16e7fd9 Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Sat, 18 Feb 2017 18:43:25 +0100 Subject: Xcode: Always track object library dependencies via hacky Makefile Always use the dependency tracker Makefile to ensure targets that depend on object libraries are up-to-date. For all other target types we use the hack only for Xcode < 5. Fixes: #16615 --- Source/cmGlobalXCodeGenerator.cxx | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index 0a9c7b8..5167205 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -423,14 +423,12 @@ void cmGlobalXCodeGenerator::AddExtraTargets( // Add XCODE depend helper std::string dir = root->GetCurrentBinaryDirectory(); cmCustomCommandLine makeHelper; - if (this->XcodeVersion < 50) { - makeHelper.push_back("make"); - makeHelper.push_back("-C"); - makeHelper.push_back(dir); - makeHelper.push_back("-f"); - makeHelper.push_back(this->CurrentXCodeHackMakefile); - makeHelper.push_back(""); // placeholder, see below - } + makeHelper.push_back("make"); + makeHelper.push_back("-C"); + makeHelper.push_back(dir); + makeHelper.push_back("-f"); + makeHelper.push_back(this->CurrentXCodeHackMakefile); + makeHelper.push_back(""); // placeholder, see below // Add ZERO_CHECK bool regenerate = !mf->IsOn("CMAKE_SUPPRESS_REGENERATION"); @@ -475,12 +473,12 @@ void cmGlobalXCodeGenerator::AddExtraTargets( // run the depend check makefile as a post build rule // this will make sure that when the next target is built // things are up-to-date - if (!makeHelper.empty() && - (target->GetType() == cmStateEnums::EXECUTABLE || - target->GetType() == cmStateEnums::OBJECT_LIBRARY || - target->GetType() == cmStateEnums::STATIC_LIBRARY || - target->GetType() == cmStateEnums::SHARED_LIBRARY || - target->GetType() == cmStateEnums::MODULE_LIBRARY)) { + if (target->GetType() == cmStateEnums::OBJECT_LIBRARY || + (this->XcodeVersion < 50 && + (target->GetType() == cmStateEnums::EXECUTABLE || + target->GetType() == cmStateEnums::STATIC_LIBRARY || + target->GetType() == cmStateEnums::SHARED_LIBRARY || + target->GetType() == cmStateEnums::MODULE_LIBRARY))) { makeHelper[makeHelper.size() - 1] = // fill placeholder this->PostBuildMakeTarget(target->GetName(), "$(CONFIGURATION)"); cmCustomCommandLines commandLines; -- cgit v0.12 From 624021a09e7850b1f6cb75af40b17a38d98c95e3 Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Sat, 18 Feb 2017 22:27:46 +0100 Subject: Add test for object library dependencies Issue: #16615 --- Tests/RunCMake/ObjectLibrary/Dependencies.cmake | 11 +++++++++++ Tests/RunCMake/ObjectLibrary/RunCMakeTest.cmake | 19 +++++++++++++++++++ Tests/RunCMake/ObjectLibrary/depends_lib.cpp | 7 +++++++ Tests/RunCMake/ObjectLibrary/depends_main.cpp | 7 +++++++ Tests/RunCMake/ObjectLibrary/depends_obj0.cpp | 4 ++++ Tests/RunCMake/ObjectLibrary/depends_obj1.cpp | 4 ++++ 6 files changed, 52 insertions(+) create mode 100644 Tests/RunCMake/ObjectLibrary/Dependencies.cmake create mode 100644 Tests/RunCMake/ObjectLibrary/depends_lib.cpp create mode 100644 Tests/RunCMake/ObjectLibrary/depends_main.cpp create mode 100644 Tests/RunCMake/ObjectLibrary/depends_obj0.cpp create mode 100644 Tests/RunCMake/ObjectLibrary/depends_obj1.cpp diff --git a/Tests/RunCMake/ObjectLibrary/Dependencies.cmake b/Tests/RunCMake/ObjectLibrary/Dependencies.cmake new file mode 100644 index 0000000..4e3db5f --- /dev/null +++ b/Tests/RunCMake/ObjectLibrary/Dependencies.cmake @@ -0,0 +1,11 @@ +cmake_minimum_required(VERSION 3.7) + +project(Dependencies) + +add_library(myobj OBJECT ${CMAKE_BINARY_DIR}/depends_obj.cpp) +add_library(mylib STATIC $ depends_lib.cpp) +add_executable(myexe depends_main.cpp) +target_link_libraries(myexe mylib) + +enable_testing() +add_test(NAME myexe COMMAND $) diff --git a/Tests/RunCMake/ObjectLibrary/RunCMakeTest.cmake b/Tests/RunCMake/ObjectLibrary/RunCMakeTest.cmake index 42973f8..9291218 100644 --- a/Tests/RunCMake/ObjectLibrary/RunCMakeTest.cmake +++ b/Tests/RunCMake/ObjectLibrary/RunCMakeTest.cmake @@ -16,3 +16,22 @@ run_cmake(ObjWithObj) run_cmake(PostBuild) run_cmake(PreBuild) run_cmake(PreLink) + +function(run_Dependencies) + set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/Dependencies-build) + set(RunCMake_TEST_NO_CLEAN 1) + + file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}") + file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}") + + run_cmake_command(Dependencies-build ${CMAKE_COMMAND} -E copy ${RunCMake_SOURCE_DIR}/depends_obj1.cpp ${RunCMake_TEST_BINARY_DIR}/depends_obj.cpp) + run_cmake(Dependencies) + run_cmake_command(Dependencies-build ${CMAKE_COMMAND} --build .) + run_cmake_command(Dependencies-build ${CMAKE_COMMAND} -E copy ${RunCMake_SOURCE_DIR}/depends_obj0.cpp ${RunCMake_TEST_BINARY_DIR}/depends_obj.cpp) + run_cmake_command(Dependencies-build ${CMAKE_COMMAND} -E sleep 1) + run_cmake_command(Dependencies-build ${CMAKE_COMMAND} -E touch_nocreate ${RunCMake_TEST_BINARY_DIR}/depends_obj.cpp) + run_cmake_command(Dependencies-build ${CMAKE_COMMAND} --build .) + run_cmake_command(Dependencies-build ${CMAKE_CTEST_COMMAND} -C Debug) +endfunction() + +run_Dependencies() diff --git a/Tests/RunCMake/ObjectLibrary/depends_lib.cpp b/Tests/RunCMake/ObjectLibrary/depends_lib.cpp new file mode 100644 index 0000000..540b536 --- /dev/null +++ b/Tests/RunCMake/ObjectLibrary/depends_lib.cpp @@ -0,0 +1,7 @@ +#include +int myobj_foo(); + +void mylib_foo() +{ + exit(myobj_foo()); +} diff --git a/Tests/RunCMake/ObjectLibrary/depends_main.cpp b/Tests/RunCMake/ObjectLibrary/depends_main.cpp new file mode 100644 index 0000000..a9d323d --- /dev/null +++ b/Tests/RunCMake/ObjectLibrary/depends_main.cpp @@ -0,0 +1,7 @@ +void mylib_foo(); + +int main() +{ + mylib_foo(); + return 0; +} diff --git a/Tests/RunCMake/ObjectLibrary/depends_obj0.cpp b/Tests/RunCMake/ObjectLibrary/depends_obj0.cpp new file mode 100644 index 0000000..73a17e7 --- /dev/null +++ b/Tests/RunCMake/ObjectLibrary/depends_obj0.cpp @@ -0,0 +1,4 @@ +int myobj_foo() +{ + return 0; +} diff --git a/Tests/RunCMake/ObjectLibrary/depends_obj1.cpp b/Tests/RunCMake/ObjectLibrary/depends_obj1.cpp new file mode 100644 index 0000000..f62ef70 --- /dev/null +++ b/Tests/RunCMake/ObjectLibrary/depends_obj1.cpp @@ -0,0 +1,4 @@ +int myobj_foo() +{ + return 1; +} -- cgit v0.12