Browse Source

Merge topic 'add-custom-target-byproduct-checks'

fd3a394614 add_custom_command: Format files in error message in a single line
a1cc6b4447 add_custom_target: Add output checks for custom target byproducts
cbb861ade8 add_custom_command: Add tests for custom command output checks

Acked-by: Kitware Robot <[email protected]>
Merge-request: !3850
Brad King 6 years ago
parent
commit
df982c4e18

+ 2 - 0
Source/CMakeLists.txt

@@ -168,6 +168,8 @@ set(SRCS
   cmBinUtilsWindowsPEObjdumpGetRuntimeDependenciesTool.h
   cmCacheManager.cxx
   cmCacheManager.h
+  cmCheckCustomOutputs.h
+  cmCheckCustomOutputs.cxx
   cmCLocaleEnvironmentScope.h
   cmCLocaleEnvironmentScope.cxx
   cmCommandArgumentParserHelper.cxx

+ 6 - 34
Source/cmAddCustomCommandCommand.cxx

@@ -5,6 +5,7 @@
 #include <sstream>
 #include <unordered_set>
 
+#include "cmCheckCustomOutputs.h"
 #include "cmCustomCommand.h"
 #include "cmCustomCommandLines.h"
 #include "cmExecutionStatus.h"
@@ -16,9 +17,6 @@
 #include "cmSystemTools.h"
 #include "cmTarget.h"
 
-static bool cmAddCustomCommandCommandCheckOutputs(
-  const std::vector<std::string>& outputs, cmExecutionStatus& status);
-
 bool cmAddCustomCommandCommand(std::vector<std::string> const& args,
                                cmExecutionStatus& status)
 {
@@ -307,9 +305,9 @@ bool cmAddCustomCommandCommand(std::vector<std::string> const& args,
   }
 
   // Make sure the output names and locations are safe.
-  if (!cmAddCustomCommandCommandCheckOutputs(output, status) ||
-      !cmAddCustomCommandCommandCheckOutputs(outputs, status) ||
-      !cmAddCustomCommandCommandCheckOutputs(byproducts, status)) {
+  if (!cmCheckCustomOutputs(output, "OUTPUT", status) ||
+      !cmCheckCustomOutputs(outputs, "OUTPUTS", status) ||
+      !cmCheckCustomOutputs(byproducts, "BYPRODUCTS", status)) {
     return false;
   }
 
@@ -322,8 +320,8 @@ bool cmAddCustomCommandCommand(std::vector<std::string> const& args,
 
     // No command for this output exists.
     status.SetError(
-      cmStrCat("given APPEND option with output\n\"", output[0],
-               "\"\nwhich is not already a custom command output."));
+      cmStrCat("given APPEND option with output\n  ", output[0],
+               "\nwhich is not already a custom command output."));
     return false;
   }
 
@@ -387,29 +385,3 @@ bool cmAddCustomCommandCommand(std::vector<std::string> const& args,
 
   return true;
 }
-
-bool cmAddCustomCommandCommandCheckOutputs(
-  const std::vector<std::string>& outputs, cmExecutionStatus& status)
-{
-  cmMakefile& mf = status.GetMakefile();
-  for (std::string const& o : outputs) {
-    // Make sure the file will not be generated into the source
-    // directory during an out of source build.
-    if (!mf.CanIWriteThisFile(o)) {
-      std::string e = "attempted to have a file \"" + o +
-        "\" in a source directory as an output of custom command.";
-      status.SetError(e);
-      cmSystemTools::SetFatalErrorOccured();
-      return false;
-    }
-
-    // Make sure the output file name has no invalid characters.
-    std::string::size_type pos = o.find_first_of("#<>");
-    if (pos != std::string::npos) {
-      status.SetError(cmStrCat("called with OUTPUT containing a \"", o[pos],
-                               "\".  This character is not allowed."));
-      return false;
-    }
-  }
-  return true;
-}

+ 6 - 0
Source/cmAddCustomTargetCommand.cxx

@@ -4,6 +4,7 @@
 
 #include <utility>
 
+#include "cmCheckCustomOutputs.h"
 #include "cmCustomCommandLines.h"
 #include "cmExecutionStatus.h"
 #include "cmGeneratorExpression.h"
@@ -205,6 +206,11 @@ bool cmAddCustomTargetCommand(std::vector<std::string> const& args,
     return false;
   }
 
+  // Make sure the byproduct names and locations are safe.
+  if (!cmCheckCustomOutputs(byproducts, "BYPRODUCTS", status)) {
+    return false;
+  }
+
   // Add the utility target to the makefile.
   bool escapeOldStyle = !verbatim;
   cmTarget* target = mf.AddUtilityCommand(

+ 36 - 0
Source/cmCheckCustomOutputs.cxx

@@ -0,0 +1,36 @@
+/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+   file Copyright.txt or https://cmake.org/licensing for details.  */
+#include "cmCheckCustomOutputs.h"
+
+#include "cmExecutionStatus.h"
+#include "cmMakefile.h"
+#include "cmStringAlgorithms.h"
+#include "cmSystemTools.h"
+
+bool cmCheckCustomOutputs(const std::vector<std::string>& outputs,
+                          cm::string_view keyword, cmExecutionStatus& status)
+{
+  cmMakefile& mf = status.GetMakefile();
+
+  for (std::string const& o : outputs) {
+    // Make sure the file will not be generated into the source
+    // directory during an out of source build.
+    if (!mf.CanIWriteThisFile(o)) {
+      status.SetError(
+        cmStrCat("attempted to have a file\n  ", o,
+                 "\nin a source directory as an output of custom command."));
+      cmSystemTools::SetFatalErrorOccured();
+      return false;
+    }
+
+    // Make sure the output file name has no invalid characters.
+    std::string::size_type pos = o.find_first_of("#<>");
+    if (pos != std::string::npos) {
+      status.SetError(cmStrCat("called with ", keyword, " containing a \"",
+                               o[pos], "\".  This character is not allowed."));
+      return false;
+    }
+  }
+
+  return true;
+}

+ 18 - 0
Source/cmCheckCustomOutputs.h

@@ -0,0 +1,18 @@
+/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+   file Copyright.txt or https://cmake.org/licensing for details.  */
+#ifndef cmCheckCustomOutputs_h
+#define cmCheckCustomOutputs_h
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <cm/string_view>
+
+#include <string>
+#include <vector>
+
+class cmExecutionStatus;
+
+bool cmCheckCustomOutputs(const std::vector<std::string>& outputs,
+                          cm::string_view keyword, cmExecutionStatus& status);
+
+#endif

+ 1 - 1
Tests/RunCMake/add_custom_command/AppendNotOutput-stderr.txt

@@ -1,7 +1,7 @@
 CMake Error at AppendNotOutput.cmake:1 \(add_custom_command\):
   add_custom_command given APPEND option with output
 
-  .*RunCMake/add_custom_command/AppendNotOutput-build/out.*
+    .*RunCMake/add_custom_command/AppendNotOutput-build/out
 
   which is not already a custom command output.
 Call Stack \(most recent call first\):

+ 1 - 0
Tests/RunCMake/add_custom_command/BadByproduct-result.txt

@@ -0,0 +1 @@
+1

+ 36 - 0
Tests/RunCMake/add_custom_command/BadByproduct-stderr.txt

@@ -0,0 +1,36 @@
+CMake Error at BadByproduct.cmake:2 \(add_custom_command\):
+  add_custom_command called with BYPRODUCTS containing a "#".  This character
+  is not allowed.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)
+
+
+CMake Error at BadByproduct.cmake:3 \(add_custom_command\):
+  add_custom_command called with BYPRODUCTS containing a "<".  This character
+  is not allowed.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)
+
+
+CMake Error at BadByproduct.cmake:4 \(add_custom_command\):
+  add_custom_command called with BYPRODUCTS containing a ">".  This character
+  is not allowed.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)
+
+
+CMake Error at BadByproduct.cmake:5 \(add_custom_command\):
+  add_custom_command called with BYPRODUCTS containing a "<".  This character
+  is not allowed.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)
+
+
+CMake Error at BadByproduct.cmake:6 \(add_custom_command\):
+  add_custom_command attempted to have a file
+
+    .*RunCMake/add_custom_command/f
+
+  in a source directory as an output of custom command.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)

+ 6 - 0
Tests/RunCMake/add_custom_command/BadByproduct.cmake

@@ -0,0 +1,6 @@
+set(CMAKE_DISABLE_SOURCE_CHANGES ON)
+add_custom_command(OUTPUT a BYPRODUCTS "a#")
+add_custom_command(OUTPUT b BYPRODUCTS "a<")
+add_custom_command(OUTPUT c BYPRODUCTS "a>")
+add_custom_command(OUTPUT d BYPRODUCTS "$<CONFIG>/#")
+add_custom_command(OUTPUT e BYPRODUCTS ${CMAKE_CURRENT_SOURCE_DIR}/f)

+ 1 - 0
Tests/RunCMake/add_custom_command/BadOutput-result.txt

@@ -0,0 +1 @@
+1

+ 36 - 0
Tests/RunCMake/add_custom_command/BadOutput-stderr.txt

@@ -0,0 +1,36 @@
+CMake Error at BadOutput.cmake:2 \(add_custom_command\):
+  add_custom_command called with OUTPUT containing a "#".  This character is
+  not allowed.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)
+
+
+CMake Error at BadOutput.cmake:3 \(add_custom_command\):
+  add_custom_command called with OUTPUT containing a "<".  This character is
+  not allowed.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)
+
+
+CMake Error at BadOutput.cmake:4 \(add_custom_command\):
+  add_custom_command called with OUTPUT containing a ">".  This character is
+  not allowed.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)
+
+
+CMake Error at BadOutput.cmake:5 \(add_custom_command\):
+  add_custom_command called with OUTPUT containing a "<".  This character is
+  not allowed.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)
+
+
+CMake Error at BadOutput.cmake:6 \(add_custom_command\):
+  add_custom_command attempted to have a file
+
+    .*RunCMake/add_custom_command/e
+
+  in a source directory as an output of custom command.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)

+ 6 - 0
Tests/RunCMake/add_custom_command/BadOutput.cmake

@@ -0,0 +1,6 @@
+set(CMAKE_DISABLE_SOURCE_CHANGES ON)
+add_custom_command(OUTPUT "a#" COMMAND a)
+add_custom_command(OUTPUT "a<" COMMAND b)
+add_custom_command(OUTPUT "a>" COMMAND c)
+add_custom_command(OUTPUT "$<CONFIG>/#" COMMAND d)
+add_custom_command(OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/e COMMAND f)

+ 2 - 0
Tests/RunCMake/add_custom_command/RunCMakeTest.cmake

@@ -4,6 +4,8 @@ run_cmake(AppendLiteralQuotes)
 run_cmake(AppendNoOutput)
 run_cmake(AppendNotOutput)
 run_cmake(BadArgument)
+run_cmake(BadByproduct)
+run_cmake(BadOutput)
 run_cmake(GeneratedProperty)
 run_cmake(LiteralQuotes)
 run_cmake(NoArguments)

+ 1 - 0
Tests/RunCMake/add_custom_target/BadByproduct-result.txt

@@ -0,0 +1 @@
+1

+ 36 - 0
Tests/RunCMake/add_custom_target/BadByproduct-stderr.txt

@@ -0,0 +1,36 @@
+CMake Error at BadByproduct.cmake:2 \(add_custom_target\):
+  add_custom_target called with BYPRODUCTS containing a "#".  This character
+  is not allowed.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)
+
+
+CMake Error at BadByproduct.cmake:3 \(add_custom_target\):
+  add_custom_target called with BYPRODUCTS containing a "<".  This character
+  is not allowed.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)
+
+
+CMake Error at BadByproduct.cmake:4 \(add_custom_target\):
+  add_custom_target called with BYPRODUCTS containing a ">".  This character
+  is not allowed.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)
+
+
+CMake Error at BadByproduct.cmake:5 \(add_custom_target\):
+  add_custom_target called with BYPRODUCTS containing a "<".  This character
+  is not allowed.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)
+
+
+CMake Error at BadByproduct.cmake:6 \(add_custom_target\):
+  add_custom_target attempted to have a file
+
+    .*RunCMake/add_custom_target/j
+
+  in a source directory as an output of custom command.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)

+ 6 - 0
Tests/RunCMake/add_custom_target/BadByproduct.cmake

@@ -0,0 +1,6 @@
+set(CMAKE_DISABLE_SOURCE_CHANGES ON)
+add_custom_target(a BYPRODUCTS "a#" COMMAND b)
+add_custom_target(c BYPRODUCTS "a<" COMMAND d)
+add_custom_target(e BYPRODUCTS "a>" COMMAND f)
+add_custom_target(g BYPRODUCTS "$<CONFIG>/#" COMMAND h)
+add_custom_target(i BYPRODUCTS ${CMAKE_CURRENT_SOURCE_DIR}/j COMMAND k)

+ 4 - 3
Tests/RunCMake/add_custom_target/RunCMakeTest.cmake

@@ -1,11 +1,12 @@
 include(RunCMake)
 
-run_cmake(CommandExpandsEmpty)
-run_cmake(GeneratedProperty)
-run_cmake(NoArguments)
+run_cmake(BadByproduct)
 run_cmake(BadTargetName)
 run_cmake(ByproductsNoCommand)
+run_cmake(CommandExpandsEmpty)
+run_cmake(GeneratedProperty)
 run_cmake(LiteralQuotes)
+run_cmake(NoArguments)
 run_cmake(UsesTerminalNoCommand)
 
 function(run_TargetOrder)

+ 1 - 0
bootstrap

@@ -278,6 +278,7 @@ CMAKE_CXX_SOURCES="\
   cmCMakePolicyCommand \
   cmCPackPropertiesGenerator \
   cmCacheManager \
+  cmCheckCustomOutputs \
   cmCommand \
   cmCommandArgumentParserHelper \
   cmCommands \