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
|
|
|
|
2006-09-15 22:09:10 +04:00
|
|
|
//#define CM_ORDER_LINK_DIRECTORIES_DEBUG
|
2005-02-24 21:16:41 +03:00
|
|
|
|
2005-03-04 02:46:52 +03:00
|
|
|
//-------------------------------------------------------------------
|
|
|
|
cmOrderLinkDirectories::cmOrderLinkDirectories()
|
|
|
|
{
|
2006-09-15 22:09:10 +04:00
|
|
|
this->StartLinkType = LinkUnknown;
|
|
|
|
this->LinkTypeEnabled = false;
|
2006-03-15 19:02:08 +03:00
|
|
|
this->Debug = false;
|
2005-03-04 02:46:52 +03:00
|
|
|
}
|
|
|
|
|
2006-09-15 22:09:10 +04:00
|
|
|
//-------------------------------------------------------------------
|
|
|
|
void
|
|
|
|
cmOrderLinkDirectories
|
|
|
|
::SetLinkTypeInformation(LinkType start_link_type,
|
|
|
|
const char* static_link_type_flag,
|
|
|
|
const char* shared_link_type_flag)
|
|
|
|
{
|
|
|
|
// We can support link type switching only if all needed flags are
|
|
|
|
// known.
|
|
|
|
this->StartLinkType = start_link_type;
|
|
|
|
if(static_link_type_flag && *static_link_type_flag &&
|
|
|
|
shared_link_type_flag && *shared_link_type_flag)
|
|
|
|
{
|
|
|
|
this->LinkTypeEnabled = true;
|
|
|
|
this->StaticLinkTypeFlag = static_link_type_flag;
|
|
|
|
this->SharedLinkTypeFlag = shared_link_type_flag;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
this->LinkTypeEnabled = false;
|
|
|
|
this->StaticLinkTypeFlag = "";
|
|
|
|
this->SharedLinkTypeFlag = "";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//-------------------------------------------------------------------
|
|
|
|
void cmOrderLinkDirectories::SetCurrentLinkType(LinkType lt)
|
|
|
|
{
|
|
|
|
if(this->CurrentLinkType != lt)
|
|
|
|
{
|
|
|
|
this->CurrentLinkType = lt;
|
|
|
|
|
|
|
|
if(this->LinkTypeEnabled)
|
|
|
|
{
|
|
|
|
switch(this->CurrentLinkType)
|
|
|
|
{
|
|
|
|
case LinkStatic:
|
|
|
|
this->LinkItems.push_back(this->StaticLinkTypeFlag); break;
|
|
|
|
case LinkShared:
|
|
|
|
this->LinkItems.push_back(this->SharedLinkTypeFlag); break;
|
|
|
|
default: break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-02-24 21:16:41 +03:00
|
|
|
//-------------------------------------------------------------------
|
2006-04-04 22:25:17 +04:00
|
|
|
bool cmOrderLinkDirectories::LibraryInDirectory(const char* desiredLib,
|
|
|
|
const char* dir,
|
2005-02-24 23:36:56 +03:00
|
|
|
const char* libIn)
|
2005-02-24 21:16:41 +03:00
|
|
|
{
|
|
|
|
// first look for the library as given
|
2006-04-04 22:25:17 +04:00
|
|
|
if(this->LibraryMayConflict(desiredLib, dir, libIn))
|
2005-02-24 21:16:41 +03:00
|
|
|
{
|
|
|
|
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)
|
|
|
|
{
|
2006-04-04 22:25:17 +04:00
|
|
|
std::string fname = lib;
|
|
|
|
lib += *i;
|
|
|
|
if(this->LibraryMayConflict(desiredLib, dir, fname.c_str()))
|
2005-02-24 21:16:41 +03:00
|
|
|
{
|
|
|
|
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)
|
|
|
|
{
|
2006-04-04 22:25:17 +04:00
|
|
|
if(this->LibraryInDirectory(lib->second.FullPath.c_str(),
|
|
|
|
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-05-12 21:39:34 +04:00
|
|
|
for(std::vector<Library>::iterator lib =
|
|
|
|
this->MultiDirectoryLibraries.begin();
|
2006-03-15 19:02:08 +03:00
|
|
|
lib != this->MultiDirectoryLibraries.end(); ++lib)
|
2005-02-24 21:16:41 +03:00
|
|
|
{
|
2006-05-12 21:39:34 +04:00
|
|
|
std::vector<cmStdString>& dirs =
|
|
|
|
this->LibraryToDirectories[lib->FullPath];
|
|
|
|
std::vector<std::pair<cmStdString, std::vector<cmStdString> >
|
|
|
|
>::iterator i;
|
|
|
|
for(i = this->DirectoryToAfterList.begin();
|
|
|
|
i != this->DirectoryToAfterList.end(); ++i)
|
2006-04-04 19:52:00 +04:00
|
|
|
{
|
|
|
|
if(i->first == lib->Path)
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(i == this->DirectoryToAfterList.end())
|
|
|
|
{
|
|
|
|
std::cerr << "ERROR: should not happen\n";
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
for(std::vector<cmStdString>::iterator d = dirs.begin();
|
|
|
|
d != dirs.end(); ++d)
|
|
|
|
{
|
|
|
|
i->second.push_back(*d);
|
|
|
|
}
|
|
|
|
}
|
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$");
|
2006-09-15 22:09:10 +04:00
|
|
|
|
|
|
|
// Compute a regex to match link extensions.
|
|
|
|
cmStdString libext = this->CreateExtensionRegex(this->LinkExtensions);
|
|
|
|
|
|
|
|
// Create regex to remove any library extension.
|
|
|
|
cmStdString reg("(.*)");
|
|
|
|
reg += libext;
|
|
|
|
this->RemoveLibraryExtension.compile(reg.c_str());
|
|
|
|
|
|
|
|
// Create a regex to match a library name. Match index 1 will be
|
|
|
|
// the prefix if it exists and empty otherwise. Match index 2 will
|
|
|
|
// be the library name. Match index 3 will be the library
|
|
|
|
// extension.
|
|
|
|
reg = "^(";
|
2006-10-05 23:08:20 +04:00
|
|
|
for(std::set<cmStdString>::iterator p = this->LinkPrefixes.begin();
|
|
|
|
p != this->LinkPrefixes.end(); ++p)
|
2006-09-15 22:09:10 +04:00
|
|
|
{
|
2006-10-05 23:08:20 +04:00
|
|
|
reg += *p;
|
2006-09-15 22:09:10 +04:00
|
|
|
reg += "|";
|
|
|
|
}
|
|
|
|
reg += ")";
|
|
|
|
reg += "([^/]*)";
|
|
|
|
|
|
|
|
// Create a regex to match any library name.
|
|
|
|
cmStdString reg_any = reg;
|
|
|
|
reg_any += libext;
|
|
|
|
#ifdef CM_ORDER_LINK_DIRECTORIES_DEBUG
|
|
|
|
fprintf(stderr, "any regex [%s]\n", reg_any.c_str());
|
|
|
|
#endif
|
|
|
|
this->ExtractAnyLibraryName.compile(reg_any.c_str());
|
|
|
|
|
|
|
|
// Create a regex to match static library names.
|
|
|
|
if(!this->StaticLinkExtensions.empty())
|
|
|
|
{
|
|
|
|
cmStdString reg_static = reg;
|
|
|
|
reg_static += this->CreateExtensionRegex(this->StaticLinkExtensions);
|
|
|
|
#ifdef CM_ORDER_LINK_DIRECTORIES_DEBUG
|
|
|
|
fprintf(stderr, "static regex [%s]\n", reg_static.c_str());
|
|
|
|
#endif
|
|
|
|
this->ExtractStaticLibraryName.compile(reg_static.c_str());
|
|
|
|
}
|
|
|
|
|
|
|
|
// Create a regex to match shared library names.
|
|
|
|
if(!this->SharedLinkExtensions.empty())
|
|
|
|
{
|
|
|
|
cmStdString reg_shared = reg;
|
|
|
|
reg_shared += this->CreateExtensionRegex(this->SharedLinkExtensions);
|
|
|
|
#ifdef CM_ORDER_LINK_DIRECTORIES_DEBUG
|
|
|
|
fprintf(stderr, "shared regex [%s]\n", reg_shared.c_str());
|
|
|
|
#endif
|
|
|
|
this->ExtractSharedLibraryName.compile(reg_shared.c_str());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//-------------------------------------------------------------------
|
|
|
|
std::string
|
|
|
|
cmOrderLinkDirectories::CreateExtensionRegex(
|
|
|
|
std::vector<cmStdString> const& exts)
|
|
|
|
{
|
|
|
|
// Build a list of extension choices.
|
2005-02-24 21:16:41 +03:00
|
|
|
cmStdString libext = "(";
|
2006-09-15 22:09:10 +04:00
|
|
|
const char* sep = "";
|
|
|
|
for(std::vector<cmStdString>::const_iterator i = exts.begin();
|
|
|
|
i != exts.end(); ++i)
|
2005-02-24 21:16:41 +03:00
|
|
|
{
|
2006-09-15 22:09:10 +04:00
|
|
|
// Separate this choice from the previous one.
|
|
|
|
libext += sep;
|
|
|
|
sep = "|";
|
|
|
|
|
|
|
|
// Store this extension choice with the "." escaped.
|
2005-02-24 21:16:41 +03:00
|
|
|
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
|
|
|
}
|
2006-09-15 22:09:10 +04:00
|
|
|
|
|
|
|
// Finish the list.
|
2005-02-24 21:16:41 +03:00
|
|
|
libext += ").*";
|
2006-09-15 22:09:10 +04:00
|
|
|
return libext;
|
2005-02-24 21:16:41 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
//-------------------------------------------------------------------
|
|
|
|
void cmOrderLinkDirectories::PrepareLinkTargets()
|
|
|
|
{
|
2006-09-15 22:09:10 +04:00
|
|
|
std::vector<cmStdString> originalLinkItems = this->LinkItems;
|
|
|
|
this->LinkItems.clear();
|
|
|
|
this->CurrentLinkType = this->StartLinkType;
|
|
|
|
for(std::vector<cmStdString>::iterator i = originalLinkItems.begin();
|
|
|
|
i != originalLinkItems.end(); ++i)
|
2005-02-24 21:16:41 +03:00
|
|
|
{
|
2006-10-06 00:59:46 +04:00
|
|
|
// Parse out the prefix, base, and suffix components of the
|
|
|
|
// library name. If the name matches that of a shared or static
|
|
|
|
// library then set the link type accordingly.
|
|
|
|
//
|
|
|
|
// Search for shared library names first because some platforms
|
|
|
|
// have shared libraries with names that match the static library
|
|
|
|
// pattern. For example cygwin and msys use the convention
|
|
|
|
// libfoo.dll.a for import libraries and libfoo.a for static
|
|
|
|
// libraries. On AIX a library with the name libfoo.a can be
|
|
|
|
// shared!
|
|
|
|
if(this->ExtractSharedLibraryName.find(*i))
|
2005-02-24 21:16:41 +03:00
|
|
|
{
|
2006-09-15 22:09:10 +04:00
|
|
|
#ifdef CM_ORDER_LINK_DIRECTORIES_DEBUG
|
|
|
|
fprintf(stderr, "shared regex matched [%s] [%s] [%s]\n",
|
|
|
|
this->ExtractSharedLibraryName.match(1).c_str(),
|
|
|
|
this->ExtractSharedLibraryName.match(2).c_str(),
|
|
|
|
this->ExtractSharedLibraryName.match(3).c_str());
|
|
|
|
#endif
|
|
|
|
this->SetCurrentLinkType(LinkShared);
|
|
|
|
this->LinkItems.push_back(this->ExtractSharedLibraryName.match(2));
|
|
|
|
}
|
2006-10-06 00:59:46 +04:00
|
|
|
else if(this->ExtractStaticLibraryName.find(*i))
|
|
|
|
{
|
|
|
|
#ifdef CM_ORDER_LINK_DIRECTORIES_DEBUG
|
|
|
|
fprintf(stderr, "static regex matched [%s] [%s] [%s]\n",
|
|
|
|
this->ExtractStaticLibraryName.match(1).c_str(),
|
|
|
|
this->ExtractStaticLibraryName.match(2).c_str(),
|
|
|
|
this->ExtractStaticLibraryName.match(3).c_str());
|
|
|
|
#endif
|
|
|
|
this->SetCurrentLinkType(LinkStatic);
|
|
|
|
this->LinkItems.push_back(this->ExtractStaticLibraryName.match(2));
|
|
|
|
}
|
2006-09-15 22:09:10 +04:00
|
|
|
else if(this->ExtractAnyLibraryName.find(*i))
|
|
|
|
{
|
|
|
|
#ifdef CM_ORDER_LINK_DIRECTORIES_DEBUG
|
|
|
|
fprintf(stderr, "any regex matched [%s] [%s] [%s]\n",
|
|
|
|
this->ExtractAnyLibraryName.match(1).c_str(),
|
|
|
|
this->ExtractAnyLibraryName.match(2).c_str(),
|
|
|
|
this->ExtractAnyLibraryName.match(3).c_str());
|
|
|
|
#endif
|
|
|
|
this->SetCurrentLinkType(this->StartLinkType);
|
|
|
|
this->LinkItems.push_back(this->ExtractAnyLibraryName.match(2));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
this->SetCurrentLinkType(this->StartLinkType);
|
|
|
|
this->LinkItems.push_back(*i);
|
2005-02-24 21:16:41 +03:00
|
|
|
}
|
|
|
|
}
|
2006-09-15 22:09:10 +04:00
|
|
|
|
|
|
|
// Restore the original linking type so system runtime libraries are
|
|
|
|
// linked properly.
|
|
|
|
this->SetCurrentLinkType(this->StartLinkType);
|
2005-02-24 21:16:41 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
//-------------------------------------------------------------------
|
2005-03-04 02:16:00 +03:00
|
|
|
bool cmOrderLinkDirectories::FindPathNotInDirectoryToAfterList(
|
|
|
|
cmStdString& path)
|
2006-04-04 19:52:00 +04:00
|
|
|
{
|
2006-05-12 21:39:34 +04:00
|
|
|
for(std::vector<std::pair<cmStdString, std::vector<cmStdString> >
|
|
|
|
>::iterator i = this->DirectoryToAfterList.begin();
|
2006-03-15 19:02:08 +03:00
|
|
|
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;
|
2006-05-12 21:39:34 +04:00
|
|
|
for(std::vector<std::pair<cmStdString, std::vector<cmStdString> >
|
|
|
|
>::iterator j = this->DirectoryToAfterList.begin();
|
|
|
|
j != this->DirectoryToAfterList.end() && !found; ++j)
|
2005-03-03 01:49:11 +03:00
|
|
|
{
|
2005-03-04 02:16:00 +03:00
|
|
|
if(j != i)
|
|
|
|
{
|
2006-05-12 21:39:34 +04:00
|
|
|
found = (std::find(j->second.begin(), j->second.end(), p)
|
|
|
|
!= j->second.end());
|
2005-03-04 02:16:00 +03:00
|
|
|
}
|
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
|
|
|
{
|
2006-05-12 21:39:34 +04:00
|
|
|
for(std::vector<std::pair<cmStdString, std::vector<cmStdString> >
|
|
|
|
>::iterator i = this->DirectoryToAfterList.begin();
|
2006-03-15 19:02:08 +03:00
|
|
|
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,
|
2006-04-04 22:25:17 +04:00
|
|
|
const std::vector<std::string>& linkDirectories,
|
|
|
|
const cmTargetManifest& manifest,
|
|
|
|
const char* configSubdir
|
2006-01-14 02:18:32 +03:00
|
|
|
)
|
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
|
|
|
|
2006-04-04 22:25:17 +04:00
|
|
|
// Save the subdirectory used for linking in this configuration.
|
|
|
|
this->ConfigSubdir = configSubdir? configSubdir : "";
|
|
|
|
|
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-04-05 19:05:06 +04:00
|
|
|
std::string dir = *p;
|
2006-04-05 19:07:54 +04:00
|
|
|
#ifdef _WIN32
|
2006-04-05 19:05:06 +04:00
|
|
|
// 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
|
|
|
|
if(this->DirectoryToAfterListEmitted.insert(dir).second)
|
2006-04-04 19:52:00 +04:00
|
|
|
{
|
|
|
|
std::pair<cmStdString, std::vector<cmStdString> > dp;
|
2006-04-05 19:05:06 +04:00
|
|
|
dp.first = dir;
|
2006-04-04 19:52:00 +04:00
|
|
|
this->DirectoryToAfterList.push_back(dp);
|
2006-04-05 19:05:06 +04:00
|
|
|
this->LinkPathSet.insert(dir);
|
2006-04-04 19:52:00 +04:00
|
|
|
}
|
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
|
|
|
}
|
2006-04-04 22:25:17 +04:00
|
|
|
|
|
|
|
// Construct a set of files that will exist after building.
|
|
|
|
for(cmTargetManifest::const_iterator i = manifest.begin();
|
|
|
|
i != manifest.end(); ++i)
|
|
|
|
{
|
|
|
|
for(cmTargetSet::const_iterator j = i->second.begin();
|
|
|
|
j != i->second.end(); ++j)
|
|
|
|
{
|
|
|
|
this->ManifestFiles.insert(*j);
|
|
|
|
}
|
|
|
|
}
|
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-09-15 22:09:10 +04:00
|
|
|
#ifdef CM_ORDER_LINK_DIRECTORIES_DEBUG
|
|
|
|
fprintf(stderr, "Raw link item [%s]\n", this->RawLinkItems[i].c_str());
|
|
|
|
#endif
|
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
|
|
|
|
{
|
2006-05-12 21:39:34 +04:00
|
|
|
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];
|
2006-05-12 21:39:34 +04:00
|
|
|
message +=
|
|
|
|
". Expected a library name or a full path to a library name.";
|
2005-12-26 21:14:19 +03:00
|
|
|
cmSystemTools::Message(message.c_str());
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(!framework)
|
|
|
|
{
|
2006-04-05 19:05:06 +04:00
|
|
|
dir = cmSystemTools::GetFilenamePath(this->RawLinkItems[i]);
|
|
|
|
file = cmSystemTools::GetFilenameName(this->RawLinkItems[i]);
|
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-04-04 19:52:00 +04:00
|
|
|
if(this->DirectoryToAfterListEmitted.insert(dir).second)
|
|
|
|
{
|
|
|
|
std::pair<cmStdString, std::vector<cmStdString> > dp;
|
|
|
|
dp.first = dir;
|
|
|
|
this->DirectoryToAfterList.push_back(dp);
|
|
|
|
}
|
2006-03-15 19:02:08 +03:00
|
|
|
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;
|
2006-09-15 22:09:10 +04:00
|
|
|
#ifdef CM_ORDER_LINK_DIRECTORIES_DEBUG
|
|
|
|
fprintf(stderr, "Storing item [%s]\n", file.c_str());
|
|
|
|
#endif
|
2006-03-15 19:02:08 +03:00
|
|
|
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-05-12 21:39:34 +04:00
|
|
|
this->LibraryToDirectories.begin();
|
|
|
|
lib!= this->LibraryToDirectories.end();
|
2005-02-24 21:16:41 +03:00
|
|
|
++lib)
|
|
|
|
{
|
|
|
|
if(lib->second.size() > 0)
|
|
|
|
{
|
2006-05-12 21:39:34 +04:00
|
|
|
this->MultiDirectoryLibraries.push_back
|
|
|
|
(this->FullPathLibraries[lib->first]);
|
2005-02-24 21:16:41 +03:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2006-05-12 21:39:34 +04: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);
|
2006-05-12 21:39:34 +04:00
|
|
|
this->PrintVector("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()
|
|
|
|
{
|
2006-05-12 21:39:34 +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.\nDirectories 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
|
|
|
}
|
|
|
|
}
|
2006-04-04 19:52:00 +04:00
|
|
|
//-------------------------------------------------------------------
|
|
|
|
void
|
|
|
|
cmOrderLinkDirectories::PrintVector(const char* name,
|
|
|
|
std::vector<std::pair<cmStdString,
|
|
|
|
std::vector<cmStdString> > >& m)
|
|
|
|
{
|
|
|
|
std::cout << name << "\n";
|
2006-05-12 21:39:34 +04:00
|
|
|
for(std::vector<std::pair<cmStdString, std::vector<cmStdString> >
|
|
|
|
>::iterator i = m.begin(); i != m.end(); ++i)
|
2006-04-04 19:52:00 +04:00
|
|
|
{
|
|
|
|
std::cout << i->first << ": ";
|
|
|
|
for(std::vector<cmStdString>::iterator l = i->second.begin();
|
|
|
|
l != i->second.end(); ++l)
|
|
|
|
{
|
|
|
|
std::cout << *l << " ";
|
|
|
|
}
|
|
|
|
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-05-12 21:39:34 +04:00
|
|
|
for(std::map<cmStdString, Library>::iterator i =
|
|
|
|
this->FullPathLibraries.begin();
|
2006-03-15 19:02:08 +03:00
|
|
|
i != this->FullPathLibraries.end(); ++i)
|
2005-02-26 01:45:12 +03:00
|
|
|
{
|
|
|
|
libs.push_back(i->first);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
2006-04-04 22:25:17 +04:00
|
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
bool cmOrderLinkDirectories::LibraryMayConflict(const char* desiredLib,
|
|
|
|
const char* dir,
|
|
|
|
const char* fname)
|
|
|
|
{
|
|
|
|
// We need to check whether the given file may be picked up by the
|
|
|
|
// linker. This will occur if it exists as given or may be built
|
|
|
|
// using the name given.
|
|
|
|
bool found = false;
|
|
|
|
std::string path = dir;
|
|
|
|
path += "/";
|
|
|
|
path += fname;
|
|
|
|
if(this->ManifestFiles.find(path) != this->ManifestFiles.end())
|
|
|
|
{
|
|
|
|
found = true;
|
|
|
|
}
|
|
|
|
else if(cmSystemTools::FileExists(path.c_str()))
|
|
|
|
{
|
|
|
|
found = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// When linking with a multi-configuration build tool the
|
|
|
|
// per-configuration subdirectory is added to each link path. Check
|
|
|
|
// this subdirectory too.
|
|
|
|
if(!found && !this->ConfigSubdir.empty())
|
|
|
|
{
|
|
|
|
path = dir;
|
|
|
|
path += "/";
|
|
|
|
path += this->ConfigSubdir;
|
|
|
|
path += "/";
|
|
|
|
path += fname;
|
|
|
|
if(this->ManifestFiles.find(path) != this->ManifestFiles.end())
|
|
|
|
{
|
|
|
|
found = true;
|
|
|
|
}
|
|
|
|
else if(cmSystemTools::FileExists(path.c_str()))
|
|
|
|
{
|
|
|
|
found = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// A library conflicts if it is found and is not a symlink back to
|
|
|
|
// the desired library.
|
|
|
|
if(found)
|
|
|
|
{
|
|
|
|
return !cmSystemTools::SameFile(desiredLib, path.c_str());
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|