ENH: Proper dependencies between shared libraries now exist in the generated makefiles. If a shared library links to another, the other will be built before the link is attempted.

This commit is contained in:
Brad King 2001-08-29 10:46:59 -04:00
parent 94337f8015
commit 82996a636e
2 changed files with 120 additions and 70 deletions

View File

@ -229,7 +229,7 @@ void cmUnixMakefileGenerator::OutputMakefile(const char* file)
this->OutputMakeVariables(fout); this->OutputMakeVariables(fout);
this->OutputMakeFlags(fout); this->OutputMakeFlags(fout);
this->OutputTargetRules(fout); this->OutputTargetRules(fout);
this->OutputDependencies(fout); this->OutputDependLibs(fout);
this->OutputTargets(fout); this->OutputTargets(fout);
this->OutputSubDirectoryRules(fout); this->OutputSubDirectoryRules(fout);
std::string dependName = m_Makefile->GetStartOutputDirectory(); std::string dependName = m_Makefile->GetStartOutputDirectory();
@ -339,7 +339,7 @@ void cmUnixMakefileGenerator::OutputTargetRules(std::ostream& fout)
fout << "${" << l->first << "_SRC_OBJS} "; fout << "${" << l->first << "_SRC_OBJS} ";
} }
} }
fout << "\n"; fout << "\n\n";
} }
@ -534,7 +534,7 @@ void cmUnixMakefileGenerator::OutputTargets(std::ostream& fout)
fout << "# rules for a shared library\n"; fout << "# rules for a shared library\n";
fout << "#\n"; fout << "#\n";
fout << m_LibraryOutputPath << "lib" << l->first << "$(SHLIB_SUFFIX): ${" << fout << m_LibraryOutputPath << "lib" << l->first << "$(SHLIB_SUFFIX): ${" <<
l->first << "_SRC_OBJS} \n"; l->first << "_SRC_OBJS} ${" << l->first << "_DEPEND_LIBS} \n";
fout << "\trm -f lib" << l->first << "$(SHLIB_SUFFIX)\n"; fout << "\trm -f lib" << l->first << "$(SHLIB_SUFFIX)\n";
fout << "\t$(CMAKE_CXX_COMPILER) ${CMAKE_SHLIB_LINK_FLAGS} " fout << "\t$(CMAKE_CXX_COMPILER) ${CMAKE_SHLIB_LINK_FLAGS} "
"${CMAKE_SHLIB_BUILD_FLAGS} ${CMAKE_CXXFLAGS} -o \\\n"; "${CMAKE_SHLIB_BUILD_FLAGS} ${CMAKE_CXXFLAGS} -o \\\n";
@ -550,7 +550,7 @@ void cmUnixMakefileGenerator::OutputTargets(std::ostream& fout)
fout << "# rules for a shared module library\n"; fout << "# rules for a shared module library\n";
fout << "#\n"; fout << "#\n";
fout << m_LibraryOutputPath << "lib" << l->first << "$(MODULE_SUFFIX): ${" << fout << m_LibraryOutputPath << "lib" << l->first << "$(MODULE_SUFFIX): ${" <<
l->first << "_SRC_OBJS} \n"; l->first << "_SRC_OBJS} ${" << l->first << "_DEPEND_LIBS} \n";
fout << "\trm -f lib" << l->first << "$(MODULE_SUFFIX)\n"; fout << "\trm -f lib" << l->first << "$(MODULE_SUFFIX)\n";
fout << "\t$(CMAKE_CXX_COMPILER) ${CMAKE_MODULE_LINK_FLAGS} " fout << "\t$(CMAKE_CXX_COMPILER) ${CMAKE_MODULE_LINK_FLAGS} "
"${CMAKE_MODULE_BUILD_FLAGS} ${CMAKE_CXXFLAGS} -o \\\n"; "${CMAKE_MODULE_BUILD_FLAGS} ${CMAKE_CXXFLAGS} -o \\\n";
@ -564,7 +564,7 @@ void cmUnixMakefileGenerator::OutputTargets(std::ostream& fout)
|| (l->second.GetType() == cmTarget::WIN32_EXECUTABLE)) || (l->second.GetType() == cmTarget::WIN32_EXECUTABLE))
{ {
fout << m_ExecutableOutputPath << l->first << ": ${" << fout << m_ExecutableOutputPath << l->first << ": ${" <<
l->first << "_SRC_OBJS} ${CMAKE_DEPEND_LIBS}\n"; l->first << "_SRC_OBJS} ${" << l->first << "_DEPEND_LIBS}\n";
fout << "\t${CMAKE_CXX_COMPILER} ${CMAKE_SHLIB_LINK_FLAGS} ${CMAKE_CXXFLAGS} " fout << "\t${CMAKE_CXX_COMPILER} ${CMAKE_SHLIB_LINK_FLAGS} ${CMAKE_CXXFLAGS} "
<< "${" << l->first << "_SRC_OBJS} "; << "${" << l->first << "_SRC_OBJS} ";
this->OutputLinkLibraries(fout, NULL,l->second); this->OutputLinkLibraries(fout, NULL,l->second);
@ -574,93 +574,90 @@ void cmUnixMakefileGenerator::OutputTargets(std::ostream& fout)
} }
// output the list of libraries that the executables // For each target that is an executable or shared library, generate
// in this makefile will depend on. // the "<name>_DEPEND_LIBS" variable listing its library dependencies.
void cmUnixMakefileGenerator::OutputDependencies(std::ostream& fout) void cmUnixMakefileGenerator::OutputDependLibs(std::ostream& fout)
{ {
// Each dependency should only be emitted once. // Build a set of libraries that will be linked into any target in
std::set<std::string> emitted; // this directory.
std::set<std::string> used;
fout << "CMAKE_DEPEND_LIBS = ";
cmTarget::LinkLibraries& libs = m_Makefile->GetLinkLibraries(); // for each target
cmTarget::LinkLibraries::const_iterator lib2; const cmTargets &tgts = m_Makefile->GetTargets();
// Search the list of libraries that will be linked into for(cmTargets::const_iterator l = tgts.begin();
// the executable l != tgts.end(); l++)
emitted.clear();
for(lib2 = libs.begin(); lib2 != libs.end(); ++lib2)
{ {
if( ! emitted.insert(lib2->first).second ) continue; // Each dependency should only be emitted once per target.
std::set<std::string> emitted;
const char* cacheValue if ((l->second.GetType() == cmTarget::SHARED_LIBRARY)
= m_Makefile->GetDefinition(lib2->first.c_str()); || (l->second.GetType() == cmTarget::MODULE_LIBRARY)
if(cacheValue ) || (l->second.GetType() == cmTarget::EXECUTABLE)
|| (l->second.GetType() == cmTarget::WIN32_EXECUTABLE))
{ {
// if there is a cache value then this is a library that cmake fout << l->first << "_DEPEND_LIBS = ";
// knows how to build, so we can depend on it
std::string libpath; // A library should not depend on itself!
if (strcmp(m_Makefile->GetCurrentOutputDirectory(), cacheValue) != 0) emitted.insert(l->first);
// First look at all makefile level link libraries.
const cmTarget::LinkLibraries& libs = m_Makefile->GetLinkLibraries();
for(cmTarget::LinkLibraries::const_iterator lib = libs.begin();
lib != libs.end(); ++lib)
{ {
// if the library is not in the current directory, then get the full // Record that this library was used.
// path to it used.insert(lib->first);
libpath = cacheValue;
if(m_LibraryOutputPath.size()) // Don't emit the same library twice for this target.
if(emitted.insert(lib->first).second)
{ {
libpath = m_LibraryOutputPath; // Output this dependency.
libpath += "lib"; this->OutputLibDepend(fout, lib->first.c_str());
}
else
{
libpath += "/lib";
} }
} }
else
// Now, look at all link libraries specific to this target.
const cmTarget::LinkLibraries& tlibs = l->second.GetLinkLibraries();
for(cmTarget::LinkLibraries::const_iterator lib = tlibs.begin();
lib != tlibs.end(); ++lib)
{ {
// library is in current Makefile so use lib as a prefix // Record that this library was used.
libpath = m_LibraryOutputPath; used.insert(lib->first);
libpath += "lib";
// Don't emit the same library twice for this target.
if(emitted.insert(lib->first).second)
{
// Output this dependency.
this->OutputLibDepend(fout, lib->first.c_str());
}
} }
// add the library name
libpath += lib2->first; fout << "\n";
// add the correct extension
std::string ltname = lib2->first+"_LIBRARY_TYPE";
const char* libType
= m_Makefile->GetDefinition(ltname.c_str());
if(libType && std::string(libType) == "SHARED")
{
libpath += m_Makefile->GetDefinition("CMAKE_SHLIB_SUFFIX");
}
else if (libType && std::string(libType) == "MODULE")
{
libpath += m_Makefile->GetDefinition("CMAKE_MODULE_SUFFIX");
}
else
{
libpath += ".a";
}
fout << libpath << " ";
} }
} }
fout << "\n\n";
emitted.clear(); fout << "\n";
for(lib2 = libs.begin(); lib2 != libs.end(); ++lib2)
// Loop over the libraries used and make sure there is a rule to
// build them in this makefile. If the library is in another
// directory, add a rule to jump to that directory and make sure it
// exists.
for(std::set<std::string>::const_iterator lib = used.begin();
lib != used.end(); ++lib)
{ {
// loop over the list of directories that the libraries might // loop over the list of directories that the libraries might
// be in, looking for an ADD_LIBRARY(lib...) line. This would // be in, looking for an ADD_LIBRARY(lib...) line. This would
// be stored in the cache // be stored in the cache
if( ! emitted.insert(lib2->first).second ) continue; const char* cacheValue = m_Makefile->GetDefinition(lib->c_str());
const char* cacheValue
= m_Makefile->GetDefinition(lib2->first.c_str());
// if cache and not the current directory add a rule, to // if cache and not the current directory add a rule, to
// jump into the directory and build for the first time // jump into the directory and build for the first time
if(cacheValue if(cacheValue
&& (strcmp(m_Makefile->GetCurrentOutputDirectory(), cacheValue) != 0)) && (strcmp(m_Makefile->GetCurrentOutputDirectory(), cacheValue) != 0))
{ {
std::string library = "lib"; std::string library = "lib";
library += lib2->first; library += *lib;
std::string libpath = cacheValue; std::string libpath = cacheValue;
// add the correct extension // add the correct extension
std::string ltname = lib2->first+"_LIBRARY_TYPE"; std::string ltname = *lib+"_LIBRARY_TYPE";
const char* libType const char* libType
= m_Makefile->GetDefinition(ltname.c_str()); = m_Makefile->GetDefinition(ltname.c_str());
if(libType && std::string(libType) == "SHARED") if(libType && std::string(libType) == "SHARED")
@ -692,6 +689,58 @@ void cmUnixMakefileGenerator::OutputDependencies(std::ostream& fout)
} }
} }
void cmUnixMakefileGenerator::OutputLibDepend(std::ostream& fout,
const char* name)
{
const char* cacheValue = m_Makefile->GetDefinition(name);
if(cacheValue )
{
// if there is a cache value, then this is a library that cmake
// knows how to build, so we can depend on it
std::string libpath;
if (strcmp(m_Makefile->GetCurrentOutputDirectory(), cacheValue) != 0)
{
// if the library is not in the current directory, then get the full
// path to it
libpath = cacheValue;
if(m_LibraryOutputPath.size())
{
libpath = m_LibraryOutputPath;
libpath += "lib";
}
else
{
libpath += "/lib";
}
}
else
{
// library is in current Makefile so use lib as a prefix
libpath = m_LibraryOutputPath;
libpath += "lib";
}
// add the library name
libpath += name;
// add the correct extension
std::string ltname = name;
ltname += "_LIBRARY_TYPE";
const char* libType = m_Makefile->GetDefinition(ltname.c_str());
if(libType && std::string(libType) == "SHARED")
{
libpath += m_Makefile->GetDefinition("CMAKE_SHLIB_SUFFIX");
}
else if (libType && std::string(libType) == "MODULE")
{
libpath += m_Makefile->GetDefinition("CMAKE_MODULE_SUFFIX");
}
else
{
libpath += ".a";
}
fout << libpath << " ";
}
}
// output make include flags // output make include flags
void cmUnixMakefileGenerator::OutputMakeFlags(std::ostream& fout) void cmUnixMakefileGenerator::OutputMakeFlags(std::ostream& fout)

View File

@ -101,7 +101,8 @@ private:
void OutputTargets(std::ostream&); void OutputTargets(std::ostream&);
void OutputSubDirectoryRules(std::ostream&); void OutputSubDirectoryRules(std::ostream&);
void OutputDependInformation(std::ostream&); void OutputDependInformation(std::ostream&);
void OutputDependencies(std::ostream&); void OutputDependLibs(std::ostream&);
void OutputLibDepend(std::ostream&, const char*);
void OutputCustomRules(std::ostream&); void OutputCustomRules(std::ostream&);
void OutputMakeVariables(std::ostream&); void OutputMakeVariables(std::ostream&);
void OutputMakeRules(std::ostream&); void OutputMakeRules(std::ostream&);