diff options
author | Bill Hoffman <bill.hoffman@kitware.com> | 2007-05-08 14:32:54 (GMT) |
---|---|---|
committer | Bill Hoffman <bill.hoffman@kitware.com> | 2007-05-08 14:32:54 (GMT) |
commit | 9323a2798973b3dbe8ca9725f1cb5c8ff6d5900b (patch) | |
tree | adf91f5e20d08609ec5c83ec09376fdc9e168f46 | |
parent | 96232d405236231e6f4ba858a70621da9066f26c (diff) | |
download | CMake-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.in | 28 | ||||
-rw-r--r-- | Modules/Platform/Darwin.cmake | 5 | ||||
-rw-r--r-- | Source/cmLocalGenerator.cxx | 7 | ||||
-rw-r--r-- | Source/cmMakefileLibraryTargetGenerator.cxx | 247 | ||||
-rw-r--r-- | Source/cmMakefileLibraryTargetGenerator.h | 13 | ||||
-rw-r--r-- | Source/cmTarget.cxx | 19 |
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())) { |