/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 = outpath + "/" + |
76 | 0 | this->GT->GetFrameworkDirectory(config, cmGeneratorTarget::FullLevel); |
77 | |
|
78 | 0 | std::string frameworkVersion = this->GT->GetFrameworkVersion(); |
79 | |
|
80 | 0 | std::string name = cmSystemTools::GetFilenameName(targetName); |
81 | 0 | if (!skipParts.InfoPlist) { |
82 | | // Configure the Info.plist file |
83 | 0 | std::string plist = newoutpath; |
84 | 0 | if (!this->Makefile->PlatformIsAppleEmbedded()) { |
85 | | // Put the Info.plist file into the Resources directory. |
86 | 0 | this->MacContentFolders->insert("Resources"); |
87 | 0 | plist += "/Resources"; |
88 | 0 | } |
89 | 0 | plist += "/Info.plist"; |
90 | 0 | this->LocalGenerator->GenerateFrameworkInfoPList(this->GT, name, plist); |
91 | 0 | } |
92 | | |
93 | | // Generate Versions directory only for MacOSX frameworks |
94 | 0 | if (this->Makefile->PlatformIsAppleEmbedded()) { |
95 | 0 | return; |
96 | 0 | } |
97 | | |
98 | | // TODO: Use the cmMakefileTargetGenerator::ExtraFiles vector to |
99 | | // drive rules to create these files at build time. |
100 | 0 | std::string oldName; |
101 | 0 | std::string newName; |
102 | | |
103 | | // Make foo.framework/Versions |
104 | 0 | std::string versions = cmStrCat(contentdir, "Versions"); |
105 | 0 | cmSystemTools::MakeDirectory(versions); |
106 | | |
107 | | // Make foo.framework/Versions/version |
108 | 0 | cmSystemTools::MakeDirectory(newoutpath); |
109 | | |
110 | | // Current -> version |
111 | 0 | oldName = frameworkVersion; |
112 | 0 | newName = cmStrCat(versions, "/Current"); |
113 | 0 | cmSystemTools::RemoveFile(newName); |
114 | 0 | cmSystemTools::CreateSymlink(oldName, newName); |
115 | 0 | this->Makefile->AddCMakeOutputFile(newName); |
116 | | |
117 | | // foo -> Versions/Current/foo |
118 | 0 | oldName = cmStrCat("Versions/Current/", name); |
119 | 0 | newName = cmStrCat(contentdir, name); |
120 | 0 | cmSystemTools::RemoveFile(newName); |
121 | 0 | cmSystemTools::CreateSymlink(oldName, newName); |
122 | 0 | this->Makefile->AddCMakeOutputFile(newName); |
123 | |
|
124 | 0 | if (!skipParts.TextStubs) { |
125 | | // foo.tbd -> Versions/Current/foo.tbd |
126 | 0 | cmValue tbdSuffix = |
127 | 0 | this->Makefile->GetDefinition("CMAKE_APPLE_IMPORT_FILE_SUFFIX"); |
128 | 0 | oldName = cmStrCat("Versions/Current/", name, tbdSuffix); |
129 | 0 | newName = cmStrCat(contentdir, name, tbdSuffix); |
130 | 0 | cmSystemTools::RemoveFile(newName); |
131 | 0 | cmSystemTools::CreateSymlink(oldName, newName); |
132 | 0 | this->Makefile->AddCMakeOutputFile(newName); |
133 | 0 | } |
134 | | |
135 | | // Resources -> Versions/Current/Resources |
136 | 0 | if (this->MacContentFolders->find("Resources") != |
137 | 0 | this->MacContentFolders->end()) { |
138 | 0 | oldName = "Versions/Current/Resources"; |
139 | 0 | newName = cmStrCat(contentdir, "Resources"); |
140 | 0 | cmSystemTools::RemoveFile(newName); |
141 | 0 | cmSystemTools::CreateSymlink(oldName, newName); |
142 | 0 | this->Makefile->AddCMakeOutputFile(newName); |
143 | 0 | } |
144 | | |
145 | | // Headers -> Versions/Current/Headers |
146 | 0 | if (this->MacContentFolders->find("Headers") != |
147 | 0 | this->MacContentFolders->end()) { |
148 | 0 | oldName = "Versions/Current/Headers"; |
149 | 0 | newName = cmStrCat(contentdir, "Headers"); |
150 | 0 | cmSystemTools::RemoveFile(newName); |
151 | 0 | cmSystemTools::CreateSymlink(oldName, newName); |
152 | 0 | this->Makefile->AddCMakeOutputFile(newName); |
153 | 0 | } |
154 | | |
155 | | // PrivateHeaders -> Versions/Current/PrivateHeaders |
156 | 0 | if (this->MacContentFolders->find("PrivateHeaders") != |
157 | 0 | this->MacContentFolders->end()) { |
158 | 0 | oldName = "Versions/Current/PrivateHeaders"; |
159 | 0 | newName = cmStrCat(contentdir, "PrivateHeaders"); |
160 | 0 | cmSystemTools::RemoveFile(newName); |
161 | 0 | cmSystemTools::CreateSymlink(oldName, newName); |
162 | 0 | this->Makefile->AddCMakeOutputFile(newName); |
163 | 0 | } |
164 | 0 | } |
165 | | |
166 | | void cmOSXBundleGenerator::CreateCFBundle(std::string const& targetName, |
167 | | std::string const& root, |
168 | | std::string const& config) |
169 | 0 | { |
170 | 0 | if (this->MustSkip()) { |
171 | 0 | return; |
172 | 0 | } |
173 | | |
174 | | // Compute bundle directory names. |
175 | 0 | std::string out = cmStrCat( |
176 | 0 | root, '/', |
177 | 0 | this->GT->GetCFBundleDirectory(config, cmGeneratorTarget::FullLevel)); |
178 | 0 | cmSystemTools::MakeDirectory(out); |
179 | 0 | this->Makefile->AddCMakeOutputFile(out); |
180 | | |
181 | | // Configure the Info.plist file. Note that it needs the executable name |
182 | | // to be set. |
183 | 0 | std::string plist = cmStrCat( |
184 | 0 | root, '/', |
185 | 0 | this->GT->GetCFBundleDirectory(config, cmGeneratorTarget::ContentLevel), |
186 | 0 | "/Info.plist"); |
187 | 0 | std::string name = cmSystemTools::GetFilenameName(targetName); |
188 | 0 | this->LocalGenerator->GenerateAppleInfoPList(this->GT, name, plist); |
189 | 0 | this->Makefile->AddCMakeOutputFile(plist); |
190 | 0 | } |
191 | | |
192 | | void cmOSXBundleGenerator::GenerateMacOSXContentStatements( |
193 | | std::vector<cmSourceFile const*> const& sources, |
194 | | MacOSXContentGeneratorType* generator, std::string const& config) |
195 | 0 | { |
196 | 0 | if (this->MustSkip()) { |
197 | 0 | return; |
198 | 0 | } |
199 | | |
200 | 0 | for (cmSourceFile const* source : sources) { |
201 | 0 | cmGeneratorTarget::SourceFileFlags tsFlags = |
202 | 0 | this->GT->GetTargetSourceFileFlags(source); |
203 | 0 | if (tsFlags.Type != cmGeneratorTarget::SourceFileTypeNormal) { |
204 | 0 | (*generator)(*source, tsFlags.MacFolder, config); |
205 | 0 | } |
206 | 0 | } |
207 | 0 | } |
208 | | |
209 | | std::string cmOSXBundleGenerator::InitMacOSXContentDirectory( |
210 | | char const* pkgloc, std::string const& config) |
211 | 0 | { |
212 | | // Construct the full path to the content subdirectory. |
213 | |
|
214 | 0 | std::string macdir = cmStrCat(this->GT->GetMacContentDirectory( |
215 | 0 | config, cmStateEnums::RuntimeBinaryArtifact), |
216 | 0 | '/', pkgloc); |
217 | 0 | cmSystemTools::MakeDirectory(macdir); |
218 | | |
219 | | // Record use of this content location. Only the first level |
220 | | // directory is needed. |
221 | 0 | { |
222 | 0 | std::string loc = pkgloc; |
223 | 0 | loc = loc.substr(0, loc.find('/')); |
224 | 0 | this->MacContentFolders->insert(loc); |
225 | 0 | } |
226 | |
|
227 | 0 | return macdir; |
228 | 0 | } |