diff options
22 files changed, 126 insertions, 53 deletions
diff --git a/Help/command/add_custom_command.rst b/Help/command/add_custom_command.rst index b0c5446..028ca5a 100644 --- a/Help/command/add_custom_command.rst +++ b/Help/command/add_custom_command.rst @@ -156,3 +156,7 @@ target is built before any target using this custom command. Additionally, if the target is an executable or library a file-level dependency is created to cause the custom command to re-run whenever the target is recompiled. + +Arguments to ``DEPENDS`` may use "generator expressions" with the syntax +``$<...>``. See the :manual:`cmake-generator-expressions(7)` manual for +available expressions. diff --git a/Help/release/dev/add_custom_command-DEPENDS-genex.rst b/Help/release/dev/add_custom_command-DEPENDS-genex.rst new file mode 100644 index 0000000..1e528e6 --- /dev/null +++ b/Help/release/dev/add_custom_command-DEPENDS-genex.rst @@ -0,0 +1,5 @@ +add_custom_command-DEPENDS-genex +-------------------------------- + +* The :command:`add_custom_command` command learned to interpret + :manual:`cmake-generator-expressions(7)` in arguments to ``DEPENDS``. diff --git a/Modules/Platform/Android.cmake b/Modules/Platform/Android.cmake new file mode 100644 index 0000000..a4c122d --- /dev/null +++ b/Modules/Platform/Android.cmake @@ -0,0 +1,5 @@ +include(Platform/Linux) +set(CMAKE_SHARED_LIBRARY_SONAME_C_FLAG "") +# RPath is useless on Android, because we can't determine the installation +# location ahead of time. +set(CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG "") diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 562040a..0744061 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,5 +1,5 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 0) -set(CMake_VERSION_PATCH 20140317) +set(CMake_VERSION_PATCH 20140320) #set(CMake_VERSION_RC 1) diff --git a/Source/QtDialog/CMakeLists.txt b/Source/QtDialog/CMakeLists.txt index 07a50b9..7885a0c 100644 --- a/Source/QtDialog/CMakeLists.txt +++ b/Source/QtDialog/CMakeLists.txt @@ -28,7 +28,7 @@ if (Qt5Widgets_FOUND) qt5_add_resources(${ARGN}) endmacro() set(CMake_QT_LIBRARIES ${Qt5Widgets_LIBRARIES}) - set(QT_QTMAIN_LIBRARY Qt5::WinMain) + set(QT_QTMAIN_LIBRARY ${Qt5Core_QTMAIN_LIBRARIES}) # Remove this when the minimum version of Qt is 4.6. add_definitions(-DQT_DISABLE_DEPRECATED_BEFORE=0) diff --git a/Source/cmCustomCommandGenerator.cxx b/Source/cmCustomCommandGenerator.cxx index a091cff..cebd9f5 100644 --- a/Source/cmCustomCommandGenerator.cxx +++ b/Source/cmCustomCommandGenerator.cxx @@ -21,7 +21,7 @@ cmCustomCommandGenerator::cmCustomCommandGenerator( cmCustomCommand const& cc, const std::string& config, cmMakefile* mf): CC(cc), Config(config), Makefile(mf), LG(mf->GetLocalGenerator()), OldStyle(cc.GetEscapeOldStyle()), MakeVars(cc.GetEscapeAllowMakeVars()), - GE(new cmGeneratorExpression(cc.GetBacktrace())) + GE(new cmGeneratorExpression(cc.GetBacktrace())), DependsDone(false) { } @@ -93,5 +93,19 @@ std::vector<std::string> const& cmCustomCommandGenerator::GetOutputs() const //---------------------------------------------------------------------------- std::vector<std::string> const& cmCustomCommandGenerator::GetDepends() const { - return this->CC.GetDepends(); + if (!this->DependsDone) + { + this->DependsDone = true; + std::vector<std::string> depends = this->CC.GetDepends(); + for(std::vector<std::string>::const_iterator + i = depends.begin(); + i != depends.end(); ++i) + { + cmsys::auto_ptr<cmCompiledGeneratorExpression> cge + = this->GE->Parse(*i); + cmSystemTools::ExpandListArgument( + cge->Evaluate(this->Makefile, this->Config), this->Depends); + } + } + return this->Depends; } diff --git a/Source/cmCustomCommandGenerator.h b/Source/cmCustomCommandGenerator.h index cbcdb41..0d8a0a4 100644 --- a/Source/cmCustomCommandGenerator.h +++ b/Source/cmCustomCommandGenerator.h @@ -28,6 +28,8 @@ class cmCustomCommandGenerator bool OldStyle; bool MakeVars; cmGeneratorExpression* GE; + mutable bool DependsDone; + mutable std::vector<std::string> Depends; public: cmCustomCommandGenerator(cmCustomCommand const& cc, const std::string& config, diff --git a/Source/cmGeneratorExpression.h b/Source/cmGeneratorExpression.h index 5b97e8b..d0a6aef 100644 --- a/Source/cmGeneratorExpression.h +++ b/Source/cmGeneratorExpression.h @@ -16,8 +16,6 @@ #include "cmStandardIncludes.h" #include "cmListFileCache.h" -#include <stack> - #include <cmsys/RegularExpression.hxx> #include <cmsys/auto_ptr.hxx> diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index 2a144c6..b35e859 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -19,6 +19,7 @@ #include "cmGeneratorExpression.h" #include "cmGeneratorExpressionDAGChecker.h" #include "cmComputeLinkInformation.h" +#include "cmCustomCommandGenerator.h" #include <queue> @@ -610,6 +611,9 @@ private: bool IsUtility(std::string const& dep); void CheckCustomCommand(cmCustomCommand const& cc); void CheckCustomCommands(const std::vector<cmCustomCommand>& commands); + void FollowCommandDepends(cmCustomCommand const& cc, + const std::string& config, + std::set<std::string>& emitted); }; //---------------------------------------------------------------------------- @@ -826,16 +830,41 @@ cmTargetTraceDependencies } // Queue the custom command dependencies. - std::vector<std::string> const& depends = cc.GetDepends(); + std::vector<std::string> configs; + std::set<std::string> emitted; + this->Makefile->GetConfigurations(configs); + if (configs.empty()) + { + configs.push_back(""); + } + for(std::vector<std::string>::const_iterator ci = configs.begin(); + ci != configs.end(); ++ci) + { + this->FollowCommandDepends(cc, *ci, emitted); + } +} + +//---------------------------------------------------------------------------- +void cmTargetTraceDependencies::FollowCommandDepends(cmCustomCommand const& cc, + const std::string& config, + std::set<std::string>& emitted) +{ + cmCustomCommandGenerator ccg(cc, config, this->Makefile); + + const std::vector<std::string>& depends = ccg.GetDepends(); + for(std::vector<std::string>::const_iterator di = depends.begin(); di != depends.end(); ++di) { std::string const& dep = *di; - if(!this->IsUtility(dep)) + if(emitted.insert(dep).second) { - // The dependency does not name a target and may be a file we - // know how to generate. Queue it. - this->FollowName(dep); + if(!this->IsUtility(dep)) + { + // The dependency does not name a target and may be a file we + // know how to generate. Queue it. + this->FollowName(dep); + } } } } diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx index 49ce1b5..88f1b08 100644 --- a/Source/cmGlobalNinjaGenerator.cxx +++ b/Source/cmGlobalNinjaGenerator.cxx @@ -639,12 +639,12 @@ void cmGlobalNinjaGenerator cmTarget* target = gt->Target; // Compute full path to object file directory for this target. - std::string dir_max; - dir_max += gt->Makefile->GetCurrentOutputDirectory(); - dir_max += "/"; - dir_max += gt->LocalGenerator->GetTargetDirectory(*target); - dir_max += "/"; - gt->ObjectDirectory = dir_max; + std::string dir; + dir += gt->Makefile->GetCurrentOutputDirectory(); + dir += "/"; + dir += gt->LocalGenerator->GetTargetDirectory(*target); + dir += "/"; + gt->ObjectDirectory = dir; } //---------------------------------------------------------------------------- diff --git a/Source/cmGlobalUnixMakefileGenerator3.cxx b/Source/cmGlobalUnixMakefileGenerator3.cxx index 4632071..3aa293e 100644 --- a/Source/cmGlobalUnixMakefileGenerator3.cxx +++ b/Source/cmGlobalUnixMakefileGenerator3.cxx @@ -111,12 +111,12 @@ cmGlobalUnixMakefileGenerator3 cmTarget* target = gt->Target; // Compute full path to object file directory for this target. - std::string dir_max; - dir_max += gt->Makefile->GetCurrentOutputDirectory(); - dir_max += "/"; - dir_max += gt->LocalGenerator->GetTargetDirectory(*target); - dir_max += "/"; - gt->ObjectDirectory = dir_max; + std::string dir; + dir += gt->Makefile->GetCurrentOutputDirectory(); + dir += "/"; + dir += gt->LocalGenerator->GetTargetDirectory(*target); + dir += "/"; + gt->ObjectDirectory = dir; } void cmGlobalUnixMakefileGenerator3::Configure() @@ -958,21 +958,6 @@ cmGlobalUnixMakefileGenerator3::RecordTargetProgress( } //---------------------------------------------------------------------------- -bool -cmGlobalUnixMakefileGenerator3::ProgressMapCompare -::operator()(cmTarget const* l, cmTarget const* r) const -{ - // Order by target name. - if(int c = strcmp(l->GetName().c_str(), r->GetName().c_str())) - { - return c < 0; - } - // Order duplicate targets by binary directory. - return strcmp(l->GetMakefile()->GetCurrentOutputDirectory(), - r->GetMakefile()->GetCurrentOutputDirectory()) < 0; -} - -//---------------------------------------------------------------------------- void cmGlobalUnixMakefileGenerator3::TargetProgress ::WriteProgressVariables(unsigned long total, unsigned long ¤t) diff --git a/Source/cmGlobalUnixMakefileGenerator3.h b/Source/cmGlobalUnixMakefileGenerator3.h index d003789..f44dd12 100644 --- a/Source/cmGlobalUnixMakefileGenerator3.h +++ b/Source/cmGlobalUnixMakefileGenerator3.h @@ -185,10 +185,8 @@ protected: std::vector<unsigned long> Marks; void WriteProgressVariables(unsigned long total, unsigned long& current); }; - struct ProgressMapCompare { bool operator()(cmTarget const*, - cmTarget const*) const; }; typedef std::map<cmTarget const*, TargetProgress, - ProgressMapCompare> ProgressMapType; + cmStrictTargetComparison> ProgressMapType; ProgressMapType ProgressMap; size_t CountProgressMarksInTarget(cmTarget const* target, diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index c63de79..c47147c 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -264,7 +264,8 @@ void cmLocalGenerator::TraceDependencies() for(cmGeneratorTargetsType::iterator t = targets.begin(); t != targets.end(); ++t) { - if (t->second->Target->IsImported()) + if (t->second->Target->IsImported() + || t->second->Target->GetType() == cmTarget::INTERFACE_LIBRARY) { continue; } diff --git a/Source/cmLocalUnixMakefileGenerator3.cxx b/Source/cmLocalUnixMakefileGenerator3.cxx index 2d36089..6e2e6a8 100644 --- a/Source/cmLocalUnixMakefileGenerator3.cxx +++ b/Source/cmLocalUnixMakefileGenerator3.cxx @@ -202,11 +202,11 @@ GetLocalObjectFiles(std::map<std::string, LocalObjectInfo> &localObjectFiles) std::vector<cmSourceFile const*> objectSources; gt->GetObjectSources(objectSources); // Compute full path to object file directory for this target. - std::string dir_max; - dir_max += gt->Makefile->GetCurrentOutputDirectory(); - dir_max += "/"; - dir_max += this->GetTargetDirectory(*gt->Target); - dir_max += "/"; + std::string dir; + dir += gt->Makefile->GetCurrentOutputDirectory(); + dir += "/"; + dir += this->GetTargetDirectory(*gt->Target); + dir += "/"; // Compute the name of each object file. for(std::vector<cmSourceFile const*>::iterator si = objectSources.begin(); @@ -215,7 +215,7 @@ GetLocalObjectFiles(std::map<std::string, LocalObjectInfo> &localObjectFiles) cmSourceFile const* sf = *si; bool hasSourceExtension = true; std::string objectName = this->GetObjectFileNameWithoutTarget(*sf, - dir_max, + dir, &hasSourceExtension); if(cmSystemTools::FileIsFullPath(objectName.c_str())) { diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index 58625fb..93a06f0 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -926,6 +926,14 @@ cmMakefile::AddCustomCommandToTarget(const std::string& target, this->IssueMessage(cmake::FATAL_ERROR, e.str()); return; } + if(ti->second.GetType() == cmTarget::INTERFACE_LIBRARY) + { + cmOStringStream e; + e << "Target \"" << target << "\" is an INTERFACE library " + "that may not have PRE_BUILD, PRE_LINK, or POST_BUILD commands."; + this->IssueMessage(cmake::FATAL_ERROR, e.str()); + return; + } // Add the command to the appropriate build step for the target. std::vector<std::string> no_output; cmCustomCommand cc(this, no_output, depends, @@ -2071,7 +2079,7 @@ cmMakefile::LinearGetSourceFileWithOutput(const std::string& name) const // does this source file have a custom command? if ((*i)->GetCustomCommand()) { - // is the output of the custom command match the source files name + // Does the output of the custom command match the source file name? const std::vector<std::string>& outputs = (*i)->GetCustomCommand()->GetOutputs(); for(std::vector<std::string>::const_iterator o = outputs.begin(); @@ -2101,7 +2109,7 @@ cmSourceFile *cmMakefile::GetSourceFileWithOutput( // linear-time search for an output with a matching suffix. if(!cmSystemTools::FileIsFullPath(name.c_str())) { - return LinearGetSourceFileWithOutput(name); + return this->LinearGetSourceFileWithOutput(name); } // Otherwise we use an efficient lookup map. OutputToSourceMap::const_iterator o = this->OutputToSource.find(name); diff --git a/Tests/CMakeOnly/AllFindModules/CMakeLists.txt b/Tests/CMakeOnly/AllFindModules/CMakeLists.txt index 691728a..15493be 100644 --- a/Tests/CMakeOnly/AllFindModules/CMakeLists.txt +++ b/Tests/CMakeOnly/AllFindModules/CMakeLists.txt @@ -8,11 +8,14 @@ endif () # Avoid ctest truncation of output message(STATUS "CTEST_FULL_OUTPUT") +set(ORIGINAL_MODULE_PATH "${CMAKE_MODULE_PATH}") + file(GLOB FIND_MODULES "${CMAKE_CURRENT_SOURCE_DIR}/../../../Modules/Find*.cmake" ) macro(do_find MODULE_NAME) message(STATUS " Checking Find${MODULE_NAME}") find_package(${MODULE_NAME}) + set(CMAKE_MODULE_PATH "${ORIGINAL_MODULE_PATH}") endmacro() # It is only possible to use either Qt3 or Qt4 in one project. diff --git a/Tests/CTestTestMemcheck/NoLogDummyChecker/CMakeLists.txt b/Tests/CTestTestMemcheck/NoLogDummyChecker/CMakeLists.txt index c5aa2cd..47d6a24 100644 --- a/Tests/CTestTestMemcheck/NoLogDummyChecker/CMakeLists.txt +++ b/Tests/CTestTestMemcheck/NoLogDummyChecker/CMakeLists.txt @@ -1,7 +1,12 @@ # A dummy checker implementation that does not write the requested output file # so it triggers an error for every checker. -file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/ret0.c" "int main(){return 0;}\n") +file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/ret0.c.in" "int main(){return 0;}\n") + +configure_file( + "${CMAKE_CURRENT_BINARY_DIR}/ret0.c.in" + "${CMAKE_CURRENT_BINARY_DIR}/ret0.c" + ) foreach(_pseudo IN ITEMS valgrind purify BC) add_executable(pseudonl_${_pseudo} "${CMAKE_CURRENT_BINARY_DIR}/ret0.c") diff --git a/Tests/CustomCommand/CMakeLists.txt b/Tests/CustomCommand/CMakeLists.txt index bbae387..a194a5f 100644 --- a/Tests/CustomCommand/CMakeLists.txt +++ b/Tests/CustomCommand/CMakeLists.txt @@ -185,7 +185,7 @@ add_executable(CustomCommand # here to test adding the generation rule after referencing the # generated source in a target. add_custom_command(OUTPUT ${PROJECT_BINARY_DIR}/generated.c - DEPENDS generator + DEPENDS $<1:generator> $<0:does_not_exist> COMMAND generator ARGS ${PROJECT_BINARY_DIR}/generated.c ) @@ -221,8 +221,11 @@ add_subdirectory(GeneratorInExtraDir) add_executable(tcat tcat.cxx) +# Test that list expansion from a generator expression works. +set_property(TARGET tcat PROPERTY DEPSLIST tcat gen_redirect_in.c) + add_custom_command(OUTPUT gen_redirect.c - DEPENDS tcat gen_redirect_in.c + DEPENDS $<TARGET_PROPERTY:tcat,DEPSLIST> COMMAND tcat < ${CMAKE_CURRENT_SOURCE_DIR}/gen_redirect_in.c > gen_redirect.c COMMAND ${CMAKE_COMMAND} -E echo "#endif" >> gen_redirect.c VERBATIM diff --git a/Tests/RunCMake/interface_library/RunCMakeTest.cmake b/Tests/RunCMake/interface_library/RunCMakeTest.cmake index 3c457c5..08e81c6 100644 --- a/Tests/RunCMake/interface_library/RunCMakeTest.cmake +++ b/Tests/RunCMake/interface_library/RunCMakeTest.cmake @@ -8,3 +8,4 @@ run_cmake(invalid_signature) run_cmake(global-interface) run_cmake(genex_link) run_cmake(add_dependencies) +run_cmake(add_custom_command-TARGET) diff --git a/Tests/RunCMake/interface_library/add_custom_command-TARGET-result.txt b/Tests/RunCMake/interface_library/add_custom_command-TARGET-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/interface_library/add_custom_command-TARGET-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/interface_library/add_custom_command-TARGET-stderr.txt b/Tests/RunCMake/interface_library/add_custom_command-TARGET-stderr.txt new file mode 100644 index 0000000..c095262 --- /dev/null +++ b/Tests/RunCMake/interface_library/add_custom_command-TARGET-stderr.txt @@ -0,0 +1,5 @@ +CMake Error at add_custom_command-TARGET.cmake:4 \(add_custom_command\): + Target "iface" is an INTERFACE library that may not have PRE_BUILD, + PRE_LINK, or POST_BUILD commands. +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/interface_library/add_custom_command-TARGET.cmake b/Tests/RunCMake/interface_library/add_custom_command-TARGET.cmake new file mode 100644 index 0000000..a5136ef --- /dev/null +++ b/Tests/RunCMake/interface_library/add_custom_command-TARGET.cmake @@ -0,0 +1,6 @@ + +add_library(iface INTERFACE) + +add_custom_command(TARGET iface + COMMAND "${CMAKE_COMMAND}" -E echo test +) |