diff options
48 files changed, 476 insertions, 173 deletions
diff --git a/Help/cpack_gen/dmg.rst b/Help/cpack_gen/dmg.rst index 1e37889..35320c2 100644 --- a/Help/cpack_gen/dmg.rst +++ b/Help/cpack_gen/dmg.rst @@ -81,6 +81,13 @@ on macOS: ``<language>.menu.txt`` and ``<language>.license.txt`` in the directory specified by the :variable:`CPACK_DMG_SLA_DIR` variable. +.. variable:: CPACK_DMG_<component>_FILE_NAME + + File name when packaging ``<component>`` as its own DMG + (``CPACK_COMPONENTS_GROUPING`` set to IGNORE). + + - Default: ``CPACK_PACKAGE_FILE_NAME-<component>`` + .. variable:: CPACK_COMMAND_HDIUTIL Path to the ``hdiutil(1)`` command used to operate on disk image files on diff --git a/Help/generator/Ninja Multi-Config.rst b/Help/generator/Ninja Multi-Config.rst index 92ca760..248eb05 100644 --- a/Help/generator/Ninja Multi-Config.rst +++ b/Help/generator/Ninja Multi-Config.rst @@ -19,8 +19,8 @@ the desired ``build-<Config>.ninja`` file with ``ninja -f``. Running ``build-<Config>.ninja`` as the ``-f`` file and ``<target>`` as the build target. -If :variable:`CMAKE_NINJA_CROSS_CONFIG_ENABLE` is turned on, executables and -libraries of any configuration can be built regardless of which +If :variable:`CMAKE_NINJA_MULTI_CROSS_CONFIG_ENABLE` is turned on, executables +and libraries of any configuration can be built regardless of which ``build-<Config>.ninja`` file is used, simply by specifying ``<target>:<OtherConfig>`` as the Ninja target. You can also specify ``<target>:all`` to build a target in all configurations. Each @@ -31,8 +31,8 @@ targets will always use the configuration specified in Ninja for the same file to be output with different commands in the same build graph. -If :variable:`CMAKE_NINJA_CROSS_CONFIG_ENABLE` is not enabled, you can still -build any target in ``build-<Config>.ninja`` by specifying +If :variable:`CMAKE_NINJA_MULTI_CROSS_CONFIG_ENABLE` is not enabled, you can +still build any target in ``build-<Config>.ninja`` by specifying ``<target>:<Config>`` or ``<target>``, but not ``<target>:<OtherConfig>`` or ``<target>:all``. @@ -60,8 +60,8 @@ This would build the ``Debug`` configuration of ``generator``, which would be used to generate ``generated.c``, which would be used to build the ``Debug`` configuration of ``generated``. -But if :variable:`CMAKE_NINJA_CROSS_CONFIG_ENABLE` is enabled, and you run the -following instead: +But if :variable:`CMAKE_NINJA_MULTI_CROSS_CONFIG_ENABLE` is enabled, and you +run the following instead: .. code-block:: shell diff --git a/Help/guide/tutorial/index.rst b/Help/guide/tutorial/index.rst index 5da7543..96f0486 100644 --- a/Help/guide/tutorial/index.rst +++ b/Help/guide/tutorial/index.rst @@ -397,16 +397,22 @@ from ``mysqrt.cxx``: #cmakedefine HAVE_LOG #cmakedefine HAVE_EXP -Modify ``mysqrt.cxx`` to include cmath. Next, in that same file in the -``mysqrt`` function we can provide an alternate implementation based on -``log`` and ``exp`` if they are available on the system using the following -code (don't forget the ``#endif`` before returning the result!): +If ``log`` and ``exp`` are available on the system, then we will use them to +compute the square root in the ``mysqrt`` function. Add the following code to +the ``mysqrt`` function in ``MathFunctions/mysqrt.cxx`` (don't forget the +``#endif`` before returning the result!): .. literalinclude:: Step6/MathFunctions/mysqrt.cxx :language: c++ :start-after: // if we have both log and exp then use them :end-before: // do ten iterations +We will also need to modify ``mysqrt.cxx`` to include ``cmath``. + +.. literalinclude:: Step6/MathFunctions/mysqrt.cxx + :language: c++ + :end-before: #include <iostream> + Run the :manual:`cmake <cmake(1)>` executable or the :manual:`cmake-gui <cmake-gui(1)>` to configure the project and then build it with your chosen build tool and run the Tutorial executable. diff --git a/Help/manual/cmake-variables.7.rst b/Help/manual/cmake-variables.7.rst index 0f7d2ec..a8fbc09 100644 --- a/Help/manual/cmake-variables.7.rst +++ b/Help/manual/cmake-variables.7.rst @@ -216,7 +216,6 @@ Variables that Change Behavior /variable/CMAKE_MESSAGE_INDENT /variable/CMAKE_MESSAGE_LOG_LEVEL /variable/CMAKE_MODULE_PATH - /variable/CMAKE_NINJA_MULTI_DEFAULT_BUILD_TYPE /variable/CMAKE_POLICY_DEFAULT_CMPNNNN /variable/CMAKE_POLICY_WARNING_CMPNNNN /variable/CMAKE_PREFIX_PATH @@ -370,6 +369,7 @@ Variables that Control the Build /variable/CMAKE_COMPILE_PDB_OUTPUT_DIRECTORY /variable/CMAKE_COMPILE_PDB_OUTPUT_DIRECTORY_CONFIG /variable/CMAKE_CONFIG_POSTFIX + /variable/CMAKE_CTEST_ARGUMENTS /variable/CMAKE_CUDA_SEPARABLE_COMPILATION /variable/CMAKE_CUDA_RESOLVE_DEVICE_SYMBOLS /variable/CMAKE_DEBUG_POSTFIX @@ -424,7 +424,8 @@ Variables that Control the Build /variable/CMAKE_MODULE_LINKER_FLAGS_INIT /variable/CMAKE_MSVCIDE_RUN_PATH /variable/CMAKE_MSVC_RUNTIME_LIBRARY - /variable/CMAKE_NINJA_CROSS_CONFIG_ENABLE + /variable/CMAKE_NINJA_MULTI_CROSS_CONFIG_ENABLE + /variable/CMAKE_NINJA_MULTI_DEFAULT_BUILD_TYPE /variable/CMAKE_NINJA_OUTPUT_PATH_PREFIX /variable/CMAKE_NO_BUILTIN_CHRPATH /variable/CMAKE_NO_SYSTEM_FROM_IMPORTED diff --git a/Help/prop_tgt/LINK_LIBRARIES_INDIRECTION.txt b/Help/prop_tgt/LINK_LIBRARIES_INDIRECTION.txt index fab4418..476e4a6 100644 --- a/Help/prop_tgt/LINK_LIBRARIES_INDIRECTION.txt +++ b/Help/prop_tgt/LINK_LIBRARIES_INDIRECTION.txt @@ -1,9 +1,9 @@ .. note:: A call to :command:`target_link_libraries(<target> ...)` may update this property on ``<target>``. If ``<target>`` was not created in the same - directory as the call then :command:`target_link_libraries` will add a - suffix of the form ``::@(directory-id)`` to each entry, where the - ``::@`` is a separator and the ``(directory-id)`` is unspecified. + directory as the call then :command:`target_link_libraries` will wrap each + entry with the form ``::@(directory-id);...;::@``, where the ``::@`` is + literal and the ``(directory-id)`` is unspecified. This tells the generators that the named libraries must be looked up in the scope of the caller rather than in the scope in which the ``<target>`` was created. Valid directory ids are stripped on export diff --git a/Help/release/dev/cmake-ctest-arguments.rst b/Help/release/dev/cmake-ctest-arguments.rst new file mode 100644 index 0000000..72a264a --- /dev/null +++ b/Help/release/dev/cmake-ctest-arguments.rst @@ -0,0 +1,6 @@ +cmake-ctest-arguments +--------------------- + +* A :variable:`CMAKE_CTEST_ARGUMENTS` variable was added to specify a list + of command-line arguments passed to CTest when running through the + ``test`` (or ``RUN_TESTS``) target of the generated build system. diff --git a/Help/release/dev/custom-dmg-names.rst b/Help/release/dev/custom-dmg-names.rst new file mode 100644 index 0000000..73a70a1 --- /dev/null +++ b/Help/release/dev/custom-dmg-names.rst @@ -0,0 +1,7 @@ +custom-dmg-names +---------------- + +* The :cpack_gen:`CPack DragNDrop Generator` learned to use + the :variable:`CPACK_DMG_<component>_FILE_NAME` variable + to set a custom filename when packaging components into + their own DMGs. diff --git a/Help/variable/CMAKE_CTEST_ARGUMENTS.rst b/Help/variable/CMAKE_CTEST_ARGUMENTS.rst new file mode 100644 index 0000000..0940b46 --- /dev/null +++ b/Help/variable/CMAKE_CTEST_ARGUMENTS.rst @@ -0,0 +1,6 @@ +CMAKE_CTEST_ARGUMENTS +--------------------- + +Set this to a :ref:`semicolon-separated list <CMake Language Lists>` of +command-line arguments to pass to :manual:`ctest(1)` when running tests +through the ``test`` (or ``RUN_TESTS``) target of the generated build system. diff --git a/Help/variable/CMAKE_NINJA_CROSS_CONFIG_ENABLE.rst b/Help/variable/CMAKE_NINJA_CROSS_CONFIG_ENABLE.rst deleted file mode 100644 index 5c9c1aa..0000000 --- a/Help/variable/CMAKE_NINJA_CROSS_CONFIG_ENABLE.rst +++ /dev/null @@ -1,6 +0,0 @@ -CMAKE_NINJA_CROSS_CONFIG_ENABLE -------------------------------- - -If this variable is enabled, cross-configuration building is enabled in the -:generator:`Ninja Multi-Config` generator. See the generator's description for -more details. diff --git a/Help/variable/CMAKE_NINJA_MULTI_CROSS_CONFIG_ENABLE.rst b/Help/variable/CMAKE_NINJA_MULTI_CROSS_CONFIG_ENABLE.rst new file mode 100644 index 0000000..0571d52 --- /dev/null +++ b/Help/variable/CMAKE_NINJA_MULTI_CROSS_CONFIG_ENABLE.rst @@ -0,0 +1,10 @@ +CMAKE_NINJA_MULTI_CROSS_CONFIG_ENABLE +------------------------------------- + +If this variable is enabled, cross-configuration building is enabled in the +:generator:`Ninja Multi-Config` generator. See the generator's description for +more details. This variable is ``OFF`` by default. + +This variable is meant to be set from the command line (via +``-DCMAKE_NINJA_MULTI_CROSS_CONFIG_ENABLE:BOOL=ON``) and should not be set from +project code. diff --git a/Modules/CMakeCSharpInformation.cmake b/Modules/CMakeCSharpInformation.cmake index 48e1a1e..41cd449 100644 --- a/Modules/CMakeCSharpInformation.cmake +++ b/Modules/CMakeCSharpInformation.cmake @@ -10,7 +10,7 @@ get_filename_component(CMAKE_BASE_NAME "${CMAKE_CSharp_COMPILER}" NAME_WE) set(CMAKE_BUILD_TYPE_INIT Debug) -set(CMAKE_CSharp_FLAGS_INIT "/define:TRACE /langversion:3") +set(CMAKE_CSharp_FLAGS_INIT "/define:TRACE") set(CMAKE_CSharp_FLAGS_DEBUG_INIT "/debug:full /optimize- /warn:3 /errorreport:prompt /define:DEBUG") set(CMAKE_CSharp_FLAGS_RELEASE_INIT "/debug:none /optimize /warn:1 /errorreport:queue") set(CMAKE_CSharp_FLAGS_RELWITHDEBINFO_INIT "/debug:full /optimize-") diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index e7dacfd..58b8191 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 16) -set(CMake_VERSION_PATCH 20200116) +set(CMake_VERSION_PATCH 20200120) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) diff --git a/Source/CPack/cmCPackDragNDropGenerator.cxx b/Source/CPack/cmCPackDragNDropGenerator.cxx index ea71007..3516235 100644 --- a/Source/CPack/cmCPackDragNDropGenerator.cxx +++ b/Source/CPack/cmCPackDragNDropGenerator.cxx @@ -775,6 +775,11 @@ std::string cmCPackDragNDropGenerator::GetComponentInstallDirNameSuffix( } } + std::string componentFileName = + "CPACK_DMG_" + cmSystemTools::UpperCase(componentName) + "_FILE_NAME"; + if (this->IsSet(componentFileName)) { + return this->GetOption(componentFileName); + } return GetComponentPackageFileName(package_file_name, componentName, false); } diff --git a/Source/cmExportFileGenerator.cxx b/Source/cmExportFileGenerator.cxx index 7a4b887..27e9906 100644 --- a/Source/cmExportFileGenerator.cxx +++ b/Source/cmExportFileGenerator.cxx @@ -14,6 +14,7 @@ #include "cmComputeLinkInformation.h" #include "cmGeneratedFileStream.h" #include "cmGeneratorTarget.h" +#include "cmGlobalGenerator.h" #include "cmLinkItem.h" #include "cmLocalGenerator.h" #include "cmMakefile.h" @@ -640,6 +641,9 @@ void cmExportFileGenerator::ResolveTargetsInGeneratorExpressions( std::string sep; input.clear(); for (std::string& li : parts) { + if (cmHasLiteralPrefix(li, CMAKE_DIRECTORY_ID_SEP)) { + continue; + } if (cmGeneratorExpression::Find(li) == std::string::npos) { this->AddTargetNamespace(li, target, missingTargets); } else { diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index b18d8bf..441515c 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -5418,16 +5418,39 @@ void cmGeneratorTarget::ReportPropertyOrigin( areport); } +bool cmGeneratorTarget::IsLinkLookupScope(std::string const& n, + cmLocalGenerator const*& lg) const +{ + if (cmHasLiteralPrefix(n, CMAKE_DIRECTORY_ID_SEP)) { + cmDirectoryId const dirId = n.substr(sizeof(CMAKE_DIRECTORY_ID_SEP) - 1); + if (dirId.String.empty()) { + lg = this->LocalGenerator; + return true; + } + if (cmLocalGenerator const* otherLG = + this->GlobalGenerator->FindLocalGenerator(dirId)) { + lg = otherLG; + return true; + } + } + return false; +} + void cmGeneratorTarget::LookupLinkItems(std::vector<std::string> const& names, cmListFileBacktrace const& bt, std::vector<cmLinkItem>& items) const { + cmLocalGenerator const* lg = this->LocalGenerator; for (std::string const& n : names) { + if (this->IsLinkLookupScope(n, lg)) { + continue; + } + std::string name = this->CheckCMP0004(n); if (name == this->GetName() || name.empty()) { continue; } - items.push_back(this->ResolveLinkItem(name, bt)); + items.push_back(this->ResolveLinkItem(name, bt, lg)); } } @@ -5436,6 +5459,7 @@ void cmGeneratorTarget::ExpandLinkItems( cmGeneratorTarget const* headTarget, bool usage_requirements_only, std::vector<cmLinkItem>& items, bool& hadHeadSensitiveCondition) const { + // Keep this logic in sync with ComputeLinkImplementationLibraries. cmGeneratorExpression ge; cmGeneratorExpressionDAGChecker dagChecker(this, prop, nullptr, nullptr); // The $<LINK_ONLY> expression may be in a link interface to specify private @@ -6511,6 +6535,7 @@ void cmGeneratorTarget::ComputeLinkImplementationLibraries( const std::string& config, cmOptionalLinkImplementation& impl, cmGeneratorTarget const* head) const { + cmLocalGenerator const* lg = this->LocalGenerator; cmStringRange entryRange = this->Target->GetLinkImplementationEntries(); cmBacktraceRange btRange = this->Target->GetLinkImplementationBacktraces(); cmBacktraceRange::const_iterator btIt = btRange.begin(); @@ -6519,6 +6544,7 @@ void cmGeneratorTarget::ComputeLinkImplementationLibraries( end = entryRange.end(); le != end; ++le, ++btIt) { std::vector<std::string> llibs; + // Keep this logic in sync with ExpandLinkItems. cmGeneratorExpressionDAGChecker dagChecker(this, "LINK_LIBRARIES", nullptr, nullptr); cmGeneratorExpression ge(*btIt); @@ -6531,6 +6557,10 @@ void cmGeneratorTarget::ComputeLinkImplementationLibraries( } for (std::string const& lib : llibs) { + if (this->IsLinkLookupScope(lib, lg)) { + continue; + } + // Skip entries that resolve to the target itself or are empty. std::string name = this->CheckCMP0004(lib); if (name == this->GetName() || name.empty()) { @@ -6565,7 +6595,7 @@ void cmGeneratorTarget::ComputeLinkImplementationLibraries( } // The entry is meant for this configuration. - impl.Libraries.emplace_back(this->ResolveLinkItem(name, *btIt), + impl.Libraries.emplace_back(this->ResolveLinkItem(name, *btIt, lg), evaluated != *le); } @@ -6602,38 +6632,16 @@ void cmGeneratorTarget::ComputeLinkImplementationLibraries( cmGeneratorTarget::TargetOrString cmGeneratorTarget::ResolveTargetReference( std::string const& name) const { - cmLocalGenerator const* lg = this->LocalGenerator; - std::string const* lookupName = &name; - - // When target_link_libraries() is called with a LHS target that is - // not created in the calling directory it adds a directory id suffix - // that we can use to look up the calling directory. It is that scope - // in which the item name is meaningful. This case is relatively rare - // so we allocate a separate string only when the directory id is present. - std::string::size_type pos = name.find(CMAKE_DIRECTORY_ID_SEP); - std::string plainName; - if (pos != std::string::npos) { - // We will look up the plain name without the directory id suffix. - plainName = name.substr(0, pos); - - // We will look up in the scope of the directory id. - // If we do not recognize the id then leave the original - // syntax in place to produce an indicative error later. - cmDirectoryId const dirId = - name.substr(pos + sizeof(CMAKE_DIRECTORY_ID_SEP) - 1); - if (cmLocalGenerator const* otherLG = - this->GlobalGenerator->FindLocalGenerator(dirId)) { - lg = otherLG; - lookupName = &plainName; - } - } + return this->ResolveTargetReference(name, this->LocalGenerator); +} +cmGeneratorTarget::TargetOrString cmGeneratorTarget::ResolveTargetReference( + std::string const& name, cmLocalGenerator const* lg) const +{ TargetOrString resolved; - if (cmGeneratorTarget* tgt = lg->FindGeneratorTargetToUse(*lookupName)) { + if (cmGeneratorTarget* tgt = lg->FindGeneratorTargetToUse(name)) { resolved.Target = tgt; - } else if (lookupName == &plainName) { - resolved.String = std::move(plainName); } else { resolved.String = name; } @@ -6644,7 +6652,14 @@ cmGeneratorTarget::TargetOrString cmGeneratorTarget::ResolveTargetReference( cmLinkItem cmGeneratorTarget::ResolveLinkItem( std::string const& name, cmListFileBacktrace const& bt) const { - TargetOrString resolved = this->ResolveTargetReference(name); + return this->ResolveLinkItem(name, bt, this->LocalGenerator); +} + +cmLinkItem cmGeneratorTarget::ResolveLinkItem(std::string const& name, + cmListFileBacktrace const& bt, + cmLocalGenerator const* lg) const +{ + TargetOrString resolved = this->ResolveTargetReference(name, lg); if (!resolved.Target) { return cmLinkItem(resolved.String, bt); diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h index 0a72cbe..9d06104 100644 --- a/Source/cmGeneratorTarget.h +++ b/Source/cmGeneratorTarget.h @@ -378,9 +378,14 @@ public: cmGeneratorTarget* Target = nullptr; }; TargetOrString ResolveTargetReference(std::string const& name) const; + TargetOrString ResolveTargetReference(std::string const& name, + cmLocalGenerator const* lg) const; cmLinkItem ResolveLinkItem(std::string const& name, cmListFileBacktrace const& bt) const; + cmLinkItem ResolveLinkItem(std::string const& name, + cmListFileBacktrace const& bt, + cmLocalGenerator const* lg) const; // Compute the set of languages compiled by the target. This is // computed every time it is called because the languages can change @@ -919,6 +924,9 @@ private: std::unordered_set<std::string> UnityBatchedSourceFiles; + bool IsLinkLookupScope(std::string const& n, + cmLocalGenerator const*& lg) const; + void ExpandLinkItems(std::string const& prop, std::string const& value, std::string const& config, const cmGeneratorTarget* headTarget, diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx index c3ab4b7..b3eb8e4 100644 --- a/Source/cmGlobalGenerator.cxx +++ b/Source/cmGlobalGenerator.cxx @@ -2458,6 +2458,13 @@ void cmGlobalGenerator::AddGlobalTarget_Test( cmCustomCommandLine singleLine; singleLine.push_back(cmSystemTools::GetCTestCommand()); singleLine.push_back("--force-new-ctest-process"); + if (auto testArgs = mf->GetDefinition("CMAKE_CTEST_ARGUMENTS")) { + std::vector<std::string> args; + cmExpandList(testArgs, args); + for (auto const& arg : args) { + singleLine.push_back(arg); + } + } if (cmakeCfgIntDir && *cmakeCfgIntDir && cmakeCfgIntDir[0] != '.') { singleLine.push_back("-C"); singleLine.push_back(cmakeCfgIntDir); diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx index 0048ba4..0487ad1 100644 --- a/Source/cmGlobalNinjaGenerator.cxx +++ b/Source/cmGlobalNinjaGenerator.cxx @@ -2203,7 +2203,7 @@ bool cmGlobalNinjaGenerator::WriteDyndepFile( bool cmGlobalNinjaGenerator::EnableCrossConfigBuild() const { return this->IsMultiConfig() && - this->Makefiles.front()->IsOn("CMAKE_NINJA_CROSS_CONFIG_ENABLE"); + this->Makefiles.front()->IsOn("CMAKE_NINJA_MULTI_CROSS_CONFIG_ENABLE"); } int cmcmd_cmake_ninja_dyndep(std::vector<std::string>::const_iterator argBeg, diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index 4f1f582..f13e18b 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -3284,7 +3284,8 @@ std::string cmLocalGenerator::GetObjectFileNameWithoutTarget( // CMakeFiles/<target>.dir/CMakeFiles/<target>.dir/generated_source_file.obj const char* unitySourceFile = source.GetProperty("UNITY_SOURCE_FILE"); const char* pchExtension = source.GetProperty("PCH_EXTENSION"); - if (unitySourceFile || pchExtension) { + const bool isPchObject = objectName.find("cmake_pch") != std::string::npos; + if (unitySourceFile || pchExtension || isPchObject) { if (pchExtension) { customOutputExtension = pchExtension; } diff --git a/Source/cmSourceFile.cxx b/Source/cmSourceFile.cxx index 2a345eb..60adf7f 100644 --- a/Source/cmSourceFile.cxx +++ b/Source/cmSourceFile.cxx @@ -128,7 +128,7 @@ bool cmSourceFile::FindFullPath(std::string* error) // The file is not generated. It must exist on disk. cmMakefile const* makefile = this->Location.GetMakefile(); // Location path - std::string const lPath = this->Location.GetFullPath(); + std::string const& lPath = this->Location.GetFullPath(); // List of extension lists std::array<std::vector<std::string> const*, 2> const extsLists = { { &makefile->GetCMakeInstance()->GetSourceExtensions(), @@ -145,7 +145,7 @@ bool cmSourceFile::FindFullPath(std::string* error) return true; } // Try full path with extension - for (auto exts : extsLists) { + for (auto& exts : extsLists) { for (std::string const& ext : *exts) { if (!ext.empty()) { std::string extPath = cmStrCat(fullPath, '.', ext); diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index ae1393f..a0b3138 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -938,14 +938,7 @@ cmTarget::LinkLibraryVectorType const& cmTarget::GetOriginalLinkLibraries() return impl->OriginalLinkLibraries; } -void cmTarget::AddLinkLibrary(cmMakefile& mf, const std::string& lib, - cmTargetLinkLibraryType llt) -{ - this->AddLinkLibrary(mf, lib, lib, llt); -} - void cmTarget::AddLinkLibrary(cmMakefile& mf, std::string const& lib, - std::string const& libRef, cmTargetLinkLibraryType llt) { cmTarget* tgt = mf.FindTargetToUse(lib); @@ -954,13 +947,13 @@ void cmTarget::AddLinkLibrary(cmMakefile& mf, std::string const& lib, const std::string libName = (isNonImportedTarget && llt != GENERAL_LibraryType) - ? targetNameGenex(libRef) - : libRef; + ? targetNameGenex(lib) + : lib; this->AppendProperty("LINK_LIBRARIES", this->GetDebugGeneratorExpressions(libName, llt)); } - if (cmGeneratorExpression::Find(lib) != std::string::npos || lib != libRef || + if (cmGeneratorExpression::Find(lib) != std::string::npos || (tgt && (tgt->GetType() == cmStateEnums::INTERFACE_LIBRARY || tgt->GetType() == cmStateEnums::OBJECT_LIBRARY)) || diff --git a/Source/cmTarget.h b/Source/cmTarget.h index bdf8c0f..ca37f0d 100644 --- a/Source/cmTarget.h +++ b/Source/cmTarget.h @@ -110,10 +110,8 @@ public: //! Clear the dependency information recorded for this target, if any. void ClearDependencyInformation(cmMakefile& mf); - void AddLinkLibrary(cmMakefile& mf, const std::string& lib, - cmTargetLinkLibraryType llt); void AddLinkLibrary(cmMakefile& mf, std::string const& lib, - std::string const& libRef, cmTargetLinkLibraryType llt); + cmTargetLinkLibraryType llt); enum TLLSignature { diff --git a/Source/cmTargetLinkLibrariesCommand.cxx b/Source/cmTargetLinkLibrariesCommand.cxx index 1d9ecc2..df751da 100644 --- a/Source/cmTargetLinkLibrariesCommand.cxx +++ b/Source/cmTargetLinkLibrariesCommand.cxx @@ -5,6 +5,8 @@ #include <cstring> #include <memory> #include <sstream> +#include <unordered_set> +#include <utility> #include "cmExecutionStatus.h" #include "cmGeneratorExpression.h" @@ -35,15 +37,30 @@ enum ProcessingState const char* LinkLibraryTypeNames[3] = { "general", "debug", "optimized" }; +struct TLL +{ + cmMakefile& Makefile; + cmTarget* Target; + bool WarnRemoteInterface = false; + bool RejectRemoteLinking = false; + bool EncodeRemoteReference = false; + std::string DirectoryId; + std::unordered_set<std::string> Props; + + TLL(cmMakefile& mf, cmTarget* target); + ~TLL(); + + bool HandleLibrary(ProcessingState currentProcessingState, + const std::string& lib, cmTargetLinkLibraryType llt); + void AppendProperty(std::string const& prop, std::string const& value); + void AffectsProperty(std::string const& prop); +}; + } // namespace static void LinkLibraryTypeSpecifierWarning(cmMakefile& mf, int left, int right); -static bool HandleLibrary(cmMakefile& mf, cmTarget* target, - ProcessingState currentProcessingState, - const std::string& lib, cmTargetLinkLibraryType llt); - bool cmTargetLinkLibrariesCommand(std::vector<std::string> const& args, cmExecutionStatus& status) { @@ -148,6 +165,8 @@ bool cmTargetLinkLibrariesCommand(std::vector<std::string> const& args, return true; } + TLL tll(mf, target); + // Keep track of link configuration specifiers. cmTargetLinkLibraryType llt = GENERAL_LibraryType; bool haveLLT = false; @@ -246,7 +265,7 @@ bool cmTargetLinkLibrariesCommand(std::vector<std::string> const& args, } else if (haveLLT) { // The link type was specified by the previous argument. haveLLT = false; - if (!HandleLibrary(mf, target, currentProcessingState, args[i], llt)) { + if (!tll.HandleLibrary(currentProcessingState, args[i], llt)) { return false; } } else { @@ -267,7 +286,7 @@ bool cmTargetLinkLibrariesCommand(std::vector<std::string> const& args, llt = OPTIMIZED_LibraryType; } } - if (!HandleLibrary(mf, target, currentProcessingState, args[i], llt)) { + if (!tll.HandleLibrary(currentProcessingState, args[i], llt)) { return false; } } @@ -310,21 +329,48 @@ static void LinkLibraryTypeSpecifierWarning(cmMakefile& mf, int left, "\" instead of a library name. The first specifier will be ignored.")); } -static bool HandleLibrary(cmMakefile& mf, cmTarget* target, - ProcessingState currentProcessingState, - const std::string& lib, cmTargetLinkLibraryType llt) +namespace { + +TLL::TLL(cmMakefile& mf, cmTarget* target) + : Makefile(mf) + , Target(target) +{ + if (&this->Makefile != this->Target->GetMakefile()) { + // The LHS target was created in another directory. + switch (this->Makefile.GetPolicyStatus(cmPolicies::CMP0079)) { + case cmPolicies::WARN: + this->WarnRemoteInterface = true; + CM_FALLTHROUGH; + case cmPolicies::OLD: + this->RejectRemoteLinking = true; + break; + case cmPolicies::REQUIRED_ALWAYS: + case cmPolicies::REQUIRED_IF_USED: + case cmPolicies::NEW: + this->EncodeRemoteReference = true; + break; + } + } + if (this->EncodeRemoteReference) { + cmDirectoryId const dirId = this->Makefile.GetDirectoryId(); + this->DirectoryId = cmStrCat(CMAKE_DIRECTORY_ID_SEP, dirId.String); + } +} + +bool TLL::HandleLibrary(ProcessingState currentProcessingState, + const std::string& lib, cmTargetLinkLibraryType llt) { - if (target->GetType() == cmStateEnums::INTERFACE_LIBRARY && + if (this->Target->GetType() == cmStateEnums::INTERFACE_LIBRARY && currentProcessingState != ProcessingKeywordLinkInterface) { - mf.IssueMessage( + this->Makefile.IssueMessage( MessageType::FATAL_ERROR, "INTERFACE library can only be used with the INTERFACE keyword of " "target_link_libraries"); return false; } - if (target->IsImported() && + if (this->Target->IsImported() && currentProcessingState != ProcessingKeywordLinkInterface) { - mf.IssueMessage( + this->Makefile.IssueMessage( MessageType::FATAL_ERROR, "IMPORTED library can only be used with the INTERFACE keyword of " "target_link_libraries"); @@ -339,11 +385,12 @@ static bool HandleLibrary(cmMakefile& mf, cmTarget* target, currentProcessingState == ProcessingKeywordLinkInterface) ? cmTarget::KeywordTLLSignature : cmTarget::PlainTLLSignature; - if (!target->PushTLLCommandTrace(sig, mf.GetExecutionContext())) { + if (!this->Target->PushTLLCommandTrace( + sig, this->Makefile.GetExecutionContext())) { std::ostringstream e; const char* modal = nullptr; MessageType messageType = MessageType::AUTHOR_WARNING; - switch (mf.GetPolicyStatus(cmPolicies::CMP0023)) { + switch (this->Makefile.GetPolicyStatus(cmPolicies::CMP0023)) { case cmPolicies::WARN: e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0023) << "\n"; modal = "should"; @@ -364,77 +411,38 @@ static bool HandleLibrary(cmMakefile& mf, cmTarget* target, e << "The " << existingSig << " signature for target_link_libraries has " "already been used with the target \"" - << target->GetName() + << this->Target->GetName() << "\". All uses of target_link_libraries with a target " << modal << " be either all-keyword or all-plain.\n"; - target->GetTllSignatureTraces(e, - sig == cmTarget::KeywordTLLSignature - ? cmTarget::PlainTLLSignature - : cmTarget::KeywordTLLSignature); - mf.IssueMessage(messageType, e.str()); + this->Target->GetTllSignatureTraces(e, + sig == cmTarget::KeywordTLLSignature + ? cmTarget::PlainTLLSignature + : cmTarget::KeywordTLLSignature); + this->Makefile.IssueMessage(messageType, e.str()); if (messageType == MessageType::FATAL_ERROR) { return false; } } } - bool warnRemoteInterface = false; - bool rejectRemoteLinking = false; - bool encodeRemoteReference = false; - if (&mf != target->GetMakefile()) { - // The LHS target was created in another directory. - switch (mf.GetPolicyStatus(cmPolicies::CMP0079)) { - case cmPolicies::WARN: - warnRemoteInterface = true; - CM_FALLTHROUGH; - case cmPolicies::OLD: - rejectRemoteLinking = true; - break; - case cmPolicies::REQUIRED_ALWAYS: - case cmPolicies::REQUIRED_IF_USED: - case cmPolicies::NEW: - encodeRemoteReference = true; - break; - } - } - - std::string libRef; - if (encodeRemoteReference && !cmSystemTools::FileIsFullPath(lib)) { - // This is a library name added by a caller that is not in the - // same directory as the target was created. Add a suffix to - // the name to tell ResolveLinkItem to look up the name in the - // caller's directory. - cmDirectoryId const dirId = mf.GetDirectoryId(); - // FIXME: The "lib" may be a genex with a list inside it. - // After expansion this id will only attach to the last entry, - // or may attach to an empty string! We will need another way - // to encode this that can apply to a whole list. See issue #20204. - libRef = lib + CMAKE_DIRECTORY_ID_SEP + dirId.String; - } else { - // This is an absolute path or a library name added by a caller - // in the same directory as the target was created. We can use - // the original name directly. - libRef = lib; - } - // Handle normal case where the command was called with another keyword than // INTERFACE / LINK_INTERFACE_LIBRARIES or none at all. (The "LINK_LIBRARIES" // property of the target on the LHS shall be populated.) if (currentProcessingState != ProcessingKeywordLinkInterface && currentProcessingState != ProcessingPlainLinkInterface) { - if (rejectRemoteLinking) { - mf.IssueMessage( + if (this->RejectRemoteLinking) { + this->Makefile.IssueMessage( MessageType::FATAL_ERROR, cmStrCat("Attempt to add link library \"", lib, "\" to target \"", - target->GetName(), + this->Target->GetName(), "\" which is not built in this " "directory.\nThis is allowed only when policy CMP0079 " "is set to NEW.")); return false; } - cmTarget* tgt = mf.GetGlobalGenerator()->FindTarget(lib); + cmTarget* tgt = this->Makefile.GetGlobalGenerator()->FindTarget(lib); if (tgt && (tgt->GetType() != cmStateEnums::STATIC_LIBRARY) && (tgt->GetType() != cmStateEnums::SHARED_LIBRARY) && @@ -442,7 +450,7 @@ static bool HandleLibrary(cmMakefile& mf, cmTarget* target, (tgt->GetType() != cmStateEnums::OBJECT_LIBRARY) && (tgt->GetType() != cmStateEnums::INTERFACE_LIBRARY) && !tgt->IsExecutableWithExports()) { - mf.IssueMessage( + this->Makefile.IssueMessage( MessageType::FATAL_ERROR, cmStrCat( "Target \"", lib, "\" of type ", @@ -452,15 +460,16 @@ static bool HandleLibrary(cmMakefile& mf, cmTarget* target, "executables with the ENABLE_EXPORTS property set.")); } - target->AddLinkLibrary(mf, lib, libRef, llt); + this->AffectsProperty("LINK_LIBRARIES"); + this->Target->AddLinkLibrary(this->Makefile, lib, llt); } - if (warnRemoteInterface) { - mf.IssueMessage( + if (this->WarnRemoteInterface) { + this->Makefile.IssueMessage( MessageType::AUTHOR_WARNING, cmStrCat( cmPolicies::GetPolicyWarning(cmPolicies::CMP0079), "\nTarget\n ", - target->GetName(), + this->Target->GetName(), "\nis not created in this " "directory. For compatibility with older versions of CMake, link " "library\n ", @@ -475,15 +484,15 @@ static bool HandleLibrary(cmMakefile& mf, cmTarget* target, // STATIC library.) if (currentProcessingState == ProcessingKeywordPrivateInterface || currentProcessingState == ProcessingPlainPrivateInterface) { - if (target->GetType() == cmStateEnums::STATIC_LIBRARY || - target->GetType() == cmStateEnums::OBJECT_LIBRARY) { + if (this->Target->GetType() == cmStateEnums::STATIC_LIBRARY || + this->Target->GetType() == cmStateEnums::OBJECT_LIBRARY) { std::string configLib = - target->GetDebugGeneratorExpressions(libRef, llt); + this->Target->GetDebugGeneratorExpressions(lib, llt); if (cmGeneratorExpression::IsValidTargetName(lib) || cmGeneratorExpression::Find(lib) != std::string::npos) { configLib = "$<LINK_ONLY:" + configLib + ">"; } - target->AppendProperty("INTERFACE_LINK_LIBRARIES", configLib); + this->AppendProperty("INTERFACE_LINK_LIBRARIES", configLib); } return true; } @@ -491,8 +500,8 @@ static bool HandleLibrary(cmMakefile& mf, cmTarget* target, // Handle general case where the command was called with another keyword than // PRIVATE / LINK_PRIVATE or none at all. (The "INTERFACE_LINK_LIBRARIES" // property of the target on the LHS shall be populated.) - target->AppendProperty("INTERFACE_LINK_LIBRARIES", - target->GetDebugGeneratorExpressions(libRef, llt)); + this->AppendProperty("INTERFACE_LINK_LIBRARIES", + this->Target->GetDebugGeneratorExpressions(lib, llt)); // Stop processing if called without any keyword. if (currentProcessingState == ProcessingLinkLibraries) { @@ -500,13 +509,13 @@ static bool HandleLibrary(cmMakefile& mf, cmTarget* target, } // Stop processing if policy CMP0022 is set to NEW. const cmPolicies::PolicyStatus policy22Status = - target->GetPolicyStatusCMP0022(); + this->Target->GetPolicyStatusCMP0022(); if (policy22Status != cmPolicies::OLD && policy22Status != cmPolicies::WARN) { return true; } // Stop processing if called with an INTERFACE library on the LHS. - if (target->GetType() == cmStateEnums::INTERFACE_LIBRARY) { + if (this->Target->GetType() == cmStateEnums::INTERFACE_LIBRARY) { return true; } @@ -516,7 +525,7 @@ static bool HandleLibrary(cmMakefile& mf, cmTarget* target, { // Get the list of configurations considered to be DEBUG. std::vector<std::string> debugConfigs = - mf.GetCMakeInstance()->GetDebugConfigs(); + this->Makefile.GetCMakeInstance()->GetDebugConfigs(); std::string prop; // Include this library in the link interface for the target. @@ -524,22 +533,49 @@ static bool HandleLibrary(cmMakefile& mf, cmTarget* target, // Put in the DEBUG configuration interfaces. for (std::string const& dc : debugConfigs) { prop = cmStrCat("LINK_INTERFACE_LIBRARIES_", dc); - target->AppendProperty(prop, libRef); + this->AppendProperty(prop, lib); } } if (llt == OPTIMIZED_LibraryType || llt == GENERAL_LibraryType) { // Put in the non-DEBUG configuration interfaces. - target->AppendProperty("LINK_INTERFACE_LIBRARIES", libRef); + this->AppendProperty("LINK_INTERFACE_LIBRARIES", lib); // Make sure the DEBUG configuration interfaces exist so that the // general one will not be used as a fall-back. for (std::string const& dc : debugConfigs) { prop = cmStrCat("LINK_INTERFACE_LIBRARIES_", dc); - if (!target->GetProperty(prop)) { - target->SetProperty(prop, ""); + if (!this->Target->GetProperty(prop)) { + this->Target->SetProperty(prop, ""); } } } } return true; } + +void TLL::AppendProperty(std::string const& prop, std::string const& value) +{ + this->AffectsProperty(prop); + this->Target->AppendProperty(prop, value); +} + +void TLL::AffectsProperty(std::string const& prop) +{ + if (!this->EncodeRemoteReference) { + return; + } + // Add a wrapper to the expression to tell LookupLinkItems to look up + // names in the caller's directory. + if (this->Props.insert(prop).second) { + this->Target->AppendProperty(prop, this->DirectoryId); + } +} + +TLL::~TLL() +{ + for (std::string const& prop : this->Props) { + this->Target->AppendProperty(prop, CMAKE_DIRECTORY_ID_SEP); + } +} + +} // namespace diff --git a/Tests/CMakeCommands/target_link_libraries/SubDirB/CMakeLists.txt b/Tests/CMakeCommands/target_link_libraries/SubDirB/CMakeLists.txt index b430834..06d1111 100644 --- a/Tests/CMakeCommands/target_link_libraries/SubDirB/CMakeLists.txt +++ b/Tests/CMakeCommands/target_link_libraries/SubDirB/CMakeLists.txt @@ -4,8 +4,9 @@ add_executable(SubDirB SubDirB.c) # be visible to the directory in which TopDir is defined. target_link_libraries(TopDir PUBLIC debug SameNameImported optimized SameNameImported) -#FIXME: Demonstrate known issue #20204. -#target_link_libraries(TopDir PUBLIC "$<1:SameNameImported;SameNameImported>") +# Link to a list of targets imported in this directory that would not +# normally be visible to the directory in which TopDir is defined. +target_link_libraries(TopDir PUBLIC "$<1:SameNameImported;SameNameImported>") # Link SubDirA to a target imported in this directory that has the same # name as a target imported in SubDirA's directory. We verify when diff --git a/Tests/ExportImport/Export/CMakeLists.txt b/Tests/ExportImport/Export/CMakeLists.txt index 7c81aea..387fe6b 100644 --- a/Tests/ExportImport/Export/CMakeLists.txt +++ b/Tests/ExportImport/Export/CMakeLists.txt @@ -156,6 +156,7 @@ target_link_libraries(testLibDepends PRIVATE testStaticLibRequiredPrivate) cmake_policy(POP) cmake_policy(PUSH) +cmake_policy(SET CMP0022 NEW) cmake_policy(SET CMP0079 NEW) add_library(TopDirLib STATIC testTopDirLib.c) add_subdirectory(SubDirLinkA) diff --git a/Tests/ExportImport/Export/SubDirLinkA/CMakeLists.txt b/Tests/ExportImport/Export/SubDirLinkA/CMakeLists.txt index 1c3c9dc..1aa41d2 100644 --- a/Tests/ExportImport/Export/SubDirLinkA/CMakeLists.txt +++ b/Tests/ExportImport/Export/SubDirLinkA/CMakeLists.txt @@ -1,6 +1,6 @@ add_library(SubDirLinkAImported IMPORTED INTERFACE) target_compile_definitions(SubDirLinkAImported INTERFACE DEF_SubDirLinkAImportedForExport) -target_link_libraries(TopDirLib PUBLIC SubDirLinkAImported) +target_link_libraries(TopDirLib PUBLIC debug "$<1:SubDirLinkAImported;SubDirLinkAImported>" optimized "$<1:SubDirLinkAImported;SubDirLinkAImported>") add_library(SubDirLinkA STATIC SubDirLinkA.c) diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt index 7936f47..d302fe3 100644 --- a/Tests/RunCMake/CMakeLists.txt +++ b/Tests/RunCMake/CMakeLists.txt @@ -604,6 +604,9 @@ set(cpack_tests STGZ External ) +if(APPLE) + list(APPEND cpack_tests DragNDrop) +endif() add_RunCMake_test_group(CPack "${cpack_tests}") # add a test to make sure symbols are exported from a shared library # for MSVC compilers CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS property is used diff --git a/Tests/RunCMake/CPack/DragNDrop/Helpers.cmake b/Tests/RunCMake/CPack/DragNDrop/Helpers.cmake new file mode 100644 index 0000000..023e597 --- /dev/null +++ b/Tests/RunCMake/CPack/DragNDrop/Helpers.cmake @@ -0,0 +1,54 @@ +set(ALL_FILES_GLOB "*.dmg") + +function(getPackageContent FILE RESULT_VAR) + get_filename_component(path_ "${FILE}" DIRECTORY) + file(REMOVE_RECURSE "${path_}/content") + file(MAKE_DIRECTORY "${path_}/content") + execute_process(COMMAND ${HDIUTIL_EXECUTABLE} attach -mountroot ${path_}/content -nobrowse ${FILE} + RESULT_VARIABLE attach_result_ + ERROR_VARIABLE attach_error_ + OUTPUT_STRIP_TRAILING_WHITESPACE) + + if(attach_result_) + message(FATAL_ERROR "Failed to attach DMG: '${attach_result_}';" + " '${attach_error_}'.") + endif() + + file(GLOB_RECURSE package_content_ LIST_DIRECTORIES true RELATIVE + "${path_}/content" "${path_}/content/*") + # Some versions of macOS have .Trashes, others do not. + list(FILTER package_content_ EXCLUDE REGEX "/.Trashes$") + set(${RESULT_VAR} "${package_content_}" PARENT_SCOPE) + + execute_process(COMMAND ${HDIUTIL_EXECUTABLE} detach ${path_}/content/volume-name + RESULT_VARIABLE detach_result_ + ERROR_VARIABLE detach_error_ + OUTPUT_STRIP_TRAILING_WHITESPACE) + + if(detach_result_) + message(FATAL_ERROR "Failed to detach DMG: '${detach_result_}';" + " '${detach_error_}'.") + endif() +endfunction() + +function(getPackageNameGlobexpr NAME COMPONENT VERSION REVISION FILE_NO RESULT_VAR) + if(COMPONENT) + set(COMPONENT "-${COMPONENT}") + endif() + + set(${RESULT_VAR} "${NAME}-${VERSION}-Darwin${COMPONENT}.dmg" PARENT_SCOPE) +endfunction() + +function(getPackageContentList FILE RESULT_VAR) + getPackageContent("${FILE}" package_content_) + + set(${RESULT_VAR} "${package_content_}" PARENT_SCOPE) +endfunction() + +function(toExpectedContentList FILE_NO CONTENT_VAR) + set(prefix_ "volume-name") + list(TRANSFORM ${CONTENT_VAR} PREPEND "${prefix_}" OUTPUT_VARIABLE prepared_) + list(APPEND prepared_ "${prefix_}") + + set(${CONTENT_VAR} "${prepared_}" PARENT_SCOPE) +endfunction() diff --git a/Tests/RunCMake/CPack/DragNDrop/Prerequirements.cmake b/Tests/RunCMake/CPack/DragNDrop/Prerequirements.cmake new file mode 100644 index 0000000..f0aaf2c --- /dev/null +++ b/Tests/RunCMake/CPack/DragNDrop/Prerequirements.cmake @@ -0,0 +1,8 @@ +function(get_test_prerequirements found_var config_file) + find_program(HDIUTIL_EXECUTABLE hdiutil) + + if(HDIUTIL_EXECUTABLE) + file(WRITE "${config_file}" "set(HDIUTIL_EXECUTABLE \"${HDIUTIL_EXECUTABLE}\")") + set(${found_var} true PARENT_SCOPE) + endif() +endfunction() diff --git a/Tests/RunCMake/CPack/DragNDrop/packaging_COMPONENT_default.cmake b/Tests/RunCMake/CPack/DragNDrop/packaging_COMPONENT_default.cmake new file mode 100644 index 0000000..aa6c8ff --- /dev/null +++ b/Tests/RunCMake/CPack/DragNDrop/packaging_COMPONENT_default.cmake @@ -0,0 +1,3 @@ +set(CPACK_COMPONENTS_GROUPING "IGNORE") +set(CPACK_DMG_DISABLE_APPLICATIONS_SYMLINK ON) +set(CPACK_DMG_VOLUME_NAME "volume-name") diff --git a/Tests/RunCMake/CPack/RunCMakeTest.cmake b/Tests/RunCMake/CPack/RunCMakeTest.cmake index 6e413aa..0fb0cc4 100644 --- a/Tests/RunCMake/CPack/RunCMakeTest.cmake +++ b/Tests/RunCMake/CPack/RunCMakeTest.cmake @@ -5,7 +5,7 @@ include("${RunCMake_SOURCE_DIR}/CPackTestHelpers.cmake") # run_cpack_test args: TEST_NAME "GENERATORS" RUN_CMAKE_BUILD_STEP "PACKAGING_TYPES" run_cpack_test(CUSTOM_BINARY_SPEC_FILE "RPM.CUSTOM_BINARY_SPEC_FILE" false "MONOLITHIC;COMPONENT") -run_cpack_test(CUSTOM_NAMES "RPM.CUSTOM_NAMES;DEB.CUSTOM_NAMES;TGZ" true "COMPONENT") +run_cpack_test(CUSTOM_NAMES "RPM.CUSTOM_NAMES;DEB.CUSTOM_NAMES;TGZ;DragNDrop" true "COMPONENT") run_cpack_test(DEBUGINFO "RPM.DEBUGINFO;DEB.DEBUGINFO" true "COMPONENT") run_cpack_test_subtests(DEFAULT_PERMISSIONS "CMAKE_var_set;CPACK_var_set;both_set;invalid_CMAKE_var;invalid_CPACK_var" "RPM.DEFAULT_PERMISSIONS;DEB.DEFAULT_PERMISSIONS" false "MONOLITHIC;COMPONENT") run_cpack_test(DEPENDENCIES "RPM.DEPENDENCIES;DEB.DEPENDENCIES" true "COMPONENT") diff --git a/Tests/RunCMake/CPack/tests/CUSTOM_NAMES/ExpectedFiles.cmake b/Tests/RunCMake/CPack/tests/CUSTOM_NAMES/ExpectedFiles.cmake index 07226df..9ac19e2 100644 --- a/Tests/RunCMake/CPack/tests/CUSTOM_NAMES/ExpectedFiles.cmake +++ b/Tests/RunCMake/CPack/tests/CUSTOM_NAMES/ExpectedFiles.cmake @@ -12,4 +12,7 @@ if(GENERATOR_TYPE STREQUAL "DEB" OR GENERATOR_TYPE STREQUAL "RPM") elseif(GENERATOR_TYPE STREQUAL "TGZ") set(EXPECTED_FILE_2 "second.tar.gz") set(EXPECTED_FILE_3 "pkg_3_abc.tar.gz") +elseif(GENERATOR_TYPE STREQUAL "DragNDrop") + set(EXPECTED_FILE_2 "second.dmg") + set(EXPECTED_FILE_3 "pkg_3_abc.dmg") endif() diff --git a/Tests/RunCMake/CPack/tests/CUSTOM_NAMES/test.cmake b/Tests/RunCMake/CPack/tests/CUSTOM_NAMES/test.cmake index 4c20e41..899258e 100644 --- a/Tests/RunCMake/CPack/tests/CUSTOM_NAMES/test.cmake +++ b/Tests/RunCMake/CPack/tests/CUSTOM_NAMES/test.cmake @@ -10,6 +10,9 @@ if(GENERATOR_TYPE STREQUAL "DEB" OR GENERATOR_TYPE STREQUAL "RPM") elseif(GENERATOR_TYPE STREQUAL "TGZ") set(CPACK_ARCHIVE_PKG_2_FILE_NAME "second") set(CPACK_ARCHIVE_PKG_3_FILE_NAME "pkg_3_abc") +elseif(GENERATOR_TYPE STREQUAL "DragNDrop") + set(CPACK_DMG_PKG_2_FILE_NAME "second") + set(CPACK_DMG_PKG_3_FILE_NAME "pkg_3_abc") endif() install(FILES CMakeLists.txt DESTINATION foo COMPONENT pkg_1) diff --git a/Tests/RunCMake/CTest/CMakeCTestArguments-test-check.cmake b/Tests/RunCMake/CTest/CMakeCTestArguments-test-check.cmake new file mode 100644 index 0000000..3e05953 --- /dev/null +++ b/Tests/RunCMake/CTest/CMakeCTestArguments-test-check.cmake @@ -0,0 +1,4 @@ +set(log "${RunCMake_TEST_BINARY_DIR}/output-log.txt") +if(NOT EXISTS "${log}") + set(RunCMake_TEST_FAILED "The expected output log file is missing:\n ${log}") +endif() diff --git a/Tests/RunCMake/CTest/CMakeCTestArguments.cmake b/Tests/RunCMake/CTest/CMakeCTestArguments.cmake new file mode 100644 index 0000000..37f2933 --- /dev/null +++ b/Tests/RunCMake/CTest/CMakeCTestArguments.cmake @@ -0,0 +1,2 @@ +include(CTest) +add_test(NAME CMakeCTestArguments COMMAND ${CMAKE_COMMAND} -E echo CMakeCTestArguments) diff --git a/Tests/RunCMake/CTest/RunCMakeTest.cmake b/Tests/RunCMake/CTest/RunCMakeTest.cmake index 1392240..761224a 100644 --- a/Tests/RunCMake/CTest/RunCMakeTest.cmake +++ b/Tests/RunCMake/CTest/RunCMakeTest.cmake @@ -5,3 +5,16 @@ run_cmake(BeforeProject) unset(RunCMake_TEST_OPTIONS) run_cmake(NotOn) + +function(run_CMakeCTestArguments) + run_cmake_with_options(CMakeCTestArguments "-DCMAKE_CTEST_ARGUMENTS=--quiet\\;--output-log\\;output-log.txt") + set(RunCMake_TEST_NO_CLEAN 1) + set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/CMakeCTestArguments-build) + if(RunCMake_GENERATOR MATCHES "Make|Ninja") + set(test "test") + else() + set(test "RUN_TESTS") + endif() + run_cmake_command(CMakeCTestArguments-test ${CMAKE_COMMAND} --build . --config Debug --target "${test}") +endfunction() +run_CMakeCTestArguments() diff --git a/Tests/RunCMake/NinjaMultiConfig/RunCMakeTest.cmake b/Tests/RunCMake/NinjaMultiConfig/RunCMakeTest.cmake index 4b9d3ed..f3208ed 100644 --- a/Tests/RunCMake/NinjaMultiConfig/RunCMakeTest.cmake +++ b/Tests/RunCMake/NinjaMultiConfig/RunCMakeTest.cmake @@ -76,7 +76,7 @@ endfunction() set(RunCMake_TEST_NO_CLEAN 1) set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/Simple-build) -set(RunCMake_TEST_OPTIONS "-DCMAKE_NINJA_MULTI_DEFAULT_BUILD_TYPE=RelWithDebInfo;-DCMAKE_NINJA_CROSS_CONFIG_ENABLE=ON") +set(RunCMake_TEST_OPTIONS "-DCMAKE_NINJA_MULTI_DEFAULT_BUILD_TYPE=RelWithDebInfo;-DCMAKE_NINJA_MULTI_CROSS_CONFIG_ENABLE=ON") run_cmake_configure(Simple) unset(RunCMake_TEST_OPTIONS) include(${RunCMake_TEST_BINARY_DIR}/target_files.cmake) @@ -117,7 +117,7 @@ run_ninja(SimpleNoCross all-all build-Debug.ninja all:all) run_cmake_build(SimpleNoCross all-clean Debug clean:all) set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/CustomCommandGenerator-build) -set(RunCMake_TEST_OPTIONS "-DCMAKE_NINJA_CROSS_CONFIG_ENABLE=ON") +set(RunCMake_TEST_OPTIONS "-DCMAKE_NINJA_MULTI_CROSS_CONFIG_ENABLE=ON") run_cmake_configure(CustomCommandGenerator) unset(RunCMake_TEST_OPTIONS) include(${RunCMake_TEST_BINARY_DIR}/target_files.cmake) @@ -134,7 +134,7 @@ run_ninja(CustomCommandGenerator release-in-debug-graph build-Debug.ninja genera run_cmake_command(CustomCommandGenerator-release-in-debug-graph-generated "${TARGET_FILE_generated_Release}") set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/CustomCommandsAndTargets-build) -set(RunCMake_TEST_OPTIONS "-DCMAKE_NINJA_CROSS_CONFIG_ENABLE=ON") +set(RunCMake_TEST_OPTIONS "-DCMAKE_NINJA_MULTI_CROSS_CONFIG_ENABLE=ON") run_cmake_configure(CustomCommandsAndTargets) unset(RunCMake_TEST_OPTIONS) include(${RunCMake_TEST_BINARY_DIR}/target_files.cmake) @@ -150,7 +150,7 @@ run_cmake_build(CustomCommandsAndTargets debug-targetpostbuild Debug TopTargetPo run_ninja(CustomCommandsAndTargets release-targetpostbuild build-Release.ninja SubdirTargetPostBuild) set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/PostfixAndLocation-build) -set(RunCMake_TEST_OPTIONS "-DCMAKE_CONFIGURATION_TYPES=Debug\\;Release;-DCMAKE_NINJA_CROSS_CONFIG_ENABLE=ON") +set(RunCMake_TEST_OPTIONS "-DCMAKE_CONFIGURATION_TYPES=Debug\\;Release;-DCMAKE_NINJA_MULTI_CROSS_CONFIG_ENABLE=ON") run_cmake_configure(PostfixAndLocation) unset(RunCMake_TEST_OPTIONS) include(${RunCMake_TEST_BINARY_DIR}/target_files.cmake) @@ -165,14 +165,14 @@ run_ninja(Clean release-notall build-Release.ninja exenotall) run_cmake_build(Clean release-clean Release clean) set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/AdditionalCleanFiles-build) -set(RunCMake_TEST_OPTIONS "-DCMAKE_NINJA_CROSS_CONFIG_ENABLE=ON") +set(RunCMake_TEST_OPTIONS "-DCMAKE_NINJA_MULTI_CROSS_CONFIG_ENABLE=ON") run_cmake_configure(AdditionalCleanFiles) unset(RunCMake_TEST_OPTIONS) run_cmake_build(AdditionalCleanFiles release-clean Release clean) run_ninja(AdditionalCleanFiles all-clean build-Debug.ninja clean:all) set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/Install-build) -set(RunCMake_TEST_OPTIONS "-DCMAKE_INSTALL_PREFIX=${RunCMake_TEST_BINARY_DIR}/install;-DCMAKE_NINJA_CROSS_CONFIG_ENABLE=ON") +set(RunCMake_TEST_OPTIONS "-DCMAKE_INSTALL_PREFIX=${RunCMake_TEST_BINARY_DIR}/install;-DCMAKE_NINJA_MULTI_CROSS_CONFIG_ENABLE=ON") run_cmake_configure(Install) unset(RunCMake_TEST_OPTIONS) include(${RunCMake_TEST_BINARY_DIR}/target_files.cmake) @@ -194,7 +194,7 @@ endif() if(CMake_TEST_Qt5) set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/Qt5-build) - set(RunCMake_TEST_OPTIONS "-DCMAKE_NINJA_CROSS_CONFIG_ENABLE=ON") + set(RunCMake_TEST_OPTIONS "-DCMAKE_NINJA_MULTI_CROSS_CONFIG_ENABLE=ON") run_cmake_configure(Qt5) unset(RunCMake_TEST_OPTIONS) include(${RunCMake_TEST_BINARY_DIR}/target_files.cmake) diff --git a/Tests/RunCMake/target_link_libraries/CMP0079-iface-NEW-stdout.txt b/Tests/RunCMake/target_link_libraries/CMP0079-iface-NEW-stdout.txt index 90a5f37..1c5cf45 100644 --- a/Tests/RunCMake/target_link_libraries/CMP0079-iface-NEW-stdout.txt +++ b/Tests/RunCMake/target_link_libraries/CMP0079-iface-NEW-stdout.txt @@ -1 +1 @@ --- INTERFACE_LINK_LIBRARIES='foo::@\([Xx0-9A-Fa-f]+\)' +-- INTERFACE_LINK_LIBRARIES='::@\([Xx0-9A-Fa-f]+\);\$<\$<CONFIG:DEBUG>:\$<1:foo;foo>>;\$<\$<NOT:\$<CONFIG:DEBUG>>:\$<1:foo;foo>>;::@' diff --git a/Tests/RunCMake/target_link_libraries/CMP0079-iface-OLD-stdout.txt b/Tests/RunCMake/target_link_libraries/CMP0079-iface-OLD-stdout.txt index e575e16..4eb06d9 100644 --- a/Tests/RunCMake/target_link_libraries/CMP0079-iface-OLD-stdout.txt +++ b/Tests/RunCMake/target_link_libraries/CMP0079-iface-OLD-stdout.txt @@ -1 +1 @@ --- INTERFACE_LINK_LIBRARIES='foo' +-- INTERFACE_LINK_LIBRARIES='\$<\$<CONFIG:DEBUG>:\$<1:foo;foo>>;\$<\$<NOT:\$<CONFIG:DEBUG>>:\$<1:foo;foo>>' diff --git a/Tests/RunCMake/target_link_libraries/CMP0079-iface-WARN-stderr.txt b/Tests/RunCMake/target_link_libraries/CMP0079-iface-WARN-stderr.txt index 6dd7d30..4c09a1f 100644 --- a/Tests/RunCMake/target_link_libraries/CMP0079-iface-WARN-stderr.txt +++ b/Tests/RunCMake/target_link_libraries/CMP0079-iface-WARN-stderr.txt @@ -10,7 +10,25 @@ is not created in this directory. For compatibility with older versions of CMake, link library - foo + \$<1:foo;foo> + + will be looked up in the directory in which the target was created rather + than in this calling directory. +This warning is for project developers. Use -Wno-dev to suppress it. ++ +CMake Warning \(dev\) at CMP0079-iface/CMakeLists.txt:[0-9]+ \(target_link_libraries\): + Policy CMP0079 is not set: target_link_libraries allows use with targets in + other directories. Run "cmake --help-policy CMP0079" for policy details. + Use the cmake_policy command to set the policy and suppress this warning. + + Target + + top + + is not created in this directory. For compatibility with older versions of + CMake, link library + + \$<1:foo;foo> will be looked up in the directory in which the target was created rather than in this calling directory. diff --git a/Tests/RunCMake/target_link_libraries/CMP0079-iface-WARN-stdout.txt b/Tests/RunCMake/target_link_libraries/CMP0079-iface-WARN-stdout.txt index e575e16..4eb06d9 100644 --- a/Tests/RunCMake/target_link_libraries/CMP0079-iface-WARN-stdout.txt +++ b/Tests/RunCMake/target_link_libraries/CMP0079-iface-WARN-stdout.txt @@ -1 +1 @@ --- INTERFACE_LINK_LIBRARIES='foo' +-- INTERFACE_LINK_LIBRARIES='\$<\$<CONFIG:DEBUG>:\$<1:foo;foo>>;\$<\$<NOT:\$<CONFIG:DEBUG>>:\$<1:foo;foo>>' diff --git a/Tests/RunCMake/target_link_libraries/CMP0079-iface/CMakeLists.txt b/Tests/RunCMake/target_link_libraries/CMP0079-iface/CMakeLists.txt index 4b15b32..e410607 100644 --- a/Tests/RunCMake/target_link_libraries/CMP0079-iface/CMakeLists.txt +++ b/Tests/RunCMake/target_link_libraries/CMP0079-iface/CMakeLists.txt @@ -1 +1 @@ -target_link_libraries(top INTERFACE foo) +target_link_libraries(top INTERFACE debug "$<1:foo;foo>" optimized "$<1:foo;foo>") diff --git a/Tests/RunCMake/target_link_libraries/CMP0079-link-NEW-bogus-stderr.txt b/Tests/RunCMake/target_link_libraries/CMP0079-link-NEW-bogus-stderr.txt index 8670403..9e38bec 100644 --- a/Tests/RunCMake/target_link_libraries/CMP0079-link-NEW-bogus-stderr.txt +++ b/Tests/RunCMake/target_link_libraries/CMP0079-link-NEW-bogus-stderr.txt @@ -1,5 +1,5 @@ ^CMake Error at CMP0079-link-NEW-bogus.cmake:[0-9]+ \(add_executable\): - Target "top" links to target "foo::@\(0xdeadbeef\)" but the target was not + Target "top" links to target "::@\(0xdeadbeef\)" but the target was not found. Perhaps a find_package\(\) call is missing for an IMPORTED target, or an ALIAS target is missing\? Call Stack \(most recent call first\): diff --git a/Tests/RunCMake/target_link_libraries/CMP0079-link-NEW-bogus.cmake b/Tests/RunCMake/target_link_libraries/CMP0079-link-NEW-bogus.cmake index ea9e071..8932521 100644 --- a/Tests/RunCMake/target_link_libraries/CMP0079-link-NEW-bogus.cmake +++ b/Tests/RunCMake/target_link_libraries/CMP0079-link-NEW-bogus.cmake @@ -3,4 +3,4 @@ cmake_policy(SET CMP0079 NEW) enable_language(C) add_executable(top empty.c) -set_property(TARGET top APPEND PROPERTY LINK_LIBRARIES "foo::@(0xdeadbeef)") +set_property(TARGET top APPEND PROPERTY LINK_LIBRARIES "::@(0xdeadbeef);foo;::@") diff --git a/Tests/RunCMake/target_link_libraries/CMP0079-link-NEW-stdout.txt b/Tests/RunCMake/target_link_libraries/CMP0079-link-NEW-stdout.txt index 3e8c7c6..fa5d4a3 100644 --- a/Tests/RunCMake/target_link_libraries/CMP0079-link-NEW-stdout.txt +++ b/Tests/RunCMake/target_link_libraries/CMP0079-link-NEW-stdout.txt @@ -1 +1 @@ --- LINK_LIBRARIES='foo::@\([Xx0-9A-Fa-f]+\)' +-- LINK_LIBRARIES='::@\([Xx0-9A-Fa-f]+\);foo;::@' diff --git a/Utilities/std/cm/type_traits b/Utilities/std/cm/type_traits index 4dfe17b..e32c2c6 100644 --- a/Utilities/std/cm/type_traits +++ b/Utilities/std/cm/type_traits @@ -33,6 +33,8 @@ using std::bool_constant; using std::invoke_result; using std::invoke_result_t; +using std::void_t; + #else // Helper classes @@ -46,6 +48,14 @@ using invoke_result = std::result_of<F(ArgTypes...)>; template <class F, typename... ArgTypes> using invoke_result_t = typename invoke_result<F, ArgTypes...>::type; +template <typename... ArgTypes> +struct make_void +{ + typedef void type; +}; +template <typename... ArgTypes> +using void_t = typename make_void<ArgTypes...>::type; + #endif } // namespace cm diff --git a/Utilities/std/cmext/memory b/Utilities/std/cmext/memory index 540a3de..50e79df 100644 --- a/Utilities/std/cmext/memory +++ b/Utilities/std/cmext/memory @@ -6,6 +6,8 @@ #ifndef cmext_memory #define cmext_memory +#include <typeinfo> + #include <cm/type_traits> namespace cm { @@ -24,7 +26,13 @@ template <typename T, typename O, int> = 0> T& dynamic_reference_cast(O& item) { - return *(dynamic_cast<T*>(item.get())); + auto p = dynamic_cast<T*>(item.get()); + + if (p == nullptr) { + throw std::bad_cast(); + } + + return *p; } } // namespace cm diff --git a/Utilities/std/cmext/type_traits b/Utilities/std/cmext/type_traits new file mode 100644 index 0000000..da6550d --- /dev/null +++ b/Utilities/std/cmext/type_traits @@ -0,0 +1,68 @@ +// -*-c++-*- +// vim: set ft=cpp: + +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#ifndef cmext_type_traits +#define cmext_type_traits + +#include <cm/type_traits> + +namespace cm { + +// type traits for managed pointer types +template <typename> +struct is_unique_ptr : std::false_type +{ +}; +template <typename T> +struct is_unique_ptr<std::unique_ptr<T>> : std::true_type +{ +}; + +// type traits for containers +template <typename, typename = void_t<>> +struct is_container : std::false_type +{ +}; +template <typename T> +struct is_container< + T, + cm::void_t<typename T::value_type, typename T::size_type, + typename T::difference_type, typename T::iterator>> + : std::true_type +{ +}; + +template <typename, typename = void_t<>> +struct is_associative_container : std::false_type +{ +}; +template <typename T> +struct is_associative_container< + T, cm::void_t<typename T::key_type, typename T::key_compare>> + : cm::is_container<T> +{ +}; + +template <typename, typename = void_t<>> +struct is_unordered_associative_container : std::false_type +{ +}; +template <typename T> +struct is_unordered_associative_container< + T, + cm::void_t<typename T::key_type, typename T::hasher, typename T::key_equal, + typename T::local_iterator>> : cm::is_container<T> +{ +}; + +template <typename T> +using is_sequence_container = + cm::bool_constant<cm::is_container<T>::value && + !cm::is_associative_container<T>::value && + !cm::is_unordered_associative_container<T>::value>; + +} // namespace cm + +#endif |