BUG: Correct some of the dependency analysis code.
- Make sure the original link line is untouched - Avoid duplicating the link line when supporting version < 1.4 - Make sure the cyclic dependencies and such are output correctly in complicated cases. - Avoid outputing dependencies that are already satisfied on the original link line when possible.
This commit is contained in:
parent
6b08b83d89
commit
0e6b39e52f
|
@ -177,6 +177,34 @@ IF(BUILD_TESTING)
|
||||||
${CMake_BINARY_DIR}/Tests/Dependency/WOLibOut/Exec
|
${CMake_BINARY_DIR}/Tests/Dependency/WOLibOut/Exec
|
||||||
Dependency)
|
Dependency)
|
||||||
|
|
||||||
|
ADD_TEST(dependency2 ${CMake_BINARY_DIR}/Source/cmaketest
|
||||||
|
${CMake_SOURCE_DIR}/Tests/Dependency
|
||||||
|
${CMake_BINARY_DIR}/Tests/Dependency/WithLibOut
|
||||||
|
exec2
|
||||||
|
${CMake_BINARY_DIR}/Tests/Dependency/WithLibOut/Exec2
|
||||||
|
Dependency CMAKE_ARGS -DLIBRARY_OUTPUT_PATH:PATH=${CMake_BINARY_DIR}/Tests/Dependency/WithLibOut/Lib)
|
||||||
|
|
||||||
|
ADD_TEST(dependency3 ${CMake_BINARY_DIR}/Source/cmaketest
|
||||||
|
${CMake_SOURCE_DIR}/Tests/Dependency
|
||||||
|
${CMake_BINARY_DIR}/Tests/Dependency/WithLibOut
|
||||||
|
exec3
|
||||||
|
${CMake_BINARY_DIR}/Tests/Dependency/WithLibOut/Exec3
|
||||||
|
Dependency CMAKE_ARGS -DLIBRARY_OUTPUT_PATH:PATH=${CMake_BINARY_DIR}/Tests/Dependency/WithLibOut/Lib)
|
||||||
|
|
||||||
|
ADD_TEST(dependency4 ${CMake_BINARY_DIR}/Source/cmaketest
|
||||||
|
${CMake_SOURCE_DIR}/Tests/Dependency
|
||||||
|
${CMake_BINARY_DIR}/Tests/Dependency/WithLibOut
|
||||||
|
exec4
|
||||||
|
${CMake_BINARY_DIR}/Tests/Dependency/WithLibOut/Exec4
|
||||||
|
Dependency CMAKE_ARGS -DLIBRARY_OUTPUT_PATH:PATH=${CMake_BINARY_DIR}/Tests/Dependency/WithLibOut/Lib)
|
||||||
|
|
||||||
|
ADD_TEST(linkline ${CMake_BINARY_DIR}/Source/cmaketest
|
||||||
|
${CMake_SOURCE_DIR}/Tests/LinkLine
|
||||||
|
${CMake_BINARY_DIR}/Tests/LinkLine
|
||||||
|
Exec
|
||||||
|
${CMake_BINARY_DIR}/Tests/LinkLine
|
||||||
|
LinkLine)
|
||||||
|
|
||||||
ENDIF (DART_ROOT)
|
ENDIF (DART_ROOT)
|
||||||
ENDIF(BUILD_TESTING)
|
ENDIF(BUILD_TESTING)
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <set>
|
#include <set>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
|
||||||
void cmTarget::GenerateSourceFilesFromSourceLists( cmMakefile &mf)
|
void cmTarget::GenerateSourceFilesFromSourceLists( cmMakefile &mf)
|
||||||
|
@ -73,15 +73,17 @@ void cmTarget::MergeLinkLibraries( cmMakefile& mf,
|
||||||
const char *selfname,
|
const char *selfname,
|
||||||
const LinkLibraries& libs )
|
const LinkLibraries& libs )
|
||||||
{
|
{
|
||||||
for( LinkLibraries::const_iterator i = libs.begin();
|
// Only add on libraries we haven't added on before.
|
||||||
i != libs.end(); ++i )
|
// Assumption: the global link libraries could only grow, never shrink
|
||||||
|
assert( libs.size() >= m_PrevLinkedLibraries.size() );
|
||||||
|
LinkLibraries::const_iterator i = libs.begin();
|
||||||
|
i += m_PrevLinkedLibraries.size();
|
||||||
|
for( ; i != libs.end(); ++i )
|
||||||
{
|
{
|
||||||
if(m_PrevLinkedLibraries.insert(i->first).second)
|
// We call this so that the dependencies get written to the cache
|
||||||
{
|
this->AddLinkLibrary( mf, selfname, i->first.c_str(), i->second );
|
||||||
// We call this so that the dependencies get written to the cache
|
|
||||||
this->AddLinkLibrary( mf, selfname, i->first.c_str(), i->second );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
m_PrevLinkedLibraries = libs;
|
||||||
}
|
}
|
||||||
|
|
||||||
void cmTarget::AddLinkDirectory(const char* d)
|
void cmTarget::AddLinkDirectory(const char* d)
|
||||||
|
@ -231,8 +233,8 @@ cmTarget::AnalyzeLibDependencies( const cmMakefile& mf )
|
||||||
// 3. Create the new link line by simply emitting any dependencies that are
|
// 3. Create the new link line by simply emitting any dependencies that are
|
||||||
// missing. Start from the back and keep adding.
|
// missing. Start from the back and keep adding.
|
||||||
|
|
||||||
LinkLibraries newLinkLibraries = m_LinkLibraries;
|
|
||||||
std::set<cmStdString> done, visited;
|
std::set<cmStdString> done, visited;
|
||||||
|
std::vector<std::string> newLinkLibraries;
|
||||||
for(LinkLibraries::reverse_iterator lib = m_LinkLibraries.rbegin();
|
for(LinkLibraries::reverse_iterator lib = m_LinkLibraries.rbegin();
|
||||||
lib != m_LinkLibraries.rend(); ++lib)
|
lib != m_LinkLibraries.rend(); ++lib)
|
||||||
{
|
{
|
||||||
|
@ -240,56 +242,57 @@ cmTarget::AnalyzeLibDependencies( const cmMakefile& mf )
|
||||||
// if a variable expands to nothing.
|
// if a variable expands to nothing.
|
||||||
if (lib->first.size() == 0) continue;
|
if (lib->first.size() == 0) continue;
|
||||||
|
|
||||||
std::vector<std::string> link_line;
|
// Emit all the dependencies that are not already satisfied on the
|
||||||
Emit( lib->first, dep_map, done, visited, link_line );
|
// original link line.
|
||||||
if( link_line.size() == 0 )
|
if( dep_map.find(lib->first) != dep_map.end() ) // does it have dependencies?
|
||||||
{
|
{
|
||||||
// everything for this library is already on the link line, but since
|
const std::set<cmStdString>& dep_on = dep_map.find( lib->first )->second;
|
||||||
// we are not going to touch the user's link line, we will output the
|
std::set<cmStdString>::iterator i;
|
||||||
// library anyway.
|
for( i = dep_on.begin(); i != dep_on.end(); ++i )
|
||||||
newLinkLibraries.push_back( *lib );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
for( std::vector<std::string>::reverse_iterator k = link_line.rbegin();
|
|
||||||
k != link_line.rend(); ++k )
|
|
||||||
{
|
{
|
||||||
if( satisfied[lib->first].insert( *k ).second )
|
if( satisfied[lib->first].end() == satisfied[lib->first].find( *i ) )
|
||||||
{
|
{
|
||||||
if( addLibDirs )
|
Emit( *i, dep_map, done, visited, newLinkLibraries );
|
||||||
{
|
|
||||||
const char* libpath = mf.GetDefinition( k->c_str() );
|
|
||||||
if( libpath )
|
|
||||||
{
|
|
||||||
// Don't add a link directory that is already present.
|
|
||||||
if(std::find(m_LinkDirectories.begin(),
|
|
||||||
m_LinkDirectories.end(), libpath) == m_LinkDirectories.end())
|
|
||||||
{
|
|
||||||
m_LinkDirectories.push_back(libpath);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
std::string linkType = *k;
|
|
||||||
linkType += "_LINK_TYPE";
|
|
||||||
cmTarget::LinkLibraryType llt = cmTarget::GENERAL;
|
|
||||||
const char* linkTypeString = mf.GetDefinition( linkType.c_str() );
|
|
||||||
if(linkTypeString)
|
|
||||||
{
|
|
||||||
if(strcmp(linkTypeString, "debug") == 0)
|
|
||||||
{
|
|
||||||
llt = cmTarget::DEBUG;
|
|
||||||
}
|
|
||||||
if(strcmp(linkTypeString, "optimized") == 0)
|
|
||||||
{
|
|
||||||
llt = cmTarget::OPTIMIZED;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
newLinkLibraries.push_back( std::make_pair(*k,llt) );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
m_LinkLibraries = newLinkLibraries;
|
|
||||||
|
// 4. Add the new libraries to the link line.
|
||||||
|
|
||||||
|
for( std::vector<std::string>::reverse_iterator k = newLinkLibraries.rbegin();
|
||||||
|
k != newLinkLibraries.rend(); ++k )
|
||||||
|
{
|
||||||
|
if( addLibDirs )
|
||||||
|
{
|
||||||
|
const char* libpath = mf.GetDefinition( k->c_str() );
|
||||||
|
if( libpath )
|
||||||
|
{
|
||||||
|
// Don't add a link directory that is already present.
|
||||||
|
if(std::find(m_LinkDirectories.begin(),
|
||||||
|
m_LinkDirectories.end(), libpath) == m_LinkDirectories.end())
|
||||||
|
{
|
||||||
|
m_LinkDirectories.push_back(libpath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
std::string linkType = *k;
|
||||||
|
linkType += "_LINK_TYPE";
|
||||||
|
cmTarget::LinkLibraryType llt = cmTarget::GENERAL;
|
||||||
|
const char* linkTypeString = mf.GetDefinition( linkType.c_str() );
|
||||||
|
if(linkTypeString)
|
||||||
|
{
|
||||||
|
if(strcmp(linkTypeString, "debug") == 0)
|
||||||
|
{
|
||||||
|
llt = cmTarget::DEBUG;
|
||||||
|
}
|
||||||
|
if(strcmp(linkTypeString, "optimized") == 0)
|
||||||
|
{
|
||||||
|
llt = cmTarget::OPTIMIZED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m_LinkLibraries.push_back( std::make_pair(*k,llt) );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -169,7 +169,7 @@ private:
|
||||||
TargetType m_TargetType;
|
TargetType m_TargetType;
|
||||||
std::vector<cmSourceFile*> m_SourceFiles;
|
std::vector<cmSourceFile*> m_SourceFiles;
|
||||||
LinkLibraries m_LinkLibraries;
|
LinkLibraries m_LinkLibraries;
|
||||||
std::set<cmStdString> m_PrevLinkedLibraries;
|
LinkLibraries m_PrevLinkedLibraries;
|
||||||
std::vector<std::string> m_LinkDirectories;
|
std::vector<std::string> m_LinkDirectories;
|
||||||
bool m_InAll;
|
bool m_InAll;
|
||||||
std::string m_InstallPath;
|
std::string m_InstallPath;
|
||||||
|
|
|
@ -3,23 +3,6 @@ PROJECT( Dependency )
|
||||||
# There is one executable that depends on eight libraries. The
|
# There is one executable that depends on eight libraries. The
|
||||||
# system has the following dependency graph:
|
# system has the following dependency graph:
|
||||||
#
|
#
|
||||||
# +----------- NoDepC <---- EXECUTABLE ---+
|
|
||||||
# | | | |
|
|
||||||
# V | | |
|
|
||||||
# | | |
|
|
||||||
# NoDepA <----- NoDepB <-------+ | |
|
|
||||||
# | |
|
|
||||||
# ^ | V
|
|
||||||
# | |
|
|
||||||
# One <------ Four -----> Two <----- Five <---|----- SixB
|
|
||||||
# | | |
|
|
||||||
# ^ ^ ^ | ^ ^ | |
|
|
||||||
# | | +-----+ | \ | | |
|
|
||||||
# | | | | \ | | |
|
|
||||||
# +--------- Three <------+ --- SixA <----+ |
|
|
||||||
# | |
|
|
||||||
# | |
|
|
||||||
# +---------------------------------+
|
|
||||||
# NoDepA:
|
# NoDepA:
|
||||||
# NoDepB: NoDepA
|
# NoDepB: NoDepA
|
||||||
# NoDepC: NoDepA
|
# NoDepC: NoDepA
|
||||||
|
@ -30,14 +13,20 @@ PROJECT( Dependency )
|
||||||
# Five: Two
|
# Five: Two
|
||||||
# SixA: Two Five
|
# SixA: Two Five
|
||||||
# SixB: Four Five
|
# SixB: Four Five
|
||||||
# Exec: NoDepB NoDepC SixA SixB
|
# Seven: Two
|
||||||
|
# Eight: Seven
|
||||||
#
|
#
|
||||||
# The libraries One,...,Five have their dependencies explicitly
|
# Exec: NoDepB NoDepC SixA SixB
|
||||||
|
# Exec2: Eight Five
|
||||||
|
# Exec3: Eight Five
|
||||||
|
# Exec4: Five Two
|
||||||
|
#
|
||||||
|
# The libraries One,...,Eight have their dependencies explicitly
|
||||||
# encoded. The libraries NoDepA,...,NoDepC do not.
|
# encoded. The libraries NoDepA,...,NoDepC do not.
|
||||||
#
|
#
|
||||||
# Although SixB does not depend on Two, there is a dependency listed
|
# Although SixB does not depend on Two, there is a dependency listed
|
||||||
# in the corresponding CMakeLists.txt just because of commands used.
|
# in the corresponding CMakeLists.txt just because of commands used.
|
||||||
|
|
||||||
SUBDIRS( NoDepA NoDepB NoDepC )
|
SUBDIRS( NoDepA NoDepB NoDepC )
|
||||||
SUBDIRS( One Two Three Four Five Six )
|
SUBDIRS( One Two Three Four Five Six Seven Eight )
|
||||||
SUBDIRS( Exec )
|
SUBDIRS( Exec Exec2 Exec3 Exec4 )
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
ADD_LIBRARY( Eight EightSrc.c )
|
||||||
|
TARGET_LINK_LIBRARIES( Eight Seven )
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
void SevenFunction();
|
||||||
|
|
||||||
|
void EightFunction()
|
||||||
|
{
|
||||||
|
SevenFunction();
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
# Here, Eight depends on Seven, which has the same dependencies as Five.
|
||||||
|
# If the dependencies of Five are emitted, and then we attempt to emit the
|
||||||
|
# dependencies of Seven, then we find that they have already been done. So:
|
||||||
|
# Original line: Eight Five
|
||||||
|
# Add deps of Five: Eight Five Two ... NoDepA
|
||||||
|
# Now, we must make sure that Seven gets inserted between Five and Two, and
|
||||||
|
# not at the end. Unfortunately, if we get it wrong, the test will only
|
||||||
|
# fail on a platform where the link order makes a difference.
|
||||||
|
LINK_LIBRARIES( Eight Five )
|
||||||
|
|
||||||
|
ADD_EXECUTABLE( exec2 ExecMain.c )
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
void FiveFunction();
|
||||||
|
void EightFunction();
|
||||||
|
|
||||||
|
int main( )
|
||||||
|
{
|
||||||
|
FiveFunction();
|
||||||
|
EightFunction();
|
||||||
|
|
||||||
|
printf("Dependency test executable ran successfully.\n");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
# Here, Five already has it's immediate dependency, Two satisfied. We must
|
||||||
|
# make sure Two gets output anyway, because Eight indirectly depends on it.
|
||||||
|
LINK_LIBRARIES( Five Two Eight Five )
|
||||||
|
|
||||||
|
ADD_EXECUTABLE( exec3 ExecMain.c )
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
void FiveFunction();
|
||||||
|
void EightFunction();
|
||||||
|
|
||||||
|
int main( )
|
||||||
|
{
|
||||||
|
FiveFunction();
|
||||||
|
EightFunction();
|
||||||
|
|
||||||
|
printf("Dependency test executable ran successfully.\n");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
# Even though Five's dependency on Two is explicitly satisfied, Two
|
||||||
|
# must be emitted again in order to satisfy a cyclic dependency on Three.
|
||||||
|
LINK_LIBRARIES( Five Two Five )
|
||||||
|
|
||||||
|
ADD_EXECUTABLE( exec4 ExecMain.c )
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
void FiveFunction();
|
||||||
|
void TwoFunction();
|
||||||
|
|
||||||
|
int main( )
|
||||||
|
{
|
||||||
|
FiveFunction();
|
||||||
|
TwoFunction();
|
||||||
|
|
||||||
|
printf("Dependency test executable ran successfully.\n");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
ADD_LIBRARY( Seven SevenSrc.c )
|
||||||
|
TARGET_LINK_LIBRARIES( Seven Two )
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
void TwoFunction();
|
||||||
|
|
||||||
|
void SevenFunction()
|
||||||
|
{
|
||||||
|
TwoFunction();
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
PROJECT( LinkLine )
|
||||||
|
|
||||||
|
# Makes sure that the library order as specified by the user are
|
||||||
|
# unchanged by dependency analysis, etc. libOne and libTwo are
|
||||||
|
# dependent on each other. The link line should be -lOne -lTwo -lOne.
|
||||||
|
|
||||||
|
ADD_LIBRARY( One One.c )
|
||||||
|
ADD_LIBRARY( Two Two.c )
|
||||||
|
|
||||||
|
LINK_LIBRARIES( One Two )
|
||||||
|
ADD_EXECUTABLE( Exec Exec.c )
|
||||||
|
LINK_LIBRARIES( One )
|
|
@ -0,0 +1,9 @@
|
||||||
|
void OneFunc();
|
||||||
|
void TwoFunc();
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
OneFunc();
|
||||||
|
TwoFunc();
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
void TwoFunc();
|
||||||
|
|
||||||
|
void OneFunc()
|
||||||
|
{
|
||||||
|
static int i = 0;
|
||||||
|
++i;
|
||||||
|
if( i==1 ) {
|
||||||
|
TwoFunc();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
void OneFunc();
|
||||||
|
|
||||||
|
void TwoFunc()
|
||||||
|
{
|
||||||
|
static int i = 0;
|
||||||
|
++i;
|
||||||
|
if( i==1 ) {
|
||||||
|
OneFunc();
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue