diff options
74 files changed, 726 insertions, 281 deletions
diff --git a/Help/command/file.rst b/Help/command/file.rst index 0664e7c..f99021e 100644 --- a/Help/command/file.rst +++ b/Help/command/file.rst @@ -292,7 +292,8 @@ Move a file or directory within a filesystem from ``<oldname>`` to Remove the given files. The ``REMOVE_RECURSE`` mode will remove the given files and directories, also non-empty directories. No error is emitted if a -given file does not exist. +given file does not exist. Relative input paths are evaluated with respect +to the current source directory. Empty input paths are ignored with a warning. .. _MAKE_DIRECTORY: diff --git a/Help/command/find_package.rst b/Help/command/find_package.rst index eb44eb2..e5e5b2c 100644 --- a/Help/command/find_package.rst +++ b/Help/command/find_package.rst @@ -59,6 +59,13 @@ for finding the package, checking the version, and producing any needed messages. Some find-modules provide limited or no support for versioning; check the module documentation. +If the ``MODULE`` option is not specfied in the above signature, +CMake first searches for the package using Module mode. Then, if the +package is not found, it searches again using Config mode. A user +may set the variable :variable:`CMAKE_FIND_PACKAGE_PREFER_CONFIG` to +``TRUE`` to direct CMake first search using Config mode before falling +back to Module mode. + Full Signature and Config Mode ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/Help/envvar/CMAKE_GENERATOR.rst b/Help/envvar/CMAKE_GENERATOR.rst new file mode 100644 index 0000000..f2d055f --- /dev/null +++ b/Help/envvar/CMAKE_GENERATOR.rst @@ -0,0 +1,16 @@ +CMAKE_GENERATOR +--------------- + +.. include:: ENV_VAR.txt + +Specifies the CMake default generator to use when no generator is supplied +with ``-G``. If the provided value doesn't name a generator known by CMake, +the internal default is used. Either way the resulting generator selection +is stored in the :variable:`CMAKE_GENERATOR` variable. + +Some generators may be additionally configured using the environment +variables: + +* :envvar:`CMAKE_GENERATOR_PLATFORM` +* :envvar:`CMAKE_GENERATOR_TOOLSET` +* :envvar:`CMAKE_GENERATOR_INSTANCE` diff --git a/Help/envvar/CMAKE_GENERATOR_INSTANCE.rst b/Help/envvar/CMAKE_GENERATOR_INSTANCE.rst new file mode 100644 index 0000000..1654fa1 --- /dev/null +++ b/Help/envvar/CMAKE_GENERATOR_INSTANCE.rst @@ -0,0 +1,7 @@ +CMAKE_GENERATOR_INSTANCE +------------------------ + +.. include:: ENV_VAR.txt + +Default value for :variable:`CMAKE_GENERATOR_INSTANCE` if no Cache entry is +present. This value is only applied if :envvar:`CMAKE_GENERATOR` is set. diff --git a/Help/envvar/CMAKE_GENERATOR_PLATFORM.rst b/Help/envvar/CMAKE_GENERATOR_PLATFORM.rst new file mode 100644 index 0000000..917b30b --- /dev/null +++ b/Help/envvar/CMAKE_GENERATOR_PLATFORM.rst @@ -0,0 +1,8 @@ +CMAKE_GENERATOR_PLATFORM +------------------------ + +.. include:: ENV_VAR.txt + +Default value for :variable:`CMAKE_GENERATOR_PLATFORM` if no Cache entry +is present and no value is specified by :manual:`cmake(1)` ``-A`` option. +This value is only applied if :envvar:`CMAKE_GENERATOR` is set. diff --git a/Help/envvar/CMAKE_GENERATOR_TOOLSET.rst b/Help/envvar/CMAKE_GENERATOR_TOOLSET.rst new file mode 100644 index 0000000..7ac3856 --- /dev/null +++ b/Help/envvar/CMAKE_GENERATOR_TOOLSET.rst @@ -0,0 +1,8 @@ +CMAKE_GENERATOR_TOOLSET +----------------------- + +.. include:: ENV_VAR.txt + +Default value for :variable:`CMAKE_GENERATOR_TOOLSET` if no Cache entry +is present and no value is specified by :manual:`cmake(1)` ``-T`` option. +This value is only applied if :envvar:`CMAKE_GENERATOR` is set. diff --git a/Help/manual/OPTIONS_BUILD.txt b/Help/manual/OPTIONS_BUILD.txt index 64fd816..810aaa9 100644 --- a/Help/manual/OPTIONS_BUILD.txt +++ b/Help/manual/OPTIONS_BUILD.txt @@ -56,6 +56,9 @@ build system. Possible generator names are specified in the :manual:`cmake-generators(7)` manual. + If not specified, CMake checks the :envvar:`CMAKE_GENERATOR` environment + variable and otherwise falls back to a builtin default selection. + ``-T <toolset-spec>`` Toolset specification for the generator, if supported. diff --git a/Help/manual/cmake-env-variables.7.rst b/Help/manual/cmake-env-variables.7.rst index f106f28..96ceb94 100644 --- a/Help/manual/cmake-env-variables.7.rst +++ b/Help/manual/cmake-env-variables.7.rst @@ -23,6 +23,10 @@ Environment Variables that Control the Build /envvar/CMAKE_BUILD_PARALLEL_LEVEL /envvar/CMAKE_CONFIG_TYPE + /envvar/CMAKE_GENERATOR + /envvar/CMAKE_GENERATOR_INSTANCE + /envvar/CMAKE_GENERATOR_PLATFORM + /envvar/CMAKE_GENERATOR_TOOLSET /envvar/CMAKE_MSVCIDE_RUN_PATH /envvar/CMAKE_NO_VERBOSE /envvar/CMAKE_OSX_ARCHITECTURES diff --git a/Help/manual/cmake-variables.7.rst b/Help/manual/cmake-variables.7.rst index fd5e28f..1011ed2 100644 --- a/Help/manual/cmake-variables.7.rst +++ b/Help/manual/cmake-variables.7.rst @@ -172,6 +172,7 @@ Variables that Change Behavior /variable/CMAKE_FIND_NO_INSTALL_PREFIX /variable/CMAKE_FIND_PACKAGE_NO_PACKAGE_REGISTRY /variable/CMAKE_FIND_PACKAGE_NO_SYSTEM_PACKAGE_REGISTRY + /variable/CMAKE_FIND_PACKAGE_PREFER_CONFIG /variable/CMAKE_FIND_PACKAGE_RESOLVE_SYMLINKS /variable/CMAKE_FIND_PACKAGE_WARN_NO_MODULE /variable/CMAKE_FIND_ROOT_PATH diff --git a/Help/release/dev/default-generator-env.rst b/Help/release/dev/default-generator-env.rst new file mode 100644 index 0000000..3f20475 --- /dev/null +++ b/Help/release/dev/default-generator-env.rst @@ -0,0 +1,9 @@ +default-generator-env +--------------------- + +* The :envvar:`CMAKE_GENERATOR` environment variable was added + to specify a default generator to use when :manual:`cmake(1)` is + run without a ``-G`` option. Additionally, environment variables + :envvar:`CMAKE_GENERATOR_PLATFORM`, :envvar:`CMAKE_GENERATOR_TOOLSET`, + and :envvar:`CMAKE_GENERATOR_INSTANCE` were created to configure + the generator. diff --git a/Help/release/dev/file-remove-no-empty.rst b/Help/release/dev/file-remove-no-empty.rst new file mode 100644 index 0000000..0a68d67 --- /dev/null +++ b/Help/release/dev/file-remove-no-empty.rst @@ -0,0 +1,6 @@ +file-remove-no-empty +-------------------- + +* The :command:`file(REMOVE)` and :command:`file(REMOVE_RECURSE)` commands + were changed to ignore empty arguments with a warning instead of treating + them as a relative path and removing the contents of the current directory. diff --git a/Help/release/dev/find-package-prefer-config.rst b/Help/release/dev/find-package-prefer-config.rst new file mode 100644 index 0000000..377e8c5 --- /dev/null +++ b/Help/release/dev/find-package-prefer-config.rst @@ -0,0 +1,6 @@ +find-package-prefer-config +-------------------------- + +* Variable :variable:`CMAKE_FIND_PACKAGE_PREFER_CONFIG` was added to tell + :command:`find_package` calls to look for a package configuration + file first even if a find module is available. diff --git a/Help/variable/CMAKE_FIND_PACKAGE_PREFER_CONFIG.rst b/Help/variable/CMAKE_FIND_PACKAGE_PREFER_CONFIG.rst new file mode 100644 index 0000000..db658a1 --- /dev/null +++ b/Help/variable/CMAKE_FIND_PACKAGE_PREFER_CONFIG.rst @@ -0,0 +1,27 @@ +CMAKE_FIND_PACKAGE_PREFER_CONFIG +--------------------------------- + +Tell :command:`find_package` to try "Config" mode before "Module" mode if no +mode was specified. + +The command :command:`find_package` operates without an explicit mode when +the reduced signature is used without the ``MODULE`` option. In this case, +by default, CMake first tries Module mode by searching for a +``Find<pkg>.cmake`` module. If it fails, CMake then searches for the package +using Config mode. + +Set ``CMAKE_FIND_PACKAGE_PREFER_CONFIG`` to ``TRUE`` to tell +:command:`find_package` to first search using Config mode before falling back +to Module mode. + +This variable may be useful when a developer has compiled a custom version of +a common library and wishes to link it to a dependent project. If this +variable is set to ``TRUE``, it would prevent a dependent project's call +to :command:`find_package` from selecting the default library located by the +system's ``Find<pkg>.cmake`` module before finding the developer's custom +built library. + +Once this variable is set, it is the responsibility of the exported +``<pkg>Config.cmake`` files to provide the same result variables as the +``Find<pkg>.cmake`` modules so that dependent projects can use them +interchangeably. diff --git a/Help/variable/CMAKE_FIND_PACKAGE_WARN_NO_MODULE.rst b/Help/variable/CMAKE_FIND_PACKAGE_WARN_NO_MODULE.rst index f1116bb..5c4f23a 100644 --- a/Help/variable/CMAKE_FIND_PACKAGE_WARN_NO_MODULE.rst +++ b/Help/variable/CMAKE_FIND_PACKAGE_WARN_NO_MODULE.rst @@ -17,3 +17,6 @@ Set ``CMAKE_FIND_PACKAGE_WARN_NO_MODULE`` to ``TRUE`` to tell :command:`find_package` to warn when it implicitly assumes Config mode. This helps developers enforce use of an explicit mode in all calls to :command:`find_package` within a project. + +This variable has no effect if :variable:`CMAKE_FIND_PACKAGE_PREFER_CONFIG` is +set to ``TRUE``. diff --git a/Help/variable/CMAKE_GENERATOR.rst b/Help/variable/CMAKE_GENERATOR.rst index cce04c1..ec52cd4 100644 --- a/Help/variable/CMAKE_GENERATOR.rst +++ b/Help/variable/CMAKE_GENERATOR.rst @@ -5,3 +5,8 @@ The generator used to build the project. See :manual:`cmake-generators(7)`. The name of the generator that is being used to generate the build files. (e.g. ``Unix Makefiles``, ``Ninja``, etc.) + +The value of this variable should never be modified by project code. +A generator may be selected via the :manual:`cmake(1)` ``-G`` option, +interactively in :manual:`cmake-gui(1)`, or via the :envvar:`CMAKE_GENERATOR` +environment variable. diff --git a/Help/variable/CMAKE_GENERATOR_INSTANCE.rst b/Help/variable/CMAKE_GENERATOR_INSTANCE.rst index 78c81b1..3657ed4 100644 --- a/Help/variable/CMAKE_GENERATOR_INSTANCE.rst +++ b/Help/variable/CMAKE_GENERATOR_INSTANCE.rst @@ -5,9 +5,10 @@ Generator-specific instance specification provided by user. Some CMake generators support selection of an instance of the native build system when multiple instances are available. If the user specifies an -instance (e.g. by setting this cache entry), or after a default instance is -chosen when a build tree is first configured, the value will be available in -this variable. +instance (e.g. by setting this cache entry or via the +:envvar:`CMAKE_GENERATOR_INSTANCE` environment variable), or after a default +instance is chosen when a build tree is first configured, the value will be +available in this variable. The value of this variable should never be modified by project code. A toolchain file specified by the :variable:`CMAKE_TOOLCHAIN_FILE` diff --git a/Help/variable/CMAKE_GENERATOR_PLATFORM.rst b/Help/variable/CMAKE_GENERATOR_PLATFORM.rst index 963f0a4..2c115a3 100644 --- a/Help/variable/CMAKE_GENERATOR_PLATFORM.rst +++ b/Help/variable/CMAKE_GENERATOR_PLATFORM.rst @@ -6,7 +6,8 @@ Generator-specific target platform specification provided by user. Some CMake generators support a target platform name to be given to the native build system to choose a compiler toolchain. If the user specifies a platform name (e.g. via the :manual:`cmake(1)` ``-A`` -option) the value will be available in this variable. +option or via the :envvar:`CMAKE_GENERATOR_PLATFORM` environment variable) +the value will be available in this variable. The value of this variable should never be modified by project code. A toolchain file specified by the :variable:`CMAKE_TOOLCHAIN_FILE` diff --git a/Help/variable/CMAKE_GENERATOR_TOOLSET.rst b/Help/variable/CMAKE_GENERATOR_TOOLSET.rst index e77f211..a01a8b7 100644 --- a/Help/variable/CMAKE_GENERATOR_TOOLSET.rst +++ b/Help/variable/CMAKE_GENERATOR_TOOLSET.rst @@ -5,7 +5,8 @@ Native build system toolset specification provided by user. Some CMake generators support a toolset specification to tell the native build system how to choose a compiler. If the user specifies -a toolset (e.g. via the :manual:`cmake(1)` ``-T`` option) the value +a toolset (e.g. via the :manual:`cmake(1)` ``-T`` option or via +the :envvar:`CMAKE_GENERATOR_TOOLSET` environment variable) the value will be available in this variable. The value of this variable should never be modified by project code. diff --git a/Modules/CMakeDetermineASMCompiler.cmake b/Modules/CMakeDetermineASMCompiler.cmake index fb005ff..a48d33c 100644 --- a/Modules/CMakeDetermineASMCompiler.cmake +++ b/Modules/CMakeDetermineASMCompiler.cmake @@ -145,7 +145,7 @@ if(CMAKE_ASM${ASM_DIALECT}_COMPILER_ID) else() set(_version "") endif() - if(CMAKE_ASM${ASM_DIALECT}_COMPILER_ARCHITECTURE_ID) + if(CMAKE_ASM${ASM_DIALECT}_COMPILER_ARCHITECTURE_ID AND "x${CMAKE_ASM${ASM_DIALECT}_COMPILER_ID}" STREQUAL "xIAR") set(_archid " ${CMAKE_ASM${ASM_DIALECT}_COMPILER_ARCHITECTURE_ID}") else() set(_archid "") diff --git a/Modules/CMakeDetermineCompilerId.cmake b/Modules/CMakeDetermineCompilerId.cmake index 7036b93..c7e5685 100644 --- a/Modules/CMakeDetermineCompilerId.cmake +++ b/Modules/CMakeDetermineCompilerId.cmake @@ -143,7 +143,7 @@ function(CMAKE_DETERMINE_COMPILER_ID lang flagvar src) else() set(_version "") endif() - if(CMAKE_${lang}_COMPILER_ARCHITECTURE_ID) + if(CMAKE_${lang}_COMPILER_ARCHITECTURE_ID AND "x${CMAKE_${lang}_COMPILER_ID}" STREQUAL "xIAR") set(_archid " ${CMAKE_${lang}_COMPILER_ARCHITECTURE_ID}") else() set(_archid "") @@ -276,8 +276,8 @@ Id flags: ${testflags} ${CMAKE_${lang}_COMPILER_ID_FLAGS_ALWAYS} else() set(id_system "") endif() - if(id_system AND CMAKE_SYSTEM_VERSION) - set(id_system_version "<ApplicationTypeRevision>${CMAKE_SYSTEM_VERSION}</ApplicationTypeRevision>") + if(id_system AND CMAKE_SYSTEM_VERSION MATCHES "^([0-9]+\\.[0-9]+)") + set(id_system_version "<ApplicationTypeRevision>${CMAKE_MATCH_1}</ApplicationTypeRevision>") else() set(id_system_version "") endif() diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index 8483f77..695e075 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -788,6 +788,8 @@ set(SRCS ${SRCS} cmNinjaUtilityTargetGenerator.h cmNinjaLinkLineComputer.cxx cmNinjaLinkLineComputer.h + cmNinjaLinkLineDeviceComputer.cxx + cmNinjaLinkLineDeviceComputer.h ) # Temporary variable for tools targets diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 4303c25..6948abd 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,5 +1,5 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 14) -set(CMake_VERSION_PATCH 20190521) +set(CMake_VERSION_PATCH 20190523) #set(CMake_VERSION_RC 1) diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx index f522d36..c0e263a 100644 --- a/Source/cmFileCommand.cxx +++ b/Source/cmFileCommand.cxx @@ -1395,6 +1395,12 @@ bool cmFileCommand::HandleRemove(std::vector<std::string> const& args, cmMakeRange(args).advance(1)) // Get rid of subcommand { std::string fileName = arg; + if (fileName.empty()) { + std::string const r = recurse ? "REMOVE_RECURSE" : "REMOVE"; + this->Makefile->IssueMessage(MessageType::AUTHOR_WARNING, + "Ignoring empty file name in " + r + "."); + continue; + } if (!cmsys::SystemTools::FileIsFullPath(fileName)) { fileName = this->Makefile->GetCurrentSourceDirectory(); fileName += "/" + arg; diff --git a/Source/cmFindPackageCommand.cxx b/Source/cmFindPackageCommand.cxx index 7ebd211..8eefaa7 100644 --- a/Source/cmFindPackageCommand.cxx +++ b/Source/cmFindPackageCommand.cxx @@ -498,57 +498,80 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args, this->SetModuleVariables(components); // See if there is a Find<PackageName>.cmake module. - if (this->UseFindModules) { - bool foundModule = false; - if (!this->FindModule(foundModule)) { - this->AppendSuccessInformation(); - return false; + bool loadedPackage = false; + if (this->Makefile->IsOn("CMAKE_FIND_PACKAGE_PREFER_CONFIG")) { + if (this->UseConfigFiles && this->FindPackageUsingConfigMode()) { + loadedPackage = true; + } else if (this->FindPackageUsingModuleMode()) { + loadedPackage = true; } - if (foundModule) { - this->AppendSuccessInformation(); - return true; + } else { + if (this->UseFindModules && this->FindPackageUsingModuleMode()) { + loadedPackage = true; + } else { + // Handle CMAKE_FIND_PACKAGE_WARN_NO_MODULE (warn when CONFIG mode is + // implicitly assumed) + if (this->UseFindModules && this->UseConfigFiles && + this->Makefile->IsOn("CMAKE_FIND_PACKAGE_WARN_NO_MODULE")) { + std::ostringstream aw; + if (this->RequiredCMakeVersion >= CMake_VERSION_ENCODE(2, 8, 8)) { + aw << "find_package called without either MODULE or CONFIG option " + "and " + "no Find" + << this->Name + << ".cmake module is in CMAKE_MODULE_PATH. " + "Add MODULE to exclusively request Module mode and fail if " + "Find" + << this->Name + << ".cmake is missing. " + "Add CONFIG to exclusively request Config mode and search for " + "a " + "package configuration file provided by " + << this->Name << " (" << this->Name << "Config.cmake or " + << cmSystemTools::LowerCase(this->Name) << "-config.cmake). "; + } else { + aw << "find_package called without NO_MODULE option and no " + "Find" + << this->Name + << ".cmake module is in CMAKE_MODULE_PATH. " + "Add NO_MODULE to exclusively request Config mode and search " + "for a " + "package configuration file provided by " + << this->Name << " (" << this->Name << "Config.cmake or " + << cmSystemTools::LowerCase(this->Name) + << "-config.cmake). " + "Otherwise make Find" + << this->Name + << ".cmake available in " + "CMAKE_MODULE_PATH."; + } + aw << "\n" + "(Variable CMAKE_FIND_PACKAGE_WARN_NO_MODULE enabled this " + "warning.)"; + this->Makefile->IssueMessage(MessageType::AUTHOR_WARNING, aw.str()); + } + + if (this->FindPackageUsingConfigMode()) { + loadedPackage = true; + } } } - if (this->UseFindModules && this->UseConfigFiles && - this->Makefile->IsOn("CMAKE_FIND_PACKAGE_WARN_NO_MODULE")) { - std::ostringstream aw; - if (this->RequiredCMakeVersion >= CMake_VERSION_ENCODE(2, 8, 8)) { - aw << "find_package called without either MODULE or CONFIG option and " - "no Find" - << this->Name - << ".cmake module is in CMAKE_MODULE_PATH. " - "Add MODULE to exclusively request Module mode and fail if " - "Find" - << this->Name - << ".cmake is missing. " - "Add CONFIG to exclusively request Config mode and search for a " - "package configuration file provided by " - << this->Name << " (" << this->Name << "Config.cmake or " - << cmSystemTools::LowerCase(this->Name) << "-config.cmake). "; - } else { - aw - << "find_package called without NO_MODULE option and no " - "Find" - << this->Name - << ".cmake module is in CMAKE_MODULE_PATH. " - "Add NO_MODULE to exclusively request Config mode and search for a " - "package configuration file provided by " - << this->Name << " (" << this->Name << "Config.cmake or " - << cmSystemTools::LowerCase(this->Name) - << "-config.cmake). " - "Otherwise make Find" - << this->Name - << ".cmake available in " - "CMAKE_MODULE_PATH."; - } - aw << "\n" - "(Variable CMAKE_FIND_PACKAGE_WARN_NO_MODULE enabled this warning.)"; - this->Makefile->IssueMessage(MessageType::AUTHOR_WARNING, aw.str()); - } - - // No find module. Assume the project has a CMake config file. Use - // a <PackageName>_DIR cache variable to locate it. + this->AppendSuccessInformation(); + return loadedPackage; +} + +bool cmFindPackageCommand::FindPackageUsingModuleMode() +{ + bool foundModule = false; + if (!this->FindModule(foundModule)) { + return false; + } + return foundModule; +} + +bool cmFindPackageCommand::FindPackageUsingConfigMode() +{ this->Variable = this->Name; this->Variable += "_DIR"; @@ -580,9 +603,7 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args, this->IgnoredPaths.insert(ignored.begin(), ignored.end()); // Find and load the package. - bool result = this->HandlePackageMode(); - this->AppendSuccessInformation(); - return result; + return this->HandlePackageMode(); } void cmFindPackageCommand::SetModuleVariables(const std::string& components) diff --git a/Source/cmFindPackageCommand.h b/Source/cmFindPackageCommand.h index a11d253..4f6d97c 100644 --- a/Source/cmFindPackageCommand.h +++ b/Source/cmFindPackageCommand.h @@ -90,6 +90,9 @@ private: static PathLabel SystemRegistry; }; + bool FindPackageUsingModuleMode(); + bool FindPackageUsingConfigMode(); + // Add additional search path labels and groups not present in the // parent class void AppendSearchPathGroups(); diff --git a/Source/cmGlobalVisualStudio10Generator.cxx b/Source/cmGlobalVisualStudio10Generator.cxx index 4fa89d0..55374a4 100644 --- a/Source/cmGlobalVisualStudio10Generator.cxx +++ b/Source/cmGlobalVisualStudio10Generator.cxx @@ -784,11 +784,11 @@ bool cmGlobalVisualStudio10Generator::FindVCTargetsPath(cmMakefile* mf) if (this->GetSystemName() == "WindowsPhone") { cmXMLElement(epg, "ApplicationType").Content("Windows Phone"); cmXMLElement(epg, "ApplicationTypeRevision") - .Content(this->GetSystemVersion()); + .Content(this->GetApplicationTypeRevision()); } else if (this->GetSystemName() == "WindowsStore") { cmXMLElement(epg, "ApplicationType").Content("Windows Store"); cmXMLElement(epg, "ApplicationTypeRevision") - .Content(this->GetSystemVersion()); + .Content(this->GetApplicationTypeRevision()); } if (!this->WindowsTargetPlatformVersion.empty()) { cmXMLElement(epg, "WindowsTargetPlatformVersion") @@ -1112,6 +1112,15 @@ std::string cmGlobalVisualStudio10Generator::GetInstalledNsightTegraVersion() return version; } +std::string cmGlobalVisualStudio10Generator::GetApplicationTypeRevision() const +{ + // Return the first two '.'-separated components of the Windows version. + std::string::size_type end1 = this->SystemVersion.find('.'); + std::string::size_type end2 = + end1 == std::string::npos ? end1 : this->SystemVersion.find('.', end1 + 1); + return this->SystemVersion.substr(0, end2); +} + static std::string cmLoadFlagTableString(Json::Value entry, const char* field) { if (entry.isMember(field)) { diff --git a/Source/cmGlobalVisualStudio10Generator.h b/Source/cmGlobalVisualStudio10Generator.h index 2f532a6..1d30cd6 100644 --- a/Source/cmGlobalVisualStudio10Generator.h +++ b/Source/cmGlobalVisualStudio10Generator.h @@ -110,6 +110,9 @@ public: static std::string GetInstalledNsightTegraVersion(); + /** Return the first two components of CMAKE_SYSTEM_VERSION. */ + std::string GetApplicationTypeRevision() const; + cmIDEFlagTable const* GetClFlagTable() const; cmIDEFlagTable const* GetCSharpFlagTable() const; cmIDEFlagTable const* GetRcFlagTable() const; diff --git a/Source/cmLinkLineDeviceComputer.cxx b/Source/cmLinkLineDeviceComputer.cxx index 211d03b..6cfe5bb 100644 --- a/Source/cmLinkLineDeviceComputer.cxx +++ b/Source/cmLinkLineDeviceComputer.cxx @@ -3,15 +3,20 @@ #include "cmLinkLineDeviceComputer.h" +#include <algorithm> #include <set> #include <sstream> #include <utility> +#include <vector> #include "cmAlgorithms.h" #include "cmComputeLinkInformation.h" #include "cmGeneratorTarget.h" -#include "cmGlobalNinjaGenerator.h" +#include "cmLocalGenerator.h" +#include "cmStateDirectory.h" +#include "cmStateSnapshot.h" #include "cmStateTypes.h" +#include "cmSystemTools.h" class cmOutputConverter; @@ -41,6 +46,27 @@ static bool cmLinkItemValidForDevice(std::string const& item) cmHasLiteralPrefix(item, "--library")); } +bool cmLinkLineDeviceComputer::ComputeRequiresDeviceLinking( + cmComputeLinkInformation& cli) +{ + // Determine if this item might requires device linking. + // For this we only consider targets + typedef cmComputeLinkInformation::ItemVector ItemVector; + ItemVector const& items = cli.GetItems(); + std::string config = cli.GetConfig(); + for (auto const& item : items) { + if (item.Target && + item.Target->GetType() == cmStateEnums::STATIC_LIBRARY) { + if ((!item.Target->GetPropertyAsBool("CUDA_RESOLVE_DEVICE_SYMBOLS")) && + item.Target->GetPropertyAsBool("CUDA_SEPARABLE_COMPILATION")) { + // this dependency requires us to device link it + return true; + } + } + } + return false; +} + std::string cmLinkLineDeviceComputer::ComputeLinkLibraries( cmComputeLinkInformation& cli, std::string const& stdLibString) { @@ -63,17 +89,12 @@ std::string cmLinkLineDeviceComputer::ComputeLinkLibraries( } if (item.Target) { - bool skip = false; - switch (item.Target->GetType()) { - case cmStateEnums::MODULE_LIBRARY: - case cmStateEnums::INTERFACE_LIBRARY: - skip = true; - break; - case cmStateEnums::STATIC_LIBRARY: - skip = item.Target->GetPropertyAsBool("CUDA_RESOLVE_DEVICE_SYMBOLS"); - break; - default: - break; + bool skip = true; + if (item.Target->GetType() == cmStateEnums::STATIC_LIBRARY) { + if ((!item.Target->GetPropertyAsBool("CUDA_RESOLVE_DEVICE_SYMBOLS")) && + item.Target->GetPropertyAsBool("CUDA_SEPARABLE_COMPILATION")) { + skip = false; + } } if (skip) { continue; @@ -118,16 +139,55 @@ std::string cmLinkLineDeviceComputer::GetLinkerLanguage(cmGeneratorTarget*, return "CUDA"; } -cmNinjaLinkLineDeviceComputer::cmNinjaLinkLineDeviceComputer( - cmOutputConverter* outputConverter, cmStateDirectory const& stateDir, - cmGlobalNinjaGenerator const* gg) - : cmLinkLineDeviceComputer(outputConverter, stateDir) - , GG(gg) +bool requireDeviceLinking(cmGeneratorTarget& target, cmLocalGenerator& lg, + const std::string& config) { -} -std::string cmNinjaLinkLineDeviceComputer::ConvertToLinkReference( - std::string const& lib) const -{ - return GG->ConvertToNinjaPath(lib); + if (target.GetType() == cmStateEnums::OBJECT_LIBRARY) { + return false; + } + + if (const char* resolveDeviceSymbols = + target.GetProperty("CUDA_RESOLVE_DEVICE_SYMBOLS")) { + // If CUDA_RESOLVE_DEVICE_SYMBOLS has been explicitly set we need + // to honor the value no matter what it is. + return cmSystemTools::IsOn(resolveDeviceSymbols); + } + + if (const char* separableCompilation = + target.GetProperty("CUDA_SEPARABLE_COMPILATION")) { + if (cmSystemTools::IsOn(separableCompilation)) { + bool doDeviceLinking = false; + switch (target.GetType()) { + case cmStateEnums::SHARED_LIBRARY: + case cmStateEnums::MODULE_LIBRARY: + case cmStateEnums::EXECUTABLE: + doDeviceLinking = true; + break; + default: + break; + } + return doDeviceLinking; + } + } + + // Determine if we have any dependencies that require + // us to do a device link step + const std::string cuda_lang("CUDA"); + cmGeneratorTarget::LinkClosure const* closure = + target.GetLinkClosure(config); + + bool closureHasCUDA = + (std::find(closure->Languages.begin(), closure->Languages.end(), + cuda_lang) != closure->Languages.end()); + if (closureHasCUDA) { + cmComputeLinkInformation* pcli = target.GetLinkInformation(config); + if (pcli) { + cmLinkLineDeviceComputer deviceLinkComputer( + &lg, lg.GetStateSnapshot().GetDirectory()); + return deviceLinkComputer.ComputeRequiresDeviceLinking(*pcli); + } + return true; + } + return false; } diff --git a/Source/cmLinkLineDeviceComputer.h b/Source/cmLinkLineDeviceComputer.h index cf66f64..0ea5f69 100644 --- a/Source/cmLinkLineDeviceComputer.h +++ b/Source/cmLinkLineDeviceComputer.h @@ -12,7 +12,7 @@ class cmComputeLinkInformation; class cmGeneratorTarget; -class cmGlobalNinjaGenerator; +class cmLocalGenerator; class cmOutputConverter; class cmStateDirectory; @@ -27,6 +27,8 @@ public: cmLinkLineDeviceComputer& operator=(cmLinkLineDeviceComputer const&) = delete; + bool ComputeRequiresDeviceLinking(cmComputeLinkInformation& cli); + std::string ComputeLinkLibraries(cmComputeLinkInformation& cli, std::string const& stdLibString) override; @@ -34,21 +36,7 @@ public: std::string const& config) override; }; -class cmNinjaLinkLineDeviceComputer : public cmLinkLineDeviceComputer -{ -public: - cmNinjaLinkLineDeviceComputer(cmOutputConverter* outputConverter, - cmStateDirectory const& stateDir, - cmGlobalNinjaGenerator const* gg); - - cmNinjaLinkLineDeviceComputer(cmNinjaLinkLineDeviceComputer const&) = delete; - cmNinjaLinkLineDeviceComputer& operator=( - cmNinjaLinkLineDeviceComputer const&) = delete; - - std::string ConvertToLinkReference(std::string const& input) const override; - -private: - cmGlobalNinjaGenerator const* GG; -}; +bool requireDeviceLinking(cmGeneratorTarget& target, cmLocalGenerator& lg, + const std::string& config); #endif diff --git a/Source/cmMakefileExecutableTargetGenerator.cxx b/Source/cmMakefileExecutableTargetGenerator.cxx index 9b21739..571da1a 100644 --- a/Source/cmMakefileExecutableTargetGenerator.cxx +++ b/Source/cmMakefileExecutableTargetGenerator.cxx @@ -2,7 +2,6 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmMakefileExecutableTargetGenerator.h" -#include <algorithm> #include <memory> // IWYU pragma: keep #include <set> #include <sstream> @@ -87,20 +86,9 @@ void cmMakefileExecutableTargetGenerator::WriteDeviceExecutableRule( return; } - const std::string cuda_lang("CUDA"); - cmGeneratorTarget::LinkClosure const* closure = - this->GeneratorTarget->GetLinkClosure(this->ConfigName); - - const bool hasCUDA = - (std::find(closure->Languages.begin(), closure->Languages.end(), - cuda_lang) != closure->Languages.end()); - - bool doDeviceLinking = true; - if (const char* resolveDeviceSymbols = - this->GeneratorTarget->GetProperty("CUDA_RESOLVE_DEVICE_SYMBOLS")) { - doDeviceLinking = cmSystemTools::IsOn(resolveDeviceSymbols); - } - if (!hasCUDA || !doDeviceLinking) { + bool requiresDeviceLinking = requireDeviceLinking( + *this->GeneratorTarget, *this->LocalGenerator, this->ConfigName); + if (!requiresDeviceLinking) { return; } diff --git a/Source/cmMakefileLibraryTargetGenerator.cxx b/Source/cmMakefileLibraryTargetGenerator.cxx index f5d1fc9..d4d565d 100644 --- a/Source/cmMakefileLibraryTargetGenerator.cxx +++ b/Source/cmMakefileLibraryTargetGenerator.cxx @@ -2,7 +2,6 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmMakefileLibraryTargetGenerator.h" -#include <algorithm> #include <memory> // IWYU pragma: keep #include <set> #include <sstream> @@ -124,20 +123,10 @@ void cmMakefileLibraryTargetGenerator::WriteObjectLibraryRules() void cmMakefileLibraryTargetGenerator::WriteStaticLibraryRules() { - const std::string cuda_lang("CUDA"); - cmGeneratorTarget::LinkClosure const* closure = - this->GeneratorTarget->GetLinkClosure(this->ConfigName); - - const bool hasCUDA = - (std::find(closure->Languages.begin(), closure->Languages.end(), - cuda_lang) != closure->Languages.end()); - - bool doDeviceLinking = false; - if (const char* resolveDeviceSymbols = - this->GeneratorTarget->GetProperty("CUDA_RESOLVE_DEVICE_SYMBOLS")) { - doDeviceLinking = cmSystemTools::IsOn(resolveDeviceSymbols); - } - if (hasCUDA && doDeviceLinking) { + + bool requiresDeviceLinking = requireDeviceLinking( + *this->GeneratorTarget, *this->LocalGenerator, this->ConfigName); + if (requiresDeviceLinking) { std::string linkRuleVar = "CMAKE_CUDA_DEVICE_LINK_LIBRARY"; this->WriteDeviceLibraryRules(linkRuleVar, false); } @@ -163,19 +152,9 @@ void cmMakefileLibraryTargetGenerator::WriteSharedLibraryRules(bool relink) } if (!relink) { - const std::string cuda_lang("CUDA"); - cmGeneratorTarget::LinkClosure const* closure = - this->GeneratorTarget->GetLinkClosure(this->ConfigName); - - const bool hasCUDA = - (std::find(closure->Languages.begin(), closure->Languages.end(), - cuda_lang) != closure->Languages.end()); - bool doDeviceLinking = true; - if (const char* resolveDeviceSymbols = - this->GeneratorTarget->GetProperty("CUDA_RESOLVE_DEVICE_SYMBOLS")) { - doDeviceLinking = cmSystemTools::IsOn(resolveDeviceSymbols); - } - if (hasCUDA && doDeviceLinking) { + bool requiresDeviceLinking = requireDeviceLinking( + *this->GeneratorTarget, *this->LocalGenerator, this->ConfigName); + if (requiresDeviceLinking) { std::string linkRuleVar = "CMAKE_CUDA_DEVICE_LINK_LIBRARY"; this->WriteDeviceLibraryRules(linkRuleVar, relink); } @@ -209,19 +188,9 @@ void cmMakefileLibraryTargetGenerator::WriteModuleLibraryRules(bool relink) { if (!relink) { - const std::string cuda_lang("CUDA"); - cmGeneratorTarget::LinkClosure const* closure = - this->GeneratorTarget->GetLinkClosure(this->ConfigName); - - const bool hasCUDA = - (std::find(closure->Languages.begin(), closure->Languages.end(), - cuda_lang) != closure->Languages.end()); - bool doDeviceLinking = true; - if (const char* resolveDeviceSymbols = - this->GeneratorTarget->GetProperty("CUDA_RESOLVE_DEVICE_SYMBOLS")) { - doDeviceLinking = cmSystemTools::IsOn(resolveDeviceSymbols); - } - if (hasCUDA && doDeviceLinking) { + bool requiresDeviceLinking = requireDeviceLinking( + *this->GeneratorTarget, *this->LocalGenerator, this->ConfigName); + if (requiresDeviceLinking) { std::string linkRuleVar = "CMAKE_CUDA_DEVICE_LINK_LIBRARY"; this->WriteDeviceLibraryRules(linkRuleVar, relink); } diff --git a/Source/cmNinjaLinkLineDeviceComputer.cxx b/Source/cmNinjaLinkLineDeviceComputer.cxx new file mode 100644 index 0000000..84c1b37 --- /dev/null +++ b/Source/cmNinjaLinkLineDeviceComputer.cxx @@ -0,0 +1,20 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ + +#include "cmNinjaLinkLineDeviceComputer.h" + +#include "cmGlobalNinjaGenerator.h" + +cmNinjaLinkLineDeviceComputer::cmNinjaLinkLineDeviceComputer( + cmOutputConverter* outputConverter, cmStateDirectory const& stateDir, + cmGlobalNinjaGenerator const* gg) + : cmLinkLineDeviceComputer(outputConverter, stateDir) + , GG(gg) +{ +} + +std::string cmNinjaLinkLineDeviceComputer::ConvertToLinkReference( + std::string const& lib) const +{ + return GG->ConvertToNinjaPath(lib); +} diff --git a/Source/cmNinjaLinkLineDeviceComputer.h b/Source/cmNinjaLinkLineDeviceComputer.h new file mode 100644 index 0000000..84ced5b --- /dev/null +++ b/Source/cmNinjaLinkLineDeviceComputer.h @@ -0,0 +1,34 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ + +#ifndef cmNinjaLinkLineDeviceComputer_h +#define cmNinjaLinkLineDeviceComputer_h + +#include "cmConfigure.h" // IWYU pragma: keep + +#include <string> + +#include "cmLinkLineDeviceComputer.h" + +class cmGlobalNinjaGenerator; +class cmOutputConverter; +class cmStateDirectory; + +class cmNinjaLinkLineDeviceComputer : public cmLinkLineDeviceComputer +{ +public: + cmNinjaLinkLineDeviceComputer(cmOutputConverter* outputConverter, + cmStateDirectory const& stateDir, + cmGlobalNinjaGenerator const* gg); + + cmNinjaLinkLineDeviceComputer(cmNinjaLinkLineDeviceComputer const&) = delete; + cmNinjaLinkLineDeviceComputer& operator=( + cmNinjaLinkLineDeviceComputer const&) = delete; + + std::string ConvertToLinkReference(std::string const& input) const override; + +private: + cmGlobalNinjaGenerator const* GG; +}; + +#endif diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx index 06063b2..1221a3f 100644 --- a/Source/cmNinjaNormalTargetGenerator.cxx +++ b/Source/cmNinjaNormalTargetGenerator.cxx @@ -22,6 +22,7 @@ #include "cmLocalGenerator.h" #include "cmLocalNinjaGenerator.h" #include "cmMakefile.h" +#include "cmNinjaLinkLineDeviceComputer.h" #include "cmNinjaTypes.h" #include "cmOSXBundleGenerator.h" #include "cmOutputConverter.h" @@ -574,32 +575,9 @@ void cmNinjaNormalTargetGenerator::WriteDeviceLinkStatement() cmGeneratorTarget& genTarget = *this->GetGeneratorTarget(); - // determine if we need to do any device linking for this target - const std::string cuda_lang("CUDA"); - cmGeneratorTarget::LinkClosure const* closure = - genTarget.GetLinkClosure(this->GetConfigName()); - - const bool hasCUDA = - (std::find(closure->Languages.begin(), closure->Languages.end(), - cuda_lang) != closure->Languages.end()); - - bool doDeviceLinking = false; - if (const char* resolveDeviceSymbols = - genTarget.GetProperty("CUDA_RESOLVE_DEVICE_SYMBOLS")) { - doDeviceLinking = cmSystemTools::IsOn(resolveDeviceSymbols); - } else { - switch (genTarget.GetType()) { - case cmStateEnums::SHARED_LIBRARY: - case cmStateEnums::MODULE_LIBRARY: - case cmStateEnums::EXECUTABLE: - doDeviceLinking = true; - break; - default: - break; - } - } - - if (!(doDeviceLinking && hasCUDA)) { + bool requiresDeviceLinking = requireDeviceLinking( + *this->GeneratorTarget, *this->GetLocalGenerator(), this->ConfigName); + if (!requiresDeviceLinking) { return; } @@ -814,10 +792,15 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement() return targetNames.Base; }(); - vars["SWIFT_MODULE"] = [this]() -> std::string { - cmGeneratorTarget::Names targetNames = - this->GetGeneratorTarget()->GetLibraryNames(this->GetConfigName()); + vars["SWIFT_MODULE_NAME"] = [this]() -> std::string { + if (const char* name = + this->GetGeneratorTarget()->GetProperty("Swift_MODULE_NAME")) { + return name; + } + return this->GetGeneratorTarget()->GetName(); + }(); + vars["SWIFT_MODULE"] = [this](const std::string& module) -> std::string { std::string directory = this->GetLocalGenerator()->GetCurrentBinaryDirectory(); if (const char* prop = this->GetGeneratorTarget()->GetProperty( @@ -825,7 +808,7 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement() directory = prop; } - std::string name = targetNames.Base + ".swiftmodule"; + std::string name = module + ".swiftmodule"; if (const char* prop = this->GetGeneratorTarget()->GetProperty("Swift_MODULE")) { name = prop; @@ -834,15 +817,7 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement() return this->GetLocalGenerator()->ConvertToOutputFormat( this->ConvertToNinjaPath(directory + "/" + name), cmOutputConverter::SHELL); - }(); - - vars["SWIFT_MODULE_NAME"] = [this]() -> std::string { - if (const char* name = - this->GetGeneratorTarget()->GetProperty("Swift_MODULE_NAME")) { - return name; - } - return this->GetGeneratorTarget()->GetName(); - }(); + }(vars["SWIFT_MODULE_NAME"]); vars["SWIFT_OUTPUT_FILE_MAP"] = this->GetLocalGenerator()->ConvertToOutputFormat( @@ -1132,7 +1107,9 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement() this->GetTargetFilePath(this->TargetNames.SharedObject)); // If one link has to be created. if (targetOutputReal == soName || targetOutput == soName) { - symlinkVars["SONAME"] = soName; + symlinkVars["SONAME"] = + this->GetLocalGenerator()->ConvertToOutputFormat( + soName, cmOutputConverter::SHELL); } else { symlinkVars["SONAME"].clear(); symlinks.push_back(soName); diff --git a/Source/cmQtAutoGen.h b/Source/cmQtAutoGen.h index 3a346b5..9c52129 100644 --- a/Source/cmQtAutoGen.h +++ b/Source/cmQtAutoGen.h @@ -5,6 +5,7 @@ #include "cmConfigure.h" // IWYU pragma: keep +#include <memory> // IWYU pragma: keep #include <string> #include <vector> @@ -40,6 +41,15 @@ public: } }; + class CompilerFeatures + { + public: + bool Evaluated = false; + std::string HelpOutput; + std::vector<std::string> ListOptions; + }; + typedef std::shared_ptr<CompilerFeatures> CompilerFeaturesHandle; + /// @brief AutoGen generator type enum class GenT { diff --git a/Source/cmQtAutoGenGlobalInitializer.cxx b/Source/cmQtAutoGenGlobalInitializer.cxx index 59e17d7..ef8a56b 100644 --- a/Source/cmQtAutoGenGlobalInitializer.cxx +++ b/Source/cmQtAutoGenGlobalInitializer.cxx @@ -203,19 +203,16 @@ void cmQtAutoGenGlobalInitializer::AddToGlobalAutoRcc( } } -bool cmQtAutoGenGlobalInitializer::GetExecutableTestOutput( +cmQtAutoGen::CompilerFeaturesHandle +cmQtAutoGenGlobalInitializer::GetCompilerFeatures( std::string const& generator, std::string const& executable, - std::string& error, std::string* output) + std::string& error) { - // Check if we have cached output + // Check if we have cached features { - auto it = this->ExecutableTestOutputs_.find(executable); - if (it != this->ExecutableTestOutputs_.end()) { - // Return output on demand - if (output != nullptr) { - *output = it->second; - } - return true; + auto it = this->CompilerFeatures_.find(executable); + if (it != this->CompilerFeatures_.end()) { + return it->second; } } @@ -226,7 +223,7 @@ bool cmQtAutoGenGlobalInitializer::GetExecutableTestOutput( error += "\" executable "; error += cmQtAutoGen::Quoted(executable); error += " does not exist."; - return false; + return cmQtAutoGen::CompilerFeaturesHandle(); } // Test the executable @@ -234,7 +231,7 @@ bool cmQtAutoGenGlobalInitializer::GetExecutableTestOutput( { std::string stdErr; std::vector<std::string> command; - command.push_back(executable); + command.emplace_back(executable); command.emplace_back("-h"); int retVal = 0; const bool runResult = cmSystemTools::RunSingleCommand( @@ -250,19 +247,19 @@ bool cmQtAutoGenGlobalInitializer::GetExecutableTestOutput( error += stdOut; error += "\n"; error += stdErr; - return false; + return cmQtAutoGen::CompilerFeaturesHandle(); } } - // Return executable output on demand - if (output != nullptr) { - *output = stdOut; - } + // Create valid handle + cmQtAutoGen::CompilerFeaturesHandle res = + std::make_shared<cmQtAutoGen::CompilerFeatures>(); + res->HelpOutput = std::move(stdOut); - // Register executable and output - this->ExecutableTestOutputs_.emplace(executable, std::move(stdOut)); + // Register compiler features + this->CompilerFeatures_.emplace(executable, res); - return true; + return res; } bool cmQtAutoGenGlobalInitializer::generate() diff --git a/Source/cmQtAutoGenGlobalInitializer.h b/Source/cmQtAutoGenGlobalInitializer.h index 77429b7..d56153a 100644 --- a/Source/cmQtAutoGenGlobalInitializer.h +++ b/Source/cmQtAutoGenGlobalInitializer.h @@ -5,6 +5,8 @@ #include "cmConfigure.h" // IWYU pragma: keep +#include "cmQtAutoGen.h" + #include <map> #include <memory> // IWYU pragma: keep #include <string> @@ -68,15 +70,16 @@ private: void AddToGlobalAutoRcc(cmLocalGenerator* localGen, std::string const& targetName); - bool GetExecutableTestOutput(std::string const& generator, - std::string const& executable, - std::string& error, std::string* output); + cmQtAutoGen::CompilerFeaturesHandle GetCompilerFeatures( + std::string const& generator, std::string const& executable, + std::string& error); private: std::vector<std::unique_ptr<cmQtAutoGenInitializer>> Initializers_; std::map<cmLocalGenerator*, std::string> GlobalAutoGenTargets_; std::map<cmLocalGenerator*, std::string> GlobalAutoRccTargets_; - std::unordered_map<std::string, std::string> ExecutableTestOutputs_; + std::unordered_map<std::string, cmQtAutoGen::CompilerFeaturesHandle> + CompilerFeatures_; Keywords const Keywords_; }; diff --git a/Source/cmQtAutoGenInitializer.cxx b/Source/cmQtAutoGenInitializer.cxx index a5e0f32..2d12964 100644 --- a/Source/cmQtAutoGenInitializer.cxx +++ b/Source/cmQtAutoGenInitializer.cxx @@ -511,7 +511,7 @@ bool cmQtAutoGenInitializer::InitMoc() // Moc executable { - if (!this->GetQtExecutable(this->Moc, "moc", false, nullptr)) { + if (!this->GetQtExecutable(this->Moc, "moc", false)) { return false; } // Let the _autogen target depend on the moc executable @@ -565,7 +565,7 @@ bool cmQtAutoGenInitializer::InitUic() // Uic executable { - if (!this->GetQtExecutable(this->Uic, "uic", true, nullptr)) { + if (!this->GetQtExecutable(this->Uic, "uic", true)) { return false; } // Let the _autogen target depend on the uic executable @@ -582,17 +582,22 @@ bool cmQtAutoGenInitializer::InitRcc() { // Rcc executable { - std::string stdOut; - if (!this->GetQtExecutable(this->Rcc, "rcc", false, &stdOut)) { + if (!this->GetQtExecutable(this->Rcc, "rcc", false)) { return false; } - // Evaluate test output - if (this->QtVersion.Major == 5 || this->QtVersion.Major == 6) { - if (stdOut.find("--list") != std::string::npos) { - this->Rcc.ListOptions.emplace_back("--list"); - } else if (stdOut.find("-list") != std::string::npos) { - this->Rcc.ListOptions.emplace_back("-list"); + // Evaluate test output on demand + CompilerFeatures& features = *this->Rcc.ExecutableFeatures; + if (!features.Evaluated) { + // Look for list options + if (this->QtVersion.Major == 5 || this->QtVersion.Major == 6) { + if (features.HelpOutput.find("--list") != std::string::npos) { + features.ListOptions.emplace_back("--list"); + } else if (features.HelpOutput.find("-list") != std::string::npos) { + features.ListOptions.emplace_back("-list"); + } } + // Evaluation finished + features.Evaluated = true; } } @@ -931,7 +936,8 @@ bool cmQtAutoGenInitializer::InitScanFiles() for (Qrc& qrc : this->Rcc.Qrcs) { if (!qrc.Generated) { std::string error; - RccLister const lister(this->Rcc.Executable, this->Rcc.ListOptions); + RccLister const lister(this->Rcc.Executable, + this->Rcc.ExecutableFeatures->ListOptions); if (!lister.list(qrc.QrcFile, qrc.Resources, error)) { cmSystemTools::Error(error); return false; @@ -1437,7 +1443,8 @@ bool cmQtAutoGenInitializer::SetupWriteRccInfo() ofs.Write("# Rcc executable\n"); ofs.Write("ARCC_RCC_EXECUTABLE", this->Rcc.Executable); - ofs.WriteStrings("ARCC_RCC_LIST_OPTIONS", this->Rcc.ListOptions); + ofs.WriteStrings("ARCC_RCC_LIST_OPTIONS", + this->Rcc.ExecutableFeatures->ListOptions); ofs.Write("# Rcc job\n"); ofs.Write("ARCC_LOCK_FILE", qrc.LockFile); @@ -1600,8 +1607,7 @@ cmQtAutoGenInitializer::GetQtVersion(cmGeneratorTarget const* target) bool cmQtAutoGenInitializer::GetQtExecutable(GenVarsT& genVars, const std::string& executable, - bool ignoreMissingTarget, - std::string* output) const + bool ignoreMissingTarget) const { auto print_err = [this, &genVars](std::string const& err) { std::string msg = genVars.GenNameUpper; @@ -1631,9 +1637,9 @@ bool cmQtAutoGenInitializer::GetQtExecutable(GenVarsT& genVars, return false; } - // Check if the provided executable already exists (it's possible for it - // not to exist when building Qt itself). - genVars.ExecutableExists = cmSystemTools::FileExists(genVars.Executable); + // Create empty compiler features. + genVars.ExecutableFeatures = + std::make_shared<cmQtAutoGen::CompilerFeatures>(); return true; } } @@ -1664,6 +1670,9 @@ bool cmQtAutoGenInitializer::GetQtExecutable(GenVarsT& genVars, } } else { if (ignoreMissingTarget) { + // Create empty compiler features. + genVars.ExecutableFeatures = + std::make_shared<cmQtAutoGen::CompilerFeatures>(); return true; } std::string err = "Could not find "; @@ -1675,15 +1684,15 @@ bool cmQtAutoGenInitializer::GetQtExecutable(GenVarsT& genVars, } } - // Test executable + // Get executable features { std::string err; - if (!this->GlobalInitializer->GetExecutableTestOutput( - executable, genVars.Executable, err, output)) { + genVars.ExecutableFeatures = this->GlobalInitializer->GetCompilerFeatures( + executable, genVars.Executable, err); + if (!genVars.ExecutableFeatures) { print_err(err); return false; } - genVars.ExecutableExists = true; } return true; diff --git a/Source/cmQtAutoGenInitializer.h b/Source/cmQtAutoGenInitializer.h index 6d2dcb6..aa073d1 100644 --- a/Source/cmQtAutoGenInitializer.h +++ b/Source/cmQtAutoGenInitializer.h @@ -67,7 +67,7 @@ public: std::string ExecutableTargetName; cmGeneratorTarget* ExecutableTarget = nullptr; std::string Executable; - bool ExecutableExists = false; + CompilerFeaturesHandle ExecutableFeatures; /// @brief Constructor GenVarsT(GenT gen) @@ -148,7 +148,7 @@ private: void AddCleanFile(std::string const& fileName); bool GetQtExecutable(GenVarsT& genVars, const std::string& executable, - bool ignoreMissingTarget, std::string* output) const; + bool ignoreMissingTarget) const; private: cmQtAutoGenGlobalInitializer* GlobalInitializer; @@ -230,7 +230,6 @@ private: struct RccT : public GenVarsT { bool GlobalTarget = false; - std::vector<std::string> ListOptions; std::vector<Qrc> Qrcs; /// @brief Constructor diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx index ab9ef79..d328a8c 100644 --- a/Source/cmVisualStudio10TargetGenerator.cxx +++ b/Source/cmVisualStudio10TargetGenerator.cxx @@ -10,6 +10,7 @@ #include "cmGeneratorExpression.h" #include "cmGeneratorTarget.h" #include "cmGlobalVisualStudio10Generator.h" +#include "cmLinkLineDeviceComputer.h" #include "cmLocalVisualStudio10Generator.h" #include "cmMakefile.h" #include "cmSourceFile.h" @@ -3007,21 +3008,8 @@ bool cmVisualStudio10TargetGenerator::ComputeCudaLinkOptions( Options& cudaLinkOptions = *pOptions; // Determine if we need to do a device link - bool doDeviceLinking = false; - if (const char* resolveDeviceSymbols = - this->GeneratorTarget->GetProperty("CUDA_RESOLVE_DEVICE_SYMBOLS")) { - doDeviceLinking = cmSystemTools::IsOn(resolveDeviceSymbols); - } else { - switch (this->GeneratorTarget->GetType()) { - case cmStateEnums::SHARED_LIBRARY: - case cmStateEnums::MODULE_LIBRARY: - case cmStateEnums::EXECUTABLE: - doDeviceLinking = true; - break; - default: - break; - } - } + bool doDeviceLinking = requireDeviceLinking( + *this->GeneratorTarget, *this->LocalGenerator, configName); cudaLinkOptions.AddFlag("PerformDeviceLink", doDeviceLinking ? "true" : "false"); @@ -4099,29 +4087,29 @@ void cmVisualStudio10TargetGenerator::WriteApplicationTypeSettings(Elem& e1) bool isAppContainer = false; bool const isWindowsPhone = this->GlobalGenerator->TargetsWindowsPhone(); bool const isWindowsStore = this->GlobalGenerator->TargetsWindowsStore(); - std::string const& v = this->GlobalGenerator->GetSystemVersion(); + std::string const& rev = this->GlobalGenerator->GetApplicationTypeRevision(); if (isWindowsPhone || isWindowsStore) { e1.Element("ApplicationType", (isWindowsPhone ? "Windows Phone" : "Windows Store")); e1.Element("DefaultLanguage", "en-US"); - if (cmHasLiteralPrefix(v, "10.0")) { - e1.Element("ApplicationTypeRevision", "10.0"); + if (rev == "10.0") { + e1.Element("ApplicationTypeRevision", rev); // Visual Studio 14.0 is necessary for building 10.0 apps e1.Element("MinimumVisualStudioVersion", "14.0"); if (this->GeneratorTarget->GetType() < cmStateEnums::UTILITY) { isAppContainer = true; } - } else if (v == "8.1") { - e1.Element("ApplicationTypeRevision", v); + } else if (rev == "8.1") { + e1.Element("ApplicationTypeRevision", rev); // Visual Studio 12.0 is necessary for building 8.1 apps e1.Element("MinimumVisualStudioVersion", "12.0"); if (this->GeneratorTarget->GetType() < cmStateEnums::UTILITY) { isAppContainer = true; } - } else if (v == "8.0") { - e1.Element("ApplicationTypeRevision", v); + } else if (rev == "8.0") { + e1.Element("ApplicationTypeRevision", rev); // Visual Studio 11.0 is necessary for building 8.0 apps e1.Element("MinimumVisualStudioVersion", "11.0"); @@ -4153,7 +4141,7 @@ void cmVisualStudio10TargetGenerator::WriteApplicationTypeSettings(Elem& e1) "VS_WINDOWS_TARGET_PLATFORM_MIN_VERSION"); if (targetPlatformMinVersion) { e1.Element("WindowsTargetPlatformMinVersion", targetPlatformMinVersion); - } else if (isWindowsStore && cmHasLiteralPrefix(v, "10.0")) { + } else if (isWindowsStore && rev == "10.0") { // If the min version is not set, then use the TargetPlatformVersion if (!targetPlatformVersion.empty()) { e1.Element("WindowsTargetPlatformMinVersion", targetPlatformVersion); diff --git a/Source/cmake.cxx b/Source/cmake.cxx index 031123a..0762ae1 100644 --- a/Source/cmake.cxx +++ b/Source/cmake.cxx @@ -159,6 +159,9 @@ cmake::cmake(Role role, cmState::Mode mode) #endif this->GlobalGenerator = nullptr; + this->GeneratorInstanceSet = false; + this->GeneratorPlatformSet = false; + this->GeneratorToolsetSet = false; this->CurrentWorkingMode = NORMAL_MODE; #ifdef CMAKE_BUILD_WITH_CMAKE @@ -174,6 +177,10 @@ cmake::cmake(Role role, cmState::Mode mode) this->AddProjectCommands(); } + if (mode == cmState::Project) { + this->LoadEnvironmentPresets(); + } + // Make sure we can capture the build tool output. cmSystemTools::EnableVSConsoleOutput(); @@ -612,6 +619,35 @@ bool cmake::FindPackage(const std::vector<std::string>& args) return packageFound; } +void cmake::LoadEnvironmentPresets() +{ + std::string envGenVar; + bool hasEnvironmentGenerator = false; + if (cmSystemTools::GetEnv("CMAKE_GENERATOR", envGenVar)) { + hasEnvironmentGenerator = true; + this->EnvironmentGenerator = envGenVar; + } + + auto readGeneratorVar = [&](std::string name, std::string& key) { + std::string varValue; + if (cmSystemTools::GetEnv(name, varValue)) { + if (hasEnvironmentGenerator) { + key = varValue; + } else if (!this->GetIsInTryCompile()) { + std::string message = "Warning: Environment variable "; + message += name; + message += " will be ignored, because CMAKE_GENERATOR "; + message += "is not set."; + cmSystemTools::Message(message, "Warning"); + } + } + }; + + readGeneratorVar("CMAKE_GENERATOR_INSTANCE", this->GeneratorInstance); + readGeneratorVar("CMAKE_GENERATOR_PLATFORM", this->GeneratorPlatform); + readGeneratorVar("CMAKE_GENERATOR_TOOLSET", this->GeneratorToolset); +} + // Parse the args void cmake::SetArgs(const std::vector<std::string>& args) { @@ -767,7 +803,7 @@ void cmake::SetArgs(const std::vector<std::string>& args) cmSystemTools::Error("Multiple -A options not allowed"); return; } - this->GeneratorPlatform = value; + this->SetGeneratorPlatform(value); havePlatform = true; } else if (arg.find("-T", 0) == 0) { std::string value = arg.substr(2); @@ -783,7 +819,7 @@ void cmake::SetArgs(const std::vector<std::string>& args) cmSystemTools::Error("Multiple -T options not allowed"); return; } - this->GeneratorToolset = value; + this->SetGeneratorToolset(value); haveToolset = true; } else if (arg.find("-G", 0) == 0) { std::string value = arg.substr(2); @@ -814,6 +850,16 @@ void cmake::SetArgs(const std::vector<std::string>& args) else { this->SetDirectoriesFromFile(arg); } + // Empty instance, platform and toolset if only a generator is specified + if (this->GlobalGenerator) { + this->GeneratorInstance = ""; + if (!this->GeneratorPlatformSet) { + this->GeneratorPlatform = ""; + } + if (!this->GeneratorToolsetSet) { + this->GeneratorToolset = ""; + } + } } const bool haveSourceDir = !this->GetHomeDirectory().empty(); @@ -1446,8 +1492,7 @@ int cmake::ActualConfigure() if (const std::string* instance = this->State->GetInitializedCacheValue("CMAKE_GENERATOR_INSTANCE")) { - if (!this->GeneratorInstance.empty() && - this->GeneratorInstance != *instance) { + if (this->GeneratorInstanceSet && this->GeneratorInstance != *instance) { std::string message = "Error: generator instance: "; message += this->GeneratorInstance; message += "\nDoes not match the instance used previously: "; @@ -1465,7 +1510,7 @@ int cmake::ActualConfigure() if (const std::string* platformName = this->State->GetInitializedCacheValue("CMAKE_GENERATOR_PLATFORM")) { - if (!this->GeneratorPlatform.empty() && + if (this->GeneratorPlatformSet && this->GeneratorPlatform != *platformName) { std::string message = "Error: generator platform: "; message += this->GeneratorPlatform; @@ -1484,7 +1529,7 @@ int cmake::ActualConfigure() if (const std::string* tsName = this->State->GetInitializedCacheValue("CMAKE_GENERATOR_TOOLSET")) { - if (!this->GeneratorToolset.empty() && this->GeneratorToolset != *tsName) { + if (this->GeneratorToolsetSet && this->GeneratorToolset != *tsName) { std::string message = "Error: generator toolset: "; message += this->GeneratorToolset; message += "\nDoes not match the toolset used previously: "; @@ -1562,6 +1607,16 @@ int cmake::ActualConfigure() std::unique_ptr<cmGlobalGenerator> cmake::EvaluateDefaultGlobalGenerator() { + if (!this->EnvironmentGenerator.empty()) { + cmGlobalGenerator* gen = + this->CreateGlobalGenerator(this->EnvironmentGenerator); + if (!gen) { + cmSystemTools::Error("CMAKE_GENERATOR was set but the specified " + "generator doesn't exist. Using CMake default."); + } else { + return std::unique_ptr<cmGlobalGenerator>(gen); + } + } #if defined(_WIN32) && !defined(__CYGWIN__) && !defined(CMAKE_BOOT_MINGW) std::string found; // Try to find the newest VS installed on the computer and diff --git a/Source/cmake.h b/Source/cmake.h index 34d9bcd..4de9d28 100644 --- a/Source/cmake.h +++ b/Source/cmake.h @@ -214,18 +214,21 @@ public: void SetGeneratorInstance(std::string const& instance) { this->GeneratorInstance = instance; + this->GeneratorInstanceSet = true; } //! Set the name of the selected generator-specific platform. void SetGeneratorPlatform(std::string const& ts) { this->GeneratorPlatform = ts; + this->GeneratorPlatformSet = true; } //! Set the name of the selected generator-specific toolset. void SetGeneratorToolset(std::string const& ts) { this->GeneratorToolset = ts; + this->GeneratorToolsetSet = true; } const std::vector<std::string>& GetSourceExtensions() const @@ -276,6 +279,9 @@ public: */ int GetSystemInformation(std::vector<std::string>&); + //! Parse environment variables + void LoadEnvironmentPresets(); + //! Parse command line arguments void SetArgs(const std::vector<std::string>& args); @@ -479,6 +485,9 @@ protected: std::string GeneratorInstance; std::string GeneratorPlatform; std::string GeneratorToolset; + bool GeneratorInstanceSet; + bool GeneratorPlatformSet; + bool GeneratorToolsetSet; //! read in a cmake list file to initialize the cache void ReadListFile(const std::vector<std::string>& args, @@ -521,6 +530,7 @@ private: std::string CheckStampFile; std::string CheckStampList; std::string VSSolutionFile; + std::string EnvironmentGenerator; std::vector<std::string> SourceFileExtensions; std::unordered_set<std::string> SourceFileExtensionsSet; std::vector<std::string> HeaderFileExtensions; diff --git a/Tests/EnforceConfig.cmake.in b/Tests/EnforceConfig.cmake.in index 8c0817c..f84d180 100644 --- a/Tests/EnforceConfig.cmake.in +++ b/Tests/EnforceConfig.cmake.in @@ -23,4 +23,10 @@ if(NOT CTEST_CONFIGURATION_TYPE) message("Guessing configuration ${CTEST_CONFIGURATION_TYPE}") endif() +# Isolate tests from user configuration in the environment. +unset(ENV{CMAKE_GENERATOR}) +unset(ENV{CMAKE_GENERATOR_INSTANCE}) +unset(ENV{CMAKE_GENERATOR_PLATFORM}) +unset(ENV{CMAKE_GENERATOR_TOOLSET}) + @TEST_HOME_ENV_CODE@ diff --git a/Tests/FindPackageTest/CMakeLists.txt b/Tests/FindPackageTest/CMakeLists.txt index 6c876a7..8802b73 100644 --- a/Tests/FindPackageTest/CMakeLists.txt +++ b/Tests/FindPackageTest/CMakeLists.txt @@ -541,7 +541,41 @@ endif() set(SortLib_DIR "" CACHE FILEPATH "Wipe out find results for testing." FORCE) unset(SortLib_VERSION) - unset(CMAKE_FIND_PACKAGE_SORT_ORDER) unset(CMAKE_FIND_PACKAGE_SORT_DIRECTION) set(CMAKE_PREFIX_PATH ) + +############################################################################ +##Test FIND_PACKAGE CMAKE_FIND_PACKAGE_PREFER_CONFIG + +set(CMAKE_PREFIX_PATH ${CMAKE_CURRENT_SOURCE_DIR}/PreferConfig) +set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/PreferConfig) + +# prefer module mode +set(CMAKE_FIND_PACKAGE_PREFER_CONFIG OFF) +unset(ABC_FOUND) +unset(ABC_CONFIG) + +find_package(ABC) +if(NOT ABC_FOUND) + message(SEND_ERROR "Did not find ABC package") +endif() +if(ABC_CONFIG) + message(SEND_ERROR "Incorrectly found ABC in CONFIG mode, expected to find it with MODULE mode") +endif() + +# Now prefer config mode +set(CMAKE_FIND_PACKAGE_PREFER_CONFIG ON) +unset(ABC_FOUND) +unset(ABC_CONFIG) + +find_package(ABC) +if(NOT ABC_FOUND) + message(SEND_ERROR "Did not find ABC package") +endif() +if(NOT ABC_CONFIG) + message(SEND_ERROR "Incorrectly found ABC in MODULE mode, expected to find it with CONFIG mode") +endif() + +set(CMAKE_FIND_PACKAGE_PREFER_CONFIG OFF) +set(CMAKE_PREFIX_PATH) diff --git a/Tests/FindPackageTest/PreferConfig/ABCConfig.cmake b/Tests/FindPackageTest/PreferConfig/ABCConfig.cmake new file mode 100644 index 0000000..281a5cd --- /dev/null +++ b/Tests/FindPackageTest/PreferConfig/ABCConfig.cmake @@ -0,0 +1 @@ +set(ABC_FOUND TRUE) diff --git a/Tests/FindPackageTest/PreferConfig/FindABC.cmake b/Tests/FindPackageTest/PreferConfig/FindABC.cmake new file mode 100644 index 0000000..281a5cd --- /dev/null +++ b/Tests/FindPackageTest/PreferConfig/FindABC.cmake @@ -0,0 +1 @@ +set(ABC_FOUND TRUE) diff --git a/Tests/RunCMake/CommandLine/EnvGenerator/CMakeLists.txt b/Tests/RunCMake/CommandLine/EnvGenerator/CMakeLists.txt new file mode 100644 index 0000000..2b8c65c --- /dev/null +++ b/Tests/RunCMake/CommandLine/EnvGenerator/CMakeLists.txt @@ -0,0 +1,10 @@ +cmake_minimum_required(VERSION 3.14) +project(EnvGenerator C) +if(CMAKE_GENERATOR MATCHES "Visual Studio") + message(STATUS "CMAKE_VS_PLATFORM_NAME='${CMAKE_VS_PLATFORM_NAME}'") +endif() +add_custom_command( + OUTPUT output.txt + COMMAND ${CMAKE_COMMAND} -E echo CustomCommand > output.txt + ) +add_custom_target(CustomTarget ALL DEPENDS output.txt) diff --git a/Tests/RunCMake/CommandLine/Envgen-A-platform-result.txt b/Tests/RunCMake/CommandLine/Envgen-A-platform-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CommandLine/Envgen-A-platform-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CommandLine/Envgen-A-platform-stderr-vs9.txt b/Tests/RunCMake/CommandLine/Envgen-A-platform-stderr-vs9.txt new file mode 100644 index 0000000..4eae6aa --- /dev/null +++ b/Tests/RunCMake/CommandLine/Envgen-A-platform-stderr-vs9.txt @@ -0,0 +1,2 @@ +^CMake Error at CMakeLists.+ + No CMAKE_C_COMPILER could be found. diff --git a/Tests/RunCMake/CommandLine/Envgen-A-platform-stderr.txt b/Tests/RunCMake/CommandLine/Envgen-A-platform-stderr.txt new file mode 100644 index 0000000..09c2d2b --- /dev/null +++ b/Tests/RunCMake/CommandLine/Envgen-A-platform-stderr.txt @@ -0,0 +1,2 @@ +^CMake Error at CMakeLists.+ +.+Platform='fromcli'.+ diff --git a/Tests/RunCMake/CommandLine/Envgen-G-implicit-platform-stdout.txt b/Tests/RunCMake/CommandLine/Envgen-G-implicit-platform-stdout.txt new file mode 100644 index 0000000..4dd6be1 --- /dev/null +++ b/Tests/RunCMake/CommandLine/Envgen-G-implicit-platform-stdout.txt @@ -0,0 +1 @@ +-- CMAKE_VS_PLATFORM_NAME='(x64|Win32)' diff --git a/Tests/RunCMake/CommandLine/Envgen-T-toolset-result.txt b/Tests/RunCMake/CommandLine/Envgen-T-toolset-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CommandLine/Envgen-T-toolset-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CommandLine/Envgen-T-toolset-stderr.txt b/Tests/RunCMake/CommandLine/Envgen-T-toolset-stderr.txt new file mode 100644 index 0000000..b432c19 --- /dev/null +++ b/Tests/RunCMake/CommandLine/Envgen-T-toolset-stderr.txt @@ -0,0 +1,2 @@ +^CMake Error at CMakeLists.+ +.+(Platform Toolset = 'fromcli'|Specified platform toolset \(fromcli\) is not installed or invalid).+ diff --git a/Tests/RunCMake/CommandLine/Envgen-bad-result.txt b/Tests/RunCMake/CommandLine/Envgen-bad-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CommandLine/Envgen-bad-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CommandLine/Envgen-bad-stderr.txt b/Tests/RunCMake/CommandLine/Envgen-bad-stderr.txt new file mode 100644 index 0000000..4a1215e --- /dev/null +++ b/Tests/RunCMake/CommandLine/Envgen-bad-stderr.txt @@ -0,0 +1,5 @@ +^CMake Error: No generator specified for -G +CMake Error: CMAKE_GENERATOR was set but the specified generator doesn't exist. Using CMake default. + +Generators.* +\* (Unix Makefiles|Visual Studio).* diff --git a/Tests/RunCMake/CommandLine/Envgen-instance-invalid-result.txt b/Tests/RunCMake/CommandLine/Envgen-instance-invalid-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CommandLine/Envgen-instance-invalid-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CommandLine/Envgen-instance-invalid-stderr.txt b/Tests/RunCMake/CommandLine/Envgen-instance-invalid-stderr.txt new file mode 100644 index 0000000..d53daa5 --- /dev/null +++ b/Tests/RunCMake/CommandLine/Envgen-instance-invalid-stderr.txt @@ -0,0 +1,2 @@ +^CMake Error at CMakeLists.+ + could not find specified instance of Visual Studio.+ diff --git a/Tests/RunCMake/CommandLine/Envgen-ninja-result.txt b/Tests/RunCMake/CommandLine/Envgen-ninja-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CommandLine/Envgen-ninja-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CommandLine/Envgen-ninja-stderr.txt b/Tests/RunCMake/CommandLine/Envgen-ninja-stderr.txt new file mode 100644 index 0000000..0d455db --- /dev/null +++ b/Tests/RunCMake/CommandLine/Envgen-ninja-stderr.txt @@ -0,0 +1,4 @@ +^CMake Error: No generator specified for -G + +Generators.* +\* Ninja.* diff --git a/Tests/RunCMake/CommandLine/Envgen-platform-invalid-result.txt b/Tests/RunCMake/CommandLine/Envgen-platform-invalid-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CommandLine/Envgen-platform-invalid-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CommandLine/Envgen-platform-invalid-stderr-vs9.txt b/Tests/RunCMake/CommandLine/Envgen-platform-invalid-stderr-vs9.txt new file mode 100644 index 0000000..4eae6aa --- /dev/null +++ b/Tests/RunCMake/CommandLine/Envgen-platform-invalid-stderr-vs9.txt @@ -0,0 +1,2 @@ +^CMake Error at CMakeLists.+ + No CMAKE_C_COMPILER could be found. diff --git a/Tests/RunCMake/CommandLine/Envgen-platform-invalid-stderr.txt b/Tests/RunCMake/CommandLine/Envgen-platform-invalid-stderr.txt new file mode 100644 index 0000000..76a8f1c --- /dev/null +++ b/Tests/RunCMake/CommandLine/Envgen-platform-invalid-stderr.txt @@ -0,0 +1,2 @@ +^CMake Error at CMakeLists.+ +.+Platform='invalid'.+ diff --git a/Tests/RunCMake/CommandLine/Envgen-toolset-invalid-result.txt b/Tests/RunCMake/CommandLine/Envgen-toolset-invalid-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CommandLine/Envgen-toolset-invalid-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CommandLine/Envgen-toolset-invalid-stderr.txt b/Tests/RunCMake/CommandLine/Envgen-toolset-invalid-stderr.txt new file mode 100644 index 0000000..51fce60 --- /dev/null +++ b/Tests/RunCMake/CommandLine/Envgen-toolset-invalid-stderr.txt @@ -0,0 +1,2 @@ +^CMake Error at CMakeLists.+ +.+(Platform Toolset = 'invalid'|Specified platform toolset \(invalid\) is not installed or invalid).+ diff --git a/Tests/RunCMake/CommandLine/Envgen-unset-result.txt b/Tests/RunCMake/CommandLine/Envgen-unset-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CommandLine/Envgen-unset-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CommandLine/Envgen-unset-stderr.txt b/Tests/RunCMake/CommandLine/Envgen-unset-stderr.txt new file mode 100644 index 0000000..ec6ec92 --- /dev/null +++ b/Tests/RunCMake/CommandLine/Envgen-unset-stderr.txt @@ -0,0 +1,4 @@ +^CMake Error: No generator specified for -G + +Generators.* +\* (Unix Makefiles|Visual Studio).* diff --git a/Tests/RunCMake/CommandLine/Envgen-warnings-result.txt b/Tests/RunCMake/CommandLine/Envgen-warnings-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CommandLine/Envgen-warnings-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CommandLine/Envgen-warnings-stderr.txt b/Tests/RunCMake/CommandLine/Envgen-warnings-stderr.txt new file mode 100644 index 0000000..47f9c9e --- /dev/null +++ b/Tests/RunCMake/CommandLine/Envgen-warnings-stderr.txt @@ -0,0 +1,7 @@ +^Warning: Environment variable CMAKE_GENERATOR_INSTANCE will be ignored, because CMAKE_GENERATOR is not set. +Warning: Environment variable CMAKE_GENERATOR_PLATFORM will be ignored, because CMAKE_GENERATOR is not set. +Warning: Environment variable CMAKE_GENERATOR_TOOLSET will be ignored, because CMAKE_GENERATOR is not set. +CMake Error: No generator specified for -G + +Generators.* +\* (Unix Makefiles|Visual Studio).* diff --git a/Tests/RunCMake/CommandLine/RunCMakeTest.cmake b/Tests/RunCMake/CommandLine/RunCMakeTest.cmake index b9aa536..cee996c 100644 --- a/Tests/RunCMake/CommandLine/RunCMakeTest.cmake +++ b/Tests/RunCMake/CommandLine/RunCMakeTest.cmake @@ -172,6 +172,74 @@ function(run_BuildDir) endfunction() run_BuildDir() +function(run_EnvironmentGenerator) + set(source_dir ${RunCMake_SOURCE_DIR}/EnvGenerator) + + set(ENV{CMAKE_GENERATOR_INSTANCE} "instance") + set(ENV{CMAKE_GENERATOR_PLATFORM} "platform") + set(ENV{CMAKE_GENERATOR_TOOLSET} "toolset") + run_cmake_command(Envgen-warnings ${CMAKE_COMMAND} -G) + unset(ENV{CMAKE_GENERATOR_INSTANCE}) + unset(ENV{CMAKE_GENERATOR_PLATFORM}) + unset(ENV{CMAKE_GENERATOR_TOOLSET}) + + # Test CMAKE_GENERATOR without actual configuring + run_cmake_command(Envgen-unset ${CMAKE_COMMAND} -G) + set(ENV{CMAKE_GENERATOR} "Ninja") + run_cmake_command(Envgen-ninja ${CMAKE_COMMAND} -G) + set(ENV{CMAKE_GENERATOR} "NoSuchGenerator") + run_cmake_command(Envgen-bad ${CMAKE_COMMAND} -G) + unset(ENV{CMAKE_GENERATOR}) + + if(RunCMake_GENERATOR MATCHES "Visual Studio.*") + set(ENV{CMAKE_GENERATOR} "${RunCMake_GENERATOR}") + run_cmake_command(Envgen ${CMAKE_COMMAND} ${source_dir}) + # Toolset is available since VS 2010. + if(RunCMake_GENERATOR MATCHES "Visual Studio [1-9][0-9]") + set(ENV{CMAKE_GENERATOR_TOOLSET} "invalid") + # Envvar shouldn't affect existing build tree + run_cmake_command(Envgen-toolset-existing ${CMAKE_COMMAND} -E chdir .. + ${CMAKE_COMMAND} --build Envgen-build) + run_cmake_command(Envgen-toolset-invalid ${CMAKE_COMMAND} ${source_dir}) + # Command line -G implies -T"" + run_cmake_command(Envgen-G-implicit-toolset ${CMAKE_COMMAND} -G "${RunCMake_GENERATOR}" ${source_dir}) + run_cmake_command(Envgen-T-toolset ${CMAKE_COMMAND} -T "fromcli" ${source_dir}) + unset(ENV{CMAKE_GENERATOR_TOOLSET}) + endif() + # Platform can be set only if not in generator name. + if(RunCMake_GENERATOR MATCHES "^Visual Studio [0-9]+ [0-9]+$") + set(ENV{CMAKE_GENERATOR_PLATFORM} "invalid") + # Envvar shouldn't affect existing build tree + run_cmake_command(Envgen-platform-existing ${CMAKE_COMMAND} -E chdir .. + ${CMAKE_COMMAND} --build Envgen-build) + if(RunCMake_GENERATOR MATCHES "^Visual Studio 9 ") + set(RunCMake-stderr-file "Envgen-platform-invalid-stderr-vs9.txt") + endif() + run_cmake_command(Envgen-platform-invalid ${CMAKE_COMMAND} ${source_dir}) + unset(RunCMake-stderr-file) + # Command line -G implies -A"" + run_cmake_command(Envgen-G-implicit-platform ${CMAKE_COMMAND} -G "${RunCMake_GENERATOR}" ${source_dir}) + if(RunCMake_GENERATOR MATCHES "^Visual Studio 9 ") + set(RunCMake-stderr-file "Envgen-A-platform-stderr-vs9.txt") + endif() + run_cmake_command(Envgen-A-platform ${CMAKE_COMMAND} -A "fromcli" ${source_dir}) + unset(RunCMake-stderr-file) + unset(ENV{CMAKE_GENERATOR_PLATFORM}) + endif() + # Instance is available since VS 2017. + if(RunCMake_GENERATOR MATCHES "Visual Studio (15|16).*") + set(ENV{CMAKE_GENERATOR_INSTANCE} "invalid") + # Envvar shouldn't affect existing build tree + run_cmake_command(Envgen-instance-existing ${CMAKE_COMMAND} -E chdir .. + ${CMAKE_COMMAND} --build Envgen-build) + run_cmake_command(Envgen-instance-invalid ${CMAKE_COMMAND} ${source_dir}) + unset(ENV{CMAKE_GENERATOR_INSTANCE}) + endif() + unset(ENV{CMAKE_GENERATOR}) + endif() +endfunction() +run_EnvironmentGenerator() + if(RunCMake_GENERATOR STREQUAL "Ninja") # Use a single build tree for a few tests without cleaning. set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/Build-build) diff --git a/Tests/RunCMake/file/REMOVE-empty-stderr.txt b/Tests/RunCMake/file/REMOVE-empty-stderr.txt new file mode 100644 index 0000000..898a6e1 --- /dev/null +++ b/Tests/RunCMake/file/REMOVE-empty-stderr.txt @@ -0,0 +1,11 @@ +^CMake Warning \(dev\) at REMOVE-empty.cmake:1 \(file\): + Ignoring empty file name in REMOVE. +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9] \(include\) +This warning is for project developers. Use -Wno-dev to suppress it. ++ +CMake Warning \(dev\) at REMOVE-empty.cmake:2 \(file\): + Ignoring empty file name in REMOVE_RECURSE. +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9] \(include\) +This warning is for project developers. Use -Wno-dev to suppress it.$ diff --git a/Tests/RunCMake/file/REMOVE-empty.cmake b/Tests/RunCMake/file/REMOVE-empty.cmake new file mode 100644 index 0000000..38046fb --- /dev/null +++ b/Tests/RunCMake/file/REMOVE-empty.cmake @@ -0,0 +1,2 @@ +file(REMOVE "") +file(REMOVE_RECURSE "") diff --git a/Tests/RunCMake/file/RunCMakeTest.cmake b/Tests/RunCMake/file/RunCMakeTest.cmake index 996d1c5..5db4b3b 100644 --- a/Tests/RunCMake/file/RunCMakeTest.cmake +++ b/Tests/RunCMake/file/RunCMakeTest.cmake @@ -43,6 +43,8 @@ run_cmake(GLOB_RECURSE-noexp-FOLLOW_SYMLINKS) run_cmake(SIZE) run_cmake(SIZE-error-does-not-exist) +run_cmake(REMOVE-empty) + # tests are valid both for GLOB and GLOB_RECURSE run_cmake(GLOB-sort-dedup) run_cmake(GLOB-error-LIST_DIRECTORIES-not-boolean) diff --git a/Utilities/cmlibarchive/libarchive/archive_write_add_filter_b64encode.c b/Utilities/cmlibarchive/libarchive/archive_write_add_filter_b64encode.c index 85eb087..b46b19a 100644 --- a/Utilities/cmlibarchive/libarchive/archive_write_add_filter_b64encode.c +++ b/Utilities/cmlibarchive/libarchive/archive_write_add_filter_b64encode.c @@ -60,7 +60,7 @@ static int archive_filter_b64encode_write(struct archive_write_filter *, const void *, size_t); static int archive_filter_b64encode_close(struct archive_write_filter *); static int archive_filter_b64encode_free(struct archive_write_filter *); -static void b64_encode(struct archive_string *, const unsigned char *, size_t); +static void la_b64_encode(struct archive_string *, const unsigned char *, size_t); static int64_t atol8(const char *, size_t); static const char base64[] = { @@ -180,7 +180,7 @@ archive_filter_b64encode_open(struct archive_write_filter *f) } static void -b64_encode(struct archive_string *as, const unsigned char *p, size_t len) +la_b64_encode(struct archive_string *as, const unsigned char *p, size_t len) { int c; @@ -234,12 +234,12 @@ archive_filter_b64encode_write(struct archive_write_filter *f, const void *buff, } if (state->hold_len < LBYTES) return (ret); - b64_encode(&state->encoded_buff, state->hold, LBYTES); + la_b64_encode(&state->encoded_buff, state->hold, LBYTES); state->hold_len = 0; } for (; length >= LBYTES; length -= LBYTES, p += LBYTES) - b64_encode(&state->encoded_buff, p, LBYTES); + la_b64_encode(&state->encoded_buff, p, LBYTES); /* Save remaining bytes. */ if (length > 0) { @@ -270,7 +270,7 @@ archive_filter_b64encode_close(struct archive_write_filter *f) /* Flush remaining bytes. */ if (state->hold_len != 0) - b64_encode(&state->encoded_buff, state->hold, state->hold_len); + la_b64_encode(&state->encoded_buff, state->hold, state->hold_len); archive_string_sprintf(&state->encoded_buff, "====\n"); /* Write the last block */ archive_write_set_bytes_in_last_block(f->archive, 1); @@ -360,6 +360,7 @@ CMAKE_CXX_SOURCES="\ cmLinkDirectoriesCommand \ cmLinkItem \ cmLinkLineComputer \ + cmLinkLineDeviceComputer \ cmListCommand \ cmListFileCache \ cmLocalCommonGenerator \ |