2005-02-24 21:16:41 +03:00
# include "cmOrderLinkDirectories.h"
# include "cmSystemTools.h"
# include "cmsys/RegularExpression.hxx"
2005-04-08 20:46:56 +04:00
# include <ctype.h>
2005-02-24 21:16:41 +03:00
2005-03-04 02:46:52 +03:00
//-------------------------------------------------------------------
cmOrderLinkDirectories : : cmOrderLinkDirectories ( )
{
2006-03-15 19:02:08 +03:00
this - > Debug = false ;
2005-03-04 02:46:52 +03:00
}
2005-02-24 21:16:41 +03:00
//-------------------------------------------------------------------
bool cmOrderLinkDirectories : : LibraryInDirectory ( const char * dir ,
2005-02-24 23:36:56 +03:00
const char * libIn )
2005-02-24 21:16:41 +03:00
{
cmStdString path = dir ;
path + = " / " ;
2005-02-24 23:36:56 +03:00
path + = libIn ;
2005-02-24 21:16:41 +03:00
// first look for the library as given
if ( cmSystemTools : : FileExists ( path . c_str ( ) ) )
{
return true ;
}
// next remove the extension (.a, .so ) and look for the library
// under a different name as the linker can do either
2006-03-15 19:02:08 +03:00
if ( this - > RemoveLibraryExtension . find ( libIn ) )
2005-02-24 21:16:41 +03:00
{
2006-03-15 19:02:08 +03:00
cmStdString lib = this - > RemoveLibraryExtension . match ( 1 ) ;
cmStdString ext = this - > RemoveLibraryExtension . match ( 2 ) ;
for ( std : : vector < cmStdString > : : iterator i = this - > LinkExtensions . begin ( ) ;
i ! = this - > LinkExtensions . end ( ) ; + + i )
2005-02-24 21:16:41 +03:00
{
if ( ext ! = * i )
{
path = dir ;
path + = " / " ;
path + = lib + * i ;
if ( cmSystemTools : : FileExists ( path . c_str ( ) ) )
{
return true ;
}
}
}
}
return false ;
}
//-------------------------------------------------------------------
2006-04-01 06:43:11 +04:00
void cmOrderLinkDirectories : : FindLibrariesInSearchPaths ( )
2005-02-24 21:16:41 +03:00
{
2006-03-15 19:02:08 +03:00
for ( std : : set < cmStdString > : : iterator dir = this - > LinkPathSet . begin ( ) ;
dir ! = this - > LinkPathSet . end ( ) ; + + dir )
2005-02-24 21:16:41 +03:00
{
for ( std : : map < cmStdString , Library > : : iterator lib
2006-03-15 19:02:08 +03:00
= this - > FullPathLibraries . begin ( ) ;
lib ! = this - > FullPathLibraries . end ( ) ; + + lib )
2005-02-24 21:16:41 +03:00
{
if ( lib - > second . Path ! = * dir )
{
2005-03-04 02:16:00 +03:00
if ( this - > LibraryInDirectory ( dir - > c_str ( ) , lib - > second . File . c_str ( ) ) )
2005-02-24 21:16:41 +03:00
{
2006-03-15 19:02:08 +03:00
this - > LibraryToDirectories [ lib - > second . FullPath ] . push_back ( * dir ) ;
2005-02-24 21:16:41 +03:00
}
}
}
}
}
//-------------------------------------------------------------------
void cmOrderLinkDirectories : : FindIndividualLibraryOrders ( )
{
2006-03-15 19:02:08 +03:00
for ( std : : vector < Library > : : iterator lib = this - > MultiDirectoryLibraries . begin ( ) ;
lib ! = this - > MultiDirectoryLibraries . end ( ) ; + + lib )
2005-02-24 21:16:41 +03:00
{
2006-03-15 19:02:08 +03:00
std : : vector < cmStdString > & dirs = this - > LibraryToDirectories [ lib - > FullPath ] ;
this - > DirectoryToAfterList [ lib - > Path ] = dirs ;
2005-02-24 21:16:41 +03:00
}
}
2005-04-08 20:46:56 +04:00
//-------------------------------------------------------------------
std : : string cmOrderLinkDirectories : : NoCaseExpression ( const char * str )
{
std : : string ret ;
const char * s = str ;
while ( * s )
{
if ( * s = = ' . ' )
{
ret + = * s ;
}
else
{
ret + = " [ " ;
ret + = tolower ( * s ) ;
ret + = toupper ( * s ) ;
ret + = " ] " ;
}
s + + ;
}
return ret ;
}
2005-02-24 21:16:41 +03:00
//-------------------------------------------------------------------
void cmOrderLinkDirectories : : CreateRegularExpressions ( )
{
2006-03-15 19:02:08 +03:00
this - > SplitFramework . compile ( " (.*)/(.*) \\ .framework$ " ) ;
2005-02-24 21:16:41 +03:00
cmStdString libext = " ( " ;
bool first = true ;
2006-03-15 19:02:08 +03:00
for ( std : : vector < cmStdString > : : iterator i = this - > LinkExtensions . begin ( ) ;
i ! = this - > LinkExtensions . end ( ) ; + + i )
2005-02-24 21:16:41 +03:00
{
if ( ! first )
{
libext + = " | " ;
}
first = false ;
libext + = " \\ " ;
2005-08-10 20:55:41 +04:00
# if defined(_WIN32) && !defined(__CYGWIN__)
2005-04-08 20:46:56 +04:00
libext + = this - > NoCaseExpression ( i - > c_str ( ) ) ;
2005-08-10 20:55:41 +04:00
# else
libext + = * i ;
2005-04-08 20:46:56 +04:00
# endif
2005-02-24 21:16:41 +03:00
}
libext + = " ).* " ;
cmStdString reg ( " (.*) " ) ;
reg + = libext ;
2006-03-15 19:02:08 +03:00
this - > RemoveLibraryExtension . compile ( reg . c_str ( ) ) ;
2005-08-10 20:55:41 +04:00
reg = " " ;
2006-03-15 19:02:08 +03:00
if ( this - > LinkPrefix . size ( ) )
2005-08-10 20:55:41 +04:00
{
reg = " ^ " ;
2006-03-15 19:02:08 +03:00
reg + = this - > LinkPrefix ;
2005-08-10 20:55:41 +04:00
}
reg + = " ([^/]*) " ;
2005-02-24 21:16:41 +03:00
reg + = libext ;
2006-03-15 19:02:08 +03:00
this - > ExtractBaseLibraryName . compile ( reg . c_str ( ) ) ;
2005-02-24 21:16:41 +03:00
reg = " ([^/]*) " ;
reg + = libext ;
2006-03-15 19:02:08 +03:00
this - > ExtractBaseLibraryNameNoPrefix . compile ( reg . c_str ( ) ) ;
2005-02-24 21:16:41 +03:00
}
//-------------------------------------------------------------------
void cmOrderLinkDirectories : : PrepareLinkTargets ( )
{
2006-03-15 19:02:08 +03:00
for ( std : : vector < cmStdString > : : iterator i = this - > LinkItems . begin ( ) ;
i ! = this - > LinkItems . end ( ) ; + + i )
2005-02-24 21:16:41 +03:00
{
// separate the library name from libfoo.a or foo.a
2006-03-15 19:02:08 +03:00
if ( this - > ExtractBaseLibraryName . find ( * i ) )
2005-02-24 21:16:41 +03:00
{
2006-03-15 19:02:08 +03:00
* i = this - > ExtractBaseLibraryName . match ( 1 ) ;
2005-02-24 21:16:41 +03:00
}
2006-03-15 19:02:08 +03:00
else if ( this - > ExtractBaseLibraryNameNoPrefix . find ( * i ) )
2005-02-24 21:16:41 +03:00
{
2006-03-15 19:02:08 +03:00
* i = this - > ExtractBaseLibraryNameNoPrefix . match ( 1 ) ;
2005-02-24 21:16:41 +03:00
}
}
}
//-------------------------------------------------------------------
2005-03-04 02:16:00 +03:00
bool cmOrderLinkDirectories : : FindPathNotInDirectoryToAfterList (
cmStdString & path )
2005-02-24 21:16:41 +03:00
{
2005-03-04 02:16:00 +03:00
for ( std : : map < cmStdString , std : : vector < cmStdString > > : : iterator i
2006-03-15 19:02:08 +03:00
= this - > DirectoryToAfterList . begin ( ) ;
i ! = this - > DirectoryToAfterList . end ( ) ; + + i )
2005-02-24 21:16:41 +03:00
{
2005-03-04 02:16:00 +03:00
const cmStdString & p = i - > first ;
bool found = false ;
for ( std : : map < cmStdString , std : : vector < cmStdString > > : : iterator j
2006-03-15 19:02:08 +03:00
= this - > DirectoryToAfterList . begin ( ) ; j ! = this - > DirectoryToAfterList . end ( )
2005-03-04 02:16:00 +03:00
& & ! found ; + + j )
2005-03-03 01:49:11 +03:00
{
2005-03-04 02:16:00 +03:00
if ( j ! = i )
{
found = ( std : : find ( j - > second . begin ( ) , j - > second . end ( ) , p ) ! = j - > second . end ( ) ) ;
}
2005-03-03 01:49:11 +03:00
}
2005-03-04 02:16:00 +03:00
if ( ! found )
2005-03-03 01:49:11 +03:00
{
2005-03-04 02:16:00 +03:00
path = p ;
2006-03-15 19:02:08 +03:00
this - > DirectoryToAfterList . erase ( i ) ;
2005-03-04 02:16:00 +03:00
return true ;
2005-03-03 01:49:11 +03:00
}
2005-03-04 02:16:00 +03:00
}
path = " " ;
return false ;
2005-03-03 02:56:46 +03:00
}
2005-03-04 02:16:00 +03:00
2005-03-03 02:56:46 +03:00
//-------------------------------------------------------------------
void cmOrderLinkDirectories : : OrderPaths ( std : : vector < cmStdString > &
orderedPaths )
{
2005-03-04 02:16:00 +03:00
cmStdString path ;
// This is a topological sort implementation
// One at a time find paths that are not in any other paths after list
// and put them into the orderedPaths vector in that order
// FindPathNotInDirectoryToAfterList removes the path from the
2006-03-15 19:02:08 +03:00
// this->DirectoryToAfterList once it is found
2005-03-04 02:16:00 +03:00
while ( this - > FindPathNotInDirectoryToAfterList ( path ) )
{
orderedPaths . push_back ( path ) ;
}
2006-03-15 19:02:08 +03:00
// at this point if there are still paths in this->DirectoryToAfterList
2005-03-04 02:16:00 +03:00
// then there is a cycle and we are stuck
2006-03-15 19:02:08 +03:00
if ( this - > DirectoryToAfterList . size ( ) )
2005-03-04 02:16:00 +03:00
{
for ( std : : map < cmStdString , std : : vector < cmStdString > > : : iterator i
2006-03-15 19:02:08 +03:00
= this - > DirectoryToAfterList . begin ( ) ;
i ! = this - > DirectoryToAfterList . end ( ) ; + + i )
2005-03-04 02:16:00 +03:00
{
2006-03-15 19:02:08 +03:00
this - > ImpossibleDirectories . insert ( i - > first ) ;
2005-03-04 02:16:00 +03:00
// still put it in the path list in the order we find them
orderedPaths . push_back ( i - > first ) ;
}
}
2005-02-24 21:16:41 +03:00
}
//-------------------------------------------------------------------
2006-01-14 02:18:32 +03:00
void cmOrderLinkDirectories : : SetLinkInformation (
const char * targetName ,
const std : : vector < std : : string > & linkLibraries ,
const std : : vector < std : : string > & linkDirectories
)
2005-02-24 21:16:41 +03:00
{
2006-01-14 02:18:32 +03:00
// Save the target name.
2006-03-15 19:02:08 +03:00
this - > TargetName = targetName ;
2006-01-14 02:18:32 +03:00
// Merge the link directory search path given into our path set.
2005-03-04 02:16:00 +03:00
std : : vector < cmStdString > empty ;
2006-01-14 02:18:32 +03:00
for ( std : : vector < std : : string > : : const_iterator p = linkDirectories . begin ( ) ;
p ! = linkDirectories . end ( ) ; + + p )
2005-02-24 21:16:41 +03:00
{
2006-03-15 19:02:08 +03:00
this - > DirectoryToAfterList [ * p ] = empty ;
this - > LinkPathSet . insert ( * p ) ;
2005-02-24 21:16:41 +03:00
}
2006-01-14 02:18:32 +03:00
// Append the link library list into our raw list.
for ( std : : vector < std : : string > : : const_iterator l = linkLibraries . begin ( ) ;
l ! = linkLibraries . end ( ) ; + + l )
2005-02-24 21:16:41 +03:00
{
2006-03-15 19:02:08 +03:00
this - > RawLinkItems . push_back ( * l ) ;
2005-02-24 21:16:41 +03:00
}
}
//-------------------------------------------------------------------
bool cmOrderLinkDirectories : : DetermineLibraryPathOrder ( )
{
// set up all the regular expressions
this - > CreateRegularExpressions ( ) ;
std : : vector < cmStdString > finalOrderPaths ;
// find all libs that are full paths
Library aLib ;
cmStdString dir ;
cmStdString file ;
2005-03-04 02:16:00 +03:00
std : : vector < cmStdString > empty ;
2006-03-16 19:27:56 +03:00
// do not add a -F for the system frameworks
this - > EmittedFrameworkPaths . insert ( " /System/Library/Frameworks " ) ;
2006-03-15 19:02:08 +03:00
for ( unsigned int i = 0 ; i < this - > RawLinkItems . size ( ) ; + + i )
2005-02-24 21:16:41 +03:00
{
2006-04-01 02:59:28 +04:00
bool framework = false ;
2006-03-15 19:02:08 +03:00
if ( cmSystemTools : : FileIsFullPath ( this - > RawLinkItems [ i ] . c_str ( ) ) )
2005-02-24 21:16:41 +03:00
{
2006-03-15 19:02:08 +03:00
if ( cmSystemTools : : FileIsDirectory ( this - > RawLinkItems [ i ] . c_str ( ) ) )
2005-11-23 00:59:31 +03:00
{
2006-03-15 19:02:08 +03:00
if ( cmSystemTools : : IsPathToFramework ( this - > RawLinkItems [ i ] . c_str ( ) ) )
2005-12-26 21:14:19 +03:00
{
2006-03-15 19:02:08 +03:00
this - > SplitFramework . find ( this - > RawLinkItems [ i ] ) ;
cmStdString path = this - > SplitFramework . match ( 1 ) ;
2005-12-26 21:14:19 +03:00
// Add the -F path if we have not yet done so
2006-03-15 19:02:08 +03:00
if ( this - > EmittedFrameworkPaths . insert ( path ) . second )
2005-12-26 21:14:19 +03:00
{
std : : string fpath = " -F " ;
fpath + = cmSystemTools : : ConvertToOutputPath ( path . c_str ( ) ) ;
2006-03-15 19:02:08 +03:00
this - > LinkItems . push_back ( fpath ) ;
2005-12-26 21:14:19 +03:00
}
// now add the -framework option
std : : string frame = " -framework " ;
2006-03-15 19:02:08 +03:00
frame + = this - > SplitFramework . match ( 2 ) ;
this - > LinkItems . push_back ( frame ) ;
2005-12-26 21:14:19 +03:00
framework = true ;
}
else
{
std : : string message = " Warning: Ignoring path found in link libraries for target: " ;
2006-03-15 19:02:08 +03:00
message + = this - > TargetName ;
2005-12-26 21:14:19 +03:00
message + = " , path is: " ;
2006-03-15 19:02:08 +03:00
message + = this - > RawLinkItems [ i ] ;
2005-12-26 21:14:19 +03:00
message + = " . Expected a library name or a full path to a library name. " ;
cmSystemTools : : Message ( message . c_str ( ) ) ;
continue ;
}
}
if ( ! framework )
{
2006-03-15 19:02:08 +03:00
cmSystemTools : : SplitProgramPath ( this - > RawLinkItems [ i ] . c_str ( ) ,
2005-12-26 21:14:19 +03:00
dir , file ) ;
2006-02-10 01:29:58 +03:00
# ifdef _WIN32
// Avoid case problems for windows paths.
if ( dir . size ( ) > 2 & & dir [ 1 ] = = ' : ' )
{
if ( dir [ 0 ] > = ' A ' & & dir [ 0 ] < = ' Z ' )
{
dir [ 0 ] + = ' a ' - ' A ' ;
}
}
dir = cmSystemTools : : GetActualCaseForPath ( dir . c_str ( ) ) ;
# endif
2006-03-15 19:02:08 +03:00
this - > DirectoryToAfterList [ dir ] = empty ;
this - > LinkPathSet . insert ( dir ) ;
aLib . FullPath = this - > RawLinkItems [ i ] ;
2005-12-26 21:14:19 +03:00
aLib . File = file ;
aLib . Path = dir ;
2006-03-15 19:02:08 +03:00
this - > FullPathLibraries [ aLib . FullPath ] = aLib ;
this - > LinkItems . push_back ( file ) ;
2005-11-23 00:59:31 +03:00
}
2005-02-24 21:16:41 +03:00
}
else
{
2006-03-15 19:02:08 +03:00
this - > LinkItems . push_back ( this - > RawLinkItems [ i ] ) ;
2005-02-24 21:16:41 +03:00
}
}
2006-04-01 06:43:11 +04:00
this - > FindLibrariesInSearchPaths ( ) ;
2005-02-24 21:16:41 +03:00
for ( std : : map < cmStdString , std : : vector < cmStdString > > : : iterator lib =
2006-03-15 19:02:08 +03:00
this - > LibraryToDirectories . begin ( ) ; lib ! = this - > LibraryToDirectories . end ( ) ;
2005-02-24 21:16:41 +03:00
+ + lib )
{
if ( lib - > second . size ( ) > 0 )
{
2006-03-15 19:02:08 +03:00
this - > MultiDirectoryLibraries . push_back ( this - > FullPathLibraries [ lib - > first ] ) ;
2005-02-24 21:16:41 +03:00
}
else
{
2006-03-15 19:02:08 +03:00
this - > SingleDirectoryLibraries . push_back ( this - > FullPathLibraries [ lib - > first ] ) ;
2005-02-24 21:16:41 +03:00
}
}
this - > FindIndividualLibraryOrders ( ) ;
2006-03-15 19:02:08 +03:00
this - > SortedSearchPaths . clear ( ) ;
if ( this - > Debug )
2005-03-04 02:46:52 +03:00
{
2006-03-15 19:02:08 +03:00
this - > PrintMap ( " this->LibraryToDirectories " , this - > LibraryToDirectories ) ;
this - > PrintMap ( " this->DirectoryToAfterList " , this - > DirectoryToAfterList ) ;
2005-03-04 02:46:52 +03:00
}
2006-03-15 19:02:08 +03:00
this - > OrderPaths ( this - > SortedSearchPaths ) ;
2005-02-24 21:16:41 +03:00
// now turn libfoo.a into foo and foo.a into foo
// This will prepare the link items for -litem
this - > PrepareLinkTargets ( ) ;
2006-03-15 19:02:08 +03:00
if ( this - > ImpossibleDirectories . size ( ) )
2005-02-24 21:16:41 +03:00
{
2005-02-26 01:45:12 +03:00
cmSystemTools : : Message ( this - > GetWarnings ( ) . c_str ( ) ) ;
2005-02-24 21:16:41 +03:00
return false ;
}
return true ;
}
std : : string cmOrderLinkDirectories : : GetWarnings ( )
{
2005-09-08 23:25:55 +04:00
std : : string warning = " It is impossible to order the linker search path in such a way that libraries specified as full paths will be picked by the linker. \n Directories and libraries involved are: \n " ;
2006-03-15 19:02:08 +03:00
for ( std : : set < cmStdString > : : iterator i = this - > ImpossibleDirectories . begin ( ) ;
i ! = this - > ImpossibleDirectories . end ( ) ; + + i )
2005-02-24 21:16:41 +03:00
{
warning + = " Directory: " ;
warning + = * i ;
2005-03-04 02:16:00 +03:00
warning + = " contains: \n " ;
2005-02-24 21:16:41 +03:00
std : : map < cmStdString , std : : vector < cmStdString > > : : iterator j ;
2006-03-15 19:02:08 +03:00
for ( j = this - > LibraryToDirectories . begin ( ) ;
j ! = this - > LibraryToDirectories . end ( ) ; + + j )
2005-02-24 21:16:41 +03:00
{
if ( std : : find ( j - > second . begin ( ) , j - > second . end ( ) , * i )
! = j - > second . end ( ) )
{
warning + = " Library: " ;
warning + = j - > first ;
warning + = " \n " ;
}
}
2005-03-04 02:16:00 +03:00
warning + = " \n " ;
2005-02-24 21:16:41 +03:00
}
warning + = " \n " ;
return warning ;
}
2005-02-24 21:26:39 +03:00
//-------------------------------------------------------------------
void
cmOrderLinkDirectories : : PrintMap ( const char * name ,
std : : map < cmStdString , std : : vector < cmStdString > > & m )
{
2005-03-04 02:46:52 +03:00
std : : cout < < name < < " \n " ;
2005-02-24 21:26:39 +03:00
for ( std : : map < cmStdString , std : : vector < cmStdString > > : : iterator i =
m . begin ( ) ; i ! = m . end ( ) ;
+ + i )
{
2005-03-04 02:46:52 +03:00
std : : cout < < i - > first < < " : " ;
2005-02-24 21:26:39 +03:00
for ( std : : vector < cmStdString > : : iterator l = i - > second . begin ( ) ;
l ! = i - > second . end ( ) ; + + l )
{
2005-03-04 02:46:52 +03:00
std : : cout < < * l < < " " ;
2005-02-24 21:26:39 +03:00
}
2005-03-04 02:46:52 +03:00
std : : cout < < " \n " ;
2005-02-24 21:26:39 +03:00
}
}
2005-02-26 01:45:12 +03:00
void cmOrderLinkDirectories : : GetFullPathLibraries ( std : : vector < cmStdString > &
libs )
{
2006-03-15 19:02:08 +03:00
for ( std : : map < cmStdString , Library > : : iterator i = this - > FullPathLibraries . begin ( ) ;
i ! = this - > FullPathLibraries . end ( ) ; + + i )
2005-02-26 01:45:12 +03:00
{
libs . push_back ( i - > first ) ;
}
}