BUG: Target names in the COMMAND part of a custom command should not create a file-level dependency that forces the command to rerun when the executable target rebuilds, but the target-level dependency should still be created. Target names in a DEPENDS should do both a target-level and file-level dependency. Updated the BuildDepends test to check that this works.
This commit is contained in:
parent
702d785c9a
commit
c288da754a
@ -124,7 +124,23 @@ public:
|
|||||||
"it is an option is to preserve compatibility with older CMake code.\n"
|
"it is an option is to preserve compatibility with older CMake code.\n"
|
||||||
"If the output of the custom command is not actually "
|
"If the output of the custom command is not actually "
|
||||||
"created as a file on disk it should be marked as SYMBOLIC with "
|
"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);
|
cmTypeMacro(cmAddCustomCommandCommand, cmCommand);
|
||||||
|
@ -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
|
cmTarget
|
||||||
::CheckForTargetsAsCommand(const std::vector<cmCustomCommand>& commands)
|
::CheckForTargetsAsCommand(const std::vector<cmCustomCommand>& commands)
|
||||||
{
|
{
|
||||||
@ -417,20 +439,7 @@ cmTarget
|
|||||||
cli != commands.end();
|
cli != commands.end();
|
||||||
++cli )
|
++cli )
|
||||||
{
|
{
|
||||||
for(cmCustomCommandLines::const_iterator cit =
|
this->CheckForTargetsAsCommand(*cli);
|
||||||
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() );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -566,24 +575,8 @@ void cmTarget::TraceVSDependencies(std::string projFile,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if commands for this custom commands are names of targets and
|
// Add target-level dependencies for the commands.
|
||||||
// if that's the case add these targets as dependencies
|
this->CheckForTargetsAsCommand(*outsf->GetCustomCommand());
|
||||||
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 its dependencies to the list to check
|
// add its dependencies to the list to check
|
||||||
for (unsigned int i = 0;
|
for (unsigned int i = 0;
|
||||||
@ -598,10 +591,9 @@ void cmTarget::TraceVSDependencies(std::string projFile,
|
|||||||
dep = cmSystemTools::GetFilenameWithoutLastExtension(dep);
|
dep = cmSystemTools::GetFilenameWithoutLastExtension(dep);
|
||||||
}
|
}
|
||||||
bool isUtility = false;
|
bool isUtility = false;
|
||||||
// see if we can find a target with this name
|
// Check for a non-imported target with this name.
|
||||||
cmTarget* t = this->Makefile->GetLocalGenerator()->
|
if(cmTarget* t = this->Makefile->GetLocalGenerator()->
|
||||||
GetGlobalGenerator()->FindTarget(0, dep.c_str(), false);
|
GetGlobalGenerator()->FindTarget(0, dep.c_str(), false))
|
||||||
if(t)
|
|
||||||
{
|
{
|
||||||
// if we find the target and the dep was given as a full
|
// 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
|
// path, then make sure it was not a full path to something
|
||||||
@ -629,7 +621,9 @@ void cmTarget::TraceVSDependencies(std::string projFile,
|
|||||||
}
|
}
|
||||||
if(isUtility)
|
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());
|
this->AddUtility(dep.c_str());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -296,9 +296,10 @@ private:
|
|||||||
const LibraryID& dep);
|
const LibraryID& dep);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Checks the prebuild, prelink and postbuild custom commands for known
|
* Check custom commands for known targets and add a target-level
|
||||||
* targets and adds them to the dependencies.
|
* dependency.
|
||||||
*/
|
*/
|
||||||
|
void CheckForTargetsAsCommand(const cmCustomCommand& cc);
|
||||||
void CheckForTargetsAsCommand(const std::vector<cmCustomCommand>& commands);
|
void CheckForTargetsAsCommand(const std::vector<cmCustomCommand>& commands);
|
||||||
|
|
||||||
|
|
||||||
|
@ -60,5 +60,5 @@ message("${out}")
|
|||||||
if("${out}" STREQUAL "foo changed ")
|
if("${out}" STREQUAL "foo changed ")
|
||||||
message("Worked!")
|
message("Worked!")
|
||||||
else("${out}" STREQUAL "foo changed ")
|
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 ")
|
endif("${out}" STREQUAL "foo changed ")
|
||||||
|
@ -1,4 +1,30 @@
|
|||||||
project(testRebuild)
|
project(testRebuild)
|
||||||
add_library(foo STATIC ${testRebuild_BINARY_DIR}/foo.cxx)
|
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)
|
target_link_libraries(bar foo)
|
||||||
|
@ -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 main()
|
||||||
{
|
{
|
||||||
int i;
|
/* Make sure the noregen header was not regenerated. */
|
||||||
printf("%s\n", foo());
|
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);
|
fflush(stdout);
|
||||||
for(;;);
|
for(;;);
|
||||||
return 0;
|
return 0;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user