ENH: Add a depends check step to custom targets. Add support for the IMPLICIT_DEPENDS feature of custom commands when building in custom targets. Convert multiple-output pair checks to be per-target instead of global.

This commit is contained in:
Brad King 2007-12-21 12:22:12 -05:00
parent 6586149d64
commit d83b4cd255
16 changed files with 161 additions and 153 deletions

View File

@ -1680,13 +1680,6 @@ void cmGlobalGenerator::AppendDirectoryForConfig(const char*, const char*,
// configuration. // configuration.
} }
//----------------------------------------------------------------------------
void cmGlobalGenerator::CheckMultipleOutputs(cmMakefile*, bool)
{
// Only certain generators need this check. They define this
// method.
}
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
std::vector<cmTarget *>& cmGlobalGenerator std::vector<cmTarget *>& cmGlobalGenerator
::GetTargetDepends(cmTarget& target) ::GetTargetDepends(cmTarget& target)

View File

@ -211,9 +211,6 @@ public:
void AddTarget(cmTargets::value_type &v); void AddTarget(cmTargets::value_type &v);
/** Support for multiple custom command outputs. */
virtual void CheckMultipleOutputs(cmMakefile* mf, bool verbose);
virtual const char* GetAllTargetName() { return "ALL_BUILD"; } virtual const char* GetAllTargetName() { return "ALL_BUILD"; }
virtual const char* GetInstallTargetName() { return "INSTALL"; } virtual const char* GetInstallTargetName() { return "INSTALL"; }
virtual const char* GetInstallLocalTargetName() { return 0; } virtual const char* GetInstallLocalTargetName() { return 0; }

View File

@ -132,16 +132,6 @@ void cmGlobalUnixMakefileGenerator3
"default make target. A \"make install\" target is also provided."; "default make target. A \"make install\" target is also provided.";
} }
//----------------------------------------------------------------------------
void
cmGlobalUnixMakefileGenerator3
::AddMultipleOutputPair(const char* depender, const char* dependee)
{
MultipleOutputPairsType::value_type p(depender, dependee);
this->MultipleOutputPairs.insert(p);
}
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void cmGlobalUnixMakefileGenerator3::Generate() void cmGlobalUnixMakefileGenerator3::Generate()
{ {
@ -373,62 +363,6 @@ void cmGlobalUnixMakefileGenerator3::WriteMainCMakefile()
this->WriteMainCMakefileLanguageRules(cmakefileStream, this->WriteMainCMakefileLanguageRules(cmakefileStream,
this->LocalGenerators); this->LocalGenerators);
if(!this->MultipleOutputPairs.empty())
{
cmakefileStream
<< "\n"
<< "SET(CMAKE_MULTIPLE_OUTPUT_PAIRS\n";
for(MultipleOutputPairsType::const_iterator pi =
this->MultipleOutputPairs.begin();
pi != this->MultipleOutputPairs.end(); ++pi)
{
cmakefileStream << " \"" << pi->first << "\" \""
<< pi->second << "\"\n";
}
cmakefileStream << " )\n\n";
}
}
//----------------------------------------------------------------------------
void cmGlobalUnixMakefileGenerator3::CheckMultipleOutputs(cmMakefile* mf,
bool verbose)
{
// Get the string listing the multiple output pairs.
const char* pairs_string = mf->GetDefinition("CMAKE_MULTIPLE_OUTPUT_PAIRS");
if(!pairs_string)
{
return;
}
// Convert the string to a list and preserve empty entries.
std::vector<std::string> pairs;
cmSystemTools::ExpandListArgument(pairs_string, pairs, true);
for(std::vector<std::string>::const_iterator i = pairs.begin();
i != pairs.end(); ++i)
{
const std::string& depender = *i;
if(++i != pairs.end())
{
const std::string& dependee = *i;
// If the depender is missing then delete the dependee to make
// sure both will be regenerated.
if(cmSystemTools::FileExists(dependee.c_str()) &&
!cmSystemTools::FileExists(depender.c_str()))
{
if(verbose)
{
cmOStringStream msg;
msg << "Deleting primary custom command output \"" << dependee
<< "\" because another output \""
<< depender << "\" does not exist." << std::endl;
cmSystemTools::Stdout(msg.str().c_str());
}
cmSystemTools::RemoveFile(dependee.c_str());
}
}
}
} }
void cmGlobalUnixMakefileGenerator3 void cmGlobalUnixMakefileGenerator3
@ -763,21 +697,18 @@ cmGlobalUnixMakefileGenerator3
<< localName << "\n\n"; << localName << "\n\n";
commands.clear(); commands.clear();
if (t->second.GetType() != cmTarget::UTILITY) makeTargetName = localName;
makeTargetName += "/depend";
commands.push_back(lg->GetRecursiveMakeCall
(makefileName.c_str(),makeTargetName.c_str()));
// add requires if we need it for this generator
if (needRequiresStep)
{ {
makeTargetName = localName; makeTargetName = localName;
makeTargetName += "/depend"; makeTargetName += "/requires";
commands.push_back(lg->GetRecursiveMakeCall commands.push_back(lg->GetRecursiveMakeCall
(makefileName.c_str(),makeTargetName.c_str())); (makefileName.c_str(),makeTargetName.c_str()));
// add requires if we need it for this generator
if (needRequiresStep)
{
makeTargetName = localName;
makeTargetName += "/requires";
commands.push_back(lg->GetRecursiveMakeCall
(makefileName.c_str(),makeTargetName.c_str()));
}
} }
makeTargetName = localName; makeTargetName = localName;
makeTargetName += "/build"; makeTargetName += "/build";

View File

@ -98,19 +98,6 @@ public:
void WriteConvenienceRules(std::ostream& ruleFileStream, void WriteConvenienceRules(std::ostream& ruleFileStream,
std::set<cmStdString> &emitted); std::set<cmStdString> &emitted);
/** 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
just depend on the first one. The check-build-system step must
remove a dependee if the depender is missing to make sure both
are regenerated properly. This method is used by the local
makefile generators to register such pairs. */
void AddMultipleOutputPair(const char* depender, const char* dependee);
/** Support for multiple custom command outputs. Called during
check-build-system step. */
virtual void CheckMultipleOutputs(cmMakefile* mf, bool verbose);
/** Get the command to use for a target that has no rule. This is /** Get the command to use for a target that has no rule. This is
used for multiple output dependencies and for cmake_force. */ used for multiple output dependencies and for cmake_force. */
std::string GetEmptyRuleHackCommand() { return this->EmptyRuleHackCommand; } std::string GetEmptyRuleHackCommand() { return this->EmptyRuleHackCommand; }
@ -191,9 +178,6 @@ protected:
// in the rule to satisfy the make program. // in the rule to satisfy the make program.
std::string EmptyRuleHackCommand; std::string EmptyRuleHackCommand;
typedef std::map<cmStdString, cmStdString> MultipleOutputPairsType;
MultipleOutputPairsType MultipleOutputPairs;
std::map<cmStdString, int > TargetSourceFileCount; std::map<cmStdString, int > TargetSourceFileCount;
bool ForceVerboseMakefiles; bool ForceVerboseMakefiles;
}; };

View File

@ -1229,6 +1229,16 @@ bool cmLocalUnixMakefileGenerator3::UpdateDependencies(const char* tgtInfo,
bool verbose, bool verbose,
bool color) bool color)
{ {
// read in the target info file
if(!this->Makefile->ReadListFile(0, tgtInfo) ||
cmSystemTools::GetErrorOccuredFlag())
{
cmSystemTools::Error("Target DependInfo.cmake file not found");
}
// Check if any multiple output pairs have a missing file.
this->CheckMultipleOutputs(verbose);
std::string dir = cmSystemTools::GetFilenamePath(tgtInfo); std::string dir = cmSystemTools::GetFilenamePath(tgtInfo);
std::string internalDependFile = dir + "/depend.internal"; std::string internalDependFile = dir + "/depend.internal";
std::string dependFile = dir + "/depend.make"; std::string dependFile = dir + "/depend.make";
@ -1257,7 +1267,7 @@ bool cmLocalUnixMakefileGenerator3::UpdateDependencies(const char* tgtInfo,
fprintf(stdout, "%s\n", message.c_str()); fprintf(stdout, "%s\n", message.c_str());
#endif #endif
return this->ScanDependencies(tgtInfo); return this->ScanDependencies(dir.c_str());
} }
else else
{ {
@ -1267,11 +1277,10 @@ bool cmLocalUnixMakefileGenerator3::UpdateDependencies(const char* tgtInfo,
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
bool cmLocalUnixMakefileGenerator3::ScanDependencies(const char* tgtInfo) bool
cmLocalUnixMakefileGenerator3
::ScanDependencies(const char* targetDir)
{ {
// The info file for this target
std::string infoFile = tgtInfo;
// Read the directory information file. // Read the directory information file.
cmMakefile* mf = this->Makefile; cmMakefile* mf = this->Makefile;
bool haveDirectoryInfo = false; bool haveDirectoryInfo = false;
@ -1284,13 +1293,6 @@ bool cmLocalUnixMakefileGenerator3::ScanDependencies(const char* tgtInfo)
haveDirectoryInfo = true; haveDirectoryInfo = true;
} }
// read in the target info file
if(!mf->ReadListFile(0, infoFile.c_str()) ||
cmSystemTools::GetErrorOccuredFlag())
{
cmSystemTools::Error("Target DependInfo.cmake file not found");
}
// Lookup useful directory information. // Lookup useful directory information.
if(haveDirectoryInfo) if(haveDirectoryInfo)
{ {
@ -1322,7 +1324,7 @@ bool cmLocalUnixMakefileGenerator3::ScanDependencies(const char* tgtInfo)
} }
// create the file stream for the depends file // create the file stream for the depends file
std::string dir = cmSystemTools::GetFilenamePath(infoFile); std::string dir = targetDir;
// Open the rule file. This should be copy-if-different because the // Open the rule file. This should be copy-if-different because the
// rules may depend on this file itself. // rules may depend on this file itself.
@ -1449,6 +1451,48 @@ bool cmLocalUnixMakefileGenerator3::ScanDependencies(const char* tgtInfo)
return true; return true;
} }
//----------------------------------------------------------------------------
void cmLocalUnixMakefileGenerator3::CheckMultipleOutputs(bool verbose)
{
cmMakefile* mf = this->Makefile;
// Get the string listing the multiple output pairs.
const char* pairs_string = mf->GetDefinition("CMAKE_MULTIPLE_OUTPUT_PAIRS");
if(!pairs_string)
{
return;
}
// Convert the string to a list and preserve empty entries.
std::vector<std::string> pairs;
cmSystemTools::ExpandListArgument(pairs_string, pairs, true);
for(std::vector<std::string>::const_iterator i = pairs.begin();
i != pairs.end(); ++i)
{
const std::string& depender = *i;
if(++i != pairs.end())
{
const std::string& dependee = *i;
// If the depender is missing then delete the dependee to make
// sure both will be regenerated.
if(cmSystemTools::FileExists(dependee.c_str()) &&
!cmSystemTools::FileExists(depender.c_str()))
{
if(verbose)
{
cmOStringStream msg;
msg << "Deleting primary custom command output \"" << dependee
<< "\" because another output \""
<< depender << "\" does not exist." << std::endl;
cmSystemTools::Stdout(msg.str().c_str());
}
cmSystemTools::RemoveFile(dependee.c_str());
}
}
}
}
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void cmLocalUnixMakefileGenerator3 void cmLocalUnixMakefileGenerator3
::WriteLocalAllRules(std::ostream& ruleFileStream) ::WriteLocalAllRules(std::ostream& ruleFileStream)

View File

@ -203,9 +203,6 @@ public:
virtual bool UpdateDependencies(const char* tgtInfo, virtual bool UpdateDependencies(const char* tgtInfo,
bool verbose, bool color); bool verbose, bool color);
/** Called from command-line hook to scan dependencies. */
bool ScanDependencies(const char* tgtInfo);
/** Called from command-line hook to clear dependencies. */ /** Called from command-line hook to clear dependencies. */
virtual void ClearDependencies(cmMakefile* mf, bool verbose); virtual void ClearDependencies(cmMakefile* mf, bool verbose);
@ -325,6 +322,10 @@ protected:
std::map<cmStdString, std::vector<int> > ProgressFiles; std::map<cmStdString, std::vector<int> > ProgressFiles;
// Helper methods for dependeny updates.
bool ScanDependencies(const char* targetDir);
void CheckMultipleOutputs(bool verbose);
private: private:
friend class cmMakefileTargetGenerator; friend class cmMakefileTargetGenerator;
friend class cmMakefileExecutableTargetGenerator; friend class cmMakefileExecutableTargetGenerator;

View File

@ -45,9 +45,6 @@ void cmMakefileExecutableTargetGenerator::WriteRuleFiles()
// write the per-target per-language flags // write the per-target per-language flags
this->WriteTargetLanguageFlags(); this->WriteTargetLanguageFlags();
// Write the dependency generation rule.
this->WriteTargetDependRules();
// write the link rules // write the link rules
this->WriteExecutableRule(false); this->WriteExecutableRule(false);
if(this->Target->NeedRelinkBeforeInstall()) if(this->Target->NeedRelinkBeforeInstall())
@ -62,6 +59,10 @@ void cmMakefileExecutableTargetGenerator::WriteRuleFiles()
// Write clean target // Write clean target
this->WriteTargetCleanRules(); this->WriteTargetCleanRules();
// Write the dependency generation rule. This must be done last so
// that multiple output pair information is available.
this->WriteTargetDependRules();
// close the streams // close the streams
this->CloseFileStreams(); this->CloseFileStreams();
} }

View File

@ -47,9 +47,6 @@ void cmMakefileLibraryTargetGenerator::WriteRuleFiles()
// write the per-target per-language flags // write the per-target per-language flags
this->WriteTargetLanguageFlags(); this->WriteTargetLanguageFlags();
// Write the dependency generation rule.
this->WriteTargetDependRules();
// write the link rules // write the link rules
// Write the rule for this target type. // Write the rule for this target type.
switch(this->Target->GetType()) switch(this->Target->GetType())
@ -85,6 +82,10 @@ void cmMakefileLibraryTargetGenerator::WriteRuleFiles()
// Write clean target // Write clean target
this->WriteTargetCleanRules(); this->WriteTargetCleanRules();
// Write the dependency generation rule. This must be done last so
// that multiple output pair information is available.
this->WriteTargetDependRules();
// close the streams // close the streams
this->CloseFileStreams(); this->CloseFileStreams();
} }

View File

@ -775,6 +775,23 @@ void cmMakefileTargetGenerator::WriteTargetDependRules()
this->LocalGenerator-> this->LocalGenerator->
WriteDependLanguageInfo(*this->InfoFileStream,*this->Target); WriteDependLanguageInfo(*this->InfoFileStream,*this->Target);
// Store multiple output pairs in the depend info file.
if(!this->MultipleOutputPairs.empty())
{
*this->InfoFileStream
<< "\n"
<< "# Pairs of files generated by the same build rule.\n"
<< "SET(CMAKE_MULTIPLE_OUTPUT_PAIRS\n";
for(MultipleOutputPairsType::const_iterator pi =
this->MultipleOutputPairs.begin();
pi != this->MultipleOutputPairs.end(); ++pi)
{
*this->InfoFileStream << " \"" << pi->first << "\" \""
<< pi->second << "\"\n";
}
*this->InfoFileStream << " )\n\n";
}
// and now write the rule to use it // and now write the rule to use it
std::vector<std::string> depends; std::vector<std::string> depends;
std::vector<std::string> commands; std::vector<std::string> commands;
@ -993,7 +1010,7 @@ cmMakefileTargetGenerator
// the check-build-system step will remove the primary output if any // the check-build-system step will remove the primary output if any
// extra outputs are missing. This forces the rule to regenerate // extra outputs are missing. This forces the rule to regenerate
// all outputs. // all outputs.
this->GlobalGenerator->AddMultipleOutputPair(out, in); this->AddMultipleOutputPair(out, in);
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@ -1334,3 +1351,12 @@ void cmMakefileTargetGenerator::WriteProgressVariables(unsigned long total,
current += this->NumberOfProgressActions; current += this->NumberOfProgressActions;
delete progressFileStream; delete progressFileStream;
} }
//----------------------------------------------------------------------------
void
cmMakefileTargetGenerator
::AddMultipleOutputPair(const char* depender, const char* dependee)
{
MultipleOutputPairsType::value_type p(depender, dependee);
this->MultipleOutputPairs.insert(p);
}

View File

@ -119,6 +119,15 @@ protected:
// append intertarget dependencies // append intertarget dependencies
void AppendTargetDepends(std::vector<std::string>& depends); void AppendTargetDepends(std::vector<std::string>& 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
just depend on the first one. The check-build-system step must
remove a dependee if the depender is missing to make sure both
are regenerated properly. This method is used by the local
makefile generators to register such pairs. */
void AddMultipleOutputPair(const char* depender, const char* dependee);
virtual void CloseFileStreams(); virtual void CloseFileStreams();
void RemoveForbiddenFlags(const char* flagVar, const char* linkLang, void RemoveForbiddenFlags(const char* flagVar, const char* linkLang,
std::string& linkFlags); std::string& linkFlags);
@ -166,6 +175,8 @@ protected:
// Set of object file names that will be built in this directory. // Set of object file names that will be built in this directory.
std::set<cmStdString> ObjectFiles; std::set<cmStdString> ObjectFiles;
typedef std::map<cmStdString, cmStdString> MultipleOutputPairsType;
MultipleOutputPairsType MultipleOutputPairs;
//================================================================== //==================================================================
// Convenience routines that do nothing more than forward to // Convenience routines that do nothing more than forward to

View File

@ -89,6 +89,10 @@ void cmMakefileUtilityTargetGenerator::WriteRuleFiles()
// Write clean target // Write clean target
this->WriteTargetCleanRules(); this->WriteTargetCleanRules();
// Write the dependency generation rule. This must be done last so
// that multiple output pair information is available.
this->WriteTargetDependRules();
// close the streams // close the streams
this->CloseFileStreams(); this->CloseFileStreams();
} }

View File

@ -2547,29 +2547,24 @@ int cmake::CheckBuildSystem()
return 1; return 1;
} }
// Now that we know the generator used to build the project, use it if(this->ClearBuildSystem)
// to check the dependency integrity.
const char* genName = mf->GetDefinition("CMAKE_DEPENDS_GENERATOR");
if (!genName || genName[0] == '\0')
{ {
genName = "Unix Makefiles"; // Get the generator used for this build system.
} const char* genName = mf->GetDefinition("CMAKE_DEPENDS_GENERATOR");
// this global generator is never set to the cmake object so it is never if(!genName || genName[0] == '\0')
// deleted, so make it an auto_ptr
std::auto_ptr<cmGlobalGenerator> ggd(this->CreateGlobalGenerator(genName));
if (ggd.get())
{
// Check the dependencies in case source files were removed.
std::auto_ptr<cmLocalGenerator> lgd(ggd->CreateLocalGenerator());
lgd->SetGlobalGenerator(ggd.get());
if(this->ClearBuildSystem)
{ {
lgd->ClearDependencies(mf, verbose); genName = "Unix Makefiles";
} }
// Check for multiple output pairs. // Create the generator and use it to clear the dependencies.
ggd->CheckMultipleOutputs(mf, verbose); std::auto_ptr<cmGlobalGenerator>
ggd(this->CreateGlobalGenerator(genName));
if(ggd.get())
{
std::auto_ptr<cmLocalGenerator> lgd(ggd->CreateLocalGenerator());
lgd->SetGlobalGenerator(ggd.get());
lgd->ClearDependencies(mf, verbose);
}
} }
// Get the set of dependencies and outputs. // Get the set of dependencies and outputs.

View File

@ -13,6 +13,8 @@ write_file(${BuildDepends_BINARY_DIR}/Project/foo.cxx
file(WRITE ${BuildDepends_BINARY_DIR}/Project/zot.hxx.in file(WRITE ${BuildDepends_BINARY_DIR}/Project/zot.hxx.in
"static const char* zot = \"zot\";\n") "static const char* zot = \"zot\";\n")
file(WRITE ${BuildDepends_BINARY_DIR}/Project/zot_custom.hxx.in
"static const char* zot_custom = \"zot_custom\";\n")
message("Building project first time") message("Building project first time")
try_compile(RESULT try_compile(RESULT
@ -70,11 +72,11 @@ execute_process(COMMAND ${zot} OUTPUT_VARIABLE out RESULT_VARIABLE runResult)
string(REGEX REPLACE "[\r\n]" " " out "${out}") string(REGEX REPLACE "[\r\n]" " " out "${out}")
message("Run result: ${runResult} Output: \"${out}\"") message("Run result: ${runResult} Output: \"${out}\"")
if("${out}" STREQUAL "zot ") if("${out}" STREQUAL "[zot] [zot_custom] ")
message("Worked!") message("Worked!")
else("${out}" STREQUAL "zot ") else("${out}" STREQUAL "[zot] [zot_custom] ")
message(SEND_ERROR "Project did not initially build properly: ${out}") message(SEND_ERROR "Project did not initially build properly: ${out}")
endif("${out}" STREQUAL "zot ") endif("${out}" STREQUAL "[zot] [zot_custom] ")
message("Waiting 3 seconds...") message("Waiting 3 seconds...")
# any additional argument will cause ${bar} to wait forever # any additional argument will cause ${bar} to wait forever
@ -85,6 +87,8 @@ write_file(${BuildDepends_BINARY_DIR}/Project/foo.cxx
"const char* foo() { return \"foo changed\";}" ) "const char* foo() { return \"foo changed\";}" )
file(WRITE ${BuildDepends_BINARY_DIR}/Project/zot.hxx.in file(WRITE ${BuildDepends_BINARY_DIR}/Project/zot.hxx.in
"static const char* zot = \"zot changed\";\n") "static const char* zot = \"zot changed\";\n")
file(WRITE ${BuildDepends_BINARY_DIR}/Project/zot_custom.hxx.in
"static const char* zot_custom = \"zot_custom changed\";\n")
message("Building project second time") message("Building project second time")
try_compile(RESULT try_compile(RESULT
@ -137,8 +141,8 @@ execute_process(COMMAND ${zot} OUTPUT_VARIABLE out RESULT_VARIABLE runResult)
string(REGEX REPLACE "[\r\n]" " " out "${out}") string(REGEX REPLACE "[\r\n]" " " out "${out}")
message("Run result: ${runResult} Output: \"${out}\"") message("Run result: ${runResult} Output: \"${out}\"")
if("${out}" STREQUAL "zot changed ") if("${out}" STREQUAL "[zot changed] [zot_custom changed] ")
message("Worked!") message("Worked!")
else("${out}" STREQUAL "zot changed ") else("${out}" STREQUAL "[zot changed] [zot_custom changed] ")
message(SEND_ERROR "Project did not rebuild properly!") message(SEND_ERROR "Project did not rebuild properly!")
endif("${out}" STREQUAL "zot changed ") endif("${out}" STREQUAL "[zot changed] [zot_custom changed] ")

View File

@ -32,9 +32,12 @@ add_executable(bar bar.cxx
IF("${CMAKE_GENERATOR}" MATCHES "Make") IF("${CMAKE_GENERATOR}" MATCHES "Make")
# Test the IMPLICIT_DEPENDS feature. # Test the IMPLICIT_DEPENDS feature.
SET(ZOT_DEPENDS IMPLICIT_DEPENDS CXX ${CMAKE_CURRENT_SOURCE_DIR}/dep.cxx) SET(ZOT_DEPENDS IMPLICIT_DEPENDS CXX ${CMAKE_CURRENT_SOURCE_DIR}/dep.cxx)
SET(ZOT_CUSTOM_DEP
IMPLICIT_DEPENDS CXX ${CMAKE_CURRENT_SOURCE_DIR}/dep_custom.cxx)
ELSE("${CMAKE_GENERATOR}" MATCHES "Make") ELSE("${CMAKE_GENERATOR}" MATCHES "Make")
# No IMPLICIT_DEPENDS...just depend directly. # No IMPLICIT_DEPENDS...just depend directly.
SET(ZOT_DEPENDS DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/zot.hxx.in) SET(ZOT_DEPENDS DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/zot.hxx.in)
SET(ZOT_CUSTOM_DEP DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/zot_custom.hxx.in)
ENDIF("${CMAKE_GENERATOR}" MATCHES "Make") ENDIF("${CMAKE_GENERATOR}" MATCHES "Make")
add_custom_command( add_custom_command(
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/zot.hxx OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/zot.hxx
@ -44,4 +47,15 @@ add_custom_command(
${ZOT_DEPENDS} ${ZOT_DEPENDS}
) )
add_custom_command(
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/zot_custom.hxx
COMMAND ${CMAKE_COMMAND} -E copy
${CMAKE_CURRENT_BINARY_DIR}/zot_custom.hxx.in
${CMAKE_CURRENT_BINARY_DIR}/zot_custom.hxx
${ZOT_CUSTOM_DEP}
)
add_custom_target(zot_custom ALL DEPENDS
${CMAKE_CURRENT_BINARY_DIR}/zot_custom.hxx)
add_executable(zot zot.cxx ${CMAKE_CURRENT_BINARY_DIR}/zot.hxx) add_executable(zot zot.cxx ${CMAKE_CURRENT_BINARY_DIR}/zot.hxx)
add_dependencies(zot zot_custom)

View File

@ -0,0 +1 @@
#include <zot_custom.hxx.in>

View File

@ -1,9 +1,10 @@
#include <zot.hxx> #include <zot.hxx>
#include <zot_custom.hxx>
#include <stdio.h> #include <stdio.h>
int main() int main()
{ {
printf("%s\n", zot); printf("[%s] [%s]\n", zot, zot_custom);
fflush(stdout); fflush(stdout);
return 0; return 0;
} }