ENH: Added executable dependencies on libraries including jump-and-build support.

This commit is contained in:
Brad King 2004-10-27 10:45:18 -04:00
parent 235bf2547c
commit 8e0985f9f1
2 changed files with 185 additions and 11 deletions

View File

@ -91,17 +91,11 @@ void cmLocalUnixMakefileGenerator2::GenerateMakefile()
runRule += " --check-rerun "; runRule += " --check-rerun ";
runRule += this->ConvertToRelativeOutputPath(cmakefileName.c_str()); runRule += this->ConvertToRelativeOutputPath(cmakefileName.c_str());
// Most unix makes will pass the command line flags to make down to // Construct recursive calls for the "all" rules.
// sub-invoked makes via an environment variable. However, some std::string depRule;
// makes do not support that, so you have to pass the flags std::string allRule;
// explicitly. this->AppendRecursiveMake(depRule, "Makefile2", "all.depends");
const char* depRule = "$(MAKE) -f Makefile2 $(MAKESILENT) all.depends"; this->AppendRecursiveMake(allRule, "Makefile2", "all");
const char* allRule = "$(MAKE) -f Makefile2 $(MAKESILENT) all";
if(m_PassMakeflags)
{
depRule = "$(MAKE) -f Makefile2 $(MAKESILENT) -$(MAKEFLAGS) all.depends";
allRule = "$(MAKE) -f Makefile2 $(MAKESILENT) -$(MAKEFLAGS) all";
}
// Write the main entry point target. This must be the VERY first // Write the main entry point target. This must be the VERY first
// target so that make with no arguments will run it. // target so that make with no arguments will run it.
@ -179,6 +173,9 @@ void cmLocalUnixMakefileGenerator2::GenerateMakefile()
<< this->ConvertToOutputForExisting(ruleFileName.c_str()).c_str() << this->ConvertToOutputForExisting(ruleFileName.c_str()).c_str()
<< "\n"; << "\n";
} }
// Write jump-and-build rules that were recorded in the map.
this->WriteJumpAndBuildRules(makefileStream);
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@ -586,6 +583,21 @@ cmLocalUnixMakefileGenerator2
{ {
depends.push_back(*obj); depends.push_back(*obj);
} }
// Add dependencies on libraries that will be linked.
std::set<cmStdString> emitted;
emitted.insert(target.GetName());
const cmTarget::LinkLibraries& tlibs = target.GetLinkLibraries();
for(cmTarget::LinkLibraries::const_iterator lib = tlibs.begin();
lib != tlibs.end(); ++lib)
{
// Don't emit the same library twice for this target.
if(emitted.insert(lib->first).second)
{
// Add this dependency.
this->AppendLibDepend(depends, lib->first.c_str());
}
}
depends.push_back(ruleFileName); depends.push_back(ruleFileName);
// Construct the full path to the executable that will be generated. // Construct the full path to the executable that will be generated.
@ -1087,6 +1099,157 @@ void cmLocalUnixMakefileGenerator2::AppendFlags(std::string& flags,
} }
} }
//----------------------------------------------------------------------------
void
cmLocalUnixMakefileGenerator2
::AppendLibDepend(std::vector<std::string>& depends, const char* name)
{
// There are a few cases for the name of the target:
// - CMake target in this directory: depend on it.
// - CMake target in another directory: depend and add jump-and-build.
// - Full path to an outside file: depend on it.
// - Other format (like -lm): do nothing.
// If it is a CMake target there will be a definition for it.
std::string dirVar = name;
dirVar += "_CMAKE_PATH";
const char* dir = m_Makefile->GetDefinition(dirVar.c_str());
if(dir && *dir)
{
// This is a CMake target somewhere in this project.
bool jumpAndBuild = false;
// Get the path to the library.
std::string libPath;
if(this->SamePath(m_Makefile->GetCurrentOutputDirectory(), dir))
{
// The target is in the current directory so this makefile will
// know about it already.
libPath = m_LibraryOutputPath;
}
else
{
// The target is in another directory. Get the path to it.
if(m_LibraryOutputPath.size())
{
libPath = m_LibraryOutputPath;
}
else
{
libPath = dir;
libPath += "/";
}
// We need to add a jump-and-build rule for this library.
jumpAndBuild = true;
}
// Add the name of the library's file. This depends on the type
// of the library.
std::string typeVar = name;
typeVar += "_LIBRARY_TYPE";
std::string libType = m_Makefile->GetSafeDefinition(typeVar.c_str());
std::string prefix;
std::string suffix;
if(libType == "SHARED")
{
prefix = m_Makefile->GetSafeDefinition("CMAKE_SHARED_LIBRARY_PREFIX");
suffix = m_Makefile->GetSafeDefinition("CMAKE_SHARED_LIBRARY_SUFFIX");
}
else if(libType == "MODULE")
{
prefix = m_Makefile->GetSafeDefinition("CMAKE_SHARED_MODULE_PREFIX");
suffix = m_Makefile->GetSafeDefinition("CMAKE_SHARED_MODULE_SUFFIX");
}
else if(libType == "STATIC")
{
prefix = m_Makefile->GetSafeDefinition("CMAKE_STATIC_LIBRARY_PREFIX");
suffix = m_Makefile->GetSafeDefinition("CMAKE_STATIC_LIBRARY_SUFFIX");
}
libPath += prefix;
libPath += name;
libPath += suffix;
if(jumpAndBuild)
{
// We need to add a jump-and-build rule for this library.
cmLocalUnixMakefileGenerator2::RemoteTarget rt;
rt.m_BuildDirectory = dir;
rt.m_FilePath =libPath;
m_JumpAndBuild[name] = rt;
}
// Add a dependency on the library.
depends.push_back(this->ConvertToRelativeOutputPath(libPath.c_str()));
}
else
{
// This is not a CMake target. If it exists and is a full path we
// can depend on it.
if(cmSystemTools::FileExists(name) && cmSystemTools::FileIsFullPath(name))
{
depends.push_back(this->ConvertToRelativeOutputPath(name));
}
}
}
//----------------------------------------------------------------------------
void
cmLocalUnixMakefileGenerator2
::AppendRecursiveMake(std::string& cmd, const char* file, const char* tgt)
{
// Call make on the given file.
cmd += "$(MAKE) -f ";
cmd += file;
// Pass down verbosity level.
cmd += " $(MAKESILENT) ";
// Most unix makes will pass the command line flags to make down to
// sub-invoked makes via an environment variable. However, some
// makes do not support that, so you have to pass the flags
// explicitly.
if(m_PassMakeflags)
{
cmd += "-$(MAKEFLAGS) ";
}
// Add the target.
cmd += tgt;
}
//----------------------------------------------------------------------------
void
cmLocalUnixMakefileGenerator2
::WriteJumpAndBuildRules(std::ostream& makefileStream)
{
std::vector<std::string> depends;
std::vector<std::string> commands;
commands.push_back("");
for(std::map<cmStdString, RemoteTarget>::iterator
jump = m_JumpAndBuild.begin(); jump != m_JumpAndBuild.end(); ++jump)
{
const cmLocalUnixMakefileGenerator2::RemoteTarget& rt = jump->second;
std::string& cmd = commands[0];
if(m_WindowsShell)
{
// TODO: implement windows version.
cmd = "";
}
else
{
cmd = "cd ";
cmd += this->ConvertToOutputForExisting(rt.m_BuildDirectory.c_str());
cmd += "; ";
std::string tgt = jump->first;
tgt += ".requires";
this->AppendRecursiveMake(cmd, "Makefile2", tgt.c_str());
}
this->OutputMakeRule(makefileStream, "jump rule for",
rt.m_FilePath.c_str(), depends, commands);
}
}
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
bool bool
cmLocalUnixMakefileGenerator2 cmLocalUnixMakefileGenerator2

View File

@ -90,10 +90,21 @@ protected:
void AddSharedFlags(std::string& flags, const char* lang, bool shared); void AddSharedFlags(std::string& flags, const char* lang, bool shared);
void AddConfigVariableFlags(std::string& flags, const char* var); void AddConfigVariableFlags(std::string& flags, const char* var);
void AppendFlags(std::string& flags, const char* newFlags); void AppendFlags(std::string& flags, const char* newFlags);
void AppendLibDepend(std::vector<std::string>& depends, const char* name);
void AppendRecursiveMake(std::string& cmd, const char* file, const char* tgt);
void WriteJumpAndBuildRules(std::ostream& makefileStream);
static bool ScanDependenciesC(const char* objFile, const char* srcFile, static bool ScanDependenciesC(const char* objFile, const char* srcFile,
std::vector<std::string> const& includes); std::vector<std::string> const& includes);
private: private:
// Map from target name to build directory containing it for
// jump-and-build targets.
struct RemoteTarget
{
std::string m_BuildDirectory;
std::string m_FilePath;
};
std::map<cmStdString, RemoteTarget> m_JumpAndBuild;
}; };
#endif #endif