| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530 | 
							- #include "cmOrderLinkDirectories.h"
 
- #include "cmSystemTools.h"
 
- #include "cmsys/RegularExpression.hxx"
 
- #include <ctype.h>
 
- //-------------------------------------------------------------------
 
- cmOrderLinkDirectories::cmOrderLinkDirectories()
 
- {
 
-   this->Debug = false;
 
- }
 
- //-------------------------------------------------------------------
 
- bool cmOrderLinkDirectories::LibraryInDirectory(const char* desiredLib,
 
-                                                 const char* dir,
 
-                                                 const char* libIn)
 
- {
 
-   // first look for the library as given
 
-   if(this->LibraryMayConflict(desiredLib, dir, libIn))
 
-     {
 
-     return true;
 
-     }
 
-   // next remove the extension (.a, .so ) and look for the library
 
-   // under a different name as the linker can do either
 
-   if(this->RemoveLibraryExtension.find(libIn))
 
-     {
 
-     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)
 
-       {
 
-       if(ext != *i)
 
-         {
 
-         std::string fname = lib;
 
-         lib += *i;
 
-         if(this->LibraryMayConflict(desiredLib, dir, fname.c_str()))
 
-           {
 
-           return true;
 
-           } 
 
-         }
 
-       }
 
-     }
 
-   return false;
 
- }
 
- //-------------------------------------------------------------------
 
- void cmOrderLinkDirectories::FindLibrariesInSearchPaths()
 
- {
 
-   for(std::set<cmStdString>::iterator dir = this->LinkPathSet.begin();
 
-       dir != this->LinkPathSet.end(); ++dir)
 
-     {
 
-     for(std::map<cmStdString, Library>::iterator lib
 
-           = this->FullPathLibraries.begin();
 
-         lib != this->FullPathLibraries.end(); ++lib)
 
-       {
 
-       if(lib->second.Path != *dir)
 
-         {
 
-         if(this->LibraryInDirectory(lib->second.FullPath.c_str(),
 
-                                     dir->c_str(), lib->second.File.c_str()))
 
-           {
 
-           this->LibraryToDirectories[lib->second.FullPath].push_back(*dir);
 
-           }
 
-         }
 
-       }
 
-     }
 
- }
 
-                  
 
- //-------------------------------------------------------------------
 
- void cmOrderLinkDirectories::FindIndividualLibraryOrders()
 
- {
 
-   for(std::vector<Library>::iterator lib = this->MultiDirectoryLibraries.begin();
 
-       lib != this->MultiDirectoryLibraries.end(); ++lib)
 
-     {
 
-     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)
 
-       {
 
-       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);
 
-         }
 
-       }
 
-     }
 
- }
 
- //-------------------------------------------------------------------
 
- 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;
 
- }
 
-     
 
- //-------------------------------------------------------------------
 
- void cmOrderLinkDirectories::CreateRegularExpressions()
 
- {
 
-   this->SplitFramework.compile("(.*)/(.*)\\.framework$");
 
-   cmStdString libext = "(";
 
-   bool first = true;
 
-   for(std::vector<cmStdString>::iterator i = this->LinkExtensions.begin();
 
-       i != this->LinkExtensions.end(); ++i)
 
-     {
 
-     if(!first)
 
-       {
 
-       libext += "|";
 
-       }
 
-     first = false;
 
-     libext += "\\";
 
- #if defined(_WIN32) && !defined(__CYGWIN__)
 
-     libext += this->NoCaseExpression(i->c_str());
 
- #else
 
-     libext += *i;
 
- #endif
 
-     }
 
-   libext += ").*";
 
-   cmStdString reg("(.*)");
 
-   reg += libext;
 
-   this->RemoveLibraryExtension.compile(reg.c_str());
 
-   reg = "";
 
-   if(this->LinkPrefix.size())
 
-     {
 
-     reg = "^";
 
-     reg += this->LinkPrefix;
 
-     }
 
-   reg += "([^/]*)";
 
-   reg += libext;
 
-   this->ExtractBaseLibraryName.compile(reg.c_str());
 
-   reg = "([^/]*)";
 
-   reg += libext;
 
-   this->ExtractBaseLibraryNameNoPrefix.compile(reg.c_str());
 
- }
 
- //-------------------------------------------------------------------
 
- void cmOrderLinkDirectories::PrepareLinkTargets()
 
- {
 
-   for(std::vector<cmStdString>::iterator i = this->LinkItems.begin();
 
-       i != this->LinkItems.end(); ++i)
 
-     {
 
-     // separate the library name from libfoo.a or foo.a
 
-     if(this->ExtractBaseLibraryName.find(*i))
 
-       {
 
-       *i = this->ExtractBaseLibraryName.match(1);
 
-       }
 
-     else if(this->ExtractBaseLibraryNameNoPrefix.find(*i))
 
-       {
 
-       *i = this->ExtractBaseLibraryNameNoPrefix.match(1);
 
-       }
 
-     }
 
- }
 
- //-------------------------------------------------------------------
 
- bool cmOrderLinkDirectories::FindPathNotInDirectoryToAfterList(
 
-   cmStdString& path)
 
- {   
 
-   for(std::vector<std::pair<cmStdString, std::vector<cmStdString> > >::iterator i
 
-         = this->DirectoryToAfterList.begin();
 
-       i != this->DirectoryToAfterList.end(); ++i)
 
-     {
 
-     const cmStdString& p = i->first;
 
-     bool found = false;
 
-     for(std::vector<std::pair<cmStdString, std::vector<cmStdString> > >::iterator j 
 
-           = this->DirectoryToAfterList.begin(); j != this->DirectoryToAfterList.end() 
 
-           && !found; ++j)
 
-       {
 
-       if(j != i)
 
-         {
 
-         found = (std::find(j->second.begin(), j->second.end(), p) != j->second.end());
 
-         }
 
-       }
 
-     if(!found)
 
-       {
 
-       path = p;
 
-       this->DirectoryToAfterList.erase(i);
 
-       return true;
 
-       }
 
-     }
 
-   path = "";
 
-   return false;
 
- }
 
- //-------------------------------------------------------------------
 
- void cmOrderLinkDirectories::OrderPaths(std::vector<cmStdString>&
 
-                                         orderedPaths)
 
- {
 
-   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
 
-   // this->DirectoryToAfterList once it is found
 
-   while(this->FindPathNotInDirectoryToAfterList(path))
 
-     {
 
-     orderedPaths.push_back(path);
 
-     }
 
-   // at this point if there are still paths in this->DirectoryToAfterList
 
-   // then there is a cycle and we are stuck
 
-   if(this->DirectoryToAfterList.size())
 
-     {
 
-     for(std::vector<std::pair<cmStdString, std::vector<cmStdString> > >::iterator i
 
-           = this->DirectoryToAfterList.begin();
 
-         i != this->DirectoryToAfterList.end(); ++i)
 
-       {
 
-       this->ImpossibleDirectories.insert(i->first);
 
-       // still put it in the path list in the order we find them
 
-       orderedPaths.push_back(i->first);
 
-       }
 
-     
 
-     }
 
- }
 
- //-------------------------------------------------------------------
 
- void cmOrderLinkDirectories::SetLinkInformation(
 
-   const char* targetName,
 
-   const std::vector<std::string>& linkLibraries,
 
-   const std::vector<std::string>& linkDirectories,
 
-   const cmTargetManifest& manifest,
 
-   const char* configSubdir
 
-   )
 
- {
 
-   // Save the target name.
 
-   this->TargetName = targetName;
 
-   // Save the subdirectory used for linking in this configuration.
 
-   this->ConfigSubdir = configSubdir? configSubdir : "";
 
-   // Merge the link directory search path given into our path set.
 
-   std::vector<cmStdString> empty;
 
-   for(std::vector<std::string>::const_iterator p = linkDirectories.begin();
 
-       p != linkDirectories.end(); ++p)
 
-     {
 
-     if(this->DirectoryToAfterListEmitted.insert(*p).second)
 
-       {
 
-       std::pair<cmStdString, std::vector<cmStdString> > dp;
 
-       dp.first = *p;
 
-       this->DirectoryToAfterList.push_back(dp);
 
-       this->LinkPathSet.insert(*p);
 
-       }
 
-     }
 
-   // Append the link library list into our raw list.
 
-   for(std::vector<std::string>::const_iterator l = linkLibraries.begin();
 
-       l != linkLibraries.end(); ++l)
 
-     {
 
-     this->RawLinkItems.push_back(*l);
 
-     }
 
-   // 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);
 
-       }
 
-     }
 
- }
 
- //-------------------------------------------------------------------
 
- 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;
 
-   std::vector<cmStdString> empty;
 
-   // do not add a -F for the system frameworks
 
-   this->EmittedFrameworkPaths.insert("/System/Library/Frameworks");
 
-   for(unsigned int i=0; i < this->RawLinkItems.size(); ++i)
 
-     {
 
-     bool framework = false;
 
-     if(cmSystemTools::FileIsFullPath(this->RawLinkItems[i].c_str()))
 
-       {
 
-       if(cmSystemTools::FileIsDirectory(this->RawLinkItems[i].c_str()))
 
-         {
 
-         if(cmSystemTools::IsPathToFramework(this->RawLinkItems[i].c_str()))
 
-           {
 
-           this->SplitFramework.find(this->RawLinkItems[i]);
 
-           cmStdString path = this->SplitFramework.match(1);
 
-           // Add the -F path if we have not yet done so
 
-           if(this->EmittedFrameworkPaths.insert(path).second)
 
-             {
 
-             std::string fpath = "-F";
 
-             fpath += cmSystemTools::ConvertToOutputPath(path.c_str());
 
-             this->LinkItems.push_back(fpath);
 
-             }
 
-           // now add the -framework option
 
-           std::string frame = "-framework ";
 
-           frame += this->SplitFramework.match(2);
 
-           this->LinkItems.push_back(frame);
 
-           framework = true;
 
-           }
 
-         else
 
-           {
 
-           std::string message = "Warning: Ignoring path found in link libraries for target: ";
 
-           message += this->TargetName;
 
-           message += ", path is: ";
 
-           message += this->RawLinkItems[i];
 
-           message += ". Expected a library name or a full path to a library name.";
 
-           cmSystemTools::Message(message.c_str());
 
-           continue;
 
-           }
 
-         }
 
-       if(!framework)
 
-         {
 
-         cmSystemTools::SplitProgramPath(this->RawLinkItems[i].c_str(),
 
-                                         dir, file);
 
- #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
 
-         if(this->DirectoryToAfterListEmitted.insert(dir).second)
 
-           {
 
-           std::pair<cmStdString, std::vector<cmStdString> > dp;
 
-           dp.first = dir;
 
-           this->DirectoryToAfterList.push_back(dp);
 
-           }
 
-         this->LinkPathSet.insert(dir);
 
-         aLib.FullPath = this->RawLinkItems[i];
 
-         aLib.File = file;
 
-         aLib.Path = dir;
 
-         this->FullPathLibraries[aLib.FullPath] = aLib;
 
-         this->LinkItems.push_back(file);
 
-         }
 
-       }
 
-     else
 
-       {
 
-       this->LinkItems.push_back(this->RawLinkItems[i]);
 
-       }
 
-     }
 
-   this->FindLibrariesInSearchPaths();
 
-   for(std::map<cmStdString, std::vector<cmStdString> >::iterator lib =
 
-         this->LibraryToDirectories.begin(); lib!= this->LibraryToDirectories.end(); 
 
-       ++lib)
 
-     {
 
-     if(lib->second.size() > 0)
 
-       {
 
-       this->MultiDirectoryLibraries.push_back(this->FullPathLibraries[lib->first]);
 
-       }
 
-     else
 
-       {
 
-       this->SingleDirectoryLibraries.push_back(this->FullPathLibraries[lib->first]);
 
-       }
 
-     }
 
-   this->FindIndividualLibraryOrders();
 
-   this->SortedSearchPaths.clear();
 
-   if(this->Debug)
 
-     {
 
-     this->PrintMap("this->LibraryToDirectories", this->LibraryToDirectories);
 
-     this->PrintVector("this->DirectoryToAfterList", this->DirectoryToAfterList);
 
-     }
 
-   this->OrderPaths(this->SortedSearchPaths); 
 
-   // now turn libfoo.a into foo and foo.a into foo
 
-   // This will prepare the link items for -litem 
 
-   this->PrepareLinkTargets();
 
-   if(this->ImpossibleDirectories.size())
 
-     {
 
-     cmSystemTools::Message(this->GetWarnings().c_str());
 
-     return false;
 
-     }
 
-   return true;
 
- }
 
- std::string cmOrderLinkDirectories::GetWarnings()
 
- {
 
-   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";
 
-   for(std::set<cmStdString>::iterator i = this->ImpossibleDirectories.begin();
 
-       i != this->ImpossibleDirectories.end(); ++i)
 
-     {
 
-     warning += "Directory: ";
 
-     warning += *i;
 
-     warning += " contains:\n";
 
-     std::map<cmStdString, std::vector<cmStdString> >::iterator j;
 
-     for(j = this->LibraryToDirectories.begin(); 
 
-         j != this->LibraryToDirectories.end(); ++j)
 
-       {
 
-       if(std::find(j->second.begin(), j->second.end(), *i)
 
-          != j->second.end())
 
-         {
 
-         warning += "Library: ";
 
-         warning += j->first;
 
-         warning += "\n";
 
-         }
 
-       }
 
-     warning += "\n";
 
-     }
 
-   warning += "\n";
 
-   return warning;
 
- }
 
- //-------------------------------------------------------------------
 
- void
 
- cmOrderLinkDirectories::PrintMap(const char* name,
 
-                        std::map<cmStdString, std::vector<cmStdString> >& m)
 
- {
 
-   std::cout << name << "\n";
 
-   for(std::map<cmStdString, std::vector<cmStdString> >::iterator i =
 
-         m.begin(); i != m.end();
 
-       ++i)
 
-     {
 
-     std::cout << i->first << ":  ";
 
-     for(std::vector<cmStdString>::iterator l = i->second.begin();
 
-         l != i->second.end(); ++l)
 
-       {
 
-       std::cout << *l << " ";
 
-       }
 
-     std::cout << "\n";
 
-     }
 
- }
 
- //-------------------------------------------------------------------
 
- void
 
- cmOrderLinkDirectories::PrintVector(const char* name,
 
-                                     std::vector<std::pair<cmStdString, 
 
-                                     std::vector<cmStdString> > >& m)
 
- {
 
-   std::cout << name << "\n";
 
-   for(std::vector<std::pair<cmStdString, std::vector<cmStdString> > >::iterator i =
 
-         m.begin(); i != m.end();
 
-       ++i)
 
-     {
 
-     std::cout << i->first << ":  ";
 
-     for(std::vector<cmStdString>::iterator l = i->second.begin();
 
-         l != i->second.end(); ++l)
 
-       {
 
-       std::cout << *l << " ";
 
-       }
 
-     std::cout << "\n";
 
-     }
 
- }
 
- void cmOrderLinkDirectories::GetFullPathLibraries(std::vector<cmStdString>& 
 
-                                                   libs)
 
- {
 
-   for(std::map<cmStdString, Library>::iterator i = this->FullPathLibraries.begin();
 
-       i != this->FullPathLibraries.end(); ++i)
 
-     {
 
-     libs.push_back(i->first);
 
-     }
 
-   
 
- }
 
- //----------------------------------------------------------------------------
 
- 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;
 
- }
 
 
  |