1 /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
2 file Copyright.txt or https://cmake.org/licensing for details. */
3 #include "cmCPackExternalGenerator.h"
4
5 #include <map>
6 #include <utility>
7 #include <vector>
8
9 #include <cm/memory>
10
11 #include <cm3p/json/value.h>
12 #include <cm3p/json/writer.h>
13
14 #include "cmsys/FStream.hxx"
15
16 #include "cmCPackComponentGroup.h"
17 #include "cmCPackLog.h"
18 #include "cmMakefile.h"
19 #include "cmStringAlgorithms.h"
20 #include "cmSystemTools.h"
21 #include "cmValue.h"
22
InitializeInternal()23 int cmCPackExternalGenerator::InitializeInternal()
24 {
25 this->SetOption("CPACK_EXTERNAL_KNOWN_VERSIONS", "1.0");
26
27 if (!this->ReadListFile("Internal/CPack/CPackExternal.cmake")) {
28 cmCPackLogger(cmCPackLog::LOG_ERROR,
29 "Error while executing CPackExternal.cmake" << std::endl);
30 return 0;
31 }
32
33 std::string major = this->GetOption("CPACK_EXTERNAL_SELECTED_MAJOR");
34 if (major == "1") {
35 this->Generator = cm::make_unique<cmCPackExternalVersion1Generator>(this);
36 }
37
38 return this->Superclass::InitializeInternal();
39 }
40
PackageFiles()41 int cmCPackExternalGenerator::PackageFiles()
42 {
43 Json::StreamWriterBuilder builder;
44 builder["indentation"] = " ";
45
46 std::string filename = "package.json";
47 if (!this->packageFileNames.empty()) {
48 filename = this->packageFileNames[0];
49 }
50
51 cmsys::ofstream fout(filename.c_str());
52 std::unique_ptr<Json::StreamWriter> jout(builder.newStreamWriter());
53
54 Json::Value root(Json::objectValue);
55
56 if (!this->Generator->WriteToJSON(root)) {
57 return 0;
58 }
59
60 if (jout->write(root, &fout)) {
61 return 0;
62 }
63
64 cmValue packageScript = this->GetOption("CPACK_EXTERNAL_PACKAGE_SCRIPT");
65 if (cmNonempty(packageScript)) {
66 if (!cmSystemTools::FileIsFullPath(packageScript)) {
67 cmCPackLogger(
68 cmCPackLog::LOG_ERROR,
69 "CPACK_EXTERNAL_PACKAGE_SCRIPT does not contain a full file path"
70 << std::endl);
71 return 0;
72 }
73
74 bool res = this->MakefileMap->ReadListFile(packageScript);
75
76 if (cmSystemTools::GetErrorOccuredFlag() || !res) {
77 return 0;
78 }
79
80 cmValue builtPackages = this->GetOption("CPACK_EXTERNAL_BUILT_PACKAGES");
81 if (builtPackages) {
82 cmExpandList(builtPackages, this->packageFileNames, false);
83 }
84 }
85
86 return 1;
87 }
88
SupportsComponentInstallation() const89 bool cmCPackExternalGenerator::SupportsComponentInstallation() const
90 {
91 return true;
92 }
93
InstallProjectViaInstallCommands(bool setDestDir,const std::string & tempInstallDirectory)94 int cmCPackExternalGenerator::InstallProjectViaInstallCommands(
95 bool setDestDir, const std::string& tempInstallDirectory)
96 {
97 if (this->StagingEnabled()) {
98 return this->cmCPackGenerator::InstallProjectViaInstallCommands(
99 setDestDir, tempInstallDirectory);
100 }
101
102 return 1;
103 }
104
InstallProjectViaInstallScript(bool setDestDir,const std::string & tempInstallDirectory)105 int cmCPackExternalGenerator::InstallProjectViaInstallScript(
106 bool setDestDir, const std::string& tempInstallDirectory)
107 {
108 if (this->StagingEnabled()) {
109 return this->cmCPackGenerator::InstallProjectViaInstallScript(
110 setDestDir, tempInstallDirectory);
111 }
112
113 return 1;
114 }
115
InstallProjectViaInstalledDirectories(bool setDestDir,const std::string & tempInstallDirectory,const mode_t * default_dir_mode)116 int cmCPackExternalGenerator::InstallProjectViaInstalledDirectories(
117 bool setDestDir, const std::string& tempInstallDirectory,
118 const mode_t* default_dir_mode)
119 {
120 if (this->StagingEnabled()) {
121 return this->cmCPackGenerator::InstallProjectViaInstalledDirectories(
122 setDestDir, tempInstallDirectory, default_dir_mode);
123 }
124
125 return 1;
126 }
127
RunPreinstallTarget(const std::string & installProjectName,const std::string & installDirectory,cmGlobalGenerator * globalGenerator,const std::string & buildConfig)128 int cmCPackExternalGenerator::RunPreinstallTarget(
129 const std::string& installProjectName, const std::string& installDirectory,
130 cmGlobalGenerator* globalGenerator, const std::string& buildConfig)
131 {
132 if (this->StagingEnabled()) {
133 return this->cmCPackGenerator::RunPreinstallTarget(
134 installProjectName, installDirectory, globalGenerator, buildConfig);
135 }
136
137 return 1;
138 }
139
InstallCMakeProject(bool setDestDir,const std::string & installDirectory,const std::string & baseTempInstallDirectory,const mode_t * default_dir_mode,const std::string & component,bool componentInstall,const std::string & installSubDirectory,const std::string & buildConfig,std::string & absoluteDestFiles)140 int cmCPackExternalGenerator::InstallCMakeProject(
141 bool setDestDir, const std::string& installDirectory,
142 const std::string& baseTempInstallDirectory, const mode_t* default_dir_mode,
143 const std::string& component, bool componentInstall,
144 const std::string& installSubDirectory, const std::string& buildConfig,
145 std::string& absoluteDestFiles)
146 {
147 if (this->StagingEnabled()) {
148 return this->cmCPackGenerator::InstallCMakeProject(
149 setDestDir, installDirectory, baseTempInstallDirectory, default_dir_mode,
150 component, componentInstall, installSubDirectory, buildConfig,
151 absoluteDestFiles);
152 }
153
154 return 1;
155 }
156
StagingEnabled() const157 bool cmCPackExternalGenerator::StagingEnabled() const
158 {
159 return !cmIsOff(this->GetOption("CPACK_EXTERNAL_ENABLE_STAGING"));
160 }
161
162 cmCPackExternalGenerator::cmCPackExternalVersionGenerator::
cmCPackExternalVersionGenerator(cmCPackExternalGenerator * parent)163 cmCPackExternalVersionGenerator(cmCPackExternalGenerator* parent)
164 : Parent(parent)
165 {
166 }
167
WriteVersion(Json::Value & root)168 int cmCPackExternalGenerator::cmCPackExternalVersionGenerator::WriteVersion(
169 Json::Value& root)
170 {
171 root["formatVersionMajor"] = this->GetVersionMajor();
172 root["formatVersionMinor"] = this->GetVersionMinor();
173
174 return 1;
175 }
176
WriteToJSON(Json::Value & root)177 int cmCPackExternalGenerator::cmCPackExternalVersionGenerator::WriteToJSON(
178 Json::Value& root)
179 {
180 if (!this->WriteVersion(root)) {
181 return 0;
182 }
183
184 cmValue packageName = this->Parent->GetOption("CPACK_PACKAGE_NAME");
185 if (packageName) {
186 root["packageName"] = *packageName;
187 }
188
189 cmValue packageVersion = this->Parent->GetOption("CPACK_PACKAGE_VERSION");
190 if (packageVersion) {
191 root["packageVersion"] = *packageVersion;
192 }
193
194 cmValue packageDescriptionFile =
195 this->Parent->GetOption("CPACK_PACKAGE_DESCRIPTION_FILE");
196 if (packageDescriptionFile) {
197 root["packageDescriptionFile"] = *packageDescriptionFile;
198 }
199
200 cmValue packageDescriptionSummary =
201 this->Parent->GetOption("CPACK_PACKAGE_DESCRIPTION_SUMMARY");
202 if (packageDescriptionSummary) {
203 root["packageDescriptionSummary"] = *packageDescriptionSummary;
204 }
205
206 cmValue buildConfigCstr = this->Parent->GetOption("CPACK_BUILD_CONFIG");
207 if (buildConfigCstr) {
208 root["buildConfig"] = *buildConfigCstr;
209 }
210
211 cmValue defaultDirectoryPermissions =
212 this->Parent->GetOption("CPACK_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS");
213 if (cmNonempty(defaultDirectoryPermissions)) {
214 root["defaultDirectoryPermissions"] = *defaultDirectoryPermissions;
215 }
216 if (cmIsInternallyOn(this->Parent->GetOption("CPACK_SET_DESTDIR"))) {
217 root["setDestdir"] = true;
218 root["packagingInstallPrefix"] =
219 *this->Parent->GetOption("CPACK_PACKAGING_INSTALL_PREFIX");
220 } else {
221 root["setDestdir"] = false;
222 }
223
224 root["stripFiles"] = !cmIsOff(this->Parent->GetOption("CPACK_STRIP_FILES"));
225 root["warnOnAbsoluteInstallDestination"] =
226 this->Parent->IsOn("CPACK_WARN_ON_ABSOLUTE_INSTALL_DESTINATION");
227 root["errorOnAbsoluteInstallDestination"] =
228 this->Parent->IsOn("CPACK_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION");
229
230 Json::Value& projects = root["projects"] = Json::Value(Json::arrayValue);
231 for (auto& project : this->Parent->CMakeProjects) {
232 Json::Value jsonProject(Json::objectValue);
233
234 jsonProject["projectName"] = project.ProjectName;
235 jsonProject["component"] = project.Component;
236 jsonProject["directory"] = project.Directory;
237 jsonProject["subDirectory"] = project.SubDirectory;
238
239 Json::Value& installationTypes = jsonProject["installationTypes"] =
240 Json::Value(Json::arrayValue);
241 for (auto& installationType : project.InstallationTypes) {
242 installationTypes.append(installationType->Name);
243 }
244
245 Json::Value& components = jsonProject["components"] =
246 Json::Value(Json::arrayValue);
247 for (auto& component : project.Components) {
248 components.append(component->Name);
249 }
250
251 projects.append(jsonProject);
252 }
253
254 Json::Value& installationTypes = root["installationTypes"] =
255 Json::Value(Json::objectValue);
256 for (auto& installationType : this->Parent->InstallationTypes) {
257 Json::Value& jsonInstallationType =
258 installationTypes[installationType.first] =
259 Json::Value(Json::objectValue);
260
261 jsonInstallationType["name"] = installationType.second.Name;
262 jsonInstallationType["displayName"] = installationType.second.DisplayName;
263 jsonInstallationType["index"] = installationType.second.Index;
264 }
265
266 Json::Value& components = root["components"] =
267 Json::Value(Json::objectValue);
268 for (auto& component : this->Parent->Components) {
269 Json::Value& jsonComponent = components[component.first] =
270 Json::Value(Json::objectValue);
271
272 jsonComponent["name"] = component.second.Name;
273 jsonComponent["displayName"] = component.second.DisplayName;
274 if (component.second.Group) {
275 jsonComponent["group"] = component.second.Group->Name;
276 }
277 jsonComponent["isRequired"] = component.second.IsRequired;
278 jsonComponent["isHidden"] = component.second.IsHidden;
279 jsonComponent["isDisabledByDefault"] =
280 component.second.IsDisabledByDefault;
281 jsonComponent["isDownloaded"] = component.second.IsDownloaded;
282 jsonComponent["description"] = component.second.Description;
283 jsonComponent["archiveFile"] = component.second.ArchiveFile;
284
285 Json::Value& cmpInstallationTypes = jsonComponent["installationTypes"] =
286 Json::Value(Json::arrayValue);
287 for (auto& installationType : component.second.InstallationTypes) {
288 cmpInstallationTypes.append(installationType->Name);
289 }
290
291 Json::Value& dependencies = jsonComponent["dependencies"] =
292 Json::Value(Json::arrayValue);
293 for (auto& dep : component.second.Dependencies) {
294 dependencies.append(dep->Name);
295 }
296 }
297
298 Json::Value& groups = root["componentGroups"] =
299 Json::Value(Json::objectValue);
300 for (auto& group : this->Parent->ComponentGroups) {
301 Json::Value& jsonGroup = groups[group.first] =
302 Json::Value(Json::objectValue);
303
304 jsonGroup["name"] = group.second.Name;
305 jsonGroup["displayName"] = group.second.DisplayName;
306 jsonGroup["description"] = group.second.Description;
307 jsonGroup["isBold"] = group.second.IsBold;
308 jsonGroup["isExpandedByDefault"] = group.second.IsExpandedByDefault;
309 if (group.second.ParentGroup) {
310 jsonGroup["parentGroup"] = group.second.ParentGroup->Name;
311 }
312
313 Json::Value& subgroups = jsonGroup["subgroups"] =
314 Json::Value(Json::arrayValue);
315 for (auto& subgroup : group.second.Subgroups) {
316 subgroups.append(subgroup->Name);
317 }
318
319 Json::Value& groupComponents = jsonGroup["components"] =
320 Json::Value(Json::arrayValue);
321 for (auto& component : group.second.Components) {
322 groupComponents.append(component->Name);
323 }
324 }
325
326 return 1;
327 }
328