| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451 | /* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying   file Copyright.txt or https://cmake.org/licensing for details.  */#include "cmsys/CommandLineArguments.hxx"#include "cmsys/Encoding.hxx"#include <iostream>#include <map>#include <memory> // IWYU pragma: keep#include <sstream>#include <stddef.h>#include <string>#include <utility>#include <vector>#if defined(_WIN32) && defined(CMAKE_BUILD_WITH_CMAKE)#  include "cmsys/ConsoleBuf.hxx"#endif#include "cmCPackGenerator.h"#include "cmCPackGeneratorFactory.h"#include "cmCPackLog.h"#include "cmDocumentation.h"#include "cmDocumentationEntry.h"#include "cmGlobalGenerator.h"#include "cmMakefile.h"#include "cmStateSnapshot.h"#include "cmSystemTools.h"#include "cmake.h"static const char* cmDocumentationName[][2] = {  { nullptr, "  cpack - Packaging driver provided by CMake." },  { nullptr, nullptr }};static const char* cmDocumentationUsage[][2] = {  // clang-format off  { nullptr, "  cpack [options]" },  { nullptr, nullptr }  // clang-format on};static const char* cmDocumentationOptions[][2] = {  { "-G <generators>", "Override/define CPACK_GENERATOR" },  { "-C <Configuration>", "Specify the project configuration" },  { "-D <var>=<value>", "Set a CPack variable." },  { "--config <configFile>", "Specify the config file." },  { "--verbose,-V", "Enable verbose output" },  { "--trace", "Put underlying cmake scripts in trace mode." },  { "--trace-expand", "Put underlying cmake scripts in expanded trace mode." },  { "--debug", "Enable debug output (for CPack developers)" },  { "-P <packageName>", "Override/define CPACK_PACKAGE_NAME" },  { "-R <packageVersion>", "Override/define CPACK_PACKAGE_VERSION" },  { "-B <packageDirectory>", "Override/define CPACK_PACKAGE_DIRECTORY" },  { "--vendor <vendorName>", "Override/define CPACK_PACKAGE_VENDOR" },  { nullptr, nullptr }};int cpackUnknownArgument(const char* /*unused*/, void* /*unused*/){  return 1;}struct cpackDefinitions{  typedef std::map<std::string, std::string> MapType;  MapType Map;  cmCPackLog* Log;};int cpackDefinitionArgument(const char* argument, const char* cValue,                            void* call_data){  (void)argument;  cpackDefinitions* def = static_cast<cpackDefinitions*>(call_data);  std::string value = cValue;  size_t pos = value.find_first_of('=');  if (pos == std::string::npos) {    cmCPack_Log(def->Log, cmCPackLog::LOG_ERROR,                "Please specify CPack definitions as: KEY=VALUE" << std::endl);    return 0;  }  std::string key = value.substr(0, pos);  value = value.c_str() + pos + 1;  def->Map[key] = value;  cmCPack_Log(def->Log, cmCPackLog::LOG_DEBUG,              "Set CPack variable: " << key << " to \"" << value << "\""                                     << std::endl);  return 1;}// this is CPack.int main(int argc, char const* const* argv){#if defined(_WIN32) && defined(CMAKE_BUILD_WITH_CMAKE)  // Replace streambuf so we can output Unicode to console  cmsys::ConsoleBuf::Manager consoleOut(std::cout);  consoleOut.SetUTF8Pipes();  cmsys::ConsoleBuf::Manager consoleErr(std::cerr, true);  consoleErr.SetUTF8Pipes();#endif  cmsys::Encoding::CommandLineArguments args =    cmsys::Encoding::CommandLineArguments::Main(argc, argv);  argc = args.argc();  argv = args.argv();  cmSystemTools::EnableMSVCDebugHook();  cmSystemTools::InitializeLibUV();  cmSystemTools::FindCMakeResources(argv[0]);  cmCPackLog log;  log.SetErrorPrefix("CPack Error: ");  log.SetWarningPrefix("CPack Warning: ");  log.SetOutputPrefix("CPack: ");  log.SetVerbosePrefix("CPack Verbose: ");  if (cmSystemTools::GetCurrentWorkingDirectory().empty()) {    cmCPack_Log(&log, cmCPackLog::LOG_ERROR,                "Current working directory cannot be established."                  << std::endl);    return 1;  }  std::string generator;  bool help = false;  bool helpVersion = false;  bool verbose = false;  bool trace = false;  bool traceExpand = false;  bool debug = false;  std::string helpFull;  std::string helpMAN;  std::string helpHTML;  std::string cpackProjectName;  std::string cpackProjectDirectory;  std::string cpackBuildConfig;  std::string cpackProjectVersion;  std::string cpackProjectPatch;  std::string cpackProjectVendor;  std::string cpackConfigFile;  cpackDefinitions definitions;  definitions.Log = &log;  cpackConfigFile.clear();  cmsys::CommandLineArguments arg;  arg.Initialize(argc, argv);  typedef cmsys::CommandLineArguments argT;  // Help arguments  arg.AddArgument("--help", argT::NO_ARGUMENT, &help, "CPack help");  arg.AddArgument("--help-full", argT::SPACE_ARGUMENT, &helpFull,                  "CPack help");  arg.AddArgument("--help-html", argT::SPACE_ARGUMENT, &helpHTML,                  "CPack help");  arg.AddArgument("--help-man", argT::SPACE_ARGUMENT, &helpMAN, "CPack help");  arg.AddArgument("--version", argT::NO_ARGUMENT, &helpVersion, "CPack help");  arg.AddArgument("-V", argT::NO_ARGUMENT, &verbose, "CPack verbose");  arg.AddArgument("--verbose", argT::NO_ARGUMENT, &verbose, "-V");  arg.AddArgument("--debug", argT::NO_ARGUMENT, &debug, "-V");  arg.AddArgument("--config", argT::SPACE_ARGUMENT, &cpackConfigFile,                  "CPack configuration file");  arg.AddArgument("--trace", argT::NO_ARGUMENT, &trace,                  "Put underlying cmake scripts in trace mode.");  arg.AddArgument("--trace-expand", argT::NO_ARGUMENT, &traceExpand,                  "Put underlying cmake scripts in expanded trace mode.");  arg.AddArgument("-C", argT::SPACE_ARGUMENT, &cpackBuildConfig,                  "CPack build configuration");  arg.AddArgument("-G", argT::SPACE_ARGUMENT, &generator, "CPack generator");  arg.AddArgument("-P", argT::SPACE_ARGUMENT, &cpackProjectName,                  "CPack project name");  arg.AddArgument("-R", argT::SPACE_ARGUMENT, &cpackProjectVersion,                  "CPack project version");  arg.AddArgument("-B", argT::SPACE_ARGUMENT, &cpackProjectDirectory,                  "CPack project directory");  arg.AddArgument("--patch", argT::SPACE_ARGUMENT, &cpackProjectPatch,                  "CPack project patch");  arg.AddArgument("--vendor", argT::SPACE_ARGUMENT, &cpackProjectVendor,                  "CPack project vendor");  arg.AddCallback("-D", argT::SPACE_ARGUMENT, cpackDefinitionArgument,                  &definitions, "CPack Definitions");  arg.SetUnknownArgumentCallback(cpackUnknownArgument);  // Parse command line  int parsed = arg.Parse();  // Setup logging  if (verbose) {    log.SetVerbose(verbose);    cmCPack_Log(&log, cmCPackLog::LOG_OUTPUT, "Enable Verbose" << std::endl);  }  if (debug) {    log.SetDebug(debug);    cmCPack_Log(&log, cmCPackLog::LOG_OUTPUT, "Enable Debug" << std::endl);  }  cmCPack_Log(&log, cmCPackLog::LOG_VERBOSE,              "Read CPack config file: " << cpackConfigFile << std::endl);  cmake cminst(cmake::RoleScript);  cminst.SetHomeDirectory("");  cminst.SetHomeOutputDirectory("");  cminst.GetCurrentSnapshot().SetDefaultDefinitions();  cmGlobalGenerator cmgg(&cminst);  cmMakefile globalMF(&cmgg, cminst.GetCurrentSnapshot());#if defined(__CYGWIN__)  globalMF.AddDefinition("CMAKE_LEGACY_CYGWIN_WIN32", "0");#endif  if (trace) {    cminst.SetTrace(true);  }  if (traceExpand) {    cminst.SetTrace(true);    cminst.SetTraceExpand(true);  }  bool cpackConfigFileSpecified = true;  if (cpackConfigFile.empty()) {    cpackConfigFile = cmSystemTools::GetCurrentWorkingDirectory();    cpackConfigFile += "/CPackConfig.cmake";    cpackConfigFileSpecified = false;  }  cmCPackGeneratorFactory generators;  generators.SetLogger(&log);  cmCPackGenerator* cpackGenerator = nullptr;  cmDocumentation doc;  doc.addCPackStandardDocSections();  /* Were we invoked to display doc or to do some work ?   * Unlike cmake launching cpack with zero argument   * should launch cpack using "cpackConfigFile" if it exists   * in the current directory.   */  help = doc.CheckOptions(argc, argv, "-G") && argc != 1;  // This part is used for cpack documentation lookup as well.  cminst.AddCMakePaths();  if (parsed && !help) {    // find out which system cpack is running on, so it can setup the search    // paths, so FIND_XXX() commands can be used in scripts    std::string systemFile =      globalMF.GetModulesFile("CMakeDetermineSystem.cmake");    if (!globalMF.ReadListFile(systemFile.c_str())) {      cmCPack_Log(&log, cmCPackLog::LOG_ERROR,                  "Error reading CMakeDetermineSystem.cmake" << std::endl);      return 1;    }    systemFile =      globalMF.GetModulesFile("CMakeSystemSpecificInformation.cmake");    if (!globalMF.ReadListFile(systemFile.c_str())) {      cmCPack_Log(&log, cmCPackLog::LOG_ERROR,                  "Error reading CMakeSystemSpecificInformation.cmake"                    << std::endl);      return 1;    }    if (!cpackBuildConfig.empty()) {      globalMF.AddDefinition("CPACK_BUILD_CONFIG", cpackBuildConfig.c_str());    }    if (cmSystemTools::FileExists(cpackConfigFile)) {      cpackConfigFile = cmSystemTools::CollapseFullPath(cpackConfigFile);      cmCPack_Log(&log, cmCPackLog::LOG_VERBOSE,                  "Read CPack configuration file: " << cpackConfigFile                                                    << std::endl);      if (!globalMF.ReadListFile(cpackConfigFile.c_str())) {        cmCPack_Log(&log, cmCPackLog::LOG_ERROR,                    "Problem reading CPack config file: \""                      << cpackConfigFile << "\"" << std::endl);        return 1;      }    } else if (cpackConfigFileSpecified) {      cmCPack_Log(&log, cmCPackLog::LOG_ERROR,                  "Cannot find CPack config file: \"" << cpackConfigFile                                                      << "\"" << std::endl);      return 1;    }    if (!generator.empty()) {      globalMF.AddDefinition("CPACK_GENERATOR", generator.c_str());    }    if (!cpackProjectName.empty()) {      globalMF.AddDefinition("CPACK_PACKAGE_NAME", cpackProjectName.c_str());    }    if (!cpackProjectVersion.empty()) {      globalMF.AddDefinition("CPACK_PACKAGE_VERSION",                             cpackProjectVersion.c_str());    }    if (!cpackProjectVendor.empty()) {      globalMF.AddDefinition("CPACK_PACKAGE_VENDOR",                             cpackProjectVendor.c_str());    }    // if this is not empty it has been set on the command line    // go for it. Command line override values set in config file.    if (!cpackProjectDirectory.empty()) {      globalMF.AddDefinition("CPACK_PACKAGE_DIRECTORY",                             cpackProjectDirectory.c_str());    }    // The value has not been set on the command line    else {      // get a default value (current working directory)      cpackProjectDirectory = cmsys::SystemTools::GetCurrentWorkingDirectory();      // use default value iff no value has been provided by the config file      if (!globalMF.IsSet("CPACK_PACKAGE_DIRECTORY")) {        globalMF.AddDefinition("CPACK_PACKAGE_DIRECTORY",                               cpackProjectDirectory.c_str());      }    }    for (auto const& cd : definitions.Map) {      globalMF.AddDefinition(cd.first, cd.second.c_str());    }    const char* cpackModulesPath = globalMF.GetDefinition("CPACK_MODULE_PATH");    if (cpackModulesPath) {      globalMF.AddDefinition("CMAKE_MODULE_PATH", cpackModulesPath);    }    const char* genList = globalMF.GetDefinition("CPACK_GENERATOR");    if (!genList) {      cmCPack_Log(&log, cmCPackLog::LOG_ERROR,                  "CPack generator not specified" << std::endl);    } else {      std::vector<std::string> generatorsVector;      cmSystemTools::ExpandListArgument(genList, generatorsVector);      for (std::string const& gen : generatorsVector) {        cmMakefile::ScopePushPop raii(&globalMF);        cmMakefile* mf = &globalMF;        cmCPack_Log(&log, cmCPackLog::LOG_VERBOSE,                    "Specified generator: " << gen << std::endl);        if (parsed && !mf->GetDefinition("CPACK_PACKAGE_NAME")) {          cmCPack_Log(&log, cmCPackLog::LOG_ERROR,                      "CPack project name not specified" << std::endl);          parsed = 0;        }        if (parsed &&            !(mf->GetDefinition("CPACK_PACKAGE_VERSION") ||              (mf->GetDefinition("CPACK_PACKAGE_VERSION_MAJOR") &&               mf->GetDefinition("CPACK_PACKAGE_VERSION_MINOR") &&               mf->GetDefinition("CPACK_PACKAGE_VERSION_PATCH")))) {          cmCPack_Log(&log, cmCPackLog::LOG_ERROR,                      "CPack project version not specified"                        << std::endl                        << "Specify CPACK_PACKAGE_VERSION, or "                           "CPACK_PACKAGE_VERSION_MAJOR, "                           "CPACK_PACKAGE_VERSION_MINOR, and "                           "CPACK_PACKAGE_VERSION_PATCH."                        << std::endl);          parsed = 0;        }        if (parsed) {          cpackGenerator = generators.NewGenerator(gen);          if (cpackGenerator) {            cpackGenerator->SetTrace(trace);            cpackGenerator->SetTraceExpand(traceExpand);          } else {            cmCPack_Log(&log, cmCPackLog::LOG_ERROR,                        "Cannot initialize CPack generator: " << gen                                                              << std::endl);            parsed = 0;          }          if (parsed && !cpackGenerator->Initialize(gen, mf)) {            cmCPack_Log(&log, cmCPackLog::LOG_ERROR,                        "Cannot initialize the generator " << gen                                                           << std::endl);            parsed = 0;          }          if (!mf->GetDefinition("CPACK_INSTALL_COMMANDS") &&              !mf->GetDefinition("CPACK_INSTALL_SCRIPT") &&              !mf->GetDefinition("CPACK_INSTALLED_DIRECTORIES") &&              !mf->GetDefinition("CPACK_INSTALL_CMAKE_PROJECTS")) {            cmCPack_Log(              &log, cmCPackLog::LOG_ERROR,              "Please specify build tree of the project that uses CMake "              "using CPACK_INSTALL_CMAKE_PROJECTS, specify "              "CPACK_INSTALL_COMMANDS, CPACK_INSTALL_SCRIPT, or "              "CPACK_INSTALLED_DIRECTORIES."                << std::endl);            parsed = 0;          }          if (parsed) {            const char* projName = mf->GetDefinition("CPACK_PACKAGE_NAME");            cmCPack_Log(&log, cmCPackLog::LOG_VERBOSE,                        "Use generator: " << cpackGenerator->GetNameOfClass()                                          << std::endl);            cmCPack_Log(&log, cmCPackLog::LOG_VERBOSE,                        "For project: " << projName << std::endl);            const char* projVersion =              mf->GetDefinition("CPACK_PACKAGE_VERSION");            if (!projVersion) {              const char* projVersionMajor =                mf->GetDefinition("CPACK_PACKAGE_VERSION_MAJOR");              const char* projVersionMinor =                mf->GetDefinition("CPACK_PACKAGE_VERSION_MINOR");              const char* projVersionPatch =                mf->GetDefinition("CPACK_PACKAGE_VERSION_PATCH");              std::ostringstream ostr;              ostr << projVersionMajor << "." << projVersionMinor << "."                   << projVersionPatch;              mf->AddDefinition("CPACK_PACKAGE_VERSION", ostr.str().c_str());            }            int res = cpackGenerator->DoPackage();            if (!res) {              cmCPack_Log(&log, cmCPackLog::LOG_ERROR,                          "Error when generating package: " << projName                                                            << std::endl);              return 1;            }          }        }      }    }  }  /* In this case we are building the documentation object   * instance in order to create appropriate structure   * in order to satisfy the appropriate --help-xxx request   */  if (help) {    // Construct and print requested documentation.    doc.SetName("cpack");    doc.SetSection("Name", cmDocumentationName);    doc.SetSection("Usage", cmDocumentationUsage);    doc.PrependSection("Options", cmDocumentationOptions);    std::vector<cmDocumentationEntry> v;    for (auto const& g : generators.GetGeneratorsList()) {      cmDocumentationEntry e;      e.Name = g.first;      e.Brief = g.second;      v.push_back(std::move(e));    }    doc.SetSection("Generators", v);    return doc.PrintRequestedDocumentation(std::cout) ? 0 : 1;  }  if (cmSystemTools::GetErrorOccuredFlag()) {    return 1;  }  return 0;}
 |