summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Source/cmAddCustomCommandCommand.h18
-rw-r--r--Source/cmTarget.cxx70
-rw-r--r--Source/cmTarget.h5
-rw-r--r--Tests/BuildDepends/CMakeLists.txt2
-rw-r--r--Tests/BuildDepends/Project/CMakeLists.txt28
-rw-r--r--Tests/BuildDepends/Project/bar.cxx17
6 files changed, 93 insertions, 47 deletions
diff --git a/Source/cmAddCustomCommandCommand.h b/Source/cmAddCustomCommandCommand.h
index 81338d6..76d9ec7 100644
--- a/Source/cmAddCustomCommandCommand.h
+++ b/Source/cmAddCustomCommandCommand.h
@@ -124,7 +124,23 @@ public:
"it is an option is to preserve compatibility with older CMake code.\n"
"If the output of the custom command is not actually "
"created as a file on disk it should be marked as SYMBOLIC with "
- "SET_SOURCE_FILES_PROPERTIES.";
+ "SET_SOURCE_FILES_PROPERTIES.\n"
+
+ "If COMMAND specifies an executable target (created by "
+ "ADD_EXECUTABLE) it will automatically be replaced by the location "
+ "of the executable created at build time. Additionally a "
+ "target-level dependency will be added so that the executable target "
+ "will be built before any target using this custom command. However "
+ "this does NOT add a file-level dependency that would cause the "
+ "custom command to re-run whenever the executable is recompiled.\n"
+
+ "If DEPENDS specifies any target (created by an ADD_* command) "
+ "a target-level dependency is created to make sure the 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.\n"
+ ;
}
cmTypeMacro(cmAddCustomCommandCommand, cmCommand);
diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx
index 6ae0aef..da33e07 100644
--- a/Source/cmTarget.cxx
+++ b/Source/cmTarget.cxx
@@ -409,7 +409,29 @@ void cmTarget::SetMakefile(cmMakefile* mf)
}
-void
+void cmTarget::CheckForTargetsAsCommand(const cmCustomCommand& cc)
+{
+ for(cmCustomCommandLines::const_iterator cit = cc.GetCommandLines().begin();
+ cit != cc.GetCommandLines().end(); ++cit )
+ {
+ std::string const& command = *cit->begin();
+ // Look for a non-imported target with this name.
+ if(cmTarget* t = this->Makefile->GetLocalGenerator()->
+ GetGlobalGenerator()->FindTarget(0, command.c_str(), false))
+ {
+ if(t->GetType() == cmTarget::EXECUTABLE)
+ {
+ // The command refers to an executable target built in
+ // this project. Add the target-level dependency to make
+ // sure the executable is up to date before this custom
+ // command possibly runs.
+ this->AddUtility(command.c_str());
+ }
+ }
+ }
+}
+
+void
cmTarget
::CheckForTargetsAsCommand(const std::vector<cmCustomCommand>& commands)
{
@@ -417,20 +439,7 @@ cmTarget
cli != commands.end();
++cli )
{
- for(cmCustomCommandLines::const_iterator cit =
- cli->GetCommandLines().begin();
- cit!=cli->GetCommandLines().end();
- ++cit )
- {
- std::string command = *cit->begin();
- // see if we can find a target with this name
- cmTarget* t = this->Makefile->GetLocalGenerator()->
- GetGlobalGenerator()->FindTarget(0, command.c_str(), false);
- if ( ( t ) && ( t->GetType() ==cmTarget::EXECUTABLE ) )
- {
- this->AddUtility ( command.c_str() );
- }
- }
+ this->CheckForTargetsAsCommand(*cli);
}
}
@@ -566,24 +575,8 @@ void cmTarget::TraceVSDependencies(std::string projFile,
}
}
- // check if commands for this custom commands are names of targets and
- // if that's the case add these targets as dependencies
- std::vector<std::string> automaticTargetDepends;
- for(cmCustomCommandLines::const_iterator it=
- outsf->GetCustomCommand()->GetCommandLines().begin();
- it!=outsf->GetCustomCommand()->GetCommandLines().end();
- ++it)
- {
- const std::string& currentCommand = (*it)[0];
- // see if we can find a target with this name
- cmTarget* t = this->Makefile->GetLocalGenerator()->
- GetGlobalGenerator()->FindTarget(0, currentCommand.c_str(), false);
- if (( t) && (t->GetType()==cmTarget::EXECUTABLE))
- {
- automaticTargetDepends.push_back(currentCommand);
- }
- }
- outsf->GetCustomCommand()->AppendDepends(automaticTargetDepends);
+ // Add target-level dependencies for the commands.
+ this->CheckForTargetsAsCommand(*outsf->GetCustomCommand());
// add its dependencies to the list to check
for (unsigned int i = 0;
@@ -598,10 +591,9 @@ void cmTarget::TraceVSDependencies(std::string projFile,
dep = cmSystemTools::GetFilenameWithoutLastExtension(dep);
}
bool isUtility = false;
- // see if we can find a target with this name
- cmTarget* t = this->Makefile->GetLocalGenerator()->
- GetGlobalGenerator()->FindTarget(0, dep.c_str(), false);
- if(t)
+ // Check for a non-imported target with this name.
+ if(cmTarget* t = this->Makefile->GetLocalGenerator()->
+ GetGlobalGenerator()->FindTarget(0, dep.c_str(), false))
{
// if we find the target and the dep was given as a full
// path, then make sure it was not a full path to something
@@ -629,7 +621,9 @@ void cmTarget::TraceVSDependencies(std::string projFile,
}
if(isUtility)
{
- // add the depend as a utility on the target
+ // The dependency refers to a target built in this project.
+ // Add the target-level dependency to make sure the target
+ // is up to date before this custom command possibly runs.
this->AddUtility(dep.c_str());
}
else
diff --git a/Source/cmTarget.h b/Source/cmTarget.h
index 4161b35..8bb8f9b 100644
--- a/Source/cmTarget.h
+++ b/Source/cmTarget.h
@@ -296,9 +296,10 @@ private:
const LibraryID& dep);
/*
- * Checks the prebuild, prelink and postbuild custom commands for known
- * targets and adds them to the dependencies.
+ * Check custom commands for known targets and add a target-level
+ * dependency.
*/
+ void CheckForTargetsAsCommand(const cmCustomCommand& cc);
void CheckForTargetsAsCommand(const std::vector<cmCustomCommand>& commands);
diff --git a/Tests/BuildDepends/CMakeLists.txt b/Tests/BuildDepends/CMakeLists.txt
index 80793bc..3a4ba26 100644
--- a/Tests/BuildDepends/CMakeLists.txt
+++ b/Tests/BuildDepends/CMakeLists.txt
@@ -60,5 +60,5 @@ message("${out}")
if("${out}" STREQUAL "foo changed ")
message("Worked!")
else("${out}" STREQUAL "foo changed ")
- message(SEND_ERROR "Program did not rebuild with changed file")
+ message(SEND_ERROR "Project did not rebuild properly!")
endif("${out}" STREQUAL "foo changed ")
diff --git a/Tests/BuildDepends/Project/CMakeLists.txt b/Tests/BuildDepends/Project/CMakeLists.txt
index f9cbc56..e831676 100644
--- a/Tests/BuildDepends/Project/CMakeLists.txt
+++ b/Tests/BuildDepends/Project/CMakeLists.txt
@@ -1,4 +1,30 @@
project(testRebuild)
add_library(foo STATIC ${testRebuild_BINARY_DIR}/foo.cxx)
-add_executable(bar bar.cxx)
+
+# Add a generated header that regenerates when the generator is
+# rebuilt.
+add_custom_command(
+ OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/regen.h
+ COMMAND generator ${CMAKE_CURRENT_BINARY_DIR}/regen.h regen
+ DEPENDS generator # adds file-level dependency to re-run rule
+ )
+
+# Add a generated header that does NOT regenerate when the generator
+# is rebuilt.
+add_custom_command(
+ OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/noregen.h
+ COMMAND generator ${CMAKE_CURRENT_BINARY_DIR}/noregen.h noregen
+ )
+
+# Test that the generator rebuilds when the static library source file
+# changes. This should cause regen.h to be recreated also.
+add_executable(generator generator.cxx)
+target_link_libraries(generator foo)
+
+# Build an executable to drive the build and rebuild.
+include_directories(${CMAKE_CURRENT_BINARY_DIR})
+add_executable(bar bar.cxx
+ ${CMAKE_CURRENT_BINARY_DIR}/regen.h
+ ${CMAKE_CURRENT_BINARY_DIR}/noregen.h
+ )
target_link_libraries(bar foo)
diff --git a/Tests/BuildDepends/Project/bar.cxx b/Tests/BuildDepends/Project/bar.cxx
index 4764af5..76e934f 100644
--- a/Tests/BuildDepends/Project/bar.cxx
+++ b/Tests/BuildDepends/Project/bar.cxx
@@ -1,10 +1,19 @@
-#include "stdio.h"
+#include <stdio.h>
+#include <string.h>
+#include <regen.h>
+#include <noregen.h>
-const char* foo();
int main()
{
- int i;
- printf("%s\n", foo());
+ /* Make sure the noregen header was not regenerated. */
+ if(strcmp("foo", noregen_string) != 0)
+ {
+ printf("FAILED: noregen.h was regenerated!\n");
+ return 1;
+ }
+
+ /* Print out the string that should have been regenerated. */
+ printf("%s\n", regen_string);
fflush(stdout);
for(;;);
return 0;