浏览代码

Makefiles: Add support of DEPFILE for add_custom_command

Issue: #20286
Fixes: #21415
Marc Chevrier 5 年之前
父节点
当前提交
cfd8a5ac1f

+ 18 - 3
Help/command/add_custom_command.rst

@@ -201,6 +201,10 @@ The options are:
   Note that the ``IMPLICIT_DEPENDS`` option is currently supported
   only for Makefile generators and will be ignored by other generators.
 
+  .. note::
+
+    This option cannot be specified at the same time as ``DEPFILE`` option.
+
 ``JOB_POOL``
   .. versionadded:: 3.15
 
@@ -263,15 +267,26 @@ The options are:
 ``DEPFILE``
   .. versionadded:: 3.7
 
-  Specify a ``.d`` depfile for the :generator:`Ninja` generator.
+  Specify a ``.d`` depfile for the :generator:`Ninja` generator and
+  :ref:`Makefile Generators`.
   A ``.d`` file holds dependencies usually emitted by the custom
   command itself.
-  Using ``DEPFILE`` with other generators than Ninja is an error.
+  Using ``DEPFILE`` with other generators than :generator:`Ninja` or
+  :ref:`Makefile Generators` is an error.
+
+  .. versionadded:: 3.20
+    Added the support of :ref:`Makefile Generators`.
 
   If the ``DEPFILE`` argument is relative, it should be relative to
   :variable:`CMAKE_CURRENT_BINARY_DIR`, and any relative paths inside the
   ``DEPFILE`` should also be relative to :variable:`CMAKE_CURRENT_BINARY_DIR`
-  (see policy :policy:`CMP0116`.)
+  (see policy :policy:`CMP0116`. This policy is always ``NEW`` for
+  :ref:`Makefile Generators`).
+
+  .. note::
+
+    For :ref:`Makefile Generators`, this option cannot be specified at the
+    same time as ``IMPLICIT_DEPENDS`` option.
 
 Examples: Generating Files
 ^^^^^^^^^^^^^^^^^^^^^^^^^^

+ 5 - 0
Help/release/dev/makefile-depfile.rst

@@ -0,0 +1,5 @@
+makefile-depfile
+----------------
+
+* The :command:`add_custom_command` command gained ``DEPFILE`` support on
+  :ref:`Makefile Generators`.

+ 6 - 0
Source/cmAddCustomCommandCommand.cxx

@@ -296,6 +296,12 @@ bool cmAddCustomCommandCommand(std::vector<std::string> const& args,
     status.SetError("given APPEND option with no OUTPUT.");
     return false;
   }
+  if (!implicit_depends.empty() && !depfile.empty() &&
+      mf.GetGlobalGenerator()->GetName() != "Ninja") {
+    // Makefiles generators does not support both at the same time
+    status.SetError("IMPLICIT_DEPENDS and DEPFILE can not both be specified.");
+    return false;
+  }
 
   // Check for an append request.
   if (append) {

+ 86 - 47
Source/cmDependsCompiler.cxx

@@ -19,6 +19,7 @@
 
 #include "cmFileTime.h"
 #include "cmGccDepfileReader.h"
+#include "cmGccDepfileReaderTypes.h"
 #include "cmGlobalUnixMakefileGenerator3.h"
 #include "cmLocalUnixMakefileGenerator3.h"
 #include "cmStringAlgorithms.h"
@@ -86,7 +87,7 @@ bool cmDependsCompiler::CheckDependencies(
     if (!forceReadDeps) {
       depFileTime.Load(depFile);
     }
-    if (forceReadDeps || depFileTime.Newer(internalDepFileTime)) {
+    if (forceReadDeps || depFileTime.Compare(internalDepFileTime) >= 0) {
       status = false;
       if (this->Verbose) {
         cmSystemTools::Stdout(cmStrCat("Dependencies file \"", depFile,
@@ -95,59 +96,92 @@ bool cmDependsCompiler::CheckDependencies(
       }
 
       std::vector<std::string> depends;
-      if (format == "msvc"_s) {
-        cmsys::ifstream fin(depFile.c_str());
-        if (!fin) {
-          continue;
+      if (format == "custom"_s) {
+        std::string prefix;
+        if (this->LocalGenerator->GetCurrentBinaryDirectory() !=
+            this->LocalGenerator->GetBinaryDirectory()) {
+          prefix =
+            cmStrCat(this->LocalGenerator->MaybeConvertToRelativePath(
+                       this->LocalGenerator->GetBinaryDirectory(),
+                       this->LocalGenerator->GetCurrentBinaryDirectory()),
+                     '/');
         }
 
-        std::string line;
-        if (!isValidPath) {
-          // insert source as first dependency
-          depends.push_back(source);
-        }
-        while (cmSystemTools::GetLineFromStream(fin, line)) {
-          depends.emplace_back(std::move(line));
-        }
-      } else {
-        auto deps = cmReadGccDepfile(depFile.c_str());
+        auto deps = cmReadGccDepfile(depFile.c_str(), prefix);
         if (!deps) {
           continue;
         }
 
-        // dependencies generated by the compiler contains only one target
-        depends = std::move(deps->front().paths);
-        if (depends.empty()) {
-          // unexpectedly empty, ignore it and continue
-          continue;
-        }
-
-        // depending of the effective format of the dependencies file generated
-        // by the compiler, the target can be wrongly identified as a
-        // dependency so remove it from the list
-        if (depends.front() == target) {
-          depends.erase(depends.begin());
+        for (auto& entry : *deps) {
+          depends = std::move(entry.paths);
+          if (isValidPath) {
+            cm::erase_if(depends, isValidPath);
+          }
+          // copy depends for each target, except first one, which can be
+          // moved
+          for (auto index = entry.rules.size() - 1; index > 0; --index) {
+            dependencies[entry.rules[index]] = depends;
+          }
+          dependencies[entry.rules.front()] = std::move(depends);
         }
+      } else {
+        if (format == "msvc"_s) {
+          cmsys::ifstream fin(depFile.c_str());
+          if (!fin) {
+            continue;
+          }
 
-        // ensure source file is the first dependency
-        if (depends.front() != source) {
-          cm::erase(depends, source);
+          std::string line;
           if (!isValidPath) {
-            depends.insert(depends.begin(), source);
+            // insert source as first dependency
+            depends.push_back(source);
+          }
+          while (cmSystemTools::GetLineFromStream(fin, line)) {
+            depends.emplace_back(std::move(line));
+          }
+        } else if (format == "gcc"_s) {
+          auto deps = cmReadGccDepfile(depFile.c_str());
+          if (!deps) {
+            continue;
           }
-        } else if (isValidPath) {
-          // remove first dependency because it must not be filtered out
-          depends.erase(depends.begin());
+
+          // dependencies generated by the compiler contains only one target
+          depends = std::move(deps->front().paths);
+          if (depends.empty()) {
+            // unexpectedly empty, ignore it and continue
+            continue;
+          }
+
+          // depending of the effective format of the dependencies file
+          // generated by the compiler, the target can be wrongly identified
+          // as a dependency so remove it from the list
+          if (depends.front() == target) {
+            depends.erase(depends.begin());
+          }
+
+          // ensure source file is the first dependency
+          if (depends.front() != source) {
+            cm::erase(depends, source);
+            if (!isValidPath) {
+              depends.insert(depends.begin(), source);
+            }
+          } else if (isValidPath) {
+            // remove first dependency because it must not be filtered out
+            depends.erase(depends.begin());
+          }
+        } else {
+          // unknown format, ignore it
+          continue;
         }
-      }
 
-      if (isValidPath) {
-        cm::erase_if(depends, isValidPath);
-        // insert source as first dependency
-        depends.insert(depends.begin(), source);
-      }
+        if (isValidPath) {
+          cm::erase_if(depends, isValidPath);
+          // insert source as first dependency
+          depends.insert(depends.begin(), source);
+        }
 
-      dependencies[target] = std::move(depends);
+        dependencies[target] = std::move(depends);
+      }
     }
   }
 
@@ -168,6 +202,8 @@ void cmDependsCompiler::WriteDependencies(
 
   // external dependencies file
   for (auto& node : makeDependencies) {
+    auto target = LocalGenerator->ConvertToMakefilePath(
+      this->LocalGenerator->MaybeConvertToRelativePath(binDir, node.first));
     auto& deps = node.second;
     std::transform(
       deps.cbegin(), deps.cend(), deps.begin(),
@@ -176,13 +212,16 @@ void cmDependsCompiler::WriteDependencies(
           this->LocalGenerator->MaybeConvertToRelativePath(binDir, dep));
       });
 
-    makeDepends << this->LocalGenerator->ConvertToMakefilePath(node.first)
-                << ": " << deps.front();
-    // first dependency is the source, remove it because should not be declared
-    // as phony target
-    deps.erase(deps.begin());
+    bool first_dep = true;
+    makeDepends << target << ": ";
     for (const auto& dep : deps) {
-      makeDepends << ' ' << lineContinue << "  " << dep;
+      if (first_dep) {
+        first_dep = false;
+        makeDepends << dep;
+      } else {
+        makeDepends << ' ' << lineContinue << "  " << dep;
+      }
+
       phonyTargets.emplace(dep.data(), dep.length());
     }
     makeDepends << std::endl << std::endl;

+ 6 - 0
Source/cmGlobalUnixMakefileGenerator3.h

@@ -93,6 +93,12 @@ public:
    */
   static bool SupportsPlatform() { return false; }
 
+  /**
+   * Utilized to determine if this generator
+   * supports DEPFILE option.
+   */
+  bool SupportsCustomCommandDepfile() const override { return true; }
+
   /** Get the documentation entry for this generator.  */
   static void GetDocumentation(cmDocumentationEntry& entry);
 

+ 27 - 12
Source/cmLocalUnixMakefileGenerator3.cxx

@@ -13,6 +13,7 @@
 #include <cm/string_view>
 #include <cm/vector>
 #include <cmext/algorithm>
+#include <cmext/string_view>
 
 #include "cmsys/FStream.hxx"
 #include "cmsys/Terminal.h"
@@ -1435,7 +1436,7 @@ bool cmLocalUnixMakefileGenerator3::UpdateDependencies(
     this->Makefile->GetSafeDefinition("CMAKE_DEPENDS_DEPENDENCY_FILES");
   if (!depends.empty()) {
     // dependencies are managed by compiler
-    auto depFiles = cmExpandedList(depends);
+    auto depFiles = cmExpandedList(depends, true);
     std::string const internalDepFile =
       targetDir + "/compiler_depend.internal";
     std::string const depFile = targetDir + "/compiler_depend.make";
@@ -1998,18 +1999,32 @@ void cmLocalUnixMakefileGenerator3::WriteDependLanguageInfo(
   cmakefileStream << "\n# The set of dependency files which are needed:\n";
   cmakefileStream << "set(CMAKE_DEPENDS_DEPENDENCY_FILES\n";
   for (auto const& compilerLang : compilerLangs) {
-    auto depFormat = this->Makefile->GetSafeDefinition(
-      cmStrCat("CMAKE_", compilerLang.first, "_DEPFILE_FORMAT"));
     auto const& compilerPairs = compilerLang.second;
-    for (auto const& compilerPair : compilerPairs) {
-      for (auto const& src : compilerPair.second) {
-        cmakefileStream << "  \"" << src << "\" \""
-                        << this->MaybeConvertToRelativePath(
-                             this->GetBinaryDirectory(), compilerPair.first)
-                        << "\" \"" << depFormat << "\" \""
-                        << this->MaybeConvertToRelativePath(
-                             this->GetBinaryDirectory(), compilerPair.first)
-                        << ".d\"\n";
+    if (compilerLang.first == "CUSTOM"_s) {
+      for (auto const& compilerPair : compilerPairs) {
+        for (auto const& src : compilerPair.second) {
+          cmakefileStream << R"(  "" ")"
+                          << this->MaybeConvertToRelativePath(
+                               this->GetBinaryDirectory(), compilerPair.first)
+                          << R"(" "custom" ")"
+                          << this->MaybeConvertToRelativePath(
+                               this->GetBinaryDirectory(), src)
+                          << "\"\n";
+        }
+      }
+    } else {
+      auto depFormat = this->Makefile->GetSafeDefinition(
+        cmStrCat("CMAKE_", compilerLang.first, "_DEPFILE_FORMAT"));
+      for (auto const& compilerPair : compilerPairs) {
+        for (auto const& src : compilerPair.second) {
+          cmakefileStream << "  \"" << src << "\" \""
+                          << this->MaybeConvertToRelativePath(
+                               this->GetBinaryDirectory(), compilerPair.first)
+                          << "\" \"" << depFormat << "\" \""
+                          << this->MaybeConvertToRelativePath(
+                               this->GetBinaryDirectory(), compilerPair.first)
+                          << ".d\"\n";
+        }
       }
     }
   }

+ 19 - 0
Source/cmMakefileTargetGenerator.cxx

@@ -1617,6 +1617,16 @@ void cmMakefileTargetGenerator::GenerateCustomRuleFile(
   std::vector<std::string> depends;
   this->LocalGenerator->AppendCustomDepend(depends, ccg);
 
+  if (!ccg.GetCC().GetDepfile().empty()) {
+    // Add dependency over timestamp file for dependencies management
+    auto dependTimestamp = cmSystemTools::ConvertToOutputPath(
+      this->LocalGenerator->MaybeConvertToRelativePath(
+        this->LocalGenerator->GetBinaryDirectory(),
+        cmStrCat(this->TargetBuildDirectoryFull, "/compiler_depend.ts")));
+
+    depends.push_back(dependTimestamp);
+  }
+
   // Write the rule.
   const std::vector<std::string>& outputs = ccg.GetOutputs();
   bool symbolic = this->WriteMakeRule(*this->BuildFileStream, nullptr, outputs,
@@ -1653,6 +1663,15 @@ void cmMakefileTargetGenerator::GenerateCustomRuleFile(
                                              objFullPath, srcFullPath);
   }
 
+  // Setup implicit depend for depfile if any
+  if (!ccg.GetCC().GetDepfile().empty()) {
+    std::string objFullPath = cmSystemTools::CollapseFullPath(
+      outputs[0], this->LocalGenerator->GetCurrentBinaryDirectory());
+    this->LocalGenerator->AddImplicitDepends(
+      this->GeneratorTarget, "CUSTOM", objFullPath, ccg.GetFullDepfile(),
+      cmDependencyScannerKind::Compiler);
+  }
+
   this->CustomCommandOutputs.insert(outputs.begin(), outputs.end());
 }
 

+ 36 - 3
Source/cmMakefileUtilityTargetGenerator.cxx

@@ -15,6 +15,7 @@
 #include "cmLocalUnixMakefileGenerator3.h"
 #include "cmMakefile.h"
 #include "cmOSXBundleGenerator.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 
 cmMakefileUtilityTargetGenerator::cmMakefileUtilityTargetGenerator(
@@ -36,10 +37,42 @@ void cmMakefileUtilityTargetGenerator::WriteRuleFiles()
   *this->BuildFileStream << "# Utility rule file for "
                          << this->GeneratorTarget->GetName() << ".\n\n";
 
+  const char* root = (this->Makefile->IsOn("CMAKE_MAKE_INCLUDE_FROM_ROOT")
+                        ? "$(CMAKE_BINARY_DIR)/"
+                        : "");
+
+  // Include the dependencies for the target.
+  std::string dependFile =
+    cmStrCat(this->TargetBuildDirectoryFull, "/compiler_depend.make");
+  *this->BuildFileStream
+    << "# Include any custom commands dependencies for this target.\n"
+    << this->GlobalGenerator->IncludeDirective << " " << root
+    << cmSystemTools::ConvertToOutputPath(
+         this->LocalGenerator->MaybeConvertToRelativePath(
+           this->LocalGenerator->GetBinaryDirectory(), dependFile))
+    << "\n\n";
+  if (!cmSystemTools::FileExists(dependFile)) {
+    // Write an empty dependency file.
+    cmGeneratedFileStream depFileStream(
+      dependFile, false, this->GlobalGenerator->GetMakefileEncoding());
+    depFileStream << "# Empty custom commands generated dependencies file for "
+                  << this->GeneratorTarget->GetName() << ".\n"
+                  << "# This may be replaced when dependencies are built.\n";
+  }
+
+  std::string dependTimestamp =
+    cmStrCat(this->TargetBuildDirectoryFull, "/compiler_depend.ts");
+  if (!cmSystemTools::FileExists(dependTimestamp)) {
+    // Write a dependency timestamp file.
+    cmGeneratedFileStream depFileStream(
+      dependTimestamp, false, this->GlobalGenerator->GetMakefileEncoding());
+    depFileStream << "# CMAKE generated file: DO NOT EDIT!\n"
+                  << "# Timestamp file for custom commands dependencies "
+                     "management for "
+                  << this->GeneratorTarget->GetName() << ".\n";
+  }
+
   if (!this->NoRuleMessages) {
-    const char* root = (this->Makefile->IsOn("CMAKE_MAKE_INCLUDE_FROM_ROOT")
-                          ? "$(CMAKE_BINARY_DIR)/"
-                          : "");
     // Include the progress variables for the target.
     *this->BuildFileStream
       << "# Include the progress variables for this target.\n"

+ 2 - 0
Source/cmcmd.cxx

@@ -1272,6 +1272,8 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args,
         cmStateSnapshot snapshot = cm.GetCurrentSnapshot();
         snapshot.GetDirectory().SetCurrentBinary(startOutDir);
         snapshot.GetDirectory().SetCurrentSource(startDir);
+        snapshot.GetDirectory().SetRelativePathTopSource(homeDir.c_str());
+        snapshot.GetDirectory().SetRelativePathTopBinary(homeOutDir.c_str());
         cmMakefile mf(cm.GetGlobalGenerator(), snapshot);
         auto lgd = cm.GetGlobalGenerator()->CreateLocalGenerator(&mf);
 

+ 0 - 0
Tests/RunCMake/Make/CustomCommandDepfile-ERROR-result.txt → Tests/RunCMake/BuildDepends/CustomCommandDependencies-BadArgs-result.txt


+ 4 - 0
Tests/RunCMake/BuildDepends/CustomCommandDependencies-BadArgs-stderr.txt

@@ -0,0 +1,4 @@
+CMake Error at CustomCommandDependencies-BadArgs.cmake:[0-9]+ \(add_custom_command\):
+  add_custom_command IMPLICIT_DEPENDS and DEPFILE can not both be specified.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:[0-9]+ \(include\)

+ 10 - 0
Tests/RunCMake/BuildDepends/CustomCommandDependencies-BadArgs.cmake

@@ -0,0 +1,10 @@
+enable_language(C)
+
+add_custom_command(OUTPUT main.c
+  DEPFILE main.c.d
+  IMPLICIT_DEPENDS C main.c.in
+  COMMAND "${CMAKE_COMMAND}" -DINFILE=main.c.in -DOUTFILE=main.c -DDEPFILE=main.c.d
+  -P "${CMAKE_CURRENT_SOURCE_DIR}/GenerateDepFile.cmake"
+  WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}")
+
+add_custom_target(mainc ALL DEPENDS main.c)

+ 73 - 0
Tests/RunCMake/BuildDepends/CustomCommandDependencies.cmake

@@ -0,0 +1,73 @@
+enable_language(C)
+
+add_custom_command(OUTPUT main.c
+  DEPFILE main.c.d
+  COMMAND "${CMAKE_COMMAND}" -DINFILE=main.c.in -DOUTFILE=main.c -DDEPFILE=main.c.d
+  -P "${CMAKE_CURRENT_SOURCE_DIR}/GenerateDepFile.cmake"
+  WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}")
+
+add_custom_target(mainc ALL DEPENDS main.c)
+
+add_executable(main ${CMAKE_CURRENT_BINARY_DIR}/main.c)
+
+file(GENERATE OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/check-$<LOWER_CASE:$<CONFIG>>.cmake CONTENT "
+cmake_minimum_required(VERSION 3.19)
+set(check_pairs
+  \"$<TARGET_FILE:main>|${CMAKE_CURRENT_BINARY_DIR}/main.c.in\"
+  \"$<TARGET_FILE:main>|${CMAKE_CURRENT_BINARY_DIR}/main.c\"
+  )
+set(check_exes
+  \"$<TARGET_FILE:main>\"
+  )
+
+if (check_step EQUAL 2)
+  include(\"${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/Makefile.cmake\")
+  if (NOT CMAKE_DEPEND_INFO_FILES)
+    set(RunCMake_TEST_FAILED \"Variable CMAKE_DEPEND_INFO_FILES not found.\")
+  else()
+    foreach(DEPEND_INFO_FILE IN LISTS CMAKE_DEPEND_INFO_FILES)
+      include(\"${CMAKE_CURRENT_BINARY_DIR}/\${DEPEND_INFO_FILE}\")
+      if (NOT CMAKE_DEPENDS_DEPENDENCY_FILES)
+        set(RunCMake_TEST_FAILED \"Variable CMAKE_DEPENDS_DEPENDENCY_FILES not found.\")
+      else()
+        list(LENGTH CMAKE_DEPENDS_DEPENDENCY_FILES DEPENDENCY_FILES_SIZE)
+          math(EXPR STOP_INDEX \"\${DEPENDENCY_FILES_SIZE} - 1\")
+        foreach(INDEX RANGE 0 \${STOP_INDEX} 4)
+          math(EXPR OBJECT_INDEX \"\${INDEX} + 1\")
+          math(EXPR FORMAT_INDEX \"\${INDEX} + 2\")
+          math(EXPR DEP_INDEX \"\${INDEX} + 3\")
+          list(GET CMAKE_DEPENDS_DEPENDENCY_FILES \${OBJECT_INDEX} OBJECT_FILE)
+          list(GET CMAKE_DEPENDS_DEPENDENCY_FILES \${FORMAT_INDEX} DEP_FORMAT)
+          list(GET CMAKE_DEPENDS_DEPENDENCY_FILES \${DEP_INDEX} DEP_FILE)
+          if (NOT EXISTS \"${CMAKE_CURRENT_BINARY_DIR}/\${DEP_FILE}\")
+            set(RunCMake_TEST_FAILED \"File \${DEP_FILE} not found.\")
+          else()
+            cmake_path(APPEND TARGET_DEP_FILE \"${CMAKE_CURRENT_BINARY_DIR}\" \"\${DEPEND_INFO_FILE}\")
+            cmake_path(REPLACE_FILENAME TARGET_DEP_FILE \"compiler_depend.make\")
+            file(READ \"\${TARGET_DEP_FILE}\" DEPENDS_CONTENT)
+            if (WIN32)
+              string (REPLACE \"\\\\\" \"/\" DEPENDS_CONTENT \"\${DEPENDS_CONTENT}\")
+              string (TOLOWER \"\${DEPENDS_CONTENT}\" DEPENDS_CONTENT)
+              string (TOLOWER \"\${OBJECT_FILE}\" OBJECT_FILE)
+            else()
+              string(REPLACE \"\\\\ \" \" \" DEPENDS_CONTENT \"\${DEPENDS_CONTENT}\")
+            endif()
+            if(DEPEND_INFO_FILE MATCHES \"main\\\\.dir\")
+              if (DEP_FORMAT STREQUAL \"gcc\" AND NOT DEPENDS_CONTENT MATCHES \"\${OBJECT_FILE} *:.+main.c\")
+                set(RunCMake_TEST_FAILED \"Dependency file '\${TARGET_DEP_FILE}' badly generated:\\n\${DEPENDS_CONTENT}\")
+              endif()
+              if (DEP_FORMAT STREQUAL \"custom\" AND NOT DEPENDS_CONTENT MATCHES \"\${OBJECT_FILE} *:.+main.c.in\")
+                set(RunCMake_TEST_FAILED \"Dependency file '\${TARGET_DEP_FILE}' badly generated:\\n\${DEPENDS_CONTENT}\")
+              endif()
+            else()
+              if (NOT DEPENDS_CONTENT MATCHES \"\${OBJECT_FILE} *:.+main.c.in\")
+                set(RunCMake_TEST_FAILED \"Dependency file '\${TARGET_DEP_FILE}' badly generated:\\n\${DEPENDS_CONTENT}\")
+              endif()
+            endif()
+          endif()
+        endforeach()
+      endif()
+    endforeach()
+  endif()
+endif()
+")

+ 3 - 0
Tests/RunCMake/BuildDepends/CustomCommandDependencies.step1.cmake

@@ -0,0 +1,3 @@
+file(WRITE "${RunCMake_TEST_BINARY_DIR}/main.c.in" [[
+int main(void) { return 1; }
+]])

+ 3 - 0
Tests/RunCMake/BuildDepends/CustomCommandDependencies.step2.cmake

@@ -0,0 +1,3 @@
+file(WRITE "${RunCMake_TEST_BINARY_DIR}/main.c.in" [[
+int main(void) { return 2; }
+]])

+ 6 - 0
Tests/RunCMake/BuildDepends/GenerateDepFile.cmake

@@ -0,0 +1,6 @@
+file(READ "${INFILE}" INCONTENT)
+file(WRITE "${OUTFILE}" "${INCONTENT}")
+
+string(REPLACE [[ ]] [[\ ]] OUTFILE "${OUTFILE}")
+string(REPLACE [[ ]] [[\ ]] INFILE "${INFILE}")
+file(WRITE "${DEPFILE}" "${OUTFILE}: ${INFILE}\n")

+ 5 - 0
Tests/RunCMake/BuildDepends/RunCMakeTest.cmake

@@ -122,4 +122,9 @@ if ((RunCMake_GENERATOR STREQUAL "Unix Makefiles"
       AND MSVC_VERSION GREATER 1300
       AND CMAKE_C_COMPILER_ID STREQUAL "MSVC"))
   run_BuildDepends(CompilerDependencies)
+  run_BuildDepends(CustomCommandDependencies)
+endif()
+
+if (RunCMake_GENERATOR MATCHES "Makefiles")
+  run_cmake(CustomCommandDependencies-BadArgs)
 endif()

+ 0 - 5
Tests/RunCMake/Make/CustomCommandDepfile-ERROR-stderr.txt

@@ -1,5 +0,0 @@
-^CMake Error at CustomCommandDepfile-ERROR.cmake:1 \(add_custom_command\):
-  add_custom_command Option DEPFILE not supported by [^
-]+
-Call Stack \(most recent call first\):
-  CMakeLists.txt:3 \(include\)$

+ 0 - 8
Tests/RunCMake/Make/CustomCommandDepfile-ERROR.cmake

@@ -1,8 +0,0 @@
-add_custom_command(
-  OUTPUT hello.copy.c
-  COMMAND "${CMAKE_COMMAND}" -E copy
-          "${CMAKE_CURRENT_SOURCE_DIR}/hello.c"
-          hello.copy.c
-  WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
-  DEPFILE "test.d"
-  )

+ 0 - 1
Tests/RunCMake/Make/RunCMakeTest.cmake

@@ -39,7 +39,6 @@ function(run_VerboseBuild)
 endfunction()
 run_VerboseBuild()
 
-run_cmake(CustomCommandDepfile-ERROR)
 run_cmake(IncludeRegexSubdir)
 
 function(run_MakefileConflict)