diff options
90 files changed, 1169 insertions, 1161 deletions
diff --git a/Help/command/target_precompile_headers.rst b/Help/command/target_precompile_headers.rst index 3e28265..7d36b11 100644 --- a/Help/command/target_precompile_headers.rst +++ b/Help/command/target_precompile_headers.rst @@ -9,9 +9,23 @@ Add a list of header files to precompile. <INTERFACE|PUBLIC|PRIVATE> [header1...] [<INTERFACE|PUBLIC|PRIVATE> [header2...] ...]) + target_precompile_headers(<target> REUSE_FROM <other_target>) + Adds header files to :prop_tgt:`PRECOMPILE_HEADERS` or :prop_tgt:`INTERFACE_PRECOMPILE_HEADERS` target properties. +The second signature will reuse an already precompiled header file artefact +from another target. This is done by setting the +:prop_tgt:`PRECOMPILE_HEADERS_REUSE_FROM` to ``<other_target>`` value. +The ``<other_target>`` will become a dependency of ``<target>``. + +.. note:: + + The second signature will require the same set of compiler options, + compiler flags, compiler definitions for both ``<target>``, and + ``<other_target>``. Compilers (e.g. GCC) will issue a warning if the + precompiled header file cannot be used (``-Winvalid-pch``). + Precompiling header files can speed up compilation by creating a partially processed version of some header files, and then using that version during compilations rather than repeatedly parsing the original headers. diff --git a/Help/manual/cmake-properties.7.rst b/Help/manual/cmake-properties.7.rst index 9e54e3e..8f8cb33 100644 --- a/Help/manual/cmake-properties.7.rst +++ b/Help/manual/cmake-properties.7.rst @@ -299,6 +299,7 @@ Properties on Targets /prop_tgt/PDB_OUTPUT_DIRECTORY /prop_tgt/POSITION_INDEPENDENT_CODE /prop_tgt/PRECOMPILE_HEADERS + /prop_tgt/PRECOMPILE_HEADERS_REUSE_FROM /prop_tgt/PREFIX /prop_tgt/PRIVATE_HEADER /prop_tgt/PROJECT_LABEL diff --git a/Help/prop_tgt/PRECOMPILE_HEADERS_REUSE_FROM.rst b/Help/prop_tgt/PRECOMPILE_HEADERS_REUSE_FROM.rst new file mode 100644 index 0000000..d740303 --- /dev/null +++ b/Help/prop_tgt/PRECOMPILE_HEADERS_REUSE_FROM.rst @@ -0,0 +1,7 @@ +PRECOMPILE_HEADERS_REUSE_FROM +----------------------------- + +Target from which to reuse the precomipled headers build artifact. + +See the second signature of :command:`target_precompile_headers` command +for more detailed information. diff --git a/Help/release/dev/FindGnuTLS-target.rst b/Help/release/dev/FindGnuTLS-target.rst new file mode 100644 index 0000000..671a7b7 --- /dev/null +++ b/Help/release/dev/FindGnuTLS-target.rst @@ -0,0 +1,4 @@ +FindGnuTLS-target +----------------- + +* The :module:`FindGnuTLS` module now provides an imported target. diff --git a/Modules/CMakeFindBinUtils.cmake b/Modules/CMakeFindBinUtils.cmake index 01f9dae..781b48c 100644 --- a/Modules/CMakeFindBinUtils.cmake +++ b/Modules/CMakeFindBinUtils.cmake @@ -134,7 +134,7 @@ else() endif() if(CMAKE_PLATFORM_HAS_INSTALLNAME) - find_program(CMAKE_INSTALL_NAME_TOOL NAMES install_name_tool HINTS ${_CMAKE_TOOLCHAIN_LOCATION}) + find_program(CMAKE_INSTALL_NAME_TOOL NAMES ${_CMAKE_TOOLCHAIN_PREFIX}install_name_tool HINTS ${_CMAKE_TOOLCHAIN_LOCATION}) if(NOT CMAKE_INSTALL_NAME_TOOL) message(FATAL_ERROR "Could not find install_name_tool, please check your installation.") diff --git a/Modules/CMakePlatformId.h.in b/Modules/CMakePlatformId.h.in index 542a6fe..95465ce 100644 --- a/Modules/CMakePlatformId.h.in +++ b/Modules/CMakePlatformId.h.in @@ -174,6 +174,9 @@ # elif defined(__ICC430__) # define ARCHITECTURE_ID "MSP430" +# elif defined(__ICCV850__) +# define ARCHITECTURE_ID "V850" + # else /* unknown architecture */ # define ARCHITECTURE_ID "" # endif diff --git a/Modules/Compiler/IAR-C.cmake b/Modules/Compiler/IAR-C.cmake index e03ce3f..9ad1ba0 100644 --- a/Modules/Compiler/IAR-C.cmake +++ b/Modules/Compiler/IAR-C.cmake @@ -60,6 +60,11 @@ elseif("${CMAKE_C_COMPILER_ARCHITECTURE_ID}" STREQUAL "MSP430") __compiler_check_default_language_standard(C 1.10 90 5.10 99) set(CMAKE_C_OUTPUT_EXTENSION ".r43") +elseif("${CMAKE_C_COMPILER_ARCHITECTURE_ID}" STREQUAL "V850") + __compiler_iar_xlink(C) + __compiler_check_default_language_standard(C 1.10 90 4.10 99) + set(CMAKE_C_OUTPUT_EXTENSION ".r85") + else() message(FATAL_ERROR "CMAKE_C_COMPILER_ARCHITECTURE_ID not detected. This should be automatic.") endif() diff --git a/Modules/Compiler/IAR-CXX.cmake b/Modules/Compiler/IAR-CXX.cmake index e8f1142..549d242 100644 --- a/Modules/Compiler/IAR-CXX.cmake +++ b/Modules/Compiler/IAR-CXX.cmake @@ -68,6 +68,10 @@ elseif("${CMAKE_CXX_COMPILER_ARCHITECTURE_ID}" STREQUAL "MSP430") __compiler_check_default_language_standard(CXX 5.10 98) set(CMAKE_CXX_OUTPUT_EXTENSION ".r43") +elseif("${CMAKE_CXX_COMPILER_ARCHITECTURE_ID}" STREQUAL "V850") + __compiler_iar_xlink(CXX) + __compiler_check_default_language_standard(CXX 1.10 98) + set(CMAKE_C_OUTPUT_EXTENSION ".r85") else() message(FATAL_ERROR "CMAKE_CXX_COMPILER_ARCHITECTURE_ID not detected. This should be automatic." ) endif() diff --git a/Modules/Compiler/IAR-DetermineCompiler.cmake b/Modules/Compiler/IAR-DetermineCompiler.cmake index 57ca1c9..7e17778 100644 --- a/Modules/Compiler/IAR-DetermineCompiler.cmake +++ b/Modules/Compiler/IAR-DetermineCompiler.cmake @@ -31,7 +31,7 @@ set(_compiler_id_version_compute " # define @PREFIX@COMPILER_VERSION_MINOR @MACRO_DEC@(((__VER__) / 1000) % 1000) # define @PREFIX@COMPILER_VERSION_PATCH @MACRO_DEC@((__VER__) % 1000) # define @PREFIX@COMPILER_VERSION_INTERNAL @MACRO_DEC@(__IAR_SYSTEMS_ICC__) -# elif defined(__VER__) && (defined(__ICCAVR__) || defined(__ICCRX__) || defined(__ICCRH850__) || defined(__ICCRL78__) || defined(__ICC430__) || defined(__ICCRISCV__)) +# elif defined(__VER__) && (defined(__ICCAVR__) || defined(__ICCRX__) || defined(__ICCRH850__) || defined(__ICCRL78__) || defined(__ICC430__) || defined(__ICCRISCV__) || defined(__ICCV850__)) # define @PREFIX@COMPILER_VERSION_MAJOR @MACRO_DEC@((__VER__) / 100) # define @PREFIX@COMPILER_VERSION_MINOR @MACRO_DEC@((__VER__) - (((__VER__) / 100)*100)) # define @PREFIX@COMPILER_VERSION_PATCH @MACRO_DEC@(__SUBVERSION__) diff --git a/Modules/Compiler/IAR-FindBinUtils.cmake b/Modules/Compiler/IAR-FindBinUtils.cmake index b7d4664..6258cf3 100644 --- a/Modules/Compiler/IAR-FindBinUtils.cmake +++ b/Modules/Compiler/IAR-FindBinUtils.cmake @@ -45,7 +45,8 @@ set(CMAKE_IAR_LINKER \"${CMAKE_IAR_LINKER}\") ") elseif("${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_ARCHITECTURE_ID}" STREQUAL "AVR" OR - "${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_ARCHITECTURE_ID}" STREQUAL "MSP430") + "${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_ARCHITECTURE_ID}" STREQUAL "MSP430" OR + "${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_ARCHITECTURE_ID}" STREQUAL "V850") # Find the "xlink" linker and "xar" archiver: find_program(CMAKE_IAR_LINKER xlink HINTS ${__iar_hints} diff --git a/Modules/FindGnuTLS.cmake b/Modules/FindGnuTLS.cmake index 123a0f5..819f000 100644 --- a/Modules/FindGnuTLS.cmake +++ b/Modules/FindGnuTLS.cmake @@ -7,16 +7,25 @@ FindGnuTLS Find the GNU Transport Layer Security library (gnutls) - - -Once done this will define - -:: - - GNUTLS_FOUND - System has gnutls - GNUTLS_INCLUDE_DIR - The gnutls include directory - GNUTLS_LIBRARIES - The libraries needed to use gnutls - GNUTLS_DEFINITIONS - Compiler switches required for using gnutls +IMPORTED Targets +^^^^^^^^^^^^^^^^ + +This module defines :prop_tgt:`IMPORTED` target ``GnuTLS::GnuTLS``, if +gnutls has been found. + +Result Variables +^^^^^^^^^^^^^^^^ + +``GNUTLS_FOUND`` + System has gnutls +``GNUTLS_INCLUDE_DIR`` + The gnutls include directory +``GNUTLS_LIBRARIES`` + The libraries needed to use gnutls +``GNUTLS_DEFINITIONS`` + Compiler switches required for using gnutls +``GNUTLS_VERSION`` + version of gnutls. #]=======================================================================] # Note that this doesn't try to find the gnutls-extra package. @@ -34,6 +43,8 @@ if (NOT WIN32) find_package(PkgConfig QUIET) PKG_CHECK_MODULES(PC_GNUTLS QUIET gnutls) set(GNUTLS_DEFINITIONS ${PC_GNUTLS_CFLAGS_OTHER}) + set(GNUTLS_VERSION ${PC_GNUTLS_VERSION}) + # keep for backward compatibility set(GNUTLS_VERSION_STRING ${PC_GNUTLS_VERSION}) endif () @@ -59,4 +70,13 @@ FIND_PACKAGE_HANDLE_STANDARD_ARGS(GnuTLS if(GNUTLS_FOUND) set(GNUTLS_LIBRARIES ${GNUTLS_LIBRARY}) set(GNUTLS_INCLUDE_DIRS ${GNUTLS_INCLUDE_DIR}) + + if(NOT TARGET GnuTLS::GnuTLS) + add_library(GnuTLS::GnuTLS UNKNOWN IMPORTED) + set_target_properties(GnuTLS::GnuTLS PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES "${GNUTLS_INCLUDE_DIRS}" + INTERFACE_COMPILE_DEFINITIONS "${GNUTLS_DEFINITIONS}" + IMPORTED_LINK_INTERFACE_LANGUAGES "C" + IMPORTED_LOCATION "${GNUTLS_LIBRARIES}") + endif() endif() diff --git a/Modules/FindPkgConfig.cmake b/Modules/FindPkgConfig.cmake index 4c9af91..5162a44 100644 --- a/Modules/FindPkgConfig.cmake +++ b/Modules/FindPkgConfig.cmake @@ -214,7 +214,11 @@ function(_pkg_find_libs _prefix _no_cmake_path _no_cmake_environment_path) NAMES ${_pkg_search} ${_find_opts}) mark_as_advanced(pkgcfg_lib_${_prefix}_${_pkg_search}) - list(APPEND _libs "${pkgcfg_lib_${_prefix}_${_pkg_search}}") + if(pkgcfg_lib_${_prefix}_${_pkg_search}) + list(APPEND _libs "${pkgcfg_lib_${_prefix}_${_pkg_search}}") + else() + list(APPEND _libs ${_pkg_search}) + endif() endforeach() set(${_prefix}_LINK_LIBRARIES "${_libs}" PARENT_SCOPE) diff --git a/Modules/Platform/Windows-MSVC.cmake b/Modules/Platform/Windows-MSVC.cmake index 6ddcaa3..34f5d03 100644 --- a/Modules/Platform/Windows-MSVC.cmake +++ b/Modules/Platform/Windows-MSVC.cmake @@ -333,10 +333,17 @@ macro(__windows_compiler_msvc lang) set(CMAKE_LINK_PCH ON) if(MSVC_VERSION GREATER_EQUAL 1910) # VS 2017 or greater - set(CMAKE_PCH_PROLOGUE "#pragma system_header") + if (NOT ${CMAKE_${lang}_COMPILER_ID} STREQUAL "Clang") + set(CMAKE_PCH_PROLOGUE "#pragma system_header") + else() + set(CMAKE_PCH_PROLOGUE "#pragma clang system_header") + endif() + endif() + if (NOT ${CMAKE_${lang}_COMPILER_ID} STREQUAL "Clang") + set(CMAKE_PCH_COPY_COMPILE_PDB ON) endif() - set(CMAKE_${lang}_COMPILE_OPTIONS_USE_PCH /Yu<PCH_HEADER> /FI<PCH_HEADER>) - set(CMAKE_${lang}_COMPILE_OPTIONS_CREATE_PCH /Yc<PCH_HEADER> /FI<PCH_HEADER>) + set(CMAKE_${lang}_COMPILE_OPTIONS_USE_PCH /Yu<PCH_HEADER> /Fp<PCH_FILE> /FI<PCH_HEADER>) + set(CMAKE_${lang}_COMPILE_OPTIONS_CREATE_PCH /Yc<PCH_HEADER> /Fp<PCH_FILE> /FI<PCH_HEADER>) if("x${CMAKE_${lang}_COMPILER_ID}" STREQUAL "xMSVC") set(_CMAKE_${lang}_IPO_SUPPORTED_BY_CMAKE YES) diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index decb39a..65cd6c9 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -191,6 +191,8 @@ set(SRCS cmCustomCommand.h cmCustomCommandGenerator.cxx cmCustomCommandGenerator.h + cmCustomCommandLines.cxx + cmCustomCommandLines.h cmDefinitions.cxx cmDefinitions.h cmDepends.cxx diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 2aef888..c09c1ce 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 15) -set(CMake_VERSION_PATCH 20190916) +set(CMake_VERSION_PATCH 20190919) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) diff --git a/Source/CPack/cmCPackGeneratorFactory.cxx b/Source/CPack/cmCPackGeneratorFactory.cxx index a564eb1..79e344b 100644 --- a/Source/CPack/cmCPackGeneratorFactory.cxx +++ b/Source/CPack/cmCPackGeneratorFactory.cxx @@ -6,7 +6,6 @@ #include <utility> #include "IFW/cmCPackIFWGenerator.h" -#include "cmAlgorithms.h" #ifdef HAVE_FREEBSD_PKG # include "cmCPackFreeBSDGenerator.h" #endif @@ -138,33 +137,21 @@ cmCPackGeneratorFactory::cmCPackGeneratorFactory() #endif } -cmCPackGeneratorFactory::~cmCPackGeneratorFactory() -{ - cmDeleteAll(this->Generators); -} - -cmCPackGenerator* cmCPackGeneratorFactory::NewGenerator( +std::unique_ptr<cmCPackGenerator> cmCPackGeneratorFactory::NewGenerator( const std::string& name) { - cmCPackGenerator* gen = this->NewGeneratorInternal(name); + auto it = this->GeneratorCreators.find(name); + if (it == this->GeneratorCreators.end()) { + return nullptr; + } + std::unique_ptr<cmCPackGenerator> gen(it->second()); if (!gen) { return nullptr; } - this->Generators.push_back(gen); gen->SetLogger(this->Logger); return gen; } -cmCPackGenerator* cmCPackGeneratorFactory::NewGeneratorInternal( - const std::string& name) -{ - auto it = this->GeneratorCreators.find(name); - if (it == this->GeneratorCreators.end()) { - return nullptr; - } - return (it->second)(); -} - void cmCPackGeneratorFactory::RegisterGenerator( const std::string& name, const char* generatorDescription, CreateGeneratorCall* createGenerator) diff --git a/Source/CPack/cmCPackGeneratorFactory.h b/Source/CPack/cmCPackGeneratorFactory.h index da2eb8d..62b7484 100644 --- a/Source/CPack/cmCPackGeneratorFactory.h +++ b/Source/CPack/cmCPackGeneratorFactory.h @@ -6,8 +6,8 @@ #include "cmConfigure.h" // IWYU pragma: keep #include <map> +#include <memory> #include <string> -#include <vector> class cmCPackGenerator; class cmCPackLog; @@ -20,14 +20,9 @@ class cmCPackGeneratorFactory { public: cmCPackGeneratorFactory(); - ~cmCPackGeneratorFactory(); - - cmCPackGeneratorFactory(const cmCPackGeneratorFactory&) = delete; - cmCPackGeneratorFactory& operator=(const cmCPackGeneratorFactory&) = delete; //! Get the generator - cmCPackGenerator* NewGenerator(const std::string& name); - void DeleteGenerator(cmCPackGenerator* gen); + std::unique_ptr<cmCPackGenerator> NewGenerator(const std::string& name); using CreateGeneratorCall = cmCPackGenerator*(); @@ -44,9 +39,6 @@ public: } private: - cmCPackGenerator* NewGeneratorInternal(const std::string& name); - std::vector<cmCPackGenerator*> Generators; - using t_GeneratorCreatorsMap = std::map<std::string, CreateGeneratorCall*>; t_GeneratorCreatorsMap GeneratorCreators; DescriptionsMap GeneratorDescriptions; diff --git a/Source/CPack/cpack.cxx b/Source/CPack/cpack.cxx index ab44a42..ce41d40 100644 --- a/Source/CPack/cpack.cxx +++ b/Source/CPack/cpack.cxx @@ -25,6 +25,7 @@ #include <cstddef> #include <iostream> #include <map> +#include <memory> #include <sstream> #include <string> #include <utility> @@ -237,7 +238,6 @@ int main(int argc, char const* const* argv) cmCPackGeneratorFactory generators; generators.SetLogger(&log); - cmCPackGenerator* cpackGenerator = nullptr; cmDocumentation doc; doc.addCPackStandardDocSections(); @@ -360,7 +360,8 @@ int main(int argc, char const* const* argv) parsed = 0; } if (parsed) { - cpackGenerator = generators.NewGenerator(gen); + std::unique_ptr<cmCPackGenerator> cpackGenerator = + generators.NewGenerator(gen); if (cpackGenerator) { cpackGenerator->SetTrace(trace); cpackGenerator->SetTraceExpand(traceExpand); diff --git a/Source/cmAddCustomCommandCommand.cxx b/Source/cmAddCustomCommandCommand.cxx index c91198c..35db6a4 100644 --- a/Source/cmAddCustomCommandCommand.cxx +++ b/Source/cmAddCustomCommandCommand.cxx @@ -321,10 +321,9 @@ bool cmAddCustomCommandCommand(std::vector<std::string> const& args, } // No command for this output exists. - std::ostringstream e; - e << "given APPEND option with output\n\"" << output[0] - << "\"\nwhich is not already a custom command output."; - status.SetError(e.str()); + status.SetError( + cmStrCat("given APPEND option with output\n\"", output[0], + "\"\nwhich is not already a custom command output.")); return false; } @@ -407,10 +406,8 @@ bool cmAddCustomCommandCommandCheckOutputs( // Make sure the output file name has no invalid characters. std::string::size_type pos = o.find_first_of("#<>"); if (pos != std::string::npos) { - std::ostringstream msg; - msg << "called with OUTPUT containing a \"" << o[pos] - << "\". This character is not allowed."; - status.SetError(msg.str()); + status.SetError(cmStrCat("called with OUTPUT containing a \"", o[pos], + "\". This character is not allowed.")); return false; } } diff --git a/Source/cmAddCustomTargetCommand.cxx b/Source/cmAddCustomTargetCommand.cxx index caea510..9fd1234 100644 --- a/Source/cmAddCustomTargetCommand.cxx +++ b/Source/cmAddCustomTargetCommand.cxx @@ -2,7 +2,6 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmAddCustomTargetCommand.h" -#include <sstream> #include <utility> #include "cmCustomCommandLines.h" @@ -29,11 +28,9 @@ bool cmAddCustomTargetCommand(std::vector<std::string> const& args, // Check the target name. if (targetName.find_first_of("/\\") != std::string::npos) { - std::ostringstream e; - e << "called with invalid target name \"" << targetName - << "\". Target names may not contain a slash. " - << "Use ADD_CUSTOM_COMMAND to generate files."; - status.SetError(e.str()); + status.SetError(cmStrCat("called with invalid target name \"", targetName, + "\". Target names may not contain a slash. " + "Use ADD_CUSTOM_COMMAND to generate files.")); return false; } @@ -127,7 +124,7 @@ bool cmAddCustomTargetCommand(std::vector<std::string> const& args, } filename += copy; cmSystemTools::ConvertToUnixSlashes(filename); - byproducts.push_back(filename); + byproducts.push_back(cmSystemTools::CollapseFullPath(filename)); } break; case doing_depends: { std::string dep = copy; @@ -153,10 +150,9 @@ bool cmAddCustomTargetCommand(std::vector<std::string> const& args, std::string::size_type pos = targetName.find_first_of("#<>"); if (pos != std::string::npos) { - std::ostringstream msg; - msg << "called with target name containing a \"" << targetName[pos] - << "\". This character is not allowed."; - status.SetError(msg.str()); + status.SetError(cmStrCat("called with target name containing a \"", + targetName[pos], + "\". This character is not allowed.")); return false; } diff --git a/Source/cmAddDependenciesCommand.cxx b/Source/cmAddDependenciesCommand.cxx index 0ddbda8..b1fc893 100644 --- a/Source/cmAddDependenciesCommand.cxx +++ b/Source/cmAddDependenciesCommand.cxx @@ -2,12 +2,11 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmAddDependenciesCommand.h" -#include <sstream> - #include "cmExecutionStatus.h" #include "cmMakefile.h" #include "cmMessageType.h" #include "cmRange.h" +#include "cmStringAlgorithms.h" #include "cmTarget.h" bool cmAddDependenciesCommand(std::vector<std::string> const& args, @@ -21,10 +20,10 @@ bool cmAddDependenciesCommand(std::vector<std::string> const& args, cmMakefile& mf = status.GetMakefile(); std::string const& target_name = args[0]; if (mf.IsAlias(target_name)) { - std::ostringstream e; - e << "Cannot add target-level dependencies to alias target \"" - << target_name << "\".\n"; - mf.IssueMessage(MessageType::FATAL_ERROR, e.str()); + mf.IssueMessage( + MessageType::FATAL_ERROR, + cmStrCat("Cannot add target-level dependencies to alias target \"", + target_name, "\".\n")); } if (cmTarget* target = mf.FindTargetToUse(target_name)) { @@ -33,14 +32,17 @@ bool cmAddDependenciesCommand(std::vector<std::string> const& args, target->AddUtility(arg, &mf); } } else { - std::ostringstream e; - e << "Cannot add target-level dependencies to non-existent target \"" - << target_name << "\".\n" - << "The add_dependencies works for top-level logical targets created " - << "by the add_executable, add_library, or add_custom_target commands. " - << "If you want to add file-level dependencies see the DEPENDS option " - << "of the add_custom_target and add_custom_command commands."; - mf.IssueMessage(MessageType::FATAL_ERROR, e.str()); + mf.IssueMessage( + MessageType::FATAL_ERROR, + cmStrCat( + "Cannot add target-level dependencies to non-existent " + "target \"", + target_name, + "\".\nThe add_dependencies works for " + "top-level logical targets created by the add_executable, " + "add_library, or add_custom_target commands. If you want to add " + "file-level dependencies see the DEPENDS option of the " + "add_custom_target and add_custom_command commands.")); } return true; diff --git a/Source/cmAddExecutableCommand.cxx b/Source/cmAddExecutableCommand.cxx index 1a87028..e738bc4 100644 --- a/Source/cmAddExecutableCommand.cxx +++ b/Source/cmAddExecutableCommand.cxx @@ -2,13 +2,12 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmAddExecutableCommand.h" -#include <sstream> - #include "cmExecutionStatus.h" #include "cmGeneratorExpression.h" #include "cmGlobalGenerator.h" #include "cmMakefile.h" #include "cmStateTypes.h" +#include "cmStringAlgorithms.h" #include "cmTarget.h" bool cmAddExecutableCommand(std::vector<std::string> const& args, @@ -99,34 +98,30 @@ bool cmAddExecutableCommand(std::vector<std::string> const& args, std::string const& aliasedName = *s; if (mf.IsAlias(aliasedName)) { - std::ostringstream e; - e << "cannot create ALIAS target \"" << exename << "\" because target \"" - << aliasedName << "\" is itself an ALIAS."; - status.SetError(e.str()); + status.SetError(cmStrCat("cannot create ALIAS target \"", exename, + "\" because target \"", aliasedName, + "\" is itself an ALIAS.")); return false; } cmTarget* aliasedTarget = mf.FindTargetToUse(aliasedName, true); if (!aliasedTarget) { - std::ostringstream e; - e << "cannot create ALIAS target \"" << exename << "\" because target \"" - << aliasedName << "\" does not already exist."; - status.SetError(e.str()); + status.SetError(cmStrCat("cannot create ALIAS target \"", exename, + "\" because target \"", aliasedName, + "\" does not already exist.")); return false; } cmStateEnums::TargetType type = aliasedTarget->GetType(); if (type != cmStateEnums::EXECUTABLE) { - std::ostringstream e; - e << "cannot create ALIAS target \"" << exename << "\" because target \"" - << aliasedName << "\" is not an executable."; - status.SetError(e.str()); + status.SetError(cmStrCat("cannot create ALIAS target \"", exename, + "\" because target \"", aliasedName, + "\" is not an executable.")); return false; } if (aliasedTarget->IsImported() && !aliasedTarget->IsImportedGloballyVisible()) { - std::ostringstream e; - e << "cannot create ALIAS target \"" << exename << "\" because target \"" - << aliasedName << "\" is imported but not globally visible."; - status.SetError(e.str()); + status.SetError(cmStrCat("cannot create ALIAS target \"", exename, + "\" because target \"", aliasedName, + "\" is imported but not globally visible.")); return false; } mf.AddAlias(exename, aliasedName); @@ -137,10 +132,9 @@ bool cmAddExecutableCommand(std::vector<std::string> const& args, if (importTarget) { // Make sure the target does not already exist. if (mf.FindTargetToUse(exename)) { - std::ostringstream e; - e << "cannot create imported target \"" << exename - << "\" because another target with the same name already exists."; - status.SetError(e.str()); + status.SetError(cmStrCat( + "cannot create imported target \"", exename, + "\" because another target with the same name already exists.")); return false; } diff --git a/Source/cmAddLibraryCommand.cxx b/Source/cmAddLibraryCommand.cxx index dc8937a..0439c51 100644 --- a/Source/cmAddLibraryCommand.cxx +++ b/Source/cmAddLibraryCommand.cxx @@ -2,8 +2,6 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmAddLibraryCommand.h" -#include <sstream> - #include "cmAlgorithms.h" #include "cmExecutionStatus.h" #include "cmGeneratorExpression.h" @@ -184,20 +182,16 @@ bool cmAddLibraryCommand(std::vector<std::string> const& args, std::string const& aliasedName = *s; if (mf.IsAlias(aliasedName)) { - std::ostringstream e; - e << "cannot create ALIAS target \"" << libName << "\" because target \"" - << aliasedName << "\" is itself an ALIAS."; - status.SetError(e.str()); + status.SetError(cmStrCat("cannot create ALIAS target \"", libName, + "\" because target \"", aliasedName, + "\" is itself an ALIAS.")); return false; } cmTarget* aliasedTarget = mf.FindTargetToUse(aliasedName, true); if (!aliasedTarget) { - std::ostringstream e; - e << "cannot create ALIAS target \"" << libName << "\" because target \"" - << aliasedName - << "\" does not already " - "exist."; - status.SetError(e.str()); + status.SetError(cmStrCat("cannot create ALIAS target \"", libName, + "\" because target \"", aliasedName, + "\" does not already exist.")); return false; } cmStateEnums::TargetType aliasedType = aliasedTarget->GetType(); @@ -208,18 +202,16 @@ bool cmAddLibraryCommand(std::vector<std::string> const& args, aliasedType != cmStateEnums::INTERFACE_LIBRARY && !(aliasedType == cmStateEnums::UNKNOWN_LIBRARY && aliasedTarget->IsImported())) { - std::ostringstream e; - e << "cannot create ALIAS target \"" << libName << "\" because target \"" - << aliasedName << "\" is not a library."; - status.SetError(e.str()); + status.SetError(cmStrCat("cannot create ALIAS target \"", libName, + "\" because target \"", aliasedName, + "\" is not a library.")); return false; } if (aliasedTarget->IsImported() && !aliasedTarget->IsImportedGloballyVisible()) { - std::ostringstream e; - e << "cannot create ALIAS target \"" << libName << "\" because target \"" - << aliasedName << "\" is imported but not globally visible."; - status.SetError(e.str()); + status.SetError(cmStrCat("cannot create ALIAS target \"", libName, + "\" because target \"", aliasedName, + "\" is imported but not globally visible.")); return false; } mf.AddAlias(libName, aliasedName); @@ -238,12 +230,13 @@ bool cmAddLibraryCommand(std::vector<std::string> const& args, if ((type == cmStateEnums::SHARED_LIBRARY || type == cmStateEnums::MODULE_LIBRARY) && !mf.GetState()->GetGlobalPropertyAsBool("TARGET_SUPPORTS_SHARED_LIBS")) { - std::ostringstream w; - w << "ADD_LIBRARY called with " - << (type == cmStateEnums::SHARED_LIBRARY ? "SHARED" : "MODULE") - << " option but the target platform does not support dynamic linking. " - "Building a STATIC library instead. This may lead to problems."; - mf.IssueMessage(MessageType::AUTHOR_WARNING, w.str()); + mf.IssueMessage( + MessageType::AUTHOR_WARNING, + cmStrCat( + "ADD_LIBRARY called with ", + (type == cmStateEnums::SHARED_LIBRARY ? "SHARED" : "MODULE"), + " option but the target platform does not support dynamic linking. ", + "Building a STATIC library instead. This may lead to problems.")); type = cmStateEnums::STATIC_LIBRARY; } @@ -266,19 +259,17 @@ bool cmAddLibraryCommand(std::vector<std::string> const& args, } if (type == cmStateEnums::INTERFACE_LIBRARY) { if (!cmGeneratorExpression::IsValidTargetName(libName)) { - std::ostringstream e; - e << "Invalid name for IMPORTED INTERFACE library target: " << libName; - status.SetError(e.str()); + status.SetError(cmStrCat( + "Invalid name for IMPORTED INTERFACE library target: ", libName)); return false; } } // Make sure the target does not already exist. if (mf.FindTargetToUse(libName)) { - std::ostringstream e; - e << "cannot create imported target \"" << libName - << "\" because another target with the same name already exists."; - status.SetError(e.str()); + status.SetError(cmStrCat( + "cannot create imported target \"", libName, + "\" because another target with the same name already exists.")); return false; } @@ -309,9 +300,8 @@ bool cmAddLibraryCommand(std::vector<std::string> const& args, if (type == cmStateEnums::INTERFACE_LIBRARY) { if (!cmGeneratorExpression::IsValidTargetName(libName) || libName.find("::") != std::string::npos) { - std::ostringstream e; - e << "Invalid name for INTERFACE library target: " << libName; - status.SetError(e.str()); + status.SetError( + cmStrCat("Invalid name for INTERFACE library target: ", libName)); return false; } diff --git a/Source/cmAddSubDirectoryCommand.cxx b/Source/cmAddSubDirectoryCommand.cxx index c0be308..6a1a514 100644 --- a/Source/cmAddSubDirectoryCommand.cxx +++ b/Source/cmAddSubDirectoryCommand.cxx @@ -3,7 +3,6 @@ #include "cmAddSubDirectoryCommand.h" #include <cstring> -#include <sstream> #include "cmExecutionStatus.h" #include "cmMakefile.h" @@ -64,13 +63,13 @@ bool cmAddSubDirectoryCommand(std::vector<std::string> const& args, // error. if (!cmSystemTools::IsSubDirectory(srcPath, mf.GetCurrentSourceDirectory())) { - std::ostringstream e; - e << "not given a binary directory but the given source directory " - << "\"" << srcPath << "\" is not a subdirectory of \"" - << mf.GetCurrentSourceDirectory() << "\". " - << "When specifying an out-of-tree source a binary directory " - << "must be explicitly specified."; - status.SetError(e.str()); + status.SetError( + cmStrCat("not given a binary directory but the given source ", + "directory \"", srcPath, "\" is not a subdirectory of \"", + mf.GetCurrentSourceDirectory(), + "\". When specifying an " + "out-of-tree source a binary directory must be explicitly " + "specified.")); return false; } diff --git a/Source/cmAddTestCommand.cxx b/Source/cmAddTestCommand.cxx index 7904bf5..8942113 100644 --- a/Source/cmAddTestCommand.cxx +++ b/Source/cmAddTestCommand.cxx @@ -2,10 +2,9 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmAddTestCommand.h" -#include <sstream> - #include "cmExecutionStatus.h" #include "cmMakefile.h" +#include "cmStringAlgorithms.h" #include "cmTest.h" #include "cmTestGenerator.h" @@ -38,10 +37,8 @@ bool cmAddTestCommand(std::vector<std::string> const& args, // If the test was already added by a new-style signature do not // allow it to be duplicated. if (!test->GetOldStyle()) { - std::ostringstream e; - e << " given test name \"" << args[0] - << "\" which already exists in this directory."; - status.SetError(e.str()); + status.SetError(cmStrCat(" given test name \"", args[0], + "\" which already exists in this directory.")); return false; } } else { @@ -110,9 +107,7 @@ bool cmAddTestCommandHandleNameMode(std::vector<std::string> const& args, working_directory = args[i]; doing = DoingNone; } else { - std::ostringstream e; - e << " given unknown argument:\n " << args[i] << "\n"; - status.SetError(e.str()); + status.SetError(cmStrCat(" given unknown argument:\n ", args[i], "\n")); return false; } } @@ -133,10 +128,8 @@ bool cmAddTestCommandHandleNameMode(std::vector<std::string> const& args, // Require a unique test name within the directory. if (mf.GetTest(name)) { - std::ostringstream e; - e << " given test NAME \"" << name - << "\" which already exists in this directory."; - status.SetError(e.str()); + status.SetError(cmStrCat(" given test NAME \"", name, + "\" which already exists in this directory.")); return false; } diff --git a/Source/cmCMakePolicyCommand.cxx b/Source/cmCMakePolicyCommand.cxx index 9b1aea9..b7f08d2 100644 --- a/Source/cmCMakePolicyCommand.cxx +++ b/Source/cmCMakePolicyCommand.cxx @@ -2,14 +2,13 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmCMakePolicyCommand.h" -#include <sstream> - #include "cmExecutionStatus.h" #include "cmMakefile.h" #include "cmMessageType.h" #include "cmPolicies.h" #include "cmState.h" #include "cmStateTypes.h" +#include "cmStringAlgorithms.h" namespace { bool HandleSetMode(std::vector<std::string> const& args, @@ -60,9 +59,7 @@ bool cmCMakePolicyCommand(std::vector<std::string> const& args, return HandleGetWarningMode(args, status); } - std::ostringstream e; - e << "given unknown first argument \"" << args[0] << "\""; - status.SetError(e.str()); + status.SetError(cmStrCat("given unknown first argument \"", args[0], "\"")); return false; } @@ -82,9 +79,8 @@ bool HandleSetMode(std::vector<std::string> const& args, } else if (args[2] == "NEW") { policyStatus = cmPolicies::NEW; } else { - std::ostringstream e; - e << "SET given unrecognized policy status \"" << args[2] << "\""; - status.SetError(e.str()); + status.SetError( + cmStrCat("SET given unrecognized policy status \"", args[2], "\"")); return false; } @@ -128,10 +124,9 @@ bool HandleGetMode(std::vector<std::string> const& args, // Lookup the policy number. cmPolicies::PolicyID pid; if (!cmPolicies::GetPolicyID(id.c_str(), pid)) { - std::ostringstream e; - e << "GET given policy \"" << id << "\" which is not known to this " - << "version of CMake."; - status.SetError(e.str()); + status.SetError( + cmStrCat("GET given policy \"", id, + "\" which is not known to this version of CMake.")); return false; } @@ -155,12 +150,14 @@ bool HandleGetMode(std::vector<std::string> const& args, case cmPolicies::REQUIRED_ALWAYS: // The policy is required to be set before anything needs it. { - std::ostringstream e; - e << cmPolicies::GetRequiredPolicyError(pid) << "\n" - << "The call to cmake_policy(GET " << id << " ...) at which this " - << "error appears requests the policy, and this version of CMake " - << "requires that the policy be set to NEW before it is checked."; - status.GetMakefile().IssueMessage(MessageType::FATAL_ERROR, e.str()); + status.GetMakefile().IssueMessage( + MessageType::FATAL_ERROR, + cmStrCat( + cmPolicies::GetRequiredPolicyError(pid), "\n", + "The call to cmake_policy(GET ", id, + " ...) at which this " + "error appears requests the policy, and this version of CMake ", + "requires that the policy be set to NEW before it is checked.")); } } @@ -188,10 +185,9 @@ bool HandleVersionMode(std::vector<std::string> const& args, : std::string(); if (dd != std::string::npos && (version_min.empty() || version_max.empty())) { - std::ostringstream e; - e << "VERSION \"" << version_string - << R"(" does not have a version on both sides of "...".)"; - status.SetError(e.str()); + status.SetError( + cmStrCat("VERSION \"", version_string, + R"(" does not have a version on both sides of "...".)")); return false; } @@ -215,10 +211,9 @@ bool HandleGetWarningMode(std::vector<std::string> const& args, // Lookup the policy number. cmPolicies::PolicyID pid; if (!cmPolicies::GetPolicyID(id.c_str(), pid)) { - std::ostringstream e; - e << "GET_WARNING given policy \"" << id - << "\" which is not known to this version of CMake."; - status.SetError(e.str()); + status.SetError( + cmStrCat("GET_WARNING given policy \"", id, + "\" which is not known to this version of CMake.")); return false; } diff --git a/Source/cmCommonTargetGenerator.cxx b/Source/cmCommonTargetGenerator.cxx index 33286ad..19a096b 100644 --- a/Source/cmCommonTargetGenerator.cxx +++ b/Source/cmCommonTargetGenerator.cxx @@ -171,6 +171,7 @@ std::string cmCommonTargetGenerator::ComputeTargetCompilePDB() const if (this->GeneratorTarget->GetType() > cmStateEnums::OBJECT_LIBRARY) { return compilePdbPath; } + compilePdbPath = this->GeneratorTarget->GetCompilePDBPath(this->GetConfigName()); if (compilePdbPath.empty()) { diff --git a/Source/cmConfigureFileCommand.cxx b/Source/cmConfigureFileCommand.cxx index 7e37f32..8767386 100644 --- a/Source/cmConfigureFileCommand.cxx +++ b/Source/cmConfigureFileCommand.cxx @@ -2,8 +2,6 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmConfigureFileCommand.h" -#include <sstream> - #include "cmExecutionStatus.h" #include "cmMakefile.h" #include "cmMessageType.h" @@ -26,13 +24,9 @@ bool cmConfigureFileCommand(std::vector<std::string> const& args, // If the input location is a directory, error out. if (cmSystemTools::FileIsDirectory(inputFile)) { - std::ostringstream e; - /* clang-format off */ - e << "input location\n" - << " " << inputFile << "\n" - << "is a directory but a file was expected."; - /* clang-format on */ - status.SetError(e.str()); + status.SetError(cmStrCat("input location\n ", inputFile, + "\n" + "is a directory but a file was expected.")); return false; } diff --git a/Source/cmCustomCommandLines.cxx b/Source/cmCustomCommandLines.cxx new file mode 100644 index 0000000..37ad75b --- /dev/null +++ b/Source/cmCustomCommandLines.cxx @@ -0,0 +1,22 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#include "cmCustomCommandLines.h" + +cmCustomCommandLine cmMakeCommandLine( + std::initializer_list<cm::string_view> ilist) +{ + cmCustomCommandLine commandLine; + commandLine.reserve(ilist.size()); + for (cm::string_view cmd : ilist) { + commandLine.emplace_back(cmd); + } + return commandLine; +} + +cmCustomCommandLines cmMakeSingleCommandLine( + std::initializer_list<cm::string_view> ilist) +{ + cmCustomCommandLines commandLines; + commandLines.push_back(cmMakeCommandLine(ilist)); + return commandLines; +} diff --git a/Source/cmCustomCommandLines.h b/Source/cmCustomCommandLines.h index 35a15ba..213aeb1 100644 --- a/Source/cmCustomCommandLines.h +++ b/Source/cmCustomCommandLines.h @@ -5,25 +5,28 @@ #include "cmConfigure.h" // IWYU pragma: keep +#include <initializer_list> #include <string> #include <vector> +#include "cm_string_view.hxx" // IWYU pragma: keep + /** Data structure to represent a single command line. */ class cmCustomCommandLine : public std::vector<std::string> { -public: - using Superclass = std::vector<std::string>; - using iterator = Superclass::iterator; - using const_iterator = Superclass::const_iterator; }; /** Data structure to represent a list of command lines. */ class cmCustomCommandLines : public std::vector<cmCustomCommandLine> { -public: - using Superclass = std::vector<cmCustomCommandLine>; - using iterator = Superclass::iterator; - using const_iterator = Superclass::const_iterator; }; +/** Return a command line from a list of command line parts. */ +cmCustomCommandLine cmMakeCommandLine( + std::initializer_list<cm::string_view> ilist); + +/** Return a command line vector with a single command line. */ +cmCustomCommandLines cmMakeSingleCommandLine( + std::initializer_list<cm::string_view> ilist); + #endif diff --git a/Source/cmFLTKWrapUICommand.cxx b/Source/cmFLTKWrapUICommand.cxx index 654714e..11844e4 100644 --- a/Source/cmFLTKWrapUICommand.cxx +++ b/Source/cmFLTKWrapUICommand.cxx @@ -77,16 +77,15 @@ bool cmFLTKWrapUICommand(std::vector<std::string> const& args, depends.push_back(fluid_exe); std::string cxxres = cmStrCat(outName, ".cxx"); - cmCustomCommandLine commandLine; - commandLine.push_back(fluid_exe); - commandLine.push_back("-c"); // instructs Fluid to run in command line - commandLine.push_back("-h"); // optionally rename .h files - commandLine.push_back(hname); - commandLine.push_back("-o"); // optionally rename .cxx files - commandLine.push_back(cxxres); - commandLine.push_back(origname); // name of the GUI fluid file - cmCustomCommandLines commandLines; - commandLines.push_back(commandLine); + cmCustomCommandLines commandLines = cmMakeSingleCommandLine({ + fluid_exe, + "-c", // instructs Fluid to run in command line + "-h", // optionally rename .h files + hname, + "-o", // optionally rename .cxx files + cxxres, + origname // name of the GUI fluid file + }); // Add command for generating the .h and .cxx files std::string no_main_dependency; diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx index 33acd05..4701d29 100644 --- a/Source/cmFileCommand.cxx +++ b/Source/cmFileCommand.cxx @@ -274,9 +274,8 @@ bool HandleHashCommand(std::vector<std::string> const& args, { #if !defined(CMAKE_BOOTSTRAP) if (args.size() != 3) { - std::ostringstream e; - e << args[0] << " requires a file name and output variable"; - status.SetError(e.str()); + status.SetError( + cmStrCat(args[0], " requires a file name and output variable")); return false; } @@ -287,16 +286,12 @@ bool HandleHashCommand(std::vector<std::string> const& args, status.GetMakefile().AddDefinition(args[2], out); return true; } - std::ostringstream e; - e << args[0] << " failed to read file \"" << args[1] - << "\": " << cmSystemTools::GetLastSystemError(); - status.SetError(e.str()); + status.SetError(cmStrCat(args[0], " failed to read file \"", args[1], + "\": ", cmSystemTools::GetLastSystemError())); } return false; #else - std::ostringstream e; - e << args[0] << " not available during bootstrap"; - status.SetError(e.str()); + status.SetError(cmStrCat(args[0], " not available during bootstrap")); return false; #endif } @@ -376,30 +371,24 @@ bool HandleStringsCommand(std::vector<std::string> const& args, } else if (arg_mode == arg_limit_input) { if (sscanf(args[i].c_str(), "%d", &limit_input) != 1 || limit_input < 0) { - std::ostringstream e; - e << "STRINGS option LIMIT_INPUT value \"" << args[i] - << "\" is not an unsigned integer."; - status.SetError(e.str()); + status.SetError(cmStrCat("STRINGS option LIMIT_INPUT value \"", + args[i], "\" is not an unsigned integer.")); return false; } arg_mode = arg_none; } else if (arg_mode == arg_limit_output) { if (sscanf(args[i].c_str(), "%d", &limit_output) != 1 || limit_output < 0) { - std::ostringstream e; - e << "STRINGS option LIMIT_OUTPUT value \"" << args[i] - << "\" is not an unsigned integer."; - status.SetError(e.str()); + status.SetError(cmStrCat("STRINGS option LIMIT_OUTPUT value \"", + args[i], "\" is not an unsigned integer.")); return false; } arg_mode = arg_none; } else if (arg_mode == arg_limit_count) { int count; if (sscanf(args[i].c_str(), "%d", &count) != 1 || count < 0) { - std::ostringstream e; - e << "STRINGS option LIMIT_COUNT value \"" << args[i] - << "\" is not an unsigned integer."; - status.SetError(e.str()); + status.SetError(cmStrCat("STRINGS option LIMIT_COUNT value \"", + args[i], "\" is not an unsigned integer.")); return false; } limit_count = count; @@ -407,10 +396,8 @@ bool HandleStringsCommand(std::vector<std::string> const& args, } else if (arg_mode == arg_length_minimum) { int len; if (sscanf(args[i].c_str(), "%d", &len) != 1 || len < 0) { - std::ostringstream e; - e << "STRINGS option LENGTH_MINIMUM value \"" << args[i] - << "\" is not an unsigned integer."; - status.SetError(e.str()); + status.SetError(cmStrCat("STRINGS option LENGTH_MINIMUM value \"", + args[i], "\" is not an unsigned integer.")); return false; } minlen = len; @@ -418,20 +405,16 @@ bool HandleStringsCommand(std::vector<std::string> const& args, } else if (arg_mode == arg_length_maximum) { int len; if (sscanf(args[i].c_str(), "%d", &len) != 1 || len < 0) { - std::ostringstream e; - e << "STRINGS option LENGTH_MAXIMUM value \"" << args[i] - << "\" is not an unsigned integer."; - status.SetError(e.str()); + status.SetError(cmStrCat("STRINGS option LENGTH_MAXIMUM value \"", + args[i], "\" is not an unsigned integer.")); return false; } maxlen = len; arg_mode = arg_none; } else if (arg_mode == arg_regex) { if (!regex.compile(args[i])) { - std::ostringstream e; - e << "STRINGS option REGEX value \"" << args[i] - << "\" could not be compiled."; - status.SetError(e.str()); + status.SetError(cmStrCat("STRINGS option REGEX value \"", args[i], + "\" could not be compiled.")); return false; } have_regex = true; @@ -448,16 +431,14 @@ bool HandleStringsCommand(std::vector<std::string> const& args, } else if (args[i] == "UTF-32BE") { encoding = encoding_utf32be; } else { - std::ostringstream e; - e << "STRINGS option ENCODING \"" << args[i] << "\" not recognized."; - status.SetError(e.str()); + status.SetError(cmStrCat("STRINGS option ENCODING \"", args[i], + "\" not recognized.")); return false; } arg_mode = arg_none; } else { - std::ostringstream e; - e << "STRINGS given unknown argument \"" << args[i] << "\""; - status.SetError(e.str()); + status.SetError( + cmStrCat("STRINGS given unknown argument \"", args[i], "\"")); return false; } } @@ -479,9 +460,8 @@ bool HandleStringsCommand(std::vector<std::string> const& args, cmsys::ifstream fin(fileName.c_str()); #endif if (!fin) { - std::ostringstream e; - e << "STRINGS file \"" << fileName << "\" cannot be read."; - status.SetError(e.str()); + status.SetError( + cmStrCat("STRINGS file \"", fileName, "\" cannot be read.")); return false; } @@ -963,9 +943,7 @@ bool HandleDifferentCommand(std::vector<std::string> const& args, file_rhs = args[i].c_str(); doing = DoingNone; } else { - std::ostringstream e; - e << "DIFFERENT given unknown argument " << args[i]; - status.SetError(e.str()); + status.SetError(cmStrCat("DIFFERENT given unknown argument ", args[i])); return false; } } @@ -1027,9 +1005,8 @@ bool HandleRPathChangeCommand(std::vector<std::string> const& args, newRPath = args[i].c_str(); doing = DoingNone; } else { - std::ostringstream e; - e << "RPATH_CHANGE given unknown argument " << args[i]; - status.SetError(e.str()); + status.SetError( + cmStrCat("RPATH_CHANGE given unknown argument ", args[i])); return false; } } @@ -1046,9 +1023,8 @@ bool HandleRPathChangeCommand(std::vector<std::string> const& args, return false; } if (!cmSystemTools::FileExists(file, true)) { - std::ostringstream e; - e << "RPATH_CHANGE given FILE \"" << file << "\" that does not exist."; - status.SetError(e.str()); + status.SetError( + cmStrCat("RPATH_CHANGE given FILE \"", file, "\" that does not exist.")); return false; } bool success = true; @@ -1058,15 +1034,9 @@ bool HandleRPathChangeCommand(std::vector<std::string> const& args, if (!cmSystemTools::ChangeRPath(file, oldRPath, newRPath, removeEnvironmentRPath, &emsg, &changed)) { - std::ostringstream e; - /* clang-format off */ - e << "RPATH_CHANGE could not write new RPATH:\n" - << " " << newRPath << "\n" - << "to the file:\n" - << " " << file << "\n" - << emsg; - /* clang-format on */ - status.SetError(e.str()); + status.SetError(cmStrCat("RPATH_CHANGE could not write new RPATH:\n ", + newRPath, "\nto the file:\n ", file, "\n", + emsg)); success = false; } if (success) { @@ -1098,9 +1068,8 @@ bool HandleRPathRemoveCommand(std::vector<std::string> const& args, file = args[i]; doing = DoingNone; } else { - std::ostringstream e; - e << "RPATH_REMOVE given unknown argument " << args[i]; - status.SetError(e.str()); + status.SetError( + cmStrCat("RPATH_REMOVE given unknown argument ", args[i])); return false; } } @@ -1109,9 +1078,8 @@ bool HandleRPathRemoveCommand(std::vector<std::string> const& args, return false; } if (!cmSystemTools::FileExists(file, true)) { - std::ostringstream e; - e << "RPATH_REMOVE given FILE \"" << file << "\" that does not exist."; - status.SetError(e.str()); + status.SetError( + cmStrCat("RPATH_REMOVE given FILE \"", file, "\" that does not exist.")); return false; } bool success = true; @@ -1119,13 +1087,9 @@ bool HandleRPathRemoveCommand(std::vector<std::string> const& args, std::string emsg; bool removed; if (!cmSystemTools::RemoveRPath(file, &emsg, &removed)) { - std::ostringstream e; - /* clang-format off */ - e << "RPATH_REMOVE could not remove RPATH from file:\n" - << " " << file << "\n" - << emsg; - /* clang-format on */ - status.SetError(e.str()); + status.SetError( + cmStrCat("RPATH_REMOVE could not remove RPATH from file: \n ", file, + "\n", emsg)); success = false; } if (success) { @@ -1164,9 +1128,8 @@ bool HandleRPathCheckCommand(std::vector<std::string> const& args, rpath = args[i].c_str(); doing = DoingNone; } else { - std::ostringstream e; - e << "RPATH_CHECK given unknown argument " << args[i]; - status.SetError(e.str()); + status.SetError( + cmStrCat("RPATH_CHECK given unknown argument ", args[i])); return false; } } @@ -1215,9 +1178,8 @@ bool HandleReadElfCommand(std::vector<std::string> const& args, Arguments const arguments = parser.Parse(cmMakeRange(args).advance(2)); if (!cmSystemTools::FileExists(fileNameArg, true)) { - std::ostringstream e; - e << "READ_ELF given FILE \"" << fileNameArg << "\" that does not exist."; - status.SetError(e.str()); + status.SetError(cmStrCat("READ_ELF given FILE \"", fileNameArg, + "\" that does not exist.")); return false; } @@ -1311,15 +1273,8 @@ bool HandleRename(std::vector<std::string> const& args, if (!cmSystemTools::RenameFile(oldname, newname)) { std::string err = cmSystemTools::GetLastSystemError(); - std::ostringstream e; - /* clang-format off */ - e << "RENAME failed to rename\n" - << " " << oldname << "\n" - << "to\n" - << " " << newname << "\n" - << "because: " << err << "\n"; - /* clang-format on */ - status.SetError(e.str()); + status.SetError(cmStrCat("RENAME failed to rename\n ", oldname, + "\nto\n ", newname, "\nbecause: ", err, "\n")); return false; } return true; @@ -1494,10 +1449,8 @@ public: bool updated = (OldPercentage != this->CurrentPercentage); if (updated) { - std::ostringstream oss; - oss << "[" << this->Text << " " << this->CurrentPercentage - << "% complete]"; - status = oss.str(); + status = + cmStrCat("[", this->Text, " ", this->CurrentPercentage, "% complete]"); } return updated; @@ -1743,9 +1696,7 @@ bool HandleDownloadCommand(std::vector<std::string> const& args, msg = cmStrCat("returning early; file already exists with expected ", hashMatchMSG, '"'); if (!statusVar.empty()) { - std::ostringstream result; - result << 0 << ";\"" << msg; - status.GetMakefile().AddDefinition(statusVar, result.str()); + status.GetMakefile().AddDefinition(statusVar, cmStrCat(0, ";\"", msg)); } return true; } @@ -1891,10 +1842,9 @@ bool HandleDownloadCommand(std::vector<std::string> const& args, ::curl_easy_cleanup(curl); if (!statusVar.empty()) { - std::ostringstream result; - result << static_cast<int>(res) << ";\"" << ::curl_easy_strerror(res) - << "\""; - status.GetMakefile().AddDefinition(statusVar, result.str()); + status.GetMakefile().AddDefinition( + statusVar, + cmStrCat(static_cast<int>(res), ";\"", ::curl_easy_strerror(res), "\"")); } ::curl_global_cleanup(); @@ -1914,14 +1864,6 @@ bool HandleDownloadCommand(std::vector<std::string> const& args, } if (expectedHash != actualHash) { - std::ostringstream oss; - oss << "DOWNLOAD HASH mismatch" << std::endl - << " for file: [" << file << "]" << std::endl - << " expected hash: [" << expectedHash << "]" << std::endl - << " actual hash: [" << actualHash << "]" << std::endl - << " status: [" << static_cast<int>(res) << ";\"" - << ::curl_easy_strerror(res) << "\"]" << std::endl; - if (!statusVar.empty() && res == 0) { status.GetMakefile().AddDefinition(statusVar, "1;HASH mismatch: " @@ -1930,7 +1872,19 @@ bool HandleDownloadCommand(std::vector<std::string> const& args, " actual: " + actualHash); } - status.SetError(oss.str()); + status.SetError(cmStrCat("DOWNLOAD HASH mismatch\n" + " for file: [", + file, + "]\n" + " expected hash: [", + expectedHash, + "]\n" + " actual hash: [", + actualHash, + "]\n" + " status: [", + static_cast<int>(res), ";\"", + ::curl_easy_strerror(res), "\"]\n")); return false; } } @@ -2180,10 +2134,9 @@ bool HandleUploadCommand(std::vector<std::string> const& args, ::curl_easy_cleanup(curl); if (!statusVar.empty()) { - std::ostringstream result; - result << static_cast<int>(res) << ";\"" << ::curl_easy_strerror(res) - << "\""; - status.GetMakefile().AddDefinition(statusVar, result.str()); + status.GetMakefile().AddDefinition( + statusVar, + cmStrCat(static_cast<int>(res), ";\"", ::curl_easy_strerror(res), "\"")); } ::curl_global_cleanup(); @@ -2322,9 +2275,9 @@ bool HandleLockCommand(std::vector<std::string> const& args, } else if (args[i] == "PROCESS") { guard = GUARD_PROCESS; } else { - std::ostringstream e; - e << merr << ", but got:\n \"" << args[i] << "\"."; - status.GetMakefile().IssueMessage(MessageType::FATAL_ERROR, e.str()); + status.GetMakefile().IssueMessage( + MessageType::FATAL_ERROR, + cmStrCat(merr, ", but got:\n \"", args[i], "\".")); return false; } @@ -2346,17 +2299,18 @@ bool HandleLockCommand(std::vector<std::string> const& args, } long scanned; if (!cmStrToLong(args[i], &scanned) || scanned < 0) { - std::ostringstream e; - e << "TIMEOUT value \"" << args[i] << "\" is not an unsigned integer."; - status.GetMakefile().IssueMessage(MessageType::FATAL_ERROR, e.str()); + status.GetMakefile().IssueMessage( + MessageType::FATAL_ERROR, + cmStrCat("TIMEOUT value \"", args[i], + "\" is not an unsigned integer.")); return false; } timeout = static_cast<unsigned long>(scanned); } else { - std::ostringstream e; - e << "expected DIRECTORY, RELEASE, GUARD, RESULT_VARIABLE or TIMEOUT\n"; - e << "but got: \"" << args[i] << "\"."; - status.GetMakefile().IssueMessage(MessageType::FATAL_ERROR, e.str()); + status.GetMakefile().IssueMessage( + MessageType::FATAL_ERROR, + cmStrCat("expected DIRECTORY, RELEASE, GUARD, RESULT_VARIABLE or ", + "TIMEOUT\nbut got: \"", args[i], "\".")); return false; } } @@ -2375,18 +2329,19 @@ bool HandleLockCommand(std::vector<std::string> const& args, // Create file and directories if needed std::string parentDir = cmSystemTools::GetParentDirectory(path); if (!cmSystemTools::MakeDirectory(parentDir)) { - std::ostringstream e; - e << "directory\n \"" << parentDir << "\"\ncreation failed "; - e << "(check permissions)."; - status.GetMakefile().IssueMessage(MessageType::FATAL_ERROR, e.str()); + status.GetMakefile().IssueMessage( + MessageType::FATAL_ERROR, + cmStrCat("directory\n \"", parentDir, + "\"\ncreation failed (check permissions).")); cmSystemTools::SetFatalErrorOccured(); return false; } FILE* file = cmsys::SystemTools::Fopen(path, "w"); if (!file) { - std::ostringstream e; - e << "file\n \"" << path << "\"\ncreation failed (check permissions)."; - status.GetMakefile().IssueMessage(MessageType::FATAL_ERROR, e.str()); + status.GetMakefile().IssueMessage( + MessageType::FATAL_ERROR, + cmStrCat("file\n \"", path, + "\"\ncreation failed (check permissions).")); cmSystemTools::SetFatalErrorOccured(); return false; } @@ -2419,9 +2374,9 @@ bool HandleLockCommand(std::vector<std::string> const& args, const std::string result = fileLockResult.GetOutputMessage(); if (resultVariable.empty() && !fileLockResult.IsOk()) { - std::ostringstream e; - e << "error locking file\n \"" << path << "\"\n" << result << "."; - status.GetMakefile().IssueMessage(MessageType::FATAL_ERROR, e.str()); + status.GetMakefile().IssueMessage( + MessageType::FATAL_ERROR, + cmStrCat("error locking file\n \"", path, "\"\n", result, ".")); cmSystemTools::SetFatalErrorOccured(); return false; } @@ -2485,9 +2440,8 @@ bool HandleSizeCommand(std::vector<std::string> const& args, cmExecutionStatus& status) { if (args.size() != 3) { - std::ostringstream e; - e << args[0] << " requires a file name and output variable"; - status.SetError(e.str()); + status.SetError( + cmStrCat(args[0], " requires a file name and output variable")); return false; } @@ -2498,9 +2452,8 @@ bool HandleSizeCommand(std::vector<std::string> const& args, const std::string& outputVariable = args[argsIndex++]; if (!cmSystemTools::FileExists(filename, true)) { - std::ostringstream e; - e << "SIZE requested of path that is not readable:\n " << filename; - status.SetError(e.str()); + status.SetError( + cmStrCat("SIZE requested of path that is not readable:\n ", filename)); return false; } @@ -2514,9 +2467,8 @@ bool HandleReadSymlinkCommand(std::vector<std::string> const& args, cmExecutionStatus& status) { if (args.size() != 3) { - std::ostringstream e; - e << args[0] << " requires a file name and output variable"; - status.SetError(e.str()); + status.SetError( + cmStrCat(args[0], " requires a file name and output variable")); return false; } @@ -2525,10 +2477,8 @@ bool HandleReadSymlinkCommand(std::vector<std::string> const& args, std::string result; if (!cmSystemTools::ReadSymlink(filename, result)) { - std::ostringstream e; - e << "READ_SYMLINK requested of path that is not a symlink:\n " - << filename; - status.SetError(e.str()); + status.SetError(cmStrCat( + "READ_SYMLINK requested of path that is not a symlink:\n ", filename)); return false; } @@ -2655,10 +2605,9 @@ bool HandleGetRuntimeDependenciesCommand(std::vector<std::string> const& args, std::string platform = status.GetMakefile().GetSafeDefinition("CMAKE_HOST_SYSTEM_NAME"); if (!supportedPlatforms.count(platform)) { - std::ostringstream e; - e << "GET_RUNTIME_DEPENDENCIES is not supported on system \"" << platform - << "\""; - status.SetError(e.str()); + status.SetError( + cmStrCat("GET_RUNTIME_DEPENDENCIES is not supported on system \"", + platform, "\"")); cmSystemTools::SetFatalErrorOccured(); return false; } @@ -2718,17 +2667,13 @@ bool HandleGetRuntimeDependenciesCommand(std::vector<std::string> const& args, &keywordsMissingValues); auto argIt = unrecognizedArguments.begin(); if (argIt != unrecognizedArguments.end()) { - std::ostringstream e; - e << "Unrecognized argument: \"" << *argIt << "\""; - status.SetError(e.str()); + status.SetError(cmStrCat("Unrecognized argument: \"", *argIt, "\"")); cmSystemTools::SetFatalErrorOccured(); return false; } argIt = keywordsMissingValues.begin(); if (argIt != keywordsMissingValues.end()) { - std::ostringstream e; - e << "Keyword missing value: " << *argIt; - status.SetError(e.str()); + status.SetError(cmStrCat("Keyword missing value: ", *argIt)); cmSystemTools::SetFatalErrorOccured(); return false; } @@ -2792,9 +2737,7 @@ bool HandleGetRuntimeDependenciesCommand(std::vector<std::string> const& args, } else { auto it = archive.GetUnresolvedPaths().begin(); assert(it != archive.GetUnresolvedPaths().end()); - std::ostringstream e; - e << "Could not resolve file " << *it; - status.SetError(e.str()); + status.SetError(cmStrCat("Could not resolve file ", *it)); cmSystemTools::SetFatalErrorOccured(); return false; } diff --git a/Source/cmFindPackageCommand.cxx b/Source/cmFindPackageCommand.cxx index 8c8cf13..fea7e08 100644 --- a/Source/cmFindPackageCommand.cxx +++ b/Source/cmFindPackageCommand.cxx @@ -348,11 +348,10 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args) } else if (doing == DoingConfigs) { if (args[i].find_first_of(":/\\") != std::string::npos || cmSystemTools::GetFilenameLastExtension(args[i]) != ".cmake") { - std::ostringstream e; - e << "given CONFIGS option followed by invalid file name \"" << args[i] - << "\". The names given must be file names without " - << "a path and with a \".cmake\" extension."; - this->SetError(e.str()); + this->SetError(cmStrCat( + "given CONFIGS option followed by invalid file name \"", args[i], + "\". The names given must be file names without " + "a path and with a \".cmake\" extension.")); return false; } this->Configs.push_back(args[i]); @@ -360,9 +359,8 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args) haveVersion = true; this->Version = args[i]; } else { - std::ostringstream e; - e << "called with invalid argument \"" << args[i] << "\""; - this->SetError(e.str()); + this->SetError( + cmStrCat("called with invalid argument \"", args[i], "\"")); return false; } } @@ -372,10 +370,10 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args) optionalComponents.begin(), optionalComponents.end(), std::back_inserter(doubledComponents)); if (!doubledComponents.empty()) { - std::ostringstream e; - e << "called with components that are both required and optional:\n"; - e << cmWrap(" ", doubledComponents, "", "\n") << "\n"; - this->SetError(e.str()); + this->SetError( + cmStrCat("called with components that are both required and " + "optional:\n", + cmWrap(" ", doubledComponents, "", "\n"), "\n")); return false; } @@ -459,11 +457,10 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args) cmStrCat("CMAKE_DISABLE_FIND_PACKAGE_", this->Name); if (this->Makefile->IsOn(disableFindPackageVar)) { if (this->Required) { - std::ostringstream e; - e << "for module " << this->Name << " called with REQUIRED, but " - << disableFindPackageVar - << " is enabled. A REQUIRED package cannot be disabled."; - this->SetError(e.str()); + this->SetError( + cmStrCat("for module ", this->Name, " called with REQUIRED, but ", + disableFindPackageVar, + " is enabled. A REQUIRED package cannot be disabled.")); return false; } @@ -701,9 +698,9 @@ bool cmFindPackageCommand::FindModule(bool& found) this->Makefile->GetPolicyStatus(it->second); switch (status) { case cmPolicies::WARN: { - std::ostringstream e; - e << cmPolicies::GetPolicyWarning(it->second) << "\n"; - this->Makefile->IssueMessage(MessageType::AUTHOR_WARNING, e.str()); + this->Makefile->IssueMessage( + MessageType::AUTHOR_WARNING, + cmStrCat(cmPolicies::GetPolicyWarning(it->second), "\n")); CM_FALLTHROUGH; } case cmPolicies::OLD: @@ -934,10 +931,10 @@ bool cmFindPackageCommand::HandlePackageMode( } // output result if in config mode but not in quiet mode else if (!this->Quiet) { - std::ostringstream aw; - aw << "Could NOT find " << this->Name << " (missing: " << this->Name - << "_DIR)"; - this->Makefile->DisplayStatus(aw.str(), -1); + this->Makefile->DisplayStatus(cmStrCat("Could NOT find ", this->Name, + " (missing: ", this->Name, + "_DIR)"), + -1); } } diff --git a/Source/cmForEachCommand.cxx b/Source/cmForEachCommand.cxx index 3c39c46..d563a1d 100644 --- a/Source/cmForEachCommand.cxx +++ b/Source/cmForEachCommand.cxx @@ -4,7 +4,6 @@ #include <cstdio> #include <cstdlib> -#include <sstream> #include <utility> #include "cm_memory.hxx" @@ -146,10 +145,9 @@ bool cmForEachCommand(std::vector<std::string> const& args, } if ((start > stop && step > 0) || (start < stop && step < 0) || step == 0) { - std::ostringstream str; - str << "called with incorrect range specification: start "; - str << start << ", stop " << stop << ", step " << step; - status.SetError(str.str()); + status.SetError( + cmStrCat("called with incorrect range specification: start ", start, + ", stop ", stop, ", step ", step)); return false; } std::vector<std::string> range; @@ -204,10 +202,9 @@ bool HandleInMode(std::vector<std::string> const& args, cmMakefile& makefile) cmExpandList(value, fb->Args, true); } } else { - std::ostringstream e; - e << "Unknown argument:\n" - << " " << args[i] << "\n"; - makefile.IssueMessage(MessageType::FATAL_ERROR, e.str()); + makefile.IssueMessage( + MessageType::FATAL_ERROR, + cmStrCat("Unknown argument:\n", " ", args[i], "\n")); return true; } } diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index 2ca5706..3a321c5 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -35,6 +35,7 @@ #include "cmRange.h" #include "cmSourceFile.h" #include "cmSourceFileLocation.h" +#include "cmSourceFileLocationKind.h" #include "cmState.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" @@ -3371,57 +3372,67 @@ std::string cmGeneratorTarget::GetPchHeader(const std::string& config, } std::string& filename = inserted.first->second; + const cmGeneratorTarget* generatorTarget = this; + const char* pchReuseFrom = + generatorTarget->GetProperty("PRECOMPILE_HEADERS_REUSE_FROM"); + if (pchReuseFrom) { + generatorTarget = + this->GetGlobalGenerator()->FindGeneratorTarget(pchReuseFrom); + } + if (this->GetGlobalGenerator()->IsMultiConfig()) { - filename = - cmStrCat(this->LocalGenerator->GetCurrentBinaryDirectory(), "/"); + filename = cmStrCat( + generatorTarget->LocalGenerator->GetCurrentBinaryDirectory(), "/"); } else { // For GCC we need to have the header file .h[xx] // next to the .h[xx].gch file - filename = this->ObjectDirectory; + filename = generatorTarget->ObjectDirectory; } - filename = cmStrCat(filename, "CMakeFiles/", this->GetName(), + filename = cmStrCat(filename, "CMakeFiles/", generatorTarget->GetName(), ".dir/cmake_pch", ((language == "C") ? ".h" : ".hxx")); const std::string filename_tmp = cmStrCat(filename, ".tmp"); - { + if (!pchReuseFrom) { auto pchPrologue = this->Makefile->GetDefinition("CMAKE_PCH_PROLOGUE"); auto pchEpilogue = this->Makefile->GetDefinition("CMAKE_PCH_EPILOGUE"); - cmGeneratedFileStream file( - filename_tmp, false, - this->GetGlobalGenerator()->GetMakefileEncoding()); - file << "/* generated by CMake */\n\n"; - if (pchPrologue) { - file << pchPrologue << "\n"; - } - if (this->GetGlobalGenerator()->IsXcode()) { - file << "#ifndef CMAKE_SKIP_PRECOMPILE_HEADERS\n"; - } - if (language == "CXX") { - file << "#ifdef __cplusplus\n"; - } - for (auto const& header_bt : headers) { - if (header_bt.Value.empty()) { - continue; + { + cmGeneratedFileStream file( + filename_tmp, false, + this->GetGlobalGenerator()->GetMakefileEncoding()); + file << "/* generated by CMake */\n\n"; + if (pchPrologue) { + file << pchPrologue << "\n"; } - if (header_bt.Value[0] == '<' || header_bt.Value[0] == '"') { - file << "#include " << header_bt.Value << "\n"; - } else { - file << "#include \"" << header_bt.Value << "\"\n"; + if (this->GetGlobalGenerator()->IsXcode()) { + file << "#ifndef CMAKE_SKIP_PRECOMPILE_HEADERS\n"; + } + if (language == "CXX") { + file << "#ifdef __cplusplus\n"; + } + for (auto const& header_bt : headers) { + if (header_bt.Value.empty()) { + continue; + } + if (header_bt.Value[0] == '<' || header_bt.Value[0] == '\"') { + file << "#include " << header_bt.Value << "\n"; + } else { + file << "#include \"" << header_bt.Value << "\"\n"; + } + } + if (language == "CXX") { + file << "#endif // __cplusplus\n"; + } + if (this->GetGlobalGenerator()->IsXcode()) { + file << "#endif // CMAKE_SKIP_PRECOMPILE_HEADERS\n"; + } + if (pchEpilogue) { + file << pchEpilogue << "\n"; } } - if (language == "CXX") { - file << "#endif // __cplusplus\n"; - } - if (this->GetGlobalGenerator()->IsXcode()) { - file << "#endif // CMAKE_SKIP_PRECOMPILE_HEADERS\n"; - } - if (pchEpilogue) { - file << pchEpilogue << "\n"; - } + cmSystemTools::MoveFileIfDifferent(filename_tmp, filename); } - cmSystemTools::MoveFileIfDifferent(filename_tmp, filename); } return inserted.first->second; } @@ -3440,8 +3451,18 @@ std::string cmGeneratorTarget::GetPchSource(const std::string& config, return std::string(); } std::string& filename = inserted.first->second; - filename = cmStrCat(this->LocalGenerator->GetCurrentBinaryDirectory(), - "/CMakeFiles/", this->GetName(), ".dir/cmake_pch"); + + const cmGeneratorTarget* generatorTarget = this; + const char* pchReuseFrom = + generatorTarget->GetProperty("PRECOMPILE_HEADERS_REUSE_FROM"); + if (pchReuseFrom) { + generatorTarget = + this->GetGlobalGenerator()->FindGeneratorTarget(pchReuseFrom); + } + + filename = + cmStrCat(generatorTarget->LocalGenerator->GetCurrentBinaryDirectory(), + "/CMakeFiles/", generatorTarget->GetName(), ".dir/cmake_pch"); // For GCC the source extension will be tranformed into .h[xx].gch if (!this->Makefile->IsOn("CMAKE_LINK_PCH")) { @@ -3449,12 +3470,40 @@ std::string cmGeneratorTarget::GetPchSource(const std::string& config, } else { filename += ((language == "C") ? ".c" : ".cxx"); } + const std::string filename_tmp = cmStrCat(filename, ".tmp"); - { - cmGeneratedFileStream file(filename_tmp); - file << "/* generated by CMake */\n"; + if (!pchReuseFrom) { + { + cmGeneratedFileStream file(filename_tmp); + file << "/* generated by CMake */\n"; + } + cmSystemTools::MoveFileIfDifferent(filename_tmp, filename); } - cmSystemTools::MoveFileIfDifferent(filename_tmp, filename); + } + return inserted.first->second; +} + +std::string cmGeneratorTarget::GetPchFileObject(const std::string& config, + const std::string& language) +{ + if (language != "C" && language != "CXX") { + return std::string(); + } + const auto inserted = + this->PchObjectFiles.insert(std::make_pair(language + config, "")); + if (inserted.second) { + const std::string pchSource = this->GetPchSource(config, language); + if (pchSource.empty()) { + return std::string(); + } + std::string& filename = inserted.first->second; + + this->AddSource(pchSource, true); + + auto pchSf = this->Makefile->GetOrCreateSource( + pchSource, false, cmSourceFileLocationKind::Known); + + filename = cmStrCat(this->ObjectDirectory, this->GetObjectName(pchSf)); } return inserted.first->second; } diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h index 4207d65..6c36c4b 100644 --- a/Source/cmGeneratorTarget.h +++ b/Source/cmGeneratorTarget.h @@ -462,6 +462,8 @@ public: const std::string& language) const; std::string GetPchSource(const std::string& config, const std::string& language) const; + std::string GetPchFileObject(const std::string& config, + const std::string& language); bool IsSystemIncludeDirectory(const std::string& dir, const std::string& config, @@ -880,6 +882,7 @@ private: mutable std::set<std::string> LinkImplicitNullProperties; mutable std::map<std::string, std::string> PchHeaders; mutable std::map<std::string, std::string> PchSources; + mutable std::map<std::string, std::string> PchObjectFiles; void ExpandLinkItems(std::string const& prop, std::string const& value, std::string const& config, diff --git a/Source/cmGetPropertyCommand.cxx b/Source/cmGetPropertyCommand.cxx index e8e87e7..947d893 100644 --- a/Source/cmGetPropertyCommand.cxx +++ b/Source/cmGetPropertyCommand.cxx @@ -2,8 +2,6 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmGetPropertyCommand.h" -#include <sstream> - #include "cmExecutionStatus.h" #include "cmGlobalGenerator.h" #include "cmInstalledFile.h" @@ -99,11 +97,11 @@ bool cmGetPropertyCommand(std::vector<std::string> const& args, } else if (args[1] == "INSTALL") { scope = cmProperty::INSTALL; } else { - std::ostringstream e; - e << "given invalid scope " << args[1] << ". " - << "Valid scopes are " - << "GLOBAL, DIRECTORY, TARGET, SOURCE, TEST, VARIABLE, CACHE, INSTALL."; - status.SetError(e.str()); + status.SetError(cmStrCat( + "given invalid scope ", args[1], + ". " + "Valid scopes are " + "GLOBAL, DIRECTORY, TARGET, SOURCE, TEST, VARIABLE, CACHE, INSTALL.")); return false; } @@ -138,9 +136,7 @@ bool cmGetPropertyCommand(std::vector<std::string> const& args, doing = DoingNone; propertyName = args[i]; } else { - std::ostringstream e; - e << "given invalid argument \"" << args[i] << "\"."; - status.SetError(e.str()); + status.SetError(cmStrCat("given invalid argument \"", args[i], "\".")); return false; } } @@ -331,10 +327,8 @@ bool HandleTargetMode(cmExecutionStatus& status, const std::string& name, } return StoreResult(infoType, status.GetMakefile(), variable, prop_cstr); } - std::ostringstream e; - e << "could not find TARGET " << name - << ". Perhaps it has not yet been created."; - status.SetError(e.str()); + status.SetError(cmStrCat("could not find TARGET ", name, + ". Perhaps it has not yet been created.")); return false; } @@ -352,9 +346,8 @@ bool HandleSourceMode(cmExecutionStatus& status, const std::string& name, return StoreResult(infoType, status.GetMakefile(), variable, sf->GetPropertyForUser(propertyName)); } - std::ostringstream e; - e << "given SOURCE name that could not be found or created: " << name; - status.SetError(e.str()); + status.SetError( + cmStrCat("given SOURCE name that could not be found or created: ", name)); return false; } @@ -374,9 +367,7 @@ bool HandleTestMode(cmExecutionStatus& status, const std::string& name, } // If not found it is an error. - std::ostringstream e; - e << "given TEST name that does not exist: " << name; - status.SetError(e.str()); + status.SetError(cmStrCat("given TEST name that does not exist: ", name)); return false; } @@ -431,9 +422,8 @@ bool HandleInstallMode(cmExecutionStatus& status, const std::string& name, return StoreResult(infoType, status.GetMakefile(), variable, isSet ? value.c_str() : nullptr); } - std::ostringstream e; - e << "given INSTALL name that could not be found or created: " << name; - status.SetError(e.str()); + status.SetError( + cmStrCat("given INSTALL name that could not be found or created: ", name)); return false; } } diff --git a/Source/cmGlobalVisualStudio8Generator.cxx b/Source/cmGlobalVisualStudio8Generator.cxx index 18ff9ac..255739d 100644 --- a/Source/cmGlobalVisualStudio8Generator.cxx +++ b/Source/cmGlobalVisualStudio8Generator.cxx @@ -3,6 +3,7 @@ #include "cmGlobalVisualStudio8Generator.h" #include "cmCustomCommand.h" +#include "cmCustomCommandLines.h" #include "cmDocumentationEntry.h" #include "cmGeneratedFileStream.h" #include "cmGeneratorExpression.h" @@ -146,12 +147,8 @@ bool cmGlobalVisualStudio8Generator::AddCheckTarget() // Add a custom prebuild target to run the VerifyGlobs script. cmake* cm = this->GetCMakeInstance(); if (cm->DoWriteGlobVerifyTarget()) { - cmCustomCommandLine verifyCommandLine; - verifyCommandLine.push_back(cmSystemTools::GetCMakeCommand()); - verifyCommandLine.push_back("-P"); - verifyCommandLine.push_back(cm->GetGlobVerifyScript()); - cmCustomCommandLines verifyCommandLines; - verifyCommandLines.push_back(verifyCommandLine); + cmCustomCommandLines verifyCommandLines = cmMakeSingleCommandLine( + { cmSystemTools::GetCMakeCommand(), "-P", cm->GetGlobVerifyScript() }); std::vector<std::string> byproducts; byproducts.push_back(cm->GetGlobVerifyStamp()); @@ -173,20 +170,13 @@ bool cmGlobalVisualStudio8Generator::AddCheckTarget() listFiles.erase(new_end, listFiles.end()); // Create a rule to re-run CMake. - cmCustomCommandLine commandLine; - commandLine.push_back(cmSystemTools::GetCMakeCommand()); std::string argS = cmStrCat("-S", lg->GetSourceDirectory()); - commandLine.push_back(argS); std::string argB = cmStrCat("-B", lg->GetBinaryDirectory()); - commandLine.push_back(argB); - commandLine.push_back("--check-stamp-list"); - commandLine.push_back(stampList.c_str()); - commandLine.push_back("--vs-solution-file"); std::string const sln = lg->GetBinaryDirectory() + "/" + lg->GetProjectName() + ".sln"; - commandLine.push_back(sln); - cmCustomCommandLines commandLines; - commandLines.push_back(commandLine); + cmCustomCommandLines commandLines = cmMakeSingleCommandLine( + { cmSystemTools::GetCMakeCommand(), argS, argB, "--check-stamp-list", + stampList, "--vs-solution-file", sln }); // Add the rule. Note that we cannot use the CMakeLists.txt // file as the main dependency because it would get diff --git a/Source/cmGlobalVisualStudioGenerator.cxx b/Source/cmGlobalVisualStudioGenerator.cxx index 6e0b804..a0ce740 100644 --- a/Source/cmGlobalVisualStudioGenerator.cxx +++ b/Source/cmGlobalVisualStudioGenerator.cxx @@ -13,6 +13,7 @@ #include "cmAlgorithms.h" #include "cmCallVisualStudioMacro.h" #include "cmCustomCommand.h" +#include "cmCustomCommandLines.h" #include "cmGeneratedFileStream.h" #include "cmGeneratorTarget.h" #include "cmLocalVisualStudioGenerator.h" @@ -900,17 +901,11 @@ void cmGlobalVisualStudioGenerator::AddSymbolExportCommand( std::string obj_dir = gt->ObjectDirectory; std::string cmakeCommand = cmSystemTools::GetCMakeCommand(); cmSystemTools::ConvertToWindowsExtendedPath(cmakeCommand); - cmCustomCommandLine cmdl; - cmdl.push_back(cmakeCommand); - cmdl.push_back("-E"); - cmdl.push_back("__create_def"); - cmdl.push_back(mdi->DefFile); std::string obj_dir_expanded = obj_dir; cmSystemTools::ReplaceString(obj_dir_expanded, this->GetCMakeCFGIntDir(), configName.c_str()); cmSystemTools::MakeDirectory(obj_dir_expanded); std::string const objs_file = obj_dir_expanded + "/objects.txt"; - cmdl.push_back(objs_file); cmGeneratedFileStream fout(objs_file.c_str()); if (!fout) { cmSystemTools::Error("could not open " + objs_file); @@ -948,8 +943,8 @@ void cmGlobalVisualStudioGenerator::AddSymbolExportCommand( fout << i->GetFullPath() << "\n"; } - cmCustomCommandLines commandLines; - commandLines.push_back(cmdl); + cmCustomCommandLines commandLines = cmMakeSingleCommandLine( + { cmakeCommand, "-E", "__create_def", mdi->DefFile, objs_file }); cmCustomCommand command(gt->Target->GetMakefile(), outputs, empty, empty, commandLines, "Auto build dll exports", "."); commands.push_back(command); diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index de04e84..4d41fd7 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -15,6 +15,7 @@ #include "cmComputeLinkInformation.h" #include "cmCustomCommand.h" #include "cmCustomCommandGenerator.h" +#include "cmCustomCommandLines.h" #include "cmDocumentationEntry.h" #include "cmGeneratedFileStream.h" #include "cmGeneratorExpression.h" @@ -500,22 +501,18 @@ void cmGlobalXCodeGenerator::AddExtraTargets( const char* no_working_directory = nullptr; std::vector<std::string> no_depends; cmTarget* allbuild = mf->AddUtilityCommand( - "ALL_BUILD", cmMakefile::TargetOrigin::Generator, true, no_depends, - no_working_directory, "echo", "Build all projects"); + "ALL_BUILD", cmMakefile::TargetOrigin::Generator, true, + no_working_directory, no_depends, + cmMakeSingleCommandLine({ "echo", "Build all projects" })); cmGeneratorTarget* allBuildGt = new cmGeneratorTarget(allbuild, root); root->AddGeneratorTarget(allBuildGt); // Add XCODE depend helper std::string dir = root->GetCurrentBinaryDirectory(); - cmCustomCommandLine makeHelper; - makeHelper.push_back("make"); - makeHelper.push_back("-C"); - makeHelper.push_back(dir); - makeHelper.push_back("-f"); - makeHelper.push_back(this->CurrentXCodeHackMakefile); - makeHelper.push_back("OBJDIR=$(OBJDIR)"); - makeHelper.push_back(""); // placeholder, see below + cmCustomCommandLines commandLines = cmMakeSingleCommandLine( + { "make", "-C", dir, "-f", this->CurrentXCodeHackMakefile, + "OBJDIR=$(OBJDIR)", /* placeholder, see below */ "" }); // Add ZERO_CHECK bool regenerate = !this->GlobalSettingIsOn("CMAKE_SUPPRESS_REGENERATION"); @@ -530,7 +527,8 @@ void cmGlobalXCodeGenerator::AddExtraTargets( cmSystemTools::ReplaceString(file, "\\ ", " "); cmTarget* check = mf->AddUtilityCommand( CMAKE_CHECK_BUILD_SYSTEM_TARGET, cmMakefile::TargetOrigin::Generator, - true, no_depends, no_working_directory, "make", "-f", file.c_str()); + true, no_working_directory, no_depends, + cmMakeSingleCommandLine({ "make", "-f", file })); cmGeneratorTarget* checkGt = new cmGeneratorTarget(check, root); root->AddGeneratorTarget(checkGt); @@ -555,10 +553,8 @@ void cmGlobalXCodeGenerator::AddExtraTargets( // this will make sure that when the next target is built // things are up-to-date if (target->GetType() == cmStateEnums::OBJECT_LIBRARY) { - makeHelper.back() = // fill placeholder + commandLines.front().back() = // fill placeholder this->PostBuildMakeTarget(target->GetName(), "$(CONFIGURATION)"); - cmCustomCommandLines commandLines; - commandLines.push_back(makeHelper); std::vector<std::string> no_byproducts; gen->GetMakefile()->AddCustomCommandToTarget( target->GetName(), no_byproducts, no_depends, commandLines, @@ -1440,19 +1436,14 @@ void cmGlobalXCodeGenerator::CreateCustomCommands( if (gtgt->GetType() == cmStateEnums::SHARED_LIBRARY && !gtgt->IsFrameworkOnApple()) { - cmCustomCommandLines cmd; - cmd.resize(1); - cmd[0].push_back(cmSystemTools::GetCMakeCommand()); - cmd[0].push_back("-E"); - cmd[0].push_back("cmake_symlink_library"); std::string str_file = cmStrCat("$<TARGET_FILE:", gtgt->GetName(), '>'); std::string str_so_file = cmStrCat("$<TARGET_SONAME_FILE:", gtgt->GetName(), '>'); std::string str_link_file = cmStrCat("$<TARGET_LINKER_FILE:", gtgt->GetName(), '>'); - cmd[0].push_back(str_file); - cmd[0].push_back(str_so_file); - cmd[0].push_back(str_link_file); + cmCustomCommandLines cmd = cmMakeSingleCommandLine( + { cmSystemTools::GetCMakeCommand(), "-E", "cmake_symlink_library", + str_file, str_so_file, str_link_file }); cmCustomCommand command(this->CurrentMakefile, std::vector<std::string>(), std::vector<std::string>(), diff --git a/Source/cmInstallCommand.cxx b/Source/cmInstallCommand.cxx index 9b931f7..e7bb1ac 100644 --- a/Source/cmInstallCommand.cxx +++ b/Source/cmInstallCommand.cxx @@ -293,9 +293,8 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args) if (!unknownArgs.empty()) { // Unknown argument. - std::ostringstream e; - e << "TARGETS given unknown argument \"" << unknownArgs[0] << "\"."; - this->SetError(e.str()); + this->SetError( + cmStrCat("TARGETS given unknown argument \"", unknownArgs[0], "\".")); return false; } @@ -391,9 +390,8 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args) for (std::string const& tgt : targetList) { if (this->Makefile->IsAlias(tgt)) { - std::ostringstream e; - e << "TARGETS given target \"" << tgt << "\" which is an alias."; - this->SetError(e.str()); + this->SetError( + cmStrCat("TARGETS given target \"", tgt, "\" which is an alias.")); return false; } // Lookup this target in the current directory. @@ -414,19 +412,17 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args) target->GetType() != cmStateEnums::MODULE_LIBRARY && target->GetType() != cmStateEnums::OBJECT_LIBRARY && target->GetType() != cmStateEnums::INTERFACE_LIBRARY) { - std::ostringstream e; - e << "TARGETS given target \"" << tgt - << "\" which is not an executable, library, or module."; - this->SetError(e.str()); + this->SetError( + cmStrCat("TARGETS given target \"", tgt, + "\" which is not an executable, library, or module.")); return false; } // Store the target in the list to be installed. targets.push_back(target); } else { // Did not find the target. - std::ostringstream e; - e << "TARGETS given target \"" << tgt << "\" which does not exist."; - this->SetError(e.str()); + this->SetError( + cmStrCat("TARGETS given target \"", tgt, "\" which does not exist.")); return false; } } @@ -507,11 +503,10 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args) frameworkGenerator = CreateInstallTargetGenerator( target, frameworkArgs, false, this->Makefile->GetBacktrace()); } else { - std::ostringstream e; - e << "TARGETS given no FRAMEWORK DESTINATION for shared library " - "FRAMEWORK target \"" - << target.GetName() << "\"."; - this->SetError(e.str()); + this->SetError( + cmStrCat("TARGETS given no FRAMEWORK DESTINATION for shared " + "library FRAMEWORK target \"", + target.GetName(), "\".")); return false; } } else { @@ -549,11 +544,11 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args) frameworkGenerator = CreateInstallTargetGenerator( target, frameworkArgs, false, this->Makefile->GetBacktrace()); } else { - std::ostringstream e; - e << "TARGETS given no FRAMEWORK DESTINATION for static library " - "FRAMEWORK target \"" - << target.GetName() << "\"."; - this->SetError(e.str()); + this->SetError( + cmStrCat("TARGETS given no FRAMEWORK DESTINATION for static " + "library FRAMEWORK target \"", + target.GetName(), "\".")); + return false; } } else { @@ -572,10 +567,10 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args) namelinkOnly = (namelinkMode == cmInstallTargetGenerator::NamelinkModeOnly); } else { - std::ostringstream e; - e << "TARGETS given no LIBRARY DESTINATION for module target \"" - << target.GetName() << "\"."; - this->SetError(e.str()); + this->SetError( + cmStrCat("TARGETS given no LIBRARY DESTINATION for module " + "target \"", + target.GetName(), "\".")); return false; } } break; @@ -586,10 +581,9 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args) std::string reason; if (!this->Makefile->GetGlobalGenerator() ->HasKnownObjectFileLocation(&reason)) { - std::ostringstream e; - e << "TARGETS given OBJECT library \"" << target.GetName() - << "\" whose objects may not be installed" << reason << "."; - this->SetError(e.str()); + this->SetError( + cmStrCat("TARGETS given OBJECT library \"", target.GetName(), + "\" whose objects may not be installed", reason, ".")); return false; } @@ -619,11 +613,9 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args) } } if (!bundleGenerator) { - std::ostringstream e; - e << "TARGETS given no BUNDLE DESTINATION for MACOSX_BUNDLE " - "executable target \"" - << target.GetName() << "\"."; - this->SetError(e.str()); + this->SetError(cmStrCat("TARGETS given no BUNDLE DESTINATION for " + "MACOSX_BUNDLE executable target \"", + target.GetName(), "\".")); return false; } } else { @@ -708,10 +700,10 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args) resourceGenerator = CreateInstallFilesGenerator( this->Makefile, absFiles, resourceArgs, false); } else { - std::ostringstream e; - e << "INSTALL TARGETS - target " << target.GetName() << " has " - << "RESOURCE files but no RESOURCE DESTINATION."; - cmSystemTools::Message(e.str(), "Warning"); + cmSystemTools::Message( + cmStrCat("INSTALL TARGETS - target ", target.GetName(), + " has RESOURCE files but no RESOURCE DESTINATION."), + "Warning"); } } } @@ -820,17 +812,15 @@ bool cmInstallCommand::HandleFilesMode(std::vector<std::string> const& args) if (!unknownArgs.empty()) { // Unknown argument. - std::ostringstream e; - e << args[0] << " given unknown argument \"" << unknownArgs[0] << "\"."; - this->SetError(e.str()); + this->SetError( + cmStrCat(args[0], " given unknown argument \"", unknownArgs[0], "\".")); return false; } std::string type = ica.GetType(); if (!type.empty() && allowedTypes.count(type) == 0) { - std::ostringstream e; - e << args[0] << " given non-type \"" << type << "\" with TYPE argument."; - this->SetError(e.str()); + this->SetError( + cmStrCat(args[0], " given non-type \"", type, "\" with TYPE argument.")); return false; } @@ -843,9 +833,8 @@ bool cmInstallCommand::HandleFilesMode(std::vector<std::string> const& args) if (!ica.GetRename().empty() && filesVector.size() > 1) { // The rename option works only with one file. - std::ostringstream e; - e << args[0] << " given RENAME option with more than one file."; - this->SetError(e.str()); + this->SetError( + cmStrCat(args[0], " given RENAME option with more than one file.")); return false; } @@ -897,20 +886,16 @@ bool cmInstallCommand::HandleFilesMode(std::vector<std::string> const& args) } if (!type.empty() && !ica.GetDestination().empty()) { - std::ostringstream e; - e << args[0] - << " given both TYPE and DESTINATION arguments. You may only specify " - "one."; - this->SetError(e.str()); + this->SetError(cmStrCat(args[0], + " given both TYPE and DESTINATION arguments. " + "You may only specify one.")); return false; } std::string destination = this->GetDestinationForType(&ica, type); if (destination.empty()) { // A destination is required. - std::ostringstream e; - e << args[0] << " given no DESTINATION!"; - this->SetError(e.str()); + this->SetError(cmStrCat(args[0], " given no DESTINATION!")); return false; } @@ -959,10 +944,8 @@ bool cmInstallCommand::HandleDirectoryMode( for (unsigned int i = 1; i < args.size(); ++i) { if (args[i] == "DESTINATION") { if (in_match_mode) { - std::ostringstream e; - e << args[0] << " does not allow \"" << args[i] - << "\" after PATTERN or REGEX."; - this->SetError(e.str()); + this->SetError(cmStrCat(args[0], " does not allow \"", args[i], + "\" after PATTERN or REGEX.")); return false; } @@ -970,10 +953,8 @@ bool cmInstallCommand::HandleDirectoryMode( doing = DoingDestination; } else if (args[i] == "TYPE") { if (in_match_mode) { - std::ostringstream e; - e << args[0] << " does not allow \"" << args[i] - << "\" after PATTERN or REGEX."; - this->SetError(e.str()); + this->SetError(cmStrCat(args[0], " does not allow \"", args[i], + "\" after PATTERN or REGEX.")); return false; } @@ -981,10 +962,8 @@ bool cmInstallCommand::HandleDirectoryMode( doing = DoingType; } else if (args[i] == "OPTIONAL") { if (in_match_mode) { - std::ostringstream e; - e << args[0] << " does not allow \"" << args[i] - << "\" after PATTERN or REGEX."; - this->SetError(e.str()); + this->SetError(cmStrCat(args[0], " does not allow \"", args[i], + "\" after PATTERN or REGEX.")); return false; } @@ -993,10 +972,8 @@ bool cmInstallCommand::HandleDirectoryMode( doing = DoingNone; } else if (args[i] == "MESSAGE_NEVER") { if (in_match_mode) { - std::ostringstream e; - e << args[0] << " does not allow \"" << args[i] - << "\" after PATTERN or REGEX."; - this->SetError(e.str()); + this->SetError(cmStrCat(args[0], " does not allow \"", args[i], + "\" after PATTERN or REGEX.")); return false; } @@ -1014,20 +991,16 @@ bool cmInstallCommand::HandleDirectoryMode( } else if (args[i] == "EXCLUDE") { // Add this property to the current match rule. if (!in_match_mode || doing == DoingPattern || doing == DoingRegex) { - std::ostringstream e; - e << args[0] << " does not allow \"" << args[i] - << "\" before a PATTERN or REGEX is given."; - this->SetError(e.str()); + this->SetError(cmStrCat(args[0], " does not allow \"", args[i], + "\" before a PATTERN or REGEX is given.")); return false; } literal_args += " EXCLUDE"; doing = DoingNone; } else if (args[i] == "PERMISSIONS") { if (!in_match_mode) { - std::ostringstream e; - e << args[0] << " does not allow \"" << args[i] - << "\" before a PATTERN or REGEX is given."; - this->SetError(e.str()); + this->SetError(cmStrCat(args[0], " does not allow \"", args[i], + "\" before a PATTERN or REGEX is given.")); return false; } @@ -1036,10 +1009,8 @@ bool cmInstallCommand::HandleDirectoryMode( doing = DoingPermsMatch; } else if (args[i] == "FILE_PERMISSIONS") { if (in_match_mode) { - std::ostringstream e; - e << args[0] << " does not allow \"" << args[i] - << "\" after PATTERN or REGEX."; - this->SetError(e.str()); + this->SetError(cmStrCat(args[0], " does not allow \"", args[i], + "\" after PATTERN or REGEX.")); return false; } @@ -1047,10 +1018,8 @@ bool cmInstallCommand::HandleDirectoryMode( doing = DoingPermsFile; } else if (args[i] == "DIRECTORY_PERMISSIONS") { if (in_match_mode) { - std::ostringstream e; - e << args[0] << " does not allow \"" << args[i] - << "\" after PATTERN or REGEX."; - this->SetError(e.str()); + this->SetError(cmStrCat(args[0], " does not allow \"", args[i], + "\" after PATTERN or REGEX.")); return false; } @@ -1058,10 +1027,8 @@ bool cmInstallCommand::HandleDirectoryMode( doing = DoingPermsDir; } else if (args[i] == "USE_SOURCE_PERMISSIONS") { if (in_match_mode) { - std::ostringstream e; - e << args[0] << " does not allow \"" << args[i] - << "\" after PATTERN or REGEX."; - this->SetError(e.str()); + this->SetError(cmStrCat(args[0], " does not allow \"", args[i], + "\" after PATTERN or REGEX.")); return false; } @@ -1070,10 +1037,8 @@ bool cmInstallCommand::HandleDirectoryMode( doing = DoingNone; } else if (args[i] == "FILES_MATCHING") { if (in_match_mode) { - std::ostringstream e; - e << args[0] << " does not allow \"" << args[i] - << "\" after PATTERN or REGEX."; - this->SetError(e.str()); + this->SetError(cmStrCat(args[0], " does not allow \"", args[i], + "\" after PATTERN or REGEX.")); return false; } @@ -1082,10 +1047,8 @@ bool cmInstallCommand::HandleDirectoryMode( doing = DoingNone; } else if (args[i] == "CONFIGURATIONS") { if (in_match_mode) { - std::ostringstream e; - e << args[0] << " does not allow \"" << args[i] - << "\" after PATTERN or REGEX."; - this->SetError(e.str()); + this->SetError(cmStrCat(args[0], " does not allow \"", args[i], + "\" after PATTERN or REGEX.")); return false; } @@ -1093,10 +1056,8 @@ bool cmInstallCommand::HandleDirectoryMode( doing = DoingConfigurations; } else if (args[i] == "COMPONENT") { if (in_match_mode) { - std::ostringstream e; - e << args[0] << " does not allow \"" << args[i] - << "\" after PATTERN or REGEX."; - this->SetError(e.str()); + this->SetError(cmStrCat(args[0], " does not allow \"", args[i], + "\" after PATTERN or REGEX.")); return false; } @@ -1104,10 +1065,8 @@ bool cmInstallCommand::HandleDirectoryMode( doing = DoingComponent; } else if (args[i] == "EXCLUDE_FROM_ALL") { if (in_match_mode) { - std::ostringstream e; - e << args[0] << " does not allow \"" << args[i] - << "\" after PATTERN or REGEX."; - this->SetError(e.str()); + this->SetError(cmStrCat(args[0], " does not allow \"", args[i], + "\" after PATTERN or REGEX.")); return false; } exclude_from_all = true; @@ -1124,10 +1083,8 @@ bool cmInstallCommand::HandleDirectoryMode( // Make sure the name is a directory. if (cmSystemTools::FileExists(dir) && !cmSystemTools::FileIsDirectory(dir)) { - std::ostringstream e; - e << args[0] << " given non-directory \"" << args[i] - << "\" to install."; - this->SetError(e.str()); + this->SetError(cmStrCat(args[0], " given non-directory \"", args[i], + "\" to install.")); return false; } @@ -1140,10 +1097,8 @@ bool cmInstallCommand::HandleDirectoryMode( doing = DoingNone; } else if (doing == DoingType) { if (allowedTypes.count(args[i]) == 0) { - std::ostringstream e; - e << args[0] << " given non-type \"" << args[i] - << "\" with TYPE argument."; - this->SetError(e.str()); + this->SetError(cmStrCat(args[0], " given non-type \"", args[i], + "\" with TYPE argument.")); return false; } @@ -1179,36 +1134,30 @@ bool cmInstallCommand::HandleDirectoryMode( // Check the requested permission. if (!cmInstallCommandArguments::CheckPermissions(args[i], permissions_file)) { - std::ostringstream e; - e << args[0] << " given invalid file permission \"" << args[i] - << "\"."; - this->SetError(e.str()); + this->SetError(cmStrCat(args[0], " given invalid file permission \"", + args[i], "\".")); return false; } } else if (doing == DoingPermsDir) { // Check the requested permission. if (!cmInstallCommandArguments::CheckPermissions(args[i], permissions_dir)) { - std::ostringstream e; - e << args[0] << " given invalid directory permission \"" << args[i] - << "\"."; - this->SetError(e.str()); + this->SetError(cmStrCat( + args[0], " given invalid directory permission \"", args[i], "\".")); return false; } } else if (doing == DoingPermsMatch) { // Check the requested permission. if (!cmInstallCommandArguments::CheckPermissions(args[i], literal_args)) { - std::ostringstream e; - e << args[0] << " given invalid permission \"" << args[i] << "\"."; - this->SetError(e.str()); + this->SetError( + cmStrCat(args[0], " given invalid permission \"", args[i], "\".")); return false; } } else { // Unknown argument. - std::ostringstream e; - e << args[0] << " given unknown argument \"" << args[i] << "\"."; - this->SetError(e.str()); + this->SetError( + cmStrCat(args[0], " given unknown argument \"", args[i], "\".")); return false; } } @@ -1226,19 +1175,15 @@ bool cmInstallCommand::HandleDirectoryMode( if (!destination) { if (type.empty()) { // A destination is required. - std::ostringstream e; - e << args[0] << " given no DESTINATION!"; - this->SetError(e.str()); + this->SetError(cmStrCat(args[0], " given no DESTINATION!")); return false; } destinationStr = this->GetDestinationForType(nullptr, type); destination = destinationStr.c_str(); } else if (!type.empty()) { - std::ostringstream e; - e << args[0] - << " given both TYPE and DESTINATION arguments. You may only specify " - "one."; - this->SetError(e.str()); + this->SetError(cmStrCat(args[0], + " given both TYPE and DESTINATION " + "arguments. You may only specify one.")); return false; } @@ -1280,9 +1225,8 @@ bool cmInstallCommand::HandleExportAndroidMKMode( if (!unknownArgs.empty()) { // Unknown argument. - std::ostringstream e; - e << args[0] << " given unknown argument \"" << unknownArgs[0] << "\"."; - this->SetError(e.str()); + this->SetError( + cmStrCat(args[0], " given unknown argument \"", unknownArgs[0], "\".")); return false; } @@ -1293,39 +1237,35 @@ bool cmInstallCommand::HandleExportAndroidMKMode( // Make sure there is a destination. if (ica.GetDestination().empty()) { // A destination is required. - std::ostringstream e; - e << args[0] << " given no DESTINATION!"; - this->SetError(e.str()); + this->SetError(cmStrCat(args[0], " given no DESTINATION!")); return false; } // Check the file name. std::string fname = filename; if (fname.find_first_of(":/\\") != std::string::npos) { - std::ostringstream e; - e << args[0] << " given invalid export file name \"" << fname << "\". " - << "The FILE argument may not contain a path. " - << "Specify the path in the DESTINATION argument."; - this->SetError(e.str()); + this->SetError(cmStrCat(args[0], " given invalid export file name \"", + fname, + "\". The FILE argument may not contain a path. " + "Specify the path in the DESTINATION argument.")); return false; } // Check the file extension. if (!fname.empty() && cmSystemTools::GetFilenameLastExtension(fname) != ".mk") { - std::ostringstream e; - e << args[0] << " given invalid export file name \"" << fname << "\". " - << "The FILE argument must specify a name ending in \".mk\"."; - this->SetError(e.str()); + this->SetError(cmStrCat( + args[0], " given invalid export file name \"", fname, + R"(". The FILE argument must specify a name ending in ".mk".)")); return false; } if (fname.find_first_of(":/\\") != std::string::npos) { - std::ostringstream e; - e << args[0] << " given export name \"" << exp << "\". " - << "This name cannot be safely converted to a file name. " - << "Specify a different export name or use the FILE option to set " - << "a file name explicitly."; - this->SetError(e.str()); + this->SetError( + cmStrCat(args[0], " given export name \"", exp, + "\". " + "This name cannot be safely converted to a file name. " + "Specify a different export name or use the FILE option to set " + "a file name explicitly.")); return false; } // Use the default name @@ -1375,9 +1315,8 @@ bool cmInstallCommand::HandleExportMode(std::vector<std::string> const& args) if (!unknownArgs.empty()) { // Unknown argument. - std::ostringstream e; - e << args[0] << " given unknown argument \"" << unknownArgs[0] << "\"."; - this->SetError(e.str()); + this->SetError( + cmStrCat(args[0], " given unknown argument \"", unknownArgs[0], "\".")); return false; } @@ -1388,30 +1327,28 @@ bool cmInstallCommand::HandleExportMode(std::vector<std::string> const& args) // Make sure there is a destination. if (ica.GetDestination().empty()) { // A destination is required. - std::ostringstream e; - e << args[0] << " given no DESTINATION!"; - this->SetError(e.str()); + this->SetError(cmStrCat(args[0], " given no DESTINATION!")); return false; } // Check the file name. std::string fname = filename; if (fname.find_first_of(":/\\") != std::string::npos) { - std::ostringstream e; - e << args[0] << " given invalid export file name \"" << fname << "\". " - << "The FILE argument may not contain a path. " - << "Specify the path in the DESTINATION argument."; - this->SetError(e.str()); + this->SetError(cmStrCat(args[0], " given invalid export file name \"", + fname, + "\". " + "The FILE argument may not contain a path. " + "Specify the path in the DESTINATION argument.")); return false; } // Check the file extension. if (!fname.empty() && cmSystemTools::GetFilenameLastExtension(fname) != ".cmake") { - std::ostringstream e; - e << args[0] << " given invalid export file name \"" << fname << "\". " - << "The FILE argument must specify a name ending in \".cmake\"."; - this->SetError(e.str()); + this->SetError( + cmStrCat(args[0], " given invalid export file name \"", fname, + "\". " + "The FILE argument must specify a name ending in \".cmake\".")); return false; } @@ -1420,12 +1357,12 @@ bool cmInstallCommand::HandleExportMode(std::vector<std::string> const& args) fname = cmStrCat(exp, ".cmake"); if (fname.find_first_of(":/\\") != std::string::npos) { - std::ostringstream e; - e << args[0] << " given export name \"" << exp << "\". " - << "This name cannot be safely converted to a file name. " - << "Specify a different export name or use the FILE option to set " - << "a file name explicitly."; - this->SetError(e.str()); + this->SetError(cmStrCat( + args[0], " given export name \"", exp, + "\". " + "This name cannot be safely converted to a file name. " + "Specify a different export name or use the FILE option to set " + "a file name explicitly.")); return false; } } @@ -1441,12 +1378,10 @@ bool cmInstallCommand::HandleExportMode(std::vector<std::string> const& args) tgt->GetPolicyStatusCMP0022() != cmPolicies::OLD); if (!newCMP0022Behavior) { - std::ostringstream e; - e << "INSTALL(EXPORT) given keyword \"" - << "EXPORT_LINK_INTERFACE_LIBRARIES" - << "\", but target \"" << te->TargetName - << "\" does not have policy CMP0022 set to NEW."; - this->SetError(e.str()); + this->SetError(cmStrCat( + "INSTALL(EXPORT) given keyword \"" + "EXPORT_LINK_INTERFACE_LIBRARIES\", but target \"", + te->TargetName, "\" does not have policy CMP0022 set to NEW.")); return false; } } @@ -1480,9 +1415,8 @@ bool cmInstallCommand::MakeFilesFullPath( // Make sure the file is not a directory. if (gpos == std::string::npos && cmSystemTools::FileIsDirectory(file)) { - std::ostringstream e; - e << modeName << " given directory \"" << relFile << "\" to install."; - this->SetError(e.str()); + this->SetError( + cmStrCat(modeName, " given directory \"", relFile, "\" to install.")); return false; } // Store the file for installation. diff --git a/Source/cmListCommand.cxx b/Source/cmListCommand.cxx index 9487e3b..826abf5 100644 --- a/Source/cmListCommand.cxx +++ b/Source/cmListCommand.cxx @@ -158,10 +158,8 @@ bool HandleGetCommand(std::vector<std::string> const& args, item = static_cast<int>(nitem) + item; } if (item < 0 || nitem <= static_cast<size_t>(item)) { - std::ostringstream str; - str << "index: " << item << " out of range (-" << nitem << ", " - << nitem - 1 << ")"; - status.SetError(str.str()); + status.SetError(cmStrCat("index: ", item, " out of range (-", nitem, + ", ", nitem - 1, ")")); return false; } value += varArgsExpanded[item]; @@ -366,9 +364,7 @@ bool HandleInsertCommand(std::vector<std::string> const& args, if ((!GetList(varArgsExpanded, listName, status.GetMakefile()) || varArgsExpanded.empty()) && item != 0) { - std::ostringstream str; - str << "index: " << item << " out of range (0, 0)"; - status.SetError(str.str()); + status.SetError(cmStrCat("index: ", item, " out of range (0, 0)")); return false; } @@ -378,10 +374,9 @@ bool HandleInsertCommand(std::vector<std::string> const& args, item = static_cast<int>(nitem) + item; } if (item < 0 || nitem < static_cast<size_t>(item)) { - std::ostringstream str; - str << "index: " << item << " out of range (-" << varArgsExpanded.size() - << ", " << varArgsExpanded.size() << ")"; - status.SetError(str.str()); + status.SetError(cmStrCat("index: ", item, " out of range (-", + varArgsExpanded.size(), ", ", + varArgsExpanded.size(), ")")); return false; } } @@ -398,10 +393,8 @@ bool HandleJoinCommand(std::vector<std::string> const& args, cmExecutionStatus& status) { if (args.size() != 4) { - std::ostringstream error; - error << "sub-command JOIN requires three arguments (" << args.size() - 1 - << " found)."; - status.SetError(error.str()); + status.SetError(cmStrCat("sub-command JOIN requires three arguments (", + args.size() - 1, " found).")); return false; } @@ -596,11 +589,9 @@ protected: index = static_cast<int>(count) + index; } if (index < 0 || count <= static_cast<std::size_t>(index)) { - std::ostringstream str; - str << "sub-command TRANSFORM, selector " << this->Tag - << ", index: " << index << " out of range (-" << count << ", " - << count - 1 << ")."; - throw transform_error(str.str()); + throw transform_error(cmStrCat( + "sub-command TRANSFORM, selector ", this->Tag, ", index: ", index, + " out of range (-", count, ", ", count - 1, ").")); } return index; } @@ -681,17 +672,14 @@ public: makefile->ClearMatches(); if (!this->ReplaceHelper.IsRegularExpressionValid()) { - std::ostringstream error; - error - << "sub-command TRANSFORM, action REPLACE: Failed to compile regex \"" - << arguments[0] << "\"."; - throw transform_error(error.str()); + throw transform_error( + cmStrCat("sub-command TRANSFORM, action REPLACE: Failed to compile " + "regex \"", + arguments[0], "\".")); } if (!this->ReplaceHelper.IsReplaceExpressionValid()) { - std::ostringstream error; - error << "sub-command TRANSFORM, action REPLACE: " - << this->ReplaceHelper.GetError() << "."; - throw transform_error(error.str()); + throw transform_error(cmStrCat("sub-command TRANSFORM, action REPLACE: ", + this->ReplaceHelper.GetError(), ".")); } } @@ -701,10 +689,8 @@ public: std::string output; if (!this->ReplaceHelper.Replace(input, output)) { - std::ostringstream error; - error << "sub-command TRANSFORM, action REPLACE: " - << this->ReplaceHelper.GetError() << "."; - throw transform_error(error.str()); + throw transform_error(cmStrCat("sub-command TRANSFORM, action REPLACE: ", + this->ReplaceHelper.GetError(), ".")); } return output; @@ -839,19 +825,17 @@ bool HandleTransformCommand(std::vector<std::string> const& args, auto descriptor = descriptors.find(args[index]); if (descriptor == descriptors.end()) { - std::ostringstream error; - error << " sub-command TRANSFORM, " << args[index] << " invalid action."; - status.SetError(error.str()); + status.SetError( + cmStrCat(" sub-command TRANSFORM, ", args[index], " invalid action.")); return false; } // Action arguments index += 1; if (args.size() < index + descriptor->Arity) { - std::ostringstream error; - error << "sub-command TRANSFORM, action " << descriptor->Name - << " expects " << descriptor->Arity << " argument(s)."; - status.SetError(error.str()); + status.SetError(cmStrCat("sub-command TRANSFORM, action ", + descriptor->Name, " expects ", descriptor->Arity, + " argument(s).")); return false; } @@ -881,10 +865,10 @@ bool HandleTransformCommand(std::vector<std::string> const& args, while (args.size() > index) { if ((args[index] == REGEX || args[index] == AT || args[index] == FOR) && command.Selector) { - std::ostringstream error; - error << "sub-command TRANSFORM, selector already specified (" - << command.Selector->Tag << ")."; - status.SetError(error.str()); + status.SetError( + cmStrCat("sub-command TRANSFORM, selector already specified (", + command.Selector->Tag, ").")); + return false; } @@ -898,11 +882,10 @@ bool HandleTransformCommand(std::vector<std::string> const& args, command.Selector = cm::make_unique<TransformSelectorRegex>(args[index]); if (!command.Selector->Validate()) { - std::ostringstream error; - error << "sub-command TRANSFORM, selector REGEX failed to compile " - "regex \""; - error << args[index] << "\"."; - status.SetError(error.str()); + status.SetError( + cmStrCat("sub-command TRANSFORM, selector REGEX failed to compile " + "regex \"", + args[index], "\".")); return false; } @@ -1020,11 +1003,9 @@ bool HandleTransformCommand(std::vector<std::string> const& args, continue; } - std::ostringstream error; - error << "sub-command TRANSFORM, '" - << cmJoin(cmMakeRange(args).advance(index), " ") - << "': unexpected argument(s)."; - status.SetError(error.str()); + status.SetError(cmStrCat("sub-command TRANSFORM, '", + cmJoin(cmMakeRange(args).advance(index), " "), + "': unexpected argument(s).")); return false; } @@ -1261,10 +1242,8 @@ bool HandleSublistCommand(std::vector<std::string> const& args, cmExecutionStatus& status) { if (args.size() != 5) { - std::ostringstream error; - error << "sub-command SUBLIST requires four arguments (" << args.size() - 1 - << " found)."; - status.SetError(error.str()); + status.SetError(cmStrCat("sub-command SUBLIST requires four arguments (", + args.size() - 1, " found).")); return false; } @@ -1285,16 +1264,12 @@ bool HandleSublistCommand(std::vector<std::string> const& args, using size_type = decltype(varArgsExpanded)::size_type; if (start < 0 || size_type(start) >= varArgsExpanded.size()) { - std::ostringstream error; - error << "begin index: " << start << " is out of range 0 - " - << varArgsExpanded.size() - 1; - status.SetError(error.str()); + status.SetError(cmStrCat("begin index: ", start, " is out of range 0 - ", + varArgsExpanded.size() - 1)); return false; } if (length < -1) { - std::ostringstream error; - error << "length: " << length << " should be -1 or greater"; - status.SetError(error.str()); + status.SetError(cmStrCat("length: ", length, " should be -1 or greater")); return false; } @@ -1344,10 +1319,8 @@ bool HandleRemoveAtCommand(std::vector<std::string> const& args, item = static_cast<int>(nitem) + item; } if (item < 0 || nitem <= static_cast<size_t>(item)) { - std::ostringstream str; - str << "index: " << item << " out of range (-" << nitem << ", " - << nitem - 1 << ")"; - status.SetError(str.str()); + status.SetError(cmStrCat("index: ", item, " out of range (-", nitem, + ", ", nitem - 1, ")")); return false; } removed.push_back(static_cast<size_t>(item)); diff --git a/Source/cmLoadCommandCommand.cxx b/Source/cmLoadCommandCommand.cxx index 66fdada..6f5df46 100644 --- a/Source/cmLoadCommandCommand.cxx +++ b/Source/cmLoadCommandCommand.cxx @@ -7,7 +7,7 @@ #include <cstdio> #include <cstdlib> #include <cstring> -#include <sstream> + #include <utility> #include "cm_memory.hxx" @@ -207,9 +207,8 @@ bool cmLoadCommandCommand(std::vector<std::string> const& args, // Try to find the program. std::string fullPath = cmSystemTools::FindFile(moduleName, path); if (fullPath.empty()) { - std::ostringstream e; - e << "Attempt to load command failed from file \"" << moduleName << "\""; - status.SetError(e.str()); + status.SetError(cmStrCat("Attempt to load command failed from file \"", + moduleName, "\"")); return false; } diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index 5bbb83c..afcd69f 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -4,7 +4,9 @@ #include "cmAlgorithms.h" #include "cmComputeLinkInformation.h" +#include "cmCustomCommand.h" #include "cmCustomCommandGenerator.h" +#include "cmCustomCommandLines.h" #include "cmGeneratedFileStream.h" #include "cmGeneratorExpression.h" #include "cmGeneratorExpressionEvaluationFile.h" @@ -2255,23 +2257,124 @@ void cmLocalGenerator::AddPchDependencies(cmGeneratorTarget* target, return; } + const char* pchReuseFrom = + target->GetProperty("PRECOMPILE_HEADERS_REUSE_FROM"); + auto pch_sf = this->Makefile->GetOrCreateSource( pchSource, false, cmSourceFileLocationKind::Known); std::string pchFile = pchHeader; if (!this->GetGlobalGenerator()->IsXcode()) { + if (!pchReuseFrom) { + target->AddSource(pchSource, true); + } + // Exclude the pch files from linking if (this->Makefile->IsOn("CMAKE_LINK_PCH")) { - cmSystemTools::ReplaceString(pchFile, (lang == "C" ? ".h" : ".hxx"), - pchExtension); - pch_sf->SetProperty("OBJECT_OUTPUTS", pchFile.c_str()); + + auto replaceExtension = [](const std::string& str, + const std::string& ext) -> std::string { + auto dot_pos = str.rfind('.'); + std::string result; + if (dot_pos != std::string::npos) { + result = str.substr(0, dot_pos); + } + result += ext; + return result; + }; + + if (!pchReuseFrom) { + std::string pchSourceObj = target->GetPchFileObject(config, lang); + + pchFile = replaceExtension(pchSourceObj, pchExtension); + pch_sf->SetProperty("OBJECT_OUTPUTS", pchFile.c_str()); + } else { + auto reuseTarget = + this->GlobalGenerator->FindGeneratorTarget(pchReuseFrom); + + if (this->Makefile->IsOn("CMAKE_PCH_COPY_COMPILE_PDB")) { + + const std::string pdb_prefix = + this->GetGlobalGenerator()->IsMultiConfig() + ? cmStrCat(this->GlobalGenerator->GetCMakeCFGIntDir(), "/") + : ""; + + const std::string target_compile_pdb_dir = + cmStrCat(target->GetLocalGenerator()->GetCurrentBinaryDirectory(), + "/", target->GetName(), ".dir/"); + + const std::string copy_script = + cmStrCat(target_compile_pdb_dir, "copy_idb_pdb.cmake"); + cmGeneratedFileStream file(copy_script); + + file << "# CMake generated file\n"; + for (auto extension : { ".pdb", ".idb" }) { + const std::string from_file = cmStrCat( + reuseTarget->GetLocalGenerator()->GetCurrentBinaryDirectory(), + "/", pchReuseFrom, ".dir/${PDB_PREFIX}", pchReuseFrom, + extension); + + const std::string to_dir = cmStrCat( + target->GetLocalGenerator()->GetCurrentBinaryDirectory(), "/", + target->GetName(), ".dir/${PDB_PREFIX}"); + + file << "if (EXISTS \"" << from_file << "\")\n"; + file << " file(COPY \"" << from_file << "\"" + << " DESTINATION \"" << to_dir << "\")\n"; + file << "endif()\n"; + } + + cmCustomCommandLines commandLines; + cmCustomCommandLine currentLine; + currentLine.push_back(cmSystemTools::GetCMakeCommand()); + currentLine.push_back(cmStrCat("-DPDB_PREFIX=", pdb_prefix)); + currentLine.push_back("-P"); + currentLine.push_back(copy_script); + commandLines.push_back(std::move(currentLine)); + + const std::string no_main_dependency; + const std::vector<std::string> no_deps; + const char* no_message = ""; + const char* no_current_dir = nullptr; + std::vector<std::string> no_byproducts; + + std::vector<std::string> outputs; + outputs.push_back(cmStrCat(target_compile_pdb_dir, pdb_prefix, + pchReuseFrom, ".pdb")); + + if (this->GetGlobalGenerator()->IsMultiConfig()) { + this->Makefile->AddCustomCommandToTarget( + target->GetName(), outputs, no_deps, commandLines, + cmTarget::PRE_BUILD, no_message, no_current_dir); + } else { + cmImplicitDependsList no_implicit_depends; + cmSourceFile* copy_rule = this->Makefile->AddCustomCommandToOutput( + outputs, no_byproducts, no_deps, no_main_dependency, + no_implicit_depends, commandLines, no_message, no_current_dir); + + if (copy_rule) { + target->AddSource(copy_rule->ResolveFullPath()); + } + } + + target->Target->SetProperty("COMPILE_PDB_OUTPUT_DIRECTORY", + target_compile_pdb_dir.c_str()); + } + + std::string pchSourceObj = reuseTarget->GetPchFileObject(config, lang); + + // Link to the pch object file + target->Target->SetProperty( + "LINK_FLAGS", + this->ConvertToOutputFormat(pchSourceObj, SHELL).c_str()); + + pchFile = replaceExtension(pchSourceObj, pchExtension); + } } else { pchFile += pchExtension; pch_sf->SetProperty("PCH_EXTENSION", pchExtension.c_str()); } - target->AddSource(pchSource, true); - for (auto& str : { std::ref(useOptionList), std::ref(createOptionList) }) { cmSystemTools::ReplaceString(str, "<PCH_HEADER>", pchHeader); cmSystemTools::ReplaceString(str, "<PCH_FILE>", pchFile); diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx index 6c7fb2b..026f494 100644 --- a/Source/cmLocalVisualStudio7Generator.cxx +++ b/Source/cmLocalVisualStudio7Generator.cxx @@ -92,11 +92,8 @@ void cmLocalVisualStudio7Generator::FixGlobalTargets() for (cmGeneratorTarget* l : tgts) { if (l->GetType() == cmStateEnums::GLOBAL_TARGET) { std::vector<std::string> no_depends; - cmCustomCommandLine force_command; - force_command.push_back("cd"); - force_command.push_back("."); - cmCustomCommandLines force_commands; - force_commands.push_back(force_command); + cmCustomCommandLines force_commands = + cmMakeSingleCommandLine({ "cd", "." }); std::string no_main_dependency; std::string force = cmStrCat(this->GetCurrentBinaryDirectory(), "/CMakeFiles/", l->GetName(), "_force"); @@ -246,21 +243,15 @@ cmSourceFile* cmLocalVisualStudio7Generator::CreateVCProjBuildRule() std::unique(listFiles.begin(), listFiles.end()); listFiles.erase(new_end, listFiles.end()); + std::string argS = cmStrCat("-S", this->GetSourceDirectory()); + std::string argB = cmStrCat("-B", this->GetBinaryDirectory()); std::string stampName = cmStrCat(this->GetCurrentBinaryDirectory(), "/CMakeFiles/generate.stamp"); - cmCustomCommandLine commandLine; - commandLine.push_back(cmSystemTools::GetCMakeCommand()); + cmCustomCommandLines commandLines = + cmMakeSingleCommandLine({ cmSystemTools::GetCMakeCommand(), argS, argB, + "--check-stamp-file", stampName }); std::string comment = cmStrCat("Building Custom Rule ", makefileIn); - std::string args; - args = cmStrCat("-S", this->GetSourceDirectory()); - commandLine.push_back(args); - args = cmStrCat("-B", this->GetBinaryDirectory()); - commandLine.push_back(args); - commandLine.push_back("--check-stamp-file"); - commandLine.push_back(stampName); - cmCustomCommandLines commandLines; - commandLines.push_back(commandLine); - const char* no_working_directory = 0; + const char* no_working_directory = nullptr; std::string fullpathStampName = cmSystemTools::CollapseFullPath(stampName.c_str()); this->Makefile->AddCustomCommandToOutput( diff --git a/Source/cmLocalVisualStudioGenerator.cxx b/Source/cmLocalVisualStudioGenerator.cxx index f3f2042..cec9c02 100644 --- a/Source/cmLocalVisualStudioGenerator.cxx +++ b/Source/cmLocalVisualStudioGenerator.cxx @@ -98,16 +98,11 @@ cmLocalVisualStudioGenerator::MaybeCreateImplibDir(cmGeneratorTarget* target, } // Add a pre-build event to create the directory. - cmCustomCommandLine command; - command.push_back(cmSystemTools::GetCMakeCommand()); - command.push_back("-E"); - command.push_back("make_directory"); - command.push_back(impDir); std::vector<std::string> no_output; std::vector<std::string> no_byproducts; std::vector<std::string> no_depends; - cmCustomCommandLines commands; - commands.push_back(command); + cmCustomCommandLines commands = cmMakeSingleCommandLine( + { cmSystemTools::GetCMakeCommand(), "-E", "make_directory", impDir }); pcc.reset(new cmCustomCommand(0, no_output, no_byproducts, no_depends, commands, 0, 0)); pcc->SetEscapeOldStyle(false); diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index 88d03f9..c593939 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -15,6 +15,8 @@ #include <sstream> #include <utility> +#include "cm_memory.hxx" + #include "cmAlgorithms.h" #include "cmCommandArgumentParserHelper.h" #include "cmCustomCommand.h" @@ -1026,7 +1028,7 @@ cmSourceFile* cmMakefile::AddCustomCommandToOutput( depends2.push_back(main_dependency); } - cmCustomCommand* cc = new cmCustomCommand( + std::unique_ptr<cmCustomCommand> cc = cm::make_unique<cmCustomCommand>( this, outputs, byproducts, depends2, commandLines, comment, workingDir); cc->SetEscapeOldStyle(escapeOldStyle); cc->SetEscapeAllowMakeVars(true); @@ -1035,7 +1037,7 @@ cmSourceFile* cmMakefile::AddCustomCommandToOutput( cc->SetCommandExpandLists(command_expand_lists); cc->SetDepfile(depfile); cc->SetJobPool(job_pool); - file->SetCustomCommand(cc); + file->SetCustomCommand(std::move(cc)); this->UpdateOutputToSourceMap(outputs, file, false); this->UpdateOutputToSourceMap(byproducts, file, true); } @@ -1173,35 +1175,6 @@ bool cmMakefile::AppendCustomCommandToOutput( cmTarget* cmMakefile::AddUtilityCommand( const std::string& utilityName, TargetOrigin origin, bool excludeFromAll, - const std::vector<std::string>& depends, const char* workingDirectory, - const char* command, const char* arg1, const char* arg2, const char* arg3, - const char* arg4) -{ - // Construct the command line for the custom command. - cmCustomCommandLine commandLine; - commandLine.push_back(command); - if (arg1) { - commandLine.push_back(arg1); - } - if (arg2) { - commandLine.push_back(arg2); - } - if (arg3) { - commandLine.push_back(arg3); - } - if (arg4) { - commandLine.push_back(arg4); - } - cmCustomCommandLines commandLines; - commandLines.push_back(std::move(commandLine)); - - // Call the real signature of this method. - return this->AddUtilityCommand(utilityName, origin, excludeFromAll, - workingDirectory, depends, commandLines); -} - -cmTarget* cmMakefile::AddUtilityCommand( - const std::string& utilityName, TargetOrigin origin, bool excludeFromAll, const char* workingDirectory, const std::vector<std::string>& depends, const cmCustomCommandLines& commandLines, bool escapeOldStyle, const char* comment, bool uses_terminal, bool command_expand_lists, diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h index 1944879..6d695a7 100644 --- a/Source/cmMakefile.h +++ b/Source/cmMakefile.h @@ -243,14 +243,6 @@ public: * Add a utility to the build. A utility target is a command that * is run every time the target is built. */ - cmTarget* AddUtilityCommand(const std::string& utilityName, - TargetOrigin origin, bool excludeFromAll, - const std::vector<std::string>& depends, - const char* workingDirectory, - const char* command, const char* arg1 = nullptr, - const char* arg2 = nullptr, - const char* arg3 = nullptr, - const char* arg4 = nullptr); cmTarget* AddUtilityCommand( const std::string& utilityName, TargetOrigin origin, bool excludeFromAll, const char* workingDirectory, const std::vector<std::string>& depends, diff --git a/Source/cmOptionCommand.cxx b/Source/cmOptionCommand.cxx index a0a0989..22e59ac 100644 --- a/Source/cmOptionCommand.cxx +++ b/Source/cmOptionCommand.cxx @@ -2,8 +2,6 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmOptionCommand.h" -#include <sstream> - #include "cmExecutionStatus.h" #include "cmMakefile.h" #include "cmMessageType.h" @@ -74,13 +72,13 @@ bool cmOptionCommand(std::vector<std::string> const& args, const auto* existsAfterSet = status.GetMakefile().GetStateSnapshot().GetDefinition(args[0]); if (!existsAfterSet) { - std::ostringstream w; - w << cmPolicies::GetPolicyWarning(cmPolicies::CMP0077) - << "\n" - "For compatibility with older versions of CMake, option " - "is clearing the normal variable '" - << args[0] << "'."; - status.GetMakefile().IssueMessage(MessageType::AUTHOR_WARNING, w.str()); + status.GetMakefile().IssueMessage( + MessageType::AUTHOR_WARNING, + cmStrCat(cmPolicies::GetPolicyWarning(cmPolicies::CMP0077), + "\n" + "For compatibility with older versions of CMake, option " + "is clearing the normal variable '", + args[0], "'.")); } } return true; diff --git a/Source/cmOrderDirectories.cxx b/Source/cmOrderDirectories.cxx index e1267ec..916a9f7 100644 --- a/Source/cmOrderDirectories.cxx +++ b/Source/cmOrderDirectories.cxx @@ -465,14 +465,14 @@ void cmOrderDirectories::FindImplicitConflicts() } // Warn about the conflicts. - std::ostringstream w; - w << "Cannot generate a safe " << this->Purpose << " for target " - << this->Target->GetName() - << " because files in some directories may conflict with " - << " libraries in implicit directories:\n" - << text << "Some of these libraries may not be found correctly."; this->GlobalGenerator->GetCMakeInstance()->IssueMessage( - MessageType::WARNING, w.str(), this->Target->GetBacktrace()); + MessageType::WARNING, + cmStrCat("Cannot generate a safe ", this->Purpose, " for target ", + this->Target->GetName(), + " because files in some directories may " + "conflict with libraries in implicit directories:\n", + text, "Some of these libraries may not be found correctly."), + this->Target->GetBacktrace()); } void cmOrderDirectories::OrderDirectories() diff --git a/Source/cmProjectCommand.cxx b/Source/cmProjectCommand.cxx index e74fff6..5fa6a21 100644 --- a/Source/cmProjectCommand.cxx +++ b/Source/cmProjectCommand.cxx @@ -8,7 +8,6 @@ #include <cstdio> #include <functional> #include <limits> -#include <sstream> #include <utility> #include "cmMakefile.h" @@ -320,10 +319,10 @@ bool cmProjectCommand::InitialPass(std::vector<std::string> const& args, } } if (!vw.empty()) { - std::ostringstream w; - w << cmPolicies::GetPolicyWarning(cmPolicies::CMP0048) - << "\nThe following variable(s) would be set to empty:" << vw; - this->Makefile->IssueMessage(MessageType::AUTHOR_WARNING, w.str()); + this->Makefile->IssueMessage( + MessageType::AUTHOR_WARNING, + cmStrCat(cmPolicies::GetPolicyWarning(cmPolicies::CMP0048), + "\nThe following variable(s) would be set to empty:", vw)); } } diff --git a/Source/cmQTWrapCPPCommand.cxx b/Source/cmQTWrapCPPCommand.cxx index 1a5602b..cc4df8f 100644 --- a/Source/cmQTWrapCPPCommand.cxx +++ b/Source/cmQTWrapCPPCommand.cxx @@ -2,8 +2,6 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmQTWrapCPPCommand.h" -#include <utility> - #include "cmCustomCommandLines.h" #include "cmExecutionStatus.h" #include "cmMakefile.h" @@ -65,14 +63,8 @@ bool cmQTWrapCPPCommand(std::vector<std::string> const& args, sourceListValue += newName; // Create the custom command to generate the file. - cmCustomCommandLine commandLine; - commandLine.push_back(moc_exe); - commandLine.push_back("-o"); - commandLine.push_back(newName); - commandLine.push_back(hname); - - cmCustomCommandLines commandLines; - commandLines.push_back(std::move(commandLine)); + cmCustomCommandLines commandLines = + cmMakeSingleCommandLine({ moc_exe, "-o", newName, hname }); std::vector<std::string> depends; depends.push_back(moc_exe); diff --git a/Source/cmQTWrapUICommand.cxx b/Source/cmQTWrapUICommand.cxx index b7b5efa..66c0228 100644 --- a/Source/cmQTWrapUICommand.cxx +++ b/Source/cmQTWrapUICommand.cxx @@ -2,8 +2,6 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmQTWrapUICommand.h" -#include <utility> - #include "cmCustomCommandLines.h" #include "cmExecutionStatus.h" #include "cmMakefile.h" @@ -76,31 +74,12 @@ bool cmQTWrapUICommand(std::vector<std::string> const& args, sourceListValue += mocName; // set up .ui to .h and .cxx command - cmCustomCommandLine hCommand; - hCommand.push_back(uic_exe); - hCommand.push_back("-o"); - hCommand.push_back(hName); - hCommand.push_back(uiName); - cmCustomCommandLines hCommandLines; - hCommandLines.push_back(std::move(hCommand)); - - cmCustomCommandLine cxxCommand; - cxxCommand.push_back(uic_exe); - cxxCommand.push_back("-impl"); - cxxCommand.push_back(hName); - cxxCommand.push_back("-o"); - cxxCommand.push_back(cxxName); - cxxCommand.push_back(uiName); - cmCustomCommandLines cxxCommandLines; - cxxCommandLines.push_back(std::move(cxxCommand)); - - cmCustomCommandLine mocCommand; - mocCommand.push_back(moc_exe); - mocCommand.push_back("-o"); - mocCommand.push_back(mocName); - mocCommand.push_back(hName); - cmCustomCommandLines mocCommandLines; - mocCommandLines.push_back(std::move(mocCommand)); + cmCustomCommandLines hCommandLines = + cmMakeSingleCommandLine({ uic_exe, "-o", hName, uiName }); + cmCustomCommandLines cxxCommandLines = cmMakeSingleCommandLine( + { uic_exe, "-impl", hName, "-o", cxxName, uiName }); + cmCustomCommandLines mocCommandLines = + cmMakeSingleCommandLine({ moc_exe, "-o", mocName, hName }); std::vector<std::string> depends; depends.push_back(uiName); diff --git a/Source/cmQtAutoGenInitializer.cxx b/Source/cmQtAutoGenInitializer.cxx index 1404554..ad4e4d5 100644 --- a/Source/cmQtAutoGenInitializer.cxx +++ b/Source/cmQtAutoGenInitializer.cxx @@ -979,16 +979,9 @@ bool cmQtAutoGenInitializer::InitAutogenTarget() } // Compose command lines - cmCustomCommandLines commandLines; - { - cmCustomCommandLine currentLine; - currentLine.push_back(cmSystemTools::GetCMakeCommand()); - currentLine.push_back("-E"); - currentLine.push_back("cmake_autogen"); - currentLine.push_back(this->AutogenTarget.InfoFile); - currentLine.push_back("$<CONFIGURATION>"); - commandLines.push_back(std::move(currentLine)); - } + cmCustomCommandLines commandLines = cmMakeSingleCommandLine( + { cmSystemTools::GetCMakeCommand(), "-E", "cmake_autogen", + this->AutogenTarget.InfoFile, "$<CONFIGURATION>" }); // Use PRE_BUILD on demand bool usePRE_BUILD = false; @@ -1121,22 +1114,14 @@ bool cmQtAutoGenInitializer::InitRccTargets() if (this->MultiConfig) { // Build for all configurations for (std::string const& config : this->ConfigsList) { - cmCustomCommandLine currentLine; - currentLine.push_back(cmSystemTools::GetCMakeCommand()); - currentLine.push_back("-E"); - currentLine.push_back("cmake_autorcc"); - currentLine.push_back(qrc.InfoFile); - currentLine.push_back(config); - commandLines.push_back(std::move(currentLine)); + commandLines.push_back( + cmMakeCommandLine({ cmSystemTools::GetCMakeCommand(), "-E", + "cmake_autorcc", qrc.InfoFile, config })); } } else { - cmCustomCommandLine currentLine; - currentLine.push_back(cmSystemTools::GetCMakeCommand()); - currentLine.push_back("-E"); - currentLine.push_back("cmake_autorcc"); - currentLine.push_back(qrc.InfoFile); - currentLine.push_back("$<CONFIG>"); - commandLines.push_back(std::move(currentLine)); + commandLines.push_back( + cmMakeCommandLine({ cmSystemTools::GetCMakeCommand(), "-E", + "cmake_autorcc", qrc.InfoFile, "$<CONFIG>" })); } std::string ccComment = cmStrCat("Automatic RCC for ", diff --git a/Source/cmSeparateArgumentsCommand.cxx b/Source/cmSeparateArgumentsCommand.cxx index 27f45a8..52bde7c 100644 --- a/Source/cmSeparateArgumentsCommand.cxx +++ b/Source/cmSeparateArgumentsCommand.cxx @@ -3,10 +3,10 @@ #include "cmSeparateArgumentsCommand.h" #include <algorithm> -#include <sstream> #include "cmExecutionStatus.h" #include "cmMakefile.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" // cmSeparateArgumentsCommand @@ -56,9 +56,7 @@ bool cmSeparateArgumentsCommand(std::vector<std::string> const& args, command = arg; doing = DoingNone; } else { - std::ostringstream e; - e << "given unknown argument " << arg; - status.SetError(e.str()); + status.SetError(cmStrCat("given unknown argument ", arg)); return false; } } diff --git a/Source/cmSetPropertyCommand.cxx b/Source/cmSetPropertyCommand.cxx index 387c3fc..112d832 100644 --- a/Source/cmSetPropertyCommand.cxx +++ b/Source/cmSetPropertyCommand.cxx @@ -100,11 +100,10 @@ bool cmSetPropertyCommand(std::vector<std::string> const& args, } else if (scopeName == "INSTALL") { scope = cmProperty::INSTALL; } else { - std::ostringstream e; - e << "given invalid scope " << scopeName << ". " - << "Valid scopes are GLOBAL, DIRECTORY, " - "TARGET, SOURCE, TEST, CACHE, INSTALL."; - status.SetError(e.str()); + status.SetError(cmStrCat("given invalid scope ", scopeName, + ". " + "Valid scopes are GLOBAL, DIRECTORY, " + "TARGET, SOURCE, TEST, CACHE, INSTALL.")); return false; } @@ -149,9 +148,7 @@ bool cmSetPropertyCommand(std::vector<std::string> const& args, propertyValue += arg; remove = false; } else { - std::ostringstream e; - e << "given invalid argument \"" << arg << "\"."; - status.SetError(e.str()); + status.SetError(cmStrCat("given invalid argument \"", arg, "\".")); return false; } } @@ -293,10 +290,8 @@ bool HandleTargetMode(cmExecutionStatus& status, return false; } } else { - std::ostringstream e; - e << "could not find TARGET " << name - << ". Perhaps it has not yet been created."; - status.SetError(e.str()); + status.SetError(cmStrCat("could not find TARGET ", name, + ". Perhaps it has not yet been created.")); return false; } } @@ -340,9 +335,8 @@ bool HandleSourceMode(cmExecutionStatus& status, return false; } } else { - std::ostringstream e; - e << "given SOURCE name that could not be found or created: " << name; - status.SetError(e.str()); + status.SetError(cmStrCat( + "given SOURCE name that could not be found or created: ", name)); return false; } } @@ -428,26 +422,23 @@ bool HandleCacheMode(cmExecutionStatus& status, { if (propertyName == "ADVANCED") { if (!remove && !cmIsOn(propertyValue) && !cmIsOff(propertyValue)) { - std::ostringstream e; - e << "given non-boolean value \"" << propertyValue - << R"(" for CACHE property "ADVANCED". )"; - status.SetError(e.str()); + status.SetError(cmStrCat("given non-boolean value \"", propertyValue, + R"(" for CACHE property "ADVANCED". )")); return false; } } else if (propertyName == "TYPE") { if (!cmState::IsCacheEntryType(propertyValue)) { - std::ostringstream e; - e << "given invalid CACHE entry TYPE \"" << propertyValue << "\""; - status.SetError(e.str()); + status.SetError( + cmStrCat("given invalid CACHE entry TYPE \"", propertyValue, "\"")); return false; } } else if (propertyName != "HELPSTRING" && propertyName != "STRINGS" && propertyName != "VALUE") { - std::ostringstream e; - e << "given invalid CACHE property " << propertyName << ". " - << "Settable CACHE properties are: " - << "ADVANCED, HELPSTRING, STRINGS, TYPE, and VALUE."; - status.SetError(e.str()); + status.SetError( + cmStrCat("given invalid CACHE property ", propertyName, + ". " + "Settable CACHE properties are: " + "ADVANCED, HELPSTRING, STRINGS, TYPE, and VALUE.")); return false; } @@ -462,10 +453,8 @@ bool HandleCacheMode(cmExecutionStatus& status, return false; } } else { - std::ostringstream e; - e << "could not find CACHE variable " << name - << ". Perhaps it has not yet been created."; - status.SetError(e.str()); + status.SetError(cmStrCat("could not find CACHE variable ", name, + ". Perhaps it has not yet been created.")); return false; } } @@ -511,9 +500,8 @@ bool HandleInstallMode(cmExecutionStatus& status, return false; } } else { - std::ostringstream e; - e << "given INSTALL name that could not be found or created: " << name; - status.SetError(e.str()); + status.SetError(cmStrCat( + "given INSTALL name that could not be found or created: ", name)); return false; } } diff --git a/Source/cmSourceFile.cxx b/Source/cmSourceFile.cxx index 4deb94a..3344217 100644 --- a/Source/cmSourceFile.cxx +++ b/Source/cmSourceFile.cxx @@ -5,7 +5,6 @@ #include <array> #include <utility> -#include "cmCustomCommand.h" #include "cmGlobalGenerator.h" #include "cmMakefile.h" #include "cmMessageType.h" @@ -21,11 +20,6 @@ cmSourceFile::cmSourceFile(cmMakefile* mf, const std::string& name, { } -cmSourceFile::~cmSourceFile() -{ - this->SetCustomCommand(nullptr); -} - std::string const& cmSourceFile::GetExtension() const { return this->Extension; @@ -320,19 +314,12 @@ bool cmSourceFile::GetPropertyAsBool(const std::string& prop) const return cmIsOn(this->GetProperty(prop)); } -cmCustomCommand* cmSourceFile::GetCustomCommand() -{ - return this->CustomCommand; -} - -cmCustomCommand const* cmSourceFile::GetCustomCommand() const +cmCustomCommand* cmSourceFile::GetCustomCommand() const { - return this->CustomCommand; + return this->CustomCommand.get(); } -void cmSourceFile::SetCustomCommand(cmCustomCommand* cc) +void cmSourceFile::SetCustomCommand(std::unique_ptr<cmCustomCommand> cc) { - cmCustomCommand* old = this->CustomCommand; - this->CustomCommand = cc; - delete old; + this->CustomCommand = std::move(cc); } diff --git a/Source/cmSourceFile.h b/Source/cmSourceFile.h index 774cb28..dd36d45 100644 --- a/Source/cmSourceFile.h +++ b/Source/cmSourceFile.h @@ -5,14 +5,15 @@ #include "cmConfigure.h" // IWYU pragma: keep +#include "cmCustomCommand.h" #include "cmPropertyMap.h" #include "cmSourceFileLocation.h" #include "cmSourceFileLocationKind.h" +#include <memory> #include <string> #include <vector> -class cmCustomCommand; class cmMakefile; /** \class cmSourceFile @@ -32,17 +33,11 @@ public: cmMakefile* mf, const std::string& name, cmSourceFileLocationKind kind = cmSourceFileLocationKind::Ambiguous); - ~cmSourceFile(); - - cmSourceFile(const cmSourceFile&) = delete; - cmSourceFile& operator=(const cmSourceFile&) = delete; - /** - * Get the list of the custom commands for this source file + * Get the custom command for this source file */ - cmCustomCommand* GetCustomCommand(); - cmCustomCommand const* GetCustomCommand() const; - void SetCustomCommand(cmCustomCommand* cc); + cmCustomCommand* GetCustomCommand() const; + void SetCustomCommand(std::unique_ptr<cmCustomCommand> cc); //! Set/Get a property of this source file void SetProperty(const std::string& prop, const char* value); @@ -114,7 +109,7 @@ public: private: cmSourceFileLocation Location; cmPropertyMap Properties; - cmCustomCommand* CustomCommand = nullptr; + std::unique_ptr<cmCustomCommand> CustomCommand; std::string Extension; std::string Language; std::string FullPath; diff --git a/Source/cmStringCommand.cxx b/Source/cmStringCommand.cxx index ab670ca..809d05e 100644 --- a/Source/cmStringCommand.cxx +++ b/Source/cmStringCommand.cxx @@ -11,7 +11,6 @@ #include <cstdlib> #include <iterator> #include <memory> -#include <sstream> #include "cm_static_string_view.hxx" @@ -46,9 +45,8 @@ bool HandleHashCommand(std::vector<std::string> const& args, { #if !defined(CMAKE_BOOTSTRAP) if (args.size() != 3) { - std::ostringstream e; - e << args[0] << " requires an output variable and an input string"; - status.SetError(e.str()); + status.SetError( + cmStrCat(args[0], " requires an output variable and an input string")); return false; } @@ -60,9 +58,7 @@ bool HandleHashCommand(std::vector<std::string> const& args, } return false; #else - std::ostringstream e; - e << args[0] << " not available during bootstrap"; - status.SetError(e.str().c_str()); + status.SetError(cmStrCat(args[0], " not available during bootstrap")); return false; #endif } @@ -148,9 +144,7 @@ bool HandleConfigureCommand(std::vector<std::string> const& args, } else if (args[i] == "ESCAPE_QUOTES") { escapeQuotes = true; } else { - std::ostringstream err; - err << "Unrecognized argument \"" << args[i] << "\""; - status.SetError(err.str()); + status.SetError(cmStrCat("Unrecognized argument \"", args[i], "\"")); return false; } } @@ -377,9 +371,7 @@ bool HandleFindCommand(std::vector<std::string> const& args, pos = sstring.rfind(schar); } if (std::string::npos != pos) { - std::ostringstream s; - s << pos; - status.GetMakefile().AddDefinition(outvar, s.str()); + status.GetMakefile().AddDefinition(outvar, std::to_string(pos)); return true; } @@ -474,16 +466,12 @@ bool HandleSubstringCommand(std::vector<std::string> const& args, size_t stringLength = stringValue.size(); int intStringLength = static_cast<int>(stringLength); if (begin < 0 || begin > intStringLength) { - std::ostringstream ostr; - ostr << "begin index: " << begin << " is out of range 0 - " - << stringLength; - status.SetError(ostr.str()); + status.SetError( + cmStrCat("begin index: ", begin, " is out of range 0 - ", stringLength)); return false; } if (end < -1) { - std::ostringstream ostr; - ostr << "end index: " << end << " should be -1 or greater"; - status.SetError(ostr.str()); + status.SetError(cmStrCat("end index: ", end, " should be -1 or greater")); return false; } @@ -915,9 +903,7 @@ bool HandleUuidCommand(std::vector<std::string> const& args, status.GetMakefile().AddDefinition(outputVariable, uuid); return true; #else - std::ostringstream e; - e << args[0] << " not available during bootstrap"; - status.SetError(e.str().c_str()); + status.SetError(cmStrCat(args[0], " not available during bootstrap")); return false; #endif } diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index 86873ed..8900ebf 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -1086,6 +1086,7 @@ void cmTarget::SetProperty(const std::string& prop, const char* value) MAKE_STATIC_PROP(COMPILE_FEATURES); MAKE_STATIC_PROP(COMPILE_OPTIONS); MAKE_STATIC_PROP(PRECOMPILE_HEADERS); + MAKE_STATIC_PROP(PRECOMPILE_HEADERS_REUSE_FROM); MAKE_STATIC_PROP(CUDA_PTX_COMPILATION); MAKE_STATIC_PROP(EXPORT_NAME); MAKE_STATIC_PROP(IMPORTED_GLOBAL); @@ -1232,6 +1233,41 @@ void cmTarget::SetProperty(const std::string& prop, const char* value) << impl->Name << "\")\n"; impl->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); return; + } else if (prop == propPRECOMPILE_HEADERS_REUSE_FROM) { + if (this->GetProperty("PRECOMPILE_HEADERS")) { + std::ostringstream e; + e << "PRECOMPILE_HEADERS property is already set on target (\"" + << impl->Name << "\")\n"; + impl->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); + return; + } + auto reusedTarget = + impl->Makefile->GetCMakeInstance()->GetGlobalGenerator()->FindTarget( + value); + if (!reusedTarget) { + const std::string e( + "PRECOMPILE_HEADERS_REUSE_FROM set with non existing target"); + impl->Makefile->IssueMessage(MessageType::FATAL_ERROR, e); + return; + } + + std::string reusedFrom = reusedTarget->GetSafeProperty(prop); + if (reusedFrom.empty()) { + reusedFrom = value; + } + + impl->Properties.SetProperty(prop, reusedFrom.c_str()); + + reusedTarget->SetProperty("COMPILE_PDB_NAME", reusedFrom.c_str()); + reusedTarget->SetProperty("COMPILE_PDB_OUTPUT_DIRECTORY", + cmStrCat(reusedFrom, ".dir/").c_str()); + + for (auto p : { "COMPILE_PDB_NAME", "PRECOMPILE_HEADERS", + "INTERFACE_PRECOMPILE_HEADERS" }) { + this->SetProperty(p, reusedTarget->GetProperty(p)); + } + + this->AddUtility(reusedFrom, impl->Makefile); } else { impl->Properties.SetProperty(prop, value); } @@ -1309,6 +1345,14 @@ void cmTarget::AppendProperty(const std::string& prop, const char* value, impl->LinkDirectoriesBacktraces.push_back(lfbt); } } else if (prop == "PRECOMPILE_HEADERS") { + if (this->GetProperty("PRECOMPILE_HEADERS_REUSE_FROM")) { + std::ostringstream e; + e << "PRECOMPILE_HEADERS_REUSE_FROM property is already set on target " + "(\"" + << impl->Name << "\")\n"; + impl->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); + return; + } if (value && *value) { impl->PrecompileHeadersEntries.emplace_back(value); cmListFileBacktrace lfbt = impl->Makefile->GetBacktrace(); diff --git a/Source/cmTargetCompileDefinitionsCommand.cxx b/Source/cmTargetCompileDefinitionsCommand.cxx index b64646a..94e249f 100644 --- a/Source/cmTargetCompileDefinitionsCommand.cxx +++ b/Source/cmTargetCompileDefinitionsCommand.cxx @@ -2,8 +2,6 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmTargetCompileDefinitionsCommand.h" -#include <sstream> - #include "cmMakefile.h" #include "cmMessageType.h" #include "cmStringAlgorithms.h" @@ -20,11 +18,10 @@ bool cmTargetCompileDefinitionsCommand::InitialPass( void cmTargetCompileDefinitionsCommand::HandleMissingTarget( const std::string& name) { - std::ostringstream e; - e << "Cannot specify compile definitions for target \"" << name - << "\" " - "which is not built by this project."; - this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); + this->Makefile->IssueMessage( + MessageType::FATAL_ERROR, + cmStrCat("Cannot specify compile definitions for target \"", name, + "\" which is not built by this project.")); } std::string cmTargetCompileDefinitionsCommand::Join( diff --git a/Source/cmTargetCompileFeaturesCommand.cxx b/Source/cmTargetCompileFeaturesCommand.cxx index 976c8cb..a22b94b 100644 --- a/Source/cmTargetCompileFeaturesCommand.cxx +++ b/Source/cmTargetCompileFeaturesCommand.cxx @@ -2,8 +2,6 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmTargetCompileFeaturesCommand.h" -#include <sstream> - #include "cmMakefile.h" #include "cmMessageType.h" #include "cmStringAlgorithms.h" @@ -20,11 +18,10 @@ bool cmTargetCompileFeaturesCommand::InitialPass( void cmTargetCompileFeaturesCommand::HandleMissingTarget( const std::string& name) { - std::ostringstream e; - e << "Cannot specify compile features for target \"" << name - << "\" " - "which is not built by this project."; - this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); + this->Makefile->IssueMessage( + MessageType::FATAL_ERROR, + cmStrCat("Cannot specify compile features for target \"", name, + "\" which is not built by this project.")); } std::string cmTargetCompileFeaturesCommand::Join( diff --git a/Source/cmTargetCompileOptionsCommand.cxx b/Source/cmTargetCompileOptionsCommand.cxx index 7dadb82..ccc215a 100644 --- a/Source/cmTargetCompileOptionsCommand.cxx +++ b/Source/cmTargetCompileOptionsCommand.cxx @@ -2,8 +2,6 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmTargetCompileOptionsCommand.h" -#include <sstream> - #include "cmListFileCache.h" #include "cmMakefile.h" #include "cmMessageType.h" @@ -21,10 +19,10 @@ bool cmTargetCompileOptionsCommand::InitialPass( 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."; - this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); + this->Makefile->IssueMessage( + MessageType::FATAL_ERROR, + cmStrCat("Cannot specify compile options for target \"", name, + "\" which is not built by this project.")); } std::string cmTargetCompileOptionsCommand::Join( diff --git a/Source/cmTargetIncludeDirectoriesCommand.cxx b/Source/cmTargetIncludeDirectoriesCommand.cxx index d099349..7801ee8 100644 --- a/Source/cmTargetIncludeDirectoriesCommand.cxx +++ b/Source/cmTargetIncludeDirectoriesCommand.cxx @@ -3,7 +3,6 @@ #include "cmTargetIncludeDirectoriesCommand.h" #include <set> -#include <sstream> #include "cmGeneratorExpression.h" #include "cmListFileCache.h" @@ -25,10 +24,10 @@ bool cmTargetIncludeDirectoriesCommand::InitialPass( 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."; - this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); + this->Makefile->IssueMessage( + MessageType::FATAL_ERROR, + cmStrCat("Cannot specify include directories for target \"", name, + "\" which is not built by this project.")); } std::string cmTargetIncludeDirectoriesCommand::Join( diff --git a/Source/cmTargetLinkDirectoriesCommand.cxx b/Source/cmTargetLinkDirectoriesCommand.cxx index 435c392..c2ef6c1 100644 --- a/Source/cmTargetLinkDirectoriesCommand.cxx +++ b/Source/cmTargetLinkDirectoriesCommand.cxx @@ -2,8 +2,6 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmTargetLinkDirectoriesCommand.h" -#include <sstream> - #include "cmGeneratorExpression.h" #include "cmListFileCache.h" #include "cmMakefile.h" @@ -23,10 +21,10 @@ bool cmTargetLinkDirectoriesCommand::InitialPass( void cmTargetLinkDirectoriesCommand::HandleMissingTarget( const std::string& name) { - std::ostringstream e; - e << "Cannot specify link directories for target \"" << name - << "\" which is not built by this project."; - this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); + this->Makefile->IssueMessage( + MessageType::FATAL_ERROR, + cmStrCat("Cannot specify link directories for target \"", name, + "\" which is not built by this project.")); } std::string cmTargetLinkDirectoriesCommand::Join( diff --git a/Source/cmTargetLinkLibrariesCommand.cxx b/Source/cmTargetLinkLibrariesCommand.cxx index 237d90c..b432599 100644 --- a/Source/cmTargetLinkLibrariesCommand.cxx +++ b/Source/cmTargetLinkLibrariesCommand.cxx @@ -256,10 +256,11 @@ bool cmTargetLinkLibrariesCommand::InitialPass( // Make sure the last argument was not a library type specifier. if (haveLLT) { - std::ostringstream e; - e << "The \"" << cmTargetLinkLibrariesCommand::LinkLibraryTypeNames[llt] - << "\" argument must be followed by a library."; - this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); + this->Makefile->IssueMessage( + MessageType::FATAL_ERROR, + cmStrCat("The \"", + cmTargetLinkLibrariesCommand::LinkLibraryTypeNames[llt], + "\" argument must be followed by a library.")); cmSystemTools::SetFatalErrorOccured(); } @@ -284,14 +285,14 @@ bool cmTargetLinkLibrariesCommand::InitialPass( void cmTargetLinkLibrariesCommand::LinkLibraryTypeSpecifierWarning(int left, int right) { - std::ostringstream w; - w << "Link library type specifier \"" - << cmTargetLinkLibrariesCommand::LinkLibraryTypeNames[left] - << "\" is followed by specifier \"" - << cmTargetLinkLibrariesCommand::LinkLibraryTypeNames[right] - << "\" instead of a library name. " - << "The first specifier will be ignored."; - this->Makefile->IssueMessage(MessageType::AUTHOR_WARNING, w.str()); + this->Makefile->IssueMessage( + MessageType::AUTHOR_WARNING, + cmStrCat( + "Link library type specifier \"", + cmTargetLinkLibrariesCommand::LinkLibraryTypeNames[left], + "\" is followed by specifier \"", + cmTargetLinkLibrariesCommand::LinkLibraryTypeNames[right], + "\" instead of a library name. The first specifier will be ignored.")); } bool cmTargetLinkLibrariesCommand::HandleLibrary(const std::string& lib, @@ -404,12 +405,13 @@ bool cmTargetLinkLibrariesCommand::HandleLibrary(const std::string& lib, this->CurrentProcessingState != ProcessingPlainLinkInterface) { if (rejectRemoteLinking) { - std::ostringstream e; - e << "Attempt to add link library \"" << lib << "\" to target \"" - << this->Target->GetName() - << "\" which is not built in this directory.\n" - << "This is allowed only when policy CMP0079 is set to NEW."; - this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); + this->Makefile->IssueMessage( + MessageType::FATAL_ERROR, + cmStrCat("Attempt to add link library \"", lib, "\" to target \"", + this->Target->GetName(), + "\" which is not built in this " + "directory.\nThis is allowed only when policy CMP0079 " + "is set to NEW.")); return false; } @@ -421,29 +423,31 @@ bool cmTargetLinkLibrariesCommand::HandleLibrary(const std::string& lib, (tgt->GetType() != cmStateEnums::OBJECT_LIBRARY) && (tgt->GetType() != cmStateEnums::INTERFACE_LIBRARY) && !tgt->IsExecutableWithExports()) { - std::ostringstream e; - e << "Target \"" << lib << "\" of type " - << cmState::GetTargetTypeName(tgt->GetType()) - << " may not be linked into another target. One may link only to " - "INTERFACE, OBJECT, STATIC or SHARED libraries, or to executables " - "with the ENABLE_EXPORTS property set."; - this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); + this->Makefile->IssueMessage( + MessageType::FATAL_ERROR, + cmStrCat( + "Target \"", lib, "\" of type ", + cmState::GetTargetTypeName(tgt->GetType()), + " may not be linked into another target. One may link only to " + "INTERFACE, OBJECT, STATIC or SHARED libraries, or to ", + "executables with the ENABLE_EXPORTS property set.")); } this->Target->AddLinkLibrary(*this->Makefile, lib, libRef, llt); } if (warnRemoteInterface) { - std::ostringstream w; - /* clang-format off */ - w << cmPolicies::GetPolicyWarning(cmPolicies::CMP0079) << "\n" - "Target\n " << this->Target->GetName() << "\nis not created in this " - "directory. For compatibility with older versions of CMake, link " - "library\n " << lib << "\nwill be looked up in the directory in " - "which the target was created rather than in this calling " - "directory."; - /* clang-format on */ - this->Makefile->IssueMessage(MessageType::AUTHOR_WARNING, w.str()); + this->Makefile->IssueMessage( + MessageType::AUTHOR_WARNING, + cmStrCat( + cmPolicies::GetPolicyWarning(cmPolicies::CMP0079), "\nTarget\n ", + this->Target->GetName(), + "\nis not created in this " + "directory. For compatibility with older versions of CMake, link " + "library\n ", + lib, + "\nwill be looked up in the directory in which " + "the target was created rather than in this calling directory.")); } // Handle (additional) case where the command was called with PRIVATE / diff --git a/Source/cmTargetLinkOptionsCommand.cxx b/Source/cmTargetLinkOptionsCommand.cxx index 2866cf1..dbd7bfe 100644 --- a/Source/cmTargetLinkOptionsCommand.cxx +++ b/Source/cmTargetLinkOptionsCommand.cxx @@ -2,8 +2,6 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmTargetLinkOptionsCommand.h" -#include <sstream> - #include "cmListFileCache.h" #include "cmMakefile.h" #include "cmMessageType.h" @@ -20,10 +18,10 @@ bool cmTargetLinkOptionsCommand::InitialPass( void cmTargetLinkOptionsCommand::HandleMissingTarget(const std::string& name) { - std::ostringstream e; - e << "Cannot specify link options for target \"" << name - << "\" which is not built by this project."; - this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); + this->Makefile->IssueMessage( + MessageType::FATAL_ERROR, + cmStrCat("Cannot specify link options for target \"", name, + "\" which is not built by this project.")); } std::string cmTargetLinkOptionsCommand::Join( diff --git a/Source/cmTargetPrecompileHeadersCommand.cxx b/Source/cmTargetPrecompileHeadersCommand.cxx index 30cf1be..97f1bea 100644 --- a/Source/cmTargetPrecompileHeadersCommand.cxx +++ b/Source/cmTargetPrecompileHeadersCommand.cxx @@ -10,7 +10,7 @@ bool cmTargetPrecompileHeadersCommand::InitialPass( std::vector<std::string> const& args, cmExecutionStatus&) { - return this->HandleArguments(args, "PRECOMPILE_HEADERS"); + return this->HandleArguments(args, "PRECOMPILE_HEADERS", PROCESS_REUSE_FROM); } void cmTargetPrecompileHeadersCommand::HandleMissingTarget( diff --git a/Source/cmTargetPropCommandBase.cxx b/Source/cmTargetPropCommandBase.cxx index 3aa845c..4bc3125 100644 --- a/Source/cmTargetPropCommandBase.cxx +++ b/Source/cmTargetPropCommandBase.cxx @@ -65,6 +65,19 @@ bool cmTargetPropCommandBase::HandleArguments( ++argIndex; } + if ((flags & PROCESS_REUSE_FROM) && args[argIndex] == "REUSE_FROM") { + if (args.size() != 3) { + this->SetError("called with incorrect number of arguments"); + return false; + } + ++argIndex; + + this->Target->SetProperty("PRECOMPILE_HEADERS_REUSE_FROM", + args[argIndex].c_str()); + + ++argIndex; + } + this->Property = prop; while (argIndex < args.size()) { diff --git a/Source/cmTargetPropCommandBase.h b/Source/cmTargetPropCommandBase.h index 943285d..b244417 100644 --- a/Source/cmTargetPropCommandBase.h +++ b/Source/cmTargetPropCommandBase.h @@ -17,9 +17,10 @@ class cmTargetPropCommandBase : public cmCommand public: enum ArgumentFlags { - NO_FLAGS = 0, - PROCESS_BEFORE = 1, - PROCESS_SYSTEM = 2 + NO_FLAGS = 0x0, + PROCESS_BEFORE = 0x1, + PROCESS_SYSTEM = 0x2, + PROCESS_REUSE_FROM = 0x3 }; bool HandleArguments(std::vector<std::string> const& args, diff --git a/Source/cmTargetSourcesCommand.cxx b/Source/cmTargetSourcesCommand.cxx index 2251a65..7c9d03c 100644 --- a/Source/cmTargetSourcesCommand.cxx +++ b/Source/cmTargetSourcesCommand.cxx @@ -30,11 +30,10 @@ void cmTargetSourcesCommand::HandleInterfaceContent( void cmTargetSourcesCommand::HandleMissingTarget(const std::string& name) { - std::ostringstream e; - e << "Cannot specify sources for target \"" << name - << "\" " - "which is not built by this project."; - this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); + this->Makefile->IssueMessage( + MessageType::FATAL_ERROR, + cmStrCat("Cannot specify sources for target \"", name, + "\" which is not built by this project.")); } std::string cmTargetSourcesCommand::Join( diff --git a/Source/cmVariableWatchCommand.cxx b/Source/cmVariableWatchCommand.cxx index f9f7d66..f2c8f3c 100644 --- a/Source/cmVariableWatchCommand.cxx +++ b/Source/cmVariableWatchCommand.cxx @@ -3,13 +3,13 @@ #include "cmVariableWatchCommand.h" #include <memory> -#include <sstream> #include <utility> #include "cmExecutionStatus.h" #include "cmListFileCache.h" #include "cmMakefile.h" #include "cmMessageType.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmVariableWatch.h" #include "cmake.h" @@ -58,22 +58,20 @@ static void cmVariableWatchCommandVariableAccessed(const std::string& variable, newLFF.Line = 9999; cmExecutionStatus status(*makefile); if (!makefile->ExecuteCommand(newLFF, status)) { - std::ostringstream error; - error << "Error in cmake code at\nUnknown:0:\n" - << "A command failed during the invocation of callback \"" - << data->Command << "\"."; - cmSystemTools::Error(error.str()); + cmSystemTools::Error( + cmStrCat("Error in cmake code at\nUnknown:0:\nA command failed " + "during the invocation of callback \"", + data->Command, "\".")); data->InCallback = false; return; } processed = true; } if (!processed) { - std::ostringstream msg; - msg << "Variable \"" << variable << "\" was accessed using " - << accessString << " with value \"" << (newValue ? newValue : "") - << "\"."; - makefile->IssueMessage(MessageType::LOG, msg.str()); + makefile->IssueMessage( + MessageType::LOG, + cmStrCat("Variable \"", variable, "\" was accessed using ", accessString, + " with value \"", (newValue ? newValue : ""), "\".")); } data->InCallback = false; @@ -134,9 +132,7 @@ bool cmVariableWatchCommand(std::vector<std::string> const& args, command = args[1]; } if (variable == "CMAKE_CURRENT_LIST_FILE") { - std::ostringstream ostr; - ostr << "cannot be set on the variable: " << variable; - status.SetError(ostr.str()); + status.SetError(cmStrCat("cannot be set on the variable: ", variable)); return false; } diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt index c14107a..78ae7aa 100644 --- a/Tests/CMakeLists.txt +++ b/Tests/CMakeLists.txt @@ -1394,6 +1394,7 @@ ${CMake_SOURCE_DIR}/Utilities/Release/push.bash --dir dev -- '${CMake_BUILD_NIGH GIF Git GLEW + GnuTLS GSL GTK2 Iconv diff --git a/Tests/CustomCommandByproducts/CMakeLists.txt b/Tests/CustomCommandByproducts/CMakeLists.txt index bfa69ce..08c897c 100644 --- a/Tests/CustomCommandByproducts/CMakeLists.txt +++ b/Tests/CustomCommandByproducts/CMakeLists.txt @@ -14,20 +14,20 @@ add_custom_command( # Generate a byproduct in a rule that runs in a dependency of the consumer. add_custom_command( - OUTPUT timestamp2.txt + OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/../CustomCommandByproducts/timestamp2.txt COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_CURRENT_SOURCE_DIR}/byproduct2.c.in byproduct2.c - BYPRODUCTS byproduct2.c + BYPRODUCTS ${CMAKE_CURRENT_BINARY_DIR}/../CustomCommandByproducts/byproduct2.c COMMAND ${CMAKE_COMMAND} -E touch timestamp2.txt DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/byproduct2.c.in ) -add_custom_target(Producer2 DEPENDS timestamp2.txt) +add_custom_target(Producer2 DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/timestamp2.txt) # Generate a byproduct in a custom target. add_custom_target(Producer3_4 COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_CURRENT_SOURCE_DIR}/byproduct3.c.in byproduct3.c - BYPRODUCTS byproduct3.c + BYPRODUCTS ${CMAKE_CURRENT_BINARY_DIR}/../CustomCommandByproducts/byproduct3.c DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/byproduct3.c.in ) @@ -36,7 +36,7 @@ add_custom_command( TARGET Producer3_4 POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_CURRENT_SOURCE_DIR}/byproduct4.c.in byproduct4.c - BYPRODUCTS byproduct4.c + BYPRODUCTS ${CMAKE_CURRENT_BINARY_DIR}/../CustomCommandByproducts/byproduct4.c DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/byproduct4.c.in ) diff --git a/Tests/FindEnvModules/EnvModules.cmake b/Tests/FindEnvModules/EnvModules.cmake index 0c81bf2..21b0042 100644 --- a/Tests/FindEnvModules/EnvModules.cmake +++ b/Tests/FindEnvModules/EnvModules.cmake @@ -18,18 +18,16 @@ if(avail_mods) message("module list") env_module_list(loaded_mods) + set(mod0_found FALSE) foreach(mod IN LISTS loaded_mods) message(" ${mod}") + if(NOT mod0_found AND mod MATCHES "^${mod0}") + set(mod0_found ${mod}) + endif() endforeach() - list(LENGTH loaded_mods num_loaded_mods) - message("Number of modules loaded: ${num_loaded_mods}") - if(NOT num_loaded_mods EQUAL 1) - message(FATAL_ERROR "Exactly 1 module should be loaded. Found ${num_loaded_mods}") - endif() - - list(GET loaded_mods 0 mod0_actual) - if(NOT (mod0_actual MATCHES "^${mod0}")) - message(FATAL_ERROR "Loaded module does not match ${mod0}. Actual: ${mod0_actual}") + if(NOT mod0_found) + message(FATAL_ERROR "Requested module ${mod0} not found in loaded modules") endif() + message("module ${mod0} found loaded as ${mod0_found}") endif() diff --git a/Tests/FindGnuTLS/CMakeLists.txt b/Tests/FindGnuTLS/CMakeLists.txt new file mode 100644 index 0000000..059ac7b --- /dev/null +++ b/Tests/FindGnuTLS/CMakeLists.txt @@ -0,0 +1,10 @@ +add_test(NAME FindGnuTLS.Test COMMAND + ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION> + --build-and-test + "${CMake_SOURCE_DIR}/Tests/FindGnuTLS/Test" + "${CMake_BINARY_DIR}/Tests/FindGnuTLS/Test" + ${build_generator_args} + --build-project TestFindGnuTLS + --build-options ${build_options} + --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION> + ) diff --git a/Tests/FindGnuTLS/Test/CMakeLists.txt b/Tests/FindGnuTLS/Test/CMakeLists.txt new file mode 100644 index 0000000..c5a9819 --- /dev/null +++ b/Tests/FindGnuTLS/Test/CMakeLists.txt @@ -0,0 +1,17 @@ +cmake_minimum_required(VERSION 3.4) +project(TestFindGnuTLS C) +include(CTest) + +find_package(GnuTLS REQUIRED) + +add_definitions(-DCMAKE_EXPECTED_GNUTLS_VERSION="${GNUTLS_VERSION}") + +add_executable(test_tgt main.c) +target_link_libraries(test_tgt GnuTLS::GnuTLS) +add_test(NAME test_tgt COMMAND test_tgt) + +add_executable(test_var main.c) +target_include_directories(test_var PRIVATE ${GNUTLS_INCLUDE_DIRS}) +target_link_libraries(test_var PRIVATE ${GNUTLS_LIBRARIES}) +target_compile_definitions(test_var PRIVATE ${GNUTLS_DEFINITIONS}) +add_test(NAME test_var COMMAND test_var) diff --git a/Tests/FindGnuTLS/Test/main.c b/Tests/FindGnuTLS/Test/main.c new file mode 100644 index 0000000..122fb2d --- /dev/null +++ b/Tests/FindGnuTLS/Test/main.c @@ -0,0 +1,22 @@ +#include <assert.h> +#include <stdio.h> +#include <string.h> + +#include <gnutls/gnutls.h> + +int main() +{ + // test the linker + gnutls_session_t session; + if (gnutls_init(&session, GNUTLS_CLIENT)) { + gnutls_deinit(session); + } + + // check the version + char gnutls_version_string[16]; + snprintf(gnutls_version_string, 16, "%i.%i.%i", GNUTLS_VERSION_MAJOR, + GNUTLS_VERSION_MINOR, GNUTLS_VERSION_PATCH); + assert(strcmp(gnutls_version_string, CMAKE_EXPECTED_GNUTLS_VERSION) == 0); + + return 0; +} diff --git a/Tests/RunCMake/FindPkgConfig/FindPkgConfig_IMPORTED_TARGET.cmake b/Tests/RunCMake/FindPkgConfig/FindPkgConfig_IMPORTED_TARGET.cmake index e82b05f..62bb5de 100644 --- a/Tests/RunCMake/FindPkgConfig/FindPkgConfig_IMPORTED_TARGET.cmake +++ b/Tests/RunCMake/FindPkgConfig/FindPkgConfig_IMPORTED_TARGET.cmake @@ -39,7 +39,7 @@ foreach(i 1 2) "Name: CMakeInternalFakePackage${i} Description: Dummy package (${i}) for FindPkgConfig IMPORTED_TARGET test Version: 1.2.3 -Libs: -l${pname} +Libs: -l${pname} -l${pname}-doesnotexist ") endforeach() @@ -47,27 +47,6 @@ endforeach() # the import target find_library() calls handle the NO...PATH options correctly set(ENV{PKG_CONFIG_PATH} ${fakePkgDir}/lib/pkgconfig) -# Confirm correct behavior of NO_CMAKE_PATH, ensuring we only find the library -# for the imported target if we have both set CMAKE_PREFIX_PATH and have not -# given the NO_CMAKE_PATH option -unset(CMAKE_PREFIX_PATH) -unset(ENV{CMAKE_PREFIX_PATH}) -pkg_check_modules(FakePackage1 QUIET IMPORTED_TARGET cmakeinternalfakepackage1) -if (TARGET PkgConfig::FakePackage1) - message(FATAL_ERROR "Have import target for fake package 1 with no path prefix") -endif() - -set(CMAKE_PREFIX_PATH ${fakePkgDir}) -pkg_check_modules(FakePackage1 QUIET IMPORTED_TARGET NO_CMAKE_PATH cmakeinternalfakepackage1) -if (TARGET PkgConfig::FakePackage1) - message(FATAL_ERROR "Have import target for fake package 1 with ignored cmake path") -endif() - -pkg_check_modules(FakePackage1 REQUIRED QUIET IMPORTED_TARGET cmakeinternalfakepackage1) -if (NOT TARGET PkgConfig::FakePackage1) - message(FATAL_ERROR "No import target for fake package 1 with prefix path") -endif() - # find targets in subdir and check their visibility add_subdirectory(target_subdir) if (TARGET PkgConfig::FakePackage1_dir) @@ -82,31 +61,35 @@ endif() # combination unset(CMAKE_PREFIX_PATH) unset(ENV{CMAKE_PREFIX_PATH}) -pkg_check_modules(FakePackage2 QUIET IMPORTED_TARGET cmakeinternalfakepackage2) -if (TARGET PkgConfig::FakePackage2) - message(FATAL_ERROR "Have import target for fake package 2 with no path prefix") -endif() - set(ENV{CMAKE_PREFIX_PATH} ${fakePkgDir}) -pkg_check_modules(FakePackage2 QUIET IMPORTED_TARGET NO_CMAKE_ENVIRONMENT_PATH cmakeinternalfakepackage2) -if (TARGET PkgConfig::FakePackage2) - message(FATAL_ERROR "Have import target for fake package 2 with ignored cmake path") -endif() pkg_check_modules(FakePackage2 REQUIRED QUIET IMPORTED_TARGET cmakeinternalfakepackage2) if (NOT TARGET PkgConfig::FakePackage2) message(FATAL_ERROR "No import target for fake package 2 with prefix path") endif() +# check that 2 library entries exist +list(LENGTH FakePackage2_LINK_LIBRARIES fp2_nlibs) +if (NOT fp2_nlibs EQUAL 2) + message(FATAL_ERROR "FakePackage2_LINK_LIBRARIES has ${fp2_nlibs} entries but should have exactly 2") +endif() + # check that the full library path is also returned -if (NOT FakePackage2_LINK_LIBRARIES STREQUAL "${fakePkgDir}/lib/libcmakeinternalfakepackage2.a") +list(GET FakePackage2_LINK_LIBRARIES 0 fp2_lib0) +if (NOT fp2_lib0 STREQUAL "${fakePkgDir}/lib/libcmakeinternalfakepackage2.a") + message(FATAL_ERROR "FakePackage2_LINK_LIBRARIES has bad content on first run: ${FakePackage2_LINK_LIBRARIES}") +endif() + +# check that the library that couldn't be found still shows up +list(GET FakePackage2_LINK_LIBRARIES 1 fp2_lib1) +if (NOT fp2_lib1 STREQUAL "cmakeinternalfakepackage2-doesnotexist") message(FATAL_ERROR "FakePackage2_LINK_LIBRARIES has bad content on first run: ${FakePackage2_LINK_LIBRARIES}") endif() # the information in *_LINK_LIBRARIES is not cached, so ensure is also is present on second run unset(FakePackage2_LINK_LIBRARIES) pkg_check_modules(FakePackage2 REQUIRED QUIET IMPORTED_TARGET cmakeinternalfakepackage2) -if (NOT FakePackage2_LINK_LIBRARIES STREQUAL "${fakePkgDir}/lib/libcmakeinternalfakepackage2.a") +if (NOT FakePackage2_LINK_LIBRARIES STREQUAL "${fakePkgDir}/lib/libcmakeinternalfakepackage2.a;cmakeinternalfakepackage2-doesnotexist") message(FATAL_ERROR "FakePackage2_LINK_LIBRARIES has bad content on second run: ${FakePackage2_LINK_LIBRARIES}") endif() diff --git a/Tests/RunCMake/PrecompileHeaders/PchReuseFrom.cmake b/Tests/RunCMake/PrecompileHeaders/PchReuseFrom.cmake new file mode 100644 index 0000000..4502456 --- /dev/null +++ b/Tests/RunCMake/PrecompileHeaders/PchReuseFrom.cmake @@ -0,0 +1,20 @@ +cmake_minimum_required(VERSION 3.15) +project(PchReuseFrom C) + +add_library(empty empty.c) +target_precompile_headers(empty PUBLIC + <stdio.h> + <string.h> +) +target_include_directories(empty PUBLIC include) + +add_library(foo foo.c) +target_include_directories(foo PUBLIC include) +target_precompile_headers(foo REUSE_FROM empty) + +add_executable(foobar foobar.c) +target_link_libraries(foobar foo ) +set_target_properties(foobar PROPERTIES PRECOMPILE_HEADERS_REUSE_FROM foo) + +enable_testing() +add_test(NAME foobar COMMAND foobar) diff --git a/Tests/RunCMake/PrecompileHeaders/PchReuseFromSubdir-build-stderr.txt b/Tests/RunCMake/PrecompileHeaders/PchReuseFromSubdir-build-stderr.txt new file mode 100644 index 0000000..8cdcfd9 --- /dev/null +++ b/Tests/RunCMake/PrecompileHeaders/PchReuseFromSubdir-build-stderr.txt @@ -0,0 +1,2 @@ +^(|Warning #670: precompiled header file [^ +]* was not generated in this directory)$ diff --git a/Tests/RunCMake/PrecompileHeaders/PchReuseFromSubdir.cmake b/Tests/RunCMake/PrecompileHeaders/PchReuseFromSubdir.cmake new file mode 100644 index 0000000..fff74dc --- /dev/null +++ b/Tests/RunCMake/PrecompileHeaders/PchReuseFromSubdir.cmake @@ -0,0 +1,18 @@ +cmake_minimum_required(VERSION 3.15) +project(PchReuseFromSubdir C) + +add_library(empty empty.c) +target_precompile_headers(empty PUBLIC + <stdio.h> + <string.h> +) +target_include_directories(empty PUBLIC include) + +add_library(foo foo.c) +target_include_directories(foo PUBLIC include) +target_precompile_headers(foo REUSE_FROM empty) + +subdirs(subdir) + +enable_testing() +add_test(NAME foobar COMMAND foobar) diff --git a/Tests/RunCMake/PrecompileHeaders/RunCMakeTest.cmake b/Tests/RunCMake/PrecompileHeaders/RunCMakeTest.cmake index fffcc47..bd3b1b8 100644 --- a/Tests/RunCMake/PrecompileHeaders/RunCMakeTest.cmake +++ b/Tests/RunCMake/PrecompileHeaders/RunCMakeTest.cmake @@ -16,3 +16,5 @@ run_cmake(DisabledPch) run_test(PchInterface) run_cmake(PchPrologueEpilogue) run_test(SkipPrecompileHeaders) +run_test(PchReuseFrom) +run_test(PchReuseFromSubdir) diff --git a/Tests/RunCMake/PrecompileHeaders/empty.c b/Tests/RunCMake/PrecompileHeaders/empty.c new file mode 100644 index 0000000..30ae1c4 --- /dev/null +++ b/Tests/RunCMake/PrecompileHeaders/empty.c @@ -0,0 +1,3 @@ +void nothing() +{ +} diff --git a/Tests/RunCMake/PrecompileHeaders/include/foo.h b/Tests/RunCMake/PrecompileHeaders/include/foo.h index 4a49474..fc0ae14 100644 --- a/Tests/RunCMake/PrecompileHeaders/include/foo.h +++ b/Tests/RunCMake/PrecompileHeaders/include/foo.h @@ -1,6 +1,6 @@ #ifndef foo_h #define foo_h -extern int foo(); +int foo(void); #endif diff --git a/Tests/RunCMake/PrecompileHeaders/subdir/CMakeLists.txt b/Tests/RunCMake/PrecompileHeaders/subdir/CMakeLists.txt new file mode 100644 index 0000000..fa926c4 --- /dev/null +++ b/Tests/RunCMake/PrecompileHeaders/subdir/CMakeLists.txt @@ -0,0 +1,3 @@ +add_executable(foobar ../foobar.c) +target_link_libraries(foobar foo ) +set_target_properties(foobar PROPERTIES PRECOMPILE_HEADERS_REUSE_FROM foo) diff --git a/Tests/RunCMake/add_custom_command/GeneratedProperty.cmake b/Tests/RunCMake/add_custom_command/GeneratedProperty.cmake new file mode 100644 index 0000000..628134b --- /dev/null +++ b/Tests/RunCMake/add_custom_command/GeneratedProperty.cmake @@ -0,0 +1,10 @@ +add_custom_command( + OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/../GeneratedProperty-build/a" + BYPRODUCTS "${CMAKE_CURRENT_BINARY_DIR}/../GeneratedProperty-build/b" + COMMAND c + ) +get_source_file_property(GENERATED_A "${CMAKE_CURRENT_BINARY_DIR}/a" GENERATED) +get_source_file_property(GENERATED_B "${CMAKE_CURRENT_BINARY_DIR}/b" GENERATED) +if(NOT GENERATED_A OR NOT GENERATED_B) + message(FATAL_ERROR "failed") +endif() diff --git a/Tests/RunCMake/add_custom_command/RunCMakeTest.cmake b/Tests/RunCMake/add_custom_command/RunCMakeTest.cmake index 0387dbb..20097b7 100644 --- a/Tests/RunCMake/add_custom_command/RunCMakeTest.cmake +++ b/Tests/RunCMake/add_custom_command/RunCMakeTest.cmake @@ -3,6 +3,7 @@ include(RunCMake) run_cmake(AppendNoOutput) run_cmake(AppendNotOutput) run_cmake(BadArgument) +run_cmake(GeneratedProperty) run_cmake(NoArguments) run_cmake(NoOutputOrTarget) run_cmake(OutputAndTarget) diff --git a/Tests/RunCMake/add_custom_target/GeneratedProperty.cmake b/Tests/RunCMake/add_custom_target/GeneratedProperty.cmake new file mode 100644 index 0000000..d034534 --- /dev/null +++ b/Tests/RunCMake/add_custom_target/GeneratedProperty.cmake @@ -0,0 +1,14 @@ +add_custom_command( + OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/../GeneratedProperty-build/a" + COMMAND b + ) +add_custom_target(CollapseFullPath + DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/a" + BYPRODUCTS "${CMAKE_CURRENT_BINARY_DIR}/../GeneratedProperty-build/c" + COMMAND d + ) +get_source_file_property(GENERATED_A "${CMAKE_CURRENT_BINARY_DIR}/a" GENERATED) +get_source_file_property(GENERATED_C "${CMAKE_CURRENT_BINARY_DIR}/c" GENERATED) +if(NOT GENERATED_A OR NOT GENERATED_C) + message(FATAL_ERROR "failed") +endif() diff --git a/Tests/RunCMake/add_custom_target/RunCMakeTest.cmake b/Tests/RunCMake/add_custom_target/RunCMakeTest.cmake index 2caed03..d80ca19 100644 --- a/Tests/RunCMake/add_custom_target/RunCMakeTest.cmake +++ b/Tests/RunCMake/add_custom_target/RunCMakeTest.cmake @@ -1,6 +1,7 @@ include(RunCMake) run_cmake(CommandExpandsEmpty) +run_cmake(GeneratedProperty) run_cmake(NoArguments) run_cmake(BadTargetName) run_cmake(ByproductsNoCommand) |