/src/CMake/Source/cmOSXBundleGenerator.cxx
Line | Count | Source |
1 | | /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying |
2 | | file LICENSE.rst or https://cmake.org/licensing for details. */ |
3 | | #include "cmOSXBundleGenerator.h" |
4 | | |
5 | | #include <cassert> |
6 | | |
7 | | #include "cmGeneratorTarget.h" |
8 | | #include "cmLocalGenerator.h" |
9 | | #include "cmMakefile.h" |
10 | | #include "cmStateTypes.h" |
11 | | #include "cmStringAlgorithms.h" |
12 | | #include "cmSystemTools.h" |
13 | | #include "cmTarget.h" |
14 | | #include "cmValue.h" |
15 | | |
16 | | class cmSourceFile; |
17 | | |
18 | | cmOSXBundleGenerator::cmOSXBundleGenerator(cmGeneratorTarget* target) |
19 | 0 | : GT(target) |
20 | 0 | , Makefile(target->Target->GetMakefile()) |
21 | 0 | , LocalGenerator(target->GetLocalGenerator()) |
22 | 0 | { |
23 | 0 | if (this->MustSkip()) { |
24 | 0 | return; |
25 | 0 | } |
26 | 0 | } |
27 | | |
28 | | bool cmOSXBundleGenerator::MustSkip() |
29 | 0 | { |
30 | 0 | return !this->GT->HaveWellDefinedOutputFiles(); |
31 | 0 | } |
32 | | |
33 | | void cmOSXBundleGenerator::CreateAppBundle(std::string const& targetName, |
34 | | std::string& outpath, |
35 | | std::string const& config) |
36 | 0 | { |
37 | 0 | if (this->MustSkip()) { |
38 | 0 | return; |
39 | 0 | } |
40 | | |
41 | | // Compute bundle directory names. |
42 | 0 | std::string out = cmStrCat( |
43 | 0 | outpath, '/', |
44 | 0 | this->GT->GetAppBundleDirectory(config, cmGeneratorTarget::FullLevel)); |
45 | 0 | cmSystemTools::MakeDirectory(out); |
46 | 0 | this->Makefile->AddCMakeOutputFile(out); |
47 | | |
48 | | // Configure the Info.plist file. Note that it needs the executable name |
49 | | // to be set. |
50 | 0 | std::string plist = cmStrCat( |
51 | 0 | outpath, '/', |
52 | 0 | this->GT->GetAppBundleDirectory(config, cmGeneratorTarget::ContentLevel), |
53 | 0 | "/Info.plist"); |
54 | 0 | this->LocalGenerator->GenerateAppleInfoPList(this->GT, targetName, plist); |
55 | 0 | this->Makefile->AddCMakeOutputFile(plist); |
56 | 0 | outpath = out; |
57 | 0 | } |
58 | | |
59 | | void cmOSXBundleGenerator::CreateFramework( |
60 | | std::string const& targetName, std::string const& outpath, |
61 | | std::string const& config, cmOSXBundleGenerator::SkipParts skipParts) |
62 | 0 | { |
63 | 0 | if (this->MustSkip()) { |
64 | 0 | return; |
65 | 0 | } |
66 | | |
67 | 0 | assert(this->MacContentFolders); |
68 | | |
69 | | // Compute the location of the top-level foo.framework directory. |
70 | 0 | std::string contentdir = cmStrCat( |
71 | 0 | outpath, '/', |
72 | 0 | this->GT->GetFrameworkDirectory(config, cmGeneratorTarget::ContentLevel), |
73 | 0 | '/'); |
74 | |
|
75 | 0 | std::string newoutpath = cmStrCat( |
76 | 0 | outpath, '/', |
77 | 0 | this->GT->GetFrameworkDirectory(config, cmGeneratorTarget::FullLevel)); |
78 | |
|
79 | 0 | std::string frameworkVersion = this->GT->GetFrameworkVersion(); |
80 | |
|
81 | 0 | std::string name = cmSystemTools::GetFilenameName(targetName); |
82 | 0 | if (!skipParts.InfoPlist) { |
83 | | // Configure the Info.plist file |
84 | 0 | std::string plist = newoutpath; |
85 | 0 | if (!this->Makefile->PlatformIsAppleEmbedded()) { |
86 | | // Put the Info.plist file into the Resources directory. |
87 | 0 | this->MacContentFolders->insert("Resources"); |
88 | 0 | plist += "/Resources"; |
89 | 0 | } |
90 | 0 | plist += "/Info.plist"; |
91 | 0 | this->LocalGenerator->GenerateFrameworkInfoPList(this->GT, name, plist); |
92 | 0 | } |
93 | | |
94 | | // Generate Versions directory only for MacOSX frameworks |
95 | 0 | if (this->Makefile->PlatformIsAppleEmbedded()) { |
96 | 0 | return; |
97 | 0 | } |
98 | | |
99 | | // TODO: Use the cmMakefileTargetGenerator::ExtraFiles vector to |
100 | | // drive rules to create these files at build time. |
101 | 0 | std::string oldName; |
102 | 0 | std::string newName; |
103 | | |
104 | | // Make foo.framework/Versions |
105 | 0 | std::string versions = cmStrCat(contentdir, "Versions"); |
106 | 0 | cmSystemTools::MakeDirectory(versions); |
107 | | |
108 | | // Make foo.framework/Versions/version |
109 | 0 | cmSystemTools::MakeDirectory(newoutpath); |
110 | | |
111 | | // Current -> version |
112 | 0 | oldName = frameworkVersion; |
113 | 0 | newName = cmStrCat(versions, "/Current"); |
114 | 0 | cmSystemTools::RemoveFile(newName); |
115 | 0 | cmSystemTools::CreateSymlink(oldName, newName); |
116 | 0 | this->Makefile->AddCMakeOutputFile(newName); |
117 | | |
118 | | // foo -> Versions/Current/foo |
119 | 0 | oldName = cmStrCat("Versions/Current/", name); |
120 | 0 | newName = cmStrCat(contentdir, name); |
121 | 0 | cmSystemTools::RemoveFile(newName); |
122 | 0 | cmSystemTools::CreateSymlink(oldName, newName); |
123 | 0 | this->Makefile->AddCMakeOutputFile(newName); |
124 | |
|
125 | 0 | if (!skipParts.TextStubs) { |
126 | | // foo.tbd -> Versions/Current/foo.tbd |
127 | 0 | cmValue tbdSuffix = |
128 | 0 | this->Makefile->GetDefinition("CMAKE_APPLE_IMPORT_FILE_SUFFIX"); |
129 | 0 | oldName = cmStrCat("Versions/Current/", name, tbdSuffix); |
130 | 0 | newName = cmStrCat(contentdir, name, tbdSuffix); |
131 | 0 | cmSystemTools::RemoveFile(newName); |
132 | 0 | cmSystemTools::CreateSymlink(oldName, newName); |
133 | 0 | this->Makefile->AddCMakeOutputFile(newName); |
134 | 0 | } |
135 | | |
136 | | // Resources -> Versions/Current/Resources |
137 | 0 | if (this->MacContentFolders->find("Resources") != |
138 | 0 | this->MacContentFolders->end()) { |
139 | 0 | oldName = "Versions/Current/Resources"; |
140 | 0 | newName = cmStrCat(contentdir, "Resources"); |
141 | 0 | cmSystemTools::RemoveFile(newName); |
142 | 0 | cmSystemTools::CreateSymlink(oldName, newName); |
143 | 0 | this->Makefile->AddCMakeOutputFile(newName); |
144 | 0 | } |
145 | | |
146 | | // Headers -> Versions/Current/Headers |
147 | 0 | if (this->MacContentFolders->find("Headers") != |
148 | 0 | this->MacContentFolders->end()) { |
149 | 0 | oldName = "Versions/Current/Headers"; |
150 | 0 | newName = cmStrCat(contentdir, "Headers"); |
151 | 0 | cmSystemTools::RemoveFile(newName); |
152 | 0 | cmSystemTools::CreateSymlink(oldName, newName); |
153 | 0 | this->Makefile->AddCMakeOutputFile(newName); |
154 | 0 | } |
155 | | |
156 | | // PrivateHeaders -> Versions/Current/PrivateHeaders |
157 | 0 | if (this->MacContentFolders->find("PrivateHeaders") != |
158 | 0 | this->MacContentFolders->end()) { |
159 | 0 | oldName = "Versions/Current/PrivateHeaders"; |
160 | 0 | newName = cmStrCat(contentdir, "PrivateHeaders"); |
161 | 0 | cmSystemTools::RemoveFile(newName); |
162 | 0 | cmSystemTools::CreateSymlink(oldName, newName); |
163 | 0 | this->Makefile->AddCMakeOutputFile(newName); |
164 | 0 | } |
165 | 0 | } |
166 | | |
167 | | void cmOSXBundleGenerator::CreateCFBundle(std::string const& targetName, |
168 | | std::string const& root, |
169 | | std::string const& config) |
170 | 0 | { |
171 | 0 | if (this->MustSkip()) { |
172 | 0 | return; |
173 | 0 | } |
174 | | |
175 | | // Compute bundle directory names. |
176 | 0 | std::string out = cmStrCat( |
177 | 0 | root, '/', |
178 | 0 | this->GT->GetCFBundleDirectory(config, cmGeneratorTarget::FullLevel)); |
179 | 0 | cmSystemTools::MakeDirectory(out); |
180 | 0 | this->Makefile->AddCMakeOutputFile(out); |
181 | | |
182 | | // Configure the Info.plist file. Note that it needs the executable name |
183 | | // to be set. |
184 | 0 | std::string plist = cmStrCat( |
185 | 0 | root, '/', |
186 | 0 | this->GT->GetCFBundleDirectory(config, cmGeneratorTarget::ContentLevel), |
187 | 0 | "/Info.plist"); |
188 | 0 | std::string name = cmSystemTools::GetFilenameName(targetName); |
189 | 0 | this->LocalGenerator->GenerateAppleInfoPList(this->GT, name, plist); |
190 | 0 | this->Makefile->AddCMakeOutputFile(plist); |
191 | 0 | } |
192 | | |
193 | | void cmOSXBundleGenerator::GenerateMacOSXContentStatements( |
194 | | std::vector<cmSourceFile const*> const& sources, |
195 | | MacOSXContentGeneratorType* generator, std::string const& config) |
196 | 0 | { |
197 | 0 | if (this->MustSkip()) { |
198 | 0 | return; |
199 | 0 | } |
200 | | |
201 | 0 | for (cmSourceFile const* source : sources) { |
202 | 0 | cmGeneratorTarget::SourceFileFlags tsFlags = |
203 | 0 | this->GT->GetTargetSourceFileFlags(source); |
204 | 0 | if (tsFlags.Type != cmGeneratorTarget::SourceFileTypeNormal) { |
205 | 0 | (*generator)(*source, tsFlags.MacFolder, config); |
206 | 0 | } |
207 | 0 | } |
208 | 0 | } |
209 | | |
210 | | std::string cmOSXBundleGenerator::InitMacOSXContentDirectory( |
211 | | char const* pkgloc, std::string const& config) |
212 | 0 | { |
213 | | // Construct the full path to the content subdirectory. |
214 | |
|
215 | 0 | std::string macdir = cmStrCat(this->GT->GetMacContentDirectory( |
216 | 0 | config, cmStateEnums::RuntimeBinaryArtifact), |
217 | 0 | '/', pkgloc); |
218 | 0 | cmSystemTools::MakeDirectory(macdir); |
219 | | |
220 | | // Record use of this content location. Only the first level |
221 | | // directory is needed. |
222 | 0 | { |
223 | 0 | std::string loc = pkgloc; |
224 | 0 | loc = loc.substr(0, loc.find('/')); |
225 | 0 | this->MacContentFolders->insert(loc); |
226 | 0 | } |
227 | |
|
228 | 0 | return macdir; |
229 | 0 | } |