summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Help/command/if.rst54
-rw-r--r--Help/generator/Ninja Multi-Config.rst31
-rw-r--r--Help/release/dev/cuda-nvcc-ccache-symlink.rst9
-rw-r--r--Modules/CMakeDetermineCUDACompiler.cmake15
-rw-r--r--Modules/FindCUDA.cmake15
-rw-r--r--Modules/FindCUDAToolkit.cmake14
-rw-r--r--Modules/FindPostgreSQL.cmake11
-rw-r--r--Source/CMakeVersion.cmake2
-rw-r--r--Source/QtDialog/CMakeLists.txt5
-rw-r--r--Source/cmGccDepfileReader.cxx23
-rw-r--r--Source/cmGccDepfileReader.h6
-rw-r--r--Source/cmLocalNinjaGenerator.cxx13
-rw-r--r--Source/cmLocalNinjaGenerator.h3
-rw-r--r--Source/cmMakefile.cxx2
-rw-r--r--Source/cmMakefileTargetGenerator.cxx63
-rw-r--r--Source/cmNinjaNormalTargetGenerator.cxx20
-rw-r--r--Source/cmSystemTools.cxx24
-rw-r--r--Source/cmSystemTools.h6
-rw-r--r--Source/cmcmd.cxx9
-rw-r--r--Tests/RunCMake/CommandLine/trace-expand.cmake1
-rw-r--r--Tests/RunCMake/NinjaMultiConfig/PostBuild-debug-in-release-graph-build-stdout.txt2
-rw-r--r--Tests/RunCMake/NinjaMultiConfig/PostBuild-release-build-stdout.txt3
-rw-r--r--Tests/RunCMake/NinjaMultiConfig/PostBuild.cmake6
-rw-r--r--Tests/RunCMake/NinjaMultiConfig/RunCMakeTest.cmake6
24 files changed, 250 insertions, 93 deletions
diff --git a/Help/command/if.rst b/Help/command/if.rst
index 72d328d..c51d2bc 100644
--- a/Help/command/if.rst
+++ b/Help/command/if.rst
@@ -47,7 +47,8 @@ as ``EXISTS``, ``COMMAND``, and ``DEFINED``. Then binary tests such as
and ``MATCHES``. Then the boolean operators in the order ``NOT``, ``AND``,
and finally ``OR``.
-Possible conditions are:
+Basic Expressions
+"""""""""""""""""
``if(<constant>)``
True if the constant is ``1``, ``ON``, ``YES``, ``TRUE``, ``Y``,
@@ -62,6 +63,9 @@ Possible conditions are:
True if given a variable that is defined to a value that is not a false
constant. False otherwise. (Note macro arguments are not variables.)
+Logic Operators
+"""""""""""""""
+
``if(NOT <condition>)``
True if the condition is not true.
@@ -71,6 +75,15 @@ Possible conditions are:
``if(<cond1> OR <cond2>)``
True if either condition would be considered true individually.
+``if((condition) AND (condition OR (condition)))``
+ The conditions inside the parenthesis are evaluated first and then
+ the remaining condition is evaluated as in the other examples.
+ Where there are nested parenthesis the innermost are evaluated as part
+ of evaluating the condition that contains them.
+
+Existence Checks
+""""""""""""""""
+
``if(COMMAND command-name)``
True if the given name is a command, macro or function that can be
invoked.
@@ -89,6 +102,21 @@ Possible conditions are:
True if the given name is an existing test name created by the
:command:`add_test` command.
+``if(DEFINED <name>|CACHE{<name>}|ENV{<name>})``
+ True if a variable, cache variable or environment variable
+ with given ``<name>`` is defined. The value of the variable
+ does not matter. Note that macro arguments are not variables.
+
+ .. versionadded:: 3.14
+ Added support for ``CACHE{<name>}`` variables.
+
+``if(<variable|string> IN_LIST <variable>)``
+ .. versionadded:: 3.3
+ True if the given element is contained in the named list variable.
+
+File Operations
+"""""""""""""""
+
``if(EXISTS path-to-file-or-directory)``
True if the named file or directory exists. Behavior is well-defined
only for full paths. Resolves symbolic links, i.e. if the named file or
@@ -114,6 +142,9 @@ Possible conditions are:
``if(IS_ABSOLUTE path)``
True if the given path is an absolute path.
+Comparisons
+"""""""""""
+
``if(<variable|string> MATCHES regex)``
True if the given string or variable's value matches the given regular
condition. See :ref:`Regex Specification` for regex format.
@@ -165,6 +196,9 @@ Possible conditions are:
True if the given string or variable's value is lexicographically greater
than or equal to the string or variable on the right.
+Version Comparisons
+"""""""""""""""""""
+
``if(<variable|string> VERSION_LESS <variable|string>)``
Component-wise integer version number comparison (version format is
``major[.minor[.patch[.tweak]]]``, omitted components are treated as zero).
@@ -197,24 +231,6 @@ Possible conditions are:
Any non-integer version component or non-integer trailing part of a version
component effectively truncates the string at that point.
-``if(<variable|string> IN_LIST <variable>)``
- .. versionadded:: 3.3
- True if the given element is contained in the named list variable.
-
-``if(DEFINED <name>|CACHE{<name>}|ENV{<name>})``
- True if a variable, cache variable or environment variable
- with given ``<name>`` is defined. The value of the variable
- does not matter. Note that macro arguments are not variables.
-
- .. versionadded:: 3.14
- Added support for ``CACHE{<name>}`` variables.
-
-``if((condition) AND (condition OR (condition)))``
- The conditions inside the parenthesis are evaluated first and then
- the remaining condition is evaluated as in the previous examples.
- Where there are nested parenthesis the innermost are evaluated as part
- of evaluating the condition that contains them.
-
Variable Expansion
^^^^^^^^^^^^^^^^^^
diff --git a/Help/generator/Ninja Multi-Config.rst b/Help/generator/Ninja Multi-Config.rst
index d1df42b..8901192 100644
--- a/Help/generator/Ninja Multi-Config.rst
+++ b/Help/generator/Ninja Multi-Config.rst
@@ -130,3 +130,34 @@ output config using the ``Release`` command config. The ``Release`` build of
the ``generator`` target is called with ``Debug.txt Debug Release`` as
arguments. The command depends on the ``Release`` builds of ``tgt1`` and
``tgt4``, and the ``Debug`` builds of ``tgt2`` and ``tgt3``.
+
+``PRE_BUILD``, ``PRE_LINK``, and ``POST_BUILD`` custom commands for targets
+only get run in their "native" configuration (the ``Release`` configuration in
+the ``build-Release.ninja`` file) unless they have no ``BYPRODUCTS`` or their
+``BYPRODUCTS`` are unique per config. Consider the following example:
+
+.. code-block:: cmake
+
+ add_executable(exe main.c)
+ add_custom_command(
+ TARGET exe
+ POST_BUILD
+ COMMAND ${CMAKE_COMMAND} -E echo "Running no-byproduct command"
+ )
+ add_custom_command(
+ TARGET exe
+ POST_BUILD
+ COMMAND ${CMAKE_COMMAND} -E echo "Running separate-byproduct command for $<CONFIG>"
+ BYPRODUCTS $<CONFIG>.txt
+ )
+ add_custom_command(
+ TARGET exe
+ POST_BUILD
+ COMMAND ${CMAKE_COMMAND} -E echo "Running common-byproduct command for $<CONFIG>"
+ BYPRODUCTS exe.txt
+ )
+
+In this example, if you build ``exe:Debug`` in ``build-Release.ninja``, the
+first and second custom commands get run, since their byproducts are unique
+per-config, but the last custom command does not. However, if you build
+``exe:Release`` in ``build-Release.ninja``, all three custom commands get run.
diff --git a/Help/release/dev/cuda-nvcc-ccache-symlink.rst b/Help/release/dev/cuda-nvcc-ccache-symlink.rst
new file mode 100644
index 0000000..4d38047
--- /dev/null
+++ b/Help/release/dev/cuda-nvcc-ccache-symlink.rst
@@ -0,0 +1,9 @@
+cuda-nvcc-ccache-symlink
+------------------------
+
+* ``CUDA`` language support now works when ``nvcc`` is a symbolic link,
+ for example due to a ``ccache`` or ``colornvcc`` wrapper script.
+
+* The :module:`FindCUDAToolkit` module gained support for finding CUDA
+ toolkits when ``nvcc`` is a symbolic link,
+ for example due to a ``ccache`` or ``colornvcc`` wrapper script.
diff --git a/Modules/CMakeDetermineCUDACompiler.cmake b/Modules/CMakeDetermineCUDACompiler.cmake
index 578729c..c77fc3a 100644
--- a/Modules/CMakeDetermineCUDACompiler.cmake
+++ b/Modules/CMakeDetermineCUDACompiler.cmake
@@ -172,7 +172,20 @@ if(NOT CMAKE_CUDA_COMPILER_ID_RUN)
endif()
endif()
- get_filename_component(CMAKE_CUDA_COMPILER_TOOLKIT_ROOT "${_CUDA_NVCC_EXECUTABLE}" DIRECTORY)
+ # If NVCC is a symlink due to a wrapper script (e.g. ccache or colornvcc), then invoke it to find the
+ # real non-scattered toolkit.
+ if(IS_SYMLINK ${_CUDA_NVCC_EXECUTABLE})
+ execute_process(COMMAND ${_CUDA_NVCC_EXECUTABLE} "-v" "__cmake_determine_cuda" ERROR_VARIABLE NVCC_ERR)
+ if(NVCC_ERR MATCHES " _HERE_=([^\r\n]*)")
+ set(CMAKE_CUDA_COMPILER_TOOLKIT_ROOT "${CMAKE_MATCH_1}")
+ else()
+ message(FATAL_ERROR "Could not execute nvcc with -v.")
+ endif()
+ unset(NVCC_ERR)
+ else()
+ get_filename_component(CMAKE_CUDA_COMPILER_TOOLKIT_ROOT "${_CUDA_NVCC_EXECUTABLE}" DIRECTORY)
+ endif()
+
set(CMAKE_CUDA_DEVICE_LINKER "${CMAKE_CUDA_COMPILER_TOOLKIT_ROOT}/nvlink${CMAKE_EXECUTABLE_SUFFIX}")
set(CMAKE_CUDA_FATBINARY "${CMAKE_CUDA_COMPILER_TOOLKIT_ROOT}/fatbinary${CMAKE_EXECUTABLE_SUFFIX}")
get_filename_component(CMAKE_CUDA_COMPILER_TOOLKIT_ROOT "${CMAKE_CUDA_COMPILER_TOOLKIT_ROOT}" DIRECTORY)
diff --git a/Modules/FindCUDA.cmake b/Modules/FindCUDA.cmake
index 6daf81d..240f0a5 100644
--- a/Modules/FindCUDA.cmake
+++ b/Modules/FindCUDA.cmake
@@ -834,7 +834,20 @@ if(NOT CUDA_TOOLKIT_ROOT_DIR AND NOT CMAKE_CROSSCOMPILING)
)
if (CUDA_TOOLKIT_ROOT_DIR_NVCC)
- get_filename_component(CUDA_TOOLKIT_ROOT_DIR_NVCC_PAR "${CUDA_TOOLKIT_ROOT_DIR_NVCC}" DIRECTORY)
+ # If NVCC is a symlink due to a wrapper script (e.g. ccache or colornvcc), then invoke it to find the
+ # real non-scattered toolkit.
+ if(IS_SYMLINK ${CUDA_TOOLKIT_ROOT_DIR_NVCC})
+ execute_process(COMMAND ${CUDA_TOOLKIT_ROOT_DIR_NVCC} "-v" "__cmake_determine_cuda" ERROR_VARIABLE NVCC_ERR)
+ if(NVCC_ERR MATCHES " _HERE_=([^\r\n]*)")
+ set(CUDA_TOOLKIT_ROOT_DIR_NVCC_PAR "${CMAKE_MATCH_1}")
+ else()
+ message(FATAL_ERROR "Could not execute nvcc with -v.")
+ endif()
+ unset(NVCC_ERR)
+ else()
+ get_filename_component(CUDA_TOOLKIT_ROOT_DIR_NVCC_PAR "${CUDA_TOOLKIT_ROOT_DIR_NVCC}" DIRECTORY)
+ endif()
+
get_filename_component(CUDA_TOOLKIT_ROOT_DIR "${CUDA_TOOLKIT_ROOT_DIR_NVCC_PAR}" DIRECTORY CACHE)
string(REGEX REPLACE "[/\\\\]?bin[64]*[/\\\\]?$" "" CUDA_TOOLKIT_ROOT_DIR ${CUDA_TOOLKIT_ROOT_DIR})
# We need to force this back into the cache.
diff --git a/Modules/FindCUDAToolkit.cmake b/Modules/FindCUDAToolkit.cmake
index 61e264b..0d80c80 100644
--- a/Modules/FindCUDAToolkit.cmake
+++ b/Modules/FindCUDAToolkit.cmake
@@ -519,7 +519,19 @@ else()
endif()
if(CUDAToolkit_NVCC_EXECUTABLE)
- get_filename_component(CUDAToolkit_BIN_DIR "${CUDAToolkit_NVCC_EXECUTABLE}" DIRECTORY)
+ # If NVCC is a symlink due to a wrapper script (e.g. ccache or colornvcc), then invoke it to find the
+ # real non-scattered toolkit.
+ if(IS_SYMLINK ${CUDAToolkit_NVCC_EXECUTABLE})
+ execute_process(COMMAND ${CUDAToolkit_NVCC_EXECUTABLE} "-v" "__cmake_determine_cuda" ERROR_VARIABLE NVCC_ERR)
+ if(NVCC_ERR MATCHES " _HERE_=([^\r\n]*)")
+ set(CUDAToolkit_BIN_DIR "${CMAKE_MATCH_1}")
+ else()
+ message(FATAL_ERROR "Could not execute nvcc with -v.")
+ endif()
+ unset(NVCC_ERR)
+ else()
+ get_filename_component(CUDAToolkit_BIN_DIR "${CUDAToolkit_NVCC_EXECUTABLE}" DIRECTORY)
+ endif()
set(CUDAToolkit_BIN_DIR "${CUDAToolkit_BIN_DIR}" CACHE PATH "" FORCE)
mark_as_advanced(CUDAToolkit_BIN_DIR)
diff --git a/Modules/FindPostgreSQL.cmake b/Modules/FindPostgreSQL.cmake
index cd50d8c..911210f 100644
--- a/Modules/FindPostgreSQL.cmake
+++ b/Modules/FindPostgreSQL.cmake
@@ -247,7 +247,7 @@ endif()
# Did we find anything?
include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake)
find_package_handle_standard_args(PostgreSQL
- REQUIRED_VARS PostgreSQL_LIBRARY PostgreSQL_INCLUDE_DIR PostgreSQL_TYPE_INCLUDE_DIR
+ REQUIRED_VARS PostgreSQL_LIBRARY PostgreSQL_INCLUDE_DIR
VERSION_VAR PostgreSQL_VERSION_STRING)
set(PostgreSQL_FOUND ${POSTGRESQL_FOUND})
@@ -271,16 +271,19 @@ endfunction()
# Now try to get the include and library path.
if(PostgreSQL_FOUND)
+ set(PostgreSQL_INCLUDE_DIRS ${PostgreSQL_INCLUDE_DIR})
+ if(PostgreSQL_TYPE_INCLUDE_DIR)
+ list(APPEND PostgreSQL_INCLUDE_DIRS ${PostgreSQL_TYPE_INCLUDE_DIR})
+ endif()
+ set(PostgreSQL_LIBRARY_DIRS ${PostgreSQL_LIBRARY_DIR} )
if (NOT TARGET PostgreSQL::PostgreSQL)
add_library(PostgreSQL::PostgreSQL UNKNOWN IMPORTED)
set_target_properties(PostgreSQL::PostgreSQL PROPERTIES
- INTERFACE_INCLUDE_DIRECTORIES "${PostgreSQL_INCLUDE_DIR};${PostgreSQL_TYPE_INCLUDE_DIR}")
+ INTERFACE_INCLUDE_DIRECTORIES "${PostgreSQL_INCLUDE_DIRS}")
__postgresql_import_library(PostgreSQL::PostgreSQL PostgreSQL_LIBRARY "")
__postgresql_import_library(PostgreSQL::PostgreSQL PostgreSQL_LIBRARY "RELEASE")
__postgresql_import_library(PostgreSQL::PostgreSQL PostgreSQL_LIBRARY "DEBUG")
endif ()
- set(PostgreSQL_INCLUDE_DIRS ${PostgreSQL_INCLUDE_DIR} ${PostgreSQL_TYPE_INCLUDE_DIR} )
- set(PostgreSQL_LIBRARY_DIRS ${PostgreSQL_LIBRARY_DIR} )
endif()
mark_as_advanced(PostgreSQL_INCLUDE_DIR PostgreSQL_TYPE_INCLUDE_DIR)
diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake
index 9f0ac8b..a5cf411 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 19)
-set(CMake_VERSION_PATCH 20210110)
+set(CMake_VERSION_PATCH 20210112)
#set(CMake_VERSION_RC 0)
set(CMake_VERSION_IS_DIRTY 0)
diff --git a/Source/QtDialog/CMakeLists.txt b/Source/QtDialog/CMakeLists.txt
index d8f89d6..0c263bb 100644
--- a/Source/QtDialog/CMakeLists.txt
+++ b/Source/QtDialog/CMakeLists.txt
@@ -213,6 +213,7 @@ else()
qt_wrap_cpp(MOC_BUILT_SRCS ${MOC_SRCS})
qt_add_resources(QRC_BUILT_SRCS ${QRC_SRCS})
endif()
+add_library(CMakeGUIQRCLib OBJECT ${QRC_BUILT_SRCS})
if (FALSE) # CMake's bootstrap binary does not support automoc
set(CMAKE_AUTOMOC 1)
@@ -221,8 +222,7 @@ if (FALSE) # CMake's bootstrap binary does not support automoc
else ()
list(APPEND SRCS
${UI_BUILT_SRCS}
- ${MOC_BUILT_SRCS}
- ${QRC_BUILT_SRCS})
+ ${MOC_BUILT_SRCS})
endif ()
if(USE_LGPL)
@@ -246,6 +246,7 @@ target_link_libraries(CMakeGUIMainLib PUBLIC CMakeGUILib)
add_executable(cmake-gui WIN32 MACOSX_BUNDLE CMakeGUIExec.cxx ${MANIFEST_FILE})
target_link_libraries(cmake-gui CMakeGUIMainLib Qt${INSTALLED_QT_VERSION}::Core)
+target_sources(CMakeGUIMainLib INTERFACE $<TARGET_OBJECTS:CMakeGUIQRCLib>)
if(WIN32)
target_sources(CMakeGUIMainLib INTERFACE $<TARGET_OBJECTS:CMakeVersion> CMakeSetup.rc)
endif()
diff --git a/Source/cmGccDepfileReader.cxx b/Source/cmGccDepfileReader.cxx
index 96a562e..8253375 100644
--- a/Source/cmGccDepfileReader.cxx
+++ b/Source/cmGccDepfileReader.cxx
@@ -12,40 +12,33 @@
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
-cm::optional<cmGccDepfileContent> cmReadGccDepfile(const char* filePath)
-{
- cmGccDepfileLexerHelper helper;
- if (helper.readFile(filePath)) {
- return cm::make_optional(std::move(helper).extractContent());
- }
- return cm::nullopt;
-}
-
cm::optional<cmGccDepfileContent> cmReadGccDepfile(const char* filePath,
const std::string& prefix)
{
- auto deps = cmReadGccDepfile(filePath);
-
- if (prefix.empty() || !deps) {
- return deps;
+ cmGccDepfileLexerHelper helper;
+ if (!helper.readFile(filePath)) {
+ return cm::nullopt;
}
+ auto deps = cm::make_optional(std::move(helper).extractContent());
for (auto& dep : *deps) {
for (auto& rule : dep.rules) {
- if (!cmSystemTools::FileIsFullPath(rule)) {
+ if (!prefix.empty() && !cmSystemTools::FileIsFullPath(rule)) {
rule = cmStrCat(prefix, rule);
}
if (cmSystemTools::FileIsFullPath(rule)) {
rule = cmSystemTools::CollapseFullPath(rule);
}
+ cmSystemTools::ConvertToLongPath(rule);
}
for (auto& path : dep.paths) {
- if (!cmSystemTools::FileIsFullPath(path)) {
+ if (!prefix.empty() && !cmSystemTools::FileIsFullPath(path)) {
path = cmStrCat(prefix, path);
}
if (cmSystemTools::FileIsFullPath(path)) {
path = cmSystemTools::CollapseFullPath(path);
}
+ cmSystemTools::ConvertToLongPath(path);
}
}
diff --git a/Source/cmGccDepfileReader.h b/Source/cmGccDepfileReader.h
index 66ff75d..c8a3748 100644
--- a/Source/cmGccDepfileReader.h
+++ b/Source/cmGccDepfileReader.h
@@ -8,10 +8,8 @@
#include "cmGccDepfileReaderTypes.h"
-cm::optional<cmGccDepfileContent> cmReadGccDepfile(const char* filePath);
-
/*
* Read dependencies file and append prefix to all relative paths
*/
-cm::optional<cmGccDepfileContent> cmReadGccDepfile(const char* filePath,
- const std::string& prefix);
+cm::optional<cmGccDepfileContent> cmReadGccDepfile(
+ const char* filePath, const std::string& prefix = {});
diff --git a/Source/cmLocalNinjaGenerator.cxx b/Source/cmLocalNinjaGenerator.cxx
index 5a747e5..7229101 100644
--- a/Source/cmLocalNinjaGenerator.cxx
+++ b/Source/cmLocalNinjaGenerator.cxx
@@ -693,13 +693,11 @@ void cmLocalNinjaGenerator::WriteCustomCommandBuildStatement(
}
}
-namespace {
-bool HasUniqueByproducts(cmLocalGenerator& lg,
- std::vector<std::string> const& byproducts,
- cmListFileBacktrace const& bt)
+bool cmLocalNinjaGenerator::HasUniqueByproducts(
+ std::vector<std::string> const& byproducts, cmListFileBacktrace const& bt)
{
std::vector<std::string> configs =
- lg.GetMakefile()->GetGeneratorConfigs(cmMakefile::IncludeEmptyConfig);
+ this->GetMakefile()->GetGeneratorConfigs(cmMakefile::IncludeEmptyConfig);
cmGeneratorExpression ge(bt);
for (std::string const& p : byproducts) {
if (cmGeneratorExpression::Find(p) == std::string::npos) {
@@ -709,7 +707,7 @@ bool HasUniqueByproducts(cmLocalGenerator& lg,
std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(p);
for (std::string const& config : configs) {
for (std::string const& b :
- lg.ExpandCustomCommandOutputPaths(*cge, config)) {
+ this->ExpandCustomCommandOutputPaths(*cge, config)) {
if (!seen.insert(b).second) {
return false;
}
@@ -719,6 +717,7 @@ bool HasUniqueByproducts(cmLocalGenerator& lg,
return true;
}
+namespace {
bool HasUniqueOutputs(std::vector<cmCustomCommandGenerator> const& ccgs)
{
std::set<std::string> allOutputs;
@@ -746,7 +745,7 @@ std::string cmLocalNinjaGenerator::CreateUtilityOutput(
// In Ninja Multi-Config, we can only produce cross-config utility
// commands if all byproducts are per-config.
if (!this->GetGlobalGenerator()->IsMultiConfig() ||
- !HasUniqueByproducts(*this, byproducts, bt)) {
+ !this->HasUniqueByproducts(byproducts, bt)) {
return this->cmLocalGenerator::CreateUtilityOutput(targetName, byproducts,
bt);
}
diff --git a/Source/cmLocalNinjaGenerator.h b/Source/cmLocalNinjaGenerator.h
index 87d5e53..5b850f3 100644
--- a/Source/cmLocalNinjaGenerator.h
+++ b/Source/cmLocalNinjaGenerator.h
@@ -86,6 +86,9 @@ public:
cmNinjaDeps& ninjaDeps,
const std::string& config);
+ bool HasUniqueByproducts(std::vector<std::string> const& byproducts,
+ cmListFileBacktrace const& bt);
+
protected:
std::string ConvertToIncludeReference(
std::string const& path,
diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx
index e4c8e4b..cea20ad 100644
--- a/Source/cmMakefile.cxx
+++ b/Source/cmMakefile.cxx
@@ -303,7 +303,7 @@ void cmMakefile::PrintCommandTrace(
args.reserve(lff.Arguments().size());
for (cmListFileArgument const& arg : lff.Arguments()) {
- if (expand) {
+ if (expand && arg.Delim != cmListFileArgument::Bracket) {
temp = arg.Value;
this->ExpandVariablesInString(temp);
args.push_back(temp);
diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx
index c33fabd..adf40b0 100644
--- a/Source/cmMakefileTargetGenerator.cxx
+++ b/Source/cmMakefileTargetGenerator.cxx
@@ -345,27 +345,51 @@ void cmMakefileTargetGenerator::WriteCommonCodeRules()
this->LocalGenerator->GetBinaryDirectory(), compilerDependFile))
<< "\n\n";
- if (!cmSystemTools::FileExists(compilerDependFile)) {
- // Write an empty dependency file.
- cmGeneratedFileStream depFileStream(
- compilerDependFile, false,
- this->GlobalGenerator->GetMakefileEncoding());
- depFileStream << "# Empty compiler generated dependencies file for "
- << this->GeneratorTarget->GetName() << ".\n"
- << "# This may be replaced when dependencies are built.\n";
- }
+ // Write an empty dependency file.
+ cmGeneratedFileStream depFileStream(
+ compilerDependFile, false, this->GlobalGenerator->GetMakefileEncoding());
+ depFileStream << "# Empty compiler generated dependencies file for "
+ << this->GeneratorTarget->GetName() << ".\n"
+ << "# This may be replaced when dependencies are built.\n";
+ // remove internal dependency file
+ cmSystemTools::RemoveFile(
+ cmStrCat(this->TargetBuildDirectoryFull, "/compiler_depend.internal"));
std::string compilerDependTimestamp =
cmStrCat(this->TargetBuildDirectoryFull, "/compiler_depend.ts");
if (!cmSystemTools::FileExists(compilerDependTimestamp)) {
// Write a dependency timestamp file.
- cmGeneratedFileStream depFileStream(
+ cmGeneratedFileStream timestampFileStream(
compilerDependTimestamp, false,
this->GlobalGenerator->GetMakefileEncoding());
- depFileStream << "# CMAKE generated file: DO NOT EDIT!\n"
- << "# Timestamp file for compiler generated dependencies "
- "management for "
- << this->GeneratorTarget->GetName() << ".\n";
+ timestampFileStream
+ << "# CMAKE generated file: DO NOT EDIT!\n"
+ << "# Timestamp file for compiler generated dependencies "
+ "management for "
+ << this->GeneratorTarget->GetName() << ".\n";
+ }
+
+ // deactivate no longer needed legacy dependency files
+ // Write an empty dependency file.
+ cmGeneratedFileStream legacyDepFileStream(
+ dependFileNameFull, false, this->GlobalGenerator->GetMakefileEncoding());
+ legacyDepFileStream
+ << "# Empty dependencies file for " << this->GeneratorTarget->GetName()
+ << ".\n"
+ << "# This may be replaced when dependencies are built.\n";
+ // remove internal dependency file
+ cmSystemTools::RemoveFile(
+ cmStrCat(this->TargetBuildDirectoryFull, "/depend.internal"));
+ } else {
+ // make sure the depend file exists
+ if (!cmSystemTools::FileExists(dependFileNameFull)) {
+ // Write an empty dependency file.
+ cmGeneratedFileStream depFileStream(
+ dependFileNameFull, false,
+ this->GlobalGenerator->GetMakefileEncoding());
+ depFileStream << "# Empty dependencies file for "
+ << this->GeneratorTarget->GetName() << ".\n"
+ << "# This may be replaced when dependencies are built.\n";
}
}
@@ -381,16 +405,6 @@ void cmMakefileTargetGenerator::WriteCommonCodeRules()
<< "\n\n";
}
- // make sure the depend file exists
- if (!cmSystemTools::FileExists(dependFileNameFull)) {
- // Write an empty dependency file.
- cmGeneratedFileStream depFileStream(
- dependFileNameFull, false, this->GlobalGenerator->GetMakefileEncoding());
- depFileStream << "# Empty dependencies file for "
- << this->GeneratorTarget->GetName() << ".\n"
- << "# This may be replaced when dependencies are built.\n";
- }
-
// Open the flags file. This should be copy-if-different because the
// rules may depend on this file itself.
this->FlagFileNameFull =
@@ -855,6 +869,7 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles(
shellDependencyFile = this->LocalGenerator->ConvertToOutputFormat(
depFile, cmOutputConverter::SHELL);
vars.DependencyFile = shellDependencyFile.c_str();
+ this->CleanFiles.insert(depFile);
dependencyTimestamp = this->LocalGenerator->MaybeConvertToRelativePath(
this->LocalGenerator->GetBinaryDirectory(),
diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx
index 620b8ff..49e5e4c 100644
--- a/Source/cmNinjaNormalTargetGenerator.cxx
+++ b/Source/cmNinjaNormalTargetGenerator.cxx
@@ -12,6 +12,7 @@
#include <utility>
#include <cm/memory>
+#include <cm/optional>
#include <cm/vector>
#include "cmComputeLinkInformation.h"
@@ -1238,14 +1239,17 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement(
std::vector<std::string> preLinkCmdLines;
std::vector<std::string> postBuildCmdLines;
- if (config == fileConfig) {
- std::vector<std::string>* cmdLineLists[3] = { &preLinkCmdLines,
- &preLinkCmdLines,
- &postBuildCmdLines };
-
- for (unsigned i = 0; i != 3; ++i) {
- for (cmCustomCommand const& cc : *cmdLists[i]) {
- cmCustomCommandGenerator ccg(cc, config, this->GetLocalGenerator());
+ std::vector<std::string>* cmdLineLists[3] = { &preLinkCmdLines,
+ &preLinkCmdLines,
+ &postBuildCmdLines };
+
+ for (unsigned i = 0; i != 3; ++i) {
+ for (cmCustomCommand const& cc : *cmdLists[i]) {
+ if (config == fileConfig ||
+ this->GetLocalGenerator()->HasUniqueByproducts(cc.GetByproducts(),
+ cc.GetBacktrace())) {
+ cmCustomCommandGenerator ccg(cc, fileConfig, this->GetLocalGenerator(),
+ true, config);
localGen.AppendCustomCommandLines(ccg, *cmdLineLists[i]);
std::vector<std::string> const& ccByproducts = ccg.GetByproducts();
std::transform(ccByproducts.begin(), ccByproducts.end(),
diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx
index 6a705f4..024356f 100644
--- a/Source/cmSystemTools.cxx
+++ b/Source/cmSystemTools.cxx
@@ -1255,6 +1255,30 @@ void cmSystemTools::ConvertToOutputSlashes(std::string& path)
#endif
}
+void cmSystemTools::ConvertToLongPath(std::string& path)
+{
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ // Try to convert path to a long path only if the path contains character '~'
+ if (path.find('~') == std::string::npos) {
+ return;
+ }
+
+ std::wstring wPath = cmsys::Encoding::ToWide(path);
+ DWORD ret = GetLongPathNameW(wPath.c_str(), nullptr, 0);
+ std::vector<wchar_t> buffer(ret);
+ if (ret != 0) {
+ ret = GetLongPathNameW(wPath.c_str(), buffer.data(),
+ static_cast<DWORD>(buffer.size()));
+ }
+
+ if (ret != 0) {
+ path = cmsys::Encoding::ToNarrow(buffer.data());
+ }
+#else
+ static_cast<void>(path);
+#endif
+}
+
std::string cmSystemTools::ConvertToRunCommandPath(const std::string& path)
{
#if defined(_WIN32) && !defined(__CYGWIN__)
diff --git a/Source/cmSystemTools.h b/Source/cmSystemTools.h
index 1100f05..5bbbb0c 100644
--- a/Source/cmSystemTools.h
+++ b/Source/cmSystemTools.h
@@ -287,6 +287,12 @@ public:
// running cmake needs paths to be in its format
static std::string ConvertToRunCommandPath(const std::string& path);
+ /**
+ * For windows computes the long path for the given path,
+ * For Unix, it is a noop
+ */
+ static void ConvertToLongPath(std::string& path);
+
/** compute the relative path from local to remote. local must
be a directory. remote can be a file or a directory.
Both remote and local must be full paths. Basically, if
diff --git a/Source/cmcmd.cxx b/Source/cmcmd.cxx
index 4c0fbeb..851205e 100644
--- a/Source/cmcmd.cxx
+++ b/Source/cmcmd.cxx
@@ -231,11 +231,10 @@ private:
bool ProcessLine() override
{
if (cmHasPrefix(this->Line, this->IncludePrefix)) {
- this->DepFile << cmCMakePath(
- cmTrimWhitespace(this->Line.c_str() +
- this->IncludePrefix.size()))
- .GenericString()
- << std::endl;
+ auto path =
+ cmTrimWhitespace(this->Line.c_str() + this->IncludePrefix.size());
+ cmSystemTools::ConvertToLongPath(path);
+ this->DepFile << cmCMakePath(path).GenericString() << std::endl;
} else {
this->Output << this->Line << std::endl << std::flush;
}
diff --git a/Tests/RunCMake/CommandLine/trace-expand.cmake b/Tests/RunCMake/CommandLine/trace-expand.cmake
index e69de29..24da02a 100644
--- a/Tests/RunCMake/CommandLine/trace-expand.cmake
+++ b/Tests/RunCMake/CommandLine/trace-expand.cmake
@@ -0,0 +1 @@
+set(a [[\B]])
diff --git a/Tests/RunCMake/NinjaMultiConfig/PostBuild-debug-in-release-graph-build-stdout.txt b/Tests/RunCMake/NinjaMultiConfig/PostBuild-debug-in-release-graph-build-stdout.txt
new file mode 100644
index 0000000..fad923a
--- /dev/null
+++ b/Tests/RunCMake/NinjaMultiConfig/PostBuild-debug-in-release-graph-build-stdout.txt
@@ -0,0 +1,2 @@
+Running post-build command with Debug
+Generating Debug\.txt
diff --git a/Tests/RunCMake/NinjaMultiConfig/PostBuild-release-build-stdout.txt b/Tests/RunCMake/NinjaMultiConfig/PostBuild-release-build-stdout.txt
new file mode 100644
index 0000000..485a52c
--- /dev/null
+++ b/Tests/RunCMake/NinjaMultiConfig/PostBuild-release-build-stdout.txt
@@ -0,0 +1,3 @@
+Running post-build command with Release
+Generating out\.txt with Release
+Generating Release\.txt
diff --git a/Tests/RunCMake/NinjaMultiConfig/PostBuild.cmake b/Tests/RunCMake/NinjaMultiConfig/PostBuild.cmake
new file mode 100644
index 0000000..5fcff74
--- /dev/null
+++ b/Tests/RunCMake/NinjaMultiConfig/PostBuild.cmake
@@ -0,0 +1,6 @@
+enable_language(C)
+
+add_executable(Exe main.c)
+add_custom_command(TARGET Exe POST_BUILD COMMAND ${CMAKE_COMMAND} -E echo "Running post-build command with $<CONFIG>")
+add_custom_command(TARGET Exe POST_BUILD COMMAND ${CMAKE_COMMAND} -E echo "Generating out.txt with $<CONFIG>" BYPRODUCTS out.txt)
+add_custom_command(TARGET Exe POST_BUILD COMMAND ${CMAKE_COMMAND} -E echo "Generating $<CONFIG>.txt" BYPRODUCTS $<CONFIG>.txt)
diff --git a/Tests/RunCMake/NinjaMultiConfig/RunCMakeTest.cmake b/Tests/RunCMake/NinjaMultiConfig/RunCMakeTest.cmake
index dc2db57..480d628 100644
--- a/Tests/RunCMake/NinjaMultiConfig/RunCMakeTest.cmake
+++ b/Tests/RunCMake/NinjaMultiConfig/RunCMakeTest.cmake
@@ -187,6 +187,12 @@ run_ninja(SimpleCrossConfigs clean-all-in-release-graph build-Release.ninja clea
run_cmake_build(SimpleCrossConfigs all-all-in-release-graph Release all:all)
run_cmake_build(SimpleCrossConfigs all-relwithdebinfo-in-release-graph Release all:RelWithDebInfo)
+set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/PostBuild-build)
+set(RunCMake_TEST_OPTIONS "-DCMAKE_CROSS_CONFIGS=all")
+run_cmake_configure(PostBuild)
+run_cmake_build(PostBuild release Release Exe)
+run_cmake_build(PostBuild debug-in-release-graph Release Exe:Debug)
+
set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/Framework-build)
set(RunCMake_TEST_OPTIONS "-DCMAKE_CROSS_CONFIGS=all")
run_cmake_configure(Framework)