diff options
192 files changed, 3677 insertions, 886 deletions
diff --git a/Help/command/LINK_OPTIONS_LINKER.txt b/Help/command/LINK_OPTIONS_LINKER.txt index a723375..3f66181 100644 --- a/Help/command/LINK_OPTIONS_LINKER.txt +++ b/Help/command/LINK_OPTIONS_LINKER.txt @@ -1,8 +1,8 @@ -To pass options to the linker tool, each compiler driver has is own syntax. -The ``LINKER:`` prefix can be used to specify, in a portable way, options -to pass to the linker tool. The ``LINKER:`` prefix is replaced by the required -driver option and the rest of the option string defines linker arguments using -``,`` as separator. These arguments will be formatted according to the +To pass options to the linker tool, each compiler driver has its own syntax. +The ``LINKER:`` prefix and ``,`` separator can be used to specify, in a portable +way, options to pass to the linker tool. ``LINKER:`` is replaced by the +appropriate driver option and ``,`` by the appropriate driver separator. +The driver prefix and driver separator are given by the values of the :variable:`CMAKE_<LANG>_LINKER_WRAPPER_FLAG` and :variable:`CMAKE_<LANG>_LINKER_WRAPPER_FLAG_SEP` variables. @@ -12,11 +12,11 @@ For example, ``"LINKER:-z,defs"`` becomes ``-Xlinker -z -Xlinker defs`` for The ``LINKER:`` prefix can be specified as part of a ``SHELL:`` prefix expression. -The ``LINKER:`` prefix supports, as alternate syntax, specification of -arguments using ``SHELL:`` prefix and space as separator. Previous example -becomes ``"LINKER:SHELL:-z defs"``. +The ``LINKER:`` prefix supports, as an alternative syntax, specification of +arguments using the ``SHELL:`` prefix and space as separator. The previous +example then becomes ``"LINKER:SHELL:-z defs"``. .. note:: - Specifying ``SHELL:`` prefix elsewhere than at the beginning of the + Specifying the ``SHELL:`` prefix anywhere other than at the beginning of the ``LINKER:`` prefix is not supported. diff --git a/Help/command/OPTIONS_SHELL.txt b/Help/command/OPTIONS_SHELL.txt index 530c012..0f8ec32 100644 --- a/Help/command/OPTIONS_SHELL.txt +++ b/Help/command/OPTIONS_SHELL.txt @@ -1,9 +1,9 @@ The final set of compile or link options used for a target is constructed by accumulating options from the current target and the usage requirements of -it dependencies. The set of options is de-duplicated to avoid repetition. +its dependencies. The set of options is de-duplicated to avoid repetition. While beneficial for individual options, the de-duplication step can break up option groups. For example, ``-D A -D B`` becomes ``-D A B``. One may specify a group of options using shell-like quoting along with a ``SHELL:`` -prefix. The ``SHELL:`` prefix is dropped and the rest of the option string +prefix. The ``SHELL:`` prefix is dropped, and the rest of the option string is parsed using the :command:`separate_arguments` ``UNIX_COMMAND`` mode. For example, ``"SHELL:-D A" "SHELL:-D B"`` becomes ``-D A -D B``. diff --git a/Help/command/message.rst b/Help/command/message.rst index 3002842..beb820a 100644 --- a/Help/command/message.rst +++ b/Help/command/message.rst @@ -57,14 +57,28 @@ are sent to stderr and are not prefixed with hyphens. The :manual:`CMake GUI <cmake-gui(1)>` displays all messages in its log area. The :manual:`curses interface <ccmake(1)>` shows ``STATUS`` to ``TRACE`` messages one at a time on a status line and other messages in an -interactive pop-up box. The ``--loglevel`` command-line option to each of +interactive pop-up box. The ``--log-level`` command-line option to each of these tools can be used to control which messages will be shown. +To make a log level persist between CMake runs, the +:variable:`CMAKE_MESSAGE_LOG_LEVEL` variable can be set instead. +Note that the command line option takes precedence over the cache variable. -Messages of log levels ``NOTICE`` and below will also have each line preceded +Messages of log levels ``NOTICE`` and below will have each line preceded by the content of the :variable:`CMAKE_MESSAGE_INDENT` variable (converted to a single string by concatenating its list items). For ``STATUS`` to ``TRACE`` messages, this indenting content will be inserted after the hyphens. +Messages of log levels ``NOTICE`` and below can also have each line preceded +with context of the form ``[some.context.example]``. The content between the +square brackets is obtained by converting the :variable:`CMAKE_MESSAGE_CONTEXT` +list variable to a dot-separated string. The message context will always +appear before any indenting content but after any automatically added leading +hyphens. By default, message context is not shown, it has to be explicitly +enabled by giving the :manual:`cmake <cmake(1)>` ``--log-context`` +command-line option or by setting the :variable:`CMAKE_MESSAGE_CONTEXT_SHOW` +variable to true. See the :variable:`CMAKE_MESSAGE_CONTEXT` documentation for +usage examples. + CMake Warning and Error message text displays using a simple markup language. Non-indented text is formatted in line-wrapped paragraphs delimited by newlines. Indented text is considered pre-formatted. diff --git a/Help/command/target_precompile_headers.rst b/Help/command/target_precompile_headers.rst index 3a32f41..d283948 100644 --- a/Help/command/target_precompile_headers.rst +++ b/Help/command/target_precompile_headers.rst @@ -47,6 +47,9 @@ with the syntax ``$<...>``. See the :manual:`cmake-generator-expressions(7)` manual for available expressions. See the :manual:`cmake-compile-features(7)` manual for information on compile features and a list of supported compilers. +The ``$<COMPILE_LANGUAGE:...>`` generator expression is particularly +useful for specifying a language-specific header to precompile for +only one language (e.g. ``CXX`` and not ``C``). Usage ^^^^^ @@ -56,6 +59,7 @@ Usage target_precompile_headers(<target> PUBLIC project_header.h + "$<$<COMPILE_LANGUAGE:CXX>:cxx_only.h>" PRIVATE [["other_header.h"]] <unordered_map> diff --git a/Help/manual/cmake-properties.7.rst b/Help/manual/cmake-properties.7.rst index 1369aa3..02e07eb 100644 --- a/Help/manual/cmake-properties.7.rst +++ b/Help/manual/cmake-properties.7.rst @@ -342,6 +342,7 @@ Properties on Targets /prop_tgt/VS_DOTNET_REFERENCES /prop_tgt/VS_DOTNET_REFERENCES_COPY_LOCAL /prop_tgt/VS_DOTNET_TARGET_FRAMEWORK_VERSION + /prop_tgt/VS_DOTNET_DOCUMENTATION_FILE /prop_tgt/VS_DPI_AWARE /prop_tgt/VS_GLOBAL_KEYWORD /prop_tgt/VS_GLOBAL_PROJECT_TYPES diff --git a/Help/manual/cmake-variables.7.rst b/Help/manual/cmake-variables.7.rst index 0442d89..cad0df6 100644 --- a/Help/manual/cmake-variables.7.rst +++ b/Help/manual/cmake-variables.7.rst @@ -70,7 +70,6 @@ Variables that Provide Information /variable/CMAKE_MAKE_PROGRAM /variable/CMAKE_MATCH_COUNT /variable/CMAKE_MATCH_n - /variable/CMAKE_MESSAGE_INDENT /variable/CMAKE_MINIMUM_REQUIRED_VERSION /variable/CMAKE_MINOR_VERSION /variable/CMAKE_NETRC @@ -205,6 +204,10 @@ Variables that Change Behavior /variable/CMAKE_LINK_DIRECTORIES_BEFORE /variable/CMAKE_MFC_FLAG /variable/CMAKE_MAXIMUM_RECURSION_DEPTH + /variable/CMAKE_MESSAGE_CONTEXT + /variable/CMAKE_MESSAGE_CONTEXT_SHOW + /variable/CMAKE_MESSAGE_INDENT + /variable/CMAKE_MESSAGE_LOG_LEVEL /variable/CMAKE_MODULE_PATH /variable/CMAKE_POLICY_DEFAULT_CMPNNNN /variable/CMAKE_POLICY_WARNING_CMPNNNN diff --git a/Help/manual/cmake.1.rst b/Help/manual/cmake.1.rst index 754f14b..71110d1 100644 --- a/Help/manual/cmake.1.rst +++ b/Help/manual/cmake.1.rst @@ -200,12 +200,30 @@ Options from the top of a binary tree for a CMake project it will dump additional information such as the cache, log files etc. -``--loglevel=<ERROR|WARNING|NOTICE|STATUS|VERBOSE|DEBUG|TRACE>`` +``--log-level=<ERROR|WARNING|NOTICE|STATUS|VERBOSE|DEBUG|TRACE>`` Set the log level. The :command:`message` command will only output messages of the specified log level or higher. The default log level is ``STATUS``. + To make a log level persist between CMake runs, set + :variable:`CMAKE_MESSAGE_LOG_LEVEL` as a cache variable instead. + If both the command line option and the variable are given, the command line + option takes precedence. + + For backward compatibility reasons, ``--loglevel`` is also accepted as a + synonym for this option. + +``--log-context`` + Enable the :command:`message` command outputting context attached to each + message. + + This option turns on showing context for the current CMake run only. + To make showing the context persistent for all subsequent CMake runs, set + :variable:`CMAKE_MESSAGE_CONTEXT_SHOW` as a cache variable instead. + When this command line option is given, :variable:`CMAKE_MESSAGE_CONTEXT_SHOW` + is ignored. + ``--debug-trycompile`` Do not delete the :command:`try_compile` build tree. Only useful on one :command:`try_compile` at a time. diff --git a/Help/prop_tgt/UNITY_BUILD.rst b/Help/prop_tgt/UNITY_BUILD.rst index beac5d4..2faad92 100644 --- a/Help/prop_tgt/UNITY_BUILD.rst +++ b/Help/prop_tgt/UNITY_BUILD.rst @@ -5,27 +5,33 @@ Should the target source files be processed into batches for faster compilation. This feature is known as "Unity build", or "Jumbo build". -The `C` and `CXX` source files are grouped separately. +The ``C`` and ``CXX`` source files are grouped separately. This property is initialized by the value of the :variable:`CMAKE_UNITY_BUILD` variable if it is set when a target is created. -.. note :: +.. note:: - It's not recommended to directly set :prop_tgt:`UNITY_BUILD` - to `ON`, but to instead set :variable:`CMAKE_UNITY_BUILD` from - the command line. However, it IS recommended to set - :prop_tgt:`UNITY_BUILD` to `OFF` if you need to ensure that a - target doesn't get a unity build. + It's not recommended to directly set :prop_tgt:`UNITY_BUILD` + to ``ON``, but to instead set :variable:`CMAKE_UNITY_BUILD` from + the command line. However, it IS recommended to set + :prop_tgt:`UNITY_BUILD` to ``OFF`` if you need to ensure that a + target doesn't get a unity build. The batch size can be specified by setting :prop_tgt:`UNITY_BUILD_BATCH_SIZE`. The batching of source files is done by adding new sources files -wich will `#include` the source files, and exclude them from -building by setting :prop_sf:`HEADER_FILE_ONLY` to `ON`. +which will ``#include`` the source files, and exclude them from +building by setting :prop_sf:`HEADER_FILE_ONLY` to ``ON``. +.. note:: + + Marking the original sources with :prop_sf:`HEADER_FILE_ONLY` + is considered an implementation detail that may change in the + future because it does not work well in combination with + the :variable:`CMAKE_EXPORT_COMPILE_COMMANDS` variable. ODR (One definition rule) errors ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -45,11 +51,11 @@ The source files that have :prop_sf:`COMPILE_OPTIONS`, With the :prop_tgt:`UNITY_BUILD_CODE_BEFORE_INCLUDE` and :prop_tgt:`UNITY_BUILD_CODE_AFTER_INCLUDE` one can specify code to be injected in the unity source file before and after every -`#include` statement. +``#include`` statement. -.. note :: +.. note:: - The order of source files defined in the `CMakeLists.txt` will - be preserved into the generated unity source files. This can - be used to manually enforce a specific grouping based on the - :prop_tgt:`UNITY_BUILD_BATCH_SIZE`. + The order of source files defined in the ``CMakeLists.txt`` will + be preserved into the generated unity source files. This can + be used to manually enforce a specific grouping based on the + :prop_tgt:`UNITY_BUILD_BATCH_SIZE` target property. diff --git a/Help/prop_tgt/VS_DOTNET_DOCUMENTATION_FILE.rst b/Help/prop_tgt/VS_DOTNET_DOCUMENTATION_FILE.rst new file mode 100644 index 0000000..1bc361c --- /dev/null +++ b/Help/prop_tgt/VS_DOTNET_DOCUMENTATION_FILE.rst @@ -0,0 +1,6 @@ +VS_DOTNET_DOCUMENTATION_FILE +---------------------------- + +Visual Studio managed project .NET documentation output + +Sets the target XML documentation file output. diff --git a/Help/release/3.16.rst b/Help/release/3.16.rst index 2b1ecf5..7992f2d 100644 --- a/Help/release/3.16.rst +++ b/Help/release/3.16.rst @@ -56,6 +56,11 @@ Command-Line option that can be used to redirect ``--trace`` output to a file instead of ``stderr``. +* The :manual:`cmake(1)` ``--loglevel`` command line option has been + renamed to ``--log-level`` to make it consistent with the naming of other + command line options. The ``--loglevel`` option is still supported to + preserve backward compatibility. + Commands -------- @@ -110,6 +115,10 @@ Variables specify the resource encoding for the the :generator:`Eclipse CDT4` extra generator. +* The :variable:`CMAKE_UNITY_BUILD` variable was added to initialize the + :prop_tgt:`UNITY_BUILD` target property to tell generators to batch + include source files for faster compilation times. + Properties ---------- diff --git a/Help/release/dev/FindCURL-cmake-package.rst b/Help/release/dev/FindCURL-cmake-package.rst new file mode 100644 index 0000000..67c5bbc --- /dev/null +++ b/Help/release/dev/FindCURL-cmake-package.rst @@ -0,0 +1,7 @@ +FindCURL-cmake-package +---------------------- + +* The :module:`FindCURL` module learned to find CURL using + the ``CURLConfig.cmake`` package configuration file generated by + CURL's cmake buildsystem. It also gained a new ``CURL_NO_CURL_CMAKE`` + option to disable this behavior. diff --git a/Help/release/dev/deprecate-policy-old.rst b/Help/release/dev/deprecate-policy-old.rst new file mode 100644 index 0000000..401f4b2 --- /dev/null +++ b/Help/release/dev/deprecate-policy-old.rst @@ -0,0 +1,8 @@ +deprecate-policy-old +-------------------- + +* An explicit deprecation diagnostic was added for policy ``CMP0068`` + and policy ``CMP0069`` (``CMP0067`` and below were already deprecated). + The :manual:`cmake-policies(7)` manual explains that the OLD behaviors + of all policies are deprecated and that projects should port to the + NEW behaviors. diff --git a/Help/release/dev/feature-CMAKE_MESSAGE_CONTEXT b/Help/release/dev/feature-CMAKE_MESSAGE_CONTEXT new file mode 100644 index 0000000..a6a5c71 --- /dev/null +++ b/Help/release/dev/feature-CMAKE_MESSAGE_CONTEXT @@ -0,0 +1,11 @@ +feature-CMAKE_MESSAGE_CONTEXT +----------------------------- + +* The :variable:`CMAKE_MESSAGE_LOG_LEVEL` variable can now be used + to persist a log level between CMake runs, unlike the ``--log-level`` + command line option which only applies to that particular run. + +* The :command:`message` command learned to output context provided in + the :variable:`CMAKE_MESSAGE_CONTEXT` variable for log levels + ``NOTICE`` and below. Enable this output with the new ``--log-context`` + command-line option or :variable:`CMAKE_MESSAGE_CONTEXT_SHOW` variable. diff --git a/Help/release/dev/vs-vctargetspath.rst b/Help/release/dev/vs-vctargetspath.rst new file mode 100644 index 0000000..d40af34 --- /dev/null +++ b/Help/release/dev/vs-vctargetspath.rst @@ -0,0 +1,10 @@ +vs-vctargetspath +---------------- + +* With :ref:`Visual Studio Generators` for VS 2010 and above, + the :variable:`CMAKE_GENERATOR_TOOLSET` setting gained an option + to specify the ``VCTargetsPath`` value for project files. + +* The :variable:`CMAKE_VS_GLOBALS` variable value now applies during + compiler identification and in targets created by the + :command:`add_custom_target` command. diff --git a/Help/release/dev/vs_dotnet_documentation_file.rst b/Help/release/dev/vs_dotnet_documentation_file.rst new file mode 100644 index 0000000..fdffb1c --- /dev/null +++ b/Help/release/dev/vs_dotnet_documentation_file.rst @@ -0,0 +1,6 @@ +vs_dotnet_documentation_file +---------------------------- + +* The :prop_tgt:`VS_DOTNET_DOCUMENTATION_FILE` target property was added + to tell :ref:`Visual Studio Generators` to generate a ``DocumentationFile`` + reference in ``.csproj`` files. diff --git a/Help/variable/CMAKE_EXPORT_COMPILE_COMMANDS.rst b/Help/variable/CMAKE_EXPORT_COMPILE_COMMANDS.rst index 8776279..4548abc 100644 --- a/Help/variable/CMAKE_EXPORT_COMPILE_COMMANDS.rst +++ b/Help/variable/CMAKE_EXPORT_COMPILE_COMMANDS.rst @@ -28,3 +28,7 @@ form. The format of the JSON file looks like: .. note:: This option is implemented only by :ref:`Makefile Generators` and the :generator:`Ninja`. It is ignored on other generators. + + This option currently does not work well in combination with + the :prop_tgt:`UNITY_BUILD` target property or the + :variable:`CMAKE_UNITY_BUILD` variable. diff --git a/Help/variable/CMAKE_GENERATOR_TOOLSET.rst b/Help/variable/CMAKE_GENERATOR_TOOLSET.rst index 222824f..53ad2f3 100644 --- a/Help/variable/CMAKE_GENERATOR_TOOLSET.rst +++ b/Help/variable/CMAKE_GENERATOR_TOOLSET.rst @@ -58,3 +58,8 @@ Supported pairs are: Specify the toolset version to use. Supported by VS 2017 and above with the specified toolset installed. See the :variable:`CMAKE_VS_PLATFORM_TOOLSET_VERSION` variable. + +``VCTargetsPath=<path>`` + Specify an alternative ``VCTargetsPath`` value for Visual Studio + project files. This allows use of VS platform extension configuration + files (``.props`` and ``.targets``) that are not installed with VS. diff --git a/Help/variable/CMAKE_MESSAGE_CONTEXT.rst b/Help/variable/CMAKE_MESSAGE_CONTEXT.rst new file mode 100644 index 0000000..6b4ca40 --- /dev/null +++ b/Help/variable/CMAKE_MESSAGE_CONTEXT.rst @@ -0,0 +1,62 @@ +CMAKE_MESSAGE_CONTEXT +--------------------- + +When enabled by the :manual:`cmake <cmake(1)>` ``--log-context`` command line +option or the :variable:`CMAKE_MESSAGE_CONTEXT_SHOW` variable, the +:command:`message` command converts the ``CMAKE_MESSAGE_CONTEXT`` list into a +dot-separated string surrounded by square brackets and prepends it to each line +for messages of log levels ``NOTICE`` and below. + +For logging contexts to work effectively, projects should generally +``APPEND`` and ``POP_BACK`` an item to the current value of +``CMAKE_MESSAGE_CONTEXT`` rather than replace it. +Projects should not assume the message context at the top of the source tree +is empty, as there are scenarios where the context might have already been set +(e.g. hierarchical projects). + +.. warning:: + + Valid context names are restricted to anything that could be used + as a CMake variable name. All names that begin with an underscore + or the string ``cmake_`` are also reserved for use by CMake and + should not be used by projects. + +Example: + +.. code-block:: cmake + + function(bar) + list(APPEND CMAKE_MESSAGE_CONTEXT "bar") + message(VERBOSE "bar VERBOSE message") + endfunction() + + function(baz) + list(APPEND CMAKE_MESSAGE_CONTEXT "baz") + message(DEBUG "baz DEBUG message") + endfunction() + + function(foo) + list(APPEND CMAKE_MESSAGE_CONTEXT "foo") + bar() + message(TRACE "foo TRACE message") + baz() + endfunction() + + list(APPEND CMAKE_MESSAGE_CONTEXT "top") + + message(VERBOSE "Before `foo`") + foo() + message(VERBOSE "After `foo`") + + list(POP_BACK CMAKE_MESSAGE_CONTEXT) + + +Which results in the following output: + +.. code-block:: none + + -- [top] Before `foo` + -- [top.foo.bar] bar VERBOSE message + -- [top.foo] foo TRACE message + -- [top.foo.baz] baz DEBUG message + -- [top] After `foo` diff --git a/Help/variable/CMAKE_MESSAGE_CONTEXT_SHOW.rst b/Help/variable/CMAKE_MESSAGE_CONTEXT_SHOW.rst new file mode 100644 index 0000000..7ec218e --- /dev/null +++ b/Help/variable/CMAKE_MESSAGE_CONTEXT_SHOW.rst @@ -0,0 +1,15 @@ +CMAKE_MESSAGE_CONTEXT_SHOW +-------------------------- + +Setting this variable to true enables showing a context with each line +logged by the :command:`message` command (see :variable:`CMAKE_MESSAGE_CONTEXT` +for how the context itself is specified). + +This variable is an alternative to providing the ``--log-context`` option +on the :manual:`cmake <cmake(1)>` command line. Whereas the command line +option will apply only to that one CMake run, setting +``CMAKE_MESSAGE_CONTEXT_SHOW`` to true as a cache variable will ensure that +subsequent CMake runs will continue to show the message context. + +Projects should not set ``CMAKE_MESSAGE_CONTEXT_SHOW``. It is intended for +users so that they may control whether or not to include context with messages. diff --git a/Help/variable/CMAKE_MESSAGE_LOG_LEVEL.rst b/Help/variable/CMAKE_MESSAGE_LOG_LEVEL.rst new file mode 100644 index 0000000..1d4cfe6 --- /dev/null +++ b/Help/variable/CMAKE_MESSAGE_LOG_LEVEL.rst @@ -0,0 +1,15 @@ +CMAKE_MESSAGE_LOG_LEVEL +----------------------- + +When set, this variable specifies the logging level used by the +:command:`message` command. Valid values are the same as those for the +``--log-level`` command line option of the :manual:`cmake(1)` program. +If this variable is set and the ``--log-level`` command line option is +given, the command line option takes precedence. + +The main advantage to using this variable is to make a log level persist +between CMake runs. Setting it as a cache variable will ensure that +subsequent CMake runs will continue to use the chosen log level. + +Projects should not set this variable, it is intended for users so that +they may control the log level according to their own needs. diff --git a/Help/variable/CMAKE_STATIC_LINKER_FLAGS.rst b/Help/variable/CMAKE_STATIC_LINKER_FLAGS.rst index 9c38673..1a810ce 100644 --- a/Help/variable/CMAKE_STATIC_LINKER_FLAGS.rst +++ b/Help/variable/CMAKE_STATIC_LINKER_FLAGS.rst @@ -1,6 +1,12 @@ CMAKE_STATIC_LINKER_FLAGS ------------------------- -Linker flags to be used to create static libraries. +Flags to be used to create static libraries. These flags will be passed +to the archiver when creating a static library. -These flags will be used by the linker when creating a static library. +See also :variable:`CMAKE_STATIC_LINKER_FLAGS_<CONFIG>`. + +.. note:: + Static libraries do not actually link. They are essentially archives + of object files. The use of the name "linker" in the name of this + variable is kept for compatibility. diff --git a/Help/variable/CMAKE_STATIC_LINKER_FLAGS_CONFIG.rst b/Help/variable/CMAKE_STATIC_LINKER_FLAGS_CONFIG.rst index b9f8003..e561dc6 100644 --- a/Help/variable/CMAKE_STATIC_LINKER_FLAGS_CONFIG.rst +++ b/Help/variable/CMAKE_STATIC_LINKER_FLAGS_CONFIG.rst @@ -1,7 +1,13 @@ CMAKE_STATIC_LINKER_FLAGS_<CONFIG> ---------------------------------- -Flags to be used when linking a static library. +Flags to be used to create static libraries. These flags will be passed +to the archiver when creating a static library in the ``<CONFIG>`` +configuration. -Same as ``CMAKE_C_FLAGS_*`` but used by the linker when creating static -libraries. +See also :variable:`CMAKE_STATIC_LINKER_FLAGS`. + +.. note:: + Static libraries do not actually link. They are essentially archives + of object files. The use of the name "linker" in the name of this + variable is kept for compatibility. diff --git a/Help/variable/CMAKE_UNITY_BUILD.rst b/Help/variable/CMAKE_UNITY_BUILD.rst index 3096954..bbcfd68 100644 --- a/Help/variable/CMAKE_UNITY_BUILD.rst +++ b/Help/variable/CMAKE_UNITY_BUILD.rst @@ -1,6 +1,12 @@ CMAKE_UNITY_BUILD ----------------- -Default value for :prop_tgt:`UNITY_BUILD` of targets. +Initializes the :prop_tgt:`UNITY_BUILD` target property on targets +as they are created. Set to ``ON`` to batch compilation of multiple +sources within each target. This feature is known as "Unity build", +or "Jumbo build". By default this variable is not set and so does +not enable unity builds on targets. -By default ``CMAKE_UNITY_BUILD`` is ``OFF``. +.. note:: + This option currently does not work well in combination with + the :variable:`CMAKE_EXPORT_COMPILE_COMMANDS` variable. diff --git a/Modules/CMakeCXXCompiler.cmake.in b/Modules/CMakeCXXCompiler.cmake.in index ef65021..efb8abf 100644 --- a/Modules/CMakeCXXCompiler.cmake.in +++ b/Modules/CMakeCXXCompiler.cmake.in @@ -45,7 +45,7 @@ set(CMAKE_CXX_COMPILER_ID_RUN 1) set(CMAKE_CXX_SOURCE_FILE_EXTENSIONS C;M;c++;cc;cpp;cxx;m;mm;CPP) set(CMAKE_CXX_IGNORE_EXTENSIONS inl;h;hpp;HPP;H;o;O;obj;OBJ;def;DEF;rc;RC) -foreach (lang OBJC OBJCXX) +foreach (lang C OBJC OBJCXX) if (CMAKE_${lang}_COMPILER_ID_RUN) foreach(extension IN LISTS CMAKE_${lang}_SOURCE_FILE_EXTENSIONS) list(REMOVE_ITEM CMAKE_CXX_SOURCE_FILE_EXTENSIONS ${extension}) diff --git a/Modules/CMakeCXXCompilerId.cpp.in b/Modules/CMakeCXXCompilerId.cpp.in index 34639b4..a743ce7 100644 --- a/Modules/CMakeCXXCompilerId.cpp.in +++ b/Modules/CMakeCXXCompilerId.cpp.in @@ -27,10 +27,20 @@ char const *info_cray = "INFO" ":" "compiler_wrapper[CrayPrgEnv]"; @CMAKE_CXX_COMPILER_ID_PLATFORM_CONTENT@ @CMAKE_CXX_COMPILER_ID_ERROR_FOR_TEST@ -#if defined(_MSC_VER) && defined(_MSVC_LANG) -#define CXX_STD _MSVC_LANG +#if defined(__INTEL_COMPILER) && defined(_MSVC_LANG) && _MSVC_LANG < 201403L +# if defined(__INTEL_CXX11_MODE__) +# if defined(__cpp_aggregate_nsdmi) +# define CXX_STD 201402L +# else +# define CXX_STD 201103L +# endif +# else +# define CXX_STD 199711L +# endif +#elif defined(_MSC_VER) && defined(_MSVC_LANG) +# define CXX_STD _MSVC_LANG #else -#define CXX_STD __cplusplus +# define CXX_STD __cplusplus #endif const char* info_language_dialect_default = "INFO" ":" "dialect_default[" diff --git a/Modules/CMakeDetermineCompilerId.cmake b/Modules/CMakeDetermineCompilerId.cmake index 908e530..f7ef755 100644 --- a/Modules/CMakeDetermineCompilerId.cmake +++ b/Modules/CMakeDetermineCompilerId.cmake @@ -317,6 +317,15 @@ Id flags: ${testflags} ${CMAKE_${lang}_COMPILER_ID_FLAGS_ALWAYS} if(CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION) set(id_WindowsTargetPlatformVersion "<WindowsTargetPlatformVersion>${CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION}</WindowsTargetPlatformVersion>") endif() + if(CMAKE_VS_PLATFORM_TOOLSET_VCTARGETS_CUSTOM_DIR) + set(id_ToolsetVCTargetsDir "<VCTargetsPath>${CMAKE_VS_PLATFORM_TOOLSET_VCTARGETS_CUSTOM_DIR}</VCTargetsPath>") + endif() + set(id_CustomGlobals "") + foreach(pair IN LISTS CMAKE_VS_GLOBALS) + if("${pair}" MATCHES "([^=]+)=(.*)$") + string(APPEND id_CustomGlobals "<${CMAKE_MATCH_1}>${CMAKE_MATCH_2}</${CMAKE_MATCH_1}>\n ") + endif() + endforeach() if(id_platform STREQUAL ARM64) set(id_WindowsSDKDesktopARMSupport "<WindowsSDKDesktopARM64Support>true</WindowsSDKDesktopARM64Support>") elseif(id_platform STREQUAL ARM) diff --git a/Modules/CMakeFindBinUtils.cmake b/Modules/CMakeFindBinUtils.cmake index 3887b2d..69ace5a 100644 --- a/Modules/CMakeFindBinUtils.cmake +++ b/Modules/CMakeFindBinUtils.cmake @@ -167,18 +167,6 @@ else() HINTS ${_CMAKE_TOOLCHAIN_LOCATION}) list(APPEND _CMAKE_TOOL_VARS AR RANLIB STRIP LINKER NM OBJDUMP OBJCOPY READELF DLLTOOL ADDR2LINE) - - - unset(_CMAKE_ADDITIONAL_AR_NAMES) - unset(_CMAKE_ADDITIONAL_RANLIB_NAMES) - unset(_CMAKE_ADDITIONAL_STRIP_NAMES) - unset(_CMAKE_ADDITIONAL_LINKER_NAMES) - unset(_CMAKE_ADDITIONAL_NM_NAMES) - unset(_CMAKE_ADDITIONAL_OBJDUMP_NAMES) - unset(_CMAKE_ADDITIONAL_OBJCOPY_NAMES) - unset(_CMAKE_ADDITIONAL_READELF_NAMES) - unset(_CMAKE_ADDITIONAL_DLLTOOL_NAMES) - unset(_CMAKE_ADDITIONAL_ADDR2LINE_NAMES) endif() if(CMAKE_PLATFORM_HAS_INSTALLNAME) diff --git a/Modules/CMakeGraphVizOptions.cmake b/Modules/CMakeGraphVizOptions.cmake index 1911e73..be4a3be 100644 --- a/Modules/CMakeGraphVizOptions.cmake +++ b/Modules/CMakeGraphVizOptions.cmake @@ -5,119 +5,145 @@ CMakeGraphVizOptions -------------------- -The builtin graphviz support of CMake. +The builtin Graphviz support of CMake. -Variables specific to the graphviz support -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Generating Graphviz files +^^^^^^^^^^^^^^^^^^^^^^^^^ -CMake -can generate `graphviz <http://www.graphviz.org/>`_ files, showing the dependencies between the -targets in a project and also external libraries which are linked -against. When CMake is run with the ``--graphviz=foo.dot`` option, it will -produce: +CMake can generate `Graphviz <https://www.graphviz.org/>`_ files showing the +dependencies between the targets in a project, as well as external libraries +which are linked against. -* a ``foo.dot`` file showing all dependencies in the project -* a ``foo.dot.<target>`` file for each target, file showing on which other targets the respective target depends -* a ``foo.dot.<target>.dependers`` file, showing which other targets depend on the respective target +When running CMake with the ``--graphviz=foo.dot`` option, it produces: -The different dependency types ``PUBLIC``, ``PRIVATE`` and ``INTERFACE`` -are represented as solid, dashed and dotted edges. +* a ``foo.dot`` file, showing all dependencies in the project +* a ``foo.dot.<target>`` file for each target, showing on which other targets + it depends +* a ``foo.dot.<target>.dependers`` file for each target, showing which other + targets depend on it -This can result in huge graphs. Using the file -``CMakeGraphVizOptions.cmake`` the look and content of the generated -graphs can be influenced. This file is searched first in -:variable:`CMAKE_BINARY_DIR` and then in :variable:`CMAKE_SOURCE_DIR`. If found, it is -read and the variables set in it are used to adjust options for the -generated graphviz files. +Those .dot files can be converted to images using the *dot* command from the +Graphviz package: -.. variable:: GRAPHVIZ_GRAPH_TYPE +.. code-block:: shell - The graph type. + dot -Tpng -o foo.png foo.dot - * Mandatory : NO - * Default : "digraph" +The different dependency types ``PUBLIC``, ``INTERFACE`` and ``PRIVATE`` +are represented as solid, dashed and dotted edges. - Valid graph types are: +Variables specific to the Graphviz support +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - * "graph" : Nodes are joined with lines - * "digraph" : Nodes are joined with arrows showing direction - * "strict graph" : Like "graph" but max one line between each node - * "strict digraph" : Like "graph" but max one line between each node in each direction +The resulting graphs can be huge. The look and content of the generated graphs +can be controlled using the file ``CMakeGraphVizOptions.cmake``. This file is +first searched in :variable:`CMAKE_BINARY_DIR`, and then in +:variable:`CMAKE_SOURCE_DIR`. If found, the variables set in it are used to +adjust options for the generated Graphviz files. .. variable:: GRAPHVIZ_GRAPH_NAME The graph name. - * Mandatory : NO - * Default : "GG" + * Mandatory: NO + * Default: value of :variable:`CMAKE_PROJECT_NAME` .. variable:: GRAPHVIZ_GRAPH_HEADER - The header written at the top of the graphviz file. + The header written at the top of the Graphviz files. - * Mandatory : NO - * Default : "node [n fontsize = "12"];" + * Mandatory: NO + * Default: "node [ fontsize = "12" ];" .. variable:: GRAPHVIZ_NODE_PREFIX - The prefix for each node in the graphviz file. + The prefix for each node in the Graphviz files. - * Mandatory : NO - * Default : "node" + * Mandatory: NO + * Default: "node" .. variable:: GRAPHVIZ_EXECUTABLES - Set this to FALSE to exclude executables from the generated graphs. + Set to FALSE to exclude executables from the generated graphs. - * Mandatory : NO - * Default : TRUE + * Mandatory: NO + * Default: TRUE .. variable:: GRAPHVIZ_STATIC_LIBS - Set this to FALSE to exclude static libraries from the generated graphs. + Set to FALSE to exclude static libraries from the generated graphs. - * Mandatory : NO - * Default : TRUE + * Mandatory: NO + * Default: TRUE .. variable:: GRAPHVIZ_SHARED_LIBS - Set this to FALSE to exclude shared libraries from the generated graphs. + Set to FALSE to exclude shared libraries from the generated graphs. - * Mandatory : NO - * Default : TRUE + * Mandatory: NO + * Default: TRUE .. variable:: GRAPHVIZ_MODULE_LIBS - Set this to FALSE to exclude module libraries from the generated graphs. + Set to FALSE to exclude module libraries from the generated graphs. + + * Mandatory: NO + * Default: TRUE + +.. variable:: GRAPHVIZ_INTERFACE_LIBS + + Set to FALSE to exclude interface libraries from the generated graphs. + + * Mandatory: NO + * Default: TRUE - * Mandatory : NO - * Default : TRUE +.. variable:: GRAPHVIZ_OBJECT_LIBS + + Set to FALSE to exclude object libraries from the generated graphs. + + * Mandatory: NO + * Default: TRUE + +.. variable:: GRAPHVIZ_UNKNOWN_LIBS + + Set to FALSE to exclude unknown libraries from the generated graphs. + + * Mandatory: NO + * Default: TRUE .. variable:: GRAPHVIZ_EXTERNAL_LIBS - Set this to FALSE to exclude external libraries from the generated graphs. + Set to FALSE to exclude external libraries from the generated graphs. + + * Mandatory: NO + * Default: TRUE + +.. variable:: GRAPHVIZ_CUSTOM_TARGETS + + Set to TRUE to include custom targets in the generated graphs. - * Mandatory : NO - * Default : TRUE + * Mandatory: NO + * Default: FALSE .. variable:: GRAPHVIZ_IGNORE_TARGETS - A list of regular expressions for ignoring targets. + A list of regular expressions for names of targets to exclude from the + generated graphs. - * Mandatory : NO - * Default : empty + * Mandatory: NO + * Default: empty .. variable:: GRAPHVIZ_GENERATE_PER_TARGET - Set this to FALSE to exclude per target graphs ``foo.dot.<target>``. + Set to FALSE to not generate per-target graphs ``foo.dot.<target>``. - * Mandatory : NO - * Default : TRUE + * Mandatory: NO + * Default: TRUE .. variable:: GRAPHVIZ_GENERATE_DEPENDERS - Set this to FALSE to exclude depender graphs ``foo.dot.<target>.dependers``. + Set to FALSE to not generate depender graphs ``foo.dot.<target>.dependers``. - * Mandatory : NO - * Default : TRUE + * Mandatory: NO + * Default: TRUE #]=======================================================================] diff --git a/Modules/CMakePlatformId.h.in b/Modules/CMakePlatformId.h.in index 95465ce..64a00b3 100644 --- a/Modules/CMakePlatformId.h.in +++ b/Modules/CMakePlatformId.h.in @@ -177,6 +177,9 @@ # elif defined(__ICCV850__) # define ARCHITECTURE_ID "V850" +# elif defined(__ICC8051__) +# define ARCHITECTURE_ID "8051" + # else /* unknown architecture */ # define ARCHITECTURE_ID "" # endif diff --git a/Modules/Compiler/IAR-ASM.cmake b/Modules/Compiler/IAR-ASM.cmake index 413d9e2..936d4ae 100644 --- a/Modules/Compiler/IAR-ASM.cmake +++ b/Modules/Compiler/IAR-ASM.cmake @@ -40,7 +40,12 @@ elseif("${CMAKE_ASM${ASM_DIALECT}_COMPILER_ARCHITECTURE_ID}" STREQUAL "MSP430") elseif("${CMAKE_ASM${ASM_DIALECT}_COMPILER_ARCHITECTURE_ID}" STREQUAL "V850") set(CMAKE_ASM_COMPILE_OBJECT "<CMAKE_ASM_COMPILER> -S <SOURCE> <DEFINES> <INCLUDES> <FLAGS> -o <OBJECT>") __compiler_iar_xlink(ASM) - set(CMAKE_ASM_SOURCE_FILE_EXTENSIONS r85;asm;msa) + set(CMAKE_ASM_SOURCE_FILE_EXTENSIONS s85;asm;msa) + +elseif("${CMAKE_ASM${ASM_DIALECT}_COMPILER_ARCHITECTURE_ID}" STREQUAL "8051") + set(CMAKE_ASM_COMPILE_OBJECT "<CMAKE_ASM_COMPILER> -S <SOURCE> <DEFINES> <INCLUDES> <FLAGS> -o <OBJECT>") + __compiler_iar_xlink(ASM) + set(CMAKE_ASM_SOURCE_FILE_EXTENSIONS s51;asm;msa) else() message(FATAL_ERROR "CMAKE_ASM${ASM_DIALECT}_COMPILER_ARCHITECTURE_ID not detected. This should be automatic.") diff --git a/Modules/Compiler/IAR-C.cmake b/Modules/Compiler/IAR-C.cmake index 9ad1ba0..e27fdfc 100644 --- a/Modules/Compiler/IAR-C.cmake +++ b/Modules/Compiler/IAR-C.cmake @@ -65,6 +65,11 @@ elseif("${CMAKE_C_COMPILER_ARCHITECTURE_ID}" STREQUAL "V850") __compiler_check_default_language_standard(C 1.10 90 4.10 99) set(CMAKE_C_OUTPUT_EXTENSION ".r85") +elseif("${CMAKE_C_COMPILER_ARCHITECTURE_ID}" STREQUAL "8051") + __compiler_iar_xlink(C) + __compiler_check_default_language_standard(C 6.10 90 8.10 99) + set(CMAKE_C_OUTPUT_EXTENSION ".r51") + else() message(FATAL_ERROR "CMAKE_C_COMPILER_ARCHITECTURE_ID not detected. This should be automatic.") endif() diff --git a/Modules/Compiler/IAR-CXX.cmake b/Modules/Compiler/IAR-CXX.cmake index 549d242..eca89c5 100644 --- a/Modules/Compiler/IAR-CXX.cmake +++ b/Modules/Compiler/IAR-CXX.cmake @@ -72,6 +72,12 @@ elseif("${CMAKE_CXX_COMPILER_ARCHITECTURE_ID}" STREQUAL "V850") __compiler_iar_xlink(CXX) __compiler_check_default_language_standard(CXX 1.10 98) set(CMAKE_C_OUTPUT_EXTENSION ".r85") + +elseif("${CMAKE_CXX_COMPILER_ARCHITECTURE_ID}" STREQUAL "8051") + __compiler_iar_xlink(CXX) + __compiler_check_default_language_standard(CXX 6.10 98) + set(CMAKE_C_OUTPUT_EXTENSION ".r51") + else() message(FATAL_ERROR "CMAKE_CXX_COMPILER_ARCHITECTURE_ID not detected. This should be automatic." ) endif() diff --git a/Modules/Compiler/IAR-DetermineCompiler.cmake b/Modules/Compiler/IAR-DetermineCompiler.cmake index 7e17778..0a026b2 100644 --- a/Modules/Compiler/IAR-DetermineCompiler.cmake +++ b/Modules/Compiler/IAR-DetermineCompiler.cmake @@ -31,7 +31,7 @@ set(_compiler_id_version_compute " # define @PREFIX@COMPILER_VERSION_MINOR @MACRO_DEC@(((__VER__) / 1000) % 1000) # define @PREFIX@COMPILER_VERSION_PATCH @MACRO_DEC@((__VER__) % 1000) # define @PREFIX@COMPILER_VERSION_INTERNAL @MACRO_DEC@(__IAR_SYSTEMS_ICC__) -# elif defined(__VER__) && (defined(__ICCAVR__) || defined(__ICCRX__) || defined(__ICCRH850__) || defined(__ICCRL78__) || defined(__ICC430__) || defined(__ICCRISCV__) || defined(__ICCV850__)) +# elif defined(__VER__) && (defined(__ICCAVR__) || defined(__ICCRX__) || defined(__ICCRH850__) || defined(__ICCRL78__) || defined(__ICC430__) || defined(__ICCRISCV__) || defined(__ICCV850__) || defined(__ICC8051__)) # define @PREFIX@COMPILER_VERSION_MAJOR @MACRO_DEC@((__VER__) / 100) # define @PREFIX@COMPILER_VERSION_MINOR @MACRO_DEC@((__VER__) - (((__VER__) / 100)*100)) # define @PREFIX@COMPILER_VERSION_PATCH @MACRO_DEC@(__SUBVERSION__) diff --git a/Modules/Compiler/IAR-FindBinUtils.cmake b/Modules/Compiler/IAR-FindBinUtils.cmake index 6258cf3..6ef3759 100644 --- a/Modules/Compiler/IAR-FindBinUtils.cmake +++ b/Modules/Compiler/IAR-FindBinUtils.cmake @@ -46,7 +46,8 @@ set(CMAKE_IAR_LINKER \"${CMAKE_IAR_LINKER}\") elseif("${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_ARCHITECTURE_ID}" STREQUAL "AVR" OR "${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_ARCHITECTURE_ID}" STREQUAL "MSP430" OR - "${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_ARCHITECTURE_ID}" STREQUAL "V850") + "${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_ARCHITECTURE_ID}" STREQUAL "V850" OR + "${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_ARCHITECTURE_ID}" STREQUAL "8051") # Find the "xlink" linker and "xar" archiver: find_program(CMAKE_IAR_LINKER xlink HINTS ${__iar_hints} diff --git a/Modules/CompilerId/VS-10.vcxproj.in b/Modules/CompilerId/VS-10.vcxproj.in index d742274..b48a332 100644 --- a/Modules/CompilerId/VS-10.vcxproj.in +++ b/Modules/CompilerId/VS-10.vcxproj.in @@ -15,6 +15,8 @@ @id_WindowsTargetPlatformVersion@ @id_WindowsSDKDesktopARMSupport@ @id_CudaToolkitCustomDir@ + @id_ToolsetVCTargetsDir@ + @id_CustomGlobals@ </PropertyGroup> @id_toolset_version_props@ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> diff --git a/Modules/ExternalProject.cmake b/Modules/ExternalProject.cmake index e55ed46..66061a1 100644 --- a/Modules/ExternalProject.cmake +++ b/Modules/ExternalProject.cmake @@ -49,7 +49,7 @@ External Project Definition ``STAMP_DIR <dir>`` Directory in which to store the timestamps of each step. Log files from - individual steps are also created in here unless overriden by LOG_DIR + individual steps are also created in here unless overridden by LOG_DIR (see *Logging Options* below). ``LOG_DIR <dir>`` @@ -425,7 +425,7 @@ External Project Definition build directory or re-uses previous build contents. If the CMake generator is the ``Green Hills MULTI`` and not overridden then - the orginal projects settings for the GHS toolset and target system + the original project's settings for the GHS toolset and target system customization cache variables are propagated into the external project. ``SOURCE_SUBDIR <dir>`` diff --git a/Modules/FindCURL.cmake b/Modules/FindCURL.cmake index aeebc84..919babc 100644 --- a/Modules/FindCURL.cmake +++ b/Modules/FindCURL.cmake @@ -37,8 +37,35 @@ This module defines the following variables: ``CURL_VERSION_STRING`` The version of ``curl`` found. + +CURL CMake +^^^^^^^^^^ + +If CURL was built using the CMake buildsystem then it provides its own +``CURLConfig.cmake`` file for use with the :command:`find_package` command's +config mode. This module looks for this file and, if found, +returns its results with no further action. + +Set ``CURL_NO_CURL_CMAKE`` to ``ON`` to disable this search. + #]=======================================================================] +include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake) + +if(NOT CURL_NO_CURL_CMAKE) + # do a find package call to specifically look for the CMake version + # of curl + find_package(CURL QUIET NO_MODULE) + mark_as_advanced(CURL_DIR) + + # if we found the CURL cmake package then we are done, and + # can print what we found and return. + if(CURL_FOUND) + find_package_handle_standard_args(CURL HANDLE_COMPONENTS CONFIG_MODE) + return() + endif() +endif() + find_package(PkgConfig QUIET) if(PKG_CONFIG_FOUND) pkg_check_modules(PC_CURL QUIET libcurl) @@ -139,7 +166,6 @@ if(CURL_FIND_COMPONENTS) endforeach() endif() -include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake) find_package_handle_standard_args(CURL REQUIRED_VARS CURL_LIBRARY CURL_INCLUDE_DIR VERSION_VAR CURL_VERSION_STRING diff --git a/Modules/FindCurses.cmake b/Modules/FindCurses.cmake index 5abc08a..ad40522 100644 --- a/Modules/FindCurses.cmake +++ b/Modules/FindCurses.cmake @@ -134,11 +134,13 @@ if(CURSES_USE_NCURSES) endif() if (CURSES_NEED_WIDE) + set(CURSES_TINFO_LIBRARY_NAME tinfow) find_path(CURSES_INCLUDE_PATH NAMES ncursesw/ncurses.h ncursesw/curses.h ncursesw.h cursesw.h HINTS "${_cursesParentDir}/include" ) else() + set(CURSES_TINFO_LIBRARY_NAME tinfo) find_path(CURSES_INCLUDE_PATH NAMES ncurses/ncurses.h ncurses/curses.h ncurses.h curses.h HINTS "${_cursesParentDir}/include" @@ -153,8 +155,8 @@ if(CURSES_USE_NCURSES) CHECK_LIBRARY_EXISTS("${CURSES_NCURSES_LIBRARY}" cbreak "" CURSES_NCURSES_HAS_CBREAK) if(NOT CURSES_NCURSES_HAS_CBREAK) - find_library(CURSES_EXTRA_LIBRARY tinfo HINTS "${_cursesLibDir}") - find_library(CURSES_EXTRA_LIBRARY tinfo ) + find_library(CURSES_EXTRA_LIBRARY "${CURSES_TINFO_LIBRARY_NAME}" HINTS "${_cursesLibDir}") + find_library(CURSES_EXTRA_LIBRARY "${CURSES_TINFO_LIBRARY_NAME}" ) endif() else() get_filename_component(_cursesLibDir "${CURSES_CURSES_LIBRARY}" PATH) diff --git a/Modules/FindHDF5.cmake b/Modules/FindHDF5.cmake index 08863c8..b488418 100644 --- a/Modules/FindHDF5.cmake +++ b/Modules/FindHDF5.cmake @@ -761,7 +761,7 @@ mark_as_advanced( HDF5_DIFF_EXECUTABLE ) if( NOT HDF5_FOUND ) # seed the initial lists of libraries to find with items we know we need set(HDF5_C_LIBRARY_NAMES hdf5) - set(HDF5_C_HL_LIBRARY_NAMES hdf5_hl) + set(HDF5_C_HL_LIBRARY_NAMES hdf5_hl ${HDF5_C_LIBRARY_NAMES} ) set(HDF5_CXX_LIBRARY_NAMES hdf5_cpp ${HDF5_C_LIBRARY_NAMES}) set(HDF5_CXX_HL_LIBRARY_NAMES hdf5_hl_cpp ${HDF5_C_HL_LIBRARY_NAMES} ${HDF5_CXX_LIBRARY_NAMES}) @@ -772,7 +772,7 @@ if( NOT HDF5_FOUND ) foreach(__lang IN LISTS HDF5_LANGUAGE_BINDINGS) # find the HDF5 include directories if("${__lang}" STREQUAL "Fortran") - set(HDF5_INCLUDE_FILENAME hdf5.mod) + set(HDF5_INCLUDE_FILENAME hdf5.mod HDF5.mod) elseif("${__lang}" STREQUAL "CXX") set(HDF5_INCLUDE_FILENAME H5Cpp.h) else() diff --git a/Modules/FindOpenMP.cmake b/Modules/FindOpenMP.cmake index def23bb..ab9d73a 100644 --- a/Modules/FindOpenMP.cmake +++ b/Modules/FindOpenMP.cmake @@ -128,6 +128,8 @@ int main(void) { #ifdef _OPENMP omp_get_max_threads(); return 0; +#elif defined(__HIP_DEVICE_COMPILE__) + return 0; #else breaks_on_purpose #endif diff --git a/Modules/FindPostgreSQL.cmake b/Modules/FindPostgreSQL.cmake index dfece22..cfa4ebc 100644 --- a/Modules/FindPostgreSQL.cmake +++ b/Modules/FindPostgreSQL.cmake @@ -87,7 +87,7 @@ set(PostgreSQL_ROOT_DIR_MESSAGE "Set the PostgreSQL_ROOT system variable to wher set(PostgreSQL_KNOWN_VERSIONS ${PostgreSQL_ADDITIONAL_VERSIONS} - "11" "10" "9.6" "9.5" "9.4" "9.3" "9.2" "9.1" "9.0" "8.4" "8.3" "8.2" "8.1" "8.0") + "12" "11" "10" "9.6" "9.5" "9.4" "9.3" "9.2" "9.1" "9.0" "8.4" "8.3" "8.2" "8.1" "8.0") # Define additional search paths for root directories. set( PostgreSQL_ROOT_DIRECTORIES @@ -107,8 +107,11 @@ foreach(suffix ${PostgreSQL_KNOWN_VERSIONS}) list(APPEND PostgreSQL_LIBRARY_ADDITIONAL_SEARCH_SUFFIXES "pgsql-${suffix}/lib") list(APPEND PostgreSQL_INCLUDE_ADDITIONAL_SEARCH_SUFFIXES + "postgresql${suffix}" + "postgresql/${suffix}" "pgsql-${suffix}/include") list(APPEND PostgreSQL_TYPE_ADDITIONAL_SEARCH_SUFFIXES + "postgresql${suffix}/server" "postgresql/${suffix}/server" "pgsql-${suffix}/include/server") endif() diff --git a/Modules/InstallRequiredSystemLibraries.cmake b/Modules/InstallRequiredSystemLibraries.cmake index e3eeea4..0e1429d 100644 --- a/Modules/InstallRequiredSystemLibraries.cmake +++ b/Modules/InstallRequiredSystemLibraries.cmake @@ -258,6 +258,7 @@ if(MSVC) cmake_host_system_information(RESULT _vs_dir QUERY VS_${_vs_ver}_DIR) # undocumented query if(IS_DIRECTORY "${_vs_dir}") file(GLOB _vs_glob_redist_paths "${_vs_dir}/VC/Redist/MSVC/*") + list(REVERSE _vs_glob_redist_paths) list(APPEND _vs_redist_paths ${_vs_glob_redist_paths}) endif() unset(_vs_glob_redist_paths) @@ -287,6 +288,9 @@ if(MSVC) "${MSVC_CRT_DIR}/msvcp${v}.dll" ) if(NOT vs VERSION_LESS 14) + if(EXISTS "${MSVC_CRT_DIR}/vcruntime${v}_1.dll") + list(APPEND __install__libs "${MSVC_CRT_DIR}/vcruntime${v}_1.dll") + endif() list(APPEND __install__libs "${MSVC_CRT_DIR}/vcruntime${v}.dll" "${MSVC_CRT_DIR}/concrt${v}.dll" @@ -305,6 +309,9 @@ if(MSVC) "${MSVC_CRT_DIR}/msvcp${v}d.dll" ) if(NOT vs VERSION_LESS 14) + if(EXISTS "${MSVC_CRT_DIR}/vcruntime${v}_1d.dll") + list(APPEND __install__libs "${MSVC_CRT_DIR}/vcruntime${v}_1d.dll") + endif() list(APPEND __install__libs "${MSVC_CRT_DIR}/vcruntime${v}d.dll" "${MSVC_CRT_DIR}/concrt${v}d.dll" diff --git a/Modules/Platform/Apple-Clang-ASM.cmake b/Modules/Platform/Apple-Clang-ASM.cmake new file mode 100644 index 0000000..935cce9 --- /dev/null +++ b/Modules/Platform/Apple-Clang-ASM.cmake @@ -0,0 +1,2 @@ +include(Platform/Apple-Clang) +__apple_compiler_clang(ASM) diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index 63e08de..26d2156 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -289,6 +289,8 @@ set(SRCS cmGeneratorExpression.h cmGeneratorTarget.cxx cmGeneratorTarget.h + cmLinkItemGraphVisitor.cxx + cmLinkItemGraphVisitor.h cmGetPipes.cxx cmGetPipes.h cmGlobalCommonGenerator.cxx @@ -1193,6 +1195,11 @@ if(WIN32) endforeach() endif() +if(CMake_JOB_POOL_LINK_BIN) + set_property(TARGET ${_tools} PROPERTY JOB_POOL_LINK "link-bin") + set_property(GLOBAL APPEND PROPERTY JOB_POOLS "link-bin=${CMake_JOB_POOL_LINK_BIN}") +endif() + # Install tools foreach(_tool ${_tools}) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index c068594..beeb0a6 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 20191007) +set(CMake_VERSION_PATCH 20191018) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) @@ -19,55 +19,57 @@ else() set(CMake_VERSION_IS_RELEASE 0) endif() -if(EXISTS ${CMake_SOURCE_DIR}/.git) - find_package(Git QUIET) - if(GIT_FOUND) - macro(_git) - execute_process( - COMMAND ${GIT_EXECUTABLE} ${ARGN} - WORKING_DIRECTORY ${CMake_SOURCE_DIR} - RESULT_VARIABLE _git_res - OUTPUT_VARIABLE _git_out OUTPUT_STRIP_TRAILING_WHITESPACE - ERROR_VARIABLE _git_err ERROR_STRIP_TRAILING_WHITESPACE - ) - endmacro() - endif() -endif() - -# Try to identify the current development source version. -if(COMMAND _git) - # Get the commit checked out in this work tree. - _git(log -n 1 HEAD "--pretty=format:%h %s" --) - set(git_info "${_git_out}") -else() - # Get the commit exported by 'git archive'. +if(NOT CMake_VERSION_NO_GIT) + # If this source was exported by 'git archive', use its commit info. set(git_info [==[$Format:%h %s$]==]) -endif() - -# Extract commit information if available. -if(git_info MATCHES "^([0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]?[0-9a-f]?)[0-9a-f]* (.*)$") - # Have commit information. - set(git_hash "${CMAKE_MATCH_1}") - set(git_subject "${CMAKE_MATCH_2}") - # If this is not the exact commit of a release, add dev info. - if(NOT "${git_subject}" MATCHES "^[Cc][Mm]ake ${CMake_VERSION}$") - set(CMake_VERSION "${CMake_VERSION}-g${git_hash}") + # Otherwise, try to identify the current development source version. + if(NOT git_info MATCHES "^([0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]?[0-9a-f]?)[0-9a-f]* " + AND EXISTS ${CMake_SOURCE_DIR}/.git) + find_package(Git QUIET) + if(GIT_FOUND) + macro(_git) + execute_process( + COMMAND ${GIT_EXECUTABLE} ${ARGN} + WORKING_DIRECTORY ${CMake_SOURCE_DIR} + RESULT_VARIABLE _git_res + OUTPUT_VARIABLE _git_out OUTPUT_STRIP_TRAILING_WHITESPACE + ERROR_VARIABLE _git_err ERROR_STRIP_TRAILING_WHITESPACE + ) + endmacro() + endif() + if(COMMAND _git) + # Get the commit checked out in this work tree. + _git(log -n 1 HEAD "--pretty=format:%h %s" --) + set(git_info "${_git_out}") + endif() endif() - # If this is a work tree, check whether it is dirty. - if(COMMAND _git) - _git(update-index -q --refresh) - _git(diff-index --name-only HEAD --) - if(_git_out) - set(CMake_VERSION_IS_DIRTY 1) + # Extract commit information if available. + if(git_info MATCHES "^([0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]?[0-9a-f]?)[0-9a-f]* (.*)$") + # Have commit information. + set(git_hash "${CMAKE_MATCH_1}") + set(git_subject "${CMAKE_MATCH_2}") + + # If this is not the exact commit of a release, add dev info. + if(NOT "${git_subject}" MATCHES "^[Cc][Mm]ake ${CMake_VERSION}$") + set(CMake_VERSION "${CMake_VERSION}-g${git_hash}") + endif() + + # If this is a work tree, check whether it is dirty. + if(COMMAND _git) + _git(update-index -q --refresh) + _git(diff-index --name-only HEAD --) + if(_git_out) + set(CMake_VERSION_IS_DIRTY 1) + endif() + endif() + else() + # No commit information. + if(NOT CMake_VERSION_IS_RELEASE) + # Generic development version. + set(CMake_VERSION "${CMake_VERSION}-git") endif() - endif() -else() - # No commit information. - if(NOT CMake_VERSION_IS_RELEASE) - # Generic development version. - set(CMake_VERSION "${CMake_VERSION}-git") endif() endif() diff --git a/Source/CursesDialog/CMakeLists.txt b/Source/CursesDialog/CMakeLists.txt index 7009717..a9e46fd5 100644 --- a/Source/CursesDialog/CMakeLists.txt +++ b/Source/CursesDialog/CMakeLists.txt @@ -34,5 +34,9 @@ else() target_link_libraries(ccmake cmForm) endif() +if(CMake_JOB_POOL_LINK_BIN) + set_property(TARGET ccmake PROPERTY JOB_POOL_LINK "link-bin") +endif() + CMake_OPTIONAL_COMPONENT(ccmake) install(TARGETS ccmake DESTINATION ${CMAKE_BIN_DIR} ${COMPONENT}) diff --git a/Source/QtDialog/CMakeLists.txt b/Source/QtDialog/CMakeLists.txt index cb89d19..98dd0e2 100644 --- a/Source/QtDialog/CMakeLists.txt +++ b/Source/QtDialog/CMakeLists.txt @@ -178,6 +178,10 @@ if(WIN32) target_sources(cmake-gui PRIVATE $<TARGET_OBJECTS:CMakeVersion>) endif() +if(CMake_JOB_POOL_LINK_BIN) + set_property(TARGET cmake-gui PROPERTY JOB_POOL_LINK "link-bin") +endif() + # cmake-gui has not been updated for `include-what-you-use`. # Block the tool until this is done. set_target_properties(cmake-gui PROPERTIES diff --git a/Source/cmCoreTryCompile.cxx b/Source/cmCoreTryCompile.cxx index 515f446..910cc9d 100644 --- a/Source/cmCoreTryCompile.cxx +++ b/Source/cmCoreTryCompile.cxx @@ -56,6 +56,8 @@ static std::string const kCMAKE_POSITION_INDEPENDENT_CODE = static std::string const kCMAKE_SYSROOT = "CMAKE_SYSROOT"; static std::string const kCMAKE_SYSROOT_COMPILE = "CMAKE_SYSROOT_COMPILE"; static std::string const kCMAKE_SYSROOT_LINK = "CMAKE_SYSROOT_LINK"; +static std::string const kCMAKE_Swift_COMPILER_TARGET = + "CMAKE_Swift_COMPILER_TARGET"; static std::string const kCMAKE_TRY_COMPILE_OSX_ARCHITECTURES = "CMAKE_TRY_COMPILE_OSX_ARCHITECTURES"; static std::string const kCMAKE_TRY_COMPILE_PLATFORM_VARIABLES = @@ -671,6 +673,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, vars.insert(kCMAKE_SYSROOT); vars.insert(kCMAKE_SYSROOT_COMPILE); vars.insert(kCMAKE_SYSROOT_LINK); + vars.insert(kCMAKE_Swift_COMPILER_TARGET); vars.insert(kCMAKE_WARN_DEPRECATED); vars.emplace("CMAKE_MSVC_RUNTIME_LIBRARY"_s); diff --git a/Source/cmExportFileGenerator.cxx b/Source/cmExportFileGenerator.cxx index 3d7eccc..aeef602 100644 --- a/Source/cmExportFileGenerator.cxx +++ b/Source/cmExportFileGenerator.cxx @@ -752,9 +752,9 @@ void cmExportFileGenerator::SetImportLinkInterface( if (iface->ImplementationIsInterface) { // Policy CMP0022 must not be NEW. - this->SetImportLinkProperty(suffix, target, - "IMPORTED_LINK_INTERFACE_LIBRARIES", - iface->Libraries, properties, missingTargets); + this->SetImportLinkProperty( + suffix, target, "IMPORTED_LINK_INTERFACE_LIBRARIES", iface->Libraries, + properties, missingTargets, ImportLinkPropertyTargetNames::Yes); return; } @@ -832,14 +832,14 @@ void cmExportFileGenerator::SetImportDetailProperties( // Add the transitive link dependencies for this configuration. if (cmLinkInterface const* iface = target->GetLinkInterface(config, target)) { - this->SetImportLinkProperty(suffix, target, - "IMPORTED_LINK_INTERFACE_LANGUAGES", - iface->Languages, properties, missingTargets); + this->SetImportLinkProperty( + suffix, target, "IMPORTED_LINK_INTERFACE_LANGUAGES", iface->Languages, + properties, missingTargets, ImportLinkPropertyTargetNames::No); std::vector<std::string> dummy; - this->SetImportLinkProperty(suffix, target, - "IMPORTED_LINK_DEPENDENT_LIBRARIES", - iface->SharedDeps, properties, dummy); + this->SetImportLinkProperty( + suffix, target, "IMPORTED_LINK_DEPENDENT_LIBRARIES", iface->SharedDeps, + properties, dummy, ImportLinkPropertyTargetNames::Yes); if (iface->Multiplicity > 0) { std::string prop = cmStrCat("IMPORTED_LINK_INTERFACE_MULTIPLICITY", suffix); @@ -880,7 +880,8 @@ template <typename T> void cmExportFileGenerator::SetImportLinkProperty( std::string const& suffix, cmGeneratorTarget* target, const std::string& propName, std::vector<T> const& entries, - ImportPropertyMap& properties, std::vector<std::string>& missingTargets) + ImportPropertyMap& properties, std::vector<std::string>& missingTargets, + ImportLinkPropertyTargetNames targetNames) { // Skip the property if there are no entries. if (entries.empty()) { @@ -895,9 +896,13 @@ void cmExportFileGenerator::SetImportLinkProperty( link_entries += sep; sep = ";"; - std::string temp = asString(l); - this->AddTargetNamespace(temp, target, missingTargets); - link_entries += temp; + if (targetNames == ImportLinkPropertyTargetNames::Yes) { + std::string temp = asString(l); + this->AddTargetNamespace(temp, target, missingTargets); + link_entries += temp; + } else { + link_entries += asString(l); + } } // Store the property. diff --git a/Source/cmExportFileGenerator.h b/Source/cmExportFileGenerator.h index b04a31e..0d69779 100644 --- a/Source/cmExportFileGenerator.h +++ b/Source/cmExportFileGenerator.h @@ -102,13 +102,19 @@ protected: ImportPropertyMap& properties, std::vector<std::string>& missingTargets); + enum class ImportLinkPropertyTargetNames + { + Yes, + No, + }; template <typename T> void SetImportLinkProperty(std::string const& suffix, cmGeneratorTarget* target, const std::string& propName, std::vector<T> const& entries, ImportPropertyMap& properties, - std::vector<std::string>& missingTargets); + std::vector<std::string>& missingTargets, + ImportLinkPropertyTargetNames targetNames); /** Each subclass knows how to generate its kind of export file. */ virtual bool GenerateMainFile(std::ostream& os) = 0; diff --git a/Source/cmFileAPICodemodel.cxx b/Source/cmFileAPICodemodel.cxx index eb50813..48561de 100644 --- a/Source/cmFileAPICodemodel.cxx +++ b/Source/cmFileAPICodemodel.cxx @@ -869,6 +869,32 @@ CompileData Target::BuildCompileData(cmSourceFile* sf) fd.Flags.emplace_back(this->ToJBT(opt)); } + // Add precompile headers compile options. + const std::string pchSource = + this->GT->GetPchSource(this->Config, fd.Language); + + if (!pchSource.empty() && !sf->GetProperty("SKIP_PRECOMPILE_HEADERS")) { + std::string pchOptions; + if (sf->GetFullPath() == pchSource) { + pchOptions = + this->GT->GetPchCreateCompileOptions(this->Config, fd.Language); + } else { + pchOptions = + this->GT->GetPchUseCompileOptions(this->Config, fd.Language); + } + + BT<std::string> tmpOpt(pchOptions); + tmpOpt.Value = genexInterpreter.Evaluate(tmpOpt.Value, COMPILE_OPTIONS); + + // After generator evaluation we need to use the AppendCompileOptions + // method so we handle situations where backtrace entries have lists + // and properly escape flags. + std::string tmp; + lg->AppendCompileOptions(tmp, tmpOpt.Value); + BT<std::string> opt(tmp, tmpOpt.Backtrace); + fd.Flags.emplace_back(this->ToJBT(opt)); + } + // Add include directories from source file properties. { const std::string INCLUDE_DIRECTORIES("INCLUDE_DIRECTORIES"); diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index 3a48ff6..949d9d9 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -3486,6 +3486,92 @@ std::string cmGeneratorTarget::GetPchFileObject(const std::string& config, return inserted.first->second; } +std::string cmGeneratorTarget::GetPchFile(const std::string& config, + const std::string& language) +{ + const auto inserted = + this->PchFiles.insert(std::make_pair(language + config, "")); + if (inserted.second) { + std::string& pchFile = inserted.first->second; + + const std::string pchExtension = + this->Makefile->GetSafeDefinition("CMAKE_PCH_EXTENSION"); + + if (this->Makefile->IsOn("CMAKE_LINK_PCH")) { + auto replaceExtension = [](const std::string& str, + const std::string& ext) -> std::string { + auto dot_pos = str.rfind('.'); + std::string result; + if (dot_pos != std::string::npos) { + result = str.substr(0, dot_pos); + } + result += ext; + return result; + }; + + cmGeneratorTarget* generatorTarget = this; + const char* pchReuseFrom = + generatorTarget->GetProperty("PRECOMPILE_HEADERS_REUSE_FROM"); + if (pchReuseFrom) { + generatorTarget = + this->GetGlobalGenerator()->FindGeneratorTarget(pchReuseFrom); + } + + const std::string pchFileObject = + generatorTarget->GetPchFileObject(config, language); + if (!pchExtension.empty()) { + pchFile = replaceExtension(pchFileObject, pchExtension); + } + } else { + pchFile = this->GetPchHeader(config, language); + pchFile += pchExtension; + } + } + return inserted.first->second; +} + +std::string cmGeneratorTarget::GetPchCreateCompileOptions( + const std::string& config, const std::string& language) +{ + const auto inserted = this->PchCreateCompileOptions.insert( + std::make_pair(language + config, "")); + if (inserted.second) { + std::string& createOptionList = inserted.first->second; + + const std::string createOptVar = + cmStrCat("CMAKE_", language, "_COMPILE_OPTIONS_CREATE_PCH"); + createOptionList = this->Makefile->GetSafeDefinition(createOptVar); + + const std::string pchHeader = this->GetPchHeader(config, language); + const std::string pchFile = this->GetPchFile(config, language); + + cmSystemTools::ReplaceString(createOptionList, "<PCH_HEADER>", pchHeader); + cmSystemTools::ReplaceString(createOptionList, "<PCH_FILE>", pchFile); + } + return inserted.first->second; +} + +std::string cmGeneratorTarget::GetPchUseCompileOptions( + const std::string& config, const std::string& language) +{ + const auto inserted = + this->PchUseCompileOptions.insert(std::make_pair(language + config, "")); + if (inserted.second) { + std::string& useOptionList = inserted.first->second; + + const std::string useOptVar = + cmStrCat("CMAKE_", language, "_COMPILE_OPTIONS_USE_PCH"); + useOptionList = this->Makefile->GetSafeDefinition(useOptVar); + + const std::string pchHeader = this->GetPchHeader(config, language); + const std::string pchFile = this->GetPchFile(config, language); + + cmSystemTools::ReplaceString(useOptionList, "<PCH_HEADER>", pchHeader); + cmSystemTools::ReplaceString(useOptionList, "<PCH_FILE>", pchFile); + } + return inserted.first->second; +} + void cmGeneratorTarget::GetLinkOptions(std::vector<std::string>& result, const std::string& config, const std::string& language) const diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h index 27ad6eb..1f824b1 100644 --- a/Source/cmGeneratorTarget.h +++ b/Source/cmGeneratorTarget.h @@ -464,6 +464,12 @@ public: const std::string& language) const; std::string GetPchFileObject(const std::string& config, const std::string& language); + std::string GetPchFile(const std::string& config, + const std::string& language); + std::string GetPchCreateCompileOptions(const std::string& config, + const std::string& language); + std::string GetPchUseCompileOptions(const std::string& config, + const std::string& language); bool IsSystemIncludeDirectory(const std::string& dir, const std::string& config, @@ -883,6 +889,9 @@ private: mutable std::map<std::string, std::string> PchHeaders; mutable std::map<std::string, std::string> PchSources; mutable std::map<std::string, std::string> PchObjectFiles; + mutable std::map<std::string, std::string> PchFiles; + mutable std::map<std::string, std::string> PchCreateCompileOptions; + mutable std::map<std::string, std::string> PchUseCompileOptions; void ExpandLinkItems(std::string const& prop, std::string const& value, std::string const& config, diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx index ee9ea3c..2efafc6 100644 --- a/Source/cmGlobalGenerator.cxx +++ b/Source/cmGlobalGenerator.cxx @@ -165,7 +165,7 @@ bool cmGlobalGenerator::SetGeneratorPlatform(std::string const& p, return false; } -bool cmGlobalGenerator::SetGeneratorToolset(std::string const& ts, +bool cmGlobalGenerator::SetGeneratorToolset(std::string const& ts, bool, cmMakefile* mf) { if (ts.empty()) { @@ -650,7 +650,7 @@ void cmGlobalGenerator::EnableLanguage( // Tell the generator about the toolset, if any. std::string toolset = mf->GetSafeDefinition("CMAKE_GENERATOR_TOOLSET"); - if (!this->SetGeneratorToolset(toolset, mf)) { + if (!this->SetGeneratorToolset(toolset, false, mf)) { cmSystemTools::SetFatalErrorOccured(); return; } @@ -1556,11 +1556,13 @@ bool cmGlobalGenerator::QtAutoGen() bool cmGlobalGenerator::AddAutomaticSources() { for (cmLocalGenerator* lg : this->LocalGenerators) { + lg->CreateEvaluationFileOutputs(); for (cmGeneratorTarget* gt : lg->GetGeneratorTargets()) { if (gt->GetType() == cmStateEnums::INTERFACE_LIBRARY) { continue; } lg->AddUnityBuild(gt); + lg->AddPchDependencies(gt); } } return true; @@ -3095,14 +3097,6 @@ cmGlobalGenerator::GetFilenameTargetDepends(cmSourceFile* sf) const return this->FilenameTargetDepends[sf]; } -void cmGlobalGenerator::CreateEvaluationSourceFiles( - std::string const& config) const -{ - for (cmLocalGenerator* localGen : this->LocalGenerators) { - localGen->CreateEvaluationFileOutputs(config); - } -} - void cmGlobalGenerator::ProcessEvaluationFiles() { std::vector<std::string> generatedFiles; diff --git a/Source/cmGlobalGenerator.h b/Source/cmGlobalGenerator.h index 9e30b8f..0e87357 100644 --- a/Source/cmGlobalGenerator.h +++ b/Source/cmGlobalGenerator.h @@ -128,7 +128,8 @@ public: /** Set the generator-specific toolset name. Returns true if toolset is supported and false otherwise. */ - virtual bool SetGeneratorToolset(std::string const& ts, cmMakefile* mf); + virtual bool SetGeneratorToolset(std::string const& ts, bool build, + cmMakefile* mf); /** * Create LocalGenerators and process the CMakeLists files. This does not @@ -457,8 +458,6 @@ public: bool GenerateCPackPropertiesFile(); - void CreateEvaluationSourceFiles(std::string const& config) const; - void SetFilenameTargetDepends( cmSourceFile* sf, std::set<cmGeneratorTarget const*> const& tgts); const std::set<const cmGeneratorTarget*>& GetFilenameTargetDepends( diff --git a/Source/cmGlobalGhsMultiGenerator.cxx b/Source/cmGlobalGhsMultiGenerator.cxx index 5a708ab..7afcd49 100644 --- a/Source/cmGlobalGhsMultiGenerator.cxx +++ b/Source/cmGlobalGhsMultiGenerator.cxx @@ -64,8 +64,11 @@ void cmGlobalGhsMultiGenerator::ComputeTargetObjectDirectory( } bool cmGlobalGhsMultiGenerator::SetGeneratorToolset(std::string const& ts, - cmMakefile* mf) + bool build, cmMakefile* mf) { + if (build) { + return true; + } std::string tsp; /* toolset path */ this->GetToolset(mf, tsp, ts); diff --git a/Source/cmGlobalGhsMultiGenerator.h b/Source/cmGlobalGhsMultiGenerator.h index ccfe073..7cd8c79 100644 --- a/Source/cmGlobalGhsMultiGenerator.h +++ b/Source/cmGlobalGhsMultiGenerator.h @@ -58,7 +58,8 @@ public: static bool SupportsPlatform() { return true; } // Toolset / Platform Support - bool SetGeneratorToolset(std::string const& ts, cmMakefile* mf) override; + bool SetGeneratorToolset(std::string const& ts, bool build, + cmMakefile* mf) override; bool SetGeneratorPlatform(std::string const& p, cmMakefile* mf) override; /** diff --git a/Source/cmGlobalVisualStudio10Generator.cxx b/Source/cmGlobalVisualStudio10Generator.cxx index 09a49e1..5b83e2f 100644 --- a/Source/cmGlobalVisualStudio10Generator.cxx +++ b/Source/cmGlobalVisualStudio10Generator.cxx @@ -26,6 +26,16 @@ static const char vs10generatorName[] = "Visual Studio 10 2010"; static std::map<std::string, std::vector<cmIDEFlagTable>> loadedFlagJsonFiles; +static void ConvertToWindowsSlashes(std::string& s) +{ + // first convert all of the slashes + for (auto& ch : s) { + if (ch == '/') { + ch = '\\'; + } + } +} + // Map generator name without year to name with year. static const char* cmVS10GenName(const std::string& name, std::string& genName) { @@ -193,7 +203,7 @@ static void cmCudaToolVersion(std::string& s) } bool cmGlobalVisualStudio10Generator::SetGeneratorToolset( - std::string const& ts, cmMakefile* mf) + std::string const& ts, bool build, cmMakefile* mf) { if (this->SystemIsWindowsCE && ts.empty() && this->DefaultPlatformToolset.empty()) { @@ -208,7 +218,11 @@ bool cmGlobalVisualStudio10Generator::SetGeneratorToolset( return false; } - if (!this->FindVCTargetsPath(mf)) { + if (build) { + return true; + } + + if (this->CustomVCTargetsPath.empty() && !this->FindVCTargetsPath(mf)) { return false; } @@ -349,6 +363,11 @@ bool cmGlobalVisualStudio10Generator::SetGeneratorToolset( if (const char* cudaDir = this->GetPlatformToolsetCudaCustomDir()) { mf->AddDefinition("CMAKE_VS_PLATFORM_TOOLSET_CUDA_CUSTOM_DIR", cudaDir); } + if (const char* vcTargetsDir = this->GetCustomVCTargetsPath()) { + mf->AddDefinition("CMAKE_VS_PLATFORM_TOOLSET_VCTARGETS_CUSTOM_DIR", + vcTargetsDir); + } + return true; } @@ -442,6 +461,11 @@ bool cmGlobalVisualStudio10Generator::ProcessGeneratorToolsetField( this->GeneratorToolsetVersion = value; return true; } + if (key == "VCTargetsPath") { + this->CustomVCTargetsPath = value; + ConvertToWindowsSlashes(this->CustomVCTargetsPath); + return true; + } return false; } @@ -603,6 +627,14 @@ void cmGlobalVisualStudio10Generator::EnableLanguage( cmGlobalVisualStudio8Generator::EnableLanguage(lang, mf, optional); } +const char* cmGlobalVisualStudio10Generator::GetCustomVCTargetsPath() const +{ + if (this->CustomVCTargetsPath.empty()) { + return nullptr; + } + return this->CustomVCTargetsPath.c_str(); +} + const char* cmGlobalVisualStudio10Generator::GetPlatformToolset() const { std::string const& toolset = this->GetPlatformToolsetString(); diff --git a/Source/cmGlobalVisualStudio10Generator.h b/Source/cmGlobalVisualStudio10Generator.h index 9adcf08..8a76047 100644 --- a/Source/cmGlobalVisualStudio10Generator.h +++ b/Source/cmGlobalVisualStudio10Generator.h @@ -20,7 +20,8 @@ public: bool SetSystemName(std::string const& s, cmMakefile* mf) override; bool SetGeneratorPlatform(std::string const& p, cmMakefile* mf) override; - bool SetGeneratorToolset(std::string const& ts, cmMakefile* mf) override; + bool SetGeneratorToolset(std::string const& ts, bool build, + cmMakefile* mf) override; std::vector<GeneratedMakeCommand> GenerateBuildCommand( const std::string& makeProgram, const std::string& projectName, @@ -45,6 +46,9 @@ public: bool IsNsightTegra() const; std::string GetNsightTegraVersion() const; + /** The vctargets path for the target platform. */ + const char* GetCustomVCTargetsPath() const; + /** The toolset name for the target platform. */ const char* GetPlatformToolset() const; std::string const& GetPlatformToolsetString() const; @@ -155,6 +159,7 @@ protected: std::string GeneratorToolset; std::string GeneratorToolsetVersion; std::string GeneratorToolsetHostArchitecture; + std::string GeneratorToolsetCustomVCTargetsDir; std::string GeneratorToolsetCuda; std::string GeneratorToolsetCudaCustomDir; std::string DefaultPlatformToolset; @@ -206,6 +211,7 @@ private: bool ParseGeneratorToolset(std::string const& ts, cmMakefile* mf); + std::string CustomVCTargetsPath; std::string VCTargetsPath; bool FindVCTargetsPath(cmMakefile* mf); diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index 8ae1e12..8a731cf 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -267,7 +267,7 @@ std::string cmGlobalXCodeGenerator::FindXcodeBuildCommand() } bool cmGlobalXCodeGenerator::SetGeneratorToolset(std::string const& ts, - cmMakefile* mf) + bool build, cmMakefile* mf) { if (ts.find_first_of(",=") != std::string::npos) { std::ostringstream e; @@ -283,6 +283,9 @@ bool cmGlobalXCodeGenerator::SetGeneratorToolset(std::string const& ts, return false; } this->GeneratorToolset = ts; + if (build) { + return true; + } if (!this->GeneratorToolset.empty()) { mf->AddDefinition("CMAKE_XCODE_PLATFORM_TOOLSET", this->GeneratorToolset); } @@ -827,6 +830,11 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateXCodeSourceFile( genexInterpreter.Evaluate(compile_defs, COMPILE_DEFINITIONS).c_str(), true); } + + if (sf->GetPropertyAsBool("SKIP_PRECOMPILE_HEADERS")) { + this->AppendDefines(flagsBuild, "CMAKE_SKIP_PRECOMPILE_HEADERS", true); + } + if (!flagsBuild.IsEmpty()) { if (!flags.empty()) { flags += ' '; @@ -2827,8 +2835,6 @@ bool cmGlobalXCodeGenerator::CreateGroups( continue; } - generator->AddPchDependencies(gtgt, ""); - auto addSourceToGroup = [this, mf, gtgt, &sourceGroups](std::string const& source) { cmSourceGroup* sourceGroup = mf->FindSourceGroup(source, sourceGroups); diff --git a/Source/cmGlobalXCodeGenerator.h b/Source/cmGlobalXCodeGenerator.h index af905d0..f60ea72 100644 --- a/Source/cmGlobalXCodeGenerator.h +++ b/Source/cmGlobalXCodeGenerator.h @@ -103,7 +103,8 @@ public: bool ShouldStripResourcePath(cmMakefile*) const override; - bool SetGeneratorToolset(std::string const& ts, cmMakefile* mf) override; + bool SetGeneratorToolset(std::string const& ts, bool build, + cmMakefile* mf) override; void AppendFlag(std::string& flags, std::string const& flag) const; protected: diff --git a/Source/cmGraphVizWriter.cxx b/Source/cmGraphVizWriter.cxx index e0d545d..7759c5f 100644 --- a/Source/cmGraphVizWriter.cxx +++ b/Source/cmGraphVizWriter.cxx @@ -2,174 +2,190 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmGraphVizWriter.h" -#include <cstddef> +#include <cctype> #include <iostream> #include <memory> -#include <sstream> +#include <set> #include <utility> +#include <cm/memory> + #include "cmGeneratedFileStream.h" #include "cmGeneratorTarget.h" #include "cmGlobalGenerator.h" +#include "cmLinkItem.h" #include "cmLocalGenerator.h" #include "cmMakefile.h" #include "cmState.h" #include "cmStateSnapshot.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" -#include "cmTarget.h" #include "cmake.h" namespace { -enum LinkLibraryScopeType -{ - LLT_SCOPE_PUBLIC, - LLT_SCOPE_PRIVATE, - LLT_SCOPE_INTERFACE -}; -const char* const GRAPHVIZ_PRIVATE_EDEGE_STYLE = "dashed"; -const char* const GRAPHVIZ_INTERFACE_EDEGE_STYLE = "dotted"; +char const* const GRAPHVIZ_EDGE_STYLE_PUBLIC = "solid"; +char const* const GRAPHVIZ_EDGE_STYLE_INTERFACE = "dashed"; +char const* const GRAPHVIZ_EDGE_STYLE_PRIVATE = "dotted"; -std::string getLinkLibraryStyle(const LinkLibraryScopeType& type) -{ - std::string style; - switch (type) { - case LLT_SCOPE_PRIVATE: - style = "[style = " + std::string(GRAPHVIZ_PRIVATE_EDEGE_STYLE) + "]"; - break; - case LLT_SCOPE_INTERFACE: - style = "[style = " + std::string(GRAPHVIZ_INTERFACE_EDEGE_STYLE) + "]"; - break; - default: - break; - } - return style; -} +char const* const GRAPHVIZ_NODE_SHAPE_EXECUTABLE = "egg"; // egg-xecutable + +// Normal libraries. +char const* const GRAPHVIZ_NODE_SHAPE_LIBRARY_STATIC = "octagon"; +char const* const GRAPHVIZ_NODE_SHAPE_LIBRARY_SHARED = "doubleoctagon"; +char const* const GRAPHVIZ_NODE_SHAPE_LIBRARY_MODULE = "tripleoctagon"; -const char* getShapeForTarget(const cmGeneratorTarget* target) +char const* const GRAPHVIZ_NODE_SHAPE_LIBRARY_INTERFACE = "pentagon"; +char const* const GRAPHVIZ_NODE_SHAPE_LIBRARY_OBJECT = "hexagon"; +char const* const GRAPHVIZ_NODE_SHAPE_LIBRARY_UNKNOWN = "septagon"; + +char const* const GRAPHVIZ_NODE_SHAPE_UTILITY = "box"; + +const char* getShapeForTarget(const cmLinkItem& item) { - if (!target) { - return "ellipse"; + if (item.Target == nullptr) { + return GRAPHVIZ_NODE_SHAPE_LIBRARY_UNKNOWN; } - switch (target->GetType()) { + switch (item.Target->GetType()) { case cmStateEnums::EXECUTABLE: - return "house"; + return GRAPHVIZ_NODE_SHAPE_EXECUTABLE; case cmStateEnums::STATIC_LIBRARY: - return "diamond"; + return GRAPHVIZ_NODE_SHAPE_LIBRARY_STATIC; case cmStateEnums::SHARED_LIBRARY: - return "polygon"; + return GRAPHVIZ_NODE_SHAPE_LIBRARY_SHARED; case cmStateEnums::MODULE_LIBRARY: - return "octagon"; + return GRAPHVIZ_NODE_SHAPE_LIBRARY_MODULE; + case cmStateEnums::OBJECT_LIBRARY: + return GRAPHVIZ_NODE_SHAPE_LIBRARY_OBJECT; + case cmStateEnums::UTILITY: + return GRAPHVIZ_NODE_SHAPE_UTILITY; + case cmStateEnums::INTERFACE_LIBRARY: + return GRAPHVIZ_NODE_SHAPE_LIBRARY_INTERFACE; + case cmStateEnums::UNKNOWN_LIBRARY: default: - break; + return GRAPHVIZ_NODE_SHAPE_LIBRARY_UNKNOWN; } +} +} - return "box"; +cmGraphVizWriter::cmGraphVizWriter(std::string const& fileName, + const cmGlobalGenerator* globalGenerator) + : FileName(fileName) + , GlobalFileStream(fileName) + , GraphName(globalGenerator->GetSafeGlobalSetting("CMAKE_PROJECT_NAME")) + , GraphHeader("node [\n fontsize = \"12\"\n];") + , GraphNodePrefix("node") + , GlobalGenerator(globalGenerator) + , NextNodeId(0) + , GenerateForExecutables(true) + , GenerateForStaticLibs(true) + , GenerateForSharedLibs(true) + , GenerateForModuleLibs(true) + , GenerateForInterfaceLibs(true) + , GenerateForObjectLibs(true) + , GenerateForUnknownLibs(true) + , GenerateForCustomTargets(false) + , GenerateForExternals(true) + , GeneratePerTarget(true) + , GenerateDependers(true) +{ } -std::map<std::string, LinkLibraryScopeType> getScopedLinkLibrariesFromTarget( - cmTarget* Target, const cmGlobalGenerator* globalGenerator) +cmGraphVizWriter::~cmGraphVizWriter() { - char sep = ';'; - std::map<std::string, LinkLibraryScopeType> tokens; - size_t start = 0; - size_t end = 0; + this->WriteFooter(this->GlobalFileStream); - const char* pInterfaceLinkLibraries = - Target->GetProperty("INTERFACE_LINK_LIBRARIES"); - const char* pLinkLibraries = Target->GetProperty("LINK_LIBRARIES"); + for (auto& fileStream : this->PerTargetFileStreams) { + this->WriteFooter(*fileStream.second); + } - if (!pInterfaceLinkLibraries && !pLinkLibraries) { - return tokens; // target is not linked against any other libraries + for (auto& fileStream : this->TargetDependersFileStreams) { + this->WriteFooter(*fileStream.second); } +} - // make sure we don't touch a null-ptr - auto interfaceLinkLibraries = - std::string(pInterfaceLinkLibraries ? pInterfaceLinkLibraries : ""); - auto linkLibraries = std::string(pLinkLibraries ? pLinkLibraries : ""); +void cmGraphVizWriter::VisitGraph(std::string const&) +{ + this->WriteHeader(GlobalFileStream, this->GraphName); + this->WriteLegend(GlobalFileStream); +} - // first extract interfaceLinkLibraries - while (start < interfaceLinkLibraries.length()) { +void cmGraphVizWriter::OnItem(cmLinkItem const& item) +{ + if (this->ItemExcluded(item)) { + return; + } - if ((end = interfaceLinkLibraries.find(sep, start)) == std::string::npos) { - end = interfaceLinkLibraries.length(); - } + NodeNames[item.AsStr()] = cmStrCat(GraphNodePrefix, NextNodeId); + ++NextNodeId; - std::string element = interfaceLinkLibraries.substr(start, end - start); - if (globalGenerator->IsAlias(element)) { - const auto tgt = globalGenerator->FindTarget(element); - if (tgt) { - element = tgt->GetName(); - } - } + this->WriteNode(this->GlobalFileStream, item); - if (std::string::npos == element.find("$<LINK_ONLY:", 0)) { - // we assume first, that this library is an interface library. - // if we find it again in the linklibraries property, we promote it to an - // public library. - tokens[element] = LLT_SCOPE_INTERFACE; - } else { - // this is an private linked static library. - // we take care of this case in the second iterator. - } - start = end + 1; + if (this->GeneratePerTarget) { + this->CreateTargetFile(this->PerTargetFileStreams, item); } - // second extract linkLibraries - start = 0; - while (start < linkLibraries.length()) { - - if ((end = linkLibraries.find(sep, start)) == std::string::npos) { - end = linkLibraries.length(); - } + if (this->GenerateDependers) { + this->CreateTargetFile(this->TargetDependersFileStreams, item, + ".dependers"); + } +} - std::string element = linkLibraries.substr(start, end - start); - if (globalGenerator->IsAlias(element)) { - const auto tgt = globalGenerator->FindTarget(element); - if (tgt) { - element = tgt->GetName(); - } - } +void cmGraphVizWriter::CreateTargetFile(FileStreamMap& fileStreamMap, + cmLinkItem const& item, + std::string const& fileNameSuffix) +{ + auto const pathSafeItemName = PathSafeString(item.AsStr()); + auto const perTargetFileName = + cmStrCat(this->FileName, '.', pathSafeItemName, fileNameSuffix); + auto perTargetFileStream = + cm::make_unique<cmGeneratedFileStream>(perTargetFileName); - if (tokens.find(element) == tokens.end()) { - // this library is not found in interfaceLinkLibraries but in - // linkLibraries. - // this results in a private linked library. - tokens[element] = LLT_SCOPE_PRIVATE; - } else if (LLT_SCOPE_INTERFACE == tokens[element]) { - // this library is found in interfaceLinkLibraries and linkLibraries. - // this results in a public linked library. - tokens[element] = LLT_SCOPE_PUBLIC; - } else { - // private and public linked libraries should not be changed anymore. - } + this->WriteHeader(*perTargetFileStream, item.AsStr()); + this->WriteNode(*perTargetFileStream, item); - start = end + 1; - } + fileStreamMap.emplace(item.AsStr(), std::move(perTargetFileStream)); +} - return tokens; +void cmGraphVizWriter::OnDirectLink(cmLinkItem const& depender, + cmLinkItem const& dependee, + DependencyType dt) +{ + this->VisitLink(depender, dependee, true, GetEdgeStyle(dt)); } + +void cmGraphVizWriter::OnIndirectLink(cmLinkItem const& depender, + cmLinkItem const& dependee) +{ + this->VisitLink(depender, dependee, false); } -cmGraphVizWriter::cmGraphVizWriter(const cmGlobalGenerator* globalGenerator) - : GraphType("digraph") - , GraphName("GG") - , GraphHeader("node [\n fontsize = \"12\"\n];") - , GraphNodePrefix("node") - , GlobalGenerator(globalGenerator) - , LocalGenerators(globalGenerator->GetLocalGenerators()) - , GenerateForExecutables(true) - , GenerateForStaticLibs(true) - , GenerateForSharedLibs(true) - , GenerateForModuleLibs(true) - , GenerateForInterface(true) - , GenerateForExternals(true) - , GeneratePerTarget(true) - , GenerateDependers(true) - , HaveTargetsAndLibs(false) +void cmGraphVizWriter::VisitLink(cmLinkItem const& depender, + cmLinkItem const& dependee, bool isDirectLink, + std::string const& scopeType) { + if (this->ItemExcluded(depender) || this->ItemExcluded(dependee)) { + return; + } + + if (!isDirectLink) { + return; + } + + this->WriteConnection(this->GlobalFileStream, depender, dependee, scopeType); + + if (this->GeneratePerTarget) { + auto fileStream = PerTargetFileStreams[depender.AsStr()].get(); + this->WriteNode(*fileStream, dependee); + this->WriteConnection(*fileStream, depender, dependee, scopeType); + } + + if (this->GenerateDependers) { + auto fileStream = TargetDependersFileStreams[dependee.AsStr()].get(); + this->WriteNode(*fileStream, depender); + this->WriteConnection(*fileStream, depender, dependee, scopeType); + } } void cmGraphVizWriter::ReadSettings( @@ -208,7 +224,6 @@ void cmGraphVizWriter::ReadSettings( } \ } while (false) - __set_if_set(this->GraphType, "GRAPHVIZ_GRAPH_TYPE"); __set_if_set(this->GraphName, "GRAPHVIZ_GRAPH_NAME"); __set_if_set(this->GraphHeader, "GRAPHVIZ_GRAPH_HEADER"); __set_if_set(this->GraphNodePrefix, "GRAPHVIZ_NODE_PREFIX"); @@ -225,7 +240,10 @@ void cmGraphVizWriter::ReadSettings( __set_bool_if_set(this->GenerateForStaticLibs, "GRAPHVIZ_STATIC_LIBS"); __set_bool_if_set(this->GenerateForSharedLibs, "GRAPHVIZ_SHARED_LIBS"); __set_bool_if_set(this->GenerateForModuleLibs, "GRAPHVIZ_MODULE_LIBS"); - __set_bool_if_set(this->GenerateForInterface, "GRAPHVIZ_INTERFACE"); + __set_bool_if_set(this->GenerateForInterfaceLibs, "GRAPHVIZ_INTERFACE_LIBS"); + __set_bool_if_set(this->GenerateForObjectLibs, "GRAPHVIZ_OBJECT_LIBS"); + __set_bool_if_set(this->GenerateForUnknownLibs, "GRAPHVIZ_UNKNOWN_LIBS"); + __set_bool_if_set(this->GenerateForCustomTargets, "GRAPHVIZ_CUSTOM_TARGETS"); __set_bool_if_set(this->GenerateForExternals, "GRAPHVIZ_EXTERNAL_LIBS"); __set_bool_if_set(this->GeneratePerTarget, "GRAPHVIZ_GENERATE_PER_TARGET"); __set_bool_if_set(this->GenerateDependers, "GRAPHVIZ_GENERATE_DEPENDERS"); @@ -248,329 +266,170 @@ void cmGraphVizWriter::ReadSettings( } } -// Iterate over all targets and write for each one a graph which shows -// which other targets depend on it. -void cmGraphVizWriter::WriteTargetDependersFiles(const std::string& fileName) +void cmGraphVizWriter::Write() { - if (!this->GenerateDependers) { - return; - } - - this->CollectTargetsAndLibs(); - - for (auto const& ptr : this->TargetPtrs) { - if (ptr.second == nullptr) { - continue; - } - - if (!this->GenerateForTargetType(ptr.second->GetType())) { - continue; - } - - std::string currentFilename = - cmStrCat(fileName, '.', ptr.first, ".dependers"); - - cmGeneratedFileStream str(currentFilename); - if (!str) { - return; + auto gg = this->GlobalGenerator; + + this->VisitGraph(gg->GetName()); + + // We want to traverse in a determined order, such that the output is always + // the same for a given project (this makes tests reproducible, etc.) + std::set<cmGeneratorTarget const*, cmGeneratorTarget::StrictTargetComparison> + sortedGeneratorTargets; + + for (cmLocalGenerator const* lg : gg->GetLocalGenerators()) { + for (cmGeneratorTarget const* gt : lg->GetGeneratorTargets()) { + // Reserved targets have inconsistent names across platforms (e.g. 'all' + // vs. 'ALL_BUILD'), which can disrupt the traversal ordering. + // We don't need or want them anyway. + if (!cmGlobalGenerator::IsReservedTarget(gt->GetName())) { + sortedGeneratorTargets.insert(gt); + } } - - std::set<std::string> insertedConnections; - std::set<std::string> insertedNodes; - - std::cout << "Writing " << currentFilename << "..." << std::endl; - this->WriteHeader(str); - - this->WriteDependerConnections(ptr.first, insertedNodes, - insertedConnections, str); - - this->WriteFooter(str); - } -} - -// Iterate over all targets and write for each one a graph which shows -// on which targets it depends. -void cmGraphVizWriter::WritePerTargetFiles(const std::string& fileName) -{ - if (!this->GeneratePerTarget) { - return; } - this->CollectTargetsAndLibs(); - - for (auto const& ptr : this->TargetPtrs) { - if (ptr.second == nullptr) { - continue; - } - - if (!this->GenerateForTargetType(ptr.second->GetType())) { - continue; - } - - std::set<std::string> insertedConnections; - std::set<std::string> insertedNodes; - - std::string currentFilename = cmStrCat(fileName, '.', ptr.first); - cmGeneratedFileStream str(currentFilename); - if (!str) { - return; - } - - std::cout << "Writing " << currentFilename << "..." << std::endl; - this->WriteHeader(str); - - this->WriteConnections(ptr.first, insertedNodes, insertedConnections, str); - this->WriteFooter(str); + for (auto const gt : sortedGeneratorTargets) { + auto item = cmLinkItem(gt, gt->GetBacktrace()); + this->VisitItem(item); } } -void cmGraphVizWriter::WriteGlobalFile(const std::string& fileName) +void cmGraphVizWriter::WriteHeader(cmGeneratedFileStream& fs, + const std::string& name) { - this->CollectTargetsAndLibs(); - - cmGeneratedFileStream str(fileName); - if (!str) { - return; - } - this->WriteHeader(str); - - std::cout << "Writing " << fileName << "..." << std::endl; - - std::set<std::string> insertedConnections; - std::set<std::string> insertedNodes; - - for (auto const& ptr : this->TargetPtrs) { - if (ptr.second == nullptr) { - continue; - } - - if (!this->GenerateForTargetType(ptr.second->GetType())) { - continue; - } - - this->WriteConnections(ptr.first, insertedNodes, insertedConnections, str); - } - this->WriteFooter(str); + auto const escapedGraphName = EscapeForDotFile(name); + fs << "digraph \"" << escapedGraphName << "\" {" << std::endl; + fs << this->GraphHeader << std::endl; } -void cmGraphVizWriter::WriteHeader(cmGeneratedFileStream& str) const +void cmGraphVizWriter::WriteFooter(cmGeneratedFileStream& fs) { - str << this->GraphType << " \"" << this->GraphName << "\" {" << std::endl; - str << this->GraphHeader << std::endl; + fs << "}" << std::endl; } -void cmGraphVizWriter::WriteFooter(cmGeneratedFileStream& str) const +void cmGraphVizWriter::WriteLegend(cmGeneratedFileStream& fs) { - str << "}" << std::endl; + // Note that the subgraph name must start with "cluster", as done here, to + // make Graphviz layout engines do the right thing and keep the nodes + // together. + fs << "subgraph clusterLegend {" << std::endl; + fs << " label = \"Legend\";" << std::endl; + // Set the color of the box surrounding the legend. + fs << " color = black;" << std::endl; + // We use invisible edges just to enforce the layout. + fs << " edge [ style = invis ];" << std::endl; + + // Nodes. + fs << " legendNode0 [ label = \"Executable\", shape = " + << GRAPHVIZ_NODE_SHAPE_EXECUTABLE << " ];" << std::endl; + + fs << " legendNode1 [ label = \"Static Library\", shape = " + << GRAPHVIZ_NODE_SHAPE_LIBRARY_STATIC << " ];" << std::endl; + fs << " legendNode2 [ label = \"Shared Library\", shape = " + << GRAPHVIZ_NODE_SHAPE_LIBRARY_SHARED << " ];" << std::endl; + fs << " legendNode3 [ label = \"Module Library\", shape = " + << GRAPHVIZ_NODE_SHAPE_LIBRARY_MODULE << " ];" << std::endl; + + fs << " legendNode4 [ label = \"Interface Library\", shape = " + << GRAPHVIZ_NODE_SHAPE_LIBRARY_INTERFACE << " ];" << std::endl; + fs << " legendNode5 [ label = \"Object Library\", shape = " + << GRAPHVIZ_NODE_SHAPE_LIBRARY_OBJECT << " ];" << std::endl; + fs << " legendNode6 [ label = \"Unknown Library\", shape = " + << GRAPHVIZ_NODE_SHAPE_LIBRARY_UNKNOWN << " ];" << std::endl; + + fs << " legendNode7 [ label = \"Custom Target\", shape = " + << GRAPHVIZ_NODE_SHAPE_UTILITY << " ];" << std::endl; + + // Edges. + // Some of those are dummy (invisible) edges to enforce a layout. + fs << " legendNode0 -> legendNode1 [ style = " << GRAPHVIZ_EDGE_STYLE_PUBLIC + << " ];" << std::endl; + fs << " legendNode0 -> legendNode2 [ style = " << GRAPHVIZ_EDGE_STYLE_PUBLIC + << " ];" << std::endl; + fs << " legendNode0 -> legendNode3;" << std::endl; + + fs << " legendNode1 -> legendNode4 [ label = \"Interface\", style = " + << GRAPHVIZ_EDGE_STYLE_INTERFACE << " ];" << std::endl; + fs << " legendNode2 -> legendNode5 [ label = \"Private\", style = " + << GRAPHVIZ_EDGE_STYLE_PRIVATE << " ];" << std::endl; + fs << " legendNode3 -> legendNode6 [ style = " << GRAPHVIZ_EDGE_STYLE_PUBLIC + << " ];" << std::endl; + + fs << " legendNode0 -> legendNode7;" << std::endl; + + fs << "}" << std::endl; } -void cmGraphVizWriter::WriteConnections( - const std::string& targetName, std::set<std::string>& insertedNodes, - std::set<std::string>& insertedConnections, cmGeneratedFileStream& str) const +void cmGraphVizWriter::WriteNode(cmGeneratedFileStream& fs, + cmLinkItem const& item) { - auto targetPtrIt = this->TargetPtrs.find(targetName); + auto const& itemName = item.AsStr(); + auto const& nodeName = this->NodeNames[itemName]; - if (targetPtrIt == this->TargetPtrs.end()) // not found at all - { - return; - } - - this->WriteNode(targetName, targetPtrIt->second, insertedNodes, str); - - if (targetPtrIt->second == nullptr) // it's an external library - { - return; - } + auto const itemNameWithAliases = ItemNameWithAliases(itemName); + auto const escapedLabel = EscapeForDotFile(itemNameWithAliases); - std::string myNodeName = this->TargetNamesNodes.find(targetName)->second; - std::map<std::string, LinkLibraryScopeType> ll = - getScopedLinkLibrariesFromTarget(targetPtrIt->second->Target, - GlobalGenerator); - - for (auto const& llit : ll) { - const std::string& libName = llit.first; - auto libNameIt = this->TargetNamesNodes.find(libName); - - // can happen e.g. if GRAPHVIZ_TARGET_IGNORE_REGEX is used - if (libNameIt == this->TargetNamesNodes.end()) { - continue; - } + fs << " \"" << nodeName << "\" [ label = \"" << escapedLabel + << "\", shape = " << getShapeForTarget(item) << " ];" << std::endl; +} - std::string connectionName = cmStrCat(myNodeName, '-', libNameIt->second); - if (insertedConnections.find(connectionName) == - insertedConnections.end()) { - insertedConnections.insert(connectionName); - this->WriteNode(libName, this->TargetPtrs.find(libName)->second, - insertedNodes, str); +void cmGraphVizWriter::WriteConnection(cmGeneratedFileStream& fs, + cmLinkItem const& depender, + cmLinkItem const& dependee, + std::string const& edgeStyle) +{ + auto const& dependerName = depender.AsStr(); + auto const& dependeeName = dependee.AsStr(); - str << " \"" << myNodeName << "\" -> \"" << libNameIt->second << "\""; + fs << " \"" << this->NodeNames[dependerName] << "\" -> \"" + << this->NodeNames[dependeeName] << "\" "; - str << getLinkLibraryStyle(llit.second); + fs << edgeStyle; - str << " // " << targetName << " -> " << libName << std::endl; - this->WriteConnections(libName, insertedNodes, insertedConnections, str); - } - } + fs << " // " << dependerName << " -> " << dependeeName << std::endl; } -void cmGraphVizWriter::WriteDependerConnections( - const std::string& targetName, std::set<std::string>& insertedNodes, - std::set<std::string>& insertedConnections, cmGeneratedFileStream& str) const +bool cmGraphVizWriter::ItemExcluded(cmLinkItem const& item) { - auto targetPtrIt = this->TargetPtrs.find(targetName); + auto const itemName = item.AsStr(); - if (targetPtrIt == this->TargetPtrs.end()) // not found at all - { - return; + if (this->ItemNameFilteredOut(itemName)) { + return true; } - this->WriteNode(targetName, targetPtrIt->second, insertedNodes, str); - - if (targetPtrIt->second == nullptr) // it's an external library - { - return; + if (item.Target == nullptr) { + return !this->GenerateForExternals; } - std::string myNodeName = this->TargetNamesNodes.find(targetName)->second; - - // now search who links against me - for (auto const& tptr : this->TargetPtrs) { - if (tptr.second == nullptr) { - continue; - } - - if (!this->GenerateForTargetType(tptr.second->GetType())) { - continue; - } - - // Now we have a target, check whether it links against targetName. - // If so, draw a connection, and then continue with dependers on that one. - std::map<std::string, LinkLibraryScopeType> ll = - getScopedLinkLibrariesFromTarget(tptr.second->Target, GlobalGenerator); - - for (auto const& llit : ll) { - if (llit.first == targetName) { - // So this target links against targetName. - auto dependerNodeNameIt = this->TargetNamesNodes.find(tptr.first); - - if (dependerNodeNameIt != this->TargetNamesNodes.end()) { - std::string connectionName = - cmStrCat(dependerNodeNameIt->second, '-', myNodeName); - - if (insertedConnections.find(connectionName) == - insertedConnections.end()) { - insertedConnections.insert(connectionName); - this->WriteNode(tptr.first, tptr.second, insertedNodes, str); - - str << " \"" << dependerNodeNameIt->second << "\" -> \"" - << myNodeName << "\""; - str << " // " << targetName << " -> " << tptr.first << std::endl; - str << getLinkLibraryStyle(llit.second); - this->WriteDependerConnections(tptr.first, insertedNodes, - insertedConnections, str); - } - } - break; - } + if (item.Target->GetType() == cmStateEnums::UTILITY) { + if ((itemName.find("Nightly") == 0) || + (itemName.find("Continuous") == 0) || + (itemName.find("Experimental") == 0)) { + return true; } } -} -void cmGraphVizWriter::WriteNode(const std::string& targetName, - const cmGeneratorTarget* target, - std::set<std::string>& insertedNodes, - cmGeneratedFileStream& str) const -{ - if (insertedNodes.find(targetName) == insertedNodes.end()) { - insertedNodes.insert(targetName); - auto nameIt = this->TargetNamesNodes.find(targetName); - - str << " \"" << nameIt->second << "\" [ label=\"" << targetName - << "\" shape=\"" << getShapeForTarget(target) << "\"];" << std::endl; + if (item.Target->IsImported() && !this->GenerateForExternals) { + return true; } -} -void cmGraphVizWriter::CollectTargetsAndLibs() -{ - if (!this->HaveTargetsAndLibs) { - this->HaveTargetsAndLibs = true; - int cnt = this->CollectAllTargets(); - if (this->GenerateForExternals) { - this->CollectAllExternalLibs(cnt); - } - } + return !this->TargetTypeEnabled(item.Target->GetType()); } -int cmGraphVizWriter::CollectAllTargets() +bool cmGraphVizWriter::ItemNameFilteredOut(std::string const& itemName) { - int cnt = 0; - // First pass get the list of all cmake targets - for (cmLocalGenerator* lg : this->LocalGenerators) { - const std::vector<cmGeneratorTarget*>& targets = lg->GetGeneratorTargets(); - for (cmGeneratorTarget* target : targets) { - const std::string& realTargetName = target->GetName(); - if (this->IgnoreThisTarget(realTargetName)) { - // Skip ignored targets - continue; - } - // std::cout << "Found target: " << tit->first << std::endl; - std::ostringstream ostr; - ostr << this->GraphNodePrefix << cnt++; - this->TargetNamesNodes[realTargetName] = ostr.str(); - this->TargetPtrs[realTargetName] = target; - } + if (itemName == ">") { + // FIXME: why do we even receive such a target here? + return true; } - return cnt; -} - -int cmGraphVizWriter::CollectAllExternalLibs(int cnt) -{ - // Ok, now find all the stuff we link to that is not in cmake - for (cmLocalGenerator* lg : this->LocalGenerators) { - const std::vector<cmGeneratorTarget*>& targets = lg->GetGeneratorTargets(); - for (cmGeneratorTarget* target : targets) { - const std::string& realTargetName = target->GetName(); - if (this->IgnoreThisTarget(realTargetName)) { - // Skip ignored targets - continue; - } - const cmTarget::LinkLibraryVectorType* ll = - &(target->Target->GetOriginalLinkLibraries()); - for (auto const& llit : *ll) { - std::string libName = llit.first; - if (this->IgnoreThisTarget(libName)) { - // Skip ignored targets - continue; - } - - if (GlobalGenerator->IsAlias(libName)) { - const auto tgt = GlobalGenerator->FindTarget(libName); - if (tgt) { - libName = tgt->GetName(); - } - } - - auto tarIt = this->TargetPtrs.find(libName); - if (tarIt == this->TargetPtrs.end()) { - std::ostringstream ostr; - ostr << this->GraphNodePrefix << cnt++; - this->TargetNamesNodes[libName] = ostr.str(); - this->TargetPtrs[libName] = nullptr; - // str << " \"" << ostr << "\" [ label=\"" << libName - // << "\" shape=\"ellipse\"];" << std::endl; - } - } - } + if (cmGlobalGenerator::IsReservedTarget(itemName)) { + return true; } - return cnt; -} -bool cmGraphVizWriter::IgnoreThisTarget(const std::string& name) -{ for (cmsys::RegularExpression& regEx : this->TargetsToIgnoreRegex) { if (regEx.is_valid()) { - if (regEx.find(name)) { + if (regEx.find(itemName)) { return true; } } @@ -579,7 +438,7 @@ bool cmGraphVizWriter::IgnoreThisTarget(const std::string& name) return false; } -bool cmGraphVizWriter::GenerateForTargetType( +bool cmGraphVizWriter::TargetTypeEnabled( cmStateEnums::TargetType targetType) const { switch (targetType) { @@ -592,9 +451,73 @@ bool cmGraphVizWriter::GenerateForTargetType( case cmStateEnums::MODULE_LIBRARY: return this->GenerateForModuleLibs; case cmStateEnums::INTERFACE_LIBRARY: - return this->GenerateForInterface; + return this->GenerateForInterfaceLibs; + case cmStateEnums::OBJECT_LIBRARY: + return this->GenerateForObjectLibs; + case cmStateEnums::UNKNOWN_LIBRARY: + return this->GenerateForUnknownLibs; + case cmStateEnums::UTILITY: + return this->GenerateForCustomTargets; + case cmStateEnums::GLOBAL_TARGET: + // Built-in targets like edit_cache, etc. + // We don't need/want those in the dot file. + return false; default: break; } return false; } + +std::string cmGraphVizWriter::ItemNameWithAliases( + std::string const& itemName) const +{ + auto nameWithAliases = itemName; + + for (auto const& lg : this->GlobalGenerator->GetLocalGenerators()) { + for (auto const& aliasTargets : lg->GetMakefile()->GetAliasTargets()) { + if (aliasTargets.second == itemName) { + nameWithAliases += "\\n(" + aliasTargets.first + ")"; + } + } + } + + return nameWithAliases; +} + +std::string cmGraphVizWriter::GetEdgeStyle(DependencyType dt) +{ + std::string style; + switch (dt) { + case DependencyType::LinkPrivate: + style = "[ style = " + std::string(GRAPHVIZ_EDGE_STYLE_PRIVATE) + " ]"; + break; + case DependencyType::LinkInterface: + style = "[ style = " + std::string(GRAPHVIZ_EDGE_STYLE_INTERFACE) + " ]"; + break; + default: + break; + } + return style; +} + +std::string cmGraphVizWriter::EscapeForDotFile(std::string const& str) +{ + return cmSystemTools::EscapeChars(str.data(), "\""); +} + +std::string cmGraphVizWriter::PathSafeString(std::string const& str) +{ + std::string pathSafeStr; + + // We'll only keep alphanumerical characters, plus the following ones that + // are common, and safe on all platforms: + auto const extra_chars = std::set<char>{ '.', '-', '_' }; + + for (char c : str) { + if (std::isalnum(c) || extra_chars.find(c) != extra_chars.cend()) { + pathSafeStr += c; + } + } + + return pathSafeStr; +} diff --git a/Source/cmGraphVizWriter.h b/Source/cmGraphVizWriter.h index 9c3051f..578660d 100644 --- a/Source/cmGraphVizWriter.h +++ b/Source/cmGraphVizWriter.h @@ -6,87 +6,106 @@ #include "cmConfigure.h" // IWYU pragma: keep #include <map> -#include <set> +#include <memory> #include <string> #include <vector> #include "cmsys/RegularExpression.hxx" +#include "cmGeneratedFileStream.h" +#include "cmLinkItemGraphVisitor.h" #include "cmStateTypes.h" -class cmGeneratedFileStream; -class cmGeneratorTarget; -class cmLocalGenerator; +class cmLinkItem; class cmGlobalGenerator; /** This class implements writing files for graphviz (dot) for graphs * representing the dependencies between the targets in the project. */ -class cmGraphVizWriter +class cmGraphVizWriter : public cmLinkItemGraphVisitor { public: - cmGraphVizWriter(const cmGlobalGenerator* globalGenerator); + cmGraphVizWriter(std::string const& fileName, + const cmGlobalGenerator* globalGenerator); + ~cmGraphVizWriter() override; + + void VisitGraph(std::string const& name) override; + + void OnItem(cmLinkItem const& item) override; + + void OnDirectLink(cmLinkItem const& depender, cmLinkItem const& dependee, + DependencyType dt) override; + + void OnIndirectLink(cmLinkItem const& depender, + cmLinkItem const& dependee) override; void ReadSettings(const std::string& settingsFileName, const std::string& fallbackSettingsFileName); - void WritePerTargetFiles(const std::string& fileName); - void WriteTargetDependersFiles(const std::string& fileName); + void Write(); + +private: + using FileStreamMap = + std::map<std::string, std::unique_ptr<cmGeneratedFileStream>>; + + void VisitLink(cmLinkItem const& depender, cmLinkItem const& dependee, + bool isDirectLink, std::string const& scopeType = ""); + + void WriteHeader(cmGeneratedFileStream& fs, std::string const& name); - void WriteGlobalFile(const std::string& fileName); + void WriteFooter(cmGeneratedFileStream& fs); -protected: - void CollectTargetsAndLibs(); + void WriteLegend(cmGeneratedFileStream& fs); - int CollectAllTargets(); + void WriteNode(cmGeneratedFileStream& fs, cmLinkItem const& item); - int CollectAllExternalLibs(int cnt); + void CreateTargetFile(FileStreamMap& fileStreamMap, cmLinkItem const& target, + std::string const& fileNameSuffix = ""); - void WriteHeader(cmGeneratedFileStream& str) const; + void WriteConnection(cmGeneratedFileStream& fs, + cmLinkItem const& dependerTargetName, + cmLinkItem const& dependeeTargetName, + std::string const& edgeStyle); - void WriteConnections(const std::string& targetName, - std::set<std::string>& insertedNodes, - std::set<std::string>& insertedConnections, - cmGeneratedFileStream& str) const; + bool ItemExcluded(cmLinkItem const& item); + bool ItemNameFilteredOut(std::string const& itemName); + bool TargetTypeEnabled(cmStateEnums::TargetType targetType) const; - void WriteDependerConnections(const std::string& targetName, - std::set<std::string>& insertedNodes, - std::set<std::string>& insertedConnections, - cmGeneratedFileStream& str) const; + std::string ItemNameWithAliases(std::string const& itemName) const; - void WriteNode(const std::string& targetName, - const cmGeneratorTarget* target, - std::set<std::string>& insertedNodes, - cmGeneratedFileStream& str) const; + static std::string GetEdgeStyle(DependencyType dt); - void WriteFooter(cmGeneratedFileStream& str) const; + static std::string EscapeForDotFile(std::string const& str); - bool IgnoreThisTarget(const std::string& name); + static std::string PathSafeString(std::string const& str); - bool GenerateForTargetType(cmStateEnums::TargetType targetType) const; + std::string FileName; + cmGeneratedFileStream GlobalFileStream; + FileStreamMap PerTargetFileStreams; + FileStreamMap TargetDependersFileStreams; - std::string GraphType; std::string GraphName; std::string GraphHeader; std::string GraphNodePrefix; std::vector<cmsys::RegularExpression> TargetsToIgnoreRegex; - const cmGlobalGenerator* GlobalGenerator; - const std::vector<cmLocalGenerator*>& LocalGenerators; + cmGlobalGenerator const* GlobalGenerator; - std::map<std::string, const cmGeneratorTarget*> TargetPtrs; - // maps from the actual target names to node names in dot: - std::map<std::string, std::string> TargetNamesNodes; + int NextNodeId; + // maps from the actual item names to node names in dot: + std::map<std::string, std::string> NodeNames; bool GenerateForExecutables; bool GenerateForStaticLibs; bool GenerateForSharedLibs; bool GenerateForModuleLibs; - bool GenerateForInterface; + bool GenerateForInterfaceLibs; + bool GenerateForObjectLibs; + bool GenerateForUnknownLibs; + bool GenerateForCustomTargets; bool GenerateForExternals; bool GeneratePerTarget; bool GenerateDependers; - bool HaveTargetsAndLibs; }; #endif diff --git a/Source/cmLinkItemGraphVisitor.cxx b/Source/cmLinkItemGraphVisitor.cxx new file mode 100644 index 0000000..ab2cf9e --- /dev/null +++ b/Source/cmLinkItemGraphVisitor.cxx @@ -0,0 +1,142 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#include "cmLinkItemGraphVisitor.h" + +#include <map> +#include <utility> +#include <vector> + +#include "cmGeneratorTarget.h" +#include "cmLinkItem.h" +#include "cmMakefile.h" + +void cmLinkItemGraphVisitor::VisitItem(cmLinkItem const& item) +{ + if (this->ItemVisited(item)) { + return; + } + + this->OnItem(item); + + this->VisitLinks(item, item); +} + +void cmLinkItemGraphVisitor::VisitLinks(cmLinkItem const& item, + cmLinkItem const& rootItem) +{ + if (this->LinkVisited(item, rootItem)) { + return; + } + + if (item.Target == nullptr) { + return; + } + + for (auto const& config : item.Target->Makefile->GetGeneratorConfigs()) { + this->VisitLinks(item, rootItem, config); + } +} + +void cmLinkItemGraphVisitor::VisitLinks(cmLinkItem const& item, + cmLinkItem const& rootItem, + std::string const& config) +{ + auto const& target = *item.Target; + + DependencyMap dependencies; + cmLinkItemGraphVisitor::GetDependencies(target, config, dependencies); + + for (auto const& d : dependencies) { + auto const& dependency = d.second; + auto const& dependencyType = dependency.first; + auto const& dependee = dependency.second; + this->VisitItem(dependee); + + if (this->LinkVisited(item, dependee)) { + continue; + } + + this->OnDirectLink(item, dependee, dependencyType); + + if (rootItem.AsStr() != item.AsStr()) { + this->OnIndirectLink(rootItem, dependee); + } + + // Visit all the direct and indirect links. + this->VisitLinks(dependee, dependee); + this->VisitLinks(dependee, item); + this->VisitLinks(dependee, rootItem); + } +} + +bool cmLinkItemGraphVisitor::ItemVisited(cmLinkItem const& item) +{ + auto& collection = this->VisitedItems; + + bool const visited = collection.find(item.AsStr()) != collection.cend(); + + if (!visited) { + collection.insert(item.AsStr()); + } + + return visited; +} + +bool cmLinkItemGraphVisitor::LinkVisited(cmLinkItem const& depender, + cmLinkItem const& dependee) +{ + auto const link = std::make_pair<>(depender.AsStr(), dependee.AsStr()); + + bool const linkVisited = + this->VisitedLinks.find(link) != this->VisitedLinks.cend(); + + if (!linkVisited) { + this->VisitedLinks.insert(link); + } + + return linkVisited; +} + +void cmLinkItemGraphVisitor::GetDependencies(cmGeneratorTarget const& target, + std::string const& config, + DependencyMap& dependencies) +{ + auto implementationLibraries = target.GetLinkImplementationLibraries(config); + if (implementationLibraries != nullptr) { + for (auto const& lib : implementationLibraries->Libraries) { + auto const& name = lib.AsStr(); + dependencies[name] = Dependency(DependencyType::LinkPrivate, lib); + } + } + + auto interfaceLibraries = + target.GetLinkInterfaceLibraries(config, &target, true); + if (interfaceLibraries != nullptr) { + for (auto const& lib : interfaceLibraries->Libraries) { + auto const& name = lib.AsStr(); + if (dependencies.find(name) != dependencies.cend()) { + dependencies[name] = Dependency(DependencyType::LinkPublic, lib); + } else { + dependencies[name] = Dependency(DependencyType::LinkInterface, lib); + } + } + } + + std::vector<cmGeneratorTarget*> objectLibraries; + target.GetObjectLibrariesCMP0026(objectLibraries); + for (auto const& lib : objectLibraries) { + auto const& name = lib->GetName(); + if (dependencies.find(name) == dependencies.cend()) { + auto objectItem = cmLinkItem(lib, lib->GetBacktrace()); + dependencies[name] = Dependency(DependencyType::Object, objectItem); + } + } + + auto const& utilityItems = target.GetUtilityItems(); + for (auto const& item : utilityItems) { + auto const& name = item.AsStr(); + if (dependencies.find(name) == dependencies.cend()) { + dependencies[name] = Dependency(DependencyType::Utility, item); + } + } +} diff --git a/Source/cmLinkItemGraphVisitor.h b/Source/cmLinkItemGraphVisitor.h new file mode 100644 index 0000000..21dc659 --- /dev/null +++ b/Source/cmLinkItemGraphVisitor.h @@ -0,0 +1,75 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#ifndef cmLinkItemGraphVisitor_h +#define cmLinkItemGraphVisitor_h + +#include <map> +#include <set> +#include <string> +#include <utility> + +#include "cmLinkItem.h" + +class cmGeneratorTarget; + +/** \class cmLinkItemGraphVisitor + * \brief Visits a graph of linked items. + * + * Allows to visit items and dependency links (direct and indirect) between + * those items. + * This abstract class takes care of the graph traversal, making sure that: + * - it terminates even in the presence of cycles; + * - it visits every object once (and only once); + * - it visits the objects in the same order every time. + * + * Children classes only have to implement OnItem() etc. to handle whatever + * logic they care about. + */ +class cmLinkItemGraphVisitor +{ +public: + virtual ~cmLinkItemGraphVisitor() = default; + + virtual void VisitGraph(std::string const& name) = 0; + + void VisitItem(cmLinkItem const& item); + +protected: + enum class DependencyType + { + LinkInterface, + LinkPublic, + LinkPrivate, + Object, + Utility + }; + + virtual void OnItem(cmLinkItem const& item) = 0; + + virtual void OnDirectLink(cmLinkItem const& depender, + cmLinkItem const& dependee, DependencyType dt) = 0; + + virtual void OnIndirectLink(cmLinkItem const& depender, + cmLinkItem const& dependee) = 0; + +private: + std::set<std::string> VisitedItems; + + std::set<std::pair<std::string, std::string>> VisitedLinks; + + void VisitLinks(cmLinkItem const& item, cmLinkItem const& rootItem); + void VisitLinks(cmLinkItem const& item, cmLinkItem const& rootItem, + std::string const& config); + + using Dependency = std::pair<DependencyType, cmLinkItem>; + using DependencyMap = std::map<std::string, Dependency>; + + bool ItemVisited(cmLinkItem const& item); + bool LinkVisited(cmLinkItem const& depender, cmLinkItem const& dependee); + + static void GetDependencies(cmGeneratorTarget const& target, + std::string const& config, + DependencyMap& dependencies); +}; + +#endif diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index ccd70a3..a2eb1b9 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -45,7 +45,6 @@ #include <cstdio> #include <cstdlib> #include <cstring> -#include <functional> #include <initializer_list> #include <iterator> #include <sstream> @@ -263,11 +262,6 @@ static void MoveSystemIncludesToEnd(std::vector<BT<std::string>>& includeDirs, void cmLocalGenerator::TraceDependencies() { - std::vector<std::string> const& configs = - this->Makefile->GetGeneratorConfigs(); - for (std::string const& c : configs) { - this->GlobalGenerator->CreateEvaluationSourceFiles(c); - } // Generate the rule files for each target. const std::vector<cmGeneratorTarget*>& targets = this->GetGeneratorTargets(); for (cmGeneratorTarget* target : targets) { @@ -360,6 +354,15 @@ void cmLocalGenerator::GenerateTestFiles() } } +void cmLocalGenerator::CreateEvaluationFileOutputs() +{ + std::vector<std::string> const& configs = + this->Makefile->GetGeneratorConfigs(); + for (std::string const& c : configs) { + this->CreateEvaluationFileOutputs(c); + } +} + void cmLocalGenerator::CreateEvaluationFileOutputs(std::string const& config) { std::vector<cmGeneratorExpressionEvaluationFile*> ef = @@ -2251,9 +2254,13 @@ void cmLocalGenerator::AppendFlagEscape(std::string& flags, this->AppendFlags(flags, this->EscapeForShell(rawFlag)); } -void cmLocalGenerator::AddPchDependencies(cmGeneratorTarget* target, - const std::string& config) +void cmLocalGenerator::AddPchDependencies(cmGeneratorTarget* target) { + // FIXME: Handle all configurations in multi-config generators. + std::string config; + if (!this->GetGlobalGenerator()->IsMultiConfig()) { + config = this->Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE"); + } const std::string buildType = cmSystemTools::UpperCase(config); std::vector<cmSourceFile*> sources; @@ -2262,7 +2269,8 @@ void cmLocalGenerator::AddPchDependencies(cmGeneratorTarget* target, for (const std::string& lang : { "C", "CXX" }) { auto langSources = std::count_if(sources.begin(), sources.end(), [lang](cmSourceFile* sf) { - return lang == sf->GetLanguage(); + return lang == sf->GetLanguage() && + !sf->GetProperty("SKIP_PRECOMPILE_HEADERS"); }); if (langSources == 0) { continue; @@ -2275,20 +2283,10 @@ void cmLocalGenerator::AddPchDependencies(cmGeneratorTarget* target, continue; } - const std::string createOptVar = - cmStrCat("CMAKE_", lang, "_COMPILE_OPTIONS_CREATE_PCH"); - std::string createOptionList = - this->Makefile->GetSafeDefinition(createOptVar); - - const std::string useOptVar = - cmStrCat("CMAKE_", lang, "_COMPILE_OPTIONS_USE_PCH"); - std::string useOptionList = this->Makefile->GetSafeDefinition(useOptVar); - const std::string pchExtension = this->Makefile->GetSafeDefinition("CMAKE_PCH_EXTENSION"); - if (createOptionList.empty() || useOptionList.empty() || - pchExtension.empty()) { + if (pchExtension.empty()) { continue; } @@ -2297,31 +2295,17 @@ void cmLocalGenerator::AddPchDependencies(cmGeneratorTarget* target, auto pch_sf = this->Makefile->GetOrCreateSource( pchSource, false, cmSourceFileLocationKind::Known); - std::string pchFile = pchHeader; if (!this->GetGlobalGenerator()->IsXcode()) { if (!pchReuseFrom) { target->AddSource(pchSource, true); } + const std::string pchFile = target->GetPchFile(config, lang); + // Exclude the pch files from linking if (this->Makefile->IsOn("CMAKE_LINK_PCH")) { - - auto replaceExtension = [](const std::string& str, - const std::string& ext) -> std::string { - auto dot_pos = str.rfind('.'); - std::string result; - if (dot_pos != std::string::npos) { - result = str.substr(0, dot_pos); - } - result += ext; - return result; - }; - if (!pchReuseFrom) { - std::string pchSourceObj = target->GetPchFileObject(config, lang); - - pchFile = replaceExtension(pchSourceObj, pchExtension); pch_sf->SetProperty("OBJECT_OUTPUTS", pchFile.c_str()); } else { auto reuseTarget = @@ -2402,14 +2386,13 @@ void cmLocalGenerator::AddPchDependencies(cmGeneratorTarget* target, reuseTarget->GetPchFileObject(config, lang); // Link to the pch object file - target->Target->SetProperty( + target->Target->AppendProperty( "LINK_FLAGS", - this->ConvertToOutputFormat(pchSourceObj, SHELL).c_str()); - - pchFile = replaceExtension(pchSourceObj, pchExtension); + cmStrCat(" ", this->ConvertToOutputFormat(pchSourceObj, SHELL)) + .c_str(), + true); } } else { - pchFile += pchExtension; pch_sf->SetProperty("PCH_EXTENSION", pchExtension.c_str()); } @@ -2420,34 +2403,6 @@ void cmLocalGenerator::AddPchDependencies(cmGeneratorTarget* target, std::string err; pchHeader_sf->ResolveFullPath(&err); target->AddSource(pchHeader); - - for (auto& str : - { std::ref(useOptionList), std::ref(createOptionList) }) { - cmSystemTools::ReplaceString(str, "<PCH_HEADER>", pchHeader); - cmSystemTools::ReplaceString(str, "<PCH_FILE>", pchFile); - } - } - - pch_sf->SetProperty("COMPILE_OPTIONS", createOptionList.c_str()); - - for (cmSourceFile* sf : sources) { - if (pch_sf == sf || sf->GetLanguage() != lang) { - continue; - } - - if (sf->GetPropertyAsBool("SKIP_PRECOMPILE_HEADERS")) { - if (this->GetGlobalGenerator()->IsXcode()) { - sf->SetProperty("COMPILE_DEFINITIONS", - "CMAKE_SKIP_PRECOMPILE_HEADERS"); - } - continue; - } - - if (!this->GetGlobalGenerator()->IsXcode()) { - sf->AppendProperty("OBJECT_DEPENDS", pchFile.c_str()); - sf->AppendProperty("OBJECT_DEPENDS", pchHeader.c_str()); - sf->SetProperty("COMPILE_OPTIONS", useOptionList.c_str()); - } } } } diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h index 14d05ad..12359db 100644 --- a/Source/cmLocalGenerator.h +++ b/Source/cmLocalGenerator.h @@ -126,8 +126,7 @@ public: const std::vector<BT<std::string>>& newFlags) const; virtual void AppendFlagEscape(std::string& flags, const std::string& rawFlag) const; - void AddPchDependencies(cmGeneratorTarget* target, - const std::string& config); + void AddPchDependencies(cmGeneratorTarget* target); void AddUnityBuild(cmGeneratorTarget* target); void AppendIPOLinkerFlags(std::string& flags, cmGeneratorTarget* target, const std::string& config, @@ -418,6 +417,7 @@ public: void IssueMessage(MessageType t, std::string const& text) const; + void CreateEvaluationFileOutputs(); void CreateEvaluationFileOutputs(const std::string& config); void ProcessEvaluationFiles(std::vector<std::string>& generatedFiles); diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx index e16e851..ff1eaec 100644 --- a/Source/cmLocalVisualStudio7Generator.cxx +++ b/Source/cmLocalVisualStudio7Generator.cxx @@ -98,6 +98,10 @@ void cmLocalVisualStudio7Generator::FixGlobalTargets() std::string no_main_dependency; std::string force = cmStrCat(this->GetCurrentBinaryDirectory(), "/CMakeFiles/", l->GetName(), "_force"); + if (cmSourceFile* sf = + this->Makefile->GetOrCreateGeneratedSource(force)) { + sf->SetProperty("SYMBOLIC", "1"); + } if (cmSourceFile* file = this->Makefile->AddCustomCommandToOutput( force.c_str(), no_depends, no_main_dependency, force_commands, " ", 0, true)) { @@ -1313,8 +1317,6 @@ void cmLocalVisualStudio7Generator::WriteVCProjFile(std::ostream& fout, const std::string& libName, cmGeneratorTarget* target) { - this->AddPchDependencies(target, ""); - std::vector<std::string> configs; this->Makefile->GetConfigurations(configs); @@ -1452,6 +1454,22 @@ cmLocalVisualStudio7GeneratorFCInfo::cmLocalVisualStudio7GeneratorFCInfo( fc.CompileFlags, genexInterpreter.Evaluate(coptions, COMPILE_OPTIONS)); needfc = true; } + // Add precompile headers compile options. + const std::string pchSource = gt->GetPchSource(config, lang); + if (!pchSource.empty() && !sf.GetProperty("SKIP_PRECOMPILE_HEADERS")) { + std::string pchOptions; + if (sf.GetFullPath() == pchSource) { + pchOptions = gt->GetPchCreateCompileOptions(config, lang); + } else { + pchOptions = gt->GetPchUseCompileOptions(config, lang); + } + + lg->AppendCompileOptions( + fc.CompileFlags, + genexInterpreter.Evaluate(pchOptions, COMPILE_OPTIONS)); + needfc = true; + } + if (lg->FortranProject) { switch (cmOutputConverter::GetFortranFormat( sf.GetProperty("Fortran_FORMAT"))) { diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index f143ef7..bf488b1 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -4487,7 +4487,7 @@ bool cmMakefile::SetPolicy(cmPolicies::PolicyID id, // Deprecate old policies, especially those that require a lot // of code to maintain the old behavior. - if (status == cmPolicies::OLD && id <= cmPolicies::CMP0067 && + if (status == cmPolicies::OLD && id <= cmPolicies::CMP0069 && !(this->GetCMakeInstance()->GetIsInTryCompile() && ( // Policies set by cmCoreTryCompile::TryCompileCode. diff --git a/Source/cmMakefileExecutableTargetGenerator.cxx b/Source/cmMakefileExecutableTargetGenerator.cxx index 0b225cb..40265ff 100644 --- a/Source/cmMakefileExecutableTargetGenerator.cxx +++ b/Source/cmMakefileExecutableTargetGenerator.cxx @@ -40,8 +40,6 @@ cmMakefileExecutableTargetGenerator::cmMakefileExecutableTargetGenerator( this->OSXBundleGenerator = cm::make_unique<cmOSXBundleGenerator>(target, this->ConfigName); this->OSXBundleGenerator->SetMacContentFolders(&this->MacContentFolders); - - this->LocalGenerator->AddPchDependencies(target, this->ConfigName); } cmMakefileExecutableTargetGenerator::~cmMakefileExecutableTargetGenerator() = diff --git a/Source/cmMakefileLibraryTargetGenerator.cxx b/Source/cmMakefileLibraryTargetGenerator.cxx index cf09374..54a6606 100644 --- a/Source/cmMakefileLibraryTargetGenerator.cxx +++ b/Source/cmMakefileLibraryTargetGenerator.cxx @@ -42,8 +42,6 @@ cmMakefileLibraryTargetGenerator::cmMakefileLibraryTargetGenerator( this->OSXBundleGenerator = cm::make_unique<cmOSXBundleGenerator>(target, this->ConfigName); this->OSXBundleGenerator->SetMacContentFolders(&this->MacContentFolders); - - this->LocalGenerator->AddPchDependencies(target, this->ConfigName); } cmMakefileLibraryTargetGenerator::~cmMakefileLibraryTargetGenerator() = diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx index d352f8e..767f4e0 100644 --- a/Source/cmMakefileTargetGenerator.cxx +++ b/Source/cmMakefileTargetGenerator.cxx @@ -423,25 +423,17 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles( // Create the directory containing the object file. This may be a // subdirectory under the target's directory. - std::string dir = cmSystemTools::GetFilenamePath(obj); - cmSystemTools::MakeDirectory(this->LocalGenerator->ConvertToFullPath(dir)); + { + std::string dir = cmSystemTools::GetFilenamePath(obj); + cmSystemTools::MakeDirectory(this->LocalGenerator->ConvertToFullPath(dir)); + } // Save this in the target's list of object files. this->Objects.push_back(obj); this->CleanFiles.insert(obj); - // TODO: Remove - // std::string relativeObj - //= this->LocalGenerator->GetHomeRelativeOutputPath(); - // relativeObj += obj; - - // we compute some depends when writing the depend.make that we will also - // use in the build.make, same with depMakeFile std::vector<std::string> depends; - // generate the build rule file - this->WriteObjectBuildFile(obj, lang, source, depends); - // The object file should be checked for dependency integrity. std::string objFullPath = cmStrCat(this->LocalGenerator->GetCurrentBinaryDirectory(), '/', obj); @@ -450,12 +442,7 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles( cmSystemTools::CollapseFullPath(source.GetFullPath()); this->LocalGenerator->AddImplicitDepends(this->GeneratorTarget, lang, objFullPath, srcFullPath); -} -void cmMakefileTargetGenerator::WriteObjectBuildFile( - std::string& obj, const std::string& lang, cmSourceFile const& source, - std::vector<std::string>& depends) -{ this->LocalGenerator->AppendRuleDepend(depends, this->FlagFileNameFull.c_str()); this->LocalGenerator->AppendRuleDepends(depends, @@ -464,6 +451,23 @@ void cmMakefileTargetGenerator::WriteObjectBuildFile( // generate the depend scanning rule this->WriteObjectDependRules(source, depends); + std::string config = this->LocalGenerator->GetConfigName(); + std::string configUpper = cmSystemTools::UpperCase(config); + + // Add precompile headers dependencies + const std::string pchSource = + this->GeneratorTarget->GetPchSource(config, lang); + if (!pchSource.empty() && !source.GetProperty("SKIP_PRECOMPILE_HEADERS")) { + std::string const& pchHeader = + this->GeneratorTarget->GetPchHeader(config, lang); + depends.push_back(pchHeader); + if (source.GetFullPath() != pchSource) { + depends.push_back(this->GeneratorTarget->GetPchFile(config, lang)); + } + this->LocalGenerator->AddImplicitDepends(this->GeneratorTarget, lang, + objFullPath, pchHeader); + } + std::string relativeObj = cmStrCat(this->LocalGenerator->GetHomeRelativeOutputPath(), obj); // Write the build rule. @@ -475,8 +479,6 @@ void cmMakefileTargetGenerator::WriteObjectBuildFile( std::string langFlags = cmStrCat("$(", lang, "_FLAGS)"); this->LocalGenerator->AppendFlags(flags, langFlags); - std::string config = this->LocalGenerator->GetConfigName(); - std::string configUpper = cmSystemTools::UpperCase(config); cmGeneratorExpressionInterpreter genexInterpreter( this->LocalGenerator, config, this->GeneratorTarget, lang); @@ -506,6 +508,26 @@ void cmMakefileTargetGenerator::WriteObjectBuildFile( << "\n"; } + // Add precompile headers compile options. + if (!pchSource.empty() && !source.GetProperty("SKIP_PRECOMPILE_HEADERS")) { + std::string pchOptions; + if (source.GetFullPath() == pchSource) { + pchOptions = + this->GeneratorTarget->GetPchCreateCompileOptions(config, lang); + } else { + pchOptions = + this->GeneratorTarget->GetPchUseCompileOptions(config, lang); + } + + const std::string& evaluatedFlags = + genexInterpreter.Evaluate(pchOptions, COMPILE_OPTIONS); + + this->LocalGenerator->AppendCompileOptions(flags, evaluatedFlags); + *this->FlagFileStream << "# PCH options: " << relativeObj + << "_OPTIONS = " << evaluatedFlags << "\n" + << "\n"; + } + // Add include directories from source file properties. std::vector<std::string> includes; diff --git a/Source/cmMakefileTargetGenerator.h b/Source/cmMakefileTargetGenerator.h index f464128..7b9c7a5 100644 --- a/Source/cmMakefileTargetGenerator.h +++ b/Source/cmMakefileTargetGenerator.h @@ -91,11 +91,6 @@ protected: // write the rules for an object void WriteObjectRuleFiles(cmSourceFile const& source); - // write the build rule for an object - void WriteObjectBuildFile(std::string& obj, const std::string& lang, - cmSourceFile const& source, - std::vector<std::string>& depends); - // write the depend.make file for an object void WriteObjectDependRules(cmSourceFile const& source, std::vector<std::string>& depends); diff --git a/Source/cmMakefileUtilityTargetGenerator.cxx b/Source/cmMakefileUtilityTargetGenerator.cxx index 516f098..1625e4f 100644 --- a/Source/cmMakefileUtilityTargetGenerator.cxx +++ b/Source/cmMakefileUtilityTargetGenerator.cxx @@ -25,8 +25,6 @@ cmMakefileUtilityTargetGenerator::cmMakefileUtilityTargetGenerator( this->OSXBundleGenerator = cm::make_unique<cmOSXBundleGenerator>(target, this->ConfigName); this->OSXBundleGenerator->SetMacContentFolders(&this->MacContentFolders); - - this->LocalGenerator->AddPchDependencies(target, this->ConfigName); } cmMakefileUtilityTargetGenerator::~cmMakefileUtilityTargetGenerator() = diff --git a/Source/cmMessageCommand.cxx b/Source/cmMessageCommand.cxx index 96a6386..24ac71a 100644 --- a/Source/cmMessageCommand.cxx +++ b/Source/cmMessageCommand.cxx @@ -21,6 +21,9 @@ bool cmMessageCommand(std::vector<std::string> const& args, status.SetError("called with incorrect number of arguments"); return false; } + + auto& mf = status.GetMakefile(); + auto i = args.cbegin(); auto type = MessageType::MESSAGE; @@ -40,13 +43,12 @@ bool cmMessageCommand(std::vector<std::string> const& args, level = cmake::LogLevel::LOG_WARNING; ++i; } else if (*i == "AUTHOR_WARNING") { - if (status.GetMakefile().IsSet("CMAKE_SUPPRESS_DEVELOPER_ERRORS") && - !status.GetMakefile().IsOn("CMAKE_SUPPRESS_DEVELOPER_ERRORS")) { + if (mf.IsSet("CMAKE_SUPPRESS_DEVELOPER_ERRORS") && + !mf.IsOn("CMAKE_SUPPRESS_DEVELOPER_ERRORS")) { fatal = true; type = MessageType::AUTHOR_ERROR; level = cmake::LogLevel::LOG_ERROR; - } else if (!status.GetMakefile().IsOn( - "CMAKE_SUPPRESS_DEVELOPER_WARNINGS")) { + } else if (!mf.IsOn("CMAKE_SUPPRESS_DEVELOPER_WARNINGS")) { type = MessageType::AUTHOR_WARNING; level = cmake::LogLevel::LOG_WARNING; } else { @@ -66,12 +68,12 @@ bool cmMessageCommand(std::vector<std::string> const& args, level = cmake::LogLevel::LOG_TRACE; ++i; } else if (*i == "DEPRECATION") { - if (status.GetMakefile().IsOn("CMAKE_ERROR_DEPRECATED")) { + if (mf.IsOn("CMAKE_ERROR_DEPRECATED")) { fatal = true; type = MessageType::DEPRECATION_ERROR; level = cmake::LogLevel::LOG_ERROR; - } else if (!status.GetMakefile().IsSet("CMAKE_WARN_DEPRECATED") || - status.GetMakefile().IsOn("CMAKE_WARN_DEPRECATED")) { + } else if (!mf.IsSet("CMAKE_WARN_DEPRECATED") || + mf.IsOn("CMAKE_WARN_DEPRECATED")) { type = MessageType::DEPRECATION_WARNING; level = cmake::LogLevel::LOG_WARNING; } else { @@ -89,10 +91,19 @@ bool cmMessageCommand(std::vector<std::string> const& args, assert("Message log level expected to be set" && level != cmake::LogLevel::LOG_UNDEFINED); - auto desiredLevel = status.GetMakefile().GetCMakeInstance()->GetLogLevel(); + auto desiredLevel = mf.GetCMakeInstance()->GetLogLevel(); assert("Expected a valid log level here" && desiredLevel != cmake::LogLevel::LOG_UNDEFINED); + // Command line option takes precedence over the cache variable + if (!mf.GetCMakeInstance()->WasLogLevelSetViaCLI()) { + const auto desiredLevelFromCache = + cmake::StringToLogLevel(mf.GetSafeDefinition("CMAKE_MESSAGE_LOG_LEVEL")); + if (desiredLevelFromCache != cmake::LogLevel::LOG_UNDEFINED) { + desiredLevel = desiredLevelFromCache; + } + } + if (desiredLevel < level) { // Suppress the message return true; @@ -101,25 +112,32 @@ bool cmMessageCommand(std::vector<std::string> const& args, auto message = cmJoin(cmMakeRange(i, args.cend()), ""); if (cmake::LogLevel::LOG_NOTICE <= level) { - // Check if any indentation has requested: - // `CMAKE_MESSAGE_INDENT` is a list of "padding" pieces - // to be joined and prepended to the message lines. - auto indent = cmJoin(cmExpandedList(status.GetMakefile().GetSafeDefinition( - "CMAKE_MESSAGE_INDENT")), - ""); - // Make every line of the `message` indented - // NOTE Can't reuse `cmDocumentationFormatter::PrintPreformatted` - // here cuz it appends `\n` to the EOM ;-( - cmSystemTools::ReplaceString(message, "\n", "\n" + indent); - message = indent + message; + auto indent = + cmJoin(cmExpandedList(mf.GetSafeDefinition("CMAKE_MESSAGE_INDENT")), ""); + if (!indent.empty()) { + cmSystemTools::ReplaceString(message, "\n", "\n" + indent); + message = indent + message; + } + + const auto showContext = mf.GetCMakeInstance()->GetShowLogContext() || + mf.IsOn("CMAKE_MESSAGE_CONTEXT_SHOW"); + if (showContext) { + // Output the current context (if any) + auto context = cmJoin( + cmExpandedList(mf.GetSafeDefinition("CMAKE_MESSAGE_CONTEXT")), "."); + if (!context.empty()) { + context = "[" + context + "] "; + cmSystemTools::ReplaceString(message, "\n", "\n" + context); + message = context + message; + } + } } switch (level) { case cmake::LogLevel::LOG_ERROR: case cmake::LogLevel::LOG_WARNING: // we've overridden the message type, above, so display it directly - status.GetMakefile().GetMessenger()->DisplayMessage( - type, message, status.GetMakefile().GetBacktrace()); + mf.GetMessenger()->DisplayMessage(type, message, mf.GetBacktrace()); break; case cmake::LogLevel::LOG_NOTICE: @@ -130,7 +148,7 @@ bool cmMessageCommand(std::vector<std::string> const& args, case cmake::LogLevel::LOG_VERBOSE: case cmake::LogLevel::LOG_DEBUG: case cmake::LogLevel::LOG_TRACE: - status.GetMakefile().DisplayStatus(message, -1); + mf.DisplayStatus(message, -1); break; default: diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx index 3f362fc..beedef4 100644 --- a/Source/cmNinjaNormalTargetGenerator.cxx +++ b/Source/cmNinjaNormalTargetGenerator.cxx @@ -61,8 +61,6 @@ cmNinjaNormalTargetGenerator::cmNinjaNormalTargetGenerator( this->OSXBundleGenerator = cm::make_unique<cmOSXBundleGenerator>(target, this->GetConfigName()); this->OSXBundleGenerator->SetMacContentFolders(&this->MacContentFolders); - - GetLocalGenerator()->AddPchDependencies(target, this->GetConfigName()); } cmNinjaNormalTargetGenerator::~cmNinjaNormalTargetGenerator() = default; diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx index 0fda47e..919a5db 100644 --- a/Source/cmNinjaTargetGenerator.cxx +++ b/Source/cmNinjaTargetGenerator.cxx @@ -141,6 +141,7 @@ std::string cmNinjaTargetGenerator::ComputeFlagsForObject( cmSourceFile const* source, const std::string& language) { std::string flags = this->GetFlags(language); + const std::string configName = this->LocalGenerator->GetConfigName(); // Add Fortran format flags. if (language == "Fortran") { @@ -149,8 +150,7 @@ std::string cmNinjaTargetGenerator::ComputeFlagsForObject( // Add source file specific flags. cmGeneratorExpressionInterpreter genexInterpreter( - this->LocalGenerator, this->LocalGenerator->GetConfigName(), - this->GeneratorTarget, language); + this->LocalGenerator, configName, this->GeneratorTarget, language); const std::string COMPILE_FLAGS("COMPILE_FLAGS"); if (const char* cflags = source->GetProperty(COMPILE_FLAGS)) { @@ -164,6 +164,24 @@ std::string cmNinjaTargetGenerator::ComputeFlagsForObject( flags, genexInterpreter.Evaluate(coptions, COMPILE_OPTIONS)); } + // Add precompile headers compile options. + const std::string pchSource = + this->GeneratorTarget->GetPchSource(configName, language); + + if (!pchSource.empty() && !source->GetProperty("SKIP_PRECOMPILE_HEADERS")) { + std::string pchOptions; + if (source->GetFullPath() == pchSource) { + pchOptions = this->GeneratorTarget->GetPchCreateCompileOptions( + configName, language); + } else { + pchOptions = + this->GeneratorTarget->GetPchUseCompileOptions(configName, language); + } + + this->LocalGenerator->AppendCompileOptions( + flags, genexInterpreter.Evaluate(pchOptions, COMPILE_OPTIONS)); + } + return flags; } @@ -984,8 +1002,27 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement( objBuild.ExplicitDeps.push_back(sourceFileName); + // Add precompile headers dependencies + std::vector<std::string> depList; + + const std::string pchSource = + this->GeneratorTarget->GetPchSource(this->GetConfigName(), language); + if (!pchSource.empty() && !source->GetProperty("SKIP_PRECOMPILE_HEADERS")) { + depList.push_back( + this->GeneratorTarget->GetPchHeader(this->GetConfigName(), language)); + if (source->GetFullPath() != pchSource) { + depList.push_back( + this->GeneratorTarget->GetPchFile(this->GetConfigName(), language)); + } + } + if (const char* objectDeps = source->GetProperty("OBJECT_DEPENDS")) { - std::vector<std::string> depList = cmExpandedList(objectDeps); + std::vector<std::string> objDepList = cmExpandedList(objectDeps); + std::copy(objDepList.begin(), objDepList.end(), + std::back_inserter(depList)); + } + + if (!depList.empty()) { for (std::string& odi : depList) { if (cmSystemTools::FileIsFullPath(odi)) { odi = cmSystemTools::CollapseFullPath(odi); diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index 99c16f2..a4f904b 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -511,8 +511,7 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type, initProp("DOTNET_TARGET_FRAMEWORK_VERSION"); } - if (this->GetType() != cmStateEnums::INTERFACE_LIBRARY && - this->GetType() != cmStateEnums::UTILITY) { + if (this->GetType() != cmStateEnums::INTERFACE_LIBRARY) { // check for "CMAKE_VS_GLOBALS" variable and set up target properties // if any diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx index 34556f9..dac86a1 100644 --- a/Source/cmVisualStudio10TargetGenerator.cxx +++ b/Source/cmVisualStudio10TargetGenerator.cxx @@ -250,8 +250,6 @@ cmVisualStudio10TargetGenerator::cmVisualStudio10TargetGenerator( this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget); this->InSourceBuild = (this->Makefile->GetCurrentSourceDirectory() == this->Makefile->GetCurrentBinaryDirectory()); - - this->LocalGenerator->AddPchDependencies(target, ""); } cmVisualStudio10TargetGenerator::~cmVisualStudio10TargetGenerator() @@ -545,6 +543,11 @@ void cmVisualStudio10TargetGenerator::Generate() e1.Element("VCProjectUpgraderObjectName", "NoUpgrade"); } + if (const char* vcTargetsPath = + this->GlobalGenerator->GetCustomVCTargetsPath()) { + e1.Element("VCTargetsPath", vcTargetsPath); + } + std::vector<std::string> keys = this->GeneratorTarget->GetPropertyKeys(); for (std::string const& keyIt : keys) { static const char* prefix = "VS_GLOBAL_"; @@ -678,6 +681,8 @@ void cmVisualStudio10TargetGenerator::Generate() this->WritePlatformExtensions(e1); } + + this->WriteDotNetDocumentationFile(e0); Elem(e0, "PropertyGroup").Attribute("Label", "UserMacros"); this->WriteWinRTPackageCertificateKeyFile(e0); this->WritePathAndIncrementalLinkOptions(e0); @@ -912,6 +917,18 @@ void cmVisualStudio10TargetGenerator::WriteDotNetReferenceCustomTags( } } +void cmVisualStudio10TargetGenerator::WriteDotNetDocumentationFile(Elem& e0) +{ + std::string const documentationFile = + this->GeneratorTarget->GetSafeProperty("VS_DOTNET_DOCUMENTATION_FILE"); + + if (this->ProjectType == csproj && !documentationFile.empty()) { + Elem e1(e0, "PropertyGroup"); + Elem e2(e1, "DocumentationFile"); + e2.Content(documentationFile); + } +} + void cmVisualStudio10TargetGenerator::WriteEmbeddedResourceGroup(Elem& e0) { std::vector<cmSourceFile const*> resxObjs; @@ -2330,10 +2347,28 @@ void cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags( cmGeneratorExpression::Find(ccdefs) != std::string::npos; configDefines += ccdefs; } + + // Add precompile headers compile options. + std::string customAndPchOptions = options; + const std::string pchSource = + this->GeneratorTarget->GetPchSource(config, lang); + if (!pchSource.empty() && !sf.GetProperty("SKIP_PRECOMPILE_HEADERS")) { + std::string pchOptions; + if (sf.GetFullPath() == pchSource) { + pchOptions = + this->GeneratorTarget->GetPchCreateCompileOptions(config, lang); + } else { + pchOptions = + this->GeneratorTarget->GetPchUseCompileOptions(config, lang); + } + customAndPchOptions += pchOptions; + } + // if we have flags or defines for this config then // use them if (!flags.empty() || !options.empty() || !configDefines.empty() || - !includes.empty() || compileAs || noWinRT) { + !includes.empty() || compileAs || noWinRT || + !customAndPchOptions.empty()) { cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator; cmIDEFlagTable const* flagtable = nullptr; const std::string& srclang = source->GetLanguage(); @@ -2366,14 +2401,15 @@ void cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags( } else { clOptions.Parse(flags); } - if (!options.empty()) { + if (!customAndPchOptions.empty()) { std::string expandedOptions; if (configDependentOptions) { this->LocalGenerator->AppendCompileOptions( expandedOptions, - genexInterpreter.Evaluate(options, "COMPILE_OPTIONS")); + genexInterpreter.Evaluate(customAndPchOptions, "COMPILE_OPTIONS")); } else { - this->LocalGenerator->AppendCompileOptions(expandedOptions, options); + this->LocalGenerator->AppendCompileOptions(expandedOptions, + customAndPchOptions); } clOptions.Parse(expandedOptions); } diff --git a/Source/cmVisualStudio10TargetGenerator.h b/Source/cmVisualStudio10TargetGenerator.h index a18a33d..0835cde 100644 --- a/Source/cmVisualStudio10TargetGenerator.h +++ b/Source/cmVisualStudio10TargetGenerator.h @@ -79,6 +79,7 @@ private: void WriteDotNetReference(Elem& e1, std::string const& ref, std::string const& hint, std::string const& config); + void WriteDotNetDocumentationFile(Elem& e0); void WriteImports(Elem& e0); void WriteDotNetReferenceCustomTags(Elem& e2, std::string const& ref); void WriteEmbeddedResourceGroup(Elem& e0); diff --git a/Source/cmVisualStudio10ToolsetOptions.cxx b/Source/cmVisualStudio10ToolsetOptions.cxx index a490e03..7fc33e6 100644 --- a/Source/cmVisualStudio10ToolsetOptions.cxx +++ b/Source/cmVisualStudio10ToolsetOptions.cxx @@ -34,8 +34,7 @@ std::string cmVisualStudio10ToolsetOptions::GetCSharpFlagTableName( std::string const useToolset = this->GetToolsetName(name, toolset); if (useToolset == "v142") { - // FIXME: Add CSharp flag table for v142. - return "v141"; + return "v142"; } else if (useToolset == "v141") { return "v141"; } else if (useToolset == "v140") { diff --git a/Source/cmake.cxx b/Source/cmake.cxx index 02606c2..4a6108d 100644 --- a/Source/cmake.cxx +++ b/Source/cmake.cxx @@ -423,6 +423,8 @@ bool cmake::SetCacheArgs(const std::vector<std::string>& args) } } std::cout << "loading initial cache file " << path << "\n"; + // Resolve script path specified on command line relative to $PWD. + path = cmSystemTools::CollapseFullPath(path); this->ReadListFile(args, path); } else if (arg.find("-P", 0) == 0) { i++; @@ -725,7 +727,19 @@ void cmake::SetArgs(const std::vector<std::string>& args) } else if (arg.find("--debug-output", 0) == 0) { std::cout << "Running with debug output on.\n"; this->SetDebugOutputOn(true); + } else if (arg.find("--log-level=", 0) == 0) { + const auto logLevel = + StringToLogLevel(arg.substr(sizeof("--log-level=") - 1)); + if (logLevel == LogLevel::LOG_UNDEFINED) { + cmSystemTools::Error("Invalid level specified for --log-level"); + return; + } + this->SetLogLevel(logLevel); + this->LogLevelWasSetViaCLI = true; } else if (arg.find("--loglevel=", 0) == 0) { + // This is supported for backward compatibility. This option only + // appeared in the 3.15.x release series and was renamed to + // --log-level in 3.16.0 const auto logLevel = StringToLogLevel(arg.substr(sizeof("--loglevel=") - 1)); if (logLevel == LogLevel::LOG_UNDEFINED) { @@ -733,6 +747,9 @@ void cmake::SetArgs(const std::vector<std::string>& args) return; } this->SetLogLevel(logLevel); + this->LogLevelWasSetViaCLI = true; + } else if (arg == "--log-context") { + this->SetShowLogContext(true); } else if (arg.find("--trace-expand", 0) == 0) { std::cout << "Running with expanded trace output on.\n"; this->SetTrace(true); @@ -2274,7 +2291,7 @@ void cmake::MarkCliAsUsed(const std::string& variable) void cmake::GenerateGraphViz(const std::string& fileName) const { #ifndef CMAKE_BOOTSTRAP - cmGraphVizWriter gvWriter(this->GetGlobalGenerator()); + cmGraphVizWriter gvWriter(fileName, this->GetGlobalGenerator()); std::string settingsFile = cmStrCat(this->GetHomeOutputDirectory(), "/CMakeGraphVizOptions.cmake"); @@ -2282,9 +2299,8 @@ void cmake::GenerateGraphViz(const std::string& fileName) const cmStrCat(this->GetHomeDirectory(), "/CMakeGraphVizOptions.cmake"); gvWriter.ReadSettings(settingsFile, fallbackSettingsFile); - gvWriter.WritePerTargetFiles(fileName); - gvWriter.WriteTargetDependersFiles(fileName); - gvWriter.WriteGlobalFile(fileName); + + gvWriter.Write(); #endif } @@ -2603,6 +2619,14 @@ int cmake::Build(int jobs, const std::string& dir, return 1; } } + const char* cachedGeneratorToolset = + this->State->GetCacheEntryValue("CMAKE_GENERATOR_TOOLSET"); + if (cachedGeneratorToolset) { + cmMakefile mf(gen, this->GetCurrentSnapshot()); + if (!gen->SetGeneratorToolset(cachedGeneratorToolset, true, &mf)) { + return 1; + } + } std::string output; std::string projName; const char* cachedProjectName = diff --git a/Source/cmake.h b/Source/cmake.h index 687c105..c2f2cce 100644 --- a/Source/cmake.h +++ b/Source/cmake.h @@ -380,6 +380,8 @@ public: */ cmFileTimeCache* GetFileTimeCache() { return this->FileTimeCache.get(); } + bool WasLogLevelSetViaCLI() const { return this->LogLevelWasSetViaCLI; } + //! Get the selected log level for `message()` commands during the cmake run. LogLevel GetLogLevel() const { return this->MessageLogLevel; } void SetLogLevel(LogLevel level) { this->MessageLogLevel = level; } @@ -389,6 +391,10 @@ public: bool GetDebugOutput() { return this->DebugOutput; } void SetDebugOutputOn(bool b) { this->DebugOutput = b; } + //! Should `message` command display context. + bool GetShowLogContext() const { return this->LogContext; } + void SetShowLogContext(bool b) { this->LogContext = b; } + //! Do we want trace output during the cmake run. bool GetTrace() { return this->Trace; } void SetTrace(bool b) { this->Trace = b; } @@ -587,6 +593,8 @@ private: std::vector<std::string> TraceOnlyThisSources; LogLevel MessageLogLevel = LogLevel::LOG_STATUS; + bool LogLevelWasSetViaCLI = false; + bool LogContext = false; void UpdateConversionPathTable(); diff --git a/Source/cmakemain.cxx b/Source/cmakemain.cxx index cc00c81..baf975e 100644 --- a/Source/cmakemain.cxx +++ b/Source/cmakemain.cxx @@ -70,8 +70,10 @@ const char* cmDocumentationOptions[][2] = { "Generate graphviz of dependencies, see " "CMakeGraphVizOptions.cmake for more." }, { "--system-information [file]", "Dump information about this system." }, - { "--loglevel=<ERROR|WARNING|NOTICE|STATUS|VERBOSE|DEBUG|TRACE>", - "Set the verbosity of messages from CMake files." }, + { "--log-level=<ERROR|WARNING|NOTICE|STATUS|VERBOSE|DEBUG|TRACE>", + "Set the verbosity of messages from CMake files. " + "--loglevel is also accepted for backward compatibility reasons." }, + { "--log-context", "Prepend log messages with context, if given" }, { "--debug-trycompile", "Do not delete the try_compile build tree. Only " "useful on one try_compile at a time." }, diff --git a/Templates/MSBuild/FlagTables/v142_CSharp.json b/Templates/MSBuild/FlagTables/v142_CSharp.json new file mode 100644 index 0000000..5989aea --- /dev/null +++ b/Templates/MSBuild/FlagTables/v142_CSharp.json @@ -0,0 +1,574 @@ +[ + { + "name": "ProjectName", + "switch": "out:", + "comment": "", + "value": "", + "flags": [ + "UserValue", + "UserRequired" + ] + }, + { + "name": "OutputType", + "switch": "target:exe", + "comment": "", + "value": "Exe", + "flags": [] + }, + { + "name": "OutputType", + "switch": "target:winexe", + "comment": "", + "value": "Winexe", + "flags": [] + }, + { + "name": "OutputType", + "switch": "target:library", + "comment": "", + "value": "Library", + "flags": [] + }, + { + "name": "OutputType", + "switch": "target:module", + "comment": "", + "value": "Module", + "flags": [] + }, + { + "name": "DocumentationFile", + "switch": "doc", + "comment": "", + "value": "", + "flags": [ + "UserValue", + "UserRequired" + ] + }, + { + "name": "Platform", + "switch": "platform:x86", + "comment": "", + "value": "x86", + "flags": [] + }, + { + "name": "Platform", + "switch": "platform:Itanium", + "comment": "", + "value": "Itanium", + "flags": [] + }, + { + "name": "Platform", + "switch": "platform:x64", + "comment": "", + "value": "x64", + "flags": [] + }, + { + "name": "Platform", + "switch": "platform:arm", + "comment": "", + "value": "arm", + "flags": [] + }, + { + "name": "Platform", + "switch": "platform:anycpu32bitpreferred", + "comment": "", + "value": "anycpu32bitpreferred", + "flags": [] + }, + { + "name": "Platform", + "switch": "platform:anycpu", + "comment": "", + "value": "anycpu", + "flags": [] + }, + { + "name": "References", + "switch": "reference:", + "comment": "mit alias", + "value": "", + "flags": [] + }, + { + "name": "References", + "switch": "reference:", + "comment": "dateiliste", + "value": "", + "flags": [] + }, + { + "name": "AddModules", + "switch": "addmodule:", + "comment": "", + "value": "", + "flags": [ + "SemicolonAppendable" + ] + }, + { + "name": "Win32Resource", + "switch": "win32res:", + "comment": "", + "value": "", + "flags": [ + "UserValue", + "UserRequired" + ] + }, + { + "name": "ApplicationIcon", + "switch": "win32icon:", + "comment": "", + "value": "", + "flags": [ + "UserValue", + "UserRequired" + ] + }, + { + "name": "ApplicationManifest", + "switch": "win32manifest:", + "comment": "", + "value": "", + "flags": [ + "UserValue", + "UserRequired" + ] + }, + { + "name": "NoWin32Manifest", + "switch": "nowin32manifest", + "comment": "", + "value": "true", + "flags": [] + }, + { + "name": "DefineDebug", + "switch": "debug", + "comment": "", + "value": "true", + "flags": [ + "Continue" + ] + }, + { + "name": "DebugSymbols", + "switch": "debug", + "comment": "", + "value": "true", + "flags": [] + }, + { + "name": "DebugSymbols", + "switch": "debug-", + "comment": "", + "value": "false", + "flags": [] + }, + { + "name": "DebugSymbols", + "switch": "debug+", + "comment": "", + "value": "true", + "flags": [] + }, + { + "name": "DebugType", + "switch": "debug:none", + "comment": "", + "value": "none", + "flags": [] + }, + { + "name": "DebugType", + "switch": "debug:full", + "comment": "", + "value": "full", + "flags": [] + }, + { + "name": "DebugType", + "switch": "debug:pdbonly", + "comment": "", + "value": "pdbonly", + "flags": [] + }, + { + "name": "Optimize", + "switch": "optimize", + "comment": "", + "value": "true", + "flags": [] + }, + { + "name": "Optimize", + "switch": "optimize-", + "comment": "", + "value": "false", + "flags": [] + }, + { + "name": "Optimize", + "switch": "optimize+", + "comment": "", + "value": "true", + "flags": [] + }, + { + "name": "TreatWarningsAsErrors", + "switch": "warnaserror", + "comment": "", + "value": "true", + "flags": [] + }, + { + "name": "TreatWarningsAsErrors", + "switch": "warnaserror-", + "comment": "", + "value": "false", + "flags": [] + }, + { + "name": "TreatWarningsAsErrors", + "switch": "warnaserror+", + "comment": "", + "value": "true", + "flags": [] + }, + { + "name": "WarningsAsErrors", + "switch": "warnaserror", + "comment": "", + "value": "", + "flags": [] + }, + { + "name": "WarningsAsErrors", + "switch": "warnaserror-", + "comment": "", + "value": "", + "flags": [] + }, + { + "name": "WarningsAsErrors", + "switch": "warnaserror+", + "comment": "", + "value": "", + "flags": [] + }, + { + "name": "WarningLevel", + "switch": "warn:0", + "comment": "", + "value": "0", + "flags": [] + }, + { + "name": "WarningLevel", + "switch": "warn:1", + "comment": "", + "value": "1", + "flags": [] + }, + { + "name": "WarningLevel", + "switch": "warn:2", + "comment": "", + "value": "2", + "flags": [] + }, + { + "name": "WarningLevel", + "switch": "warn:3", + "comment": "", + "value": "3", + "flags": [] + }, + { + "name": "WarningLevel", + "switch": "warn:4", + "comment": "", + "value": "4", + "flags": [] + }, + { + "name": "NoWarn", + "switch": "nowarn:", + "comment": "", + "value": "", + "flags": [ + "UserValue", + "UserRequired", + "CommaAppendable" + ] + }, + { + "name": "CheckForOverflowUnderflow", + "switch": "checked", + "comment": "", + "value": "true", + "flags": [] + }, + { + "name": "CheckForOverflowUnderflow", + "switch": "checked-", + "comment": "", + "value": "false", + "flags": [] + }, + { + "name": "CheckForOverflowUnderflow", + "switch": "checked+", + "comment": "", + "value": "true", + "flags": [] + }, + { + "name": "AllowUnsafeBlocks", + "switch": "unsafe", + "comment": "", + "value": "true", + "flags": [] + }, + { + "name": "AllowUnsafeBlocks", + "switch": "unsafe-", + "comment": "", + "value": "false", + "flags": [] + }, + { + "name": "AllowUnsafeBlocks", + "switch": "unsafe+", + "comment": "", + "value": "true", + "flags": [] + }, + { + "name": "DefineConstants", + "switch": "define:", + "comment": "", + "value": "", + "flags": [ + "SemicolonAppendable", + "UserValue" + ] + }, + { + "name": "LangVersion", + "switch": "langversion:ISO-1", + "comment": "", + "value": "ISO-1", + "flags": [] + }, + { + "name": "LangVersion", + "switch": "langversion:ISO-2", + "comment": "", + "value": "ISO-2", + "flags": [] + }, + { + "name": "LangVersion", + "switch": "langversion:3", + "comment": "", + "value": "3", + "flags": [] + }, + { + "name": "LangVersion", + "switch": "langversion:4", + "comment": "", + "value": "4", + "flags": [] + }, + { + "name": "LangVersion", + "switch": "langversion:5", + "comment": "", + "value": "5", + "flags": [] + }, + { + "name": "LangVersion", + "switch": "langversion:6", + "comment": "", + "value": "6", + "flags": [] + }, + { + "name": "LangVersion", + "switch": "langversion:default", + "comment": "", + "value": "default", + "flags": [] + }, + { + "name": "DelaySign", + "switch": "delaysign", + "comment": "", + "value": "true", + "flags": [] + }, + { + "name": "DelaySign", + "switch": "delaysign-", + "comment": "", + "value": "false", + "flags": [] + }, + { + "name": "DelaySign", + "switch": "delaysign+", + "comment": "", + "value": "true", + "flags": [] + }, + { + "name": "AssemblyOriginatorKeyFile", + "switch": "keyfile", + "comment": "", + "value": "", + "flags": [] + }, + { + "name": "KeyContainerName", + "switch": "keycontainer", + "comment": "", + "value": "", + "flags": [] + }, + { + "name": "NoLogo", + "switch": "nologo", + "comment": "", + "value": "", + "flags": [] + }, + { + "name": "NoConfig", + "switch": "noconfig", + "comment": "", + "value": "true", + "flags": [] + }, + { + "name": "BaseAddress", + "switch": "baseaddress:", + "comment": "", + "value": "", + "flags": [] + }, + { + "name": "CodePage", + "switch": "codepage", + "comment": "", + "value": "", + "flags": [] + }, + { + "name": "Utf8Output", + "switch": "utf8output", + "comment": "", + "value": "", + "flags": [] + }, + { + "name": "MainEntryPoint", + "switch": "main:", + "comment": "", + "value": "", + "flags": [] + }, + { + "name": "GenerateFullPaths", + "switch": "fullpaths", + "comment": "", + "value": "true", + "flags": [] + }, + { + "name": "FileAlignment", + "switch": "filealign", + "comment": "", + "value": "", + "flags": [] + }, + { + "name": "PdbFile", + "switch": "pdb:", + "comment": "", + "value": "", + "flags": [] + }, + { + "name": "NoStandardLib", + "switch": "nostdlib", + "comment": "", + "value": "true", + "flags": [] + }, + { + "name": "NoStandardLib", + "switch": "nostdlib-", + "comment": "", + "value": "false", + "flags": [] + }, + { + "name": "NoStandardLib", + "switch": "nostdlib+", + "comment": "", + "value": "true", + "flags": [] + }, + { + "name": "SubsystemVersion", + "switch": "subsystemversion", + "comment": "", + "value": "", + "flags": [] + }, + { + "name": "AdditionalLibPaths", + "switch": "lib:", + "comment": "", + "value": "", + "flags": [] + }, + { + "name": "ErrorReport", + "switch": "errorreport:none", + "comment": "Do Not Send Report", + "value": "none", + "flags": [] + }, + { + "name": "ErrorReport", + "switch": "errorreport:prompt", + "comment": "Prompt Immediately", + "value": "prompt", + "flags": [] + }, + { + "name": "ErrorReport", + "switch": "errorreport:queue", + "comment": "Queue For Next Login", + "value": "queue", + "flags": [] + }, + { + "name": "ErrorReport", + "switch": "errorreport:send", + "comment": "Send Automatically", + "value": "send", + "flags": [] + } +] diff --git a/Tests/BuildDepends/CMakeLists.txt b/Tests/BuildDepends/CMakeLists.txt index 39a5131..c1ad17c 100644 --- a/Tests/BuildDepends/CMakeLists.txt +++ b/Tests/BuildDepends/CMakeLists.txt @@ -62,6 +62,12 @@ file(WRITE ${BuildDepends_BINARY_DIR}/Project/zot_macro_dir.hxx "static const char* zot_macro_dir = \"zot_macro_dir\";\n") file(WRITE ${BuildDepends_BINARY_DIR}/Project/zot_macro_tgt.hxx "static const char* zot_macro_tgt = \"zot_macro_tgt\";\n") +file(WRITE ${BuildDepends_BINARY_DIR}/Project/zot_pch.hxx + "#ifndef ZOT_PCH_HXX\n" + "#define ZOT_PCH_HXX\n" + "static const char* zot_pch = \"zot_pch\";\n" + "#endif\n" + ) file(WRITE ${BuildDepends_BINARY_DIR}/Project/link_depends_no_shared_lib.h "#define link_depends_no_shared_lib_value 1\n") @@ -155,7 +161,7 @@ execute_process(COMMAND ${zot} OUTPUT_VARIABLE out RESULT_VARIABLE runResult) string(REGEX REPLACE "[\r\n]" " " out "${out}") message("Run result: ${runResult} Output: \"${out}\"") -set(VALUE_UNCHANGED "[zot] [zot_custom] [zot_macro_dir] [zot_macro_tgt] ") +set(VALUE_UNCHANGED "[zot] [zot_custom] [zot_macro_dir] [zot_macro_tgt] [zot_pch] ") if("${out}" STREQUAL "${VALUE_UNCHANGED}") message("Worked!") else() @@ -245,6 +251,12 @@ file(WRITE ${BuildDepends_BINARY_DIR}/Project/zot_macro_dir.hxx "static const char* zot_macro_dir = \"zot_macro_dir changed\";\n") file(WRITE ${BuildDepends_BINARY_DIR}/Project/zot_macro_tgt.hxx "static const char* zot_macro_tgt = \"zot_macro_tgt changed\";\n") +file(WRITE ${BuildDepends_BINARY_DIR}/Project/zot_pch.hxx + "#ifndef ZOT_PCH_HXX\n" + "#define ZOT_PCH_HXX\n" + "static const char* zot_pch = \"zot_pch changed\";\n" + "#endif\n" + ) file(WRITE ${BuildDepends_BINARY_DIR}/Project/link_depends_no_shared_lib.h "#define link_depends_no_shared_lib_value 0\n") @@ -326,7 +338,7 @@ string(REGEX REPLACE "[\r\n]" " " out "${out}") message("Run result: ${runResult} Output: \"${out}\"") set(VALUE_CHANGED - "[zot changed] [zot_custom changed] [zot_macro_dir changed] [zot_macro_tgt changed] " + "[zot changed] [zot_custom changed] [zot_macro_dir changed] [zot_macro_tgt changed] [zot_pch changed] " ) if("${out}" STREQUAL "${VALUE_CHANGED}") message("Worked!") diff --git a/Tests/BuildDepends/Project/CMakeLists.txt b/Tests/BuildDepends/Project/CMakeLists.txt index 3f41b26..8338800 100644 --- a/Tests/BuildDepends/Project/CMakeLists.txt +++ b/Tests/BuildDepends/Project/CMakeLists.txt @@ -93,6 +93,12 @@ add_executable(zot zot.cxx ${CMAKE_CURRENT_BINARY_DIR}/zot.hxx zot_macro_dir.cxx zot_macro_tgt.cxx) add_dependencies(zot zot_custom) +add_library(zot_pch zot_pch.cxx) +target_link_libraries(zot zot_pch) +if(NOT CMAKE_OSX_ARCHITECTURES MATCHES "[;$]") + target_precompile_headers(zot_pch PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/zot_pch.hxx) +endif() + # Test the #include line macro transformation rule support. set_property( TARGET zot diff --git a/Tests/BuildDepends/Project/zot.cxx b/Tests/BuildDepends/Project/zot.cxx index faee7d3..2d08c4b 100644 --- a/Tests/BuildDepends/Project/zot.cxx +++ b/Tests/BuildDepends/Project/zot.cxx @@ -4,11 +4,12 @@ const char* zot_macro_dir_f(); const char* zot_macro_tgt_f(); +const char* zot_pch_f(); int main() { - printf("[%s] [%s] [%s] [%s]\n", zot, zot_custom, zot_macro_dir_f(), - zot_macro_tgt_f()); + printf("[%s] [%s] [%s] [%s] [%s]\n", zot, zot_custom, zot_macro_dir_f(), + zot_macro_tgt_f(), zot_pch_f()); fflush(stdout); return 0; } diff --git a/Tests/BuildDepends/Project/zot_pch.cxx b/Tests/BuildDepends/Project/zot_pch.cxx new file mode 100644 index 0000000..d9d04c7 --- /dev/null +++ b/Tests/BuildDepends/Project/zot_pch.cxx @@ -0,0 +1,6 @@ +#include <zot_pch.hxx> + +const char* zot_pch_f() +{ + return zot_pch; +} diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt index 32b580b..b29638b 100644 --- a/Tests/CMakeLists.txt +++ b/Tests/CMakeLists.txt @@ -2353,6 +2353,18 @@ ${CMake_SOURCE_DIR}/Utilities/Release/push.bash --dir dev -- '${CMake_BUILD_NIGH ) list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/Objective-C/c-file-extension-test") + add_test(Objective-C.cxx-file-extension-test ${CMAKE_CTEST_COMMAND} + --build-and-test + "${CMake_SOURCE_DIR}/Tests/Objective-C/cxx-file-extension-test" + "${CMake_BINARY_DIR}/Tests/Objective-C/cxx-file-extension-test" + --build-two-config + ${build_generator_args} + --build-project cxx-file-extension-test + --build-options ${build_options} + --test-command cxx-file-extension-test + ) + list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/Objective-C/cxx-file-extension-test") + add_test(Objective-C.objc-file-extension-test ${CMAKE_CTEST_COMMAND} --build-and-test "${CMake_SOURCE_DIR}/Tests/Objective-C/objc-file-extension-test" diff --git a/Tests/CompileFeatures/CMakeLists.txt b/Tests/CompileFeatures/CMakeLists.txt index 060fb49..ef9198d 100644 --- a/Tests/CompileFeatures/CMakeLists.txt +++ b/Tests/CompileFeatures/CMakeLists.txt @@ -130,6 +130,12 @@ if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") endif() if (CMAKE_CXX_COMPILER_ID STREQUAL "Intel") + if (CMAKE_CXX_SIMULATE_ID STREQUAL "MSVC" + AND CMAKE_CXX_SIMULATE_VERSION VERSION_LESS 19.10) + list(REMOVE_ITEM CXX_non_features + cxx_relaxed_constexpr + ) + endif() if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 16.0) if (CMAKE_CXX_COMIPLER_VERSION VERSION_EQUAL 15.0) list(REMOVE_ITEM CXX_non_features diff --git a/Tests/CompileFeatures/default_dialect.cpp b/Tests/CompileFeatures/default_dialect.cpp index 3ee60a6..e6b3ff6 100644 --- a/Tests/CompileFeatures/default_dialect.cpp +++ b/Tests/CompileFeatures/default_dialect.cpp @@ -2,7 +2,17 @@ template <long l> struct Outputter; -#if defined(_MSC_VER) && defined(_MSVC_LANG) +#if defined(__INTEL_COMPILER) && defined(_MSVC_LANG) && _MSVC_LANG < 201403L +# if defined(__INTEL_CXX11_MODE__) +# if defined(__cpp_aggregate_nsdmi) +# define CXX_STD 201402L +# else +# define CXX_STD 201103L +# endif +# else +# define CXX_STD 199711L +# endif +#elif defined(_MSC_VER) && defined(_MSVC_LANG) # define CXX_STD _MSVC_LANG #else # define CXX_STD __cplusplus diff --git a/Tests/ExportImport/Export/CMakeLists.txt b/Tests/ExportImport/Export/CMakeLists.txt index 5cf04e8..9d8a248 100644 --- a/Tests/ExportImport/Export/CMakeLists.txt +++ b/Tests/ExportImport/Export/CMakeLists.txt @@ -645,3 +645,8 @@ if(CMAKE_GENERATOR MATCHES "Make|Ninja") EXPORT RequiredExp DESTINATION lib) export(TARGETS testLinkDepends NAMESPACE bld_ APPEND FILE ExportBuildTree.cmake) endif() + +# Test the presence of targets named the same as languages. +# IMPORTED_LINK_INTERFACE_LANGUAGES entries should not be targets. +add_library(C INTERFACE) +add_library(CXX INTERFACE) diff --git a/Tests/Objective-C/cxx-file-extension-test/CMakeLists.txt b/Tests/Objective-C/cxx-file-extension-test/CMakeLists.txt new file mode 100644 index 0000000..eb065e4 --- /dev/null +++ b/Tests/Objective-C/cxx-file-extension-test/CMakeLists.txt @@ -0,0 +1,8 @@ +cmake_minimum_required(VERSION 3.15) + +project(cxx-file-extension-test) + +string(APPEND CMAKE_CXX_FLAGS " -std=c++11") +set(CMAKE_CXX_STANDARD 14) + +add_executable(cxx-file-extension-test main.m) diff --git a/Tests/Objective-C/cxx-file-extension-test/main.m b/Tests/Objective-C/cxx-file-extension-test/main.m new file mode 100644 index 0000000..1c159a9 --- /dev/null +++ b/Tests/Objective-C/cxx-file-extension-test/main.m @@ -0,0 +1,8 @@ +#ifndef __OBJC__ +# error "Compiler cannot compile Objective-C" +#endif + +int main() +{ + return 0; +} diff --git a/Tests/RunCMake/CMP0068/CMP0068-OLD-stderr.txt b/Tests/RunCMake/CMP0068/CMP0068-OLD-stderr.txt new file mode 100644 index 0000000..a736129 --- /dev/null +++ b/Tests/RunCMake/CMP0068/CMP0068-OLD-stderr.txt @@ -0,0 +1,10 @@ +^CMake Deprecation Warning at CMP0068-OLD.cmake:[0-9]+ \(cmake_policy\): + The OLD behavior for policy CMP0068 will be removed from a future version + of CMake. + + The cmake-policies\(7\) manual explains that the OLD behaviors of all + policies are deprecated and that a policy should be set to OLD only under + specific short-term circumstances. Projects should be ported to the NEW + behavior and not rely on setting a policy to OLD. +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\)$ diff --git a/Tests/RunCMake/CMP0069/CMP0069-OLD-stderr.txt b/Tests/RunCMake/CMP0069/CMP0069-OLD-stderr.txt new file mode 100644 index 0000000..f51a6f4 --- /dev/null +++ b/Tests/RunCMake/CMP0069/CMP0069-OLD-stderr.txt @@ -0,0 +1,10 @@ +^CMake Deprecation Warning at CMP0069-OLD.cmake:[0-9]+ \(cmake_policy\): + The OLD behavior for policy CMP0069 will be removed from a future version + of CMake. + + The cmake-policies\(7\) manual explains that the OLD behaviors of all + policies are deprecated and that a policy should be set to OLD only under + specific short-term circumstances. Projects should be ported to the NEW + behavior and not rely on setting a policy to OLD. +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\)$ diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt index 0925c0e..31b280b 100644 --- a/Tests/RunCMake/CMakeLists.txt +++ b/Tests/RunCMake/CMakeLists.txt @@ -189,6 +189,7 @@ add_RunCMake_test(GeneratorToolset) add_RunCMake_test(GetPrerequisites) add_RunCMake_test(GNUInstallDirs -DSYSTEM_NAME=${CMAKE_SYSTEM_NAME}) add_RunCMake_test(GoogleTest) # Note: does not actually depend on Google Test +add_RunCMake_test(Graphviz) add_RunCMake_test(TargetPropertyGeneratorExpressions) add_RunCMake_test(Languages) add_RunCMake_test(LinkStatic) diff --git a/Tests/RunCMake/CheckIPOSupported/cmp0069-is-old-stderr.txt b/Tests/RunCMake/CheckIPOSupported/cmp0069-is-old-stderr.txt index f183594..1baa63a 100644 --- a/Tests/RunCMake/CheckIPOSupported/cmp0069-is-old-stderr.txt +++ b/Tests/RunCMake/CheckIPOSupported/cmp0069-is-old-stderr.txt @@ -1,4 +1,15 @@ -^CMake Error at .*/Modules/CheckIPOSupported\.cmake:[0-9]+ \(message\): +^CMake Deprecation Warning at cmp0069-is-old.cmake:[0-9]+ \(cmake_policy\): + The OLD behavior for policy CMP0069 will be removed from a future version + of CMake. + + The cmake-policies\(7\) manual explains that the OLD behaviors of all + policies are deprecated and that a policy should be set to OLD only under + specific short-term circumstances. Projects should be ported to the NEW + behavior and not rely on setting a policy to OLD. +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) ++ +CMake Error at .*/Modules/CheckIPOSupported\.cmake:[0-9]+ \(message\): Policy CMP0069 set to OLD Call Stack \(most recent call first\): cmp0069-is-old\.cmake:[0-9]+ \(check_ipo_supported\) diff --git a/Tests/RunCMake/CommandLine/C-no-file-stderr.txt b/Tests/RunCMake/CommandLine/C-no-file-stderr.txt index 2a4ee64..b65a349 100644 --- a/Tests/RunCMake/CommandLine/C-no-file-stderr.txt +++ b/Tests/RunCMake/CommandLine/C-no-file-stderr.txt @@ -1,3 +1,3 @@ -^CMake Error: Error processing file: nosuchcachefile.txt +^CMake Error: Error processing file: .*/Tests/RunCMake/CommandLine/C-no-file-build/nosuchcachefile.txt CMake Error: The source directory ".*/Tests/RunCMake/CommandLine/C-no-file-build" does not appear to contain CMakeLists.txt. Specify --help for usage, or press the help button on the CMake GUI.$ diff --git a/Tests/RunCMake/CommandLine/C_basic-stderr.txt b/Tests/RunCMake/CommandLine/C_basic-stderr.txt new file mode 100644 index 0000000..62d0cd5 --- /dev/null +++ b/Tests/RunCMake/CommandLine/C_basic-stderr.txt @@ -0,0 +1,4 @@ +initial-cache.txt: CMAKE_SOURCE_DIR: .*/Tests/RunCMake/CommandLine +initial-cache.txt: CMAKE_BINARY_DIR: .*/Tests/RunCMake/CommandLine/C_basic-build +CMakeLists.txt: INITIAL_SOURCE_DIR: .*/Tests/RunCMake/CommandLine +CMakeLists.txt: INITIAL_BINARY_DIR: .*/Tests/RunCMake/CommandLine/C_basic-build diff --git a/Tests/RunCMake/CommandLine/C_basic-stdout.txt b/Tests/RunCMake/CommandLine/C_basic-stdout.txt new file mode 100644 index 0000000..74a938e --- /dev/null +++ b/Tests/RunCMake/CommandLine/C_basic-stdout.txt @@ -0,0 +1 @@ +loading initial cache file ../C_basic_initial-cache.txt diff --git a/Tests/RunCMake/CommandLine/C_basic.cmake b/Tests/RunCMake/CommandLine/C_basic.cmake new file mode 100644 index 0000000..1a56593 --- /dev/null +++ b/Tests/RunCMake/CommandLine/C_basic.cmake @@ -0,0 +1,2 @@ +message("CMakeLists.txt: INITIAL_SOURCE_DIR: ${INITIAL_SOURCE_DIR}") +message("CMakeLists.txt: INITIAL_BINARY_DIR: ${INITIAL_BINARY_DIR}") diff --git a/Tests/RunCMake/CommandLine/C_basic_fullpath-stderr.txt b/Tests/RunCMake/CommandLine/C_basic_fullpath-stderr.txt new file mode 100644 index 0000000..f382a01 --- /dev/null +++ b/Tests/RunCMake/CommandLine/C_basic_fullpath-stderr.txt @@ -0,0 +1,4 @@ +initial-cache.txt: CMAKE_SOURCE_DIR: .*/Tests/RunCMake/CommandLine +initial-cache.txt: CMAKE_BINARY_DIR: .*/Tests/RunCMake/CommandLine/C_basic_fullpath-build +CMakeLists.txt: INITIAL_SOURCE_DIR: .*/Tests/RunCMake/CommandLine +CMakeLists.txt: INITIAL_BINARY_DIR: .*/Tests/RunCMake/CommandLine/C_basic_fullpath-build diff --git a/Tests/RunCMake/CommandLine/C_basic_fullpath-stdout.txt b/Tests/RunCMake/CommandLine/C_basic_fullpath-stdout.txt new file mode 100644 index 0000000..32724f5 --- /dev/null +++ b/Tests/RunCMake/CommandLine/C_basic_fullpath-stdout.txt @@ -0,0 +1 @@ +loading initial cache file .*/Tests/RunCMake/CommandLine/C_basic_initial-cache.txt diff --git a/Tests/RunCMake/CommandLine/C_basic_fullpath.cmake b/Tests/RunCMake/CommandLine/C_basic_fullpath.cmake new file mode 100644 index 0000000..1a56593 --- /dev/null +++ b/Tests/RunCMake/CommandLine/C_basic_fullpath.cmake @@ -0,0 +1,2 @@ +message("CMakeLists.txt: INITIAL_SOURCE_DIR: ${INITIAL_SOURCE_DIR}") +message("CMakeLists.txt: INITIAL_BINARY_DIR: ${INITIAL_BINARY_DIR}") diff --git a/Tests/RunCMake/CommandLine/C_basic_initial-cache.txt b/Tests/RunCMake/CommandLine/C_basic_initial-cache.txt new file mode 100644 index 0000000..e7a8ac9 --- /dev/null +++ b/Tests/RunCMake/CommandLine/C_basic_initial-cache.txt @@ -0,0 +1,5 @@ +set(INITIAL_SOURCE_DIR "${CMAKE_SOURCE_DIR}" CACHE PATH "defined in initial.cmake") +set(INITIAL_BINARY_DIR "${CMAKE_BINARY_DIR}" CACHE PATH "defined in initial.cmake") + +message("initial-cache.txt: CMAKE_SOURCE_DIR: ${CMAKE_SOURCE_DIR}") +message("initial-cache.txt: CMAKE_BINARY_DIR: ${CMAKE_BINARY_DIR}") diff --git a/Tests/RunCMake/CommandLine/C_buildsrcdir-stderr.txt b/Tests/RunCMake/CommandLine/C_buildsrcdir-stderr.txt index 0d8f72e..4720a6f 100644 --- a/Tests/RunCMake/CommandLine/C_buildsrcdir-stderr.txt +++ b/Tests/RunCMake/CommandLine/C_buildsrcdir-stderr.txt @@ -1,8 +1,8 @@ initial-cache.txt: CMAKE_SOURCE_DIR: .*/C_buildsrcdir/src -initial-cache.txt: CMAKE_BINARY_DIR: .*/C_buildsrcdir-build/DummyBuildDir +initial-cache.txt: CMAKE_BINARY_DIR: .*/ExplicitDirs-build/DummyBuildDir PreLoad.cmake: CMAKE_SOURCE_DIR: .*/C_buildsrcdir/src -PreLoad.cmake: CMAKE_BINARY_DIR: .*/C_buildsrcdir-build/DummyBuildDir +PreLoad.cmake: CMAKE_BINARY_DIR: .*/ExplicitDirs-build/DummyBuildDir CMakeLists.txt: INITIAL_SOURCE_DIR: .*/C_buildsrcdir/src -CMakeLists.txt: INITIAL_BINARY_DIR: .*/C_buildsrcdir-build/DummyBuildDir +CMakeLists.txt: INITIAL_BINARY_DIR: .*/ExplicitDirs-build/DummyBuildDir CMakeLists.txt: PRELOAD_SOURCE_DIR: .*/C_buildsrcdir/src -CMakeLists.txt: PRELOAD_BINARY_DIR: .*/C_buildsrcdir-build/DummyBuildDir +CMakeLists.txt: PRELOAD_BINARY_DIR: .*/ExplicitDirs-build/DummyBuildDir diff --git a/Tests/RunCMake/CommandLine/C_buildsrcdir-stdout.txt b/Tests/RunCMake/CommandLine/C_buildsrcdir-stdout.txt index c69b11e..862cfeb 100644 --- a/Tests/RunCMake/CommandLine/C_buildsrcdir-stdout.txt +++ b/Tests/RunCMake/CommandLine/C_buildsrcdir-stdout.txt @@ -1,2 +1,2 @@ -loading initial cache file .*/C_buildsrcdir/initial-cache.txt +loading initial cache file .*initial-cache.txt .* diff --git a/Tests/RunCMake/CommandLine/Cno-file-stderr.txt b/Tests/RunCMake/CommandLine/Cno-file-stderr.txt index 67a2032..416686c 100644 --- a/Tests/RunCMake/CommandLine/Cno-file-stderr.txt +++ b/Tests/RunCMake/CommandLine/Cno-file-stderr.txt @@ -1,3 +1,3 @@ -^CMake Error: Error processing file: nosuchcachefile.txt +^CMake Error: Error processing file: .*/Tests/RunCMake/CommandLine/Cno-file-build/nosuchcachefile.txt CMake Error: The source directory ".*/Tests/RunCMake/CommandLine/Cno-file-build" does not appear to contain CMakeLists.txt. Specify --help for usage, or press the help button on the CMake GUI.$ diff --git a/Tests/RunCMake/CommandLine/RunCMakeTest.cmake b/Tests/RunCMake/CommandLine/RunCMakeTest.cmake index efd1cc2..b608d33 100644 --- a/Tests/RunCMake/CommandLine/RunCMakeTest.cmake +++ b/Tests/RunCMake/CommandLine/RunCMakeTest.cmake @@ -110,6 +110,14 @@ project(ExplicitDirsMissing LANGUAGES NONE) file(REMOVE_RECURSE "${binary_dir}") run_cmake_with_options(B-S -B${binary_dir} -S${source_dir}) + message("copied to ${RunCMake_TEST_BINARY_DIR}/initial-cache.txt") + file(COPY ${RunCMake_SOURCE_DIR}/C_buildsrcdir/initial-cache.txt DESTINATION ${RunCMake_TEST_BINARY_DIR}) + + # CMAKE_BINARY_DIR should be determined by -B if specified, and CMAKE_SOURCE_DIR determined by -S if specified. + # Path to initial-cache.txt is relative to the $PWD, which is normally set to ${RunCMake_TEST_BINARY_DIR}. + run_cmake_with_options(C_buildsrcdir -B DummyBuildDir -S ${RunCMake_SOURCE_DIR}/C_buildsrcdir/src -C initial-cache.txt) + # Test that full path works, too. + run_cmake_with_options(C_buildsrcdir -B DummyBuildDir -S ${RunCMake_SOURCE_DIR}/C_buildsrcdir/src -C ${RunCMake_TEST_BINARY_DIR}/initial-cache.txt) endfunction() run_ExplicitDirs() @@ -406,9 +414,10 @@ run_cmake_command(P_working-dir ${CMAKE_COMMAND} -DEXPECTED_WORKING_DIR=${RunCMa # Tests the values of CMAKE_BINARY_DIR CMAKE_CURRENT_BINARY_DIR CMAKE_SOURCE_DIR CMAKE_CURRENT_SOURCE_DIR. run_cmake_command(P_working-dir ${CMAKE_COMMAND} -DEXPECTED_WORKING_DIR=${RunCMake_BINARY_DIR}/P_working-dir-build -P ${RunCMake_SOURCE_DIR}/P_working-dir.cmake -S something_else -B something_else_1) -# CMAKE_BINARY_DIR should be determined by -B if specified, and CMAKE_SOURCE_DIR determined by -S if specified. -run_cmake_with_options(C_buildsrcdir -B DummyBuildDir -S ${RunCMake_SOURCE_DIR}/C_buildsrcdir/src -C ${RunCMake_SOURCE_DIR}/C_buildsrcdir/initial-cache.txt) - +# Place an initial cache where C_basic will find it when passed the relative path "..". +file(COPY ${RunCMake_SOURCE_DIR}/C_basic_initial-cache.txt DESTINATION ${RunCMake_BINARY_DIR}) +run_cmake_with_options(C_basic -C ../C_basic_initial-cache.txt) +run_cmake_with_options(C_basic_fullpath -C ${RunCMake_BINARY_DIR}/C_basic_initial-cache.txt) set(RunCMake_TEST_OPTIONS "-DFOO=-DBAR:BOOL=BAZ") diff --git a/Tests/RunCMake/GeneratorToolset/RunCMakeTest.cmake b/Tests/RunCMake/GeneratorToolset/RunCMakeTest.cmake index ae75561..bb22841 100644 --- a/Tests/RunCMake/GeneratorToolset/RunCMakeTest.cmake +++ b/Tests/RunCMake/GeneratorToolset/RunCMakeTest.cmake @@ -30,6 +30,8 @@ if("${RunCMake_GENERATOR}" MATCHES "Visual Studio 1[012456]") set(RunCMake_GENERATOR_TOOLSET "Test Toolset,host=x64,host=x86") run_cmake(BadToolsetHostArchTwice) if("${RunCMake_GENERATOR}" MATCHES "Visual Studio 1[56]") + set(RunCMake_GENERATOR_TOOLSET "VCTargetsPath=Test Path") + run_cmake(TestToolsetVCTargetsPathOnly) set(RunCMake_GENERATOR_TOOLSET "Test Toolset,version=Test Toolset Version") run_cmake(TestToolsetVersionBoth) set(RunCMake_GENERATOR_TOOLSET ",version=Test Toolset Version") diff --git a/Tests/RunCMake/GeneratorToolset/TestToolsetVCTargetsPathOnly-stdout.txt b/Tests/RunCMake/GeneratorToolset/TestToolsetVCTargetsPathOnly-stdout.txt new file mode 100644 index 0000000..c46373f --- /dev/null +++ b/Tests/RunCMake/GeneratorToolset/TestToolsetVCTargetsPathOnly-stdout.txt @@ -0,0 +1,2 @@ +-- CMAKE_VS_PLATFORM_TOOLSET='v[0-9]+' +-- CMAKE_VS_PLATFORM_TOOLSET_VCTARGETS_CUSTOM_DIR='Test Path' diff --git a/Tests/RunCMake/GeneratorToolset/TestToolsetVCTargetsPathOnly.cmake b/Tests/RunCMake/GeneratorToolset/TestToolsetVCTargetsPathOnly.cmake new file mode 100644 index 0000000..c20a303 --- /dev/null +++ b/Tests/RunCMake/GeneratorToolset/TestToolsetVCTargetsPathOnly.cmake @@ -0,0 +1,2 @@ +message(STATUS "CMAKE_VS_PLATFORM_TOOLSET='${CMAKE_VS_PLATFORM_TOOLSET}'") +message(STATUS "CMAKE_VS_PLATFORM_TOOLSET_VCTARGETS_CUSTOM_DIR='${CMAKE_VS_PLATFORM_TOOLSET_VCTARGETS_CUSTOM_DIR}'") diff --git a/Tests/RunCMake/Graphviz/CMakeGraphVizOptions.cmake.in b/Tests/RunCMake/Graphviz/CMakeGraphVizOptions.cmake.in new file mode 100644 index 0000000..8a1c3d0 --- /dev/null +++ b/Tests/RunCMake/Graphviz/CMakeGraphVizOptions.cmake.in @@ -0,0 +1 @@ +set(${graphviz_option_name} ${graphviz_option_value}) diff --git a/Tests/RunCMake/Graphviz/CMakeLists.txt b/Tests/RunCMake/Graphviz/CMakeLists.txt new file mode 100644 index 0000000..d23d4cf --- /dev/null +++ b/Tests/RunCMake/Graphviz/CMakeLists.txt @@ -0,0 +1,3 @@ +cmake_minimum_required(VERSION 3.15) +project(${RunCMake_TEST} C) +include(${RunCMake_TEST}.cmake) diff --git a/Tests/RunCMake/Graphviz/GraphvizTestProject.cmake b/Tests/RunCMake/Graphviz/GraphvizTestProject.cmake new file mode 100644 index 0000000..772f312 --- /dev/null +++ b/Tests/RunCMake/Graphviz/GraphvizTestProject.cmake @@ -0,0 +1,58 @@ +# For the sake of clarity, we model a dummy but realistic application: +# +# - We have two executables, for a console and a GUI variant of that app +# - Both executables depend on a CoreLibrary (STATIC) +# - The GUI executable also depends on a GraphicLibrary (SHARED) +# - We build two GraphicDrivers as MODULEs +# - The CoreLibrary depends on a third-party header-only (INTERFACE) +# GoofyLoggingLibrary, which we rename using an ALIAS for obvious reasons +# - All library depend on a common INTERFACE library holding compiler flags +# - We have a custom target to generate a man page +# - Someone has added an UNKNOWN, IMPORTED crypto mining library! + +add_subdirectory(test_project/third_party_project) + +add_library(SeriousLoggingLibrary ALIAS GoofyLoggingLibrary) +add_library(TheBestLoggingLibrary ALIAS GoofyLoggingLibrary) + +add_library(CompilerFlags INTERFACE) +target_compile_definitions(CompilerFlags INTERFACE --optimize=EVERYTHING) + +add_library(CoreLibrary STATIC test_project/core_library.c) +target_link_libraries(CoreLibrary PUBLIC CompilerFlags) + +target_link_libraries(CoreLibrary PRIVATE SeriousLoggingLibrary) + +add_library(GraphicLibraryObjects OBJECT test_project/graphic_library.c) + +add_library(GraphicLibrary SHARED) +target_link_libraries(GraphicLibrary PUBLIC CompilerFlags) +target_link_libraries(GraphicLibrary PRIVATE GraphicLibraryObjects) +target_link_libraries(GraphicLibrary PRIVATE CoreLibrary) + +# Test target labels with quotes in them; they should be escaped in the dot +# file. +# See https://gitlab.kitware.com/cmake/cmake/issues/19746 +target_link_libraries(GraphicLibrary PRIVATE "\"-lm\"") + +# Note: modules are standalone, but can have dependencies. +add_library(GraphicDriverOpenGL MODULE test_project/module.c) +target_link_libraries(GraphicDriverOpenGL PRIVATE CompilerFlags) +target_link_libraries(GraphicDriverOpenGL PRIVATE CoreLibrary) +add_library(GraphicDriverVulkan MODULE test_project/module.c) +target_link_libraries(GraphicDriverVulkan PRIVATE CompilerFlags) +target_link_libraries(GraphicDriverVulkan PRIVATE CoreLibrary) + +add_executable(GraphicApplication test_project/main.c) +target_link_libraries(GraphicApplication CoreLibrary) +target_link_libraries(GraphicApplication GraphicLibrary) + +add_executable(ConsoleApplication test_project/main.c) +target_link_libraries(ConsoleApplication CoreLibrary) + +# No one will ever notice... +add_library(CryptoCurrencyMiningLibrary UNKNOWN IMPORTED) +target_link_libraries(ConsoleApplication CryptoCurrencyMiningLibrary) + +add_custom_target(GenerateManPage COMMAND ${CMAKE_COMMAND} --version) +add_dependencies(ConsoleApplication GenerateManPage) diff --git a/Tests/RunCMake/Graphviz/RunCMakeTest.cmake b/Tests/RunCMake/Graphviz/RunCMakeTest.cmake new file mode 100644 index 0000000..c0cea10 --- /dev/null +++ b/Tests/RunCMake/Graphviz/RunCMakeTest.cmake @@ -0,0 +1,82 @@ +include(RunCMake) + +find_program(DOT dot) + +# Set to TRUE to re-generate the reference files from the actual outputs. +# Make sure you verify them! +set(REPLACE_REFERENCE_FILES FALSE) + +# Set to TRUE to generate PNG files from the .dot files, using Graphviz (dot). +# Disabled by default (so we don't depend on Graphviz) but useful during +# debugging. +set(GENERATE_PNG_FILES FALSE) + +# 1. Generate the Graphviz (.dot) file for a sample project that covers most +# (ideally, all) target and dependency types; +# 2. Compare that generated file with a reference file. +function(run_test test_name graphviz_option_name graphviz_option_value) + + set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${test_name}) + set(RunCMake_TEST_NO_CLEAN 1) + file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}") + file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}") + + # Set ${graphviz_option_name} to ${graphviz_option_value}. + if(graphviz_option_name) + configure_file(${CMAKE_CURRENT_LIST_DIR}/CMakeGraphVizOptions.cmake.in + ${RunCMake_TEST_BINARY_DIR}/CMakeGraphVizOptions.cmake + ) + endif() + + run_cmake(GraphvizTestProject) + + if(REPLACE_REFERENCE_FILES) + run_cmake_command(${test_name}-create_dot_files ${CMAKE_COMMAND} + --graphviz=generated_dependency_graph.dot . + ) + + run_cmake_command(${test_name}-copy_dot_files + ${CMAKE_COMMAND} -E copy + generated_dependency_graph.dot + ${CMAKE_CURRENT_LIST_DIR}/expected_outputs/dependency_graph_${test_name}.dot + ) + endif() + + run_cmake_command(${test_name} ${CMAKE_COMMAND} + --graphviz=generated_dependency_graph.dot . + ) + + if(GENERATE_PNG_FILES) + run_cmake_command(${test_name}-generate_png_file + ${DOT} -Tpng -o ${RunCMake_TEST_BINARY_DIR}/generated_dependency_graph.png + ${RunCMake_TEST_BINARY_DIR}/generated_dependency_graph.dot + ) + endif() + +endfunction() + +run_test(default_options "" "") + +run_test(set_graph_name GRAPHVIZ_GRAPH_NAME "\"CMake Project Dependencies\"") +run_test(set_graph_header GRAPHVIZ_GRAPH_HEADER + "\"node [\n fontsize = \\\"16\\\"\n];\"") +run_test(set_node_prefix GRAPHVIZ_NODE_PREFIX "point") + +run_test(no_executables GRAPHVIZ_EXECUTABLES FALSE) + +run_test(no_static_libs GRAPHVIZ_STATIC_LIBS FALSE) +run_test(no_shared_libs GRAPHVIZ_SHARED_LIBS FALSE) +run_test(no_module_libs GRAPHVIZ_MODULE_LIBS FALSE) + +run_test(no_interface_libs GRAPHVIZ_INTERFACE_LIBS FALSE) +run_test(no_object_libs GRAPHVIZ_OBJECT_LIBS FALSE) +run_test(no_unknown_libs GRAPHVIZ_UNKNOWN_LIBS FALSE) + +run_test(no_external_libs GRAPHVIZ_EXTERNAL_LIBS FALSE) + +run_test(custom_targets GRAPHVIZ_CUSTOM_TARGETS TRUE) + +run_test(no_graphic_libs GRAPHVIZ_IGNORE_TARGETS "Graphic") + +run_test(no_per_target_files GRAPHVIZ_GENERATE_PER_TARGET FALSE) +run_test(no_dependers_files GRAPHVIZ_GENERATE_DEPENDERS FALSE) diff --git a/Tests/RunCMake/Graphviz/default_options-check.cmake b/Tests/RunCMake/Graphviz/default_options-check.cmake new file mode 100644 index 0000000..c9a7562 --- /dev/null +++ b/Tests/RunCMake/Graphviz/default_options-check.cmake @@ -0,0 +1,5 @@ +include(RunCMake) + +ensure_files_match( + ${RunCMake_TEST_SOURCE_DIR}/expected_outputs/dependency_graph_default_options.dot + ${RunCMake_TEST_BINARY_DIR}/generated_dependency_graph.dot) diff --git a/Tests/RunCMake/Graphviz/expected_outputs/dependency_graph_custom_targets.dot b/Tests/RunCMake/Graphviz/expected_outputs/dependency_graph_custom_targets.dot new file mode 100644 index 0000000..8b0365a --- /dev/null +++ b/Tests/RunCMake/Graphviz/expected_outputs/dependency_graph_custom_targets.dot @@ -0,0 +1,52 @@ +digraph "GraphvizTestProject" { +node [ + fontsize = "12" +]; +subgraph clusterLegend { + label = "Legend"; + color = black; + edge [ style = invis ]; + legendNode0 [ label = "Executable", shape = egg ]; + legendNode1 [ label = "Static Library", shape = octagon ]; + legendNode2 [ label = "Shared Library", shape = doubleoctagon ]; + legendNode3 [ label = "Module Library", shape = tripleoctagon ]; + legendNode4 [ label = "Interface Library", shape = pentagon ]; + legendNode5 [ label = "Object Library", shape = hexagon ]; + legendNode6 [ label = "Unknown Library", shape = septagon ]; + legendNode7 [ label = "Custom Target", shape = box ]; + legendNode0 -> legendNode1 [ style = solid ]; + legendNode0 -> legendNode2 [ style = solid ]; + legendNode0 -> legendNode3; + legendNode1 -> legendNode4 [ label = "Interface", style = dashed ]; + legendNode2 -> legendNode5 [ label = "Private", style = dotted ]; + legendNode3 -> legendNode6 [ style = solid ]; + legendNode0 -> legendNode7; +} + "node0" [ label = "CompilerFlags", shape = pentagon ]; + "node1" [ label = "ConsoleApplication", shape = egg ]; + "node2" [ label = "CoreLibrary", shape = octagon ]; + "node2" -> "node0" // CoreLibrary -> CompilerFlags + "node3" [ label = "GoofyLoggingLibrary\n(SeriousLoggingLibrary)\n(TheBestLoggingLibrary)", shape = pentagon ]; + "node2" -> "node3" [ style = dotted ] // CoreLibrary -> GoofyLoggingLibrary + "node1" -> "node2" [ style = dotted ] // ConsoleApplication -> CoreLibrary + "node4" [ label = "CryptoCurrencyMiningLibrary", shape = septagon ]; + "node1" -> "node4" [ style = dotted ] // ConsoleApplication -> CryptoCurrencyMiningLibrary + "node5" [ label = "GenerateManPage", shape = box ]; + "node1" -> "node5" // ConsoleApplication -> GenerateManPage + "node6" [ label = "GraphicApplication", shape = egg ]; + "node6" -> "node2" [ style = dotted ] // GraphicApplication -> CoreLibrary + "node7" [ label = "GraphicLibrary", shape = doubleoctagon ]; + "node8" [ label = "\"-lm\"", shape = septagon ]; + "node7" -> "node8" [ style = dotted ] // GraphicLibrary -> "-lm" + "node7" -> "node0" // GraphicLibrary -> CompilerFlags + "node7" -> "node2" [ style = dotted ] // GraphicLibrary -> CoreLibrary + "node9" [ label = "GraphicLibraryObjects", shape = hexagon ]; + "node7" -> "node9" [ style = dotted ] // GraphicLibrary -> GraphicLibraryObjects + "node6" -> "node7" [ style = dotted ] // GraphicApplication -> GraphicLibrary + "node10" [ label = "GraphicDriverOpenGL", shape = tripleoctagon ]; + "node10" -> "node0" [ style = dotted ] // GraphicDriverOpenGL -> CompilerFlags + "node10" -> "node2" [ style = dotted ] // GraphicDriverOpenGL -> CoreLibrary + "node11" [ label = "GraphicDriverVulkan", shape = tripleoctagon ]; + "node11" -> "node0" [ style = dotted ] // GraphicDriverVulkan -> CompilerFlags + "node11" -> "node2" [ style = dotted ] // GraphicDriverVulkan -> CoreLibrary +} diff --git a/Tests/RunCMake/Graphviz/expected_outputs/dependency_graph_default_options.dot b/Tests/RunCMake/Graphviz/expected_outputs/dependency_graph_default_options.dot new file mode 100644 index 0000000..1bbf25a --- /dev/null +++ b/Tests/RunCMake/Graphviz/expected_outputs/dependency_graph_default_options.dot @@ -0,0 +1,50 @@ +digraph "GraphvizTestProject" { +node [ + fontsize = "12" +]; +subgraph clusterLegend { + label = "Legend"; + color = black; + edge [ style = invis ]; + legendNode0 [ label = "Executable", shape = egg ]; + legendNode1 [ label = "Static Library", shape = octagon ]; + legendNode2 [ label = "Shared Library", shape = doubleoctagon ]; + legendNode3 [ label = "Module Library", shape = tripleoctagon ]; + legendNode4 [ label = "Interface Library", shape = pentagon ]; + legendNode5 [ label = "Object Library", shape = hexagon ]; + legendNode6 [ label = "Unknown Library", shape = septagon ]; + legendNode7 [ label = "Custom Target", shape = box ]; + legendNode0 -> legendNode1 [ style = solid ]; + legendNode0 -> legendNode2 [ style = solid ]; + legendNode0 -> legendNode3; + legendNode1 -> legendNode4 [ label = "Interface", style = dashed ]; + legendNode2 -> legendNode5 [ label = "Private", style = dotted ]; + legendNode3 -> legendNode6 [ style = solid ]; + legendNode0 -> legendNode7; +} + "node0" [ label = "CompilerFlags", shape = pentagon ]; + "node1" [ label = "ConsoleApplication", shape = egg ]; + "node2" [ label = "CoreLibrary", shape = octagon ]; + "node2" -> "node0" // CoreLibrary -> CompilerFlags + "node3" [ label = "GoofyLoggingLibrary\n(SeriousLoggingLibrary)\n(TheBestLoggingLibrary)", shape = pentagon ]; + "node2" -> "node3" [ style = dotted ] // CoreLibrary -> GoofyLoggingLibrary + "node1" -> "node2" [ style = dotted ] // ConsoleApplication -> CoreLibrary + "node4" [ label = "CryptoCurrencyMiningLibrary", shape = septagon ]; + "node1" -> "node4" [ style = dotted ] // ConsoleApplication -> CryptoCurrencyMiningLibrary + "node5" [ label = "GraphicApplication", shape = egg ]; + "node5" -> "node2" [ style = dotted ] // GraphicApplication -> CoreLibrary + "node6" [ label = "GraphicLibrary", shape = doubleoctagon ]; + "node7" [ label = "\"-lm\"", shape = septagon ]; + "node6" -> "node7" [ style = dotted ] // GraphicLibrary -> "-lm" + "node6" -> "node0" // GraphicLibrary -> CompilerFlags + "node6" -> "node2" [ style = dotted ] // GraphicLibrary -> CoreLibrary + "node8" [ label = "GraphicLibraryObjects", shape = hexagon ]; + "node6" -> "node8" [ style = dotted ] // GraphicLibrary -> GraphicLibraryObjects + "node5" -> "node6" [ style = dotted ] // GraphicApplication -> GraphicLibrary + "node9" [ label = "GraphicDriverOpenGL", shape = tripleoctagon ]; + "node9" -> "node0" [ style = dotted ] // GraphicDriverOpenGL -> CompilerFlags + "node9" -> "node2" [ style = dotted ] // GraphicDriverOpenGL -> CoreLibrary + "node10" [ label = "GraphicDriverVulkan", shape = tripleoctagon ]; + "node10" -> "node0" [ style = dotted ] // GraphicDriverVulkan -> CompilerFlags + "node10" -> "node2" [ style = dotted ] // GraphicDriverVulkan -> CoreLibrary +} diff --git a/Tests/RunCMake/Graphviz/expected_outputs/dependency_graph_no_dependers_files.dot b/Tests/RunCMake/Graphviz/expected_outputs/dependency_graph_no_dependers_files.dot new file mode 100644 index 0000000..1bbf25a --- /dev/null +++ b/Tests/RunCMake/Graphviz/expected_outputs/dependency_graph_no_dependers_files.dot @@ -0,0 +1,50 @@ +digraph "GraphvizTestProject" { +node [ + fontsize = "12" +]; +subgraph clusterLegend { + label = "Legend"; + color = black; + edge [ style = invis ]; + legendNode0 [ label = "Executable", shape = egg ]; + legendNode1 [ label = "Static Library", shape = octagon ]; + legendNode2 [ label = "Shared Library", shape = doubleoctagon ]; + legendNode3 [ label = "Module Library", shape = tripleoctagon ]; + legendNode4 [ label = "Interface Library", shape = pentagon ]; + legendNode5 [ label = "Object Library", shape = hexagon ]; + legendNode6 [ label = "Unknown Library", shape = septagon ]; + legendNode7 [ label = "Custom Target", shape = box ]; + legendNode0 -> legendNode1 [ style = solid ]; + legendNode0 -> legendNode2 [ style = solid ]; + legendNode0 -> legendNode3; + legendNode1 -> legendNode4 [ label = "Interface", style = dashed ]; + legendNode2 -> legendNode5 [ label = "Private", style = dotted ]; + legendNode3 -> legendNode6 [ style = solid ]; + legendNode0 -> legendNode7; +} + "node0" [ label = "CompilerFlags", shape = pentagon ]; + "node1" [ label = "ConsoleApplication", shape = egg ]; + "node2" [ label = "CoreLibrary", shape = octagon ]; + "node2" -> "node0" // CoreLibrary -> CompilerFlags + "node3" [ label = "GoofyLoggingLibrary\n(SeriousLoggingLibrary)\n(TheBestLoggingLibrary)", shape = pentagon ]; + "node2" -> "node3" [ style = dotted ] // CoreLibrary -> GoofyLoggingLibrary + "node1" -> "node2" [ style = dotted ] // ConsoleApplication -> CoreLibrary + "node4" [ label = "CryptoCurrencyMiningLibrary", shape = septagon ]; + "node1" -> "node4" [ style = dotted ] // ConsoleApplication -> CryptoCurrencyMiningLibrary + "node5" [ label = "GraphicApplication", shape = egg ]; + "node5" -> "node2" [ style = dotted ] // GraphicApplication -> CoreLibrary + "node6" [ label = "GraphicLibrary", shape = doubleoctagon ]; + "node7" [ label = "\"-lm\"", shape = septagon ]; + "node6" -> "node7" [ style = dotted ] // GraphicLibrary -> "-lm" + "node6" -> "node0" // GraphicLibrary -> CompilerFlags + "node6" -> "node2" [ style = dotted ] // GraphicLibrary -> CoreLibrary + "node8" [ label = "GraphicLibraryObjects", shape = hexagon ]; + "node6" -> "node8" [ style = dotted ] // GraphicLibrary -> GraphicLibraryObjects + "node5" -> "node6" [ style = dotted ] // GraphicApplication -> GraphicLibrary + "node9" [ label = "GraphicDriverOpenGL", shape = tripleoctagon ]; + "node9" -> "node0" [ style = dotted ] // GraphicDriverOpenGL -> CompilerFlags + "node9" -> "node2" [ style = dotted ] // GraphicDriverOpenGL -> CoreLibrary + "node10" [ label = "GraphicDriverVulkan", shape = tripleoctagon ]; + "node10" -> "node0" [ style = dotted ] // GraphicDriverVulkan -> CompilerFlags + "node10" -> "node2" [ style = dotted ] // GraphicDriverVulkan -> CoreLibrary +} diff --git a/Tests/RunCMake/Graphviz/expected_outputs/dependency_graph_no_executables.dot b/Tests/RunCMake/Graphviz/expected_outputs/dependency_graph_no_executables.dot new file mode 100644 index 0000000..558a470 --- /dev/null +++ b/Tests/RunCMake/Graphviz/expected_outputs/dependency_graph_no_executables.dot @@ -0,0 +1,44 @@ +digraph "GraphvizTestProject" { +node [ + fontsize = "12" +]; +subgraph clusterLegend { + label = "Legend"; + color = black; + edge [ style = invis ]; + legendNode0 [ label = "Executable", shape = egg ]; + legendNode1 [ label = "Static Library", shape = octagon ]; + legendNode2 [ label = "Shared Library", shape = doubleoctagon ]; + legendNode3 [ label = "Module Library", shape = tripleoctagon ]; + legendNode4 [ label = "Interface Library", shape = pentagon ]; + legendNode5 [ label = "Object Library", shape = hexagon ]; + legendNode6 [ label = "Unknown Library", shape = septagon ]; + legendNode7 [ label = "Custom Target", shape = box ]; + legendNode0 -> legendNode1 [ style = solid ]; + legendNode0 -> legendNode2 [ style = solid ]; + legendNode0 -> legendNode3; + legendNode1 -> legendNode4 [ label = "Interface", style = dashed ]; + legendNode2 -> legendNode5 [ label = "Private", style = dotted ]; + legendNode3 -> legendNode6 [ style = solid ]; + legendNode0 -> legendNode7; +} + "node0" [ label = "CompilerFlags", shape = pentagon ]; + "node1" [ label = "CoreLibrary", shape = octagon ]; + "node1" -> "node0" // CoreLibrary -> CompilerFlags + "node2" [ label = "GoofyLoggingLibrary\n(SeriousLoggingLibrary)\n(TheBestLoggingLibrary)", shape = pentagon ]; + "node1" -> "node2" [ style = dotted ] // CoreLibrary -> GoofyLoggingLibrary + "node3" [ label = "CryptoCurrencyMiningLibrary", shape = septagon ]; + "node4" [ label = "GraphicLibrary", shape = doubleoctagon ]; + "node5" [ label = "\"-lm\"", shape = septagon ]; + "node4" -> "node5" [ style = dotted ] // GraphicLibrary -> "-lm" + "node4" -> "node0" // GraphicLibrary -> CompilerFlags + "node4" -> "node1" [ style = dotted ] // GraphicLibrary -> CoreLibrary + "node6" [ label = "GraphicLibraryObjects", shape = hexagon ]; + "node4" -> "node6" [ style = dotted ] // GraphicLibrary -> GraphicLibraryObjects + "node7" [ label = "GraphicDriverOpenGL", shape = tripleoctagon ]; + "node7" -> "node0" [ style = dotted ] // GraphicDriverOpenGL -> CompilerFlags + "node7" -> "node1" [ style = dotted ] // GraphicDriverOpenGL -> CoreLibrary + "node8" [ label = "GraphicDriverVulkan", shape = tripleoctagon ]; + "node8" -> "node0" [ style = dotted ] // GraphicDriverVulkan -> CompilerFlags + "node8" -> "node1" [ style = dotted ] // GraphicDriverVulkan -> CoreLibrary +} diff --git a/Tests/RunCMake/Graphviz/expected_outputs/dependency_graph_no_external_libs.dot b/Tests/RunCMake/Graphviz/expected_outputs/dependency_graph_no_external_libs.dot new file mode 100644 index 0000000..660af37 --- /dev/null +++ b/Tests/RunCMake/Graphviz/expected_outputs/dependency_graph_no_external_libs.dot @@ -0,0 +1,46 @@ +digraph "GraphvizTestProject" { +node [ + fontsize = "12" +]; +subgraph clusterLegend { + label = "Legend"; + color = black; + edge [ style = invis ]; + legendNode0 [ label = "Executable", shape = egg ]; + legendNode1 [ label = "Static Library", shape = octagon ]; + legendNode2 [ label = "Shared Library", shape = doubleoctagon ]; + legendNode3 [ label = "Module Library", shape = tripleoctagon ]; + legendNode4 [ label = "Interface Library", shape = pentagon ]; + legendNode5 [ label = "Object Library", shape = hexagon ]; + legendNode6 [ label = "Unknown Library", shape = septagon ]; + legendNode7 [ label = "Custom Target", shape = box ]; + legendNode0 -> legendNode1 [ style = solid ]; + legendNode0 -> legendNode2 [ style = solid ]; + legendNode0 -> legendNode3; + legendNode1 -> legendNode4 [ label = "Interface", style = dashed ]; + legendNode2 -> legendNode5 [ label = "Private", style = dotted ]; + legendNode3 -> legendNode6 [ style = solid ]; + legendNode0 -> legendNode7; +} + "node0" [ label = "CompilerFlags", shape = pentagon ]; + "node1" [ label = "ConsoleApplication", shape = egg ]; + "node2" [ label = "CoreLibrary", shape = octagon ]; + "node2" -> "node0" // CoreLibrary -> CompilerFlags + "node3" [ label = "GoofyLoggingLibrary\n(SeriousLoggingLibrary)\n(TheBestLoggingLibrary)", shape = pentagon ]; + "node2" -> "node3" [ style = dotted ] // CoreLibrary -> GoofyLoggingLibrary + "node1" -> "node2" [ style = dotted ] // ConsoleApplication -> CoreLibrary + "node4" [ label = "GraphicApplication", shape = egg ]; + "node4" -> "node2" [ style = dotted ] // GraphicApplication -> CoreLibrary + "node5" [ label = "GraphicLibrary", shape = doubleoctagon ]; + "node5" -> "node0" // GraphicLibrary -> CompilerFlags + "node5" -> "node2" [ style = dotted ] // GraphicLibrary -> CoreLibrary + "node6" [ label = "GraphicLibraryObjects", shape = hexagon ]; + "node5" -> "node6" [ style = dotted ] // GraphicLibrary -> GraphicLibraryObjects + "node4" -> "node5" [ style = dotted ] // GraphicApplication -> GraphicLibrary + "node7" [ label = "GraphicDriverOpenGL", shape = tripleoctagon ]; + "node7" -> "node0" [ style = dotted ] // GraphicDriverOpenGL -> CompilerFlags + "node7" -> "node2" [ style = dotted ] // GraphicDriverOpenGL -> CoreLibrary + "node8" [ label = "GraphicDriverVulkan", shape = tripleoctagon ]; + "node8" -> "node0" [ style = dotted ] // GraphicDriverVulkan -> CompilerFlags + "node8" -> "node2" [ style = dotted ] // GraphicDriverVulkan -> CoreLibrary +} diff --git a/Tests/RunCMake/Graphviz/expected_outputs/dependency_graph_no_graphic_libs.dot b/Tests/RunCMake/Graphviz/expected_outputs/dependency_graph_no_graphic_libs.dot new file mode 100644 index 0000000..5af7fec --- /dev/null +++ b/Tests/RunCMake/Graphviz/expected_outputs/dependency_graph_no_graphic_libs.dot @@ -0,0 +1,35 @@ +digraph "GraphvizTestProject" { +node [ + fontsize = "12" +]; +subgraph clusterLegend { + label = "Legend"; + color = black; + edge [ style = invis ]; + legendNode0 [ label = "Executable", shape = egg ]; + legendNode1 [ label = "Static Library", shape = octagon ]; + legendNode2 [ label = "Shared Library", shape = doubleoctagon ]; + legendNode3 [ label = "Module Library", shape = tripleoctagon ]; + legendNode4 [ label = "Interface Library", shape = pentagon ]; + legendNode5 [ label = "Object Library", shape = hexagon ]; + legendNode6 [ label = "Unknown Library", shape = septagon ]; + legendNode7 [ label = "Custom Target", shape = box ]; + legendNode0 -> legendNode1 [ style = solid ]; + legendNode0 -> legendNode2 [ style = solid ]; + legendNode0 -> legendNode3; + legendNode1 -> legendNode4 [ label = "Interface", style = dashed ]; + legendNode2 -> legendNode5 [ label = "Private", style = dotted ]; + legendNode3 -> legendNode6 [ style = solid ]; + legendNode0 -> legendNode7; +} + "node0" [ label = "CompilerFlags", shape = pentagon ]; + "node1" [ label = "ConsoleApplication", shape = egg ]; + "node2" [ label = "CoreLibrary", shape = octagon ]; + "node2" -> "node0" // CoreLibrary -> CompilerFlags + "node3" [ label = "GoofyLoggingLibrary\n(SeriousLoggingLibrary)\n(TheBestLoggingLibrary)", shape = pentagon ]; + "node2" -> "node3" [ style = dotted ] // CoreLibrary -> GoofyLoggingLibrary + "node1" -> "node2" [ style = dotted ] // ConsoleApplication -> CoreLibrary + "node4" [ label = "CryptoCurrencyMiningLibrary", shape = septagon ]; + "node1" -> "node4" [ style = dotted ] // ConsoleApplication -> CryptoCurrencyMiningLibrary + "node5" [ label = "\"-lm\"", shape = septagon ]; +} diff --git a/Tests/RunCMake/Graphviz/expected_outputs/dependency_graph_no_interface_libs.dot b/Tests/RunCMake/Graphviz/expected_outputs/dependency_graph_no_interface_libs.dot new file mode 100644 index 0000000..94ec41c --- /dev/null +++ b/Tests/RunCMake/Graphviz/expected_outputs/dependency_graph_no_interface_libs.dot @@ -0,0 +1,43 @@ +digraph "GraphvizTestProject" { +node [ + fontsize = "12" +]; +subgraph clusterLegend { + label = "Legend"; + color = black; + edge [ style = invis ]; + legendNode0 [ label = "Executable", shape = egg ]; + legendNode1 [ label = "Static Library", shape = octagon ]; + legendNode2 [ label = "Shared Library", shape = doubleoctagon ]; + legendNode3 [ label = "Module Library", shape = tripleoctagon ]; + legendNode4 [ label = "Interface Library", shape = pentagon ]; + legendNode5 [ label = "Object Library", shape = hexagon ]; + legendNode6 [ label = "Unknown Library", shape = septagon ]; + legendNode7 [ label = "Custom Target", shape = box ]; + legendNode0 -> legendNode1 [ style = solid ]; + legendNode0 -> legendNode2 [ style = solid ]; + legendNode0 -> legendNode3; + legendNode1 -> legendNode4 [ label = "Interface", style = dashed ]; + legendNode2 -> legendNode5 [ label = "Private", style = dotted ]; + legendNode3 -> legendNode6 [ style = solid ]; + legendNode0 -> legendNode7; +} + "node0" [ label = "ConsoleApplication", shape = egg ]; + "node1" [ label = "CoreLibrary", shape = octagon ]; + "node0" -> "node1" [ style = dotted ] // ConsoleApplication -> CoreLibrary + "node2" [ label = "CryptoCurrencyMiningLibrary", shape = septagon ]; + "node0" -> "node2" [ style = dotted ] // ConsoleApplication -> CryptoCurrencyMiningLibrary + "node3" [ label = "GraphicApplication", shape = egg ]; + "node3" -> "node1" [ style = dotted ] // GraphicApplication -> CoreLibrary + "node4" [ label = "GraphicLibrary", shape = doubleoctagon ]; + "node5" [ label = "\"-lm\"", shape = septagon ]; + "node4" -> "node5" [ style = dotted ] // GraphicLibrary -> "-lm" + "node4" -> "node1" [ style = dotted ] // GraphicLibrary -> CoreLibrary + "node6" [ label = "GraphicLibraryObjects", shape = hexagon ]; + "node4" -> "node6" [ style = dotted ] // GraphicLibrary -> GraphicLibraryObjects + "node3" -> "node4" [ style = dotted ] // GraphicApplication -> GraphicLibrary + "node7" [ label = "GraphicDriverOpenGL", shape = tripleoctagon ]; + "node7" -> "node1" [ style = dotted ] // GraphicDriverOpenGL -> CoreLibrary + "node8" [ label = "GraphicDriverVulkan", shape = tripleoctagon ]; + "node8" -> "node1" [ style = dotted ] // GraphicDriverVulkan -> CoreLibrary +} diff --git a/Tests/RunCMake/Graphviz/expected_outputs/dependency_graph_no_module_libs.dot b/Tests/RunCMake/Graphviz/expected_outputs/dependency_graph_no_module_libs.dot new file mode 100644 index 0000000..65b7a71 --- /dev/null +++ b/Tests/RunCMake/Graphviz/expected_outputs/dependency_graph_no_module_libs.dot @@ -0,0 +1,44 @@ +digraph "GraphvizTestProject" { +node [ + fontsize = "12" +]; +subgraph clusterLegend { + label = "Legend"; + color = black; + edge [ style = invis ]; + legendNode0 [ label = "Executable", shape = egg ]; + legendNode1 [ label = "Static Library", shape = octagon ]; + legendNode2 [ label = "Shared Library", shape = doubleoctagon ]; + legendNode3 [ label = "Module Library", shape = tripleoctagon ]; + legendNode4 [ label = "Interface Library", shape = pentagon ]; + legendNode5 [ label = "Object Library", shape = hexagon ]; + legendNode6 [ label = "Unknown Library", shape = septagon ]; + legendNode7 [ label = "Custom Target", shape = box ]; + legendNode0 -> legendNode1 [ style = solid ]; + legendNode0 -> legendNode2 [ style = solid ]; + legendNode0 -> legendNode3; + legendNode1 -> legendNode4 [ label = "Interface", style = dashed ]; + legendNode2 -> legendNode5 [ label = "Private", style = dotted ]; + legendNode3 -> legendNode6 [ style = solid ]; + legendNode0 -> legendNode7; +} + "node0" [ label = "CompilerFlags", shape = pentagon ]; + "node1" [ label = "ConsoleApplication", shape = egg ]; + "node2" [ label = "CoreLibrary", shape = octagon ]; + "node2" -> "node0" // CoreLibrary -> CompilerFlags + "node3" [ label = "GoofyLoggingLibrary\n(SeriousLoggingLibrary)\n(TheBestLoggingLibrary)", shape = pentagon ]; + "node2" -> "node3" [ style = dotted ] // CoreLibrary -> GoofyLoggingLibrary + "node1" -> "node2" [ style = dotted ] // ConsoleApplication -> CoreLibrary + "node4" [ label = "CryptoCurrencyMiningLibrary", shape = septagon ]; + "node1" -> "node4" [ style = dotted ] // ConsoleApplication -> CryptoCurrencyMiningLibrary + "node5" [ label = "GraphicApplication", shape = egg ]; + "node5" -> "node2" [ style = dotted ] // GraphicApplication -> CoreLibrary + "node6" [ label = "GraphicLibrary", shape = doubleoctagon ]; + "node7" [ label = "\"-lm\"", shape = septagon ]; + "node6" -> "node7" [ style = dotted ] // GraphicLibrary -> "-lm" + "node6" -> "node0" // GraphicLibrary -> CompilerFlags + "node6" -> "node2" [ style = dotted ] // GraphicLibrary -> CoreLibrary + "node8" [ label = "GraphicLibraryObjects", shape = hexagon ]; + "node6" -> "node8" [ style = dotted ] // GraphicLibrary -> GraphicLibraryObjects + "node5" -> "node6" [ style = dotted ] // GraphicApplication -> GraphicLibrary +} diff --git a/Tests/RunCMake/Graphviz/expected_outputs/dependency_graph_no_object_libs.dot b/Tests/RunCMake/Graphviz/expected_outputs/dependency_graph_no_object_libs.dot new file mode 100644 index 0000000..8116bc9 --- /dev/null +++ b/Tests/RunCMake/Graphviz/expected_outputs/dependency_graph_no_object_libs.dot @@ -0,0 +1,48 @@ +digraph "GraphvizTestProject" { +node [ + fontsize = "12" +]; +subgraph clusterLegend { + label = "Legend"; + color = black; + edge [ style = invis ]; + legendNode0 [ label = "Executable", shape = egg ]; + legendNode1 [ label = "Static Library", shape = octagon ]; + legendNode2 [ label = "Shared Library", shape = doubleoctagon ]; + legendNode3 [ label = "Module Library", shape = tripleoctagon ]; + legendNode4 [ label = "Interface Library", shape = pentagon ]; + legendNode5 [ label = "Object Library", shape = hexagon ]; + legendNode6 [ label = "Unknown Library", shape = septagon ]; + legendNode7 [ label = "Custom Target", shape = box ]; + legendNode0 -> legendNode1 [ style = solid ]; + legendNode0 -> legendNode2 [ style = solid ]; + legendNode0 -> legendNode3; + legendNode1 -> legendNode4 [ label = "Interface", style = dashed ]; + legendNode2 -> legendNode5 [ label = "Private", style = dotted ]; + legendNode3 -> legendNode6 [ style = solid ]; + legendNode0 -> legendNode7; +} + "node0" [ label = "CompilerFlags", shape = pentagon ]; + "node1" [ label = "ConsoleApplication", shape = egg ]; + "node2" [ label = "CoreLibrary", shape = octagon ]; + "node2" -> "node0" // CoreLibrary -> CompilerFlags + "node3" [ label = "GoofyLoggingLibrary\n(SeriousLoggingLibrary)\n(TheBestLoggingLibrary)", shape = pentagon ]; + "node2" -> "node3" [ style = dotted ] // CoreLibrary -> GoofyLoggingLibrary + "node1" -> "node2" [ style = dotted ] // ConsoleApplication -> CoreLibrary + "node4" [ label = "CryptoCurrencyMiningLibrary", shape = septagon ]; + "node1" -> "node4" [ style = dotted ] // ConsoleApplication -> CryptoCurrencyMiningLibrary + "node5" [ label = "GraphicApplication", shape = egg ]; + "node5" -> "node2" [ style = dotted ] // GraphicApplication -> CoreLibrary + "node6" [ label = "GraphicLibrary", shape = doubleoctagon ]; + "node7" [ label = "\"-lm\"", shape = septagon ]; + "node6" -> "node7" [ style = dotted ] // GraphicLibrary -> "-lm" + "node6" -> "node0" // GraphicLibrary -> CompilerFlags + "node6" -> "node2" [ style = dotted ] // GraphicLibrary -> CoreLibrary + "node5" -> "node6" [ style = dotted ] // GraphicApplication -> GraphicLibrary + "node8" [ label = "GraphicDriverOpenGL", shape = tripleoctagon ]; + "node8" -> "node0" [ style = dotted ] // GraphicDriverOpenGL -> CompilerFlags + "node8" -> "node2" [ style = dotted ] // GraphicDriverOpenGL -> CoreLibrary + "node9" [ label = "GraphicDriverVulkan", shape = tripleoctagon ]; + "node9" -> "node0" [ style = dotted ] // GraphicDriverVulkan -> CompilerFlags + "node9" -> "node2" [ style = dotted ] // GraphicDriverVulkan -> CoreLibrary +} diff --git a/Tests/RunCMake/Graphviz/expected_outputs/dependency_graph_no_per_target_files.dot b/Tests/RunCMake/Graphviz/expected_outputs/dependency_graph_no_per_target_files.dot new file mode 100644 index 0000000..1bbf25a --- /dev/null +++ b/Tests/RunCMake/Graphviz/expected_outputs/dependency_graph_no_per_target_files.dot @@ -0,0 +1,50 @@ +digraph "GraphvizTestProject" { +node [ + fontsize = "12" +]; +subgraph clusterLegend { + label = "Legend"; + color = black; + edge [ style = invis ]; + legendNode0 [ label = "Executable", shape = egg ]; + legendNode1 [ label = "Static Library", shape = octagon ]; + legendNode2 [ label = "Shared Library", shape = doubleoctagon ]; + legendNode3 [ label = "Module Library", shape = tripleoctagon ]; + legendNode4 [ label = "Interface Library", shape = pentagon ]; + legendNode5 [ label = "Object Library", shape = hexagon ]; + legendNode6 [ label = "Unknown Library", shape = septagon ]; + legendNode7 [ label = "Custom Target", shape = box ]; + legendNode0 -> legendNode1 [ style = solid ]; + legendNode0 -> legendNode2 [ style = solid ]; + legendNode0 -> legendNode3; + legendNode1 -> legendNode4 [ label = "Interface", style = dashed ]; + legendNode2 -> legendNode5 [ label = "Private", style = dotted ]; + legendNode3 -> legendNode6 [ style = solid ]; + legendNode0 -> legendNode7; +} + "node0" [ label = "CompilerFlags", shape = pentagon ]; + "node1" [ label = "ConsoleApplication", shape = egg ]; + "node2" [ label = "CoreLibrary", shape = octagon ]; + "node2" -> "node0" // CoreLibrary -> CompilerFlags + "node3" [ label = "GoofyLoggingLibrary\n(SeriousLoggingLibrary)\n(TheBestLoggingLibrary)", shape = pentagon ]; + "node2" -> "node3" [ style = dotted ] // CoreLibrary -> GoofyLoggingLibrary + "node1" -> "node2" [ style = dotted ] // ConsoleApplication -> CoreLibrary + "node4" [ label = "CryptoCurrencyMiningLibrary", shape = septagon ]; + "node1" -> "node4" [ style = dotted ] // ConsoleApplication -> CryptoCurrencyMiningLibrary + "node5" [ label = "GraphicApplication", shape = egg ]; + "node5" -> "node2" [ style = dotted ] // GraphicApplication -> CoreLibrary + "node6" [ label = "GraphicLibrary", shape = doubleoctagon ]; + "node7" [ label = "\"-lm\"", shape = septagon ]; + "node6" -> "node7" [ style = dotted ] // GraphicLibrary -> "-lm" + "node6" -> "node0" // GraphicLibrary -> CompilerFlags + "node6" -> "node2" [ style = dotted ] // GraphicLibrary -> CoreLibrary + "node8" [ label = "GraphicLibraryObjects", shape = hexagon ]; + "node6" -> "node8" [ style = dotted ] // GraphicLibrary -> GraphicLibraryObjects + "node5" -> "node6" [ style = dotted ] // GraphicApplication -> GraphicLibrary + "node9" [ label = "GraphicDriverOpenGL", shape = tripleoctagon ]; + "node9" -> "node0" [ style = dotted ] // GraphicDriverOpenGL -> CompilerFlags + "node9" -> "node2" [ style = dotted ] // GraphicDriverOpenGL -> CoreLibrary + "node10" [ label = "GraphicDriverVulkan", shape = tripleoctagon ]; + "node10" -> "node0" [ style = dotted ] // GraphicDriverVulkan -> CompilerFlags + "node10" -> "node2" [ style = dotted ] // GraphicDriverVulkan -> CoreLibrary +} diff --git a/Tests/RunCMake/Graphviz/expected_outputs/dependency_graph_no_shared_libs.dot b/Tests/RunCMake/Graphviz/expected_outputs/dependency_graph_no_shared_libs.dot new file mode 100644 index 0000000..439d1f7 --- /dev/null +++ b/Tests/RunCMake/Graphviz/expected_outputs/dependency_graph_no_shared_libs.dot @@ -0,0 +1,44 @@ +digraph "GraphvizTestProject" { +node [ + fontsize = "12" +]; +subgraph clusterLegend { + label = "Legend"; + color = black; + edge [ style = invis ]; + legendNode0 [ label = "Executable", shape = egg ]; + legendNode1 [ label = "Static Library", shape = octagon ]; + legendNode2 [ label = "Shared Library", shape = doubleoctagon ]; + legendNode3 [ label = "Module Library", shape = tripleoctagon ]; + legendNode4 [ label = "Interface Library", shape = pentagon ]; + legendNode5 [ label = "Object Library", shape = hexagon ]; + legendNode6 [ label = "Unknown Library", shape = septagon ]; + legendNode7 [ label = "Custom Target", shape = box ]; + legendNode0 -> legendNode1 [ style = solid ]; + legendNode0 -> legendNode2 [ style = solid ]; + legendNode0 -> legendNode3; + legendNode1 -> legendNode4 [ label = "Interface", style = dashed ]; + legendNode2 -> legendNode5 [ label = "Private", style = dotted ]; + legendNode3 -> legendNode6 [ style = solid ]; + legendNode0 -> legendNode7; +} + "node0" [ label = "CompilerFlags", shape = pentagon ]; + "node1" [ label = "ConsoleApplication", shape = egg ]; + "node2" [ label = "CoreLibrary", shape = octagon ]; + "node2" -> "node0" // CoreLibrary -> CompilerFlags + "node3" [ label = "GoofyLoggingLibrary\n(SeriousLoggingLibrary)\n(TheBestLoggingLibrary)", shape = pentagon ]; + "node2" -> "node3" [ style = dotted ] // CoreLibrary -> GoofyLoggingLibrary + "node1" -> "node2" [ style = dotted ] // ConsoleApplication -> CoreLibrary + "node4" [ label = "CryptoCurrencyMiningLibrary", shape = septagon ]; + "node1" -> "node4" [ style = dotted ] // ConsoleApplication -> CryptoCurrencyMiningLibrary + "node5" [ label = "GraphicApplication", shape = egg ]; + "node5" -> "node2" [ style = dotted ] // GraphicApplication -> CoreLibrary + "node6" [ label = "\"-lm\"", shape = septagon ]; + "node7" [ label = "GraphicLibraryObjects", shape = hexagon ]; + "node8" [ label = "GraphicDriverOpenGL", shape = tripleoctagon ]; + "node8" -> "node0" [ style = dotted ] // GraphicDriverOpenGL -> CompilerFlags + "node8" -> "node2" [ style = dotted ] // GraphicDriverOpenGL -> CoreLibrary + "node9" [ label = "GraphicDriverVulkan", shape = tripleoctagon ]; + "node9" -> "node0" [ style = dotted ] // GraphicDriverVulkan -> CompilerFlags + "node9" -> "node2" [ style = dotted ] // GraphicDriverVulkan -> CoreLibrary +} diff --git a/Tests/RunCMake/Graphviz/expected_outputs/dependency_graph_no_static_libs.dot b/Tests/RunCMake/Graphviz/expected_outputs/dependency_graph_no_static_libs.dot new file mode 100644 index 0000000..81199a2 --- /dev/null +++ b/Tests/RunCMake/Graphviz/expected_outputs/dependency_graph_no_static_libs.dot @@ -0,0 +1,42 @@ +digraph "GraphvizTestProject" { +node [ + fontsize = "12" +]; +subgraph clusterLegend { + label = "Legend"; + color = black; + edge [ style = invis ]; + legendNode0 [ label = "Executable", shape = egg ]; + legendNode1 [ label = "Static Library", shape = octagon ]; + legendNode2 [ label = "Shared Library", shape = doubleoctagon ]; + legendNode3 [ label = "Module Library", shape = tripleoctagon ]; + legendNode4 [ label = "Interface Library", shape = pentagon ]; + legendNode5 [ label = "Object Library", shape = hexagon ]; + legendNode6 [ label = "Unknown Library", shape = septagon ]; + legendNode7 [ label = "Custom Target", shape = box ]; + legendNode0 -> legendNode1 [ style = solid ]; + legendNode0 -> legendNode2 [ style = solid ]; + legendNode0 -> legendNode3; + legendNode1 -> legendNode4 [ label = "Interface", style = dashed ]; + legendNode2 -> legendNode5 [ label = "Private", style = dotted ]; + legendNode3 -> legendNode6 [ style = solid ]; + legendNode0 -> legendNode7; +} + "node0" [ label = "CompilerFlags", shape = pentagon ]; + "node1" [ label = "ConsoleApplication", shape = egg ]; + "node2" [ label = "GoofyLoggingLibrary\n(SeriousLoggingLibrary)\n(TheBestLoggingLibrary)", shape = pentagon ]; + "node3" [ label = "CryptoCurrencyMiningLibrary", shape = septagon ]; + "node1" -> "node3" [ style = dotted ] // ConsoleApplication -> CryptoCurrencyMiningLibrary + "node4" [ label = "GraphicApplication", shape = egg ]; + "node5" [ label = "GraphicLibrary", shape = doubleoctagon ]; + "node6" [ label = "\"-lm\"", shape = septagon ]; + "node5" -> "node6" [ style = dotted ] // GraphicLibrary -> "-lm" + "node5" -> "node0" // GraphicLibrary -> CompilerFlags + "node7" [ label = "GraphicLibraryObjects", shape = hexagon ]; + "node5" -> "node7" [ style = dotted ] // GraphicLibrary -> GraphicLibraryObjects + "node4" -> "node5" [ style = dotted ] // GraphicApplication -> GraphicLibrary + "node8" [ label = "GraphicDriverOpenGL", shape = tripleoctagon ]; + "node8" -> "node0" [ style = dotted ] // GraphicDriverOpenGL -> CompilerFlags + "node9" [ label = "GraphicDriverVulkan", shape = tripleoctagon ]; + "node9" -> "node0" [ style = dotted ] // GraphicDriverVulkan -> CompilerFlags +} diff --git a/Tests/RunCMake/Graphviz/expected_outputs/dependency_graph_no_unknown_libs.dot b/Tests/RunCMake/Graphviz/expected_outputs/dependency_graph_no_unknown_libs.dot new file mode 100644 index 0000000..1be6550 --- /dev/null +++ b/Tests/RunCMake/Graphviz/expected_outputs/dependency_graph_no_unknown_libs.dot @@ -0,0 +1,48 @@ +digraph "GraphvizTestProject" { +node [ + fontsize = "12" +]; +subgraph clusterLegend { + label = "Legend"; + color = black; + edge [ style = invis ]; + legendNode0 [ label = "Executable", shape = egg ]; + legendNode1 [ label = "Static Library", shape = octagon ]; + legendNode2 [ label = "Shared Library", shape = doubleoctagon ]; + legendNode3 [ label = "Module Library", shape = tripleoctagon ]; + legendNode4 [ label = "Interface Library", shape = pentagon ]; + legendNode5 [ label = "Object Library", shape = hexagon ]; + legendNode6 [ label = "Unknown Library", shape = septagon ]; + legendNode7 [ label = "Custom Target", shape = box ]; + legendNode0 -> legendNode1 [ style = solid ]; + legendNode0 -> legendNode2 [ style = solid ]; + legendNode0 -> legendNode3; + legendNode1 -> legendNode4 [ label = "Interface", style = dashed ]; + legendNode2 -> legendNode5 [ label = "Private", style = dotted ]; + legendNode3 -> legendNode6 [ style = solid ]; + legendNode0 -> legendNode7; +} + "node0" [ label = "CompilerFlags", shape = pentagon ]; + "node1" [ label = "ConsoleApplication", shape = egg ]; + "node2" [ label = "CoreLibrary", shape = octagon ]; + "node2" -> "node0" // CoreLibrary -> CompilerFlags + "node3" [ label = "GoofyLoggingLibrary\n(SeriousLoggingLibrary)\n(TheBestLoggingLibrary)", shape = pentagon ]; + "node2" -> "node3" [ style = dotted ] // CoreLibrary -> GoofyLoggingLibrary + "node1" -> "node2" [ style = dotted ] // ConsoleApplication -> CoreLibrary + "node4" [ label = "GraphicApplication", shape = egg ]; + "node4" -> "node2" [ style = dotted ] // GraphicApplication -> CoreLibrary + "node5" [ label = "GraphicLibrary", shape = doubleoctagon ]; + "node6" [ label = "\"-lm\"", shape = septagon ]; + "node5" -> "node6" [ style = dotted ] // GraphicLibrary -> "-lm" + "node5" -> "node0" // GraphicLibrary -> CompilerFlags + "node5" -> "node2" [ style = dotted ] // GraphicLibrary -> CoreLibrary + "node7" [ label = "GraphicLibraryObjects", shape = hexagon ]; + "node5" -> "node7" [ style = dotted ] // GraphicLibrary -> GraphicLibraryObjects + "node4" -> "node5" [ style = dotted ] // GraphicApplication -> GraphicLibrary + "node8" [ label = "GraphicDriverOpenGL", shape = tripleoctagon ]; + "node8" -> "node0" [ style = dotted ] // GraphicDriverOpenGL -> CompilerFlags + "node8" -> "node2" [ style = dotted ] // GraphicDriverOpenGL -> CoreLibrary + "node9" [ label = "GraphicDriverVulkan", shape = tripleoctagon ]; + "node9" -> "node0" [ style = dotted ] // GraphicDriverVulkan -> CompilerFlags + "node9" -> "node2" [ style = dotted ] // GraphicDriverVulkan -> CoreLibrary +} diff --git a/Tests/RunCMake/Graphviz/expected_outputs/dependency_graph_set_graph_header.dot b/Tests/RunCMake/Graphviz/expected_outputs/dependency_graph_set_graph_header.dot new file mode 100644 index 0000000..1cfbe0f --- /dev/null +++ b/Tests/RunCMake/Graphviz/expected_outputs/dependency_graph_set_graph_header.dot @@ -0,0 +1,50 @@ +digraph "GraphvizTestProject" { +node [ + fontsize = "16" +]; +subgraph clusterLegend { + label = "Legend"; + color = black; + edge [ style = invis ]; + legendNode0 [ label = "Executable", shape = egg ]; + legendNode1 [ label = "Static Library", shape = octagon ]; + legendNode2 [ label = "Shared Library", shape = doubleoctagon ]; + legendNode3 [ label = "Module Library", shape = tripleoctagon ]; + legendNode4 [ label = "Interface Library", shape = pentagon ]; + legendNode5 [ label = "Object Library", shape = hexagon ]; + legendNode6 [ label = "Unknown Library", shape = septagon ]; + legendNode7 [ label = "Custom Target", shape = box ]; + legendNode0 -> legendNode1 [ style = solid ]; + legendNode0 -> legendNode2 [ style = solid ]; + legendNode0 -> legendNode3; + legendNode1 -> legendNode4 [ label = "Interface", style = dashed ]; + legendNode2 -> legendNode5 [ label = "Private", style = dotted ]; + legendNode3 -> legendNode6 [ style = solid ]; + legendNode0 -> legendNode7; +} + "node0" [ label = "CompilerFlags", shape = pentagon ]; + "node1" [ label = "ConsoleApplication", shape = egg ]; + "node2" [ label = "CoreLibrary", shape = octagon ]; + "node2" -> "node0" // CoreLibrary -> CompilerFlags + "node3" [ label = "GoofyLoggingLibrary\n(SeriousLoggingLibrary)\n(TheBestLoggingLibrary)", shape = pentagon ]; + "node2" -> "node3" [ style = dotted ] // CoreLibrary -> GoofyLoggingLibrary + "node1" -> "node2" [ style = dotted ] // ConsoleApplication -> CoreLibrary + "node4" [ label = "CryptoCurrencyMiningLibrary", shape = septagon ]; + "node1" -> "node4" [ style = dotted ] // ConsoleApplication -> CryptoCurrencyMiningLibrary + "node5" [ label = "GraphicApplication", shape = egg ]; + "node5" -> "node2" [ style = dotted ] // GraphicApplication -> CoreLibrary + "node6" [ label = "GraphicLibrary", shape = doubleoctagon ]; + "node7" [ label = "\"-lm\"", shape = septagon ]; + "node6" -> "node7" [ style = dotted ] // GraphicLibrary -> "-lm" + "node6" -> "node0" // GraphicLibrary -> CompilerFlags + "node6" -> "node2" [ style = dotted ] // GraphicLibrary -> CoreLibrary + "node8" [ label = "GraphicLibraryObjects", shape = hexagon ]; + "node6" -> "node8" [ style = dotted ] // GraphicLibrary -> GraphicLibraryObjects + "node5" -> "node6" [ style = dotted ] // GraphicApplication -> GraphicLibrary + "node9" [ label = "GraphicDriverOpenGL", shape = tripleoctagon ]; + "node9" -> "node0" [ style = dotted ] // GraphicDriverOpenGL -> CompilerFlags + "node9" -> "node2" [ style = dotted ] // GraphicDriverOpenGL -> CoreLibrary + "node10" [ label = "GraphicDriverVulkan", shape = tripleoctagon ]; + "node10" -> "node0" [ style = dotted ] // GraphicDriverVulkan -> CompilerFlags + "node10" -> "node2" [ style = dotted ] // GraphicDriverVulkan -> CoreLibrary +} diff --git a/Tests/RunCMake/Graphviz/expected_outputs/dependency_graph_set_graph_name.dot b/Tests/RunCMake/Graphviz/expected_outputs/dependency_graph_set_graph_name.dot new file mode 100644 index 0000000..9653c33 --- /dev/null +++ b/Tests/RunCMake/Graphviz/expected_outputs/dependency_graph_set_graph_name.dot @@ -0,0 +1,50 @@ +digraph "CMake Project Dependencies" { +node [ + fontsize = "12" +]; +subgraph clusterLegend { + label = "Legend"; + color = black; + edge [ style = invis ]; + legendNode0 [ label = "Executable", shape = egg ]; + legendNode1 [ label = "Static Library", shape = octagon ]; + legendNode2 [ label = "Shared Library", shape = doubleoctagon ]; + legendNode3 [ label = "Module Library", shape = tripleoctagon ]; + legendNode4 [ label = "Interface Library", shape = pentagon ]; + legendNode5 [ label = "Object Library", shape = hexagon ]; + legendNode6 [ label = "Unknown Library", shape = septagon ]; + legendNode7 [ label = "Custom Target", shape = box ]; + legendNode0 -> legendNode1 [ style = solid ]; + legendNode0 -> legendNode2 [ style = solid ]; + legendNode0 -> legendNode3; + legendNode1 -> legendNode4 [ label = "Interface", style = dashed ]; + legendNode2 -> legendNode5 [ label = "Private", style = dotted ]; + legendNode3 -> legendNode6 [ style = solid ]; + legendNode0 -> legendNode7; +} + "node0" [ label = "CompilerFlags", shape = pentagon ]; + "node1" [ label = "ConsoleApplication", shape = egg ]; + "node2" [ label = "CoreLibrary", shape = octagon ]; + "node2" -> "node0" // CoreLibrary -> CompilerFlags + "node3" [ label = "GoofyLoggingLibrary\n(SeriousLoggingLibrary)\n(TheBestLoggingLibrary)", shape = pentagon ]; + "node2" -> "node3" [ style = dotted ] // CoreLibrary -> GoofyLoggingLibrary + "node1" -> "node2" [ style = dotted ] // ConsoleApplication -> CoreLibrary + "node4" [ label = "CryptoCurrencyMiningLibrary", shape = septagon ]; + "node1" -> "node4" [ style = dotted ] // ConsoleApplication -> CryptoCurrencyMiningLibrary + "node5" [ label = "GraphicApplication", shape = egg ]; + "node5" -> "node2" [ style = dotted ] // GraphicApplication -> CoreLibrary + "node6" [ label = "GraphicLibrary", shape = doubleoctagon ]; + "node7" [ label = "\"-lm\"", shape = septagon ]; + "node6" -> "node7" [ style = dotted ] // GraphicLibrary -> "-lm" + "node6" -> "node0" // GraphicLibrary -> CompilerFlags + "node6" -> "node2" [ style = dotted ] // GraphicLibrary -> CoreLibrary + "node8" [ label = "GraphicLibraryObjects", shape = hexagon ]; + "node6" -> "node8" [ style = dotted ] // GraphicLibrary -> GraphicLibraryObjects + "node5" -> "node6" [ style = dotted ] // GraphicApplication -> GraphicLibrary + "node9" [ label = "GraphicDriverOpenGL", shape = tripleoctagon ]; + "node9" -> "node0" [ style = dotted ] // GraphicDriverOpenGL -> CompilerFlags + "node9" -> "node2" [ style = dotted ] // GraphicDriverOpenGL -> CoreLibrary + "node10" [ label = "GraphicDriverVulkan", shape = tripleoctagon ]; + "node10" -> "node0" [ style = dotted ] // GraphicDriverVulkan -> CompilerFlags + "node10" -> "node2" [ style = dotted ] // GraphicDriverVulkan -> CoreLibrary +} diff --git a/Tests/RunCMake/Graphviz/expected_outputs/dependency_graph_set_node_prefix.dot b/Tests/RunCMake/Graphviz/expected_outputs/dependency_graph_set_node_prefix.dot new file mode 100644 index 0000000..82d96d0 --- /dev/null +++ b/Tests/RunCMake/Graphviz/expected_outputs/dependency_graph_set_node_prefix.dot @@ -0,0 +1,50 @@ +digraph "GraphvizTestProject" { +node [ + fontsize = "12" +]; +subgraph clusterLegend { + label = "Legend"; + color = black; + edge [ style = invis ]; + legendNode0 [ label = "Executable", shape = egg ]; + legendNode1 [ label = "Static Library", shape = octagon ]; + legendNode2 [ label = "Shared Library", shape = doubleoctagon ]; + legendNode3 [ label = "Module Library", shape = tripleoctagon ]; + legendNode4 [ label = "Interface Library", shape = pentagon ]; + legendNode5 [ label = "Object Library", shape = hexagon ]; + legendNode6 [ label = "Unknown Library", shape = septagon ]; + legendNode7 [ label = "Custom Target", shape = box ]; + legendNode0 -> legendNode1 [ style = solid ]; + legendNode0 -> legendNode2 [ style = solid ]; + legendNode0 -> legendNode3; + legendNode1 -> legendNode4 [ label = "Interface", style = dashed ]; + legendNode2 -> legendNode5 [ label = "Private", style = dotted ]; + legendNode3 -> legendNode6 [ style = solid ]; + legendNode0 -> legendNode7; +} + "point0" [ label = "CompilerFlags", shape = pentagon ]; + "point1" [ label = "ConsoleApplication", shape = egg ]; + "point2" [ label = "CoreLibrary", shape = octagon ]; + "point2" -> "point0" // CoreLibrary -> CompilerFlags + "point3" [ label = "GoofyLoggingLibrary\n(SeriousLoggingLibrary)\n(TheBestLoggingLibrary)", shape = pentagon ]; + "point2" -> "point3" [ style = dotted ] // CoreLibrary -> GoofyLoggingLibrary + "point1" -> "point2" [ style = dotted ] // ConsoleApplication -> CoreLibrary + "point4" [ label = "CryptoCurrencyMiningLibrary", shape = septagon ]; + "point1" -> "point4" [ style = dotted ] // ConsoleApplication -> CryptoCurrencyMiningLibrary + "point5" [ label = "GraphicApplication", shape = egg ]; + "point5" -> "point2" [ style = dotted ] // GraphicApplication -> CoreLibrary + "point6" [ label = "GraphicLibrary", shape = doubleoctagon ]; + "point7" [ label = "\"-lm\"", shape = septagon ]; + "point6" -> "point7" [ style = dotted ] // GraphicLibrary -> "-lm" + "point6" -> "point0" // GraphicLibrary -> CompilerFlags + "point6" -> "point2" [ style = dotted ] // GraphicLibrary -> CoreLibrary + "point8" [ label = "GraphicLibraryObjects", shape = hexagon ]; + "point6" -> "point8" [ style = dotted ] // GraphicLibrary -> GraphicLibraryObjects + "point5" -> "point6" [ style = dotted ] // GraphicApplication -> GraphicLibrary + "point9" [ label = "GraphicDriverOpenGL", shape = tripleoctagon ]; + "point9" -> "point0" [ style = dotted ] // GraphicDriverOpenGL -> CompilerFlags + "point9" -> "point2" [ style = dotted ] // GraphicDriverOpenGL -> CoreLibrary + "point10" [ label = "GraphicDriverVulkan", shape = tripleoctagon ]; + "point10" -> "point0" [ style = dotted ] // GraphicDriverVulkan -> CompilerFlags + "point10" -> "point2" [ style = dotted ] // GraphicDriverVulkan -> CoreLibrary +} diff --git a/Tests/RunCMake/Graphviz/no_dependers_files-check.cmake b/Tests/RunCMake/Graphviz/no_dependers_files-check.cmake new file mode 100644 index 0000000..f4a43b6 --- /dev/null +++ b/Tests/RunCMake/Graphviz/no_dependers_files-check.cmake @@ -0,0 +1,4 @@ +file(GLOB dependers_files ${RunCMake_TEST_BINARY_DIR}/*.dependers) +if(${dependers_files}) + set(RunCMake_TEST_FAILED "Found *.dependers files despite GRAPHVIZ_GENERATE_DEPENDERS set to FALSE.") +endif() diff --git a/Tests/RunCMake/Graphviz/no_executables-check.cmake b/Tests/RunCMake/Graphviz/no_executables-check.cmake new file mode 100644 index 0000000..be29a4f --- /dev/null +++ b/Tests/RunCMake/Graphviz/no_executables-check.cmake @@ -0,0 +1,5 @@ +include(RunCMake) + +ensure_files_match( + ${RunCMake_TEST_SOURCE_DIR}/expected_outputs/dependency_graph_no_executables.dot + ${RunCMake_TEST_BINARY_DIR}/generated_dependency_graph.dot) diff --git a/Tests/RunCMake/Graphviz/no_external_libs-check.cmake b/Tests/RunCMake/Graphviz/no_external_libs-check.cmake new file mode 100644 index 0000000..518ef7b --- /dev/null +++ b/Tests/RunCMake/Graphviz/no_external_libs-check.cmake @@ -0,0 +1,5 @@ +include(RunCMake) + +ensure_files_match( + ${RunCMake_TEST_SOURCE_DIR}/expected_outputs/dependency_graph_no_external_libs.dot + ${RunCMake_TEST_BINARY_DIR}/generated_dependency_graph.dot) diff --git a/Tests/RunCMake/Graphviz/no_graphic_libs-check.cmake b/Tests/RunCMake/Graphviz/no_graphic_libs-check.cmake new file mode 100644 index 0000000..0f5aa47 --- /dev/null +++ b/Tests/RunCMake/Graphviz/no_graphic_libs-check.cmake @@ -0,0 +1,5 @@ +include(RunCMake) + +ensure_files_match( + ${RunCMake_TEST_SOURCE_DIR}/expected_outputs/dependency_graph_no_graphic_libs.dot + ${RunCMake_TEST_BINARY_DIR}/generated_dependency_graph.dot) diff --git a/Tests/RunCMake/Graphviz/no_interface_libs-check.cmake b/Tests/RunCMake/Graphviz/no_interface_libs-check.cmake new file mode 100644 index 0000000..018fef0 --- /dev/null +++ b/Tests/RunCMake/Graphviz/no_interface_libs-check.cmake @@ -0,0 +1,5 @@ +include(RunCMake) + +ensure_files_match( + ${RunCMake_TEST_SOURCE_DIR}/expected_outputs/dependency_graph_no_interface_libs.dot + ${RunCMake_TEST_BINARY_DIR}/generated_dependency_graph.dot) diff --git a/Tests/RunCMake/Graphviz/no_module_libs-check.cmake b/Tests/RunCMake/Graphviz/no_module_libs-check.cmake new file mode 100644 index 0000000..e185cb1 --- /dev/null +++ b/Tests/RunCMake/Graphviz/no_module_libs-check.cmake @@ -0,0 +1,5 @@ +include(RunCMake) + +ensure_files_match( + ${RunCMake_TEST_SOURCE_DIR}/expected_outputs/dependency_graph_no_module_libs.dot + ${RunCMake_TEST_BINARY_DIR}/generated_dependency_graph.dot) diff --git a/Tests/RunCMake/Graphviz/no_object_libs-check.cmake b/Tests/RunCMake/Graphviz/no_object_libs-check.cmake new file mode 100644 index 0000000..90e7ecb --- /dev/null +++ b/Tests/RunCMake/Graphviz/no_object_libs-check.cmake @@ -0,0 +1,5 @@ +include(RunCMake) + +ensure_files_match( + ${RunCMake_TEST_SOURCE_DIR}/expected_outputs/dependency_graph_no_object_libs.dot + ${RunCMake_TEST_BINARY_DIR}/generated_dependency_graph.dot) diff --git a/Tests/RunCMake/Graphviz/no_per_target_files-check.cmake b/Tests/RunCMake/Graphviz/no_per_target_files-check.cmake new file mode 100644 index 0000000..95d05a1 --- /dev/null +++ b/Tests/RunCMake/Graphviz/no_per_target_files-check.cmake @@ -0,0 +1,5 @@ +file(GLOB per_target_files ${RunCMake_TEST_BINARY_DIR}/*.dot.*) +list(FILTER per_target_files EXCLUDE REGEX ".*\\.dependers$") +if(per_target_files) + set(RunCMake_TEST_FAILED "Found per-target .dot files despite GRAPHVIZ_GENERATE_PER_TARGET set to FALSE.") +endif() diff --git a/Tests/RunCMake/Graphviz/no_shared_libs-check.cmake b/Tests/RunCMake/Graphviz/no_shared_libs-check.cmake new file mode 100644 index 0000000..b45da2e --- /dev/null +++ b/Tests/RunCMake/Graphviz/no_shared_libs-check.cmake @@ -0,0 +1,5 @@ +include(RunCMake) + +ensure_files_match( + ${RunCMake_TEST_SOURCE_DIR}/expected_outputs/dependency_graph_no_shared_libs.dot + ${RunCMake_TEST_BINARY_DIR}/generated_dependency_graph.dot) diff --git a/Tests/RunCMake/Graphviz/no_static_libs-check.cmake b/Tests/RunCMake/Graphviz/no_static_libs-check.cmake new file mode 100644 index 0000000..befc11b --- /dev/null +++ b/Tests/RunCMake/Graphviz/no_static_libs-check.cmake @@ -0,0 +1,5 @@ +include(RunCMake) + +ensure_files_match( + ${RunCMake_TEST_SOURCE_DIR}/expected_outputs/dependency_graph_no_static_libs.dot + ${RunCMake_TEST_BINARY_DIR}/generated_dependency_graph.dot) diff --git a/Tests/RunCMake/Graphviz/no_unknown_libs-check.cmake b/Tests/RunCMake/Graphviz/no_unknown_libs-check.cmake new file mode 100644 index 0000000..95286bc --- /dev/null +++ b/Tests/RunCMake/Graphviz/no_unknown_libs-check.cmake @@ -0,0 +1,5 @@ +include(RunCMake) + +ensure_files_match( + ${RunCMake_TEST_SOURCE_DIR}/expected_outputs/dependency_graph_no_unknown_libs.dot + ${RunCMake_TEST_BINARY_DIR}/generated_dependency_graph.dot) diff --git a/Tests/RunCMake/Graphviz/set_graph_header-check.cmake b/Tests/RunCMake/Graphviz/set_graph_header-check.cmake new file mode 100644 index 0000000..1396484 --- /dev/null +++ b/Tests/RunCMake/Graphviz/set_graph_header-check.cmake @@ -0,0 +1,5 @@ +include(RunCMake) + +ensure_files_match( + ${RunCMake_TEST_SOURCE_DIR}/expected_outputs/dependency_graph_set_graph_header.dot + ${RunCMake_TEST_BINARY_DIR}/generated_dependency_graph.dot) diff --git a/Tests/RunCMake/Graphviz/set_graph_name-check.cmake b/Tests/RunCMake/Graphviz/set_graph_name-check.cmake new file mode 100644 index 0000000..0c522e9 --- /dev/null +++ b/Tests/RunCMake/Graphviz/set_graph_name-check.cmake @@ -0,0 +1,5 @@ +include(RunCMake) + +ensure_files_match( + ${RunCMake_TEST_SOURCE_DIR}/expected_outputs/dependency_graph_set_graph_name.dot + ${RunCMake_TEST_BINARY_DIR}/generated_dependency_graph.dot) diff --git a/Tests/RunCMake/Graphviz/set_node_prefix-check.cmake b/Tests/RunCMake/Graphviz/set_node_prefix-check.cmake new file mode 100644 index 0000000..61e9b24 --- /dev/null +++ b/Tests/RunCMake/Graphviz/set_node_prefix-check.cmake @@ -0,0 +1,5 @@ +include(RunCMake) + +ensure_files_match( + ${RunCMake_TEST_SOURCE_DIR}/expected_outputs/dependency_graph_set_node_prefix.dot + ${RunCMake_TEST_BINARY_DIR}/generated_dependency_graph.dot) diff --git a/Tests/RunCMake/Graphviz/test_project/core_library.c b/Tests/RunCMake/Graphviz/test_project/core_library.c new file mode 100644 index 0000000..e8a8844 --- /dev/null +++ b/Tests/RunCMake/Graphviz/test_project/core_library.c @@ -0,0 +1,3 @@ +void log_something() +{ +} diff --git a/Tests/RunCMake/Graphviz/test_project/graphic_library.c b/Tests/RunCMake/Graphviz/test_project/graphic_library.c new file mode 100644 index 0000000..958c8ab --- /dev/null +++ b/Tests/RunCMake/Graphviz/test_project/graphic_library.c @@ -0,0 +1,3 @@ +void initialize_graphics() +{ +} diff --git a/Tests/RunCMake/Graphviz/test_project/main.c b/Tests/RunCMake/Graphviz/test_project/main.c new file mode 100644 index 0000000..d123e09 --- /dev/null +++ b/Tests/RunCMake/Graphviz/test_project/main.c @@ -0,0 +1,4 @@ +int main(int argc, char** argv) +{ + return 0; +} diff --git a/Tests/RunCMake/Graphviz/test_project/module.c b/Tests/RunCMake/Graphviz/test_project/module.c new file mode 100644 index 0000000..a508b09 --- /dev/null +++ b/Tests/RunCMake/Graphviz/test_project/module.c @@ -0,0 +1,3 @@ +static void some_function() +{ +} diff --git a/Tests/RunCMake/Graphviz/test_project/third_party_project/CMakeLists.txt b/Tests/RunCMake/Graphviz/test_project/third_party_project/CMakeLists.txt new file mode 100644 index 0000000..e381750 --- /dev/null +++ b/Tests/RunCMake/Graphviz/test_project/third_party_project/CMakeLists.txt @@ -0,0 +1,3 @@ +project(ThirdPartyProject) + +add_library(GoofyLoggingLibrary INTERFACE) diff --git a/Tests/RunCMake/PrecompileHeaders/PchMultilanguage-check.cmake b/Tests/RunCMake/PrecompileHeaders/PchMultilanguage-check.cmake index 44fe2da..e0b753a 100644 --- a/Tests/RunCMake/PrecompileHeaders/PchMultilanguage-check.cmake +++ b/Tests/RunCMake/PrecompileHeaders/PchMultilanguage-check.cmake @@ -15,3 +15,17 @@ if (NOT EXISTS ${foobar_pch_hxx_header}) set(RunCMake_TEST_FAILED "Generated foobar C++ pch header ${foobar_pch_hxx_header} does not exist") return() endif() + +file(STRINGS ${foobar_pch_h_header} foobar_pch_h_header_strings) + +if (NOT foobar_pch_h_header_strings MATCHES ";#include <stddef.h>(;|$)") + set(RunCMake_TEST_FAILED "Generated foo pch header\n ${foobar_pch_h_header}\nhas bad content:\n ${foobar_pch_h_header_strings}") + return() +endif() + +file(STRINGS ${foobar_pch_hxx_header} foobar_pch_hxx_header_strings) + +if (NOT foobar_pch_hxx_header_strings MATCHES ";#include <cstddef>(;|$)") + set(RunCMake_TEST_FAILED "Generated foo pch header\n ${foobar_pch_hxx_header}\nhas bad content:\n ${foobar_pch_hxx_header_strings}") + return() +endif() diff --git a/Tests/RunCMake/PrecompileHeaders/PchMultilanguage.cmake b/Tests/RunCMake/PrecompileHeaders/PchMultilanguage.cmake index 7a837da..cdc42b2 100644 --- a/Tests/RunCMake/PrecompileHeaders/PchMultilanguage.cmake +++ b/Tests/RunCMake/PrecompileHeaders/PchMultilanguage.cmake @@ -6,4 +6,7 @@ add_executable(foobar main.cpp ) target_include_directories(foobar PUBLIC include) -target_precompile_headers(foobar PRIVATE "<stddef.h>") +target_precompile_headers(foobar PRIVATE + "$<$<COMPILE_LANGUAGE:C>:<stddef.h$<ANGLE-R>>" + "$<$<COMPILE_LANGUAGE:CXX>:<cstddef$<ANGLE-R>>" + ) diff --git a/Tests/RunCMake/RunCMake.cmake b/Tests/RunCMake/RunCMake.cmake index da4d1e5..f24cfab 100644 --- a/Tests/RunCMake/RunCMake.cmake +++ b/Tests/RunCMake/RunCMake.cmake @@ -204,5 +204,28 @@ function(run_cmake_with_options test) run_cmake(${test}) endfunction() +function(ensure_files_match expected_file actual_file) + if(NOT EXISTS "${expected_file}") + message(FATAL_ERROR "Expected file does not exist:\n ${expected_file}") + endif() + if(NOT EXISTS "${actual_file}") + message(FATAL_ERROR "Actual file does not exist:\n ${actual_file}") + endif() + file(READ "${expected_file}" expected_file_content) + file(READ "${actual_file}" actual_file_content) + if(NOT "${expected_file_content}" STREQUAL "${actual_file_content}") + message(FATAL_ERROR "Actual file content does not match expected:\n + \n + expected file: ${expected_file}\n + expected content:\n + ${expected_file_content}\n + \n + actual file: ${actual_file}\n + actual content:\n + ${actual_file_content}\n + ") + endif() +endfunction() + # Protect RunCMake tests from calling environment. unset(ENV{MAKEFLAGS}) diff --git a/Tests/RunCMake/VS10Project/RunCMakeTest.cmake b/Tests/RunCMake/VS10Project/RunCMakeTest.cmake index 44ccd6b..1487161 100644 --- a/Tests/RunCMake/VS10Project/RunCMakeTest.cmake +++ b/Tests/RunCMake/VS10Project/RunCMakeTest.cmake @@ -15,6 +15,7 @@ run_cmake(VsDebuggerCommand) run_cmake(VsDebuggerCommandArguments) run_cmake(VsDebuggerEnvironment) run_cmake(VsCSharpCustomTags) +run_cmake(VsCSharpDocumentationFile) run_cmake(VsCSharpReferenceProps) run_cmake(VsCSharpWithoutSources) run_cmake(VsCSharpDeployFiles) @@ -28,6 +29,10 @@ run_cmake(VsDpiAwareBadParam) run_cmake(VsPrecompileHeaders) run_cmake(VsPrecompileHeadersReuseFromCompilePDBName) +set(RunCMake_GENERATOR_TOOLSET "VCTargetsPath=$(VCTargetsPath)") +run_cmake(VsVCTargetsPath) +unset(RunCMake_GENERATOR_TOOLSET) + if(CMAKE_C_COMPILER_ID STREQUAL "MSVC" AND CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 19.05) run_cmake(VsJustMyCode) endif() diff --git a/Tests/RunCMake/VS10Project/VsCSharpDocumentationFile-check.cmake b/Tests/RunCMake/VS10Project/VsCSharpDocumentationFile-check.cmake new file mode 100644 index 0000000..0393362 --- /dev/null +++ b/Tests/RunCMake/VS10Project/VsCSharpDocumentationFile-check.cmake @@ -0,0 +1,26 @@ +# +# Check C# VS project for required elements +# +set(csProjectFile "${RunCMake_TEST_BINARY_DIR}/foo.csproj") +if(NOT EXISTS "${csProjectFile}") + set(RunCMake_TEST_FAILED "Project file ${csProjectFile} does not exist.") + return() +endif() + +file(STRINGS "${csProjectFile}" lines) + +set(HAVE_DocumentationFile 0) +foreach(line IN LISTS lines) + if(line MATCHES "^ *<DocumentationFile>([^<>]+)</DocumentationFile>") + if(HAVE_DocumentationFile) + set(RunCMake_TEST_FAILED "Documentation node has been generated more than once for\n ${csProjectFile}") + return() + endif() + set(HAVE_DocumentationFile 1) + endif() +endforeach() + +if(NOT HAVE_DocumentationFile) + set(RunCMake_TEST_FAILED "Documentation node has not been generated for\n ${csProjectFile}") + return() +endif() diff --git a/Tests/RunCMake/VS10Project/VsCSharpDocumentationFile.cmake b/Tests/RunCMake/VS10Project/VsCSharpDocumentationFile.cmake new file mode 100644 index 0000000..83b6b97 --- /dev/null +++ b/Tests/RunCMake/VS10Project/VsCSharpDocumentationFile.cmake @@ -0,0 +1,8 @@ +set(CMAKE_CONFIGURATION_TYPES Debug) +enable_language(CSharp) + +add_library(foo SHARED + foo.cs) + +set_target_properties(foo PROPERTIES + VS_DOTNET_DOCUMENTATION_FILE foo.xml) diff --git a/Tests/RunCMake/VS10Project/VsGlobals-check.cmake b/Tests/RunCMake/VS10Project/VsGlobals-check.cmake index 0e7fd45..6a30099 100644 --- a/Tests/RunCMake/VS10Project/VsGlobals-check.cmake +++ b/Tests/RunCMake/VS10Project/VsGlobals-check.cmake @@ -1,44 +1,65 @@ -set(vcProjectFile "${RunCMake_TEST_BINARY_DIR}/foo.vcxproj") -if(NOT EXISTS "${vcProjectFile}") - set(RunCMake_TEST_FAILED "Project file ${vcProjectFile} does not exist.") - return() -endif() +macro(check_project_file projectFile) + if(NOT EXISTS "${projectFile}") + set(RunCMake_TEST_FAILED "Project file ${projectFile} does not exist.") + return() + endif() + + string(REPLACE "${RunCMake_TEST_BINARY_DIR}/" "" projectName ${projectFile}) -set(InsideGlobals FALSE) -set(DefaultLanguageSet FALSE) -set(MinimumVisualStudioVersionSet FALSE) + set(InsideGlobals FALSE) + set(DefaultLanguageSet FALSE) + set(MinimumVisualStudioVersionSet FALSE) + set(TestPropertySet FALSE) -file(STRINGS "${vcProjectFile}" lines) -foreach(line IN LISTS lines) - if(line MATCHES "^ *<PropertyGroup Label=\"Globals\"> *$") - set(InsideGlobals TRUE) - elseif(line MATCHES "^ *<DefaultLanguage>([a-zA-Z\\-]+)</DefaultLanguage> *$") - if("${CMAKE_MATCH_1}" STREQUAL "en-US") - if(InsideGlobals) - message(STATUS "foo.vcxproj has correct DefaultLanguage global property") - set(DefaultLanguageSet TRUE) - else() - message(STATUS "DefaultLanguage is set but not within \"Globals\" property group") + file(STRINGS "${projectFile}" lines) + foreach(line IN LISTS lines) + if(line MATCHES "^ *<PropertyGroup Label=\"Globals\"> *$") + set(InsideGlobals TRUE) + elseif(line MATCHES "^ *<DefaultLanguage>([a-zA-Z\\-]+)</DefaultLanguage> *$") + if("${CMAKE_MATCH_1}" STREQUAL "en-US") + if(InsideGlobals) + message(STATUS "${projectName} has correct DefaultLanguage global property") + set(DefaultLanguageSet TRUE) + else() + message(STATUS "DefaultLanguage is set but not within \"Globals\" property group") + endif() endif() - endif() - elseif(line MATCHES "^ *<MinimumVisualStudioVersion>([0-9\\.]+)</MinimumVisualStudioVersion> *$") - if("${CMAKE_MATCH_1}" STREQUAL "14.0") - if(InsideGlobals) - message(STATUS "foo.vcxproj has correct MinimumVisualStudioVersion global property") - set(MinimumVisualStudioVersionSet TRUE) - else() - message(STATUS "MinimumVisualStudioVersion is set but not within \"Globals\" property group") + elseif(line MATCHES "^ *<MinimumVisualStudioVersion>([0-9\\.]+)</MinimumVisualStudioVersion> *$") + if("${CMAKE_MATCH_1}" STREQUAL "10.0") + if(InsideGlobals) + message(STATUS "${projectName} has correct MinimumVisualStudioVersion global property") + set(MinimumVisualStudioVersionSet TRUE) + else() + message(STATUS "MinimumVisualStudioVersion is set but not within \"Globals\" property group") + endif() + endif() + elseif(line MATCHES "^ *<TestProperty>(.+)</TestProperty> *$") + if("${CMAKE_MATCH_1}" STREQUAL "TestValue") + if(InsideGlobals) + message(STATUS "${projectName} has correct TestProperty global property") + set(TestPropertySet TRUE) + else() + message(STATUS "TestProperty is set but not within \"Globals\" property group") + endif() endif() endif() + endforeach() + + if(NOT DefaultLanguageSet) + set(RunCMake_TEST_FAILED "DefaultLanguage not found or not set correctly in ${projectName}.") + return() + endif() + + if(NOT MinimumVisualStudioVersionSet) + set(RunCMake_TEST_FAILED "MinimumVisualStudioVersion not found or not set correctly in ${projectName}.") + return() endif() -endforeach() -if(NOT DefaultLanguageSet) - set(RunCMake_TEST_FAILED "DefaultLanguageSet not found or not set correctly.") - return() -endif() + if(NOT TestPropertySet) + set(RunCMake_TEST_FAILED "TestProperty not found or not set correctly in ${projectName}.") + return() + endif() +endmacro() -if(NOT MinimumVisualStudioVersionSet) - set(RunCMake_TEST_FAILED "MinimumVisualStudioVersionSet not found or not set correctly.") - return() -endif() +check_project_file("${RunCMake_TEST_BINARY_DIR}/CMakeFiles/${CMAKE_VERSION}/CompilerIdCXX/CompilerIdCXX.vcxproj") +check_project_file("${RunCMake_TEST_BINARY_DIR}/foo.vcxproj") diff --git a/Tests/RunCMake/VS10Project/VsGlobals.cmake b/Tests/RunCMake/VS10Project/VsGlobals.cmake index a3ed5af..09d806d 100644 --- a/Tests/RunCMake/VS10Project/VsGlobals.cmake +++ b/Tests/RunCMake/VS10Project/VsGlobals.cmake @@ -1,8 +1,9 @@ -enable_language(CXX) - set(CMAKE_VS_GLOBALS "DefaultLanguage=en-US" - "MinimumVisualStudioVersion=14.0" + "MinimumVisualStudioVersion=10.0" + "TestProperty=TestValue" ) +enable_language(CXX) + add_library(foo foo.cpp) diff --git a/Tests/RunCMake/VS10Project/VsVCTargetsPath-check.cmake b/Tests/RunCMake/VS10Project/VsVCTargetsPath-check.cmake new file mode 100644 index 0000000..5b1701c --- /dev/null +++ b/Tests/RunCMake/VS10Project/VsVCTargetsPath-check.cmake @@ -0,0 +1,32 @@ +macro(check_project_file projectFile) + set(insideGlobals FALSE) + set(pathFound FALSE) + + if(NOT EXISTS "${projectFile}") + set(RunCMake_TEST_FAILED "Project file ${projectFile} does not exist.") + return() + endif() + + string(REPLACE "${RunCMake_TEST_BINARY_DIR}/" "" projectName ${projectFile}) + + file(STRINGS "${projectFile}" lines) + foreach(line IN LISTS lines) + if(line MATCHES "^ *<PropertyGroup Label=\"Globals\">.*$") + set(insideGlobals TRUE) + elseif(insideGlobals) + if(line MATCHES "^ *</PropertyGroup>.*$") + set(insideGlobals FALSE) + elseif(line MATCHES "^ *<VCTargetsPath>(.+)</VCTargetsPath>*$") + message(STATUS "Found VCTargetsPath = ${CMAKE_MATCH_1} in PropertyGroup 'Globals' in ${projectName}") + set(pathFound TRUE) + endif() + endif() + endforeach() + if(NOT pathFound) + set(RunCMake_TEST_FAILED "VCTargetsPath not found in \"Globals\" propertygroup in ${projectName}") + return() # This should intentionally return from the caller, not the macro + endif() +endmacro() + +check_project_file("${RunCMake_TEST_BINARY_DIR}/CMakeFiles/${CMAKE_VERSION}/CompilerIdCXX/CompilerIdCXX.vcxproj") +check_project_file("${RunCMake_TEST_BINARY_DIR}/foo.vcxproj") diff --git a/Tests/RunCMake/VS10Project/VsVCTargetsPath.cmake b/Tests/RunCMake/VS10Project/VsVCTargetsPath.cmake new file mode 100644 index 0000000..6a6088f --- /dev/null +++ b/Tests/RunCMake/VS10Project/VsVCTargetsPath.cmake @@ -0,0 +1,3 @@ +enable_language(CXX) + +add_library(foo foo.cpp) diff --git a/Tests/RunCMake/message/RunCMakeTest.cmake b/Tests/RunCMake/message/RunCMakeTest.cmake index 3c7e51c..bf6a47e 100644 --- a/Tests/RunCMake/message/RunCMakeTest.cmake +++ b/Tests/RunCMake/message/RunCMakeTest.cmake @@ -11,53 +11,75 @@ run_cmake(warnmessage) run_cmake(errormessage_deprecated) run_cmake(errormessage_dev) -run_cmake_command( - message-loglevel-invalid - ${CMAKE_COMMAND} --loglevel=blah -P ${RunCMake_SOURCE_DIR}/message-all-loglevels.cmake - ) +foreach(opt IN ITEMS loglevel log-level) + run_cmake_command( + message-${opt}-invalid + ${CMAKE_COMMAND} --${opt}=blah -P ${RunCMake_SOURCE_DIR}/message-all-loglevels.cmake + ) + + # Checking various combinations of `message(...)` and log levels `WARNING` to `TRACE` + # - no CLI option -> `WARNING` to `STATUS` output + run_cmake_command( + message-${opt}-default + ${CMAKE_COMMAND} -P ${RunCMake_SOURCE_DIR}/message-all-loglevels.cmake + ) + # - Only `WARNING` output + run_cmake_command( + message-${opt}-warning + ${CMAKE_COMMAND} --${opt}=warning -P ${RunCMake_SOURCE_DIR}/message-all-loglevels.cmake + ) + # - Only `WARNING` and `NOTICE` output + run_cmake_command( + message-${opt}-notice + ${CMAKE_COMMAND} --${opt}=notice -P ${RunCMake_SOURCE_DIR}/message-all-loglevels.cmake + ) + # - `WARNING` to `STATUS` output + run_cmake_command( + message-${opt}-status + ${CMAKE_COMMAND} --${opt}=status -P ${RunCMake_SOURCE_DIR}/message-all-loglevels.cmake + ) + # - `WARNING` to `VERBOSE` output + run_cmake_command( + message-${opt}-verbose + ${CMAKE_COMMAND} --${opt}=verbose -P ${RunCMake_SOURCE_DIR}/message-all-loglevels.cmake + ) + # - `WARNING` to `DEBUG` output + run_cmake_command( + message-${opt}-debug + ${CMAKE_COMMAND} --${opt}=debug -P ${RunCMake_SOURCE_DIR}/message-all-loglevels.cmake + ) + # - `WARNING` to `TRACE` output + run_cmake_command( + message-${opt}-trace + ${CMAKE_COMMAND} --${opt}=trace -P ${RunCMake_SOURCE_DIR}/message-all-loglevels.cmake + ) +endforeach() -# Checking various combinations of `message(...)` and log levels `WARNING` to `TRACE` -# - no CLI option -> `WARNING` to `STATUS` output -run_cmake_command( - message-loglevel-default - ${CMAKE_COMMAND} -P ${RunCMake_SOURCE_DIR}/message-all-loglevels.cmake - ) -# - Only `WARNING` output -run_cmake_command( - message-loglevel-warning - ${CMAKE_COMMAND} --loglevel=warning -P ${RunCMake_SOURCE_DIR}/message-all-loglevels.cmake - ) -# - Only `WARNING` and `NOTICE` output -run_cmake_command( - message-loglevel-notice - ${CMAKE_COMMAND} --loglevel=notice -P ${RunCMake_SOURCE_DIR}/message-all-loglevels.cmake - ) -# - `WARNING` to `STATUS` output run_cmake_command( - message-loglevel-status - ${CMAKE_COMMAND} --loglevel=status -P ${RunCMake_SOURCE_DIR}/message-all-loglevels.cmake + message-log-level-override + ${CMAKE_COMMAND} --log-level=debug -DCMAKE_MESSAGE_LOG_LEVEL=TRACE -P ${RunCMake_SOURCE_DIR}/message-all-loglevels.cmake ) -# - `WARNING` to `VERBOSE` output + run_cmake_command( - message-loglevel-verbose - ${CMAKE_COMMAND} --loglevel=verbose -P ${RunCMake_SOURCE_DIR}/message-all-loglevels.cmake + message-indent + ${CMAKE_COMMAND} -P ${RunCMake_SOURCE_DIR}/message-indent.cmake ) -# - `WARNING` to `DEBUG` output run_cmake_command( - message-loglevel-debug - ${CMAKE_COMMAND} --loglevel=debug -P ${RunCMake_SOURCE_DIR}/message-all-loglevels.cmake + message-indent-multiline + ${CMAKE_COMMAND} -P ${RunCMake_SOURCE_DIR}/message-indent-multiline.cmake ) -# - `WARNING` to `TRACE` output + run_cmake_command( - message-loglevel-trace - ${CMAKE_COMMAND} --loglevel=trace -P ${RunCMake_SOURCE_DIR}/message-all-loglevels.cmake + message-context-cli + ${CMAKE_COMMAND} --log-level=trace --log-context -P ${RunCMake_SOURCE_DIR}/message-context.cmake ) run_cmake_command( - message-indent - ${CMAKE_COMMAND} -P ${RunCMake_SOURCE_DIR}/message-indent.cmake + message-context-cache + ${CMAKE_COMMAND} -DCMAKE_MESSAGE_LOG_LEVEL=TRACE -DCMAKE_MESSAGE_CONTEXT_SHOW=ON -P ${RunCMake_SOURCE_DIR}/message-context.cmake ) + run_cmake_command( - message-indent-multiline - ${CMAKE_COMMAND} -P ${RunCMake_SOURCE_DIR}/message-indent-multiline.cmake + message-context-cli-wins-cache + ${CMAKE_COMMAND} --log-level=verbose --log-context -DCMAKE_MESSAGE_CONTEXT_SHOW=OFF -P ${RunCMake_SOURCE_DIR}/message-context.cmake ) diff --git a/Tests/RunCMake/message/message-context-cache-stdout.txt b/Tests/RunCMake/message/message-context-cache-stdout.txt new file mode 100644 index 0000000..af18c15 --- /dev/null +++ b/Tests/RunCMake/message/message-context-cache-stdout.txt @@ -0,0 +1,8 @@ +-- Begin context output test +-- \[top\] Top: before +-- \[top\.foo\.bar\] <-- indent -->bar VERBOSE message +-- \[top\.foo\] foo TRACE message +-- \[top\.foo\.baz\] This is the multi-line +\[top\.foo\.baz\] baz DEBUG message +-- \[top\] Top: after +-- End of context output test diff --git a/Tests/RunCMake/message/message-context-cli-stdout.txt b/Tests/RunCMake/message/message-context-cli-stdout.txt new file mode 100644 index 0000000..af18c15 --- /dev/null +++ b/Tests/RunCMake/message/message-context-cli-stdout.txt @@ -0,0 +1,8 @@ +-- Begin context output test +-- \[top\] Top: before +-- \[top\.foo\.bar\] <-- indent -->bar VERBOSE message +-- \[top\.foo\] foo TRACE message +-- \[top\.foo\.baz\] This is the multi-line +\[top\.foo\.baz\] baz DEBUG message +-- \[top\] Top: after +-- End of context output test diff --git a/Tests/RunCMake/message/message-context-cli-wins-cache-stdout.txt b/Tests/RunCMake/message/message-context-cli-wins-cache-stdout.txt new file mode 100644 index 0000000..157db97 --- /dev/null +++ b/Tests/RunCMake/message/message-context-cli-wins-cache-stdout.txt @@ -0,0 +1,5 @@ +-- Begin context output test +-- \[top\] Top: before +-- \[top\.foo\.bar\] <-- indent -->bar VERBOSE message +-- \[top\] Top: after +-- End of context output test diff --git a/Tests/RunCMake/message/message-context.cmake b/Tests/RunCMake/message/message-context.cmake new file mode 100644 index 0000000..93d4cd9 --- /dev/null +++ b/Tests/RunCMake/message/message-context.cmake @@ -0,0 +1,27 @@ +function(bar) + list(APPEND CMAKE_MESSAGE_CONTEXT "bar") + list(APPEND CMAKE_MESSAGE_INDENT "<-- indent -->") + message(VERBOSE "bar VERBOSE message") +endfunction() + +function(baz) + list(APPEND CMAKE_MESSAGE_CONTEXT "baz") + message(DEBUG "This is the multi-line\nbaz DEBUG message") +endfunction() + +function(foo) + list(APPEND CMAKE_MESSAGE_CONTEXT "foo") + bar() + message(TRACE "foo TRACE message") + baz() +endfunction() + +message(STATUS "Begin context output test") +list(APPEND CMAKE_MESSAGE_CONTEXT "top") + +message(STATUS "Top: before") +foo() +message(STATUS "Top: after") + +list(POP_BACK CMAKE_MESSAGE_CONTEXT) +message(STATUS "End of context output test") diff --git a/Tests/RunCMake/message/message-log-level-debug-stderr.txt b/Tests/RunCMake/message/message-log-level-debug-stderr.txt new file mode 100644 index 0000000..efec736 --- /dev/null +++ b/Tests/RunCMake/message/message-log-level-debug-stderr.txt @@ -0,0 +1,12 @@ +^CMake Deprecation Warning at.*/Tests/RunCMake/message/message-all-loglevels\.cmake:2 \(message\): + Deprecation warning ++ +CMake Warning \(dev\) at.*/Tests/RunCMake/message/message-all-loglevels\.cmake:3 \(message\): + Author warning message +This warning is for project developers\. Use -Wno-dev to suppress it\. ++ +CMake Warning at.*/Tests/RunCMake/message/message-all-loglevels\.cmake:4 \(message\): + Warning message ++ +Default NOTICE message +NOTICE message$ diff --git a/Tests/RunCMake/message/message-log-level-debug-stdout.txt b/Tests/RunCMake/message/message-log-level-debug-stdout.txt new file mode 100644 index 0000000..feee110 --- /dev/null +++ b/Tests/RunCMake/message/message-log-level-debug-stdout.txt @@ -0,0 +1,3 @@ +-- STATUS message +-- VERBOSE message +-- DEBUG message$ diff --git a/Tests/RunCMake/message/message-log-level-default-stderr.txt b/Tests/RunCMake/message/message-log-level-default-stderr.txt new file mode 100644 index 0000000..efec736 --- /dev/null +++ b/Tests/RunCMake/message/message-log-level-default-stderr.txt @@ -0,0 +1,12 @@ +^CMake Deprecation Warning at.*/Tests/RunCMake/message/message-all-loglevels\.cmake:2 \(message\): + Deprecation warning ++ +CMake Warning \(dev\) at.*/Tests/RunCMake/message/message-all-loglevels\.cmake:3 \(message\): + Author warning message +This warning is for project developers\. Use -Wno-dev to suppress it\. ++ +CMake Warning at.*/Tests/RunCMake/message/message-all-loglevels\.cmake:4 \(message\): + Warning message ++ +Default NOTICE message +NOTICE message$ diff --git a/Tests/RunCMake/message/message-log-level-default-stdout.txt b/Tests/RunCMake/message/message-log-level-default-stdout.txt new file mode 100644 index 0000000..b5d6acb --- /dev/null +++ b/Tests/RunCMake/message/message-log-level-default-stdout.txt @@ -0,0 +1 @@ +-- STATUS message$ diff --git a/Tests/RunCMake/message/message-log-level-invalid-result.txt b/Tests/RunCMake/message/message-log-level-invalid-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/message/message-log-level-invalid-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/message/message-log-level-invalid-stderr.txt b/Tests/RunCMake/message/message-log-level-invalid-stderr.txt new file mode 100644 index 0000000..a166bbc --- /dev/null +++ b/Tests/RunCMake/message/message-log-level-invalid-stderr.txt @@ -0,0 +1 @@ +CMake Error: Invalid level specified for --log-level diff --git a/Tests/RunCMake/message/message-log-level-notice-stderr.txt b/Tests/RunCMake/message/message-log-level-notice-stderr.txt new file mode 100644 index 0000000..efec736 --- /dev/null +++ b/Tests/RunCMake/message/message-log-level-notice-stderr.txt @@ -0,0 +1,12 @@ +^CMake Deprecation Warning at.*/Tests/RunCMake/message/message-all-loglevels\.cmake:2 \(message\): + Deprecation warning ++ +CMake Warning \(dev\) at.*/Tests/RunCMake/message/message-all-loglevels\.cmake:3 \(message\): + Author warning message +This warning is for project developers\. Use -Wno-dev to suppress it\. ++ +CMake Warning at.*/Tests/RunCMake/message/message-all-loglevels\.cmake:4 \(message\): + Warning message ++ +Default NOTICE message +NOTICE message$ diff --git a/Tests/RunCMake/message/message-log-level-override-stderr.txt b/Tests/RunCMake/message/message-log-level-override-stderr.txt new file mode 100644 index 0000000..efec736 --- /dev/null +++ b/Tests/RunCMake/message/message-log-level-override-stderr.txt @@ -0,0 +1,12 @@ +^CMake Deprecation Warning at.*/Tests/RunCMake/message/message-all-loglevels\.cmake:2 \(message\): + Deprecation warning ++ +CMake Warning \(dev\) at.*/Tests/RunCMake/message/message-all-loglevels\.cmake:3 \(message\): + Author warning message +This warning is for project developers\. Use -Wno-dev to suppress it\. ++ +CMake Warning at.*/Tests/RunCMake/message/message-all-loglevels\.cmake:4 \(message\): + Warning message ++ +Default NOTICE message +NOTICE message$ diff --git a/Tests/RunCMake/message/message-log-level-override-stdout.txt b/Tests/RunCMake/message/message-log-level-override-stdout.txt new file mode 100644 index 0000000..feee110 --- /dev/null +++ b/Tests/RunCMake/message/message-log-level-override-stdout.txt @@ -0,0 +1,3 @@ +-- STATUS message +-- VERBOSE message +-- DEBUG message$ diff --git a/Tests/RunCMake/message/message-log-level-status-stderr.txt b/Tests/RunCMake/message/message-log-level-status-stderr.txt new file mode 100644 index 0000000..efec736 --- /dev/null +++ b/Tests/RunCMake/message/message-log-level-status-stderr.txt @@ -0,0 +1,12 @@ +^CMake Deprecation Warning at.*/Tests/RunCMake/message/message-all-loglevels\.cmake:2 \(message\): + Deprecation warning ++ +CMake Warning \(dev\) at.*/Tests/RunCMake/message/message-all-loglevels\.cmake:3 \(message\): + Author warning message +This warning is for project developers\. Use -Wno-dev to suppress it\. ++ +CMake Warning at.*/Tests/RunCMake/message/message-all-loglevels\.cmake:4 \(message\): + Warning message ++ +Default NOTICE message +NOTICE message$ diff --git a/Tests/RunCMake/message/message-log-level-status-stdout.txt b/Tests/RunCMake/message/message-log-level-status-stdout.txt new file mode 100644 index 0000000..b5d6acb --- /dev/null +++ b/Tests/RunCMake/message/message-log-level-status-stdout.txt @@ -0,0 +1 @@ +-- STATUS message$ diff --git a/Tests/RunCMake/message/message-log-level-trace-stderr.txt b/Tests/RunCMake/message/message-log-level-trace-stderr.txt new file mode 100644 index 0000000..efec736 --- /dev/null +++ b/Tests/RunCMake/message/message-log-level-trace-stderr.txt @@ -0,0 +1,12 @@ +^CMake Deprecation Warning at.*/Tests/RunCMake/message/message-all-loglevels\.cmake:2 \(message\): + Deprecation warning ++ +CMake Warning \(dev\) at.*/Tests/RunCMake/message/message-all-loglevels\.cmake:3 \(message\): + Author warning message +This warning is for project developers\. Use -Wno-dev to suppress it\. ++ +CMake Warning at.*/Tests/RunCMake/message/message-all-loglevels\.cmake:4 \(message\): + Warning message ++ +Default NOTICE message +NOTICE message$ diff --git a/Tests/RunCMake/message/message-log-level-trace-stdout.txt b/Tests/RunCMake/message/message-log-level-trace-stdout.txt new file mode 100644 index 0000000..3d36a7f --- /dev/null +++ b/Tests/RunCMake/message/message-log-level-trace-stdout.txt @@ -0,0 +1,4 @@ +-- STATUS message +-- VERBOSE message +-- DEBUG message +-- TRACE message$ diff --git a/Tests/RunCMake/message/message-log-level-verbose-stderr.txt b/Tests/RunCMake/message/message-log-level-verbose-stderr.txt new file mode 100644 index 0000000..efec736 --- /dev/null +++ b/Tests/RunCMake/message/message-log-level-verbose-stderr.txt @@ -0,0 +1,12 @@ +^CMake Deprecation Warning at.*/Tests/RunCMake/message/message-all-loglevels\.cmake:2 \(message\): + Deprecation warning ++ +CMake Warning \(dev\) at.*/Tests/RunCMake/message/message-all-loglevels\.cmake:3 \(message\): + Author warning message +This warning is for project developers\. Use -Wno-dev to suppress it\. ++ +CMake Warning at.*/Tests/RunCMake/message/message-all-loglevels\.cmake:4 \(message\): + Warning message ++ +Default NOTICE message +NOTICE message$ diff --git a/Tests/RunCMake/message/message-log-level-verbose-stdout.txt b/Tests/RunCMake/message/message-log-level-verbose-stdout.txt new file mode 100644 index 0000000..47c0846 --- /dev/null +++ b/Tests/RunCMake/message/message-log-level-verbose-stdout.txt @@ -0,0 +1,2 @@ +-- STATUS message +-- VERBOSE message$ diff --git a/Tests/RunCMake/message/message-log-level-warning-stderr.txt b/Tests/RunCMake/message/message-log-level-warning-stderr.txt new file mode 100644 index 0000000..c721b06 --- /dev/null +++ b/Tests/RunCMake/message/message-log-level-warning-stderr.txt @@ -0,0 +1,9 @@ +^CMake Deprecation Warning at.*/Tests/RunCMake/message/message-all-loglevels\.cmake:2 \(message\): + Deprecation warning ++ +CMake Warning \(dev\) at.*/Tests/RunCMake/message/message-all-loglevels\.cmake:3 \(message\): + Author warning message +This warning is for project developers\. Use -Wno-dev to suppress it\. ++ +CMake Warning at.*/Tests/RunCMake/message/message-all-loglevels\.cmake:4 \(message\): + Warning message$ diff --git a/Tests/RunCMake/message/message-loglevel-debug-stdout.txt b/Tests/RunCMake/message/message-loglevel-debug-stdout.txt index 1452137..feee110 100644 --- a/Tests/RunCMake/message/message-loglevel-debug-stdout.txt +++ b/Tests/RunCMake/message/message-loglevel-debug-stdout.txt @@ -1,3 +1,3 @@ -- STATUS message -- VERBOSE message --- DEBUG message +-- DEBUG message$ diff --git a/Tests/RunCMake/message/message-loglevel-default-stdout.txt b/Tests/RunCMake/message/message-loglevel-default-stdout.txt index 809f4cc..b5d6acb 100644 --- a/Tests/RunCMake/message/message-loglevel-default-stdout.txt +++ b/Tests/RunCMake/message/message-loglevel-default-stdout.txt @@ -1 +1 @@ --- STATUS message +-- STATUS message$ diff --git a/Tests/RunCMake/message/message-loglevel-status-stdout.txt b/Tests/RunCMake/message/message-loglevel-status-stdout.txt index 809f4cc..b5d6acb 100644 --- a/Tests/RunCMake/message/message-loglevel-status-stdout.txt +++ b/Tests/RunCMake/message/message-loglevel-status-stdout.txt @@ -1 +1 @@ --- STATUS message +-- STATUS message$ diff --git a/Tests/RunCMake/message/message-loglevel-trace-stdout.txt b/Tests/RunCMake/message/message-loglevel-trace-stdout.txt index 1cfce6f..3d36a7f 100644 --- a/Tests/RunCMake/message/message-loglevel-trace-stdout.txt +++ b/Tests/RunCMake/message/message-loglevel-trace-stdout.txt @@ -1,4 +1,4 @@ -- STATUS message -- VERBOSE message -- DEBUG message --- TRACE message +-- TRACE message$ diff --git a/Tests/RunCMake/message/message-loglevel-verbose-stdout.txt b/Tests/RunCMake/message/message-loglevel-verbose-stdout.txt index c15d43f..47c0846 100644 --- a/Tests/RunCMake/message/message-loglevel-verbose-stdout.txt +++ b/Tests/RunCMake/message/message-loglevel-verbose-stdout.txt @@ -1,2 +1,2 @@ -- STATUS message --- VERBOSE message +-- VERBOSE message$ diff --git a/Utilities/Release/push.bash b/Utilities/Release/push.bash index 1c8efe9..a1c6651 100755 --- a/Utilities/Release/push.bash +++ b/Utilities/Release/push.bash @@ -50,6 +50,9 @@ if test -z "$dir"; then dir="v${version}" fi readonly dir +if ! test -d "${dest}/${dir}"; then + mkdir "${dest}/${dir}" +fi for f in cmake-${version}*; do if ! test -f "${f}"; then @@ -372,6 +372,7 @@ CMAKE_CXX_SOURCES="\ cmLDConfigTool \ cmLinkDirectoriesCommand \ cmLinkItem \ + cmLinkItemGraphVisitor \ cmLinkLineComputer \ cmLinkLineDeviceComputer \ cmListCommand \ |