1 /*============================================================================
2 CMake - Cross Platform Makefile Generator
3 Copyright 2012 Nicolas Despres <nicolas.despres@gmail.com>
5 Distributed under the OSI-approved BSD License (the "License");
6 see accompanying file Copyright.txt for details.
8 This software is distributed WITHOUT ANY WARRANTY; without even the
9 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
10 See the License for more information.
11 ============================================================================*/
12 #include "cmOSXBundleGenerator.h"
13 #include "cmMakefile.h"
15 #include "cmLocalGenerator.h"
19 //----------------------------------------------------------------------------
20 cmOSXBundleGenerator::
21 cmOSXBundleGenerator(cmTarget* target,
22 const char* configName)
24 , Makefile(target->GetMakefile())
25 , LocalGenerator(Makefile->GetLocalGenerator())
26 , ConfigName(configName)
27 , MacContentFolders(0)
34 //----------------------------------------------------------------------------
35 bool cmOSXBundleGenerator::MustSkip()
37 return !this->Target->HaveWellDefinedOutputFiles();
40 //----------------------------------------------------------------------------
41 void cmOSXBundleGenerator::CreateAppBundle(const std::string& targetName,
47 // Compute bundle directory names.
48 std::string out = outpath;
50 out += this->Target->GetAppBundleDirectory(this->ConfigName, false);
51 cmSystemTools::MakeDirectory(out.c_str());
52 this->Makefile->AddCMakeOutputFile(out);
54 std::string newoutpath = out;
56 // Configure the Info.plist file. Note that it needs the executable name
58 std::string plist = outpath;
60 plist += this->Target->GetAppBundleDirectory(this->ConfigName, true);
61 plist += "/Info.plist";
62 this->LocalGenerator->GenerateAppleInfoPList(this->Target,
65 this->Makefile->AddCMakeOutputFile(plist);
69 //----------------------------------------------------------------------------
70 void cmOSXBundleGenerator::CreateFramework(
71 const std::string& targetName, const std::string& outpath)
76 assert(this->MacContentFolders);
78 // Compute the location of the top-level foo.framework directory.
79 std::string contentdir = outpath + "/" +
80 this->Target->GetFrameworkDirectory(this->ConfigName, true);
83 std::string newoutpath = outpath + "/" +
84 this->Target->GetFrameworkDirectory(this->ConfigName, false);
86 std::string frameworkVersion = this->Target->GetFrameworkVersion();
88 // Configure the Info.plist file into the Resources directory.
89 this->MacContentFolders->insert("Resources");
90 std::string plist = newoutpath;
91 plist += "/Resources/Info.plist";
92 std::string name = cmSystemTools::GetFilenameName(targetName);
93 this->LocalGenerator->GenerateFrameworkInfoPList(this->Target,
97 // TODO: Use the cmMakefileTargetGenerator::ExtraFiles vector to
98 // drive rules to create these files at build time.
103 // Make foo.framework/Versions
104 std::string versions = contentdir;
105 versions += "Versions";
106 cmSystemTools::MakeDirectory(versions.c_str());
108 // Make foo.framework/Versions/version
109 cmSystemTools::MakeDirectory(newoutpath.c_str());
111 // Current -> version
112 oldName = frameworkVersion;
114 newName += "/Current";
115 cmSystemTools::RemoveFile(newName.c_str());
116 cmSystemTools::CreateSymlink(oldName.c_str(), newName.c_str());
117 this->Makefile->AddCMakeOutputFile(newName);
119 // foo -> Versions/Current/foo
120 oldName = "Versions/Current/";
122 newName = contentdir;
124 cmSystemTools::RemoveFile(newName.c_str());
125 cmSystemTools::CreateSymlink(oldName.c_str(), newName.c_str());
126 this->Makefile->AddCMakeOutputFile(newName);
128 // Resources -> Versions/Current/Resources
129 if(this->MacContentFolders->find("Resources") !=
130 this->MacContentFolders->end())
132 oldName = "Versions/Current/Resources";
133 newName = contentdir;
134 newName += "Resources";
135 cmSystemTools::RemoveFile(newName.c_str());
136 cmSystemTools::CreateSymlink(oldName.c_str(), newName.c_str());
137 this->Makefile->AddCMakeOutputFile(newName);
140 // Headers -> Versions/Current/Headers
141 if(this->MacContentFolders->find("Headers") !=
142 this->MacContentFolders->end())
144 oldName = "Versions/Current/Headers";
145 newName = contentdir;
146 newName += "Headers";
147 cmSystemTools::RemoveFile(newName.c_str());
148 cmSystemTools::CreateSymlink(oldName.c_str(), newName.c_str());
149 this->Makefile->AddCMakeOutputFile(newName);
152 // PrivateHeaders -> Versions/Current/PrivateHeaders
153 if(this->MacContentFolders->find("PrivateHeaders") !=
154 this->MacContentFolders->end())
156 oldName = "Versions/Current/PrivateHeaders";
157 newName = contentdir;
158 newName += "PrivateHeaders";
159 cmSystemTools::RemoveFile(newName.c_str());
160 cmSystemTools::CreateSymlink(oldName.c_str(), newName.c_str());
161 this->Makefile->AddCMakeOutputFile(newName);
165 //----------------------------------------------------------------------------
166 void cmOSXBundleGenerator::CreateCFBundle(const std::string& targetName,
167 const std::string& root)
169 if (this->MustSkip())
172 // Compute bundle directory names.
173 std::string out = root;
175 out += this->Target->GetCFBundleDirectory(this->ConfigName, false);
176 cmSystemTools::MakeDirectory(out.c_str());
177 this->Makefile->AddCMakeOutputFile(out);
179 // Configure the Info.plist file. Note that it needs the executable name
182 this->Target->GetCFBundleDirectory(this->ConfigName, true);
183 plist += "/Info.plist";
184 this->LocalGenerator->GenerateAppleInfoPList(this->Target,
187 this->Makefile->AddCMakeOutputFile(plist);
190 //----------------------------------------------------------------------------
192 cmOSXBundleGenerator::
193 GenerateMacOSXContentStatements(std::vector<cmSourceFile*> const& sources,
194 MacOSXContentGeneratorType* generator)
196 if (this->MustSkip())
199 for(std::vector<cmSourceFile*>::const_iterator
200 si = sources.begin(); si != sources.end(); ++si)
202 cmTarget::SourceFileFlags tsFlags =
203 this->Target->GetTargetSourceFileFlags(*si);
204 if(tsFlags.Type != cmTarget::SourceFileTypeNormal)
206 (*generator)(**si, tsFlags.MacFolder);
211 //----------------------------------------------------------------------------
213 cmOSXBundleGenerator::InitMacOSXContentDirectory(const char* pkgloc)
215 // Construct the full path to the content subdirectory.
218 this->Target->GetMacContentDirectory(this->ConfigName,
222 cmSystemTools::MakeDirectory(macdir.c_str());
224 // Record use of this content location. Only the first level
225 // directory is needed.
227 std::string loc = pkgloc;
228 loc = loc.substr(0, loc.find('/'));
229 this->MacContentFolders->insert(loc);