ENH: Implemented full per-object test for whether provides-requires mode is needed. This will still use a recursive make for any Fortran object even if it doesn't have requires. It is possible to avoid it but we can do that later.

This commit is contained in:
Brad King 2005-01-28 14:17:48 -05:00
parent 62aba58b82
commit 892a7c4fd9
2 changed files with 130 additions and 89 deletions

View File

@ -42,20 +42,12 @@
# define CMLUMG_MAKEFILE_NAME "Makefile2" # define CMLUMG_MAKEFILE_NAME "Makefile2"
#endif #endif
#if 0
# define CMLUMG_PROVIDES_REQUIRES
#endif
// TODO: Add "help" target. // TODO: Add "help" target.
// TODO: Identify remaining relative path violations. // TODO: Identify remaining relative path violations.
// TODO: Add test to drive installation through native build system. // TODO: Add test to drive installation through native build system.
// TODO: External object file feature. // TODO: External object file feature.
// TODO: Need test for separate executable/library output path. // TODO: Need test for separate executable/library output path.
// TODO: Fortran support:
// - This needs a "provides-requires" mode for the .o files in a target.
// - Driving target must be TGT.requires: account for this in jump-and-build.
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
cmLocalUnixMakefileGenerator2::cmLocalUnixMakefileGenerator2() cmLocalUnixMakefileGenerator2::cmLocalUnixMakefileGenerator2()
{ {
@ -287,6 +279,7 @@ cmLocalUnixMakefileGenerator2
// First generate the object rule files. Save a list of all object // First generate the object rule files. Save a list of all object
// files for this target. // files for this target.
std::vector<std::string> objects; std::vector<std::string> objects;
std::vector<std::string> provides_requires;
const std::vector<cmSourceFile*>& sources = target.GetSourceFiles(); const std::vector<cmSourceFile*>& sources = target.GetSourceFiles();
for(std::vector<cmSourceFile*>::const_iterator source = sources.begin(); for(std::vector<cmSourceFile*>::const_iterator source = sources.begin();
source != sources.end(); ++source) source != sources.end(); ++source)
@ -296,7 +289,8 @@ cmLocalUnixMakefileGenerator2
!m_GlobalGenerator->IgnoreFile((*source)->GetSourceExtension().c_str())) !m_GlobalGenerator->IgnoreFile((*source)->GetSourceExtension().c_str()))
{ {
// Generate this object file's rule file. // Generate this object file's rule file.
this->GenerateObjectRuleFile(target, *(*source), objects); this->GenerateObjectRuleFile(target, *(*source), objects,
provides_requires);
} }
} }
@ -351,19 +345,19 @@ cmLocalUnixMakefileGenerator2
{ {
case cmTarget::STATIC_LIBRARY: case cmTarget::STATIC_LIBRARY:
this->WriteStaticLibraryRule(ruleFileStream, ruleFileName.c_str(), this->WriteStaticLibraryRule(ruleFileStream, ruleFileName.c_str(),
target, objects); target, objects, provides_requires);
break; break;
case cmTarget::SHARED_LIBRARY: case cmTarget::SHARED_LIBRARY:
this->WriteSharedLibraryRule(ruleFileStream, ruleFileName.c_str(), this->WriteSharedLibraryRule(ruleFileStream, ruleFileName.c_str(),
target, objects); target, objects, provides_requires);
break; break;
case cmTarget::MODULE_LIBRARY: case cmTarget::MODULE_LIBRARY:
this->WriteModuleLibraryRule(ruleFileStream, ruleFileName.c_str(), this->WriteModuleLibraryRule(ruleFileStream, ruleFileName.c_str(),
target, objects); target, objects, provides_requires);
break; break;
case cmTarget::EXECUTABLE: case cmTarget::EXECUTABLE:
this->WriteExecutableRule(ruleFileStream, ruleFileName.c_str(), this->WriteExecutableRule(ruleFileStream, ruleFileName.c_str(),
target, objects); target, objects, provides_requires);
break; break;
default: default:
break; break;
@ -374,7 +368,8 @@ cmLocalUnixMakefileGenerator2
void void
cmLocalUnixMakefileGenerator2 cmLocalUnixMakefileGenerator2
::GenerateObjectRuleFile(const cmTarget& target, const cmSourceFile& source, ::GenerateObjectRuleFile(const cmTarget& target, const cmSourceFile& source,
std::vector<std::string>& objects) std::vector<std::string>& objects,
std::vector<std::string>& provides_requires)
{ {
// Identify the language of the source file. // Identify the language of the source file.
const char* lang = this->GetSourceFileLanguage(source); const char* lang = this->GetSourceFileLanguage(source);
@ -554,26 +549,35 @@ cmLocalUnixMakefileGenerator2
obj.c_str(), depends, commands); obj.c_str(), depends, commands);
} }
#ifdef CMLUMG_PROVIDES_REQUIRES // If the language needs provides-requires mode, create the
std::string objectRequires = obj; // corresponding targets.
std::string objectProvides = obj; if(strcmp(lang, "Fortran") == 0)
objectRequires += ".requires"; {
objectProvides += ".provides"; std::string objectRequires = obj;
{ std::string objectProvides = obj;
std::vector<std::string> no_commands; objectRequires += ".requires";
std::vector<std::string> depends; objectProvides += ".provides";
depends.push_back(obj); {
this->WriteMakeRule(ruleFileStream, 0, 0, // Add the provides target to build the object file.
objectProvides.c_str(), depends, no_commands); std::vector<std::string> no_commands;
} std::vector<std::string> depends;
{ depends.push_back(obj);
std::vector<std::string> no_depends; this->WriteMakeRule(ruleFileStream, 0, 0,
std::vector<std::string> commands; objectProvides.c_str(), depends, no_commands);
commands.push_back(this->GetRecursiveMakeCall(objectProvides.c_str())); }
this->WriteMakeRule(ruleFileStream, 0, 0, {
objectRequires.c_str(), no_depends, commands); // Add the requires target to recursively build the provides
} // target after needed information is up to date.
#endif std::vector<std::string> no_depends;
std::vector<std::string> commands;
commands.push_back(this->GetRecursiveMakeCall(objectProvides.c_str()));
this->WriteMakeRule(ruleFileStream, 0, 0,
objectRequires.c_str(), no_depends, commands);
}
// Add this to the set of provides-requires objects on the target.
provides_requires.push_back(objectRequires);
}
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@ -1403,7 +1407,8 @@ cmLocalUnixMakefileGenerator2
::WriteExecutableRule(std::ostream& ruleFileStream, ::WriteExecutableRule(std::ostream& ruleFileStream,
const char* ruleFileName, const char* ruleFileName,
const cmTarget& target, const cmTarget& target,
std::vector<std::string>& objects) std::vector<std::string>& objects,
const std::vector<std::string>& provides_requires)
{ {
// Write the dependency generation rule. // Write the dependency generation rule.
this->WriteTargetDependsRule(ruleFileStream, ruleFileName, target, objects); this->WriteTargetDependsRule(ruleFileStream, ruleFileName, target, objects);
@ -1538,42 +1543,8 @@ cmLocalUnixMakefileGenerator2
cleanFiles.push_back(objs); cleanFiles.push_back(objs);
this->WriteTargetCleanRule(ruleFileStream, target, cleanFiles); this->WriteTargetCleanRule(ruleFileStream, target, cleanFiles);
// Construct name of driving target listed in build.local rule. // Write the driving make target.
// TODO: See top of file description of Fortran support. this->WriteTargetRequiresRule(ruleFileStream, target, provides_requires);
std::string targetDriveName = target.GetName();
#ifdef CMLUMG_PROVIDES_REQUIRES
targetDriveName += ".requires";
std::string targetProvides = target.GetName();
targetProvides += ".provides";
{
std::vector<std::string> no_commands;
std::vector<std::string> depends;
depends.push_back(target.GetName());
this->WriteMakeRule(ruleFileStream, 0, 0,
targetProvides.c_str(), depends, no_commands);
}
{
// Build list of require-level dependencies.
std::vector<std::string> depends;
for(std::vector<std::string>::const_iterator obj = objects.begin();
obj != objects.end(); ++obj)
{
depends.push_back(*obj + ".requires");
}
std::vector<std::string> commands;
commands.push_back(this->GetRecursiveMakeCall(targetProvides.c_str()));
this->WriteMakeRule(ruleFileStream, 0, 0,
targetDriveName.c_str(), depends, commands);
}
#endif
// Add this to the list of build rules in this directory.
if(target.IsInAll())
{
m_BuildTargets.push_back(targetDriveName);
}
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@ -1582,7 +1553,8 @@ cmLocalUnixMakefileGenerator2
::WriteStaticLibraryRule(std::ostream& ruleFileStream, ::WriteStaticLibraryRule(std::ostream& ruleFileStream,
const char* ruleFileName, const char* ruleFileName,
const cmTarget& target, const cmTarget& target,
std::vector<std::string>& objects) std::vector<std::string>& objects,
const std::vector<std::string>& provides_requires)
{ {
const char* linkLanguage = const char* linkLanguage =
target.GetLinkerLanguage(this->GetGlobalGenerator()); target.GetLinkerLanguage(this->GetGlobalGenerator());
@ -1593,7 +1565,8 @@ cmLocalUnixMakefileGenerator2
std::string extraFlags; std::string extraFlags;
this->AppendFlags(extraFlags, target.GetProperty("STATIC_LIBRARY_FLAGS")); this->AppendFlags(extraFlags, target.GetProperty("STATIC_LIBRARY_FLAGS"));
this->WriteLibraryRule(ruleFileStream, ruleFileName, target, objects, this->WriteLibraryRule(ruleFileStream, ruleFileName, target, objects,
linkRuleVar.c_str(), extraFlags.c_str()); linkRuleVar.c_str(), extraFlags.c_str(),
provides_requires);
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@ -1602,7 +1575,8 @@ cmLocalUnixMakefileGenerator2
::WriteSharedLibraryRule(std::ostream& ruleFileStream, ::WriteSharedLibraryRule(std::ostream& ruleFileStream,
const char* ruleFileName, const char* ruleFileName,
const cmTarget& target, const cmTarget& target,
std::vector<std::string>& objects) std::vector<std::string>& objects,
const std::vector<std::string>& provides_requires)
{ {
const char* linkLanguage = const char* linkLanguage =
target.GetLinkerLanguage(this->GetGlobalGenerator()); target.GetLinkerLanguage(this->GetGlobalGenerator());
@ -1628,7 +1602,8 @@ cmLocalUnixMakefileGenerator2
} }
} }
this->WriteLibraryRule(ruleFileStream, ruleFileName, target, objects, this->WriteLibraryRule(ruleFileStream, ruleFileName, target, objects,
linkRuleVar.c_str(), extraFlags.c_str()); linkRuleVar.c_str(), extraFlags.c_str(),
provides_requires);
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@ -1637,7 +1612,8 @@ cmLocalUnixMakefileGenerator2
::WriteModuleLibraryRule(std::ostream& ruleFileStream, ::WriteModuleLibraryRule(std::ostream& ruleFileStream,
const char* ruleFileName, const char* ruleFileName,
const cmTarget& target, const cmTarget& target,
std::vector<std::string>& objects) std::vector<std::string>& objects,
const std::vector<std::string>& provides_requires)
{ {
const char* linkLanguage = const char* linkLanguage =
target.GetLinkerLanguage(this->GetGlobalGenerator()); target.GetLinkerLanguage(this->GetGlobalGenerator());
@ -1650,7 +1626,8 @@ cmLocalUnixMakefileGenerator2
this->AddConfigVariableFlags(extraFlags, "CMAKE_MODULE_LINKER_FLAGS"); this->AddConfigVariableFlags(extraFlags, "CMAKE_MODULE_LINKER_FLAGS");
// TODO: .def files should be supported here also. // TODO: .def files should be supported here also.
this->WriteLibraryRule(ruleFileStream, ruleFileName, target, objects, this->WriteLibraryRule(ruleFileStream, ruleFileName, target, objects,
linkRuleVar.c_str(), extraFlags.c_str()); linkRuleVar.c_str(), extraFlags.c_str(),
provides_requires);
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@ -1661,7 +1638,8 @@ cmLocalUnixMakefileGenerator2
const cmTarget& target, const cmTarget& target,
std::vector<std::string>& objects, std::vector<std::string>& objects,
const char* linkRuleVar, const char* linkRuleVar,
const char* extraFlags) const char* extraFlags,
const std::vector<std::string>& provides_requires)
{ {
// Write the dependency generation rule. // Write the dependency generation rule.
this->WriteTargetDependsRule(ruleFileStream, ruleFileName, target, objects); this->WriteTargetDependsRule(ruleFileStream, ruleFileName, target, objects);
@ -1817,11 +1795,8 @@ cmLocalUnixMakefileGenerator2
cleanFiles.push_back(objs); cleanFiles.push_back(objs);
this->WriteTargetCleanRule(ruleFileStream, target, cleanFiles); this->WriteTargetCleanRule(ruleFileStream, target, cleanFiles);
// Add this to the list of build rules in this directory. // Write the driving make target.
if(target.IsInAll()) this->WriteTargetRequiresRule(ruleFileStream, target, provides_requires);
{
m_BuildTargets.push_back(target.GetName());
}
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@ -1930,6 +1905,62 @@ cmLocalUnixMakefileGenerator2
} }
} }
//----------------------------------------------------------------------------
void
cmLocalUnixMakefileGenerator2
::WriteTargetRequiresRule(std::ostream& ruleFileStream, const cmTarget& target,
const std::vector<std::string>& provides_requires)
{
// Create the driving make target.
std::string targetRequires = target.GetName();
targetRequires += ".requires";
if(provides_requires.empty())
{
// No provides-requires mode objects in this target. Anything
// that requires the target can build it directly.
std::vector<std::string> no_commands;
std::vector<std::string> depends;
depends.push_back(target.GetName());
this->WriteMakeRule(ruleFileStream, 0, 0,
targetRequires.c_str(), depends, no_commands);
}
else
{
// There are provides-requires mode objects in this target. Use
// provides-requires mode to build the target itself.
std::string targetProvides = target.GetName();
targetProvides += ".provides";
{
std::vector<std::string> no_commands;
std::vector<std::string> depends;
depends.push_back(target.GetName());
this->WriteMakeRule(ruleFileStream, 0, 0,
targetProvides.c_str(), depends, no_commands);
}
{
// Build list of require-level dependencies.
std::vector<std::string> depends;
for(std::vector<std::string>::const_iterator
pr = provides_requires.begin();
pr != provides_requires.end(); ++pr)
{
depends.push_back(*pr);
}
std::vector<std::string> commands;
commands.push_back(this->GetRecursiveMakeCall(targetProvides.c_str()));
this->WriteMakeRule(ruleFileStream, 0, 0,
targetRequires.c_str(), depends, commands);
}
}
// Add this to the list of build rules in this directory.
if(target.IsInAll())
{
m_BuildTargets.push_back(targetRequires);
}
}
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
std::string std::string
cmLocalUnixMakefileGenerator2 cmLocalUnixMakefileGenerator2
@ -2627,6 +2658,7 @@ cmLocalUnixMakefileGenerator2
dep += ".depends"; dep += ".depends";
dep = this->ConvertToRelativeOutputPath(dep.c_str()); dep = this->ConvertToRelativeOutputPath(dep.c_str());
std::string tgt = jump->first; std::string tgt = jump->first;
tgt += ".requires";
tgt = this->ConvertToRelativeOutputPath(tgt.c_str()); tgt = this->ConvertToRelativeOutputPath(tgt.c_str());
// Build the jump-and-build command list. // Build the jump-and-build command list.

View File

@ -67,7 +67,8 @@ protected:
void GenerateTargetRuleFile(const cmTarget& target); void GenerateTargetRuleFile(const cmTarget& target);
void GenerateObjectRuleFile(const cmTarget& target, void GenerateObjectRuleFile(const cmTarget& target,
const cmSourceFile& source, const cmSourceFile& source,
std::vector<std::string>& objects); std::vector<std::string>& objects,
std::vector<std::string>& provides_requires);
void GenerateCustomRuleFile(const cmCustomCommand& cc); void GenerateCustomRuleFile(const cmCustomCommand& cc);
void GenerateUtilityRuleFile(const cmTarget& target); void GenerateUtilityRuleFile(const cmTarget& target);
bool GenerateDependsMakeFile(const std::string& lang, bool GenerateDependsMakeFile(const std::string& lang,
@ -107,25 +108,30 @@ protected:
void WriteExecutableRule(std::ostream& ruleFileStream, void WriteExecutableRule(std::ostream& ruleFileStream,
const char* ruleFileName, const char* ruleFileName,
const cmTarget& target, const cmTarget& target,
std::vector<std::string>& objects); std::vector<std::string>& objects,
const std::vector<std::string>& provides_requires);
void WriteStaticLibraryRule(std::ostream& ruleFileStream, void WriteStaticLibraryRule(std::ostream& ruleFileStream,
const char* ruleFileName, const char* ruleFileName,
const cmTarget& target, const cmTarget& target,
std::vector<std::string>& objects); std::vector<std::string>& objects,
const std::vector<std::string>& provides_requires);
void WriteSharedLibraryRule(std::ostream& ruleFileStream, void WriteSharedLibraryRule(std::ostream& ruleFileStream,
const char* ruleFileName, const char* ruleFileName,
const cmTarget& target, const cmTarget& target,
std::vector<std::string>& objects); std::vector<std::string>& objects,
const std::vector<std::string>& provides_requires);
void WriteModuleLibraryRule(std::ostream& ruleFileStream, void WriteModuleLibraryRule(std::ostream& ruleFileStream,
const char* ruleFileName, const char* ruleFileName,
const cmTarget& target, const cmTarget& target,
std::vector<std::string>& objects); std::vector<std::string>& objects,
const std::vector<std::string>& provides_requires);
void WriteLibraryRule(std::ostream& ruleFileStream, void WriteLibraryRule(std::ostream& ruleFileStream,
const char* ruleFileName, const char* ruleFileName,
const cmTarget& target, const cmTarget& target,
std::vector<std::string>& objects, std::vector<std::string>& objects,
const char* linkRuleVar, const char* linkRuleVar,
const char* extraLinkFlags); const char* extraLinkFlags,
const std::vector<std::string>& provides_requires);
void WriteObjectsVariable(std::ostream& ruleFileStream, void WriteObjectsVariable(std::ostream& ruleFileStream,
const cmTarget& target, const cmTarget& target,
const std::vector<std::string>& objects, const std::vector<std::string>& objects,
@ -137,6 +143,9 @@ protected:
void WriteTargetCleanRule(std::ostream& ruleFileStream, void WriteTargetCleanRule(std::ostream& ruleFileStream,
const cmTarget& target, const cmTarget& target,
const std::vector<std::string>& files); const std::vector<std::string>& files);
void WriteTargetRequiresRule(std::ostream& ruleFileStream,
const cmTarget& target,
const std::vector<std::string>& provides_requires);
std::string GetTargetDirectory(const cmTarget& target); std::string GetTargetDirectory(const cmTarget& target);
std::string GetSubdirTargetName(const char* pass, const char* subdir); std::string GetSubdirTargetName(const char* pass, const char* subdir);
std::string GetObjectFileName(const cmTarget& target, std::string GetObjectFileName(const cmTarget& target,