diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index 8225a7293..43c47f8f4 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -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; diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index 57e0eea2b..b0066b055 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -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; diff --git a/Source/cmLocalUnixMakefileGenerator3.cxx b/Source/cmLocalUnixMakefileGenerator3.cxx index 482854de5..f446bc784 100644 --- a/Source/cmLocalUnixMakefileGenerator3.cxx +++ b/Source/cmLocalUnixMakefileGenerator3.cxx @@ -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& frameworks = target.GetFrameworks(); + for(std::vector::iterator i = frameworks.begin(); + i != frameworks.end(); ++i) + { + flags += "-F"; + flags += this->ConvertToOutputForExisting(i->c_str()); + flags += " "; + } + return flags; +#endif +} + //---------------------------------------------------------------------------- void cmLocalUnixMakefileGenerator3 diff --git a/Source/cmLocalUnixMakefileGenerator3.h b/Source/cmLocalUnixMakefileGenerator3.h index 7288ed384..247efe8b6 100644 --- a/Source/cmLocalUnixMakefileGenerator3.h +++ b/Source/cmLocalUnixMakefileGenerator3.h @@ -171,7 +171,9 @@ 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); diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index 6cf43293d..ae8c11669 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -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")) { diff --git a/Source/cmOrderLinkDirectories.cxx b/Source/cmOrderLinkDirectories.cxx index 94b6160e2..bfcd0735f 100644 --- a/Source/cmOrderLinkDirectories.cxx +++ b/Source/cmOrderLinkDirectories.cxx @@ -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::iterator i = m_LinkExtensions.begin(); @@ -278,29 +279,53 @@ bool cmOrderLinkDirectories::DetermineLibraryPathOrder() cmStdString dir; cmStdString file; std::vector 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 { diff --git a/Source/cmOrderLinkDirectories.h b/Source/cmOrderLinkDirectories.h index b70dcf826..49830b545 100644 --- a/Source/cmOrderLinkDirectories.h +++ b/Source/cmOrderLinkDirectories.h @@ -121,6 +121,8 @@ private: std::vector m_RawLinkItems; // This vector holds the sorted -L paths std::vector m_SortedSearchPaths; + // This vector holds the -F paths + std::set m_EmittedFrameworkPaths; // This is the set of -L paths unsorted, but unique std::set 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; }; diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx index 623a0f917..e2df4b25b 100644 --- a/Source/cmSystemTools.cxx +++ b/Source/cmSystemTools.cxx @@ -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; +} diff --git a/Source/cmSystemTools.h b/Source/cmSystemTools.h index edee40b7d..c647469ed 100644 --- a/Source/cmSystemTools.h +++ b/Source/cmSystemTools.h @@ -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, diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index 70a44c2e3..2960749b7 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -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(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::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(lib,llt) ); if(llt != cmTarget::GENERAL) diff --git a/Source/cmTarget.h b/Source/cmTarget.h index 56ee49751..630367de3 100644 --- a/Source/cmTarget.h +++ b/Source/cmTarget.h @@ -79,6 +79,9 @@ public: * Get the list of the source lists used by this target */ std::vector &GetSourceLists() {return m_SourceLists;} + + ///! Return the list of frameworks being linked to this target + std::vector &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 m_SourceFiles; LinkLibraries m_LinkLibraries; LinkLibraries m_PrevLinkedLibraries; + std::vector m_Frameworks; std::vector m_LinkDirectories; std::string m_InstallPath; std::string m_RuntimeInstallPath; diff --git a/Source/kwsys/SystemTools.cxx b/Source/kwsys/SystemTools.cxx index 5d34ac508..e406723d5 100644 --- a/Source/kwsys/SystemTools.cxx +++ b/Source/kwsys/SystemTools.cxx @@ -1992,6 +1992,17 @@ kwsys_stl::string SystemTools for(kwsys_stl::vector::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 += "/";