summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBill Hoffman <bill.hoffman@kitware.com>2007-05-08 14:32:54 (GMT)
committerBill Hoffman <bill.hoffman@kitware.com>2007-05-08 14:32:54 (GMT)
commit9323a2798973b3dbe8ca9725f1cb5c8ff6d5900b (patch)
treeadf91f5e20d08609ec5c83ec09376fdc9e168f46
parent96232d405236231e6f4ba858a70621da9066f26c (diff)
downloadCMake-9323a2798973b3dbe8ca9725f1cb5c8ff6d5900b.zip
CMake-9323a2798973b3dbe8ca9725f1cb5c8ff6d5900b.tar.gz
CMake-9323a2798973b3dbe8ca9725f1cb5c8ff6d5900b.tar.bz2
ENH: initial support for creation of frameworks on Mac
-rw-r--r--Modules/MacOSXFrameworkInfo.plist.in28
-rw-r--r--Modules/Platform/Darwin.cmake5
-rw-r--r--Source/cmLocalGenerator.cxx7
-rw-r--r--Source/cmMakefileLibraryTargetGenerator.cxx247
-rw-r--r--Source/cmMakefileLibraryTargetGenerator.h13
-rw-r--r--Source/cmTarget.cxx19
6 files changed, 315 insertions, 4 deletions
diff --git a/Modules/MacOSXFrameworkInfo.plist.in b/Modules/MacOSXFrameworkInfo.plist.in
new file mode 100644
index 0000000..46287aa
--- /dev/null
+++ b/Modules/MacOSXFrameworkInfo.plist.in
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>English</string>
+ <key>CFBundleExecutable</key>
+ <string>${MACOSX_FRAMEWORK_NAME}</string>
+ <key>CFBundleGetInfoString</key>
+ <string>${MACOSX_FRAMEWORK_INFO_STRING}</string>
+ <key>CFBundleIdentifier</key>
+ <string>${MACOSX_FRAMEWORK_IDENTIFIER}</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundlePackageType</key>
+ <string>FMWK</string>
+ <key>CFBundleShortVersionString</key>
+ <string>${MACOSX_FRAMEWORK_SHORT_VERSION_STRING}</string>
+ <key>CFBundleSignature</key>
+ <string>????</string>
+ <key>CFBundleVersion</key>
+ <string>${MACOSX_FRAMEWORK_BUNDLE_VERSION}</string>
+ <key>CSResourcesFileMapped</key>
+ <true/>
+ <key>NSHumanReadableCopyright</key>
+ <string>${MACOSX_FRAMEWORK_COPYRIGHT}</string>
+</dict>
+</plist>
diff --git a/Modules/Platform/Darwin.cmake b/Modules/Platform/Darwin.cmake
index 11f76d6..adff353 100644
--- a/Modules/Platform/Darwin.cmake
+++ b/Modules/Platform/Darwin.cmake
@@ -76,6 +76,11 @@ SET(CMAKE_C_CREATE_SHARED_MODULE
SET(CMAKE_Fortran_CREATE_SHARED_MODULE
"<CMAKE_Fortran_COMPILER> <LANGUAGE_COMPILE_FLAGS> <CMAKE_SHARED_MODULE_CREATE_Fortran_FLAGS> <LINK_FLAGS> -o <TARGET> <OBJECTS> <LINK_LIBRARIES>")
+SET(CMAKE_C_CREATE_MACOSX_FRAMEWORK
+ "<CMAKE_C_COMPILER> <LANGUAGE_COMPILE_FLAGS> <CMAKE_SHARED_LIBRARY_CREATE_C_FLAGS> <LINK_FLAGS> -o <TARGET> -install_name <TARGET_INSTALLNAME_DIR><TARGET_SONAME> <OBJECTS> <LINK_LIBRARIES>")
+SET(CMAKE_CXX_CREATE_MACOSX_FRAMEWORK
+ "<CMAKE_CXX_COMPILER> <LANGUAGE_COMPILE_FLAGS> <CMAKE_SHARED_LIBRARY_CREATE_CXX_FLAGS> <LINK_FLAGS> -o <TARGET> -install_name <TARGET_INSTALLNAME_DIR><TARGET_SONAME> <OBJECTS> <LINK_LIBRARIES>")
+
SET(CMAKE_PLATFORM_IMPLICIT_INCLUDE_DIRECTORIES /usr/local/include)
diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx
index 2200102..7479871 100644
--- a/Source/cmLocalGenerator.cxx
+++ b/Source/cmLocalGenerator.cxx
@@ -1728,8 +1728,11 @@ void cmLocalGenerator
// off the per-configuration subdirectory. The link directory
// ordering knows how to deal with this.
linkItem += tgt->GetDirectory(0, implib);
- linkItem += "/";
- linkItem += tgt->GetFullName(config, implib);
+ if(!tgt->GetPropertyAsBool("FRAMEWORK"))
+ {
+ linkItem += "/";
+ linkItem += tgt->GetFullName(config, implib);
+ }
}
linkLibraries.push_back(linkItem);
// For full path, use the true location.
diff --git a/Source/cmMakefileLibraryTargetGenerator.cxx b/Source/cmMakefileLibraryTargetGenerator.cxx
index 5325c06..4eaefce 100644
--- a/Source/cmMakefileLibraryTargetGenerator.cxx
+++ b/Source/cmMakefileLibraryTargetGenerator.cxx
@@ -111,6 +111,13 @@ void cmMakefileLibraryTargetGenerator::WriteStaticLibraryRules()
//----------------------------------------------------------------------------
void cmMakefileLibraryTargetGenerator::WriteSharedLibraryRules(bool relink)
{
+#ifdef __APPLE__
+ if(this->Target->GetPropertyAsBool("FRAMEWORK"))
+ {
+ this->WriteFrameworkRules(relink);
+ return;
+ }
+#endif
const char* linkLanguage =
this->Target->GetLinkerLanguage(this->GlobalGenerator);
std::string linkRuleVar = "CMAKE_";
@@ -184,6 +191,238 @@ void cmMakefileLibraryTargetGenerator::WriteModuleLibraryRules(bool relink)
}
//----------------------------------------------------------------------------
+void cmMakefileLibraryTargetGenerator::WriteFrameworkRules(bool relink)
+{
+ const char* linkLanguage =
+ this->Target->GetLinkerLanguage(this->GlobalGenerator);
+ std::string linkRuleVar = "CMAKE_";
+ if (linkLanguage)
+ {
+ linkRuleVar += linkLanguage;
+ }
+ linkRuleVar += "_CREATE_MACOSX_FRAMEWORK";
+
+ std::string extraFlags;
+ this->LocalGenerator->AppendFlags(extraFlags,
+ this->Target->GetProperty("LINK_FLAGS"));
+ std::string linkFlagsConfig = "LINK_FLAGS_";
+ linkFlagsConfig +=
+ cmSystemTools::UpperCase(this->LocalGenerator->ConfigurationName.c_str());
+ this->LocalGenerator->AppendFlags
+ (extraFlags, this->Target->GetProperty(linkFlagsConfig.c_str()));
+ this->LocalGenerator->AddConfigVariableFlags
+ (extraFlags, "CMAKE_MACOSX_FRAMEWORK_LINKER_FLAGS",
+ this->LocalGenerator->ConfigurationName.c_str());
+
+ // TODO: .def files should be supported here also.
+ this->WriteLibraryRules(linkRuleVar.c_str(), extraFlags.c_str(), relink);
+}
+
+
+//----------------------------------------------------------------------------
+void cmMakefileLibraryTargetGenerator::CreateFrameworkLinksAndDirs(
+ std::string& targetName,
+ std::string& outpath,
+ const char* version)
+{
+ std::string symlink;
+ std::string symlink2;
+ // Make foo.framework/Versions
+ std::string dir = outpath;
+ dir += "Versions";
+ cmSystemTools::MakeDirectory(dir.c_str());
+ std::string cwd = cmSystemTools::GetCurrentWorkingDirectory();
+ // cd foo.framework to setup symlinks with relative paths
+ cmSystemTools::ChangeDirectory((outpath+"Versions").c_str());
+ // Current -> version
+ symlink = version;
+ symlink2 = "Current";
+ cmSystemTools::RemoveFile("Current");
+ cmSystemTools::CreateSymlink(symlink.c_str(), symlink2.c_str());
+ this->Makefile->AddCMakeOutputFile((outpath + "Versions/Current").c_str());
+ // change to top level of framework to create next set of symlinks
+ cmSystemTools::ChangeDirectory(outpath.c_str());
+ // foo -> Versions/Current/foo
+ symlink = "Versions/Current/";
+ symlink += targetName;
+ symlink2 = targetName;
+ cmSystemTools::CreateSymlink(symlink.c_str(), symlink2.c_str());
+ this->Makefile->AddCMakeOutputFile((outpath + targetName).c_str());
+ // Resources -> Versions/Current/Resources
+ symlink = "Versions/Current/Resources";
+ symlink2 = "Resources";
+ cmSystemTools::CreateSymlink(symlink.c_str(), symlink2.c_str());
+ this->Makefile->AddCMakeOutputFile((outpath + "Resources").c_str());
+ // Libraries -> Versions/Current/Libraries
+ symlink = "Versions/Current/Libraries";
+ symlink2 = "Libraries";
+ cmSystemTools::CreateSymlink(symlink.c_str(), symlink2.c_str());
+ this->Makefile->AddCMakeOutputFile((outpath + "Libraries").c_str());
+ // Headers -> Versions/Current/Headers
+ symlink = "Versions/Current/Headers";
+ symlink2 = "Headers";
+ cmSystemTools::CreateSymlink(symlink.c_str(), symlink2.c_str());
+ this->Makefile->AddCMakeOutputFile((outpath + "Headers").c_str());
+ // go back to where we were
+ cmSystemTools::ChangeDirectory(cwd.c_str());
+}
+
+//----------------------------------------------------------------------------
+void cmMakefileLibraryTargetGenerator::CopyFrameworkPublicHeaders(
+ std::string& targetName,
+ std::string& outpath,
+ const char* /*version*/)
+{
+ std::string fullOutput= outpath + targetName;
+ const char* headers = this->Target->GetProperty("FRAMEWORK_PUBLIC_HEADERS");
+ if(!headers)
+ {
+ return;
+ }
+ std::vector<std::string> headersVec;
+ cmSystemTools::ExpandListArgument(headers,
+ headersVec);
+ cmCustomCommandLines commandLines;
+ std::vector<std::string> depends;
+ for(std::vector<std::string>::iterator i = headersVec.begin();
+ i != headersVec.end(); ++i)
+ {
+ cmCustomCommandLine line;
+ cmSourceFile* sf = this->Makefile->GetOrCreateSource(i->c_str());
+ std::string dest = outpath + "Headers/";
+ dest += sf->GetSourceName();
+ std::string ext = sf->GetSourceExtension();
+ if(ext.size())
+ {
+ dest += ".";
+ dest += sf->GetSourceExtension();
+ }
+ line.push_back("$(CMAKE_COMMAND)");
+ line.push_back("-E");
+ line.push_back("copy_if_different");
+ line.push_back(sf->GetFullPath());
+ depends.push_back(sf->GetFullPath());
+ line.push_back(dest);
+ commandLines.push_back(line);
+ // make sure the target gets rebuilt if any of the headers is removed
+ this->GenerateExtraOutput(dest.c_str(),
+ fullOutput.c_str());
+ }
+ // add a set of prebuild commands to run on the target
+ this->Makefile->
+ AddCustomCommandToTarget(this->Target->GetName(),
+ depends,
+ commandLines,
+ cmTarget::PRE_BUILD,
+ "copy files",
+ this->Makefile->GetCurrentOutputDirectory());
+}
+
+//----------------------------------------------------------------------------
+void cmMakefileLibraryTargetGenerator::CopyFrameworkResources(
+ std::string& targetName,
+ std::string& outpath,
+ const char* /*version*/)
+{
+ std::string fullOutput= outpath + targetName;
+ const char* resources = this->Target->GetProperty("FRAMEWORK_RESOURCES");
+ if(!resources)
+ {
+ return;
+ }
+ std::vector<std::string> resourcesVec;
+ cmSystemTools::ExpandListArgument(resources,
+ resourcesVec);
+ cmCustomCommandLines commandLines;
+ std::vector<std::string> depends;
+ for(std::vector<std::string>::iterator i = resourcesVec.begin();
+ i != resourcesVec.end(); ++i)
+ {
+ cmCustomCommandLine line;
+ cmSourceFile* sf = this->Makefile->GetOrCreateSource(i->c_str());
+ std::string dest = outpath + "Resources/";
+ dest += sf->GetSourceName();
+ std::string ext = sf->GetSourceExtension();
+ if(ext.size())
+ {
+ dest += ".";
+ dest += sf->GetSourceExtension();
+ }
+ line.push_back("$(CMAKE_COMMAND)");
+ line.push_back("-E");
+ line.push_back("copy_if_different");
+ line.push_back(sf->GetFullPath());
+ depends.push_back(sf->GetFullPath());
+ line.push_back(dest);
+ commandLines.push_back(line);
+ // make sure the target gets rebuilt if any of the resources is removed
+ this->GenerateExtraOutput(dest.c_str(),
+ fullOutput.c_str());
+ }
+ // add a set of prebuild commands to run on the target
+ this->Makefile->
+ AddCustomCommandToTarget(this->Target->GetName(),
+ depends,
+ commandLines,
+ cmTarget::PRE_BUILD,
+ "copy files",
+ this->Makefile->GetCurrentOutputDirectory());
+}
+
+//----------------------------------------------------------------------------
+void cmMakefileLibraryTargetGenerator::CreateFramework(
+ std::string& targetName,
+ std::string& outpath)
+{
+ std::string macdir = outpath;
+ const char* version = this->Target->GetProperty("FRAMEWORK_VERSION");
+ if(!version)
+ {
+ version = "A";
+ std::string message =
+ "Warning: FRAMEWORK_VERSION property not found on ";
+ message += targetName;
+ message += ". Default to verison A.";
+ cmSystemTools::Message(message.c_str());
+ }
+ // create the symbolic links and directories
+ this->CreateFrameworkLinksAndDirs(targetName,
+ outpath,
+ version);
+ macdir += "Versions/";
+ macdir += version;
+ macdir += "/";
+ outpath += "Versions/";
+ outpath += version;
+ outpath += "/";
+
+ cmSystemTools::MakeDirectory((macdir + "Libraries").c_str());
+ cmSystemTools::MakeDirectory((macdir + "Headers").c_str());
+ // Configure the Info.plist file. Note that it needs the executable name
+ // to be set
+ std::string rsrcDir = macdir + "Resources/";
+ cmSystemTools::MakeDirectory(rsrcDir.c_str());
+ this->Makefile->AddDefinition("MACOSX_FRAMEWORK_NAME",
+ targetName.c_str());
+ std::string f1 =
+ this->Makefile->GetModulesFile("MacOSXFrameworkInfo.plist.in");
+ if ( f1.size() == 0 )
+ {
+ cmSystemTools::Error(
+ "could not find Mac OSX framework Info.plist template file.");
+ }
+ std::string f2 = rsrcDir + "Info.plist";
+ this->Makefile->ConfigureFile(f1.c_str(), f2.c_str(),
+ false, false, false);
+ this->CopyFrameworkPublicHeaders(targetName,
+ outpath,
+ version);
+ this->CopyFrameworkResources(targetName,
+ outpath,
+ version);
+}
+
+//----------------------------------------------------------------------------
void cmMakefileLibraryTargetGenerator::WriteLibraryRules
(const char* linkRuleVar, const char* extraFlags, bool relink)
{
@@ -269,6 +508,13 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules
outpathImp += "/";
}
}
+#if defined(__APPLE__)
+ // If we're creating a framework, place the output into a framework directory
+ if(this->Target->GetPropertyAsBool("FRAMEWORK"))
+ {
+ this->CreateFramework(targetName, outpath);
+ }
+#endif
std::string targetFullPath = outpath + targetName;
std::string targetFullPathPDB = outpath + targetNamePDB;
std::string targetFullPathSO = outpath + targetNameSO;
@@ -510,7 +756,6 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules
this->Makefile->GetHomeOutputDirectory());
commands.insert(commands.end(), commands1.begin(), commands1.end());
}
-
// Add the post-build rules when building but not when relinking.
if(!relink)
{
diff --git a/Source/cmMakefileLibraryTargetGenerator.h b/Source/cmMakefileLibraryTargetGenerator.h
index 1194afe..1be2ebd 100644
--- a/Source/cmMakefileLibraryTargetGenerator.h
+++ b/Source/cmMakefileLibraryTargetGenerator.h
@@ -35,6 +35,19 @@ protected:
void WriteModuleLibraryRules(bool relink);
void WriteLibraryRules(const char *linkRule, const char *extraFlags,
bool relink);
+ // MacOSX Framework support methods
+ void WriteFrameworkRules(bool relink);
+ void CreateFramework(std::string& targetName,
+ std::string& outpath);
+ void CreateFrameworkLinksAndDirs(std::string& targetName,
+ std::string& outpath,
+ const char* version);
+ void CopyFrameworkPublicHeaders(std::string& targetName,
+ std::string& outpath,
+ const char* version);
+ void CopyFrameworkResources(std::string& targetName,
+ std::string& outpath,
+ const char* version);
};
#endif
diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx
index 5b15428..85f3d6e 100644
--- a/Source/cmTarget.cxx
+++ b/Source/cmTarget.cxx
@@ -1634,6 +1634,14 @@ void cmTarget::GetFullNameInternal(TargetType type,
{
targetSuffix = this->Makefile->GetSafeDefinition(suffixVar);
}
+#if defined(__APPLE__)
+ // frameworks do not have a prefix or a suffix
+ if(this->GetPropertyAsBool("FRAMEWORK"))
+ {
+ targetPrefix = 0;
+ targetSuffix = 0;
+ }
+#endif
// Begin the final name with the prefix.
outPrefix = targetPrefix?targetPrefix:"";
@@ -2145,7 +2153,6 @@ const char* cmTarget::GetOutputDir(bool implib)
// Default to the current output directory.
out = ".";
}
-
// Convert the output path to a full path in case it is
// specified as a relative path. Treat a relative path as
// relative to the current output directory for this makefile.
@@ -2153,6 +2160,16 @@ const char* cmTarget::GetOutputDir(bool implib)
cmSystemTools::CollapseFullPath
(out.c_str(), this->Makefile->GetStartOutputDirectory());
+#if defined(__APPLE__)
+ // frameworks do not have a prefix or a suffix
+ if(this->GetPropertyAsBool("FRAMEWORK"))
+ {
+ out += "/";
+ out += this->GetFullName(0, implib);
+ out += ".framework";
+ }
+#endif
+
// Make sure the output path exists on disk.
if(!cmSystemTools::MakeDirectory(out.c_str()))
{