ENH: add better support for framework linking

This commit is contained in:
Bill Hoffman 2005-12-26 13:14:19 -05:00
parent 102ab85a17
commit 452925649a
12 changed files with 137 additions and 20 deletions

View File

@ -1545,7 +1545,7 @@ void cmGlobalXCodeGenerator::AddLinkLibrary(cmXCodeObject* target,
// if the library is not a full path then add it with a -l flag
// to the settings of the target
cmsys::RegularExpression reg("^([ \t]*\\-[lLWRB])|([ \t]*\\-framework)|(\\${)|([ \t]*\\-pthread)|([ \t]*`)");
cmsys::RegularExpression reg("^([ \t]*\\-[lLWRBF])|([ \t]*\\-framework)|(\\${)|([ \t]*\\-pthread)|([ \t]*`)");
// if the library is not already in the form required by the compiler
// add a -l infront of the name
std::string link;

View File

@ -1411,7 +1411,7 @@ void cmLocalGenerator::OutputLinkLibraries(std::ostream& fout,
{
cmStdString& linkItem = *lib;
// check to see if the link item has a -l already
cmsys::RegularExpression reg("^([ \t]*\\-[lLWRB])|([ \t]*\\-framework)|(\\${)|([ \t]*\\-pthread)|([ \t]*`)");
cmsys::RegularExpression reg("^([ \t]*\\-[lLWRBF])|([ \t]*\\-framework)|(\\${)|([ \t]*\\-pthread)|([ \t]*`)");
if(!reg.find(linkItem))
{
librariesLinked += libLinkFlag;

View File

@ -445,6 +445,9 @@ cmLocalUnixMakefileGenerator3
// Add include directory flags.
this->AppendFlags(flags, this->GetIncludeFlags(lang));
// Add include directory flags.
this->AppendFlags(flags, this->GetFrameworkFlags(target).c_str());
flagFileStream << lang << "_FLAGS = " << flags
<< "\n"
<< "\n";
@ -498,6 +501,27 @@ cmLocalUnixMakefileGenerator3
this->WriteTargetCleanRule(ruleFileStream, target, cleanFiles);
}
//----------------------------------------------------------------------------
std::string
cmLocalUnixMakefileGenerator3
::GetFrameworkFlags(cmTarget& target)
{
#ifndef __APPLE__
return std::string();
#else
std::string flags;
std::vector<std::string>& frameworks = target.GetFrameworks();
for(std::vector<std::string>::iterator i = frameworks.begin();
i != frameworks.end(); ++i)
{
flags += "-F";
flags += this->ConvertToOutputForExisting(i->c_str());
flags += " ";
}
return flags;
#endif
}
//----------------------------------------------------------------------------
void
cmLocalUnixMakefileGenerator3

View File

@ -171,6 +171,8 @@ public:
void WriteLocalAllRules(std::ostream& ruleFileStream);
protected:
// Return the a string with -F flags on apple
std::string GetFrameworkFlags(cmTarget&);
// write the depend info
void WriteDependLanguageInfo(std::ostream& cmakefileStream, cmTarget &tgt);

View File

@ -2215,6 +2215,11 @@ std::string cmMakefile::FindLibrary(const char* name,
cmSystemTools::GetPath(path, "CMAKE_LIBRARY_PATH");
cmSystemTools::GetPath(path, "LIB");
cmSystemTools::GetPath(path);
bool supportFrameworks = false;
if(this->GetDefinition("APPLE"))
{
supportFrameworks = true;
}
// now add the path
path.insert(path.end(), userPaths.begin(), userPaths.end());
// Add some lib directories specific to compilers, depending on the
@ -2270,6 +2275,13 @@ std::string cmMakefile::FindLibrary(const char* name,
path.push_back(lib_path);
}
}
else if(supportFrameworks)
{
path.push_back("~/Library/Frameworks");
path.push_back("/Library/Frameworks");
path.push_back("/System/Library/Frameworks");
path.push_back("/Network/Library/Frameworks");
}
}
if(m_LocalGenerator->GetGlobalGenerator()->GetLanguageEnabled("C"))
{

View File

@ -104,6 +104,7 @@ std::string cmOrderLinkDirectories::NoCaseExpression(const char* str)
//-------------------------------------------------------------------
void cmOrderLinkDirectories::CreateRegularExpressions()
{
m_SplitFramework.compile("(.*)/(.*)\\.framework$");
cmStdString libext = "(";
bool first = true;
for(std::vector<cmStdString>::iterator i = m_LinkExtensions.begin();
@ -278,29 +279,53 @@ bool cmOrderLinkDirectories::DetermineLibraryPathOrder()
cmStdString dir;
cmStdString file;
std::vector<cmStdString> empty;
bool framework = false;
for(unsigned int i=0; i < m_RawLinkItems.size(); ++i)
{
if(cmSystemTools::FileIsFullPath(m_RawLinkItems[i].c_str()))
{
if(cmSystemTools::FileIsDirectory(m_RawLinkItems[i].c_str()))
{
std::string message = "Warning: Ignoring path found in link libraries for target: ";
message += m_TargetName;
message += ", path is: ";
message += m_RawLinkItems[i];
message += ". Expected a library name or a full path to a library name.";
cmSystemTools::Message(message.c_str());
continue;
if(cmSystemTools::IsPathToFramework(m_RawLinkItems[i].c_str()))
{
m_SplitFramework.find(m_RawLinkItems[i]);
cmStdString path = m_SplitFramework.match(1);
// Add the -F path if we have not yet done so
if(m_EmittedFrameworkPaths.insert(path).second)
{
std::string fpath = "-F";
fpath += cmSystemTools::ConvertToOutputPath(path.c_str());
m_LinkItems.push_back(fpath);
}
// now add the -framework option
std::string frame = "-framework ";
frame += m_SplitFramework.match(2);
m_LinkItems.push_back(frame);
framework = true;
}
else
{
std::string message = "Warning: Ignoring path found in link libraries for target: ";
message += m_TargetName;
message += ", path is: ";
message += m_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(m_RawLinkItems[i].c_str(),
dir, file);
m_DirectoryToAfterList[dir] = empty;
m_LinkPathSet.insert(dir);
aLib.FullPath = m_RawLinkItems[i];
aLib.File = file;
aLib.Path = dir;
m_FullPathLibraries[aLib.FullPath] = aLib;
m_LinkItems.push_back(file);
}
cmSystemTools::SplitProgramPath(m_RawLinkItems[i].c_str(),
dir, file);
m_DirectoryToAfterList[dir] = empty;
m_LinkPathSet.insert(dir);
aLib.FullPath = m_RawLinkItems[i];
aLib.File = file;
aLib.Path = dir;
m_FullPathLibraries[aLib.FullPath] = aLib;
m_LinkItems.push_back(file);
}
else
{

View File

@ -121,6 +121,8 @@ private:
std::vector<cmStdString> m_RawLinkItems;
// This vector holds the sorted -L paths
std::vector<cmStdString> m_SortedSearchPaths;
// This vector holds the -F paths
std::set<cmStdString> m_EmittedFrameworkPaths;
// This is the set of -L paths unsorted, but unique
std::set<cmStdString> m_LinkPathSet;
// the names of link extensions
@ -135,6 +137,7 @@ private:
cmsys::RegularExpression m_RemoveLibraryExtension;
cmsys::RegularExpression m_ExtractBaseLibraryName;
cmsys::RegularExpression m_ExtractBaseLibraryNameNoPrefix;
cmsys::RegularExpression m_SplitFramework;
bool m_Debug;
};

View File

@ -1345,3 +1345,16 @@ bool cmSystemTools::PutEnv(const char* value)
localEnvironment.push_back(envVar);
return ret == 0;
}
bool cmSystemTools::IsPathToFramework(const char* path)
{
if(cmSystemTools::FileIsFullPath(path))
{
std::string libname = path;
if(libname.find(".framework") == libname.size()+1-sizeof(".framework"))
{
return true;
}
}
return false;
}

View File

@ -131,6 +131,8 @@ public:
///! Return true if value is NOTFOUND or ends in -NOTFOUND.
static bool IsNOTFOUND(const char* value);
///! Return true if the path is a framework
static bool IsPathToFramework(const char* value);
static bool DoesFileExistWithExtensions(
const char *name,

View File

@ -301,9 +301,28 @@ void cmTarget::ClearDependencyInformation( cmMakefile& mf, const char* target )
void cmTarget::AddLinkLibrary(const std::string& lib,
LinkLibraryType llt)
{
this->AddFramework(lib.c_str(), llt);
m_LinkLibraries.push_back( std::pair<std::string, cmTarget::LinkLibraryType>(lib,llt) );
}
bool cmTarget::AddFramework(const std::string& libname, LinkLibraryType llt)
{
if(cmSystemTools::IsPathToFramework(libname.c_str()))
{
std::string frameworkDir = libname;
frameworkDir += "/../";
frameworkDir = cmSystemTools::CollapseFullPath(frameworkDir.c_str());
std::vector<std::string>::iterator i =
std::find(m_Frameworks.begin(),
m_Frameworks.end(), frameworkDir);
if(i == m_Frameworks.end())
{
m_Frameworks.push_back(frameworkDir);
}
return true;
}
return false;
}
void cmTarget::AddLinkLibrary(cmMakefile& mf,
const char *target, const char* lib,
LinkLibraryType llt)
@ -313,7 +332,7 @@ void cmTarget::AddLinkLibrary(cmMakefile& mf,
{
return;
}
this->AddFramework(lib, llt);
m_LinkLibraries.push_back( std::pair<std::string, cmTarget::LinkLibraryType>(lib,llt) );
if(llt != cmTarget::GENERAL)

View File

@ -80,6 +80,9 @@ public:
*/
std::vector<std::string> &GetSourceLists() {return m_SourceLists;}
///! Return the list of frameworks being linked to this target
std::vector<std::string> &GetFrameworks() {return m_Frameworks;}
/**
* Get the list of the source files used by this target
*/
@ -97,6 +100,8 @@ public:
*/
void ClearDependencyInformation(cmMakefile& mf, const char* target);
// Check to see if a library is a framework and treat it different on Mac
bool AddFramework(const std::string& lib, LinkLibraryType llt);
void AddLinkLibrary(cmMakefile& mf,
const char *target, const char* lib,
LinkLibraryType llt);
@ -276,6 +281,7 @@ private:
std::vector<cmSourceFile*> m_SourceFiles;
LinkLibraries m_LinkLibraries;
LinkLibraries m_PrevLinkedLibraries;
std::vector<std::string> m_Frameworks;
std::vector<std::string> m_LinkDirectories;
std::string m_InstallPath;
std::string m_RuntimeInstallPath;

View File

@ -1992,6 +1992,17 @@ kwsys_stl::string SystemTools
for(kwsys_stl::vector<kwsys_stl::string>::const_iterator p = path.begin();
p != path.end(); ++p)
{
#if defined(__APPLE__)
tryPath = *p;
tryPath += "/";
tryPath += name;
tryPath += ".framework";
if(SystemTools::FileExists(tryPath.c_str())
&& SystemTools::FileIsDirectory(tryPath.c_str()))
{
return SystemTools::CollapseFullPath(tryPath.c_str());
}
#endif
#if defined(_WIN32) && !defined(__CYGWIN__) && !defined(__MINGW32__)
tryPath = *p;
tryPath += "/";