diff options
Diffstat (limited to 'Source')
93 files changed, 1567 insertions, 641 deletions
diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index a4dd918..f15dff8 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -936,8 +936,13 @@ if(UNIX) endif() endif() -if(WIN32) +if(CYGWIN) + find_package(LibUUID) +endif() +if(WIN32 OR (CYGWIN AND LibUUID_FOUND)) set(CPACK_SRCS ${CPACK_SRCS} + CPack/Wix/cmCMakeToWixPath.cxx + CPack/Wix/cmCMakeToWixPath.h CPack/WiX/cmCPackWIXGenerator.cxx CPack/WiX/cmCPackWIXGenerator.h CPack/WiX/cmWIXAccessControlList.cxx @@ -958,7 +963,7 @@ if(WIN32) CPack/WiX/cmWIXShortcut.h CPack/WiX/cmWIXSourceWriter.cxx CPack/WiX/cmWIXSourceWriter.h - ) + ) endif() if(APPLE) @@ -991,6 +996,11 @@ if(APPLE) "See CMakeFiles/CMakeError.log for details of the failure.") endif() endif() +if(CYGWIN AND LibUUID_FOUND) + target_link_libraries(CPackLib ${LibUUID_LIBRARIES}) + include_directories(CPackLib ${LibUUID_INCLUDE_DIRS}) + set_property(SOURCE CPack/cmCPackGeneratorFactory.cxx PROPERTY COMPILE_DEFINITIONS HAVE_LIBUUID) +endif() if(CPACK_ENABLE_FREEBSD_PKG AND FREEBSD_PKG_INCLUDE_DIRS AND FREEBSD_PKG_LIBRARIES) target_link_libraries(CPackLib ${FREEBSD_PKG_LIBRARIES}) include_directories(${FREEBSD_PKG_INCLUDE_DIRS}) @@ -1047,6 +1057,19 @@ endif() include (${CMake_BINARY_DIR}/Source/LocalUserOptions.cmake OPTIONAL) include (${CMake_SOURCE_DIR}/Source/LocalUserOptions.cmake OPTIONAL) +if(WIN32) + # Add Windows executable version information. + configure_file("CMakeVersion.rc.in" "CMakeVersion.rc" @ONLY) + + # We use a separate object library for this to work around a limitation of + # MinGW's windres tool with spaces in the path to the include directories. + add_library(CMakeVersion OBJECT "${CMAKE_CURRENT_BINARY_DIR}/CMakeVersion.rc") + set_property(TARGET CMakeVersion PROPERTY INCLUDE_DIRECTORIES "") + foreach(_tool ${_tools}) + target_sources(${_tool} PRIVATE $<TARGET_OBJECTS:CMakeVersion>) + endforeach() +endif() + # Install tools foreach(_tool ${_tools}) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 3a14f8e..0ecbd07 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,5 +1,5 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 10) -set(CMake_VERSION_PATCH 0) -set(CMake_VERSION_RC 3) +set(CMake_VERSION_PATCH 20171101) +#set(CMake_VERSION_RC 1) diff --git a/Source/CMakeVersion.rc.in b/Source/CMakeVersion.rc.in new file mode 100644 index 0000000..f4ca3d5 --- /dev/null +++ b/Source/CMakeVersion.rc.in @@ -0,0 +1,34 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ + +#define VER_FILEVERSION @CMake_VERSION_MAJOR@,@CMake_VERSION_MINOR@,@CMake_VERSION_PATCH@ +#define VER_FILEVERSION_STR "@CMake_VERSION_MAJOR@.@CMake_VERSION_MINOR@.@CMake_VERSION_PATCH@\0" + +#define VER_PRODUCTVERSION @CMake_VERSION_MAJOR@,@CMake_VERSION_MINOR@,@CMake_VERSION_PATCH@ +#define VER_PRODUCTVERSION_STR "@CMake_VERSION@\0" + +VS_VERSION_INFO VERSIONINFO +FILEVERSION VER_FILEVERSION +PRODUCTVERSION VER_PRODUCTVERSION +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904E4" + BEGIN + VALUE "FileVersion", VER_FILEVERSION_STR + VALUE "ProductVersion", VER_PRODUCTVERSION_STR + END + END + + BLOCK "VarFileInfo" + BEGIN + /* The following line should only be modified for localized versions. */ + /* It consists of any number of WORD,WORD pairs, with each pair */ + /* describing a language,codepage combination supported by the file. */ + /* */ + /* For example, a file might have values "0x409,1252" indicating that it */ + /* supports English language (0x409) in the Windows ANSI codepage (1252). */ + + VALUE "Translation", 0x409, 1252 + END +END diff --git a/Source/CPack/WiX/cmCMakeToWixPath.cxx b/Source/CPack/WiX/cmCMakeToWixPath.cxx new file mode 100644 index 0000000..0b0e42a --- /dev/null +++ b/Source/CPack/WiX/cmCMakeToWixPath.cxx @@ -0,0 +1,39 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#include "cmCMakeToWixPath.h" + +#include "cmSystemTools.h" + +#include <string> +#include <vector> + +#ifdef __CYGWIN__ +#include <sys/cygwin.h> +std::string CMakeToWixPath(const std::string& cygpath) +{ + std::vector<char> winpath_chars; + ssize_t winpath_size; + + // Get the required buffer size. + winpath_size = + cygwin_conv_path(CCP_POSIX_TO_WIN_A, cygpath.c_str(), nullptr, 0); + if (winpath_size <= 0) { + return cygpath; + } + + winpath_chars.assign(static_cast<size_t>(winpath_size) + 1, '\0'); + + winpath_size = cygwin_conv_path(CCP_POSIX_TO_WIN_A, cygpath.c_str(), + winpath_chars.data(), winpath_size); + if (winpath_size < 0) { + return cygpath; + } + + return cmSystemTools::TrimWhitespace(winpath_chars.data()); +} +#else +std::string CMakeToWixPath(const std::string& path) +{ + return path; +} +#endif diff --git a/Source/CPack/WiX/cmCMakeToWixPath.h b/Source/CPack/WiX/cmCMakeToWixPath.h new file mode 100644 index 0000000..8bb9e04 --- /dev/null +++ b/Source/CPack/WiX/cmCMakeToWixPath.h @@ -0,0 +1,12 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#ifndef cmCMakeToWixPath_h +#define cmCMakeToWixPath_h + +#include "cmConfigure.h" //IWYU pragma: keep + +#include <string> + +std::string CMakeToWixPath(const std::string& cygpath); + +#endif // cmCMakeToWixPath_h diff --git a/Source/CPack/WiX/cmCPackWIXGenerator.cxx b/Source/CPack/WiX/cmCPackWIXGenerator.cxx index ba07d08..a0bc0ea 100644 --- a/Source/CPack/WiX/cmCPackWIXGenerator.cxx +++ b/Source/CPack/WiX/cmCPackWIXGenerator.cxx @@ -22,7 +22,13 @@ #include "cmsys/FStream.hxx" #include "cmsys/SystemTools.hxx" -#include <rpc.h> // for GUID generation +#ifdef _WIN32 +#include <rpc.h> // for GUID generation (windows only) +#else +#include <uuid/uuid.h> // for GUID generation (libuuid) +#endif + +#include "cmCMakeToWixPath.h" cmCPackWIXGenerator::cmCPackWIXGenerator() : Patch(0) @@ -110,7 +116,7 @@ bool cmCPackWIXGenerator::RunLightCommand(std::string const& objectFiles) std::ostringstream command; command << QuotePath(executable); command << " -nologo"; - command << " -out " << QuotePath(packageFileNames.at(0)); + command << " -out " << QuotePath(CMakeToWixPath(packageFileNames.at(0))); for (std::string const& ext : this->LightExtensions) { command << " -ext " << QuotePath(ext); @@ -270,11 +276,12 @@ bool cmCPackWIXGenerator::PackageFilesImpl() std::string objectFilename = this->CPackTopLevel + "/" + uniqueBaseName + ".wixobj"; - if (!RunCandleCommand(sourceFilename, objectFilename)) { + if (!RunCandleCommand(CMakeToWixPath(sourceFilename), + CMakeToWixPath(objectFilename))) { return false; } - objectFiles << " " << QuotePath(objectFilename); + objectFiles << " " << QuotePath(CMakeToWixPath(objectFilename)); } AppendUserSuppliedExtraObjects(objectFiles); @@ -320,10 +327,10 @@ void cmCPackWIXGenerator::CreateWiXVariablesIncludeFile() CopyDefinition(includeFile, "CPACK_PACKAGE_VENDOR"); CopyDefinition(includeFile, "CPACK_PACKAGE_NAME"); CopyDefinition(includeFile, "CPACK_PACKAGE_VERSION"); - CopyDefinition(includeFile, "CPACK_WIX_LICENSE_RTF"); - CopyDefinition(includeFile, "CPACK_WIX_PRODUCT_ICON"); - CopyDefinition(includeFile, "CPACK_WIX_UI_BANNER"); - CopyDefinition(includeFile, "CPACK_WIX_UI_DIALOG"); + CopyDefinition(includeFile, "CPACK_WIX_LICENSE_RTF", DefinitionType::PATH); + CopyDefinition(includeFile, "CPACK_WIX_PRODUCT_ICON", DefinitionType::PATH); + CopyDefinition(includeFile, "CPACK_WIX_UI_BANNER", DefinitionType::PATH); + CopyDefinition(includeFile, "CPACK_WIX_UI_DIALOG", DefinitionType::PATH); SetOptionIfNotSet("CPACK_WIX_PROGRAM_MENU_FOLDER", GetOption("CPACK_PACKAGE_NAME")); CopyDefinition(includeFile, "CPACK_WIX_PROGRAM_MENU_FOLDER"); @@ -390,11 +397,16 @@ void cmCPackWIXGenerator::CreateWiXProductFragmentIncludeFile() } void cmCPackWIXGenerator::CopyDefinition(cmWIXSourceWriter& source, - std::string const& name) + std::string const& name, + DefinitionType type) { const char* value = GetOption(name.c_str()); if (value) { - AddDefinition(source, name, value); + if (type == DefinitionType::PATH) { + AddDefinition(source, name, CMakeToWixPath(value)); + } else { + AddDefinition(source, name, value); + } } } @@ -966,6 +978,7 @@ std::string cmCPackWIXGenerator::GetArchitecture() const std::string cmCPackWIXGenerator::GenerateGUID() { +#ifdef _WIN32 UUID guid; UuidCreate(&guid); @@ -975,6 +988,14 @@ std::string cmCPackWIXGenerator::GenerateGUID() std::string result = cmsys::Encoding::ToNarrow(reinterpret_cast<wchar_t*>(tmp)); RpcStringFreeW(&tmp); +#else + uuid_t guid; + char guid_ch[37] = { 0 }; + + uuid_generate(guid); + uuid_unparse(guid, guid_ch); + std::string result = guid_ch; +#endif return cmSystemTools::UpperCase(result); } diff --git a/Source/CPack/WiX/cmCPackWIXGenerator.h b/Source/CPack/WiX/cmCPackWIXGenerator.h index b2633a7..128a04d 100644 --- a/Source/CPack/WiX/cmCPackWIXGenerator.h +++ b/Source/CPack/WiX/cmCPackWIXGenerator.h @@ -48,6 +48,12 @@ private: typedef std::map<std::string, size_t> ambiguity_map_t; typedef std::set<std::string> extension_set_t; + enum class DefinitionType + { + STRING, + PATH + }; + bool InitializeWiXConfiguration(); bool PackageFilesImpl(); @@ -58,7 +64,8 @@ private: void CreateWiXProductFragmentIncludeFile(); - void CopyDefinition(cmWIXSourceWriter& source, std::string const& name); + void CopyDefinition(cmWIXSourceWriter& source, std::string const& name, + DefinitionType type = DefinitionType::STRING); void AddDefinition(cmWIXSourceWriter& source, std::string const& name, std::string const& value); diff --git a/Source/CPack/WiX/cmWIXFilesSourceWriter.cxx b/Source/CPack/WiX/cmWIXFilesSourceWriter.cxx index b4cd1a3..dd3caf9 100644 --- a/Source/CPack/WiX/cmWIXFilesSourceWriter.cxx +++ b/Source/CPack/WiX/cmWIXFilesSourceWriter.cxx @@ -11,6 +11,8 @@ #include "cm_sys_stat.h" +#include "cmCMakeToWixPath.h" + cmWIXFilesSourceWriter::cmWIXFilesSourceWriter(cmCPackLog* logger, std::string const& filename, GuidType componentGuidType) @@ -139,7 +141,7 @@ std::string cmWIXFilesSourceWriter::EmitComponentFile( patch.ApplyFragment(componentId, *this); BeginElement("File"); AddAttribute("Id", fileId); - AddAttribute("Source", filePath); + AddAttribute("Source", CMakeToWixPath(filePath)); AddAttribute("KeyPath", "yes"); mode_t fileMode = 0; diff --git a/Source/CPack/cmCPackDragNDropGenerator.cxx b/Source/CPack/cmCPackDragNDropGenerator.cxx index 1e1543f..bb35623 100644 --- a/Source/CPack/cmCPackDragNDropGenerator.cxx +++ b/Source/CPack/cmCPackDragNDropGenerator.cxx @@ -411,6 +411,7 @@ int cmCPackDragNDropGenerator::CreateDMG(const std::string& src_dir, std::string temp_image = this->GetOption("CPACK_TOPLEVEL_DIRECTORY"); temp_image += "/temp.dmg"; + std::string create_error; std::ostringstream temp_image_command; temp_image_command << this->GetOption("CPACK_COMMAND_HDIUTIL"); temp_image_command << " create"; @@ -421,9 +422,11 @@ int cmCPackDragNDropGenerator::CreateDMG(const std::string& src_dir, temp_image_command << " -format " << temp_image_format; temp_image_command << " \"" << temp_image << "\""; - if (!this->RunCommand(temp_image_command)) { + if (!this->RunCommand(temp_image_command, &create_error)) { cmCPackLogger(cmCPackLog::LOG_ERROR, - "Error generating temporary disk image." << std::endl); + "Error generating temporary disk image." << std::endl + << create_error + << std::endl); return 0; } @@ -464,15 +467,17 @@ int cmCPackDragNDropGenerator::CreateDMG(const std::string& src_dir, // Optionally set the custom icon flag for the image ... if (!had_error && !cpack_package_icon.empty()) { + std::string error; std::ostringstream setfile_command; setfile_command << this->GetOption("CPACK_COMMAND_SETFILE"); setfile_command << " -a C"; setfile_command << " \"" << temp_mount << "\""; - if (!this->RunCommand(setfile_command)) { + if (!this->RunCommand(setfile_command, &error)) { cmCPackLogger(cmCPackLog::LOG_ERROR, "Error assigning custom icon to temporary disk image." - << std::endl); + << std::endl + << error << std::endl); had_error = true; } @@ -717,9 +722,12 @@ int cmCPackDragNDropGenerator::CreateDMG(const std::string& src_dir, final_image_command << " zlib-level=9"; final_image_command << " -o \"" << output_file << "\""; - if (!this->RunCommand(final_image_command)) { + std::string convert_error; + + if (!this->RunCommand(final_image_command, &convert_error)) { cmCPackLogger(cmCPackLog::LOG_ERROR, "Error compressing disk image." - << std::endl); + << std::endl + << convert_error << std::endl); return 0; } diff --git a/Source/CPack/cmCPackGeneratorFactory.cxx b/Source/CPack/cmCPackGeneratorFactory.cxx index 4b81bbc..47e7527 100644 --- a/Source/CPack/cmCPackGeneratorFactory.cxx +++ b/Source/CPack/cmCPackGeneratorFactory.cxx @@ -40,7 +40,7 @@ #include "cmCPackRPMGenerator.h" #endif -#ifdef _WIN32 +#if defined(_WIN32) || (defined(__CYGWIN__) && defined(HAVE_LIBUUID)) #include "WiX/cmCPackWIXGenerator.h" #endif @@ -87,7 +87,7 @@ cmCPackGeneratorFactory::cmCPackGeneratorFactory() this->RegisterGenerator("7Z", "7-Zip file format", cmCPack7zGenerator::CreateGenerator); } -#ifdef _WIN32 +#if defined(_WIN32) || (defined(__CYGWIN__) && defined(HAVE_LIBUUID)) if (cmCPackWIXGenerator::CanGenerate()) { this->RegisterGenerator("WIX", "MSI file format via WiX tools", cmCPackWIXGenerator::CreateGenerator); diff --git a/Source/LexerParser/cmCommandArgumentLexer.cxx b/Source/LexerParser/cmCommandArgumentLexer.cxx index bf6bc2f..6b4fc85 100644 --- a/Source/LexerParser/cmCommandArgumentLexer.cxx +++ b/Source/LexerParser/cmCommandArgumentLexer.cxx @@ -674,6 +674,13 @@ Modify cmCommandArgumentLexer.cxx: /* Include the set of tokens from the parser. */ #include "cmCommandArgumentParserTokens.h" +static const char *DCURLYVariable = "${"; +static const char *RCURLYVariable = "}"; +static const char *ATVariable = "@"; +static const char *DOLLARVariable = "$"; +static const char *LCURLYVariable = "{"; +static const char *BSLASHVariable = "\\"; + /*--------------------------------------------------------------------------*/ #define INITIAL 0 @@ -1011,7 +1018,7 @@ YY_RULE_SETUP { //std::cerr << __LINE__ << " here: [" << yytext << "]" << std::endl; //yyextra->AllocateParserType(yylvalp, yytext, strlen(yytext)); - yylvalp->str = yyextra->DCURLYVariable; + yylvalp->str = DCURLYVariable; return cal_DCURLY; } YY_BREAK @@ -1020,7 +1027,7 @@ YY_RULE_SETUP { //std::cerr << __LINE__ << " here: [" << yytext << "]" << std::endl; //yyextra->AllocateParserType(yylvalp, yytext, strlen(yytext)); - yylvalp->str = yyextra->RCURLYVariable; + yylvalp->str = RCURLYVariable; return cal_RCURLY; } YY_BREAK @@ -1029,7 +1036,7 @@ YY_RULE_SETUP { //std::cerr << __LINE__ << " here: [" << yytext << "]" << std::endl; //yyextra->AllocateParserType(yylvalp, yytext, strlen(yytext)); - yylvalp->str = yyextra->ATVariable; + yylvalp->str = ATVariable; return cal_AT; } YY_BREAK @@ -1064,7 +1071,7 @@ case 10: YY_RULE_SETUP { //yyextra->AllocateParserType(yylvalp, yytext, strlen(yytext)); - yylvalp->str = yyextra->DOLLARVariable; + yylvalp->str = DOLLARVariable; return cal_DOLLAR; } YY_BREAK @@ -1072,7 +1079,7 @@ case 11: YY_RULE_SETUP { //yyextra->AllocateParserType(yylvalp, yytext, strlen(yytext)); - yylvalp->str = yyextra->LCURLYVariable; + yylvalp->str = LCURLYVariable; return cal_LCURLY; } YY_BREAK @@ -1080,7 +1087,7 @@ case 12: YY_RULE_SETUP { //yyextra->AllocateParserType(yylvalp, yytext, strlen(yytext)); - yylvalp->str = yyextra->BSLASHVariable; + yylvalp->str = BSLASHVariable; return cal_BSLASH; } YY_BREAK @@ -1088,7 +1095,7 @@ case 13: YY_RULE_SETUP { //yyextra->AllocateParserType(yylvalp, yytext, strlen(yytext)); - yylvalp->str = yyextra->BSLASHVariable; + yylvalp->str = BSLASHVariable; return cal_SYMBOL; } YY_BREAK diff --git a/Source/LexerParser/cmCommandArgumentLexer.in.l b/Source/LexerParser/cmCommandArgumentLexer.in.l index acf18f3..5927b9e 100644 --- a/Source/LexerParser/cmCommandArgumentLexer.in.l +++ b/Source/LexerParser/cmCommandArgumentLexer.in.l @@ -28,6 +28,13 @@ Modify cmCommandArgumentLexer.cxx: /* Include the set of tokens from the parser. */ #include "cmCommandArgumentParserTokens.h" +static const char *DCURLYVariable = "${"; +static const char *RCURLYVariable = "}"; +static const char *ATVariable = "@"; +static const char *DOLLARVariable = "$"; +static const char *LCURLYVariable = "{"; +static const char *BSLASHVariable = "\\"; + /*--------------------------------------------------------------------------*/ %} @@ -63,21 +70,21 @@ Modify cmCommandArgumentLexer.cxx: "${" { //std::cerr << __LINE__ << " here: [" << yytext << "]" << std::endl; //yyextra->AllocateParserType(yylvalp, yytext, strlen(yytext)); - yylvalp->str = yyextra->DCURLYVariable; + yylvalp->str = DCURLYVariable; return cal_DCURLY; } "}" { //std::cerr << __LINE__ << " here: [" << yytext << "]" << std::endl; //yyextra->AllocateParserType(yylvalp, yytext, strlen(yytext)); - yylvalp->str = yyextra->RCURLYVariable; + yylvalp->str = RCURLYVariable; return cal_RCURLY; } "@" { //std::cerr << __LINE__ << " here: [" << yytext << "]" << std::endl; //yyextra->AllocateParserType(yylvalp, yytext, strlen(yytext)); - yylvalp->str = yyextra->ATVariable; + yylvalp->str = ATVariable; return cal_AT; } @@ -103,25 +110,25 @@ Modify cmCommandArgumentLexer.cxx: "$" { //yyextra->AllocateParserType(yylvalp, yytext, strlen(yytext)); - yylvalp->str = yyextra->DOLLARVariable; + yylvalp->str = DOLLARVariable; return cal_DOLLAR; } "{" { //yyextra->AllocateParserType(yylvalp, yytext, strlen(yytext)); - yylvalp->str = yyextra->LCURLYVariable; + yylvalp->str = LCURLYVariable; return cal_LCURLY; } <ESCAPES>"\\" { //yyextra->AllocateParserType(yylvalp, yytext, strlen(yytext)); - yylvalp->str = yyextra->BSLASHVariable; + yylvalp->str = BSLASHVariable; return cal_BSLASH; } <NOESCAPES>"\\" { //yyextra->AllocateParserType(yylvalp, yytext, strlen(yytext)); - yylvalp->str = yyextra->BSLASHVariable; + yylvalp->str = BSLASHVariable; return cal_SYMBOL; } diff --git a/Source/Modules/FindLibUUID.cmake b/Source/Modules/FindLibUUID.cmake new file mode 100644 index 0000000..17f11c1 --- /dev/null +++ b/Source/Modules/FindLibUUID.cmake @@ -0,0 +1,85 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + +#[=======================================================================[.rst: +FindLibUUID +------------ + +Find LibUUID include directory and library. + +Imported Targets +^^^^^^^^^^^^^^^^ + +An :ref:`imported target <Imported targets>` named +``LibUUID::LibUUID`` is provided if LibUUID has been found. + +Result Variables +^^^^^^^^^^^^^^^^ + +This module defines the following variables: + +``LibUUID_FOUND`` + True if LibUUID was found, false otherwise. +``LibUUID_INCLUDE_DIRS`` + Include directories needed to include LibUUID headers. +``LibUUID_LIBRARIES`` + Libraries needed to link to LibUUID. + +Cache Variables +^^^^^^^^^^^^^^^ + +This module uses the following cache variables: + +``LibUUID_LIBRARY`` + The location of the LibUUID library file. +``LibUUID_INCLUDE_DIR`` + The location of the LibUUID include directory containing ``uuid/uuid.h``. + +The cache variables should not be used by project code. +They may be set by end users to point at LibUUID components. +#]=======================================================================] + +#----------------------------------------------------------------------------- +if(CYGWIN) + # Note: on current version of Cygwin, linking to libuuid.dll.a doesn't + # import the right symbols sometimes. Fix this by linking directly + # to the DLL that provides the symbols, instead. + set(old_suffixes ${CMAKE_FIND_LIBRARY_SUFFIXES}) + set(CMAKE_FIND_LIBRARY_SUFFIXES .dll) + find_library(LibUUID_LIBRARY + NAMES cyguuid-1.dll + ) + set(CMAKE_FIND_LIBRARY_SUFFIXES ${old_suffixes}) +else() + find_library(LibUUID_LIBRARY + NAMES uuid + ) +endif() +mark_as_advanced(LibUUID_LIBRARY) + +find_path(LibUUID_INCLUDE_DIR + NAMES uuid/uuid.h + ) +mark_as_advanced(LibUUID_INCLUDE_DIR) + +#----------------------------------------------------------------------------- +include(${CMAKE_CURRENT_LIST_DIR}/../../Modules/FindPackageHandleStandardArgs.cmake) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(LibUUID + FOUND_VAR LibUUID_FOUND + REQUIRED_VARS LibUUID_LIBRARY LibUUID_INCLUDE_DIR + ) +set(LIBUUID_FOUND ${LibUUID_FOUND}) + +#----------------------------------------------------------------------------- +# Provide documented result variables and targets. +if(LibUUID_FOUND) + set(LibUUID_INCLUDE_DIRS ${LibUUID_INCLUDE_DIR}) + set(LibUUID_LIBRARIES ${LibUUID_LIBRARY}) + if(NOT TARGET LibUUID::LibUUID) + add_library(LibUUID::LibUUID UNKNOWN IMPORTED) + set_target_properties(LibUUID::LibUUID PROPERTIES + IMPORTED_LOCATION "${LibUUID_LIBRARY}" + INTERFACE_INCLUDE_DIRECTORIES "${LibUUID_INCLUDE_DIRS}" + ) + endif() +endif() diff --git a/Source/QtDialog/CMakeSetupDialog.cxx b/Source/QtDialog/CMakeSetupDialog.cxx index bbb2395..5be9ec3 100644 --- a/Source/QtDialog/CMakeSetupDialog.cxx +++ b/Source/QtDialog/CMakeSetupDialog.cxx @@ -188,6 +188,9 @@ CMakeSetupDialog::CMakeSetupDialog() connect(this->Output, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(doOutputContextMenu(const QPoint&))); + // disable open project button + this->OpenProjectButton->setDisabled(true); + // start the cmake worker thread this->CMakeThread = new QCMakeThread(this); QObject::connect(this->CMakeThread, SIGNAL(cmakeInitialized()), this, @@ -249,6 +252,10 @@ void CMakeSetupDialog::initialize() SIGNAL(outputMessage(QString)), this, SLOT(message(QString))); + QObject::connect(this->CMakeThread->cmakeInstance(), + SIGNAL(openPossible(bool)), this->OpenProjectButton, + SLOT(setEnabled(bool))); + QObject::connect(this->groupedCheck, SIGNAL(toggled(bool)), this, SLOT(setGroupedView(bool))); QObject::connect(this->advancedCheck, SIGNAL(toggled(bool)), this, @@ -492,24 +499,10 @@ void CMakeSetupDialog::doGenerate() this->ConfigureNeeded = true; } -QString CMakeSetupDialog::getProjectFilename() -{ - QStringList nameFilter; - nameFilter << "*.sln" - << "*.xcodeproj"; - QDir directory(this->BinaryDirectory->currentText()); - QStringList nlnFile = directory.entryList(nameFilter); - - if (nlnFile.count() == 1) { - return this->BinaryDirectory->currentText() + "/" + nlnFile.at(0); - } - - return QString(); -} - void CMakeSetupDialog::doOpenProject() { - QDesktopServices::openUrl(QUrl::fromLocalFile(this->getProjectFilename())); + QMetaObject::invokeMethod(this->CMakeThread->cmakeInstance(), "open", + Qt::QueuedConnection); } void CMakeSetupDialog::closeEvent(QCloseEvent* e) @@ -630,11 +623,6 @@ void CMakeSetupDialog::updateBinaryDirectory(const QString& dir) this->BinaryDirectory->setEditText(dir); this->BinaryDirectory->blockSignals(false); } - if (!this->getProjectFilename().isEmpty()) { - this->OpenProjectButton->setEnabled(true); - } else { - this->OpenProjectButton->setEnabled(false); - } } void CMakeSetupDialog::doBinaryBrowse() @@ -1039,9 +1027,6 @@ void CMakeSetupDialog::enterState(CMakeSetupDialog::State s) this->GenerateButton->setEnabled(true); this->GenerateAction->setEnabled(true); this->ConfigureButton->setEnabled(true); - if (!this->getProjectFilename().isEmpty()) { - this->OpenProjectButton->setEnabled(true); - } this->ConfigureButton->setText(tr("&Configure")); this->GenerateButton->setText(tr("&Generate")); } else if (s == ReadyGenerate) { @@ -1049,9 +1034,6 @@ void CMakeSetupDialog::enterState(CMakeSetupDialog::State s) this->GenerateButton->setEnabled(true); this->GenerateAction->setEnabled(true); this->ConfigureButton->setEnabled(true); - if (!this->getProjectFilename().isEmpty()) { - this->OpenProjectButton->setEnabled(true); - } this->ConfigureButton->setText(tr("&Configure")); this->GenerateButton->setText(tr("&Generate")); } diff --git a/Source/QtDialog/CMakeSetupDialog.h b/Source/QtDialog/CMakeSetupDialog.h index 0da28d8..7b767e5 100644 --- a/Source/QtDialog/CMakeSetupDialog.h +++ b/Source/QtDialog/CMakeSetupDialog.h @@ -31,7 +31,6 @@ protected slots: void initialize(); void doConfigure(); void doGenerate(); - QString getProjectFilename(); void doOpenProject(); void doInstallForCommandLine(); void doHelp(); diff --git a/Source/QtDialog/QCMake.cxx b/Source/QtDialog/QCMake.cxx index d473d9b..7e94a27 100644 --- a/Source/QtDialog/QCMake.cxx +++ b/Source/QtDialog/QCMake.cxx @@ -115,6 +115,8 @@ void QCMake::setBinaryDirectory(const QString& _dir) if (toolset) { this->setToolset(QString::fromLocal8Bit(toolset)); } + + checkOpenPossible(); } } @@ -183,6 +185,26 @@ void QCMake::generate() #endif emit this->generateDone(err); + checkOpenPossible(); +} + +void QCMake::open() +{ +#ifdef Q_OS_WIN + UINT lastErrorMode = SetErrorMode(0); +#endif + + InterruptFlag = 0; + cmSystemTools::ResetErrorOccuredFlag(); + + auto successful = this->CMakeInstance->Open( + this->BinaryDirectory.toLocal8Bit().data(), false); + +#ifdef Q_OS_WIN + SetErrorMode(lastErrorMode); +#endif + + emit this->openDone(successful); } void QCMake::setProperties(const QCMakePropertyList& newProps) @@ -450,3 +472,10 @@ void QCMake::setWarnUnusedMode(bool value) { this->WarnUnusedMode = value; } + +void QCMake::checkOpenPossible() +{ + auto data = this->BinaryDirectory.toLocal8Bit().data(); + auto possible = this->CMakeInstance->Open(data, true); + emit openPossible(possible); +} diff --git a/Source/QtDialog/QCMake.h b/Source/QtDialog/QCMake.h index 3b8cea7..6fae7e3 100644 --- a/Source/QtDialog/QCMake.h +++ b/Source/QtDialog/QCMake.h @@ -80,6 +80,8 @@ public slots: void configure(); /// generate the files void generate(); + /// open the project + void open(); /// set the property values void setProperties(const QCMakePropertyList&); /// interrupt the configure or generate process (if connecting, make a direct @@ -111,6 +113,8 @@ public slots: void setWarnUninitializedMode(bool value); /// set whether to run cmake with warnings about unused variables void setWarnUnusedMode(bool value); + /// check if project IDE open is possible and emit openPossible signal + void checkOpenPossible(); public: /// get the list of cache properties @@ -151,6 +155,10 @@ signals: void debugOutputChanged(bool); /// signal when the toolset changes void toolsetChanged(const QString& toolset); + /// signal when open is done + void openDone(bool successful); + /// signal when open is done + void openPossible(bool possible); protected: cmake* CMakeInstance; diff --git a/Source/cmAddCustomTargetCommand.cxx b/Source/cmAddCustomTargetCommand.cxx index a8d5b2e..f4b4f66 100644 --- a/Source/cmAddCustomTargetCommand.cxx +++ b/Source/cmAddCustomTargetCommand.cxx @@ -8,7 +8,7 @@ #include "cmGeneratorExpression.h" #include "cmGlobalGenerator.h" #include "cmMakefile.h" -#include "cmPolicies.h" +#include "cmStateTypes.h" #include "cmSystemTools.h" #include "cmTarget.h" #include "cmake.h" @@ -160,35 +160,9 @@ bool cmAddCustomTargetCommand::InitialPass( if (nameOk) { nameOk = targetName.find(':') == std::string::npos; } - if (!nameOk) { - cmake::MessageType messageType = cmake::AUTHOR_WARNING; - std::ostringstream e; - bool issueMessage = false; - switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0037)) { - case cmPolicies::WARN: - e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0037) << "\n"; - issueMessage = true; - case cmPolicies::OLD: - break; - case cmPolicies::NEW: - case cmPolicies::REQUIRED_IF_USED: - case cmPolicies::REQUIRED_ALWAYS: - issueMessage = true; - messageType = cmake::FATAL_ERROR; - } - if (issueMessage) { - /* clang-format off */ - e << "The target name \"" << targetName << - "\" is reserved or not valid for certain " - "CMake features, such as generator expressions, and may result " - "in undefined behavior."; - /* clang-format on */ - this->Makefile->IssueMessage(messageType, e.str()); - - if (messageType == cmake::FATAL_ERROR) { - return false; - } - } + if (!nameOk && + !this->Makefile->CheckCMP0037(targetName, cmStateEnums::UTILITY)) { + return false; } // Store the last command line finished. diff --git a/Source/cmAddExecutableCommand.cxx b/Source/cmAddExecutableCommand.cxx index 1d0376f..b9e200a 100644 --- a/Source/cmAddExecutableCommand.cxx +++ b/Source/cmAddExecutableCommand.cxx @@ -7,10 +7,8 @@ #include "cmGeneratorExpression.h" #include "cmGlobalGenerator.h" #include "cmMakefile.h" -#include "cmPolicies.h" #include "cmStateTypes.h" #include "cmTarget.h" -#include "cmake.h" class cmExecutionStatus; @@ -18,7 +16,7 @@ class cmExecutionStatus; bool cmAddExecutableCommand::InitialPass(std::vector<std::string> const& args, cmExecutionStatus&) { - if (args.size() < 2) { + if (args.empty()) { this->SetError("called with incorrect number of arguments"); return false; } @@ -63,35 +61,9 @@ bool cmAddExecutableCommand::InitialPass(std::vector<std::string> const& args, if (nameOk && !importTarget && !isAlias) { nameOk = exename.find(':') == std::string::npos; } - if (!nameOk) { - cmake::MessageType messageType = cmake::AUTHOR_WARNING; - std::ostringstream e; - bool issueMessage = false; - switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0037)) { - case cmPolicies::WARN: - e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0037) << "\n"; - issueMessage = true; - case cmPolicies::OLD: - break; - case cmPolicies::NEW: - case cmPolicies::REQUIRED_IF_USED: - case cmPolicies::REQUIRED_ALWAYS: - issueMessage = true; - messageType = cmake::FATAL_ERROR; - } - if (issueMessage) { - /* clang-format off */ - e << "The target name \"" << exename << - "\" is reserved or not valid for certain " - "CMake features, such as generator expressions, and may result " - "in undefined behavior."; - /* clang-format on */ - this->Makefile->IssueMessage(messageType, e.str()); - - if (messageType == cmake::FATAL_ERROR) { - return false; - } - } + if (!nameOk && + !this->Makefile->CheckCMP0037(exename, cmStateEnums::EXECUTABLE)) { + return false; } // Special modifiers are not allowed with IMPORTED signature. @@ -140,8 +112,7 @@ bool cmAddExecutableCommand::InitialPass(std::vector<std::string> const& args, if (!aliasedTarget) { std::ostringstream e; e << "cannot create ALIAS target \"" << exename << "\" because target \"" - << aliasedName << "\" does not already " - "exist."; + << aliasedName << "\" does not already exist."; this->SetError(e.str()); return false; } @@ -149,15 +120,15 @@ bool cmAddExecutableCommand::InitialPass(std::vector<std::string> const& args, if (type != cmStateEnums::EXECUTABLE) { std::ostringstream e; e << "cannot create ALIAS target \"" << exename << "\" because target \"" - << aliasedName << "\" is not an " - "executable."; + << aliasedName << "\" is not an executable."; this->SetError(e.str()); return false; } - if (aliasedTarget->IsImported()) { + if (aliasedTarget->IsImported() && + !aliasedTarget->IsImportedGloballyVisible()) { std::ostringstream e; e << "cannot create ALIAS target \"" << exename << "\" because target \"" - << aliasedName << "\" is IMPORTED."; + << aliasedName << "\" is imported but not globally visible."; this->SetError(e.str()); return false; } @@ -191,12 +162,6 @@ bool cmAddExecutableCommand::InitialPass(std::vector<std::string> const& args, } } - if (s == args.end()) { - this->SetError( - "called with incorrect number of arguments, no sources provided"); - return false; - } - std::vector<std::string> srclists(s, args.end()); cmTarget* tgt = this->Makefile->AddExecutable(exename.c_str(), srclists, excludeFromAll); diff --git a/Source/cmAddLibraryCommand.cxx b/Source/cmAddLibraryCommand.cxx index ebf1763..0fcffdd 100644 --- a/Source/cmAddLibraryCommand.cxx +++ b/Source/cmAddLibraryCommand.cxx @@ -7,7 +7,6 @@ #include "cmGeneratorExpression.h" #include "cmGlobalGenerator.h" #include "cmMakefile.h" -#include "cmPolicies.h" #include "cmState.h" #include "cmStateTypes.h" #include "cmSystemTools.h" @@ -175,35 +174,8 @@ bool cmAddLibraryCommand::InitialPass(std::vector<std::string> const& args, if (nameOk && !importTarget && !isAlias) { nameOk = libName.find(':') == std::string::npos; } - if (!nameOk) { - cmake::MessageType messageType = cmake::AUTHOR_WARNING; - std::ostringstream e; - bool issueMessage = false; - switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0037)) { - case cmPolicies::WARN: - if (type != cmStateEnums::INTERFACE_LIBRARY) { - e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0037) << "\n"; - issueMessage = true; - } - case cmPolicies::OLD: - break; - case cmPolicies::NEW: - case cmPolicies::REQUIRED_IF_USED: - case cmPolicies::REQUIRED_ALWAYS: - issueMessage = true; - messageType = cmake::FATAL_ERROR; - } - if (issueMessage) { - e << "The target name \"" << libName - << "\" is reserved or not valid for certain " - "CMake features, such as generator expressions, and may result " - "in undefined behavior."; - this->Makefile->IssueMessage(messageType, e.str()); - - if (messageType == cmake::FATAL_ERROR) { - return false; - } - } + if (!nameOk && !this->Makefile->CheckCMP0037(libName, type)) { + return false; } if (isAlias) { @@ -256,13 +228,6 @@ bool cmAddLibraryCommand::InitialPass(std::vector<std::string> const& args, this->SetError(e.str()); return false; } - if (aliasedTarget->IsImported()) { - std::ostringstream e; - e << "cannot create ALIAS target \"" << libName << "\" because target \"" - << aliasedName << "\" is IMPORTED."; - this->SetError(e.str()); - return false; - } this->Makefile->AddAlias(libName, aliasedName); return true; } @@ -362,14 +327,6 @@ bool cmAddLibraryCommand::InitialPass(std::vector<std::string> const& args, return true; } - if (s == args.end()) { - std::string msg = "You have called ADD_LIBRARY for library "; - msg += args[0]; - msg += " without any source files. This typically indicates a problem "; - msg += "with your CMakeLists.txt file"; - cmSystemTools::Message(msg.c_str(), "Warning"); - } - srclists.insert(srclists.end(), s, args.end()); this->Makefile->AddLibrary(libName, type, srclists, excludeFromAll); diff --git a/Source/cmAlgorithms.h b/Source/cmAlgorithms.h index 69d0ed6..3380b78 100644 --- a/Source/cmAlgorithms.h +++ b/Source/cmAlgorithms.h @@ -43,22 +43,6 @@ inline bool cmHasLiteralSuffixImpl(const char* str1, const char* str2, } template <typename T, size_t N> -const T* cmArrayBegin(const T (&a)[N]) -{ - return a; -} -template <typename T, size_t N> -const T* cmArrayEnd(const T (&a)[N]) -{ - return a + N; -} -template <typename T, size_t N> -size_t cmArraySize(const T (&)[N]) -{ - return N; -} - -template <typename T, size_t N> bool cmHasLiteralPrefix(const T& str1, const char (&str2)[N]) { return cmHasLiteralPrefixImpl(str1, str2, N - 1); @@ -418,6 +402,67 @@ std::unique_ptr<T> make_unique(Args&&... args) #endif +#if __cplusplus >= 201703L || defined(_MSVC_LANG) && _MSVC_LANG >= 201703L + +using std::size; + +#else + +// std::size backport from C++17. +template <class C> +#if !defined(_MSC_VER) || _MSC_VER >= 1900 +constexpr +#endif + auto + size(C const& c) -> decltype(c.size()) +{ + return c.size(); +} + +template <typename T, size_t N> +#if !defined(_MSC_VER) || _MSC_VER >= 1900 +constexpr +#endif + std::size_t + size(const T (&)[N]) throw() +{ + return N; +} + +#endif + +#if __cplusplus >= 201402L || defined(_MSVC_LANG) && _MSVC_LANG >= 201402L + +using std::cbegin; +using std::cend; + +#else + +// std::c{begin,end} backport from C++14 +template <class C> +#if defined(_MSC_VER) && _MSC_VER < 1900 +auto cbegin(C const& c) +#else +constexpr auto cbegin(C const& c) noexcept(noexcept(std::begin(c))) +#endif + -> decltype(std::begin(c)) +{ + return std::begin(c); +} + +template <class C> +#if defined(_MSC_VER) && _MSC_VER < 1900 +auto cend(C const& c) +#else +constexpr auto cend(C const& c) noexcept(noexcept(std::end(c))) +#endif + -> decltype(std::end(c)) +{ + return std::end(c); +} + +#endif + } // namespace cm #endif diff --git a/Source/cmCMakeHostSystemInformationCommand.cxx b/Source/cmCMakeHostSystemInformationCommand.cxx index 5106f52..662dd74 100644 --- a/Source/cmCMakeHostSystemInformationCommand.cxx +++ b/Source/cmCMakeHostSystemInformationCommand.cxx @@ -8,6 +8,9 @@ #include "cmsys/SystemInformation.hxx" #if defined(_WIN32) +#include "cmAlgorithms.h" +#include "cmGlobalGenerator.h" +#include "cmGlobalVisualStudio15Generator.h" #include "cmSystemTools.h" #include "cmVSSetupHelper.h" #define HAVE_VS_SETUP_HELPER @@ -127,6 +130,17 @@ bool cmCMakeHostSystemInformationCommand::GetValue( value = this->ValueToString(info.GetOSPlatform()); #ifdef HAVE_VS_SETUP_HELPER } else if (key == "VS_15_DIR") { + // If generating for the VS 15 IDE, use the same instance. + cmGlobalGenerator* gg = this->Makefile->GetGlobalGenerator(); + if (cmHasLiteralPrefix(gg->GetName(), "Visual Studio 15 ")) { + cmGlobalVisualStudio15Generator* vs15gen = + static_cast<cmGlobalVisualStudio15Generator*>(gg); + if (vs15gen->GetVSInstance(value)) { + return true; + } + } + + // Otherwise, find a VS 15 instance ourselves. cmVSSetupAPIHelper vsSetupAPIHelper; if (vsSetupAPIHelper.GetVSInstanceInfo(value)) { cmSystemTools::ConvertToUnixSlashes(value); diff --git a/Source/cmCTest.cxx b/Source/cmCTest.cxx index 4ea1493..37ff901 100644 --- a/Source/cmCTest.cxx +++ b/Source/cmCTest.cxx @@ -12,6 +12,7 @@ #include "cmsys/String.hxx" #include "cmsys/SystemInformation.hxx" #include <algorithm> +#include <cstdint> #include <ctype.h> #include <iostream> #include <map> @@ -1421,7 +1422,7 @@ int cmCTest::GenerateCTestNotesOutput(cmXMLWriter& xml, std::string note_time = this->CurrentTime(); xml.StartElement("Note"); xml.Attribute("Name", file); - xml.Element("Time", cmSystemTools::GetTime()); + xml.Element("Time", static_cast<uint64_t>(cmSystemTools::GetTime())); xml.Element("DateTime", note_time); xml.StartElement("Text"); cmsys::ifstream ifs(file.c_str()); diff --git a/Source/cmCommandArgumentParserHelper.cxx b/Source/cmCommandArgumentParserHelper.cxx index 6ae58d6..bf314bd 100644 --- a/Source/cmCommandArgumentParserHelper.cxx +++ b/Source/cmCommandArgumentParserHelper.cxx @@ -21,13 +21,6 @@ cmCommandArgumentParserHelper::cmCommandArgumentParserHelper() this->FileLine = -1; this->FileName = nullptr; this->RemoveEmpty = true; - this->EmptyVariable[0] = 0; - strcpy(this->DCURLYVariable, "${"); - strcpy(this->RCURLYVariable, "}"); - strcpy(this->ATVariable, "@"); - strcpy(this->DOLLARVariable, "$"); - strcpy(this->LCURLYVariable, "{"); - strcpy(this->BSLASHVariable, "\\"); this->NoEscapeMode = false; this->ReplaceAtSyntax = false; @@ -44,10 +37,10 @@ void cmCommandArgumentParserHelper::SetLineFile(long line, const char* file) this->FileName = file; } -char* cmCommandArgumentParserHelper::AddString(const std::string& str) +const char* cmCommandArgumentParserHelper::AddString(const std::string& str) { if (str.empty()) { - return this->EmptyVariable; + return ""; } char* stVal = new char[str.size() + 1]; strcpy(stVal, str.c_str()); @@ -55,14 +48,14 @@ char* cmCommandArgumentParserHelper::AddString(const std::string& str) return stVal; } -char* cmCommandArgumentParserHelper::ExpandSpecialVariable(const char* key, - const char* var) +const char* cmCommandArgumentParserHelper::ExpandSpecialVariable( + const char* key, const char* var) { if (!key) { return this->ExpandVariable(var); } if (!var) { - return this->EmptyVariable; + return ""; } if (strcmp(key, "ENV") == 0) { std::string str; @@ -72,7 +65,7 @@ char* cmCommandArgumentParserHelper::ExpandSpecialVariable(const char* key, } return this->AddString(str); } - return this->EmptyVariable; + return ""; } if (strcmp(key, "CACHE") == 0) { if (const char* c = @@ -82,7 +75,7 @@ char* cmCommandArgumentParserHelper::ExpandSpecialVariable(const char* key, } return this->AddString(c); } - return this->EmptyVariable; + return ""; } std::ostringstream e; e << "Syntax $" << key << "{} is not supported. " @@ -91,7 +84,7 @@ char* cmCommandArgumentParserHelper::ExpandSpecialVariable(const char* key, return nullptr; } -char* cmCommandArgumentParserHelper::ExpandVariable(const char* var) +const char* cmCommandArgumentParserHelper::ExpandVariable(const char* var) { if (!var) { return nullptr; @@ -125,11 +118,11 @@ char* cmCommandArgumentParserHelper::ExpandVariable(const char* var) return this->AddString(value ? value : ""); } -char* cmCommandArgumentParserHelper::ExpandVariableForAt(const char* var) +const char* cmCommandArgumentParserHelper::ExpandVariableForAt(const char* var) { if (this->ReplaceAtSyntax) { // try to expand the variable - char* ret = this->ExpandVariable(var); + const char* ret = this->ExpandVariable(var); // if the return was 0 and we want to replace empty strings // then return an empty string if (!ret && this->RemoveEmpty) { @@ -150,7 +143,8 @@ char* cmCommandArgumentParserHelper::ExpandVariableForAt(const char* var) return this->AddString(ref); } -char* cmCommandArgumentParserHelper::CombineUnions(char* in1, char* in2) +const char* cmCommandArgumentParserHelper::CombineUnions(const char* in1, + const char* in2) { if (!in1) { return in2; @@ -176,10 +170,11 @@ void cmCommandArgumentParserHelper::AllocateParserType( if (len == 0) { return; } - pt->str = new char[len + 1]; - strncpy(pt->str, str, len); - pt->str[len] = 0; - this->Variables.push_back(pt->str); + char* out = new char[len + 1]; + strncpy(out, str, len); + out[len] = 0; + pt->str = out; + this->Variables.push_back(out); } bool cmCommandArgumentParserHelper::HandleEscapeSymbol( diff --git a/Source/cmCommandArgumentParserHelper.h b/Source/cmCommandArgumentParserHelper.h index cb2a390..098c000 100644 --- a/Source/cmCommandArgumentParserHelper.h +++ b/Source/cmCommandArgumentParserHelper.h @@ -17,7 +17,7 @@ class cmCommandArgumentParserHelper public: struct ParserType { - char* str; + const char* str; }; cmCommandArgumentParserHelper(); @@ -35,11 +35,11 @@ public: void Error(const char* str); // For yacc - char* CombineUnions(char* in1, char* in2); + const char* CombineUnions(const char* in1, const char* in2); - char* ExpandSpecialVariable(const char* key, const char* var); - char* ExpandVariable(const char* var); - char* ExpandVariableForAt(const char* var); + const char* ExpandSpecialVariable(const char* key, const char* var); + const char* ExpandVariable(const char* var); + const char* ExpandVariableForAt(const char* var); void SetResult(const char* value); void SetMakefile(const cmMakefile* mf); @@ -53,13 +53,6 @@ public: void SetRemoveEmpty(bool b) { this->RemoveEmpty = b; } const char* GetError() { return this->ErrorString.c_str(); } - char EmptyVariable[1]; - char DCURLYVariable[3]; - char RCURLYVariable[3]; - char ATVariable[3]; - char DOLLARVariable[3]; - char LCURLYVariable[3]; - char BSLASHVariable[3]; private: std::string::size_type InputBufferPos; @@ -69,7 +62,7 @@ private: void Print(const char* place, const char* str); void SafePrintMissing(const char* str, int line, int cnt); - char* AddString(const std::string& str); + const char* AddString(const std::string& str); void CleanupParser(); void SetError(std::string const& msg); diff --git a/Source/cmCurl.cxx b/Source/cmCurl.cxx index 341b8c0..8ef8bff 100644 --- a/Source/cmCurl.cxx +++ b/Source/cmCurl.cxx @@ -56,3 +56,41 @@ std::string cmCurlSetCAInfo(::CURL* curl, const char* cafile) #endif return e; } + +std::string cmCurlSetNETRCOption(::CURL* curl, const std::string& netrc_level, + const std::string& netrc_file) +{ + std::string e; + CURL_NETRC_OPTION curl_netrc_level = CURL_NETRC_LAST; + ::CURLcode res; + + if (!netrc_level.empty()) { + if (netrc_level == "OPTIONAL") { + curl_netrc_level = CURL_NETRC_OPTIONAL; + } else if (netrc_level == "REQUIRED") { + curl_netrc_level = CURL_NETRC_REQUIRED; + } else if (netrc_level == "IGNORED") { + curl_netrc_level = CURL_NETRC_IGNORED; + } else { + e = "NETRC accepts OPTIONAL, IGNORED or REQUIRED but got: "; + e += netrc_level; + return e; + } + } + + if (curl_netrc_level != CURL_NETRC_LAST && + curl_netrc_level != CURL_NETRC_IGNORED) { + res = ::curl_easy_setopt(curl, CURLOPT_NETRC, curl_netrc_level); + check_curl_result(res, "Unable to set netrc level: "); + if (!e.empty()) { + return e; + } + + // check to see if a .netrc file has been specified + if (!netrc_file.empty()) { + res = ::curl_easy_setopt(curl, CURLOPT_NETRC_FILE, netrc_file.c_str()); + check_curl_result(res, "Unable to set .netrc file path : "); + } + } + return e; +} diff --git a/Source/cmCurl.h b/Source/cmCurl.h index 0688bb2..fe7eb80 100644 --- a/Source/cmCurl.h +++ b/Source/cmCurl.h @@ -9,5 +9,7 @@ #include <string> std::string cmCurlSetCAInfo(::CURL* curl, const char* cafile = nullptr); +std::string cmCurlSetNETRCOption(::CURL* curl, const std::string& netrc_level, + const std::string& netrc_file); #endif diff --git a/Source/cmExternalMakefileProjectGenerator.cxx b/Source/cmExternalMakefileProjectGenerator.cxx index 825ec65..fecd821 100644 --- a/Source/cmExternalMakefileProjectGenerator.cxx +++ b/Source/cmExternalMakefileProjectGenerator.cxx @@ -24,6 +24,13 @@ std::string cmExternalMakefileProjectGenerator::CreateFullGeneratorName( return fullName; } +bool cmExternalMakefileProjectGenerator::Open( + const std::string& /*bindir*/, const std::string& /*projectName*/, + bool /*dryRun*/) +{ + return false; +} + cmExternalMakefileProjectGeneratorFactory:: cmExternalMakefileProjectGeneratorFactory(const std::string& n, const std::string& doc) diff --git a/Source/cmExternalMakefileProjectGenerator.h b/Source/cmExternalMakefileProjectGenerator.h index a1734ee..7f332a8 100644 --- a/Source/cmExternalMakefileProjectGenerator.h +++ b/Source/cmExternalMakefileProjectGenerator.h @@ -55,6 +55,9 @@ public: void SetName(const std::string& n) { Name = n; } std::string GetName() const { return Name; } + virtual bool Open(const std::string& bindir, const std::string& projectName, + bool dryRun); + protected: ///! Contains the names of the global generators support by this generator. std::vector<std::string> SupportedGlobalGenerators; diff --git a/Source/cmExtraSublimeTextGenerator.cxx b/Source/cmExtraSublimeTextGenerator.cxx index 73a9c85..3d72ae3 100644 --- a/Source/cmExtraSublimeTextGenerator.cxx +++ b/Source/cmExtraSublimeTextGenerator.cxx @@ -400,3 +400,26 @@ std::string cmExtraSublimeTextGenerator::ComputeDefines( return definesString; } + +bool cmExtraSublimeTextGenerator::Open(const std::string& bindir, + const std::string& projectName, + bool dryRun) +{ + const char* sublExecutable = + this->GlobalGenerator->GetCMakeInstance()->GetCacheDefinition( + "CMAKE_SUBLIMETEXT_EXECUTABLE"); + if (!sublExecutable) { + return false; + } + if (cmSystemTools::IsNOTFOUND(sublExecutable)) { + return false; + } + + std::string filename = bindir + "/" + projectName + ".sublime-project"; + if (dryRun) { + return cmSystemTools::FileExists(filename, true); + } + + return cmSystemTools::RunSingleCommand( + { sublExecutable, "--project", filename }); +} diff --git a/Source/cmExtraSublimeTextGenerator.h b/Source/cmExtraSublimeTextGenerator.h index 7fb304e..57ba1cf 100644 --- a/Source/cmExtraSublimeTextGenerator.h +++ b/Source/cmExtraSublimeTextGenerator.h @@ -65,6 +65,9 @@ private: std::string ComputeDefines(cmSourceFile* source, cmLocalGenerator* lg, cmGeneratorTarget* gtgt); + bool Open(const std::string& bindir, const std::string& projectName, + bool dryRun) override; + bool ExcludeBuildFolder; std::string EnvSettings; }; diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx index fdd5f0c..191a666 100644 --- a/Source/cmFileCommand.cxx +++ b/Source/cmFileCommand.cxx @@ -2626,6 +2626,9 @@ bool cmFileCommand::HandleDownloadCommand(std::vector<std::string> const& args) std::string statusVar; bool tls_verify = this->Makefile->IsOn("CMAKE_TLS_VERIFY"); const char* cainfo = this->Makefile->GetDefinition("CMAKE_TLS_CAINFO"); + std::string netrc_level = this->Makefile->GetSafeDefinition("CMAKE_NETRC"); + std::string netrc_file = + this->Makefile->GetSafeDefinition("CMAKE_NETRC_FILE"); std::string expectedHash; std::string hashMatchMSG; std::unique_ptr<cmCryptoHash> hash; @@ -2681,6 +2684,22 @@ bool cmFileCommand::HandleDownloadCommand(std::vector<std::string> const& args) this->SetError("TLS_CAFILE missing file value."); return false; } + } else if (*i == "NETRC_FILE") { + ++i; + if (i != args.end()) { + netrc_file = *i; + } else { + this->SetError("DOWNLOAD missing file value for NETRC_FILE."); + return false; + } + } else if (*i == "NETRC") { + ++i; + if (i != args.end()) { + netrc_level = *i; + } else { + this->SetError("DOWNLOAD missing level value for NETRC."); + return false; + } } else if (*i == "EXPECTED_MD5") { ++i; if (i == args.end()) { @@ -2822,6 +2841,16 @@ bool cmFileCommand::HandleDownloadCommand(std::vector<std::string> const& args) return false; } + // check to see if netrc parameters have been specified + // local command args takes precedence over CMAKE_NETRC* + netrc_level = cmSystemTools::UpperCase(netrc_level); + std::string const& netrc_option_err = + cmCurlSetNETRCOption(curl, netrc_level, netrc_file); + if (!netrc_option_err.empty()) { + this->SetError(netrc_option_err); + return false; + } + cmFileCommandVectorOfChar chunkDebug; res = ::curl_easy_setopt(curl, CURLOPT_WRITEDATA, &fout); @@ -2964,6 +2993,9 @@ bool cmFileCommand::HandleUploadCommand(std::vector<std::string> const& args) std::string statusVar; bool showProgress = false; std::string userpwd; + std::string netrc_level = this->Makefile->GetSafeDefinition("CMAKE_NETRC"); + std::string netrc_file = + this->Makefile->GetSafeDefinition("CMAKE_NETRC_FILE"); std::vector<std::string> curl_headers; @@ -3000,6 +3032,22 @@ bool cmFileCommand::HandleUploadCommand(std::vector<std::string> const& args) statusVar = *i; } else if (*i == "SHOW_PROGRESS") { showProgress = true; + } else if (*i == "NETRC_FILE") { + ++i; + if (i != args.end()) { + netrc_file = *i; + } else { + this->SetError("UPLOAD missing file value for NETRC_FILE."); + return false; + } + } else if (*i == "NETRC") { + ++i; + if (i != args.end()) { + netrc_level = *i; + } else { + this->SetError("UPLOAD missing level value for NETRC."); + return false; + } } else if (*i == "USERPWD") { ++i; if (i == args.end()) { @@ -3132,6 +3180,16 @@ bool cmFileCommand::HandleUploadCommand(std::vector<std::string> const& args) check_curl_result(res, "UPLOAD cannot set user password: "); } + // check to see if netrc parameters have been specified + // local command args takes precedence over CMAKE_NETRC* + netrc_level = cmSystemTools::UpperCase(netrc_level); + std::string const& netrc_option_err = + cmCurlSetNETRCOption(curl, netrc_level, netrc_file); + if (!netrc_option_err.empty()) { + this->SetError(netrc_option_err); + return false; + } + struct curl_slist* headers = nullptr; for (std::string const& h : curl_headers) { headers = ::curl_slist_append(headers, h.c_str()); diff --git a/Source/cmFilePathChecksum.cxx b/Source/cmFilePathChecksum.cxx index f9afeef..f84360e 100644 --- a/Source/cmFilePathChecksum.cxx +++ b/Source/cmFilePathChecksum.cxx @@ -34,10 +34,10 @@ void cmFilePathChecksum::setupParentDirs(std::string const& currentSrcDir, std::string const& projectSrcDir, std::string const& projectBinDir) { - this->parentDirs[0].first = cmsys::SystemTools::GetRealPath(currentSrcDir); - this->parentDirs[1].first = cmsys::SystemTools::GetRealPath(currentBinDir); - this->parentDirs[2].first = cmsys::SystemTools::GetRealPath(projectSrcDir); - this->parentDirs[3].first = cmsys::SystemTools::GetRealPath(projectBinDir); + this->parentDirs[0].first = cmSystemTools::GetRealPath(currentSrcDir); + this->parentDirs[1].first = cmSystemTools::GetRealPath(currentBinDir); + this->parentDirs[2].first = cmSystemTools::GetRealPath(projectSrcDir); + this->parentDirs[3].first = cmSystemTools::GetRealPath(projectBinDir); this->parentDirs[0].second = "CurrentSource"; this->parentDirs[1].second = "CurrentBinary"; @@ -50,7 +50,7 @@ std::string cmFilePathChecksum::get(std::string const& filePath) const std::string relPath; std::string relSeed; { - std::string const fileReal = cmsys::SystemTools::GetRealPath(filePath); + std::string const fileReal = cmSystemTools::GetRealPath(filePath); std::string parentDir; // Find closest project parent directory for (auto const& pDir : this->parentDirs) { diff --git a/Source/cmForEachCommand.cxx b/Source/cmForEachCommand.cxx index 542a860..df288bd 100644 --- a/Source/cmForEachCommand.cxx +++ b/Source/cmForEachCommand.cxx @@ -7,6 +7,7 @@ #include <stdio.h> #include <stdlib.h> +#include "cmAlgorithms.h" #include "cmExecutionStatus.h" #include "cmMakefile.h" #include "cmSystemTools.h" @@ -121,7 +122,7 @@ bool cmForEachCommand::InitialPass(std::vector<std::string> const& args, } // create a function blocker - cmForEachFunctionBlocker* f = new cmForEachFunctionBlocker(this->Makefile); + auto f = cm::make_unique<cmForEachFunctionBlocker>(this->Makefile); if (args.size() > 1) { if (args[1] == "RANGE") { int start = 0; @@ -175,7 +176,7 @@ bool cmForEachCommand::InitialPass(std::vector<std::string> const& args, } else { f->Args = args; } - this->Makefile->AddFunctionBlocker(f); + this->Makefile->AddFunctionBlocker(f.release()); return true; } diff --git a/Source/cmGeneratorExpressionNode.cxx b/Source/cmGeneratorExpressionNode.cxx index fea20ba..7fe0cbe 100644 --- a/Source/cmGeneratorExpressionNode.cxx +++ b/Source/cmGeneratorExpressionNode.cxx @@ -1035,7 +1035,7 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode // No error. We just skip cyclic references. return std::string(); case cmGeneratorExpressionDAGChecker::ALREADY_SEEN: - for (size_t i = 1; i < cmArraySize(targetPropertyTransitiveWhitelist); + for (size_t i = 1; i < cm::size(targetPropertyTransitiveWhitelist); ++i) { if (targetPropertyTransitiveWhitelist[i] == propertyName) { // No error. We're not going to find anything new here. @@ -1443,7 +1443,7 @@ static const struct TargetPolicyNode : public cmGeneratorExpressionNode context->HadContextSensitiveCondition = true; context->HadHeadSensitiveCondition = true; - for (size_t i = 1; i < cmArraySize(targetPolicyWhitelist); ++i) { + for (size_t i = 1; i < cm::size(targetPolicyWhitelist); ++i) { const char* policy = targetPolicyWhitelist[i]; if (parameters.front() == policy) { cmLocalGenerator* lg = context->HeadTarget->GetLocalGenerator(); diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx index 05efff3..11ea46f 100644 --- a/Source/cmGlobalGenerator.cxx +++ b/Source/cmGlobalGenerator.cxx @@ -111,6 +111,26 @@ cmGlobalGenerator::~cmGlobalGenerator() delete this->ExtraGenerator; } +bool cmGlobalGenerator::SetGeneratorInstance(std::string const& i, + cmMakefile* mf) +{ + if (i.empty()) { + return true; + } + + std::ostringstream e; + /* clang-format off */ + e << + "Generator\n" + " " << this->GetName() << "\n" + "does not support instance specification, but instance\n" + " " << i << "\n" + "was specified."; + /* clang-format on */ + mf->IssueMessage(cmake::FATAL_ERROR, e.str()); + return false; +} + bool cmGlobalGenerator::SetGeneratorPlatform(std::string const& p, cmMakefile* mf) { @@ -261,6 +281,43 @@ void cmGlobalGenerator::ForceLinkerLanguages() { } +bool cmGlobalGenerator::CheckTargetsForMissingSources() const +{ + bool failed = false; + for (cmLocalGenerator* localGen : this->LocalGenerators) { + const std::vector<cmGeneratorTarget*>& targets = + localGen->GetGeneratorTargets(); + + for (cmGeneratorTarget* target : targets) { + if (target->GetType() == cmStateEnums::TargetType::GLOBAL_TARGET || + target->GetType() == cmStateEnums::TargetType::INTERFACE_LIBRARY || + target->GetType() == cmStateEnums::TargetType::UTILITY) { + continue; + } + + std::vector<std::string> configs; + target->Makefile->GetConfigurations(configs); + std::vector<cmSourceFile*> srcs; + if (configs.empty()) { + target->GetSourceFiles(srcs, ""); + } else { + for (std::vector<std::string>::const_iterator ci = configs.begin(); + ci != configs.end() && srcs.empty(); ++ci) { + target->GetSourceFiles(srcs, *ci); + } + } + if (srcs.empty()) { + std::ostringstream e; + e << "No SOURCES given to target: " << target->GetName(); + this->GetCMakeInstance()->IssueMessage(cmake::FATAL_ERROR, e.str(), + target->GetBacktrace()); + failed = true; + } + } + } + return failed; +} + bool cmGlobalGenerator::IsExportedTargetsFile( const std::string& filename) const { @@ -491,6 +548,13 @@ void cmGlobalGenerator::EnableLanguage( } if (readCMakeSystem) { + // Tell the generator about the instance, if any. + std::string instance = mf->GetSafeDefinition("CMAKE_GENERATOR_INSTANCE"); + if (!this->SetGeneratorInstance(instance, mf)) { + cmSystemTools::SetFatalErrorOccured(); + return; + } + // Find the native build tool for this generator. if (!this->FindMakeProgram(mf)) { return; @@ -1292,6 +1356,11 @@ bool cmGlobalGenerator::Compute() localGen->TraceDependencies(); } + // Make sure that all (non-imported) targets have source files added! + if (this->CheckTargetsForMissingSources()) { + return false; + } + this->ForceLinkerLanguages(); // Compute the manifest of main targets generated. @@ -1824,6 +1893,16 @@ int cmGlobalGenerator::Build(const std::string& /*unused*/, return retVal; } +bool cmGlobalGenerator::Open(const std::string& bindir, + const std::string& projectName, bool dryRun) +{ + if (this->ExtraGenerator) { + return this->ExtraGenerator->Open(bindir, projectName, dryRun); + } + + return false; +} + std::string cmGlobalGenerator::GenerateCMakeBuildCommand( const std::string& target, const std::string& config, const std::string& native, bool ignoreErrors) @@ -2141,6 +2220,45 @@ inline std::string removeQuotes(const std::string& s) return s; } +bool cmGlobalGenerator::CheckCMP0037(std::string const& targetName, + std::string const& reason) const +{ + cmTarget* tgt = this->FindTarget(targetName); + if (!tgt) { + return true; + } + cmake::MessageType messageType = cmake::AUTHOR_WARNING; + std::ostringstream e; + bool issueMessage = false; + switch (tgt->GetPolicyStatusCMP0037()) { + case cmPolicies::WARN: + e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0037) << "\n"; + issueMessage = true; + CM_FALLTHROUGH; + case cmPolicies::OLD: + break; + case cmPolicies::NEW: + case cmPolicies::REQUIRED_IF_USED: + case cmPolicies::REQUIRED_ALWAYS: + issueMessage = true; + messageType = cmake::FATAL_ERROR; + break; + } + if (issueMessage) { + e << "The target name \"" << targetName << "\" is reserved " << reason + << "."; + if (messageType == cmake::AUTHOR_WARNING) { + e << " It may result in undefined behavior."; + } + this->GetCMakeInstance()->IssueMessage(messageType, e.str(), + tgt->GetBacktrace()); + if (messageType == cmake::FATAL_ERROR) { + return false; + } + } + return true; +} + void cmGlobalGenerator::CreateDefaultGlobalTargets( std::vector<GlobalTargetInfo>& targets) { @@ -2156,6 +2274,20 @@ void cmGlobalGenerator::AddGlobalTarget_Package( std::vector<GlobalTargetInfo>& targets) { cmMakefile* mf = this->Makefiles[0]; + std::string configFile = mf->GetCurrentBinaryDirectory(); + configFile += "/CPackConfig.cmake"; + if (!cmSystemTools::FileExists(configFile.c_str())) { + return; + } + + const char* reservedTargets[] = { "package", "PACKAGE" }; + for (const char* const* tn = cm::cbegin(reservedTargets); + tn != cm::cend(reservedTargets); ++tn) { + if (!this->CheckCMP0037(*tn, "when CPack packaging is enabled")) { + return; + } + } + const char* cmakeCfgIntDir = this->GetCMakeCFGIntDir(); GlobalTargetInfo gti; gti.Name = this->GetPackageTargetName(); @@ -2169,8 +2301,6 @@ void cmGlobalGenerator::AddGlobalTarget_Package( singleLine.push_back(cmakeCfgIntDir); } singleLine.push_back("--config"); - std::string configFile = mf->GetCurrentBinaryDirectory(); - configFile += "/CPackConfig.cmake"; std::string relConfigFile = "./CPackConfig.cmake"; singleLine.push_back(relConfigFile); gti.CommandLines.push_back(singleLine); @@ -2183,61 +2313,81 @@ void cmGlobalGenerator::AddGlobalTarget_Package( gti.Depends.push_back(this->GetAllTargetName()); } } - if (cmSystemTools::FileExists(configFile.c_str())) { - targets.push_back(gti); - } + targets.push_back(gti); } void cmGlobalGenerator::AddGlobalTarget_PackageSource( std::vector<GlobalTargetInfo>& targets) { - cmMakefile* mf = this->Makefiles[0]; const char* packageSourceTargetName = this->GetPackageSourceTargetName(); - if (packageSourceTargetName) { - GlobalTargetInfo gti; - gti.Name = packageSourceTargetName; - gti.Message = "Run CPack packaging tool for source..."; - gti.WorkingDir = mf->GetCurrentBinaryDirectory(); - gti.UsesTerminal = true; - cmCustomCommandLine singleLine; - singleLine.push_back(cmSystemTools::GetCPackCommand()); - singleLine.push_back("--config"); - std::string configFile = mf->GetCurrentBinaryDirectory(); - configFile += "/CPackSourceConfig.cmake"; - std::string relConfigFile = "./CPackSourceConfig.cmake"; - singleLine.push_back(relConfigFile); - if (cmSystemTools::FileExists(configFile.c_str())) { - singleLine.push_back(configFile); - gti.CommandLines.push_back(singleLine); - targets.push_back(gti); + if (!packageSourceTargetName) { + return; + } + + cmMakefile* mf = this->Makefiles[0]; + std::string configFile = mf->GetCurrentBinaryDirectory(); + configFile += "/CPackSourceConfig.cmake"; + if (!cmSystemTools::FileExists(configFile.c_str())) { + return; + } + + const char* reservedTargets[] = { "package_source" }; + for (const char* const* tn = cm::cbegin(reservedTargets); + tn != cm::cend(reservedTargets); ++tn) { + if (!this->CheckCMP0037(*tn, "when CPack source packaging is enabled")) { + return; } } + + GlobalTargetInfo gti; + gti.Name = packageSourceTargetName; + gti.Message = "Run CPack packaging tool for source..."; + gti.WorkingDir = mf->GetCurrentBinaryDirectory(); + gti.UsesTerminal = true; + cmCustomCommandLine singleLine; + singleLine.push_back(cmSystemTools::GetCPackCommand()); + singleLine.push_back("--config"); + std::string relConfigFile = "./CPackSourceConfig.cmake"; + singleLine.push_back(relConfigFile); + singleLine.push_back(configFile); + gti.CommandLines.push_back(singleLine); + targets.push_back(gti); } void cmGlobalGenerator::AddGlobalTarget_Test( std::vector<GlobalTargetInfo>& targets) { cmMakefile* mf = this->Makefiles[0]; - const char* cmakeCfgIntDir = this->GetCMakeCFGIntDir(); - if (mf->IsOn("CMAKE_TESTING_ENABLED")) { - GlobalTargetInfo gti; - gti.Name = this->GetTestTargetName(); - gti.Message = "Running tests..."; - gti.UsesTerminal = true; - cmCustomCommandLine singleLine; - singleLine.push_back(cmSystemTools::GetCTestCommand()); - singleLine.push_back("--force-new-ctest-process"); - if (cmakeCfgIntDir && *cmakeCfgIntDir && cmakeCfgIntDir[0] != '.') { - singleLine.push_back("-C"); - singleLine.push_back(cmakeCfgIntDir); - } else // TODO: This is a hack. Should be something to do with the - // generator - { - singleLine.push_back("$(ARGS)"); + if (!mf->IsOn("CMAKE_TESTING_ENABLED")) { + return; + } + + const char* reservedTargets[] = { "test", "RUN_TESTS" }; + for (const char* const* tn = cm::cbegin(reservedTargets); + tn != cm::cend(reservedTargets); ++tn) { + if (!this->CheckCMP0037(*tn, "when CTest testing is enabled")) { + return; } - gti.CommandLines.push_back(singleLine); - targets.push_back(gti); } + + const char* cmakeCfgIntDir = this->GetCMakeCFGIntDir(); + GlobalTargetInfo gti; + gti.Name = this->GetTestTargetName(); + gti.Message = "Running tests..."; + gti.UsesTerminal = true; + cmCustomCommandLine singleLine; + singleLine.push_back(cmSystemTools::GetCTestCommand()); + singleLine.push_back("--force-new-ctest-process"); + if (cmakeCfgIntDir && *cmakeCfgIntDir && cmakeCfgIntDir[0] != '.') { + singleLine.push_back("-C"); + singleLine.push_back(cmakeCfgIntDir); + } else // TODO: This is a hack. Should be something to do with the + // generator + { + singleLine.push_back("$(ARGS)"); + } + gti.CommandLines.push_back(singleLine); + targets.push_back(gti); } void cmGlobalGenerator::AddGlobalTarget_EditCache( @@ -2503,14 +2653,13 @@ bool cmGlobalGenerator::IsReservedTarget(std::string const& name) // by one or more of the cmake generators. // Adding additional targets to this list will require a policy! - const char* reservedTargets[] = { - "all", "ALL_BUILD", "help", "install", "INSTALL", - "preinstall", "clean", "edit_cache", "rebuild_cache", "test", - "RUN_TESTS", "package", "PACKAGE", "package_source", "ZERO_CHECK" - }; - - return std::find(cmArrayBegin(reservedTargets), cmArrayEnd(reservedTargets), - name) != cmArrayEnd(reservedTargets); + const char* reservedTargets[] = { "all", "ALL_BUILD", "help", + "install", "INSTALL", "preinstall", + "clean", "edit_cache", "rebuild_cache", + "ZERO_CHECK" }; + + return std::find(cm::cbegin(reservedTargets), cm::cend(reservedTargets), + name) != cm::cend(reservedTargets); } void cmGlobalGenerator::SetExternalMakefileProjectGenerator( diff --git a/Source/cmGlobalGenerator.h b/Source/cmGlobalGenerator.h index 18ca682..8fcb533 100644 --- a/Source/cmGlobalGenerator.h +++ b/Source/cmGlobalGenerator.h @@ -70,6 +70,9 @@ public: /** Tell the generator about the target system. */ virtual bool SetSystemName(std::string const&, cmMakefile*) { return true; } + /** Set the generator-specific instance. Returns true if supported. */ + virtual bool SetGeneratorInstance(std::string const& i, cmMakefile* mf); + /** Set the generator-specific platform name. Returns true if platform is supported and false otherwise. */ virtual bool SetGeneratorPlatform(std::string const& p, cmMakefile* mf); @@ -162,6 +165,12 @@ public: std::vector<std::string> const& nativeOptions = std::vector<std::string>()); + /** + * Open a generated IDE project given the following information. + */ + virtual bool Open(const std::string& bindir, const std::string& projectName, + bool dryRun); + virtual void GenerateBuildCommand( std::vector<std::string>& makeCommand, const std::string& makeProgram, const std::string& projectName, const std::string& projectDir, @@ -533,6 +542,8 @@ private: virtual void ForceLinkerLanguages(); + bool CheckTargetsForMissingSources() const; + void CreateLocalGenerators(); void CheckCompilerIdCompatibility(cmMakefile* mf, @@ -557,6 +568,9 @@ private: void ClearGeneratorMembers(); + bool CheckCMP0037(std::string const& targetName, + std::string const& reason) const; + void IndexMakefile(cmMakefile* mf); virtual const char* GetBuildIgnoreErrorsFlag() const { return nullptr; } diff --git a/Source/cmGlobalVisualStudio15Generator.cxx b/Source/cmGlobalVisualStudio15Generator.cxx index d2bf7cc..014d93d 100644 --- a/Source/cmGlobalVisualStudio15Generator.cxx +++ b/Source/cmGlobalVisualStudio15Generator.cxx @@ -111,6 +111,53 @@ void cmGlobalVisualStudio15Generator::WriteSLNHeader(std::ostream& fout) } } +bool cmGlobalVisualStudio15Generator::SetGeneratorInstance( + std::string const& i, cmMakefile* mf) +{ + if (!i.empty()) { + if (!this->vsSetupAPIHelper.SetVSInstance(i)) { + std::ostringstream e; + /* clang-format off */ + e << + "Generator\n" + " " << this->GetName() << "\n" + "could not find specified instance of Visual Studio:\n" + " " << i; + /* clang-format on */ + mf->IssueMessage(cmake::FATAL_ERROR, e.str()); + return false; + } + } + + std::string vsInstance; + if (!this->vsSetupAPIHelper.GetVSInstanceInfo(vsInstance)) { + std::ostringstream e; + /* clang-format off */ + e << + "Generator\n" + " " << this->GetName() << "\n" + "could not find any instance of Visual Studio.\n"; + /* clang-format on */ + mf->IssueMessage(cmake::FATAL_ERROR, e.str()); + return false; + } + + // Save the selected instance persistently. + std::string genInstance = mf->GetSafeDefinition("CMAKE_GENERATOR_INSTANCE"); + if (vsInstance != genInstance) { + this->CMakeInstance->AddCacheEntry( + "CMAKE_GENERATOR_INSTANCE", vsInstance.c_str(), + "Generator instance identifier.", cmStateEnums::INTERNAL); + } + + return true; +} + +bool cmGlobalVisualStudio15Generator::GetVSInstance(std::string& dir) const +{ + return vsSetupAPIHelper.GetVSInstanceInfo(dir); +} + bool cmGlobalVisualStudio15Generator::InitializeWindows(cmMakefile* mf) { // If the Win 8.1 SDK is installed then we can select a SDK matching diff --git a/Source/cmGlobalVisualStudio15Generator.h b/Source/cmGlobalVisualStudio15Generator.h index e934882..852a4e7 100644 --- a/Source/cmGlobalVisualStudio15Generator.h +++ b/Source/cmGlobalVisualStudio15Generator.h @@ -27,6 +27,11 @@ public: virtual void WriteSLNHeader(std::ostream& fout); virtual const char* GetToolsVersion() { return "15.0"; } + + bool SetGeneratorInstance(std::string const& i, cmMakefile* mf) override; + + bool GetVSInstance(std::string& dir) const; + protected: bool InitializeWindows(cmMakefile* mf) override; virtual bool SelectWindowsStoreToolset(std::string& toolset) const; diff --git a/Source/cmGlobalVisualStudioGenerator.cxx b/Source/cmGlobalVisualStudioGenerator.cxx index 0651536..99600df 100644 --- a/Source/cmGlobalVisualStudioGenerator.cxx +++ b/Source/cmGlobalVisualStudioGenerator.cxx @@ -4,7 +4,10 @@ #include "cmGlobalVisualStudioGenerator.h" #include "cmsys/Encoding.hxx" +#include <future> #include <iostream> +#include <objbase.h> +#include <shellapi.h> #include <windows.h> #include "cmAlgorithms.h" @@ -103,15 +106,6 @@ void cmGlobalVisualStudioGenerator::AddExtraIDETargets() // Configure CMake Visual Studio macros, for this user on this version // of Visual Studio. this->ConfigureCMakeVisualStudioMacros(); - - // Add CMakeLists.txt with custom command to rerun CMake. - for (std::vector<cmLocalGenerator*>::const_iterator lgi = - this->LocalGenerators.begin(); - lgi != this->LocalGenerators.end(); ++lgi) { - cmLocalVisualStudioGenerator* lg = - static_cast<cmLocalVisualStudioGenerator*>(*lgi); - lg->AddCMakeListsRules(); - } } void cmGlobalVisualStudioGenerator::ComputeTargetObjectDirectory( @@ -928,3 +922,33 @@ void cmGlobalVisualStudioGenerator::AddSymbolExportCommand( commandLines, "Auto build dll exports", "."); commands.push_back(command); } + +static bool OpenSolution(std::string sln) +{ + HRESULT comInitialized = + CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE); + if (FAILED(comInitialized)) { + return false; + } + + HINSTANCE hi = + ShellExecuteA(NULL, "open", sln.c_str(), NULL, NULL, SW_SHOWNORMAL); + + CoUninitialize(); + + return reinterpret_cast<intptr_t>(hi) > 32; +} + +bool cmGlobalVisualStudioGenerator::Open(const std::string& bindir, + const std::string& projectName, + bool dryRun) +{ + std::string buildDir = cmSystemTools::ConvertToOutputPath(bindir.c_str()); + std::string sln = buildDir + "\\" + projectName + ".sln"; + + if (dryRun) { + return cmSystemTools::FileExists(sln, true); + } + + return std::async(std::launch::async, OpenSolution, sln).get(); +} diff --git a/Source/cmGlobalVisualStudioGenerator.h b/Source/cmGlobalVisualStudioGenerator.h index 62bfd3b..55a6813 100644 --- a/Source/cmGlobalVisualStudioGenerator.h +++ b/Source/cmGlobalVisualStudioGenerator.h @@ -131,6 +131,9 @@ public: std::vector<cmCustomCommand>& commands, std::string const& configName); + bool Open(const std::string& bindir, const std::string& projectName, + bool dryRun) override; + protected: virtual void AddExtraIDETargets(); diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index c79ee47..a85a700 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -35,6 +35,11 @@ struct cmLinkImplementation; +#if defined(CMAKE_BUILD_WITH_CMAKE) && defined(__APPLE__) +#define HAVE_APPLICATION_SERVICES +#include <ApplicationServices/ApplicationServices.h> +#endif + #if defined(CMAKE_BUILD_WITH_CMAKE) #include "cmXMLParser.h" @@ -287,6 +292,35 @@ void cmGlobalXCodeGenerator::EnableLanguage( this->ComputeArchitectures(mf); } +bool cmGlobalXCodeGenerator::Open(const std::string& bindir, + const std::string& projectName, bool dryRun) +{ + bool ret = false; + +#ifdef HAVE_APPLICATION_SERVICES + std::string url = bindir + "/" + projectName + ".xcodeproj"; + + if (dryRun) { + return cmSystemTools::FileExists(url, false); + } + + CFStringRef cfStr = CFStringCreateWithCString( + kCFAllocatorDefault, url.c_str(), kCFStringEncodingUTF8); + if (cfStr) { + CFURLRef cfUrl = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, cfStr, + kCFURLPOSIXPathStyle, true); + if (cfUrl) { + OSStatus err = LSOpenCFURLRef(cfUrl, nullptr); + ret = err == noErr; + CFRelease(cfUrl); + } + CFRelease(cfStr); + } +#endif + + return ret; +} + void cmGlobalXCodeGenerator::GenerateBuildCommand( std::vector<std::string>& makeCommand, const std::string& makeProgram, const std::string& projectName, const std::string& /*projectDir*/, @@ -354,6 +388,17 @@ void cmGlobalXCodeGenerator::Generate() std::map<std::string, std::vector<cmLocalGenerator*>>::iterator it; for (it = this->ProjectMap.begin(); it != this->ProjectMap.end(); ++it) { cmLocalGenerator* root = it->second[0]; + + bool generateTopLevelProjectOnly = + root->GetMakefile()->IsOn("CMAKE_XCODE_GENERATE_TOP_LEVEL_PROJECT_ONLY"); + + if (generateTopLevelProjectOnly) { + cmStateSnapshot snp = root->GetStateSnapshot(); + if (snp.GetBuildsystemDirectoryParent().IsValid()) { + continue; + } + } + this->SetGenerationRoot(root); // now create the project this->OutputXCodeProject(root, it->second); @@ -404,12 +449,6 @@ void cmGlobalXCodeGenerator::AddExtraTargets( cmGeneratorTarget* allBuildGt = new cmGeneratorTarget(allbuild, root); root->AddGeneratorTarget(allBuildGt); - // Refer to the main build configuration file for easy editing. - std::string listfile = root->GetCurrentSourceDirectory(); - listfile += "/"; - listfile += "CMakeLists.txt"; - allBuildGt->AddSource(listfile); - // Add XCODE depend helper std::string dir = root->GetCurrentBinaryDirectory(); cmCustomCommandLine makeHelper; @@ -479,12 +518,6 @@ void cmGlobalXCodeGenerator::AddExtraTargets( !target->GetPropertyAsBool("EXCLUDE_FROM_ALL")) { allbuild->AddUtility(target->GetName()); } - - // Refer to the build configuration file for easy editing. - listfile = gen->GetCurrentSourceDirectory(); - listfile += "/"; - listfile += "CMakeLists.txt"; - target->AddSource(listfile); } } } @@ -962,6 +995,13 @@ bool cmGlobalXCodeGenerator::CreateXCodeTargets( if (!gtgt->GetConfigCommonSourceFiles(classes)) { return false; } + + // Add CMakeLists.txt file for user convenience. + std::string listfile = + gtgt->GetLocalGenerator()->GetCurrentSourceDirectory(); + listfile += "/CMakeLists.txt"; + classes.push_back(gtgt->Makefile->GetOrCreateSource(listfile)); + std::sort(classes.begin(), classes.end(), cmSourceFilePathCompare()); gtgt->ComputeObjectMapping(); @@ -2259,12 +2299,19 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateUtilityTarget( this->XCodeObjectMap[gtgt] = target; // Add source files without build rules for editing convenience. - if (gtgt->GetType() == cmStateEnums::UTILITY) { + if (gtgt->GetType() == cmStateEnums::UTILITY && + gtgt->GetName() != CMAKE_CHECK_BUILD_SYSTEM_TARGET) { std::vector<cmSourceFile*> sources; if (!gtgt->GetConfigCommonSourceFiles(sources)) { return nullptr; } + // Add CMakeLists.txt file for user convenience. + std::string listfile = + gtgt->GetLocalGenerator()->GetCurrentSourceDirectory(); + listfile += "/CMakeLists.txt"; + sources.push_back(gtgt->Makefile->GetOrCreateSource(listfile)); + for (std::vector<cmSourceFile*>::const_iterator i = sources.begin(); i != sources.end(); ++i) { if (!(*i)->GetPropertyAsBool("GENERATED")) { @@ -2670,7 +2717,7 @@ bool cmGlobalXCodeGenerator::CreateGroups( generator->GetGeneratorTargets(); for (auto gtgt : tgts) { // Same skipping logic here as in CreateXCodeTargets so that we do not - // end up with (empty anyhow) ALL_BUILD and XCODE_DEPEND_HELPER source + // end up with (empty anyhow) ZERO_CHECK, install, or test source // groups: // if (gtgt->GetType() == cmStateEnums::GLOBAL_TARGET) { @@ -2679,6 +2726,9 @@ bool cmGlobalXCodeGenerator::CreateGroups( if (gtgt->GetType() == cmStateEnums::INTERFACE_LIBRARY) { continue; } + if (gtgt->GetName() == CMAKE_CHECK_BUILD_SYSTEM_TARGET) { + continue; + } // add the soon to be generated Info.plist file as a source for a // MACOSX_BUNDLE file @@ -2706,6 +2756,20 @@ bool cmGlobalXCodeGenerator::CreateGroups( std::string key = GetGroupMapKeyFromPath(gtgt, source); this->GroupMap[key] = pbxgroup; } + + // Add CMakeLists.txt file for user convenience. + { + std::string listfile = + gtgt->GetLocalGenerator()->GetCurrentSourceDirectory(); + listfile += "/CMakeLists.txt"; + cmSourceFile* sf = gtgt->Makefile->GetOrCreateSource(listfile); + std::string const& source = sf->GetFullPath(); + cmSourceGroup* sourceGroup = + mf->FindSourceGroup(source.c_str(), sourceGroups); + cmXCodeObject* pbxgroup = this->CreateOrGetPBXGroup(gtgt, sourceGroup); + std::string key = GetGroupMapKeyFromPath(gtgt, source); + this->GroupMap[key] = pbxgroup; + } } } return true; diff --git a/Source/cmGlobalXCodeGenerator.h b/Source/cmGlobalXCodeGenerator.h index e9ca91c..b758e97 100644 --- a/Source/cmGlobalXCodeGenerator.h +++ b/Source/cmGlobalXCodeGenerator.h @@ -55,6 +55,13 @@ public: */ void EnableLanguage(std::vector<std::string> const& languages, cmMakefile*, bool optional) override; + + /** + * Open a generated IDE project given the following information. + */ + bool Open(const std::string& bindir, const std::string& projectName, + bool dryRun) override; + /** * Try running cmake and building a file. This is used for dynalically * loaded commands, not as part of the usual build process. diff --git a/Source/cmLinkedTree.h b/Source/cmLinkedTree.h index 8865e23..975f052 100644 --- a/Source/cmLinkedTree.h +++ b/Source/cmLinkedTree.h @@ -137,7 +137,7 @@ public: iterator Push(iterator it) { return Push_impl(it, T()); } - iterator Push(iterator it, T t) { return Push_impl(it, t); } + iterator Push(iterator it, T t) { return Push_impl(it, std::move(t)); } bool IsLast(iterator it) { return it.Position == this->Data.size(); } @@ -177,12 +177,12 @@ private: T* GetPointer(PositionType pos) { return &this->Data[pos]; } - iterator Push_impl(iterator it, T t) + iterator Push_impl(iterator it, T&& t) { assert(this->UpPositions.size() == this->Data.size()); assert(it.Position <= this->UpPositions.size()); this->UpPositions.push_back(it.Position); - this->Data.push_back(t); + this->Data.push_back(std::move(t)); return iterator(this, this->UpPositions.size()); } diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index 1a088ea..12c0cfd 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -135,8 +135,8 @@ cmLocalGenerator::cmLocalGenerator(cmGlobalGenerator* gg, cmMakefile* makefile) this->VariableMappings[compilerOptionSysroot] = this->Makefile->GetSafeDefinition(compilerOptionSysroot); - for (const char* const* replaceIter = cmArrayBegin(ruleReplaceVars); - replaceIter != cmArrayEnd(ruleReplaceVars); ++replaceIter) { + for (const char* const* replaceIter = cm::cbegin(ruleReplaceVars); + replaceIter != cm::cend(ruleReplaceVars); ++replaceIter) { std::string actualReplace = *replaceIter; if (actualReplace.find("${LANG}") != std::string::npos) { cmSystemTools::ReplaceString(actualReplace, "${LANG}", lang); diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx index d8030b7..beb80f2 100644 --- a/Source/cmLocalVisualStudio7Generator.cxx +++ b/Source/cmLocalVisualStudio7Generator.cxx @@ -36,6 +36,13 @@ private: cmLocalVisualStudio7Generator* LocalGenerator; }; +class cmLocalVisualStudio7Generator::AllConfigSources +{ +public: + std::vector<cmGeneratorTarget::AllConfigSource> Sources; + std::map<cmSourceFile const*, size_t> Index; +}; + extern cmVS7FlagTable cmLocalVisualStudio7GeneratorFlagTable[]; static void cmConvertToWindowsSlash(std::string& s) @@ -83,29 +90,6 @@ void cmLocalVisualStudio7Generator::Generate() this->WriteStampFiles(); } -void cmLocalVisualStudio7Generator::AddCMakeListsRules() -{ - // Create the regeneration custom rule. - if (!this->Makefile->IsOn("CMAKE_SUPPRESS_REGENERATION")) { - // Create a rule to regenerate the build system when the target - // specification source changes. - if (cmSourceFile* sf = this->CreateVCProjBuildRule()) { - // Add the rule to targets that need it. - const std::vector<cmGeneratorTarget*>& tgts = - this->GetGeneratorTargets(); - for (std::vector<cmGeneratorTarget*>::const_iterator l = tgts.begin(); - l != tgts.end(); ++l) { - if ((*l)->GetType() == cmStateEnums::GLOBAL_TARGET) { - continue; - } - if ((*l)->GetName() != CMAKE_CHECK_BUILD_SYSTEM_TARGET) { - (*l)->AddSource(sf->GetFullPath()); - } - } - } - } -} - void cmLocalVisualStudio7Generator::FixGlobalTargets() { // Visual Studio .NET 2003 Service Pack 1 will not run post-build @@ -239,19 +223,29 @@ void cmLocalVisualStudio7Generator::CreateSingleVCProj( cmSourceFile* cmLocalVisualStudio7Generator::CreateVCProjBuildRule() { + if (this->Makefile->IsOn("CMAKE_SUPPRESS_REGENERATION")) { + return nullptr; + } + + std::string makefileIn = this->GetCurrentSourceDirectory(); + makefileIn += "/"; + makefileIn += "CMakeLists.txt"; + makefileIn = cmSystemTools::CollapseFullPath(makefileIn); + if (cmSourceFile* file = this->Makefile->GetSource(makefileIn)) { + if (file->GetCustomCommand()) { + return file; + } + } + if (!cmSystemTools::FileExists(makefileIn)) { + return nullptr; + } + std::string stampName = this->GetCurrentBinaryDirectory(); stampName += "/"; stampName += cmake::GetCMakeFilesDirectoryPostSlash(); stampName += "generate.stamp"; cmCustomCommandLine commandLine; commandLine.push_back(cmSystemTools::GetCMakeCommand()); - std::string makefileIn = this->GetCurrentSourceDirectory(); - makefileIn += "/"; - makefileIn += "CMakeLists.txt"; - makefileIn = cmSystemTools::CollapseFullPath(makefileIn.c_str()); - if (!cmSystemTools::FileExists(makefileIn.c_str())) { - return 0; - } std::string comment = "Building Custom Rule "; comment += makefileIn; std::string args; @@ -275,10 +269,13 @@ cmSourceFile* cmLocalVisualStudio7Generator::CreateVCProjBuildRule() fullpathStampName.c_str(), listFiles, makefileIn.c_str(), commandLines, comment.c_str(), no_working_directory, true, false); if (cmSourceFile* file = this->Makefile->GetSource(makefileIn.c_str())) { + // Finalize the source file path now since we're adding this after + // the generator validated all project-named sources. + file->GetFullPath(); return file; } else { cmSystemTools::Error("Error adding rule for ", makefileIn.c_str()); - return 0; + return nullptr; } } @@ -1368,13 +1365,26 @@ void cmLocalVisualStudio7Generator::WriteVCProjFile(std::ostream& fout, // We may be modifying the source groups temporarily, so make a copy. std::vector<cmSourceGroup> sourceGroups = this->Makefile->GetSourceGroups(); - std::vector<cmGeneratorTarget::AllConfigSource> const& sources = - target->GetAllConfigSources(); - std::map<cmSourceFile const*, size_t> sourcesIndex; + AllConfigSources sources; + sources.Sources = target->GetAllConfigSources(); + + // Add CMakeLists.txt file with rule to re-run CMake for user convenience. + if (target->GetType() != cmStateEnums::GLOBAL_TARGET && + target->GetName() != CMAKE_CHECK_BUILD_SYSTEM_TARGET) { + if (cmSourceFile const* sf = this->CreateVCProjBuildRule()) { + cmGeneratorTarget::AllConfigSource acs; + acs.Source = sf; + acs.Kind = cmGeneratorTarget::SourceKindCustomCommand; + for (size_t ci = 0; ci < configs.size(); ++ci) { + acs.Configs.push_back(ci); + } + sources.Sources.emplace_back(std::move(acs)); + } + } - for (size_t si = 0; si < sources.size(); ++si) { - cmSourceFile const* sf = sources[si].Source; - sourcesIndex[sf] = si; + for (size_t si = 0; si < sources.Sources.size(); ++si) { + cmSourceFile const* sf = sources.Sources[si].Source; + sources.Index[sf] = si; if (!sf->GetObjectLibrary().empty()) { if (this->FortranProject) { // Intel Fortran does not support per-config source locations @@ -1400,7 +1410,7 @@ void cmLocalVisualStudio7Generator::WriteVCProjFile(std::ostream& fout, // Loop through every source group. for (unsigned int i = 0; i < sourceGroups.size(); ++i) { cmSourceGroup sg = sourceGroups[i]; - this->WriteGroup(&sg, target, fout, libName, configs, sourcesIndex); + this->WriteGroup(&sg, target, fout, libName, configs, sources); } fout << "\t</Files>\n"; @@ -1567,7 +1577,7 @@ std::string cmLocalVisualStudio7Generator::ComputeLongestObjectDirectory( bool cmLocalVisualStudio7Generator::WriteGroup( const cmSourceGroup* sg, cmGeneratorTarget* target, std::ostream& fout, const std::string& libName, std::vector<std::string> const& configs, - std::map<cmSourceFile const*, size_t> const& sourcesIndex) + AllConfigSources const& sources) { cmGlobalVisualStudio7Generator* gg = static_cast<cmGlobalVisualStudio7Generator*>(this->GlobalGenerator); @@ -1579,7 +1589,7 @@ bool cmLocalVisualStudio7Generator::WriteGroup( std::ostringstream tmpOut; for (unsigned int i = 0; i < children.size(); ++i) { if (this->WriteGroup(&children[i], target, tmpOut, libName, configs, - sourcesIndex)) { + sources)) { hasChildrenWithSources = true; } } @@ -1595,9 +1605,6 @@ bool cmLocalVisualStudio7Generator::WriteGroup( this->WriteVCProjBeginGroup(fout, name.c_str(), ""); } - std::vector<cmGeneratorTarget::AllConfigSource> const& sources = - target->GetAllConfigSources(); - // Loop through each source in the source group. for (std::vector<const cmSourceFile*>::const_iterator sf = sourceFiles.begin(); @@ -1608,10 +1615,11 @@ bool cmLocalVisualStudio7Generator::WriteGroup( target->GetType() == cmStateEnums::GLOBAL_TARGET) { // Look up the source kind and configs. std::map<cmSourceFile const*, size_t>::const_iterator map_it = - sourcesIndex.find(*sf); + sources.Index.find(*sf); // The map entry must exist because we populated it earlier. - assert(map_it != sourcesIndex.end()); - cmGeneratorTarget::AllConfigSource const& acs = sources[map_it->second]; + assert(map_it != sources.Index.end()); + cmGeneratorTarget::AllConfigSource const& acs = + sources.Sources[map_it->second]; FCInfo fcinfo(this, target, acs, configs); diff --git a/Source/cmLocalVisualStudio7Generator.h b/Source/cmLocalVisualStudio7Generator.h index 7a77574..48f2e1a 100644 --- a/Source/cmLocalVisualStudio7Generator.h +++ b/Source/cmLocalVisualStudio7Generator.h @@ -65,7 +65,6 @@ public: virtual void ReadAndStoreExternalGUID(const std::string& name, const char* path); - virtual void AddCMakeListsRules(); protected: void CreateSingleVCProj(const std::string& lname, cmGeneratorTarget* tgt); @@ -117,10 +116,11 @@ private: FCInfo& fcinfo); void WriteTargetVersionAttribute(std::ostream& fout, cmGeneratorTarget* gt); + class AllConfigSources; bool WriteGroup(const cmSourceGroup* sg, cmGeneratorTarget* target, std::ostream& fout, const std::string& libName, std::vector<std::string> const& configs, - std::map<cmSourceFile const*, size_t> const& sourcesIndex); + AllConfigSources const& sources); friend class cmLocalVisualStudio7GeneratorFCInfo; friend class cmLocalVisualStudio7GeneratorInternals; diff --git a/Source/cmLocalVisualStudioGenerator.h b/Source/cmLocalVisualStudioGenerator.h index cba24fe..ace2f89 100644 --- a/Source/cmLocalVisualStudioGenerator.h +++ b/Source/cmLocalVisualStudioGenerator.h @@ -44,8 +44,6 @@ public: virtual std::string ComputeLongestObjectDirectory( cmGeneratorTarget const*) const = 0; - virtual void AddCMakeListsRules() = 0; - virtual void ComputeObjectFilenames( std::map<cmSourceFile const*, std::string>& mapping, cmGeneratorTarget const* = 0); diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index 5643c97..43c529c 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -7,6 +7,7 @@ #include <algorithm> #include <assert.h> #include <ctype.h> +#include <iterator> #include <memory> // IWYU pragma: keep #include <sstream> #include <stdlib.h> @@ -122,6 +123,42 @@ void cmMakefile::IssueMessage(cmake::MessageType t, this->GetCMakeInstance()->IssueMessage(t, text, this->GetBacktrace()); } +bool cmMakefile::CheckCMP0037(std::string const& targetName, + cmStateEnums::TargetType targetType) const +{ + cmake::MessageType messageType = cmake::AUTHOR_WARNING; + std::ostringstream e; + bool issueMessage = false; + switch (this->GetPolicyStatus(cmPolicies::CMP0037)) { + case cmPolicies::WARN: + if (targetType != cmStateEnums::INTERFACE_LIBRARY) { + e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0037) << "\n"; + issueMessage = true; + } + CM_FALLTHROUGH; + case cmPolicies::OLD: + break; + case cmPolicies::NEW: + case cmPolicies::REQUIRED_IF_USED: + case cmPolicies::REQUIRED_ALWAYS: + issueMessage = true; + messageType = cmake::FATAL_ERROR; + break; + } + if (issueMessage) { + e << "The target name \"" << targetName + << "\" is reserved or not valid for certain " + "CMake features, such as generator expressions, and may result " + "in undefined behavior."; + this->IssueMessage(messageType, e.str()); + + if (messageType == cmake::FATAL_ERROR) { + return false; + } + } + return true; +} + cmStringRange cmMakefile::GetIncludeDirectoriesEntries() const { return this->StateSnapshot.GetDirectory().GetIncludeDirectoriesEntries(); @@ -3186,6 +3223,7 @@ int cmMakefile::TryCompile(const std::string& srcdir, // do a configure cm.SetHomeDirectory(srcdir); cm.SetHomeOutputDirectory(bindir); + cm.SetGeneratorInstance(this->GetSafeDefinition("CMAKE_GENERATOR_INSTANCE")); cm.SetGeneratorPlatform(this->GetSafeDefinition("CMAKE_GENERATOR_PLATFORM")); cm.SetGeneratorToolset(this->GetSafeDefinition("CMAKE_GENERATOR_TOOLSET")); cm.LoadCache(); @@ -4133,15 +4171,15 @@ bool cmMakefile::CompileFeatureKnown(cmTarget const* target, assert(cmGeneratorExpression::Find(feature) == std::string::npos); bool isCFeature = - std::find_if(cmArrayBegin(C_FEATURES) + 1, cmArrayEnd(C_FEATURES), - cmStrCmp(feature)) != cmArrayEnd(C_FEATURES); + std::find_if(cm::cbegin(C_FEATURES) + 1, cm::cend(C_FEATURES), + cmStrCmp(feature)) != cm::cend(C_FEATURES); if (isCFeature) { lang = "C"; return true; } bool isCxxFeature = - std::find_if(cmArrayBegin(CXX_FEATURES) + 1, cmArrayEnd(CXX_FEATURES), - cmStrCmp(feature)) != cmArrayEnd(CXX_FEATURES); + std::find_if(cm::cbegin(CXX_FEATURES) + 1, cm::cend(CXX_FEATURES), + cmStrCmp(feature)) != cm::cend(CXX_FEATURES); if (isCxxFeature) { lang = "CXX"; return true; @@ -4230,8 +4268,8 @@ bool cmMakefile::HaveCStandardAvailable(cmTarget const* target, // Return true so the caller does not try to lookup the default standard. return true; } - if (std::find_if(cmArrayBegin(C_STANDARDS), cmArrayEnd(C_STANDARDS), - cmStrCmp(defaultCStandard)) == cmArrayEnd(C_STANDARDS)) { + if (std::find_if(cm::cbegin(C_STANDARDS), cm::cend(C_STANDARDS), + cmStrCmp(defaultCStandard)) == cm::cend(C_STANDARDS)) { std::ostringstream e; e << "The CMAKE_C_STANDARD_DEFAULT variable contains an " "invalid value: \"" @@ -4251,8 +4289,8 @@ bool cmMakefile::HaveCStandardAvailable(cmTarget const* target, existingCStandard = defaultCStandard; } - if (std::find_if(cmArrayBegin(C_STANDARDS), cmArrayEnd(C_STANDARDS), - cmStrCmp(existingCStandard)) == cmArrayEnd(C_STANDARDS)) { + if (std::find_if(cm::cbegin(C_STANDARDS), cm::cend(C_STANDARDS), + cmStrCmp(existingCStandard)) == cm::cend(C_STANDARDS)) { std::ostringstream e; e << "The C_STANDARD property on target \"" << target->GetName() << "\" contained an invalid value: \"" << existingCStandard << "\"."; @@ -4261,23 +4299,23 @@ bool cmMakefile::HaveCStandardAvailable(cmTarget const* target, } const char* const* existingCIt = existingCStandard - ? std::find_if(cmArrayBegin(C_STANDARDS), cmArrayEnd(C_STANDARDS), + ? std::find_if(cm::cbegin(C_STANDARDS), cm::cend(C_STANDARDS), cmStrCmp(existingCStandard)) - : cmArrayEnd(C_STANDARDS); + : cm::cend(C_STANDARDS); if (needC11 && existingCStandard && - existingCIt < std::find_if(cmArrayBegin(C_STANDARDS), - cmArrayEnd(C_STANDARDS), cmStrCmp("11"))) { + existingCIt < std::find_if(cm::cbegin(C_STANDARDS), + cm::cend(C_STANDARDS), cmStrCmp("11"))) { return false; } if (needC99 && existingCStandard && - existingCIt < std::find_if(cmArrayBegin(C_STANDARDS), - cmArrayEnd(C_STANDARDS), cmStrCmp("99"))) { + existingCIt < std::find_if(cm::cbegin(C_STANDARDS), + cm::cend(C_STANDARDS), cmStrCmp("99"))) { return false; } if (needC90 && existingCStandard && - existingCIt < std::find_if(cmArrayBegin(C_STANDARDS), - cmArrayEnd(C_STANDARDS), cmStrCmp("90"))) { + existingCIt < std::find_if(cm::cbegin(C_STANDARDS), + cm::cend(C_STANDARDS), cmStrCmp("90"))) { return false; } return true; @@ -4289,16 +4327,16 @@ bool cmMakefile::IsLaterStandard(std::string const& lang, { if (lang == "C") { const char* const* rhsIt = std::find_if( - cmArrayBegin(C_STANDARDS), cmArrayEnd(C_STANDARDS), cmStrCmp(rhs)); + cm::cbegin(C_STANDARDS), cm::cend(C_STANDARDS), cmStrCmp(rhs)); - return std::find_if(rhsIt, cmArrayEnd(C_STANDARDS), cmStrCmp(lhs)) != - cmArrayEnd(C_STANDARDS); + return std::find_if(rhsIt, cm::cend(C_STANDARDS), cmStrCmp(lhs)) != + cm::cend(C_STANDARDS); } const char* const* rhsIt = std::find_if( - cmArrayBegin(CXX_STANDARDS), cmArrayEnd(CXX_STANDARDS), cmStrCmp(rhs)); + cm::cbegin(CXX_STANDARDS), cm::cend(CXX_STANDARDS), cmStrCmp(rhs)); - return std::find_if(rhsIt, cmArrayEnd(CXX_STANDARDS), cmStrCmp(lhs)) != - cmArrayEnd(CXX_STANDARDS); + return std::find_if(rhsIt, cm::cend(CXX_STANDARDS), cmStrCmp(lhs)) != + cm::cend(CXX_STANDARDS); } bool cmMakefile::HaveCxxStandardAvailable(cmTarget const* target, @@ -4314,9 +4352,8 @@ bool cmMakefile::HaveCxxStandardAvailable(cmTarget const* target, // Return true so the caller does not try to lookup the default standard. return true; } - if (std::find_if(cmArrayBegin(CXX_STANDARDS), cmArrayEnd(CXX_STANDARDS), - cmStrCmp(defaultCxxStandard)) == - cmArrayEnd(CXX_STANDARDS)) { + if (std::find_if(cm::cbegin(CXX_STANDARDS), cm::cend(CXX_STANDARDS), + cmStrCmp(defaultCxxStandard)) == cm::cend(CXX_STANDARDS)) { std::ostringstream e; e << "The CMAKE_CXX_STANDARD_DEFAULT variable contains an " "invalid value: \"" @@ -4337,9 +4374,8 @@ bool cmMakefile::HaveCxxStandardAvailable(cmTarget const* target, existingCxxStandard = defaultCxxStandard; } - if (std::find_if(cmArrayBegin(CXX_STANDARDS), cmArrayEnd(CXX_STANDARDS), - cmStrCmp(existingCxxStandard)) == - cmArrayEnd(CXX_STANDARDS)) { + if (std::find_if(cm::cbegin(CXX_STANDARDS), cm::cend(CXX_STANDARDS), + cmStrCmp(existingCxxStandard)) == cm::cend(CXX_STANDARDS)) { std::ostringstream e; e << "The CXX_STANDARD property on target \"" << target->GetName() << "\" contained an invalid value: \"" << existingCxxStandard << "\"."; @@ -4348,32 +4384,28 @@ bool cmMakefile::HaveCxxStandardAvailable(cmTarget const* target, } const char* const* existingCxxIt = existingCxxStandard - ? std::find_if(cmArrayBegin(CXX_STANDARDS), cmArrayEnd(CXX_STANDARDS), + ? std::find_if(cm::cbegin(CXX_STANDARDS), cm::cend(CXX_STANDARDS), cmStrCmp(existingCxxStandard)) - : cmArrayEnd(CXX_STANDARDS); + : cm::cend(CXX_STANDARDS); if (needCxx17 && - existingCxxIt < std::find_if(cmArrayBegin(CXX_STANDARDS), - cmArrayEnd(CXX_STANDARDS), - cmStrCmp("17"))) { + existingCxxIt < std::find_if(cm::cbegin(CXX_STANDARDS), + cm::cend(CXX_STANDARDS), cmStrCmp("17"))) { return false; } if (needCxx14 && - existingCxxIt < std::find_if(cmArrayBegin(CXX_STANDARDS), - cmArrayEnd(CXX_STANDARDS), - cmStrCmp("14"))) { + existingCxxIt < std::find_if(cm::cbegin(CXX_STANDARDS), + cm::cend(CXX_STANDARDS), cmStrCmp("14"))) { return false; } if (needCxx11 && - existingCxxIt < std::find_if(cmArrayBegin(CXX_STANDARDS), - cmArrayEnd(CXX_STANDARDS), - cmStrCmp("11"))) { + existingCxxIt < std::find_if(cm::cbegin(CXX_STANDARDS), + cm::cend(CXX_STANDARDS), cmStrCmp("11"))) { return false; } if (needCxx98 && - existingCxxIt < std::find_if(cmArrayBegin(CXX_STANDARDS), - cmArrayEnd(CXX_STANDARDS), - cmStrCmp("98"))) { + existingCxxIt < std::find_if(cm::cbegin(CXX_STANDARDS), + cm::cend(CXX_STANDARDS), cmStrCmp("98"))) { return false; } return true; @@ -4423,9 +4455,9 @@ bool cmMakefile::AddRequiredTargetCxxFeature(cmTarget* target, const char* existingCxxStandard = target->GetProperty("CXX_STANDARD"); if (existingCxxStandard) { - if (std::find_if(cmArrayBegin(CXX_STANDARDS), cmArrayEnd(CXX_STANDARDS), + if (std::find_if(cm::cbegin(CXX_STANDARDS), cm::cend(CXX_STANDARDS), cmStrCmp(existingCxxStandard)) == - cmArrayEnd(CXX_STANDARDS)) { + cm::cend(CXX_STANDARDS)) { std::ostringstream e; e << "The CXX_STANDARD property on target \"" << target->GetName() << "\" contained an invalid value: \"" << existingCxxStandard << "\"."; @@ -4439,9 +4471,9 @@ bool cmMakefile::AddRequiredTargetCxxFeature(cmTarget* target, } } const char* const* existingCxxIt = existingCxxStandard - ? std::find_if(cmArrayBegin(CXX_STANDARDS), cmArrayEnd(CXX_STANDARDS), + ? std::find_if(cm::cbegin(CXX_STANDARDS), cm::cend(CXX_STANDARDS), cmStrCmp(existingCxxStandard)) - : cmArrayEnd(CXX_STANDARDS); + : cm::cend(CXX_STANDARDS); bool setCxx98 = needCxx98 && !existingCxxStandard; bool setCxx11 = needCxx11 && !existingCxxStandard; @@ -4449,23 +4481,22 @@ bool cmMakefile::AddRequiredTargetCxxFeature(cmTarget* target, bool setCxx17 = needCxx17 && !existingCxxStandard; if (needCxx17 && existingCxxStandard && - existingCxxIt < std::find_if(cmArrayBegin(CXX_STANDARDS), - cmArrayEnd(CXX_STANDARDS), - cmStrCmp("17"))) { + existingCxxIt < std::find_if(cm::cbegin(CXX_STANDARDS), + cm::cend(CXX_STANDARDS), cmStrCmp("17"))) { setCxx17 = true; } else if (needCxx14 && existingCxxStandard && - existingCxxIt < std::find_if(cmArrayBegin(CXX_STANDARDS), - cmArrayEnd(CXX_STANDARDS), + existingCxxIt < std::find_if(cm::cbegin(CXX_STANDARDS), + cm::cend(CXX_STANDARDS), cmStrCmp("14"))) { setCxx14 = true; } else if (needCxx11 && existingCxxStandard && - existingCxxIt < std::find_if(cmArrayBegin(CXX_STANDARDS), - cmArrayEnd(CXX_STANDARDS), + existingCxxIt < std::find_if(cm::cbegin(CXX_STANDARDS), + cm::cend(CXX_STANDARDS), cmStrCmp("11"))) { setCxx11 = true; } else if (needCxx98 && existingCxxStandard && - existingCxxIt < std::find_if(cmArrayBegin(CXX_STANDARDS), - cmArrayEnd(CXX_STANDARDS), + existingCxxIt < std::find_if(cm::cbegin(CXX_STANDARDS), + cm::cend(CXX_STANDARDS), cmStrCmp("98"))) { setCxx98 = true; } @@ -4522,8 +4553,8 @@ bool cmMakefile::AddRequiredTargetCFeature(cmTarget* target, const char* existingCStandard = target->GetProperty("C_STANDARD"); if (existingCStandard) { - if (std::find_if(cmArrayBegin(C_STANDARDS), cmArrayEnd(C_STANDARDS), - cmStrCmp(existingCStandard)) == cmArrayEnd(C_STANDARDS)) { + if (std::find_if(cm::cbegin(C_STANDARDS), cm::cend(C_STANDARDS), + cmStrCmp(existingCStandard)) == cm::cend(C_STANDARDS)) { std::ostringstream e; e << "The C_STANDARD property on target \"" << target->GetName() << "\" contained an invalid value: \"" << existingCStandard << "\"."; @@ -4537,26 +4568,26 @@ bool cmMakefile::AddRequiredTargetCFeature(cmTarget* target, } } const char* const* existingCIt = existingCStandard - ? std::find_if(cmArrayBegin(C_STANDARDS), cmArrayEnd(C_STANDARDS), + ? std::find_if(cm::cbegin(C_STANDARDS), cm::cend(C_STANDARDS), cmStrCmp(existingCStandard)) - : cmArrayEnd(C_STANDARDS); + : cm::cend(C_STANDARDS); bool setC90 = needC90 && !existingCStandard; bool setC99 = needC99 && !existingCStandard; bool setC11 = needC11 && !existingCStandard; if (needC11 && existingCStandard && - existingCIt < std::find_if(cmArrayBegin(C_STANDARDS), - cmArrayEnd(C_STANDARDS), cmStrCmp("11"))) { + existingCIt < std::find_if(cm::cbegin(C_STANDARDS), + cm::cend(C_STANDARDS), cmStrCmp("11"))) { setC11 = true; } else if (needC99 && existingCStandard && - existingCIt < std::find_if(cmArrayBegin(C_STANDARDS), - cmArrayEnd(C_STANDARDS), + existingCIt < std::find_if(cm::cbegin(C_STANDARDS), + cm::cend(C_STANDARDS), cmStrCmp("99"))) { setC99 = true; } else if (needC90 && existingCStandard && - existingCIt < std::find_if(cmArrayBegin(C_STANDARDS), - cmArrayEnd(C_STANDARDS), + existingCIt < std::find_if(cm::cbegin(C_STANDARDS), + cm::cend(C_STANDARDS), cmStrCmp("90"))) { setC90 = true; } diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h index 0273f5b..5e7a361 100644 --- a/Source/cmMakefile.h +++ b/Source/cmMakefile.h @@ -665,6 +665,10 @@ public: { return this->InstallGenerators; } + const std::vector<cmInstallGenerator*>& GetInstallGenerators() const + { + return this->InstallGenerators; + } void AddTestGenerator(cmTestGenerator* g) { @@ -737,6 +741,9 @@ public: /** Set whether or not to report a CMP0000 violation. */ void SetCheckCMP0000(bool b) { this->CheckCMP0000 = b; } + bool CheckCMP0037(std::string const& targetName, + cmStateEnums::TargetType targetType) const; + cmStringRange GetIncludeDirectoriesEntries() const; cmBacktraceRange GetIncludeDirectoriesBacktraces() const; cmStringRange GetCompileOptionsEntries() const; diff --git a/Source/cmPolicies.h b/Source/cmPolicies.h index 6c33e2b..f614dca 100644 --- a/Source/cmPolicies.h +++ b/Source/cmPolicies.h @@ -225,6 +225,7 @@ class cmMakefile; F(CMP0021) \ F(CMP0022) \ F(CMP0027) \ + F(CMP0037) \ F(CMP0038) \ F(CMP0041) \ F(CMP0042) \ diff --git a/Source/cmQtAutoGen.cxx b/Source/cmQtAutoGen.cxx index 5e89978..9dc77ac 100644 --- a/Source/cmQtAutoGen.cxx +++ b/Source/cmQtAutoGen.cxx @@ -9,6 +9,7 @@ #include "cmsys/RegularExpression.hxx" #include <algorithm> +#include <iterator> #include <sstream> #include <stddef.h> @@ -301,8 +302,7 @@ std::string cmQtAutoGen::Quoted(std::string const& text) "\r", "\\r", "\t", "\\t", "\v", "\\v" }; std::string res = text; - for (const char* const* it = cmArrayBegin(rep); it != cmArrayEnd(rep); - it += 2) { + for (const char* const* it = cm::cbegin(rep); it != cm::cend(rep); it += 2) { cmSystemTools::ReplaceString(res, *it, *(it + 1)); } res = '"' + res; diff --git a/Source/cmServerDictionary.h b/Source/cmServerDictionary.h index 405ff6b..03f1cc1 100644 --- a/Source/cmServerDictionary.h +++ b/Source/cmServerDictionary.h @@ -88,6 +88,8 @@ static const std::string kWARN_UNUSED_CLI_KEY = "warnUnusedCli"; static const std::string kWARN_UNUSED_KEY = "warnUnused"; static const std::string kWATCHED_DIRECTORIES_KEY = "watchedDirectories"; static const std::string kWATCHED_FILES_KEY = "watchedFiles"; +static const std::string kHAS_INSTALL_RULE = "hasInstallRule"; +static const std::string kINSTALL_PATHS = "installPaths"; static const std::string kTARGET_CROSS_REFERENCES_KEY = "crossReferences"; static const std::string kLINE_NUMBER_KEY = "line"; diff --git a/Source/cmServerProtocol.cxx b/Source/cmServerProtocol.cxx index e835b7a..fc06fed 100644 --- a/Source/cmServerProtocol.cxx +++ b/Source/cmServerProtocol.cxx @@ -8,6 +8,8 @@ #include "cmGeneratorExpression.h" #include "cmGeneratorTarget.h" #include "cmGlobalGenerator.h" +#include "cmInstallGenerator.h" +#include "cmInstallTargetGenerator.h" #include "cmLinkLineComputer.h" #include "cmListFileCache.h" #include "cmLocalGenerator.h" @@ -30,6 +32,7 @@ #include <functional> #include <limits> #include <map> +#include <memory> #include <set> #include <string> #include <unordered_map> @@ -252,7 +255,7 @@ bool cmServerProtocol::DoActivate(const cmServerRequest& /*request*/, std::pair<int, int> cmServerProtocol1::ProtocolVersion() const { - return std::make_pair(1, 1); + return std::make_pair(1, 2); } static void setErrorMessage(std::string* errorMessage, const std::string& text) @@ -797,6 +800,34 @@ static Json::Value DumpTarget(cmGeneratorTarget* target, result[kFULL_NAME_KEY] = target->GetFullName(config); + if (target->Target->GetHaveInstallRule()) { + result[kHAS_INSTALL_RULE] = true; + + Json::Value installPaths = Json::arrayValue; + auto targetGenerators = target->Makefile->GetInstallGenerators(); + for (auto installGenerator : targetGenerators) { + auto installTargetGenerator = + dynamic_cast<cmInstallTargetGenerator*>(installGenerator); + if (installTargetGenerator != nullptr && + installTargetGenerator->GetTarget()->Target == target->Target) { + auto dest = installTargetGenerator->GetDestination(config); + + std::string installPath; + if (!dest.empty() && cmSystemTools::FileIsFullPath(dest.c_str())) { + installPath = dest; + } else { + std::string installPrefix = + target->Makefile->GetSafeDefinition("CMAKE_INSTALL_PREFIX"); + installPath = installPrefix + '/' + dest; + } + + installPaths.append(installPath); + } + } + + result[kINSTALL_PATHS] = installPaths; + } + Json::Value crossRefs = Json::objectValue; crossRefs[kBACKTRACE_KEY] = DumpBacktrace(target->Target->GetBacktrace()); @@ -933,6 +964,7 @@ static Json::Value DumpProjectList(const cmake* cm, std::string const& config) // Project structure information: const cmMakefile* mf = lg->GetMakefile(); + pObj[kHAS_INSTALL_RULE] = mf->GetInstallGenerators().empty() == false; pObj[kSOURCE_DIRECTORY_KEY] = mf->GetCurrentSourceDirectory(); pObj[kBUILD_DIRECTORY_KEY] = mf->GetCurrentBinaryDirectory(); pObj[kTARGETS_KEY] = DumpTargetsList(projectIt.second, config); diff --git a/Source/cmSetCommand.cxx b/Source/cmSetCommand.cxx index b32cda3..985aac8 100644 --- a/Source/cmSetCommand.cxx +++ b/Source/cmSetCommand.cxx @@ -2,8 +2,6 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmSetCommand.h" -#include <string.h> - #include "cmAlgorithms.h" #include "cmMakefile.h" #include "cmState.h" @@ -22,19 +20,15 @@ bool cmSetCommand::InitialPass(std::vector<std::string> const& args, } // watch for ENV signatures - const char* variable = args[0].c_str(); // VAR is always first - if (cmHasLiteralPrefix(variable, "ENV{") && strlen(variable) > 5) { + auto const& variable = args[0]; // VAR is always first + if (cmHasLiteralPrefix(variable, "ENV{") && variable.size() > 5) { // what is the variable name - char* varName = new char[strlen(variable)]; - strncpy(varName, variable + 4, strlen(variable) - 5); - varName[strlen(variable) - 5] = '\0'; - std::string putEnvArg = varName; - putEnvArg += "="; + auto const& varName = variable.substr(4, variable.size() - 5); + std::string putEnvArg = varName + "="; // what is the current value if any std::string currValue; const bool currValueSet = cmSystemTools::GetEnv(varName, currValue); - delete[] varName; // will it be set to something, then set it if (args.size() > 1 && !args[1].empty()) { diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx index 63c1452..5d1f5f7 100644 --- a/Source/cmSystemTools.cxx +++ b/Source/cmSystemTools.cxx @@ -50,6 +50,8 @@ #include <windows.h> // include wincrypt.h after windows.h #include <wincrypt.h> + +#include "cm_uv.h" #else #include <sys/time.h> #include <unistd.h> @@ -943,6 +945,39 @@ cmSystemTools::WindowsFileRetry cmSystemTools::GetWindowsFileRetry() } return retry; } + +std::string cmSystemTools::GetRealPath(const std::string& path, + std::string* errorMessage) +{ + // uv_fs_realpath uses Windows Vista API so fallback to kwsys if not found + std::string resolved_path; + uv_fs_t req; + int err = uv_fs_realpath(NULL, &req, path.c_str(), NULL); + if (!err) { + resolved_path = std::string((char*)req.ptr); + cmSystemTools::ConvertToUnixSlashes(resolved_path); + // Normalize to upper-case drive letter as GetActualCaseForPath does. + if (resolved_path.size() > 1 && resolved_path[1] == ':') { + resolved_path[0] = toupper(resolved_path[0]); + } + } else if (err == UV_ENOSYS) { + resolved_path = cmsys::SystemTools::GetRealPath(path, errorMessage); + } else if (errorMessage) { + LPSTR message = NULL; + DWORD size = FormatMessageA( + FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&message, 0, + NULL); + *errorMessage = std::string(message, size); + LocalFree(message); + + resolved_path = ""; + } else { + resolved_path = path; + } + return resolved_path; +} #endif bool cmSystemTools::RenameFile(const char* oldname, const char* newname) diff --git a/Source/cmSystemTools.h b/Source/cmSystemTools.h index e7082e6..2646df9 100644 --- a/Source/cmSystemTools.h +++ b/Source/cmSystemTools.h @@ -497,6 +497,10 @@ public: unsigned int Delay; }; static WindowsFileRetry GetWindowsFileRetry(); + + /** Get the real path for a given path, removing all symlinks. */ + static std::string GetRealPath(const std::string& path, + std::string* errorMessage = 0); #endif private: static bool s_ForceUnixPaths; diff --git a/Source/cmTargetCompileDefinitionsCommand.cxx b/Source/cmTargetCompileDefinitionsCommand.cxx index d159d41..bd4121d 100644 --- a/Source/cmTargetCompileDefinitionsCommand.cxx +++ b/Source/cmTargetCompileDefinitionsCommand.cxx @@ -17,15 +17,6 @@ bool cmTargetCompileDefinitionsCommand::InitialPass( return this->HandleArguments(args, "COMPILE_DEFINITIONS"); } -void cmTargetCompileDefinitionsCommand::HandleImportedTarget( - const std::string& tgt) -{ - std::ostringstream e; - e << "Cannot specify compile definitions for imported target \"" << tgt - << "\"."; - this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); -} - void cmTargetCompileDefinitionsCommand::HandleMissingTarget( const std::string& name) { @@ -56,5 +47,5 @@ bool cmTargetCompileDefinitionsCommand::HandleDirectContent( cmTarget* tgt, const std::vector<std::string>& content, bool, bool) { tgt->AppendProperty("COMPILE_DEFINITIONS", this->Join(content).c_str()); - return true; + return true; // Successfully handled. } diff --git a/Source/cmTargetCompileDefinitionsCommand.h b/Source/cmTargetCompileDefinitionsCommand.h index f910452..d41483a 100644 --- a/Source/cmTargetCompileDefinitionsCommand.h +++ b/Source/cmTargetCompileDefinitionsCommand.h @@ -30,7 +30,6 @@ public: cmExecutionStatus& status) override; private: - void HandleImportedTarget(const std::string& tgt) override; void HandleMissingTarget(const std::string& name) override; bool HandleDirectContent(cmTarget* tgt, diff --git a/Source/cmTargetCompileFeaturesCommand.cxx b/Source/cmTargetCompileFeaturesCommand.cxx index 722bbe5..f58e404 100644 --- a/Source/cmTargetCompileFeaturesCommand.cxx +++ b/Source/cmTargetCompileFeaturesCommand.cxx @@ -17,15 +17,6 @@ bool cmTargetCompileFeaturesCommand::InitialPass( return this->HandleArguments(args, "COMPILE_FEATURES", NO_FLAGS); } -void cmTargetCompileFeaturesCommand::HandleImportedTarget( - const std::string& tgt) -{ - std::ostringstream e; - e << "Cannot specify compile features for imported target \"" << tgt - << "\"."; - this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); -} - void cmTargetCompileFeaturesCommand::HandleMissingTarget( const std::string& name) { @@ -49,8 +40,8 @@ bool cmTargetCompileFeaturesCommand::HandleDirectContent( std::string error; if (!this->Makefile->AddRequiredTargetFeature(tgt, it, &error)) { this->SetError(error); - return false; + return false; // Not (successfully) handled. } } - return true; + return true; // Successfully handled. } diff --git a/Source/cmTargetCompileFeaturesCommand.h b/Source/cmTargetCompileFeaturesCommand.h index 444d260..45240a5 100644 --- a/Source/cmTargetCompileFeaturesCommand.h +++ b/Source/cmTargetCompileFeaturesCommand.h @@ -22,7 +22,6 @@ class cmTargetCompileFeaturesCommand : public cmTargetPropCommandBase cmExecutionStatus& status) override; private: - void HandleImportedTarget(const std::string& tgt) override; void HandleMissingTarget(const std::string& name) override; bool HandleDirectContent(cmTarget* tgt, diff --git a/Source/cmTargetCompileOptionsCommand.cxx b/Source/cmTargetCompileOptionsCommand.cxx index 1b4056d..4df3630 100644 --- a/Source/cmTargetCompileOptionsCommand.cxx +++ b/Source/cmTargetCompileOptionsCommand.cxx @@ -18,21 +18,12 @@ bool cmTargetCompileOptionsCommand::InitialPass( return this->HandleArguments(args, "COMPILE_OPTIONS", PROCESS_BEFORE); } -void cmTargetCompileOptionsCommand::HandleImportedTarget( - const std::string& tgt) -{ - std::ostringstream e; - e << "Cannot specify compile options for imported target \"" << tgt << "\"."; - this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); -} - void cmTargetCompileOptionsCommand::HandleMissingTarget( const std::string& name) { std::ostringstream e; e << "Cannot specify compile options for target \"" << name - << "\" " - "which is not built by this project."; + << "\" which is not built by this project."; this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); } @@ -47,5 +38,5 @@ bool cmTargetCompileOptionsCommand::HandleDirectContent( { cmListFileBacktrace lfbt = this->Makefile->GetBacktrace(); tgt->InsertCompileOption(this->Join(content), lfbt); - return true; + return true; // Successfully handled. } diff --git a/Source/cmTargetCompileOptionsCommand.h b/Source/cmTargetCompileOptionsCommand.h index 3fab238..6fb151a 100644 --- a/Source/cmTargetCompileOptionsCommand.h +++ b/Source/cmTargetCompileOptionsCommand.h @@ -30,7 +30,6 @@ public: cmExecutionStatus& status) override; private: - void HandleImportedTarget(const std::string& tgt) override; void HandleMissingTarget(const std::string& name) override; bool HandleDirectContent(cmTarget* tgt, diff --git a/Source/cmTargetIncludeDirectoriesCommand.cxx b/Source/cmTargetIncludeDirectoriesCommand.cxx index 4646c7e..dcec830 100644 --- a/Source/cmTargetIncludeDirectoriesCommand.cxx +++ b/Source/cmTargetIncludeDirectoriesCommand.cxx @@ -21,22 +21,12 @@ bool cmTargetIncludeDirectoriesCommand::InitialPass( ArgumentFlags(PROCESS_BEFORE | PROCESS_SYSTEM)); } -void cmTargetIncludeDirectoriesCommand::HandleImportedTarget( - const std::string& tgt) -{ - std::ostringstream e; - e << "Cannot specify include directories for imported target \"" << tgt - << "\"."; - this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); -} - void cmTargetIncludeDirectoriesCommand::HandleMissingTarget( const std::string& name) { std::ostringstream e; e << "Cannot specify include directories for target \"" << name - << "\" " - "which is not built by this project."; + << "\" which is not built by this project."; this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); } @@ -79,7 +69,7 @@ bool cmTargetIncludeDirectoriesCommand::HandleDirectContent( } tgt->AddSystemIncludeDirectories(sdirs); } - return true; + return true; // Successfully handled. } void cmTargetIncludeDirectoriesCommand::HandleInterfaceContent( diff --git a/Source/cmTargetIncludeDirectoriesCommand.h b/Source/cmTargetIncludeDirectoriesCommand.h index 27a2f43..57bf8fc 100644 --- a/Source/cmTargetIncludeDirectoriesCommand.h +++ b/Source/cmTargetIncludeDirectoriesCommand.h @@ -30,7 +30,6 @@ public: cmExecutionStatus& status) override; private: - void HandleImportedTarget(const std::string& tgt) override; void HandleMissingTarget(const std::string& name) override; bool HandleDirectContent(cmTarget* tgt, diff --git a/Source/cmTargetLinkLibrariesCommand.cxx b/Source/cmTargetLinkLibrariesCommand.cxx index dda0464..37bcb70 100644 --- a/Source/cmTargetLinkLibrariesCommand.cxx +++ b/Source/cmTargetLinkLibrariesCommand.cxx @@ -40,6 +40,16 @@ bool cmTargetLinkLibrariesCommand::InitialPass( this->Makefile->GetCMakeInstance()->GetGlobalGenerator()->FindTarget( args[0]); if (!this->Target) { + const std::vector<cmTarget*>& importedTargets = + this->Makefile->GetOwnedImportedTargets(); + for (cmTarget* importedTarget : importedTargets) { + if (importedTarget->GetName() == args[0]) { + this->Target = importedTarget; + break; + } + } + } + if (!this->Target) { cmake::MessageType t = cmake::FATAL_ERROR; // fail by default std::ostringstream e; e << "Cannot specify link libraries for target \"" << args[0] << "\" " @@ -228,7 +238,7 @@ bool cmTargetLinkLibrariesCommand::InitialPass( } else { // Lookup old-style cache entry if type is unspecified. So if you // do a target_link_libraries(foo optimized bar) it will stay optimized - // and not use the lookup. As there maybe the case where someone has + // and not use the lookup. As there may be the case where someone has // specifed that a library is both debug and optimized. (this check is // only there for backwards compatibility when mixing projects built // with old versions of CMake and new) @@ -299,6 +309,14 @@ bool cmTargetLinkLibrariesCommand::HandleLibrary(const std::string& lib, "target_link_libraries"); return false; } + if (this->Target->IsImported() && + this->CurrentProcessingState != ProcessingKeywordLinkInterface) { + this->Makefile->IssueMessage( + cmake::FATAL_ERROR, + "IMPORTED library can only be used with the INTERFACE keyword of " + "target_link_libraries"); + return false; + } cmTarget::TLLSignature sig = (this->CurrentProcessingState == ProcessingPlainPrivateInterface || @@ -355,6 +373,16 @@ bool cmTargetLinkLibrariesCommand::HandleLibrary(const std::string& lib, cmTarget* t = this->Makefile->FindLocalNonAliasTarget(this->Target->GetName()); if (!t) { + const std::vector<cmTarget*>& importedTargets = + this->Makefile->GetOwnedImportedTargets(); + for (cmTarget* importedTarget : importedTargets) { + if (importedTarget->GetName() == this->Target->GetName()) { + t = importedTarget; + break; + } + } + } + if (!t) { std::ostringstream e; e << "Attempt to add link library \"" << lib << "\" to target \"" << this->Target->GetName() diff --git a/Source/cmTargetPropCommandBase.cxx b/Source/cmTargetPropCommandBase.cxx index 45fe430..9a8fd96 100644 --- a/Source/cmTargetPropCommandBase.cxx +++ b/Source/cmTargetPropCommandBase.cxx @@ -17,11 +17,11 @@ bool cmTargetPropCommandBase::HandleArguments( return false; } - // Lookup the target for which libraries are specified. if (this->Makefile->IsAlias(args[0])) { this->SetError("can not be used on an ALIAS target."); return false; } + // Lookup the target for which property-values are specified. this->Target = this->Makefile->GetCMakeInstance()->GetGlobalGenerator()->FindTarget( args[0]); @@ -84,16 +84,13 @@ bool cmTargetPropCommandBase::ProcessContentArgs( this->SetError("called with invalid arguments"); return false; } - - if (this->Target->IsImported()) { - this->HandleImportedTarget(args[0]); - return false; - } - if (this->Target->GetType() == cmStateEnums::INTERFACE_LIBRARY && scope != "INTERFACE") { - this->SetError("may only be set INTERFACE properties on INTERFACE " - "targets"); + this->SetError("may only set INTERFACE properties on INTERFACE targets"); + return false; + } + if (this->Target->IsImported() && scope != "INTERFACE") { + this->SetError("may only set INTERFACE properties on IMPORTED targets"); return false; } diff --git a/Source/cmTargetPropCommandBase.h b/Source/cmTargetPropCommandBase.h index 46a2f6b..3c736fc 100644 --- a/Source/cmTargetPropCommandBase.h +++ b/Source/cmTargetPropCommandBase.h @@ -35,7 +35,6 @@ protected: bool prepend, bool system); private: - virtual void HandleImportedTarget(const std::string& tgt) = 0; virtual void HandleMissingTarget(const std::string& name) = 0; virtual bool HandleDirectContent(cmTarget* tgt, diff --git a/Source/cmTargetSourcesCommand.cxx b/Source/cmTargetSourcesCommand.cxx index 058659a..3dd3748 100644 --- a/Source/cmTargetSourcesCommand.cxx +++ b/Source/cmTargetSourcesCommand.cxx @@ -17,13 +17,6 @@ bool cmTargetSourcesCommand::InitialPass(std::vector<std::string> const& args, return this->HandleArguments(args, "SOURCES"); } -void cmTargetSourcesCommand::HandleImportedTarget(const std::string& tgt) -{ - std::ostringstream e; - e << "Cannot specify sources for imported target \"" << tgt << "\"."; - this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); -} - void cmTargetSourcesCommand::HandleMissingTarget(const std::string& name) { std::ostringstream e; @@ -43,5 +36,5 @@ bool cmTargetSourcesCommand::HandleDirectContent( cmTarget* tgt, const std::vector<std::string>& content, bool, bool) { tgt->AppendProperty("SOURCES", this->Join(content).c_str()); - return true; + return true; // Successfully handled. } diff --git a/Source/cmTargetSourcesCommand.h b/Source/cmTargetSourcesCommand.h index 0639e98..ea8776a 100644 --- a/Source/cmTargetSourcesCommand.h +++ b/Source/cmTargetSourcesCommand.h @@ -30,7 +30,6 @@ public: cmExecutionStatus& status) override; private: - void HandleImportedTarget(const std::string& tgt) override; void HandleMissingTarget(const std::string& name) override; bool HandleDirectContent(cmTarget* tgt, diff --git a/Source/cmTimestamp.cxx b/Source/cmTimestamp.cxx index 9fb79d9..e747adb 100644 --- a/Source/cmTimestamp.cxx +++ b/Source/cmTimestamp.cxx @@ -33,11 +33,13 @@ std::string cmTimestamp::FileModificationTime(const char* path, const std::string& formatString, bool utcFlag) { - if (!cmsys::SystemTools::FileExists(path)) { + std::string real_path = cmSystemTools::GetRealPath(path); + + if (!cmsys::SystemTools::FileExists(real_path)) { return std::string(); } - time_t mtime = cmsys::SystemTools::ModifiedTime(path); + time_t mtime = cmsys::SystemTools::ModifiedTime(real_path); return CreateTimestampFromTimeT(mtime, formatString, utcFlag); } diff --git a/Source/cmTryRunCommand.cxx b/Source/cmTryRunCommand.cxx index dcaa493..932b976 100644 --- a/Source/cmTryRunCommand.cxx +++ b/Source/cmTryRunCommand.cxx @@ -4,7 +4,6 @@ #include "cmsys/FStream.hxx" #include <stdio.h> -#include <string.h> #include "cmMakefile.h" #include "cmState.h" @@ -191,13 +190,15 @@ void cmTryRunCommand::RunExecutable(const std::string& runArgs, finalCommand.c_str(), out, out, &retVal, nullptr, cmSystemTools::OUTPUT_NONE, timeout); // set the run var - char retChar[1000]; + char retChar[16]; + const char* retStr; if (worked) { sprintf(retChar, "%i", retVal); + retStr = retChar; } else { - strcpy(retChar, "FAILED_TO_RUN"); + retStr = "FAILED_TO_RUN"; } - this->Makefile->AddCacheDefinition(this->RunResultVariable, retChar, + this->Makefile->AddCacheDefinition(this->RunResultVariable, retStr, "Result of TRY_RUN", cmStateEnums::INTERNAL); } diff --git a/Source/cmUnsetCommand.cxx b/Source/cmUnsetCommand.cxx index 18bbdd7..cfaa1fd2 100644 --- a/Source/cmUnsetCommand.cxx +++ b/Source/cmUnsetCommand.cxx @@ -2,8 +2,6 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmUnsetCommand.h" -#include <string.h> - #include "cmAlgorithms.h" #include "cmMakefile.h" #include "cmSystemTools.h" @@ -19,19 +17,16 @@ bool cmUnsetCommand::InitialPass(std::vector<std::string> const& args, return false; } - const char* variable = args[0].c_str(); + auto const& variable = args[0]; // unset(ENV{VAR}) - if (cmHasLiteralPrefix(variable, "ENV{") && strlen(variable) > 5) { + if (cmHasLiteralPrefix(variable, "ENV{") && variable.size() > 5) { // what is the variable name - char* envVarName = new char[strlen(variable)]; - strncpy(envVarName, variable + 4, strlen(variable) - 5); - envVarName[strlen(variable) - 5] = '\0'; + auto const& envVarName = variable.substr(4, variable.size() - 5); #ifdef CMAKE_BUILD_WITH_CMAKE - cmSystemTools::UnsetEnv(envVarName); + cmSystemTools::UnsetEnv(envVarName.c_str()); #endif - delete[] envVarName; return true; } // unset(VAR) diff --git a/Source/cmVS141CLFlagTable.h b/Source/cmVS141CLFlagTable.h index c780d46..7d3e356 100644 --- a/Source/cmVS141CLFlagTable.h +++ b/Source/cmVS141CLFlagTable.h @@ -1,6 +1,10 @@ static cmVS7FlagTable cmVS141CLFlagTable[] = { // Enum Properties + { "DiagnosticsFormat", "diagnostics:classic", "Classic", "Classic", 0 }, + { "DiagnosticsFormat", "diagnostics:column", "Column", "Column", 0 }, + { "DiagnosticsFormat", "diagnostics:caret", "Caret", "Caret", 0 }, + { "DebugInformationFormat", "", "None", "None", 0 }, { "DebugInformationFormat", "Z7", "C7 compatible", "OldStyle", 0 }, { "DebugInformationFormat", "Zi", "Program Database", "ProgramDatabase", 0 }, diff --git a/Source/cmVSSetupHelper.cxx b/Source/cmVSSetupHelper.cxx index ea13649..c2f8deb 100644 --- a/Source/cmVSSetupHelper.cxx +++ b/Source/cmVSSetupHelper.cxx @@ -80,6 +80,14 @@ cmVSSetupAPIHelper::~cmVSSetupAPIHelper() CoUninitialize(); } +bool cmVSSetupAPIHelper::SetVSInstance(std::string const& vsInstallLocation) +{ + this->SpecifiedVSInstallLocation = vsInstallLocation; + cmSystemTools::ConvertToUnixSlashes(this->SpecifiedVSInstallLocation); + chosenInstanceInfo = VSInstanceInfo(); + return this->EnumerateAndChooseVSInstance(); +} + bool cmVSSetupAPIHelper::IsVS2017Installed() { return this->EnumerateAndChooseVSInstance(); @@ -265,13 +273,6 @@ bool cmVSSetupAPIHelper::EnumerateAndChooseVSInstance() if (cmSystemTools::GetEnv("VS150COMNTOOLS", envVSCommonToolsDir)) { cmSystemTools::ConvertToUnixSlashes(envVSCommonToolsDir); } - // FIXME: If the environment variable value changes between runs - // of CMake within a given build tree the results are not defined. - // Instead we should save a CMAKE_GENERATOR_INSTANCE value in the cache - // (similar to CMAKE_GENERATOR_TOOLSET) to hold it persistently. - // Unfortunately doing so will require refactoring elsewhere in - // order to make sure the value is available in time to create - // the generator. std::vector<VSInstanceInfo> vecVSInstances; SmartCOMPtr<IEnumSetupInstances> enumInstances = NULL; @@ -296,16 +297,29 @@ bool cmVSSetupAPIHelper::EnumerateAndChooseVSInstance() instance = instance2 = NULL; if (isInstalled) { - if (!envVSCommonToolsDir.empty()) { + if (!this->SpecifiedVSInstallLocation.empty()) { + // We are looking for a specific instance. std::string currentVSLocation = instanceInfo.GetInstallLocation(); - currentVSLocation += "/Common7/Tools"; if (cmSystemTools::ComparePath(currentVSLocation, - envVSCommonToolsDir)) { + this->SpecifiedVSInstallLocation)) { chosenInstanceInfo = instanceInfo; return true; } + } else { + // We are not looking for a specific instance. + // If we've been given a hint then use it. + if (!envVSCommonToolsDir.empty()) { + std::string currentVSLocation = instanceInfo.GetInstallLocation(); + currentVSLocation += "/Common7/Tools"; + if (cmSystemTools::ComparePath(currentVSLocation, + envVSCommonToolsDir)) { + chosenInstanceInfo = instanceInfo; + return true; + } + } + // Otherwise, add this to the list of candidates. + vecVSInstances.push_back(instanceInfo); } - vecVSInstances.push_back(instanceInfo); } } diff --git a/Source/cmVSSetupHelper.h b/Source/cmVSSetupHelper.h index 74a7ec0..c07cfaf 100644 --- a/Source/cmVSSetupHelper.h +++ b/Source/cmVSSetupHelper.h @@ -126,6 +126,8 @@ public: cmVSSetupAPIHelper(); ~cmVSSetupAPIHelper(); + bool SetVSInstance(std::string const& vsInstallLocation); + bool IsVS2017Installed(); bool GetVSInstanceInfo(std::string& vsInstallLocation); bool IsWin10SDKInstalled(); @@ -150,6 +152,8 @@ private: HRESULT comInitialized; // current best instance of VS selected VSInstanceInfo chosenInstanceInfo; + + std::string SpecifiedVSInstallLocation; }; #endif diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx index c61902a..1aadf67 100644 --- a/Source/cmVisualStudio10TargetGenerator.cxx +++ b/Source/cmVisualStudio10TargetGenerator.cxx @@ -15,6 +15,7 @@ #include "cmVisualStudioGeneratorOptions.h" #include "windows.h" +#include <iterator> #include <memory> // IWYU pragma: keep static std::string cmVS10EscapeXML(std::string arg) @@ -1174,6 +1175,15 @@ void cmVisualStudio10TargetGenerator::WriteCustomCommands() si != customCommands.end(); ++si) { this->WriteCustomCommand(*si); } + + // Add CMakeLists.txt file with rule to re-run CMake for user convenience. + if (this->GeneratorTarget->GetType() != cmStateEnums::GLOBAL_TARGET && + this->GeneratorTarget->GetName() != CMAKE_CHECK_BUILD_SYSTEM_TARGET) { + if (cmSourceFile const* sf = + this->LocalGenerator->CreateVCProjBuildRule()) { + this->WriteCustomCommand(sf); + } + } } void cmVisualStudio10TargetGenerator::WriteCustomCommand( @@ -1592,6 +1602,8 @@ void cmVisualStudio10TargetGenerator::WriteExtraSource(cmSourceFile const* sf) std::string shaderEntryPoint; std::string shaderModel; std::string shaderAdditionalFlags; + std::string shaderDisableOptimizations; + std::string shaderEnableDebug; std::string outputHeaderFile; std::string variableName; std::string settingsGenerator; @@ -1658,6 +1670,16 @@ void cmVisualStudio10TargetGenerator::WriteExtraSource(cmSourceFile const* sf) shaderAdditionalFlags = saf; toolHasSettings = true; } + // Figure out if debug information should be generated + if (const char* sed = sf->GetProperty("VS_SHADER_ENABLE_DEBUG")) { + shaderEnableDebug = cmSystemTools::IsOn(sed) ? "true" : "false"; + toolHasSettings = true; + } + // Figure out if optimizations should be disabled + if (const char* sdo = sf->GetProperty("VS_SHADER_DISABLE_OPTIMIZATIONS")) { + shaderDisableOptimizations = cmSystemTools::IsOn(sdo) ? "true" : "false"; + toolHasSettings = true; + } } else if (ext == "jpg" || ext == "png") { tool = "Image"; } else if (ext == "resw") { @@ -1800,6 +1822,16 @@ void cmVisualStudio10TargetGenerator::WriteExtraSource(cmSourceFile const* sf) this->WriteString("</VariableName>\n", 0); } } + if (!shaderEnableDebug.empty()) { + this->WriteString("<EnableDebuggingInformation>", 3); + (*this->BuildFileStream) << cmVS10EscapeXML(shaderEnableDebug) + << "</EnableDebuggingInformation>\n"; + } + if (!shaderDisableOptimizations.empty()) { + this->WriteString("<DisableOptimizations>", 3); + (*this->BuildFileStream) << cmVS10EscapeXML(shaderDisableOptimizations) + << "</DisableOptimizations>\n"; + } if (!shaderAdditionalFlags.empty()) { this->WriteString("<AdditionalOptions>", 3); (*this->BuildFileStream) << cmVS10EscapeXML(shaderAdditionalFlags) @@ -2359,14 +2391,14 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions( // Choose a language whose flags to use for ClCompile. static const char* clLangs[] = { "CXX", "C", "Fortran", "CSharp" }; std::string langForClCompile; - if (std::find(cmArrayBegin(clLangs), cmArrayEnd(clLangs), linkLanguage) != - cmArrayEnd(clLangs)) { + if (std::find(cm::cbegin(clLangs), cm::cend(clLangs), linkLanguage) != + cm::cend(clLangs)) { langForClCompile = linkLanguage; } else { std::set<std::string> languages; this->GeneratorTarget->GetLanguages(languages, configName); - for (const char* const* l = cmArrayBegin(clLangs); - l != cmArrayEnd(clLangs); ++l) { + for (const char* const* l = cm::cbegin(clLangs); l != cm::cend(clLangs); + ++l) { if (languages.find(*l) != languages.end()) { langForClCompile = *l; break; diff --git a/Source/cm_codecvt.cxx b/Source/cm_codecvt.cxx index cf55741..6705851 100644 --- a/Source/cm_codecvt.cxx +++ b/Source/cm_codecvt.cxx @@ -38,12 +38,14 @@ codecvt::codecvt(Encoding e) } } -codecvt::~codecvt(){}; +codecvt::~codecvt() +{ +} bool codecvt::do_always_noconv() const throw() { return m_noconv; -}; +} std::codecvt_base::result codecvt::do_out(mbstate_t& state, const char* from, const char* from_end, @@ -122,7 +124,7 @@ std::codecvt_base::result codecvt::do_out(mbstate_t& state, const char* from, static_cast<void>(to_next); return std::codecvt_base::noconv; #endif -}; +} std::codecvt_base::result codecvt::do_unshift(mbstate_t& state, char* to, char* to_end, @@ -143,7 +145,7 @@ std::codecvt_base::result codecvt::do_unshift(mbstate_t& state, char* to, static_cast<void>(to_end); return std::codecvt_base::ok; #endif -}; +} #if defined(_WIN32) std::codecvt_base::result codecvt::Decode(mbstate_t& state, int size, @@ -235,9 +237,9 @@ void codecvt::BufferPartial(mbstate_t& state, int size, int codecvt::do_max_length() const throw() { return 4; -}; +} int codecvt::do_encoding() const throw() { return 0; -}; +} diff --git a/Source/cmake.cxx b/Source/cmake.cxx index fd7151f..fde77a7 100644 --- a/Source/cmake.cxx +++ b/Source/cmake.cxx @@ -110,6 +110,7 @@ #include "cmsys/RegularExpression.hxx" #include <algorithm> #include <iostream> +#include <iterator> #include <memory> // IWYU pragma: keep #include <sstream> #include <stdio.h> @@ -1326,6 +1327,25 @@ int cmake::ActualConfigure() cmStateEnums::INTERNAL); } + if (const char* instance = + this->State->GetInitializedCacheValue("CMAKE_GENERATOR_INSTANCE")) { + if (!this->GeneratorInstance.empty() && + this->GeneratorInstance != instance) { + std::string message = "Error: generator instance: "; + message += this->GeneratorInstance; + message += "\nDoes not match the instance used previously: "; + message += instance; + message += "\nEither remove the CMakeCache.txt file and CMakeFiles " + "directory or choose a different binary directory."; + cmSystemTools::Error(message.c_str()); + return -2; + } + } else { + this->AddCacheEntry( + "CMAKE_GENERATOR_INSTANCE", this->GeneratorInstance.c_str(), + "Generator instance identifier.", cmStateEnums::INTERNAL); + } + if (const char* platformName = this->State->GetInitializedCacheValue("CMAKE_GENERATOR_PLATFORM")) { if (!this->GeneratorPlatform.empty() && @@ -1453,12 +1473,12 @@ void cmake::CreateDefaultGlobalGenerator() if (vsSetupAPIHelper.IsVS2017Installed()) { found = "Visual Studio 15 2017"; } else { - for (VSVersionedGenerator const* g = cmArrayBegin(vsGenerators); - found.empty() && g != cmArrayEnd(vsGenerators); ++g) { - for (const char* const* v = cmArrayBegin(vsVariants); - found.empty() && v != cmArrayEnd(vsVariants); ++v) { - for (const char* const* e = cmArrayBegin(vsEntries); - found.empty() && e != cmArrayEnd(vsEntries); ++e) { + for (VSVersionedGenerator const* g = cm::cbegin(vsGenerators); + found.empty() && g != cm::cend(vsGenerators); ++g) { + for (const char* const* v = cm::cbegin(vsVariants); + found.empty() && v != cm::cend(vsVariants); ++v) { + for (const char* const* e = cm::cbegin(vsEntries); + found.empty() && e != cm::cend(vsEntries); ++e) { std::string const reg = vsregBase + *v + g->MSVersion + *e; std::string dir; if (cmSystemTools::ReadRegistryValue(reg, dir, @@ -1716,8 +1736,8 @@ bool cmake::LoadCache(const std::string& path, bool internal, bool result = this->State->LoadCache(path, internal, excludes, includes); static const char* entries[] = { "CMAKE_CACHE_MAJOR_VERSION", "CMAKE_CACHE_MINOR_VERSION" }; - for (const char* const* nameIt = cmArrayBegin(entries); - nameIt != cmArrayEnd(entries); ++nameIt) { + for (const char* const* nameIt = cm::cbegin(entries); + nameIt != cm::cend(entries); ++nameIt) { this->UnwatchUnusedCli(*nameIt); } return result; @@ -1730,8 +1750,8 @@ bool cmake::SaveCache(const std::string& path) "CMAKE_CACHE_MINOR_VERSION", "CMAKE_CACHE_PATCH_VERSION", "CMAKE_CACHEFILE_DIR" }; - for (const char* const* nameIt = cmArrayBegin(entries); - nameIt != cmArrayEnd(entries); ++nameIt) { + for (const char* const* nameIt = cm::cbegin(entries); + nameIt != cm::cend(entries); ++nameIt) { this->UnwatchUnusedCli(*nameIt); } return result; @@ -2360,6 +2380,14 @@ int cmake::Build(const std::string& dir, const std::string& target, << "\"\n"; return 1; } + const char* cachedGeneratorInstance = + this->State->GetCacheEntryValue("CMAKE_GENERATOR_INSTANCE"); + if (cachedGeneratorInstance) { + cmMakefile mf(gen.get(), this->GetCurrentSnapshot()); + if (!gen->SetGeneratorInstance(cachedGeneratorInstance, &mf)) { + return 1; + } + } std::string output; std::string projName; const char* cachedProjectName = @@ -2425,6 +2453,49 @@ int cmake::Build(const std::string& dir, const std::string& target, nativeOptions); } +bool cmake::Open(const std::string& dir, bool dryRun) +{ + this->SetHomeDirectory(""); + this->SetHomeOutputDirectory(""); + if (!cmSystemTools::FileIsDirectory(dir)) { + std::cerr << "Error: " << dir << " is not a directory\n"; + return false; + } + + std::string cachePath = FindCacheFile(dir); + if (!this->LoadCache(cachePath)) { + std::cerr << "Error: could not load cache\n"; + return false; + } + const char* genName = this->State->GetCacheEntryValue("CMAKE_GENERATOR"); + if (!genName) { + std::cerr << "Error: could not find CMAKE_GENERATOR in Cache\n"; + return false; + } + const char* extraGenName = + this->State->GetInitializedCacheValue("CMAKE_EXTRA_GENERATOR"); + std::string fullName = + cmExternalMakefileProjectGenerator::CreateFullGeneratorName( + genName, extraGenName ? extraGenName : ""); + + std::unique_ptr<cmGlobalGenerator> gen( + this->CreateGlobalGenerator(fullName)); + if (!gen.get()) { + std::cerr << "Error: could create CMAKE_GENERATOR \"" << fullName + << "\"\n"; + return false; + } + + const char* cachedProjectName = + this->State->GetCacheEntryValue("CMAKE_PROJECT_NAME"); + if (!cachedProjectName) { + std::cerr << "Error: could not find CMAKE_PROJECT_NAME in Cache\n"; + return false; + } + + return gen->Open(dir, cachedProjectName, dryRun); +} + void cmake::WatchUnusedCli(const std::string& var) { #ifdef CMAKE_BUILD_WITH_CMAKE diff --git a/Source/cmake.h b/Source/cmake.h index b31b6f5..5c5a90d 100644 --- a/Source/cmake.h +++ b/Source/cmake.h @@ -203,6 +203,12 @@ public: ///! Get the names of the current registered generators void GetRegisteredGenerators(std::vector<GeneratorInfo>& generators) const; + ///! Set the name of the selected generator-specific instance. + void SetGeneratorInstance(std::string const& instance) + { + this->GeneratorInstance = instance; + } + ///! Set the name of the selected generator-specific platform. void SetGeneratorPlatform(std::string const& ts) { @@ -401,6 +407,9 @@ public: const std::string& config, const std::vector<std::string>& nativeOptions, bool clean); + ///! run the --open option + bool Open(const std::string& dir, bool dryRun); + void UnwatchUnusedCli(const std::string& var); void WatchUnusedCli(const std::string& var); @@ -428,6 +437,7 @@ protected: cmGlobalGenerator* GlobalGenerator; std::map<std::string, DiagLevel> DiagLevels; + std::string GeneratorInstance; std::string GeneratorPlatform; std::string GeneratorToolset; diff --git a/Source/cmakemain.cxx b/Source/cmakemain.cxx index a1dfc3e..59b908a 100644 --- a/Source/cmakemain.cxx +++ b/Source/cmakemain.cxx @@ -66,6 +66,7 @@ static const char* cmDocumentationOptions[][2] = { { "-E", "CMake command mode." }, { "-L[A][H]", "List non-advanced cached variables." }, { "--build <dir>", "Build a CMake-generated project binary tree." }, + { "--open <dir>", "Open generated project in the associated application." }, { "-N", "View mode only." }, { "-P <file>", "Process script mode." }, { "--find-package", "Run in pkg-config like mode." }, @@ -100,6 +101,7 @@ static int do_command(int ac, char const* const* av) int do_cmake(int ac, char const* const* av); static int do_build(int ac, char const* const* av); +static int do_open(int ac, char const* const* av); static cmMakefile* cmakemainGetMakefile(void* clientdata) { @@ -186,6 +188,9 @@ int main(int ac, char const* const* av) if (strcmp(av[1], "--build") == 0) { return do_build(ac, av); } + if (strcmp(av[1], "--open") == 0) { + return do_open(ac, av); + } if (strcmp(av[1], "-E") == 0) { return do_command(ac, av); } @@ -423,3 +428,41 @@ static int do_build(int ac, char const* const* av) return cm.Build(dir, target, config, nativeOptions, clean); #endif } + +static int do_open(int ac, char const* const* av) +{ +#ifndef CMAKE_BUILD_WITH_CMAKE + std::cerr << "This cmake does not support --open\n"; + return -1; +#else + std::string dir; + + enum Doing + { + DoingNone, + DoingDir, + }; + Doing doing = DoingDir; + for (int i = 2; i < ac; ++i) { + switch (doing) { + case DoingDir: + dir = cmSystemTools::CollapseFullPath(av[i]); + doing = DoingNone; + break; + default: + std::cerr << "Unknown argument " << av[i] << std::endl; + dir.clear(); + break; + } + } + if (dir.empty()) { + std::cerr << "Usage: cmake --open <dir>\n"; + return 1; + } + + cmake cm(cmake::RoleInternal); + cmSystemTools::SetMessageCallback(cmakemainMessageCallback, &cm); + cm.SetProgressCallback(cmakemainProgressCallback, &cm); + return cm.Open(dir, false) ? 0 : 1; +#endif +} diff --git a/Source/cmcmd.cxx b/Source/cmcmd.cxx index b4772a9..ef75b01 100644 --- a/Source/cmcmd.cxx +++ b/Source/cmcmd.cxx @@ -34,6 +34,7 @@ #include "cmsys/Terminal.h" #include <algorithm> #include <iostream> +#include <iterator> #include <memory> // IWYU pragma: keep #include <sstream> #include <stdio.h> @@ -371,8 +372,8 @@ int cmcmd::HandleCoCompileCommands(std::vector<std::string>& args) doing_options = false; } else if (doing_options) { bool optionFound = false; - for (CoCompiler const* cc = cmArrayBegin(CoCompilers); - cc != cmArrayEnd(CoCompilers); ++cc) { + for (CoCompiler const* cc = cm::cbegin(CoCompilers); + cc != cm::cend(CoCompilers); ++cc) { size_t optionLen = strlen(cc->Option); if (arg.compare(0, optionLen, cc->Option) == 0) { optionFound = true; @@ -402,8 +403,8 @@ int cmcmd::HandleCoCompileCommands(std::vector<std::string>& args) if (jobs.empty()) { std::cerr << "__run_co_compile missing command to run. " "Looking for one or more of the following:\n"; - for (CoCompiler const* cc = cmArrayBegin(CoCompilers); - cc != cmArrayEnd(CoCompilers); ++cc) { + for (CoCompiler const* cc = cm::cbegin(CoCompilers); + cc != cm::cend(CoCompilers); ++cc) { std::cerr << cc->Option << "\n"; } return 1; @@ -1024,8 +1025,8 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args) } else if (cmHasLiteralPrefix(arg, "--format=")) { format = arg.substr(9); bool isKnown = - std::find(cmArrayBegin(knownFormats), cmArrayEnd(knownFormats), - format) != cmArrayEnd(knownFormats); + std::find(cm::cbegin(knownFormats), cm::cend(knownFormats), + format) != cm::cend(knownFormats); if (!isKnown) { cmSystemTools::Error("Unknown -E tar --format= argument: ", diff --git a/Source/kwsys/CMakeLists.txt b/Source/kwsys/CMakeLists.txt index 21568bb..f36f9b6 100644 --- a/Source/kwsys/CMakeLists.txt +++ b/Source/kwsys/CMakeLists.txt @@ -445,8 +445,13 @@ KWSYS_PLATFORM_C_TEST(KWSYS_C_HAS_PTRDIFF_T "Checking whether C compiler has ptrdiff_t in stddef.h" DIRECT) KWSYS_PLATFORM_C_TEST(KWSYS_C_HAS_SSIZE_T "Checking whether C compiler has ssize_t in unistd.h" DIRECT) +IF(KWSYS_USE_Process) + KWSYS_PLATFORM_C_TEST(KWSYS_C_HAS_CLOCK_GETTIME_MONOTONIC + "Checking whether C compiler has clock_gettime" DIRECT) +ENDIF() + SET_SOURCE_FILES_PROPERTIES(ProcessUNIX.c System.c PROPERTIES - COMPILE_FLAGS "-DKWSYS_C_HAS_PTRDIFF_T=${KWSYS_C_HAS_PTRDIFF_T} -DKWSYS_C_HAS_SSIZE_T=${KWSYS_C_HAS_SSIZE_T}" + COMPILE_FLAGS "-DKWSYS_C_HAS_PTRDIFF_T=${KWSYS_C_HAS_PTRDIFF_T} -DKWSYS_C_HAS_SSIZE_T=${KWSYS_C_HAS_SSIZE_T} -DKWSYS_C_HAS_CLOCK_GETTIME_MONOTONIC=${KWSYS_C_HAS_CLOCK_GETTIME_MONOTONIC}" ) IF(DEFINED KWSYS_PROCESS_USE_SELECT) diff --git a/Source/kwsys/CommandLineArguments.cxx b/Source/kwsys/CommandLineArguments.cxx index 5613bd7..5792da9 100644 --- a/Source/kwsys/CommandLineArguments.cxx +++ b/Source/kwsys/CommandLineArguments.cxx @@ -529,10 +529,7 @@ void CommandLineArguments::GenerateHelp() } } - // Create format for that string - char format[80]; - sprintf(format, " %%-%us ", static_cast<unsigned int>(maxlen)); - + CommandLineArguments::Internal::String::size_type maxstrlen = maxlen; maxlen += 4; // For the space before and after the option // Print help for each option @@ -540,27 +537,24 @@ void CommandLineArguments::GenerateHelp() CommandLineArguments::Internal::SetOfStrings::iterator sit; for (sit = mpit->second.begin(); sit != mpit->second.end(); sit++) { str << std::endl; - char argument[100]; - sprintf(argument, "%s", sit->c_str()); + std::string argument = *sit; switch (this->Internals->Callbacks[*sit].ArgumentType) { case CommandLineArguments::NO_ARGUMENT: break; case CommandLineArguments::CONCAT_ARGUMENT: - strcat(argument, "opt"); + argument += "opt"; break; case CommandLineArguments::SPACE_ARGUMENT: - strcat(argument, " opt"); + argument += " opt"; break; case CommandLineArguments::EQUAL_ARGUMENT: - strcat(argument, "=opt"); + argument += "=opt"; break; case CommandLineArguments::MULTI_ARGUMENT: - strcat(argument, " opt opt ..."); + argument += " opt opt ..."; break; } - char buffer[80]; - sprintf(buffer, format, argument); - str << buffer; + str << " " << argument.substr(0, maxstrlen) << " "; } const char* ptr = this->Internals->Callbacks[mpit->first].Help; size_t len = strlen(ptr); @@ -649,10 +643,7 @@ void CommandLineArguments::PopulateVariable(double* variable, void CommandLineArguments::PopulateVariable(char** variable, const std::string& value) { - if (*variable) { - delete[] * variable; - *variable = 0; - } + delete[] * variable; *variable = new char[value.size() + 1]; strcpy(*variable, value.c_str()); } diff --git a/Source/kwsys/DynamicLoader.cxx b/Source/kwsys/DynamicLoader.cxx index 1b4596a..664f183 100644 --- a/Source/kwsys/DynamicLoader.cxx +++ b/Source/kwsys/DynamicLoader.cxx @@ -163,17 +163,13 @@ DynamicLoader::SymbolPointer DynamicLoader::GetSymbolAddress( { void* result = 0; // Need to prepend symbols with '_' on Apple-gcc compilers - size_t len = sym.size(); - char* rsym = new char[len + 1 + 1]; - strcpy(rsym, "_"); - strcat(rsym + 1, sym.c_str()); + std::string rsym = '_' + sym; - NSSymbol symbol = NSLookupSymbolInModule(lib, rsym); + NSSymbol symbol = NSLookupSymbolInModule(lib, rsym.c_str()); if (symbol) { result = NSAddressOfSymbol(symbol); } - delete[] rsym; // Hack to cast pointer-to-data to pointer-to-function. return *reinterpret_cast<DynamicLoader::SymbolPointer*>(&result); } @@ -237,17 +233,12 @@ DynamicLoader::SymbolPointer DynamicLoader::GetSymbolAddress( void* result; #if defined(__BORLANDC__) || defined(__WATCOMC__) // Need to prepend symbols with '_' - size_t len = sym.size(); - char* rsym = new char[len + 1 + 1]; - strcpy(rsym, "_"); - strcat(rsym, sym.c_str()); + std::string ssym = '_' + sym; + const char* rsym = ssym.c_str(); #else const char* rsym = sym.c_str(); #endif result = (void*)GetProcAddress(lib, rsym); -#if defined(__BORLANDC__) || defined(__WATCOMC__) - delete[] rsym; -#endif // Hack to cast pointer-to-data to pointer-to-function. #ifdef __WATCOMC__ return *(DynamicLoader::SymbolPointer*)(&result); diff --git a/Source/kwsys/ProcessUNIX.c b/Source/kwsys/ProcessUNIX.c index 3b32ca7..e62ef34 100644 --- a/Source/kwsys/ProcessUNIX.c +++ b/Source/kwsys/ProcessUNIX.c @@ -359,9 +359,7 @@ void kwsysProcess_Delete(kwsysProcess* cp) kwsysProcess_SetPipeFile(cp, kwsysProcess_Pipe_STDIN, 0); kwsysProcess_SetPipeFile(cp, kwsysProcess_Pipe_STDOUT, 0); kwsysProcess_SetPipeFile(cp, kwsysProcess_Pipe_STDERR, 0); - if (cp->CommandExitCodes) { - free(cp->CommandExitCodes); - } + free(cp->CommandExitCodes); free(cp->ProcessResults); free(cp); } @@ -498,11 +496,10 @@ int kwsysProcess_SetWorkingDirectory(kwsysProcess* cp, const char* dir) cp->WorkingDirectory = 0; } if (dir) { - cp->WorkingDirectory = (char*)malloc(strlen(dir) + 1); + cp->WorkingDirectory = strdup(dir); if (!cp->WorkingDirectory) { return 0; } - strcpy(cp->WorkingDirectory, dir); } return 1; } @@ -531,11 +528,10 @@ int kwsysProcess_SetPipeFile(kwsysProcess* cp, int prPipe, const char* file) *pfile = 0; } if (file) { - *pfile = (char*)malloc(strlen(file) + 1); + *pfile = strdup(file); if (!*pfile) { return 0; } - strcpy(*pfile, file); } /* If we are redirecting the pipe, do not share it or use a native @@ -1514,9 +1510,7 @@ static int kwsysProcessInitialize(kwsysProcess* cp) oldForkPIDs = cp->ForkPIDs; cp->ForkPIDs = (volatile pid_t*)malloc(sizeof(volatile pid_t) * (size_t)(cp->NumberOfCommands)); - if (oldForkPIDs) { - kwsysProcessVolatileFree(oldForkPIDs); - } + kwsysProcessVolatileFree(oldForkPIDs); if (!cp->ForkPIDs) { return 0; } @@ -1524,9 +1518,7 @@ static int kwsysProcessInitialize(kwsysProcess* cp) cp->ForkPIDs[i] = 0; /* can't use memset due to volatile */ } - if (cp->CommandExitCodes) { - free(cp->CommandExitCodes); - } + free(cp->CommandExitCodes); cp->CommandExitCodes = (int*)malloc(sizeof(int) * (size_t)(cp->NumberOfCommands)); if (!cp->CommandExitCodes) { @@ -1938,6 +1930,7 @@ static int kwsysProcessSetupOutputPipeFile(int* p, const char* name) /* Set close-on-exec flag on the pipe's end. */ if (fcntl(fout, F_SETFD, FD_CLOEXEC) < 0) { + close(fout); return 0; } @@ -2033,7 +2026,15 @@ static kwsysProcessTime kwsysProcessTimeGetCurrent(void) { kwsysProcessTime current; kwsysProcessTimeNative current_native; +#if KWSYS_C_HAS_CLOCK_GETTIME_MONOTONIC + struct timespec current_timespec; + clock_gettime(CLOCK_MONOTONIC, ¤t_timespec); + + current_native.tv_sec = current_timespec.tv_sec; + current_native.tv_usec = current_timespec.tv_nsec / 1000; +#else gettimeofday(¤t_native, 0); +#endif current.tv_sec = (long)current_native.tv_sec; current.tv_usec = (long)current_native.tv_usec; return current; @@ -2290,6 +2291,7 @@ static void kwsysProcessChildErrorExit(int errorPipe) char buffer[KWSYSPE_PIPE_BUFFER_SIZE]; kwsysProcess_ssize_t result; strncpy(buffer, strerror(errno), KWSYSPE_PIPE_BUFFER_SIZE); + buffer[KWSYSPE_PIPE_BUFFER_SIZE - 1] = '\0'; /* Report the error to the parent through the special pipe. */ result = write(errorPipe, buffer, strlen(buffer)); diff --git a/Source/kwsys/ProcessWin32.c b/Source/kwsys/ProcessWin32.c index 5183e3d..945fa28 100644 --- a/Source/kwsys/ProcessWin32.c +++ b/Source/kwsys/ProcessWin32.c @@ -523,9 +523,7 @@ void kwsysProcess_Delete(kwsysProcess* cp) kwsysProcess_SetPipeFile(cp, kwsysProcess_Pipe_STDIN, 0); kwsysProcess_SetPipeFile(cp, kwsysProcess_Pipe_STDOUT, 0); kwsysProcess_SetPipeFile(cp, kwsysProcess_Pipe_STDERR, 0); - if (cp->CommandExitCodes) { - free(cp->CommandExitCodes); - } + free(cp->CommandExitCodes); free(cp->ProcessResults); free(cp); } @@ -713,11 +711,10 @@ int kwsysProcess_SetPipeFile(kwsysProcess* cp, int pipe, const char* file) *pfile = 0; } if (file) { - *pfile = (char*)malloc(strlen(file) + 1); + *pfile = strdup(file); if (!*pfile) { return 0; } - strcpy(*pfile, file); } /* If we are redirecting the pipe, do not share it or use a native @@ -1607,9 +1604,7 @@ int kwsysProcessInitialize(kwsysProcess* cp) } ZeroMemory(cp->ProcessInformation, sizeof(PROCESS_INFORMATION) * cp->NumberOfCommands); - if (cp->CommandExitCodes) { - free(cp->CommandExitCodes); - } + free(cp->CommandExitCodes); cp->CommandExitCodes = (DWORD*)malloc(sizeof(DWORD) * cp->NumberOfCommands); if (!cp->CommandExitCodes) { return 0; @@ -2362,9 +2357,7 @@ static int kwsysProcess_List__New_NT4(kwsysProcess_List* self) static void kwsysProcess_List__Delete_NT4(kwsysProcess_List* self) { /* Free the process information buffer. */ - if (self->Buffer) { - free(self->Buffer); - } + free(self->Buffer); } static int kwsysProcess_List__Update_NT4(kwsysProcess_List* self) diff --git a/Source/kwsys/SystemInformation.cxx b/Source/kwsys/SystemInformation.cxx index 86fdccd..366fe30 100644 --- a/Source/kwsys/SystemInformation.cxx +++ b/Source/kwsys/SystemInformation.cxx @@ -1346,7 +1346,7 @@ std::string SymbolProperties::GetBinary() const std::string binary; char buf[1024] = { '\0' }; ssize_t ll = 0; - if ((ll = readlink("/proc/self/exe", buf, 1024)) > 0) { + if ((ll = readlink("/proc/self/exe", buf, 1024)) > 0 && ll < 1024) { buf[ll] = '\0'; binary = buf; } else { diff --git a/Source/kwsys/SystemTools.cxx b/Source/kwsys/SystemTools.cxx index ecfa331..a24a326 100644 --- a/Source/kwsys/SystemTools.cxx +++ b/Source/kwsys/SystemTools.cxx @@ -20,6 +20,7 @@ #include KWSYS_HEADER(SystemTools.hxx) #include KWSYS_HEADER(Directory.hxx) #include KWSYS_HEADER(FStream.hxx) +#include KWSYS_HEADER(Encoding.h) #include KWSYS_HEADER(Encoding.hxx) #include <fstream> @@ -227,13 +228,17 @@ inline const char* Getcwd(char* buf, unsigned int len) { std::vector<wchar_t> w_buf(len); if (_wgetcwd(&w_buf[0], len)) { - // make sure the drive letter is capital - if (wcslen(&w_buf[0]) > 1 && w_buf[1] == L':') { - w_buf[0] = towupper(w_buf[0]); + size_t nlen = kwsysEncoding_wcstombs(buf, &w_buf[0], len); + if (nlen == static_cast<size_t>(-1)) { + return 0; + } + if (nlen < len) { + // make sure the drive letter is capital + if (nlen > 1 && buf[1] == ':') { + buf[0] = toupper(buf[0]); + } + return buf; } - std::string tmp = KWSYS_NAMESPACE::Encoding::ToNarrow(&w_buf[0]); - strcpy(buf, tmp.c_str()); - return buf; } return 0; } diff --git a/Source/kwsys/kwsysPlatformTestsC.c b/Source/kwsys/kwsysPlatformTestsC.c index 64a361b..5432633 100644 --- a/Source/kwsys/kwsysPlatformTestsC.c +++ b/Source/kwsys/kwsysPlatformTestsC.c @@ -55,6 +55,21 @@ int KWSYS_PLATFORM_TEST_C_MAIN() } #endif +#ifdef TEST_KWSYS_C_HAS_CLOCK_GETTIME_MONOTONIC +#if defined(__APPLE__) +#include <AvailabilityMacros.h> +#if MAC_OS_X_VERSION_MIN_REQUIRED < 101200 +#error "clock_gettime not available on macOS < 10.12" +#endif +#endif +#include <time.h> +int KWSYS_PLATFORM_TEST_C_MAIN() +{ + struct timespec ts; + return clock_gettime(CLOCK_MONOTONIC, &ts); +} +#endif + #ifdef TEST_KWSYS_C_TYPE_MACROS char* info_macros = #if defined(__SIZEOF_SHORT__) diff --git a/Source/kwsys/testEncoding.cxx b/Source/kwsys/testEncoding.cxx index 2c5ef46..2742fe4 100644 --- a/Source/kwsys/testEncoding.cxx +++ b/Source/kwsys/testEncoding.cxx @@ -75,6 +75,10 @@ static int testRobustEncoding() // test that the conversion functions handle invalid // unicode correctly/gracefully + // we manipulate the format flags of stdout, remember + // the original state here to restore before return + std::ios::fmtflags const& flags = std::cout.flags(); + int ret = 0; char cstr[] = { (char)-1, 0 }; // this conversion could fail @@ -120,6 +124,7 @@ static int testRobustEncoding() ret++; } + std::cout.flags(flags); return ret; } diff --git a/Source/kwsys/testProcess.c b/Source/kwsys/testProcess.c index 092dd03..cd817d9 100644 --- a/Source/kwsys/testProcess.c +++ b/Source/kwsys/testProcess.c @@ -687,9 +687,7 @@ int main(int argc, const char* argv[]) fflush(stdout); fflush(stderr); #if defined(_WIN32) - if (argv0) { - free(argv0); - } + free(argv0); #endif return r; } else if (argc > 2 && strcmp(argv[1], "0") == 0) { diff --git a/Source/kwsys/testSystemTools.cxx b/Source/kwsys/testSystemTools.cxx index 768eb4d..3b694c9 100644 --- a/Source/kwsys/testSystemTools.cxx +++ b/Source/kwsys/testSystemTools.cxx @@ -254,22 +254,22 @@ static bool CheckFileOperations() } // should work, was created as new file before if (!kwsys::SystemTools::FileExists(testNewFile)) { - std::cerr << "Problem with FileExists for: " << testNewDir << std::endl; + std::cerr << "Problem with FileExists for: " << testNewFile << std::endl; res = false; } if (!kwsys::SystemTools::FileExists(testNewFile.c_str())) { - std::cerr << "Problem with FileExists as C string for: " << testNewDir + std::cerr << "Problem with FileExists as C string for: " << testNewFile << std::endl; res = false; } if (!kwsys::SystemTools::FileExists(testNewFile, true)) { - std::cerr << "Problem with FileExists as file for: " << testNewDir + std::cerr << "Problem with FileExists as file for: " << testNewFile << std::endl; res = false; } if (!kwsys::SystemTools::FileExists(testNewFile.c_str(), true)) { std::cerr << "Problem with FileExists as C string and file for: " - << testNewDir << std::endl; + << testNewFile << std::endl; res = false; } @@ -285,7 +285,7 @@ static bool CheckFileOperations() } // should work, was created as new file before if (!kwsys::SystemTools::PathExists(testNewFile)) { - std::cerr << "Problem with PathExists for: " << testNewDir << std::endl; + std::cerr << "Problem with PathExists for: " << testNewFile << std::endl; res = false; } |