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 /Source/cmMakefileLibraryTargetGenerator.cxx | |
parent | 96232d405236231e6f4ba858a70621da9066f26c (diff) | |
download | CMake-9323a2798973b3dbe8ca9725f1cb5c8ff6d5900b.zip CMake-9323a2798973b3dbe8ca9725f1cb5c8ff6d5900b.tar.gz CMake-9323a2798973b3dbe8ca9725f1cb5c8ff6d5900b.tar.bz2 |
ENH: initial support for creation of frameworks on Mac
Diffstat (limited to 'Source/cmMakefileLibraryTargetGenerator.cxx')
-rw-r--r-- | Source/cmMakefileLibraryTargetGenerator.cxx | 247 |
1 files changed, 246 insertions, 1 deletions
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) { |