mirror of
https://github.com/reactos/CMake.git
synced 2025-03-03 17:39:10 +00:00

On Windows, libuv uses `_CrtSetReportHook` to install a handler it uses to suppress assertions on invalid file descriptors in `_get_osfhandle`. This removes the handler we install in CI environments to suppress interactive popups. Move installation of our handler to after libuv is initialized so that our handler is actually used. Unfortunately this also removes libuv's handler and so may cause Debug builds under CI to abort on invalid file descriptors instead of simply converting them to `INVALID_HANDLE_VALUE`. If this becomes a problem we may need to modify libuv to make its hook more configurable.
479 lines
17 KiB
C++
479 lines
17 KiB
C++
/* 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 "cmCPackGenerator.h"
|
|
#include "cmCPackGeneratorFactory.h"
|
|
#include "cmCPackLog.h"
|
|
#include "cmDocumentation.h"
|
|
#include "cmDocumentationEntry.h"
|
|
#include "cmDocumentationFormatter.h"
|
|
#include "cmGlobalGenerator.h"
|
|
#include "cmMakefile.h"
|
|
#include "cmState.h"
|
|
#include "cmStateSnapshot.h"
|
|
#include "cmStringAlgorithms.h"
|
|
#include "cmSystemTools.h"
|
|
#include "cmake.h"
|
|
|
|
#if defined(_WIN32) && !defined(CMAKE_BOOTSTRAP)
|
|
# include "cmsys/ConsoleBuf.hxx"
|
|
#endif
|
|
|
|
#include <cstddef>
|
|
#include <iostream>
|
|
#include <map>
|
|
#include <memory>
|
|
#include <sstream>
|
|
#include <string>
|
|
#include <utility>
|
|
#include <vector>
|
|
|
|
namespace {
|
|
const char* cmDocumentationName[][2] = {
|
|
{ nullptr, " cpack - Packaging driver provided by CMake." },
|
|
{ nullptr, nullptr }
|
|
};
|
|
|
|
const char* cmDocumentationUsage[][2] = {
|
|
// clang-format off
|
|
{ nullptr, " cpack [options]" },
|
|
{ nullptr, nullptr }
|
|
// clang-format on
|
|
};
|
|
|
|
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
|
|
{
|
|
using MapType = std::map<std::string, std::string>;
|
|
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.substr(pos + 1);
|
|
def->Map[key] = value;
|
|
cmCPack_Log(def->Log, cmCPackLog::LOG_DEBUG,
|
|
"Set CPack variable: " << key << " to \"" << value << "\""
|
|
<< std::endl);
|
|
return 1;
|
|
}
|
|
|
|
void cpackProgressCallback(const std::string& message, float /*unused*/)
|
|
{
|
|
std::cout << "-- " << message << std::endl;
|
|
}
|
|
} // namespace
|
|
|
|
// this is CPack.
|
|
int main(int argc, char const* const* argv)
|
|
{
|
|
cmSystemTools::EnsureStdPipes();
|
|
#if defined(_WIN32) && !defined(CMAKE_BOOTSTRAP)
|
|
// 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::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);
|
|
using argT = cmsys::CommandLineArguments;
|
|
// 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, cmState::CPack);
|
|
cminst.SetHomeDirectory("");
|
|
cminst.SetHomeOutputDirectory("");
|
|
cminst.SetProgressCallback(cpackProgressCallback);
|
|
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 = cmStrCat(cmSystemTools::GetCurrentWorkingDirectory(),
|
|
"/CPackConfig.cmake");
|
|
cpackConfigFileSpecified = false;
|
|
}
|
|
|
|
cmCPackGeneratorFactory generators;
|
|
generators.SetLogger(&log);
|
|
|
|
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)) {
|
|
cmCPack_Log(&log, cmCPackLog::LOG_ERROR,
|
|
"Error reading CMakeDetermineSystem.cmake" << std::endl);
|
|
return 1;
|
|
}
|
|
|
|
systemFile =
|
|
globalMF.GetModulesFile("CMakeSystemSpecificInformation.cmake");
|
|
if (!globalMF.ReadListFile(systemFile)) {
|
|
cmCPack_Log(&log, cmCPackLog::LOG_ERROR,
|
|
"Error reading CMakeSystemSpecificInformation.cmake"
|
|
<< std::endl);
|
|
return 1;
|
|
}
|
|
|
|
if (!cpackBuildConfig.empty()) {
|
|
globalMF.AddDefinition("CPACK_BUILD_CONFIG", cpackBuildConfig);
|
|
}
|
|
|
|
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)) {
|
|
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);
|
|
}
|
|
if (!cpackProjectName.empty()) {
|
|
globalMF.AddDefinition("CPACK_PACKAGE_NAME", cpackProjectName);
|
|
}
|
|
if (!cpackProjectVersion.empty()) {
|
|
globalMF.AddDefinition("CPACK_PACKAGE_VERSION", cpackProjectVersion);
|
|
}
|
|
if (!cpackProjectVendor.empty()) {
|
|
globalMF.AddDefinition("CPACK_PACKAGE_VENDOR", cpackProjectVendor);
|
|
}
|
|
// 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);
|
|
}
|
|
// 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 if no value has been provided by the config file
|
|
if (!globalMF.IsSet("CPACK_PACKAGE_DIRECTORY")) {
|
|
globalMF.AddDefinition("CPACK_PACKAGE_DIRECTORY",
|
|
cpackProjectDirectory);
|
|
}
|
|
}
|
|
for (auto const& cd : definitions.Map) {
|
|
globalMF.AddDefinition(cd.first, cd.second);
|
|
}
|
|
|
|
// Force CPACK_PACKAGE_DIRECTORY as absolute path
|
|
cpackProjectDirectory = globalMF.GetDefinition("CPACK_PACKAGE_DIRECTORY");
|
|
cpackProjectDirectory =
|
|
cmSystemTools::CollapseFullPath(cpackProjectDirectory);
|
|
globalMF.AddDefinition("CPACK_PACKAGE_DIRECTORY", cpackProjectDirectory);
|
|
|
|
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 = cmExpandedList(genList);
|
|
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) {
|
|
std::unique_ptr<cmCPackGenerator> cpackGenerator =
|
|
generators.NewGenerator(gen);
|
|
if (cpackGenerator) {
|
|
cpackGenerator->SetTrace(trace);
|
|
cpackGenerator->SetTraceExpand(traceExpand);
|
|
} else {
|
|
cmCPack_Log(&log, cmCPackLog::LOG_ERROR,
|
|
"Could not create CPack generator: " << gen
|
|
<< std::endl);
|
|
// Print out all the valid generators
|
|
cmDocumentation generatorDocs;
|
|
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));
|
|
}
|
|
generatorDocs.SetSection("Generators", v);
|
|
std::cerr << "\n";
|
|
generatorDocs.PrintDocumentation(cmDocumentation::ListGenerators,
|
|
std::cerr);
|
|
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());
|
|
}
|
|
|
|
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;
|
|
}
|