ENH: Implement linking with paths to library files instead of -L and -l separation. See bug #3832

- This is purely an implementation improvement.  No interface has changed.
  - Create cmComputeLinkInformation class
  - Move and re-implement logic from:
      cmLocalGenerator::ComputeLinkInformation
      cmOrderLinkDirectories
  - Link libraries to targets with their full path (if it is known)
  - Dirs specified with link_directories command still added with -L
  - Make link type specific to library names without paths
    (name libfoo.a without path becomes -Wl,-Bstatic -lfoo)
  - Make directory ordering specific to a runtime path computation feature
    (look for conflicting SONAMEs instead of library names)
  - Implement proper rpath support on HP-UX and AIX.
This commit is contained in:
Brad King
2008-01-22 09:13:04 -05:00
parent 0df9e6904c
commit 96fd5909d9
25 changed files with 1781 additions and 1790 deletions

View File

@@ -13,7 +13,6 @@ extern "C" {
#include "cmSystemTools.h"
#include "cmDynamicLoader.h"
#include "cmSystemTools.h"
#include "cmOrderLinkDirectories.h"
#include "cmGeneratedFileStream.h"
#include <cmsys/DynamicLoader.hxx>
#else
@@ -69,99 +68,6 @@ void cmPassed(const char* Message, const char* m2="")
#endif
#ifdef COMPLEX_TEST_CMAKELIB
// Here is a stupid function that tries to use std::string methods
// so that the dec cxx compiler will instantiate the stuff that
// we are using from the CMakeLib library....
bool TestLibraryOrder(bool shouldFail)
{
std::string Adir = std::string(BINARY_DIR) + std::string("/A");
std::string Bdir = std::string(BINARY_DIR) + std::string("/B");
std::string Cdir = std::string(BINARY_DIR) + std::string("/C");
#ifdef _WIN32
// Avoid case problems for windows paths.
if(Adir[0] >= 'A' && Adir[0] <= 'Z') { Adir[0] += 'a' - 'A'; }
if(Bdir[0] >= 'A' && Bdir[0] <= 'Z') { Bdir[0] += 'a' - 'A'; }
if(Cdir[0] >= 'A' && Cdir[0] <= 'Z') { Cdir[0] += 'a' - 'A'; }
Adir = cmSystemTools::GetActualCaseForPath(Adir.c_str());
Bdir = cmSystemTools::GetActualCaseForPath(Bdir.c_str());
Cdir = cmSystemTools::GetActualCaseForPath(Cdir.c_str());
#endif
if(!shouldFail)
{
std::string rm = Bdir;
rm += "/libA.a";
cmSystemTools::RemoveFile(rm.c_str());
}
std::vector<std::string> linkLibraries;
std::vector<std::string> linkDirectories;
linkDirectories.push_back(Adir);
linkDirectories.push_back(Bdir);
linkDirectories.push_back(Cdir);
linkDirectories.push_back("/lib/extra/stuff");
Adir += "/libA.a";
Bdir += "/libB.a";
Cdir += "/libC.a";
linkLibraries.push_back(Adir);
linkLibraries.push_back(Bdir);
linkLibraries.push_back(Cdir);
linkLibraries.push_back("-lm");
std::vector<cmStdString> sortedpaths;
std::vector<cmStdString> linkItems;
cmOrderLinkDirectories orderLibs;
orderLibs.DebugOn();
orderLibs.AddLinkExtension(".so");
orderLibs.AddLinkExtension(".a");
orderLibs.AddLinkPrefix("lib");
cmTargetManifest manifest;
orderLibs.SetLinkInformation("test", linkLibraries, linkDirectories,
manifest, "");
bool ret = orderLibs.DetermineLibraryPathOrder();
if(!ret)
{
std::cout << orderLibs.GetWarnings() << "\n";
}
orderLibs.GetLinkerInformation(sortedpaths, linkItems);
std::cout << "Sorted Link Paths:\n";
for(std::vector<cmStdString>::iterator i = sortedpaths.begin();
i != sortedpaths.end(); ++i)
{
std::cout << *i << "\n";
}
std::cout << "Link Items: \n";
for(std::vector<cmStdString>::iterator i = linkItems.begin();
i != linkItems.end(); ++i)
{
std::cout << *i << "\n";
}
if(!(linkItems[0] == "A" &&
linkItems[1] == "B" &&
linkItems[2] == "C" &&
linkItems[3] == "-lm" ))
{
std::cout << "fail because link items should be A B C -lm and the are not\n";
return shouldFail;
}
// if this is not the fail test then the order should be f B C A
if(!shouldFail)
{
char order[5];
order[4] = 0;
for(int i =0; i < 4; ++i)
{
order[i] = sortedpaths[i][sortedpaths[i].size()-1];
}
if(!(strcmp(order, "fBCA") == 0 || strcmp(order, "BCAf") == 0))
{
std::cout << "fail because order should be /lib/extra/stuff B C A and it is not\n";
return false;
}
}
return ret;
}
// ======================================================================
void TestAndRemoveFile(const char* filename)
@@ -286,6 +192,9 @@ void TestCMGeneratedFileSTream()
}
#endif
// Here is a stupid function that tries to use std::string methods
// so that the dec cxx compiler will instantiate the stuff that
// we are using from the CMakeLib library....
void ForceStringUse()
{
std::vector<std::string> v;
@@ -1283,27 +1192,6 @@ int main()
#endif
#ifdef COMPLEX_TEST_CMAKELIB
// first run with shouldFail = true, this will
// run with A B C as set by the CMakeList.txt file.
if(!TestLibraryOrder(true))
{
cmPassed("CMake cmOrderLinkDirectories failed when it should.");
}
else
{
cmFailed("CMake cmOrderLinkDirectories failed to fail when given an impossible set of paths.");
}
// next run with shouldPass = true, this will
// run with B/libA.a removed and should create the order
// B C A
if(TestLibraryOrder(false))
{
cmPassed("CMake cmOrderLinkDirectories worked.");
}
else
{
cmFailed("CMake cmOrderLinkDirectories failed.");
}
// Test the generated file stream.
TestCMGeneratedFileSTream();
#endif