Imported Upstream version 3.25.0
[platform/upstream/cmake.git] / Source / CPack / cpack.cxx
1 /* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
2    file Copyright.txt or https://cmake.org/licensing for details.  */
3
4 #include <algorithm>
5 #include <cstddef>
6 #include <functional>
7 #include <iostream>
8 #include <map>
9 #include <memory>
10 #include <sstream>
11 #include <string>
12 #include <utility>
13 #include <vector>
14
15 #include <cm/optional>
16 #include <cmext/algorithm>
17
18 #include "cmsys/Encoding.hxx"
19
20 #include "cmCMakePresetsGraph.h"
21 #include "cmCPackGenerator.h"
22 #include "cmCPackGeneratorFactory.h"
23 #include "cmCPackLog.h"
24 #include "cmCommandLineArgument.h"
25 #include "cmConsoleBuf.h"
26 #include "cmDocumentation.h"
27 #include "cmDocumentationEntry.h"
28 #include "cmDocumentationFormatter.h"
29 #include "cmGlobalGenerator.h"
30 #include "cmMakefile.h"
31 #include "cmState.h"
32 #include "cmStateSnapshot.h"
33 #include "cmStringAlgorithms.h"
34 #include "cmSystemTools.h"
35 #include "cmValue.h"
36 #include "cmake.h"
37
38 namespace {
39 const char* cmDocumentationName[][2] = {
40   { nullptr, "  cpack - Packaging driver provided by CMake." },
41   { nullptr, nullptr }
42 };
43
44 const char* cmDocumentationUsage[][2] = {
45   // clang-format off
46   { nullptr, "  cpack [options]" },
47   { nullptr, nullptr }
48   // clang-format on
49 };
50
51 const char* cmDocumentationOptions[][2] = {
52   { "-G <generators>", "Override/define CPACK_GENERATOR" },
53   { "-C <Configuration>", "Specify the project configuration" },
54   { "-D <var>=<value>", "Set a CPack variable." },
55   { "--config <configFile>", "Specify the config file." },
56   { "-V,--verbose", "Enable verbose output" },
57   { "--trace", "Put underlying cmake scripts in trace mode." },
58   { "--trace-expand", "Put underlying cmake scripts in expanded trace mode." },
59   { "--debug", "Enable debug output (for CPack developers)" },
60   { "-P <packageName>", "Override/define CPACK_PACKAGE_NAME" },
61   { "-R <packageVersion>", "Override/define CPACK_PACKAGE_VERSION" },
62   { "-B <packageDirectory>", "Override/define CPACK_PACKAGE_DIRECTORY" },
63   { "--vendor <vendorName>", "Override/define CPACK_PACKAGE_VENDOR" },
64   { "--preset", "Read arguments from a package preset" },
65   { "--list-presets", "List available package presets" },
66   { nullptr, nullptr }
67 };
68
69 void cpackProgressCallback(const std::string& message, float /*unused*/)
70 {
71   std::cout << "-- " << message << std::endl;
72 }
73 } // namespace
74
75 // this is CPack.
76 int main(int argc, char const* const* argv)
77 {
78   cmSystemTools::EnsureStdPipes();
79
80   // Replace streambuf so we can output Unicode to console
81   cmConsoleBuf consoleBuf;
82   consoleBuf.SetUTF8Pipes();
83
84   cmsys::Encoding::CommandLineArguments args =
85     cmsys::Encoding::CommandLineArguments::Main(argc, argv);
86   argc = args.argc();
87   argv = args.argv();
88
89   std::vector<std::string> inputArgs;
90   inputArgs.reserve(argc - 1);
91   cm::append(inputArgs, argv + 1, argv + argc);
92
93   cmSystemTools::InitializeLibUV();
94   cmSystemTools::FindCMakeResources(argv[0]);
95   cmCPackLog log;
96
97   log.SetErrorPrefix("CPack Error: ");
98   log.SetWarningPrefix("CPack Warning: ");
99   log.SetOutputPrefix("CPack: ");
100   log.SetVerbosePrefix("CPack Verbose: ");
101
102   if (cmSystemTools::GetCurrentWorkingDirectory().empty()) {
103     cmCPack_Log(&log, cmCPackLog::LOG_ERROR,
104                 "Current working directory cannot be established."
105                   << std::endl);
106     return 1;
107   }
108
109   std::string generator;
110   bool help = false;
111   bool helpVersion = false;
112   std::string helpFull;
113   std::string helpMAN;
114   std::string helpHTML;
115
116   std::string cpackProjectName;
117   std::string cpackProjectDirectory;
118   std::string cpackBuildConfig;
119   std::string cpackProjectVersion;
120   std::string cpackProjectPatch;
121   std::string cpackProjectVendor;
122   std::string cpackConfigFile;
123
124   std::string preset;
125   bool listPresets = false;
126
127   std::map<std::string, std::string> definitions;
128
129   auto const verboseLambda = [&log](const std::string&, cmake*,
130                                     cmMakefile*) -> bool {
131     log.SetVerbose(true);
132     cmCPack_Log(&log, cmCPackLog::LOG_OUTPUT, "Enable Verbose" << std::endl);
133     return true;
134   };
135
136   auto const debugLambda = [&log](const std::string&, cmake*,
137                                   cmMakefile*) -> bool {
138     log.SetDebug(true);
139     cmCPack_Log(&log, cmCPackLog::LOG_OUTPUT, "Enable Debug" << std::endl);
140     return true;
141   };
142
143   auto const traceLambda = [](const std::string&, cmake* state,
144                               cmMakefile*) -> bool {
145     state->SetTrace(true);
146     return true;
147   };
148
149   auto const traceExpandLambda = [](const std::string&, cmake* state,
150                                     cmMakefile*) -> bool {
151     state->SetTrace(true);
152     state->SetTraceExpand(true);
153     return true;
154   };
155
156   using CommandArgument =
157     cmCommandLineArgument<bool(std::string const&, cmake*, cmMakefile*)>;
158
159   std::vector<CommandArgument> arguments = {
160     CommandArgument{ "--help", CommandArgument::Values::Zero,
161                      CommandArgument::setToTrue(help) },
162     CommandArgument{ "--help-full", CommandArgument::Values::Zero,
163                      CommandArgument::setToValue(helpFull) },
164     CommandArgument{ "--help-html", CommandArgument::Values::Zero,
165                      CommandArgument::setToValue(helpHTML) },
166     CommandArgument{ "--help-man", CommandArgument::Values::Zero,
167                      CommandArgument::setToValue(helpMAN) },
168     CommandArgument{ "--version", CommandArgument::Values::Zero,
169                      CommandArgument::setToTrue(helpVersion) },
170     CommandArgument{ "-V", CommandArgument::Values::Zero, verboseLambda },
171     CommandArgument{ "--verbose", CommandArgument::Values::Zero,
172                      verboseLambda },
173     CommandArgument{ "--debug", CommandArgument::Values::Zero, debugLambda },
174     CommandArgument{ "--config", CommandArgument::Values::One,
175                      CommandArgument::setToValue(cpackConfigFile) },
176     CommandArgument{ "--trace", CommandArgument::Values::Zero, traceLambda },
177     CommandArgument{ "--trace-expand", CommandArgument::Values::Zero,
178                      traceExpandLambda },
179     CommandArgument{ "-C", CommandArgument::Values::One,
180                      CommandArgument::setToValue(cpackBuildConfig) },
181     CommandArgument{ "-G", CommandArgument::Values::One,
182                      CommandArgument::setToValue(generator) },
183     CommandArgument{ "-P", CommandArgument::Values::One,
184                      CommandArgument::setToValue(cpackProjectName) },
185     CommandArgument{ "-R", CommandArgument::Values::One,
186                      CommandArgument::setToValue(cpackProjectVersion) },
187     CommandArgument{ "-B", CommandArgument::Values::One,
188                      CommandArgument::setToValue(cpackProjectDirectory) },
189     CommandArgument{ "--patch", CommandArgument::Values::One,
190                      CommandArgument::setToValue(cpackProjectPatch) },
191     CommandArgument{ "--vendor", CommandArgument::Values::One,
192                      CommandArgument::setToValue(cpackProjectVendor) },
193     CommandArgument{ "--preset", CommandArgument::Values::One,
194                      CommandArgument::setToValue(preset) },
195     CommandArgument{ "--list-presets", CommandArgument::Values::Zero,
196                      CommandArgument::setToTrue(listPresets) },
197     CommandArgument{
198       "-D", CommandArgument::Values::One,
199       [&log, &definitions](const std::string& arg, cmake*,
200                            cmMakefile*) -> bool {
201         std::string value = arg;
202         size_t pos = value.find_first_of('=');
203         if (pos == std::string::npos) {
204           cmCPack_Log(&log, cmCPackLog::LOG_ERROR,
205                       "Please specify CPack definitions as: KEY=VALUE"
206                         << std::endl);
207           return false;
208         }
209         std::string key = value.substr(0, pos);
210         value.erase(0, pos + 1);
211         definitions[key] = value;
212         cmCPack_Log(&log, cmCPackLog::LOG_DEBUG,
213                     "Set CPack variable: " << key << " to \"" << value << "\""
214                                            << std::endl);
215         return true;
216       } },
217   };
218
219   cmake cminst(cmake::RoleScript, cmState::CPack);
220   cminst.SetHomeDirectory("");
221   cminst.SetHomeOutputDirectory("");
222   cminst.SetProgressCallback(cpackProgressCallback);
223   cminst.GetCurrentSnapshot().SetDefaultDefinitions();
224   cmGlobalGenerator cmgg(&cminst);
225   cmMakefile globalMF(&cmgg, cminst.GetCurrentSnapshot());
226 #if defined(__CYGWIN__)
227   globalMF.AddDefinition("CMAKE_LEGACY_CYGWIN_WIN32", "0");
228 #endif
229
230   bool parsed = true;
231   for (std::size_t i = 0; i < inputArgs.size(); i++) {
232     auto const& arg = inputArgs[i];
233     for (auto const& m : arguments) {
234       if (m.matches(arg)) {
235         if (!m.parse(arg, i, inputArgs, &cminst, &globalMF)) {
236           parsed = false;
237         }
238         break;
239       }
240     }
241   }
242
243   cmCPackGeneratorFactory generators;
244   generators.SetLogger(&log);
245
246   // Set up presets
247   if (!preset.empty() || listPresets) {
248     const auto workingDirectory = cmSystemTools::GetCurrentWorkingDirectory();
249
250     auto const presetGeneratorsPresent =
251       [&generators](const cmCMakePresetsGraph::PackagePreset& p) {
252         return std::all_of(p.Generators.begin(), p.Generators.end(),
253                            [&generators](const std::string& gen) {
254                              return generators.GetGeneratorsList().count(
255                                       gen) != 0;
256                            });
257       };
258
259     cmCMakePresetsGraph presetsGraph;
260     auto result = presetsGraph.ReadProjectPresets(workingDirectory);
261     if (result != cmCMakePresetsGraph::ReadFileResult::READ_OK) {
262       cmCPack_Log(&log, cmCPackLog::LOG_ERROR,
263                   "Could not read presets from "
264                     << workingDirectory << ": "
265                     << cmCMakePresetsGraph::ResultToString(result)
266                     << std::endl);
267       return 1;
268     }
269
270     if (listPresets) {
271       presetsGraph.PrintPackagePresetList(presetGeneratorsPresent);
272       return 0;
273     }
274
275     auto presetPair = presetsGraph.PackagePresets.find(preset);
276     if (presetPair == presetsGraph.PackagePresets.end()) {
277       cmCPack_Log(&log, cmCPackLog::LOG_ERROR,
278                   "No such package preset in " << workingDirectory << ": \""
279                                                << preset << '"' << std::endl);
280       presetsGraph.PrintPackagePresetList(presetGeneratorsPresent);
281       return 1;
282     }
283
284     if (presetPair->second.Unexpanded.Hidden) {
285       cmCPack_Log(&log, cmCPackLog::LOG_ERROR,
286                   "Cannot use hidden package preset in "
287                     << workingDirectory << ": \"" << preset << '"'
288                     << std::endl);
289       presetsGraph.PrintPackagePresetList(presetGeneratorsPresent);
290       return 1;
291     }
292
293     auto const& expandedPreset = presetPair->second.Expanded;
294     if (!expandedPreset) {
295       cmCPack_Log(&log, cmCPackLog::LOG_ERROR,
296                   "Could not evaluate package preset \""
297                     << preset << "\": Invalid macro expansion" << std::endl);
298       presetsGraph.PrintPackagePresetList(presetGeneratorsPresent);
299       return 1;
300     }
301
302     if (!expandedPreset->ConditionResult) {
303       cmCPack_Log(&log, cmCPackLog::LOG_ERROR,
304                   "Cannot use disabled package preset in "
305                     << workingDirectory << ": \"" << preset << '"'
306                     << std::endl);
307       presetsGraph.PrintPackagePresetList(presetGeneratorsPresent);
308       return 1;
309     }
310
311     if (!presetGeneratorsPresent(presetPair->second.Unexpanded)) {
312       cmCPack_Log(&log, cmCPackLog::LOG_ERROR, "Cannot use preset");
313       presetsGraph.PrintPackagePresetList(presetGeneratorsPresent);
314       return 1;
315     }
316
317     auto configurePresetPair =
318       presetsGraph.ConfigurePresets.find(expandedPreset->ConfigurePreset);
319     if (configurePresetPair == presetsGraph.ConfigurePresets.end()) {
320       cmCPack_Log(&log, cmCPackLog::LOG_ERROR,
321                   "No such configure preset in "
322                     << workingDirectory << ": \""
323                     << expandedPreset->ConfigurePreset << '"' << std::endl);
324       presetsGraph.PrintConfigurePresetList();
325       return 1;
326     }
327
328     if (configurePresetPair->second.Unexpanded.Hidden) {
329       cmCPack_Log(&log, cmCPackLog::LOG_ERROR,
330                   "Cannot use hidden configure preset in "
331                     << workingDirectory << ": \""
332                     << expandedPreset->ConfigurePreset << '"' << std::endl);
333       presetsGraph.PrintConfigurePresetList();
334       return 1;
335     }
336
337     auto const& expandedConfigurePreset = configurePresetPair->second.Expanded;
338     if (!expandedConfigurePreset) {
339       cmCPack_Log(&log, cmCPackLog::LOG_ERROR,
340                   "Could not evaluate configure preset \""
341                     << expandedPreset->ConfigurePreset
342                     << "\": Invalid macro expansion" << std::endl);
343       return 1;
344     }
345
346     cmSystemTools::ChangeDirectory(expandedConfigurePreset->BinaryDir);
347
348     auto presetEnvironment = expandedPreset->Environment;
349     for (auto const& var : presetEnvironment) {
350       if (var.second) {
351         cmSystemTools::PutEnv(cmStrCat(var.first, '=', *var.second));
352       }
353     }
354
355     if (!expandedPreset->ConfigFile.empty() && cpackConfigFile.empty()) {
356       cpackConfigFile = expandedPreset->ConfigFile;
357     }
358
359     if (!expandedPreset->Generators.empty() && generator.empty()) {
360       generator = cmJoin(expandedPreset->Generators, ";");
361     }
362
363     if (!expandedPreset->Configurations.empty() && cpackBuildConfig.empty()) {
364       cpackBuildConfig = cmJoin(expandedPreset->Configurations, ";");
365     }
366
367     definitions.insert(expandedPreset->Variables.begin(),
368                        expandedPreset->Variables.end());
369
370     if (expandedPreset->DebugOutput == true) {
371       debugLambda("", &cminst, &globalMF);
372     }
373
374     if (expandedPreset->VerboseOutput == true) {
375       verboseLambda("", &cminst, &globalMF);
376     }
377
378     if (!expandedPreset->PackageName.empty() && cpackProjectName.empty()) {
379       cpackProjectName = expandedPreset->PackageName;
380     }
381
382     if (!expandedPreset->PackageVersion.empty() &&
383         cpackProjectVersion.empty()) {
384       cpackProjectVersion = expandedPreset->PackageVersion;
385     }
386
387     if (!expandedPreset->PackageDirectory.empty() &&
388         cpackProjectDirectory.empty()) {
389       cpackProjectDirectory = expandedPreset->PackageDirectory;
390     }
391
392     if (!expandedPreset->VendorName.empty() && cpackProjectVendor.empty()) {
393       cpackProjectVendor = expandedPreset->VendorName;
394     }
395   }
396
397   cmCPack_Log(&log, cmCPackLog::LOG_VERBOSE,
398               "Read CPack config file: " << cpackConfigFile << std::endl);
399
400   bool cpackConfigFileSpecified = true;
401   if (cpackConfigFile.empty()) {
402     cpackConfigFile = cmStrCat(cmSystemTools::GetCurrentWorkingDirectory(),
403                                "/CPackConfig.cmake");
404     cpackConfigFileSpecified = false;
405   }
406
407   cmDocumentation doc;
408   doc.addCPackStandardDocSections();
409   /* Were we invoked to display doc or to do some work ?
410    * Unlike cmake launching cpack with zero argument
411    * should launch cpack using "cpackConfigFile" if it exists
412    * in the current directory.
413    */
414   help = doc.CheckOptions(argc, argv, "-G") && argc != 1;
415
416   // This part is used for cpack documentation lookup as well.
417   cminst.AddCMakePaths();
418
419   if (parsed && !help) {
420     // find out which system cpack is running on, so it can setup the search
421     // paths, so FIND_XXX() commands can be used in scripts
422     std::string systemFile =
423       globalMF.GetModulesFile("CMakeDetermineSystem.cmake");
424     if (!globalMF.ReadListFile(systemFile)) {
425       cmCPack_Log(&log, cmCPackLog::LOG_ERROR,
426                   "Error reading CMakeDetermineSystem.cmake" << std::endl);
427       return 1;
428     }
429
430     systemFile =
431       globalMF.GetModulesFile("CMakeSystemSpecificInformation.cmake");
432     if (!globalMF.ReadListFile(systemFile)) {
433       cmCPack_Log(&log, cmCPackLog::LOG_ERROR,
434                   "Error reading CMakeSystemSpecificInformation.cmake"
435                     << std::endl);
436       return 1;
437     }
438
439     if (!cpackBuildConfig.empty()) {
440       globalMF.AddDefinition("CPACK_BUILD_CONFIG", cpackBuildConfig);
441     }
442
443     if (cmSystemTools::FileExists(cpackConfigFile)) {
444       cpackConfigFile = cmSystemTools::CollapseFullPath(cpackConfigFile);
445       cmCPack_Log(&log, cmCPackLog::LOG_VERBOSE,
446                   "Read CPack configuration file: " << cpackConfigFile
447                                                     << std::endl);
448       if (!globalMF.ReadListFile(cpackConfigFile)) {
449         cmCPack_Log(&log, cmCPackLog::LOG_ERROR,
450                     "Problem reading CPack config file: \""
451                       << cpackConfigFile << "\"" << std::endl);
452         return 1;
453       }
454     } else if (cpackConfigFileSpecified) {
455       cmCPack_Log(&log, cmCPackLog::LOG_ERROR,
456                   "Cannot find CPack config file: \"" << cpackConfigFile
457                                                       << "\"" << std::endl);
458       return 1;
459     }
460
461     if (!generator.empty()) {
462       globalMF.AddDefinition("CPACK_GENERATOR", generator);
463     }
464     if (!cpackProjectName.empty()) {
465       globalMF.AddDefinition("CPACK_PACKAGE_NAME", cpackProjectName);
466     }
467     if (!cpackProjectVersion.empty()) {
468       globalMF.AddDefinition("CPACK_PACKAGE_VERSION", cpackProjectVersion);
469     }
470     if (!cpackProjectVendor.empty()) {
471       globalMF.AddDefinition("CPACK_PACKAGE_VENDOR", cpackProjectVendor);
472     }
473     // if this is not empty it has been set on the command line
474     // go for it. Command line override values set in config file.
475     if (!cpackProjectDirectory.empty()) {
476       globalMF.AddDefinition("CPACK_PACKAGE_DIRECTORY", cpackProjectDirectory);
477     }
478     // The value has not been set on the command line
479     else {
480       // get a default value (current working directory)
481       cpackProjectDirectory = cmSystemTools::GetCurrentWorkingDirectory();
482       // use default value if no value has been provided by the config file
483       if (!globalMF.IsSet("CPACK_PACKAGE_DIRECTORY")) {
484         globalMF.AddDefinition("CPACK_PACKAGE_DIRECTORY",
485                                cpackProjectDirectory);
486       }
487     }
488     for (auto const& cd : definitions) {
489       globalMF.AddDefinition(cd.first, cd.second);
490     }
491
492     // Force CPACK_PACKAGE_DIRECTORY as absolute path
493     cpackProjectDirectory =
494       globalMF.GetSafeDefinition("CPACK_PACKAGE_DIRECTORY");
495     cpackProjectDirectory =
496       cmSystemTools::CollapseFullPath(cpackProjectDirectory);
497     globalMF.AddDefinition("CPACK_PACKAGE_DIRECTORY", cpackProjectDirectory);
498
499     cmValue cpackModulesPath = globalMF.GetDefinition("CPACK_MODULE_PATH");
500     if (cpackModulesPath) {
501       globalMF.AddDefinition("CMAKE_MODULE_PATH", *cpackModulesPath);
502     }
503     cmValue genList = globalMF.GetDefinition("CPACK_GENERATOR");
504     if (!genList) {
505       cmCPack_Log(&log, cmCPackLog::LOG_ERROR,
506                   "CPack generator not specified" << std::endl);
507     } else {
508       std::vector<std::string> generatorsVector = cmExpandedList(*genList);
509       for (std::string const& gen : generatorsVector) {
510         cmMakefile::ScopePushPop raii(&globalMF);
511         cmMakefile* mf = &globalMF;
512         cmCPack_Log(&log, cmCPackLog::LOG_VERBOSE,
513                     "Specified generator: " << gen << std::endl);
514         if (!mf->GetDefinition("CPACK_PACKAGE_NAME")) {
515           cmCPack_Log(&log, cmCPackLog::LOG_ERROR,
516                       "CPack project name not specified" << std::endl);
517           parsed = false;
518         }
519         if (parsed &&
520             !(mf->GetDefinition("CPACK_PACKAGE_VERSION") ||
521               (mf->GetDefinition("CPACK_PACKAGE_VERSION_MAJOR") &&
522                mf->GetDefinition("CPACK_PACKAGE_VERSION_MINOR") &&
523                mf->GetDefinition("CPACK_PACKAGE_VERSION_PATCH")))) {
524           cmCPack_Log(&log, cmCPackLog::LOG_ERROR,
525                       "CPack project version not specified"
526                         << std::endl
527                         << "Specify CPACK_PACKAGE_VERSION, or "
528                            "CPACK_PACKAGE_VERSION_MAJOR, "
529                            "CPACK_PACKAGE_VERSION_MINOR, and "
530                            "CPACK_PACKAGE_VERSION_PATCH."
531                         << std::endl);
532           parsed = false;
533         }
534         if (parsed) {
535           std::unique_ptr<cmCPackGenerator> cpackGenerator =
536             generators.NewGenerator(gen);
537           if (cpackGenerator) {
538             cpackGenerator->SetTrace(cminst.GetTrace());
539             cpackGenerator->SetTraceExpand(cminst.GetTraceExpand());
540           } else {
541             cmCPack_Log(&log, cmCPackLog::LOG_ERROR,
542                         "Could not create CPack generator: " << gen
543                                                              << std::endl);
544             // Print out all the valid generators
545             cmDocumentation generatorDocs;
546             std::vector<cmDocumentationEntry> v;
547             for (auto const& g : generators.GetGeneratorsList()) {
548               cmDocumentationEntry e;
549               e.Name = g.first;
550               e.Brief = g.second;
551               v.push_back(std::move(e));
552             }
553             generatorDocs.SetSection("Generators", v);
554             std::cerr << "\n";
555             generatorDocs.PrintDocumentation(cmDocumentation::ListGenerators,
556                                              std::cerr);
557             parsed = false;
558           }
559
560           if (parsed && !cpackGenerator->Initialize(gen, mf)) {
561             cmCPack_Log(&log, cmCPackLog::LOG_ERROR,
562                         "Cannot initialize the generator " << gen
563                                                            << std::endl);
564             parsed = false;
565           }
566
567           if (!mf->GetDefinition("CPACK_INSTALL_COMMANDS") &&
568               !mf->GetDefinition("CPACK_INSTALL_SCRIPT") &&
569               !mf->GetDefinition("CPACK_INSTALLED_DIRECTORIES") &&
570               !mf->GetDefinition("CPACK_INSTALL_CMAKE_PROJECTS")) {
571             cmCPack_Log(
572               &log, cmCPackLog::LOG_ERROR,
573               "Please specify build tree of the project that uses CMake "
574               "using CPACK_INSTALL_CMAKE_PROJECTS, specify "
575               "CPACK_INSTALL_COMMANDS, CPACK_INSTALL_SCRIPT, or "
576               "CPACK_INSTALLED_DIRECTORIES."
577                 << std::endl);
578             parsed = false;
579           }
580           if (parsed) {
581             cmValue projName = mf->GetDefinition("CPACK_PACKAGE_NAME");
582             cmCPack_Log(&log, cmCPackLog::LOG_VERBOSE,
583                         "Use generator: " << cpackGenerator->GetNameOfClass()
584                                           << std::endl);
585             cmCPack_Log(&log, cmCPackLog::LOG_VERBOSE,
586                         "For project: " << *projName << std::endl);
587
588             cmValue projVersion = mf->GetDefinition("CPACK_PACKAGE_VERSION");
589             if (!projVersion) {
590               cmValue projVersionMajor =
591                 mf->GetDefinition("CPACK_PACKAGE_VERSION_MAJOR");
592               cmValue projVersionMinor =
593                 mf->GetDefinition("CPACK_PACKAGE_VERSION_MINOR");
594               cmValue projVersionPatch =
595                 mf->GetDefinition("CPACK_PACKAGE_VERSION_PATCH");
596               std::ostringstream ostr;
597               ostr << *projVersionMajor << "." << *projVersionMinor << "."
598                    << *projVersionPatch;
599               mf->AddDefinition("CPACK_PACKAGE_VERSION", ostr.str());
600             }
601
602             int res = cpackGenerator->DoPackage();
603             if (!res) {
604               cmCPack_Log(&log, cmCPackLog::LOG_ERROR,
605                           "Error when generating package: " << *projName
606                                                             << std::endl);
607               return 1;
608             }
609           }
610         }
611       }
612     }
613   }
614
615   /* In this case we are building the documentation object
616    * instance in order to create appropriate structure
617    * in order to satisfy the appropriate --help-xxx request
618    */
619   if (help) {
620     // Construct and print requested documentation.
621
622     doc.SetName("cpack");
623     doc.SetSection("Name", cmDocumentationName);
624     doc.SetSection("Usage", cmDocumentationUsage);
625     doc.PrependSection("Options", cmDocumentationOptions);
626
627     std::vector<cmDocumentationEntry> v;
628     for (auto const& g : generators.GetGeneratorsList()) {
629       cmDocumentationEntry e;
630       e.Name = g.first;
631       e.Brief = g.second;
632       v.push_back(std::move(e));
633     }
634     doc.SetSection("Generators", v);
635
636     return doc.PrintRequestedDocumentation(std::cout) ? 0 : 1;
637   }
638
639   if (cmSystemTools::GetErrorOccurredFlag()) {
640     return 1;
641   }
642
643   return 0;
644 }