Merge topic 'ExternalProject-log-options'

7ddc9e353b ExternalProject: option LOG_MERGED_STDOUTERR to combine stdout and stderr
b6f6cac378 ExternalProject: add LOG_DIR option that allows overriding of log location

Acked-by: Kitware Robot <kwrobot@kitware.com>
Merge-request: !2488
diff --git a/Auxiliary/vim/syntax/cmake.vim b/Auxiliary/vim/syntax/cmake.vim
index 076b47f..25384e4 100644
--- a/Auxiliary/vim/syntax/cmake.vim
+++ b/Auxiliary/vim/syntax/cmake.vim
@@ -873,8 +873,10 @@
             \ LOG_
             \ LOG_BUILD
             \ LOG_CONFIGURE
+            \ LOG_DIR
             \ LOG_DOWNLOAD
             \ LOG_INSTALL
+            \ LOG_MERGED_STDOUTERR
             \ LOG_TEST
             \ LOG_UPDATE
             \ MAKE_EXE
diff --git a/Help/release/dev/ExternalProject-log-options.rst b/Help/release/dev/ExternalProject-log-options.rst
new file mode 100644
index 0000000..2fc4c4f
--- /dev/null
+++ b/Help/release/dev/ExternalProject-log-options.rst
@@ -0,0 +1,5 @@
+ExternalProject-log-options
+---------------------------
+
+* The :module:`ExternalProject` module :command:`ExternalProject_Add` command
+  gained ``LOG_DIR`` and ``LOG_MERGED_STDOUTERR`` options to control logging.
diff --git a/Modules/ExternalProject.cmake b/Modules/ExternalProject.cmake
index eb4f9fa..a8c31ed 100644
--- a/Modules/ExternalProject.cmake
+++ b/Modules/ExternalProject.cmake
@@ -49,7 +49,11 @@
 
     ``STAMP_DIR <dir>``
       Directory in which to store the timestamps of each step. Log files from
-      individual steps are also created in here (see *Logging Options* below).
+      individual steps are also created in here unless overriden by LOG_DIR
+      (see *Logging Options* below).
+
+    ``LOG_DIR <dir>``
+      Directory in which to store the logs of each step.
 
     ``DOWNLOAD_DIR <dir>``
       Directory in which to store downloaded files before unpacking them. This
@@ -92,6 +96,7 @@
       SOURCE_DIR   = <prefix>/src/<name>
       BINARY_DIR   = <prefix>/src/<name>-build
       INSTALL_DIR  = <prefix>
+      LOG_DIR      = <STAMP_DIR>
 
     Otherwise, if the ``EP_BASE`` directory property is set then components
     of an external project are stored under the specified base::
@@ -102,6 +107,7 @@
       SOURCE_DIR   = <base>/Source/<name>
       BINARY_DIR   = <base>/Build/<name>
       INSTALL_DIR  = <base>/Install/<name>
+      LOG_DIR      = <STAMP_DIR>
 
     If no ``PREFIX``, ``EP_PREFIX``, or ``EP_BASE`` is specified, then the
     default is to set ``PREFIX`` to ``<name>-prefix``. Relative paths are
@@ -517,7 +523,8 @@
   **Output Logging Options:**
     Each of the following ``LOG_...`` options can be used to wrap the relevant
     step in a script to capture its output to files. The log files will be
-    created in the ``STAMP_DIR`` directory with step-specific file names.
+    created in ``LOG_DIR`` if supplied or otherwise the ``STAMP_DIR``
+    directory with step-specific file names.
 
     ``LOG_DOWNLOAD <bool>``
       When enabled, the output of the download step is logged to files.
@@ -537,6 +544,9 @@
     ``LOG_TEST <bool>``
       When enabled, the output of the test step is logged to files.
 
+    ``LOG_MERGED_STDOUTERR <bool>``
+      When enabled, the output the step is not split by stdout and stderr.
+
   **Terminal Access Options:**
     Steps can be given direct access to the terminal in some cases. Giving a
     step access to the terminal may allow it to receive terminal input if
@@ -713,7 +723,7 @@
 
   ``LOG <bool>``
     If set, this causes the output from the custom step to be captured to files
-    in the external project's ``STAMP_DIR``.
+    in the external project's ``LOG_DIR`` if supplied or ``STAMP_DIR``.
 
   ``USES_TERMINAL <bool>``
     If enabled, this gives the custom step direct access to the terminal if
@@ -1620,6 +1630,7 @@
     set(stamp_default "${base}/Stamp/${name}")
     set(install_default "${base}/Install/${name}")
   endif()
+  set(log_default "${stamp_default}")
   get_property(build_in_source TARGET ${name} PROPERTY _EP_BUILD_IN_SOURCE)
   if(build_in_source)
     get_property(have_binary_dir TARGET ${name} PROPERTY _EP_BINARY_DIR SET)
@@ -1629,7 +1640,7 @@
     endif()
   endif()
   set(top "${CMAKE_CURRENT_BINARY_DIR}")
-  set(places stamp download source binary install tmp)
+  set(places stamp download source binary install tmp log)
   foreach(var ${places})
     string(TOUPPER "${var}" VAR)
     get_property(${var}_dir TARGET ${name} PROPERTY _EP_${VAR}_DIR)
@@ -1683,7 +1694,7 @@
   set(vars ${ARGN})
   foreach(var ${vars})
     if(${var})
-      foreach(dir SOURCE_DIR SOURCE_SUBDIR BINARY_DIR INSTALL_DIR TMP_DIR DOWNLOAD_DIR DOWNLOADED_FILE)
+      foreach(dir SOURCE_DIR SOURCE_SUBDIR BINARY_DIR INSTALL_DIR TMP_DIR DOWNLOAD_DIR DOWNLOADED_FILE LOG_DIR)
         get_property(val TARGET ${target_name} PROPERTY _EP_${dir})
         string(REPLACE "<${dir}>" "${val}" ${var} "${${var}}")
       endforeach()
@@ -1865,6 +1876,7 @@
 endfunction()
 
 function(_ep_write_log_script name step cmd_var)
+  ExternalProject_Get_Property(${name} log_dir)
   ExternalProject_Get_Property(${name} stamp_dir)
   set(command "${${cmd_var}}")
 
@@ -1936,22 +1948,30 @@
 
   # Wrap the command in a script to log output to files.
   set(script ${stamp_dir}/${name}-${step}-$<CONFIG>.cmake)
-  set(logbase ${stamp_dir}/${name}-${step})
+  set(logbase ${log_dir}/${name}-${step})
+  get_property(log_merged TARGET ${name} PROPERTY _EP_LOG_MERGED_STDOUTERR)
+  if (log_merged)
+    set(stdout_log "${logbase}.log")
+    set(stderr_log "${logbase}.log")
+  else()
+    set(stdout_log "${logbase}-out.log")
+    set(stderr_log "${logbase}-err.log")
+  endif()
   set(code "
 ${code_cygpath_make}
 set(command \"${command}\")
 execute_process(
   COMMAND \${command}
   RESULT_VARIABLE result
-  OUTPUT_FILE \"${logbase}-out.log\"
-  ERROR_FILE \"${logbase}-err.log\"
+  OUTPUT_FILE \"${stdout_log}\"
+  ERROR_FILE \"${stderr_log}\"
   )
 if(result)
   set(msg \"Command failed: \${result}\\n\")
   foreach(arg IN LISTS command)
     set(msg \"\${msg} '\${arg}'\")
   endforeach()
-  set(msg \"\${msg}\\nSee also\\n  ${logbase}-*.log\")
+  set(msg \"\${msg}\\nSee also\\n  ${stderr_log}\")
   message(FATAL_ERROR \"\${msg}\")
 else()
   set(msg \"${name} ${step} command succeeded.  See also ${logbase}-*.log\")
@@ -2224,7 +2244,7 @@
 
 function(_ep_add_mkdir_command name)
   ExternalProject_Get_Property(${name}
-    source_dir binary_dir install_dir stamp_dir download_dir tmp_dir)
+    source_dir binary_dir install_dir stamp_dir download_dir tmp_dir log_dir)
 
   _ep_get_configuration_subdir_suffix(cfgdir)
 
@@ -2236,6 +2256,7 @@
     COMMAND ${CMAKE_COMMAND} -E make_directory ${tmp_dir}
     COMMAND ${CMAKE_COMMAND} -E make_directory ${stamp_dir}${cfgdir}
     COMMAND ${CMAKE_COMMAND} -E make_directory ${download_dir}
+    COMMAND ${CMAKE_COMMAND} -E make_directory ${log_dir}
     )
 endfunction()
 
diff --git a/Tests/ExternalProject/CMakeLists.txt b/Tests/ExternalProject/CMakeLists.txt
index 6b73563..5adcbd9 100644
--- a/Tests/ExternalProject/CMakeLists.txt
+++ b/Tests/ExternalProject/CMakeLists.txt
@@ -631,3 +631,21 @@
   LOG_BUILD 1
   LOG_INSTALL 1
   )
+
+set(proj ExternalProject-log-dir)
+ExternalProject_Add(${proj}
+  DOWNLOAD_COMMAND "${download_cmd}" COMMAND "${CMAKE_COMMAND}" -E echo "download"
+  PATCH_COMMAND "${patch_cmd}" COMMAND "${CMAKE_COMMAND}" -E echo "patch"
+  UPDATE_COMMAND "${update_cmd}" COMMAND "${CMAKE_COMMAND}" -E echo "update"
+  CONFIGURE_COMMAND "${configure_cmd}" COMMAND "${CMAKE_COMMAND}" -E echo "configure"
+  BUILD_COMMAND "${build_cmd}" COMMAND "${CMAKE_COMMAND}" -E echo "build"
+  INSTALL_COMMAND "${install_cmd}" COMMAND "${CMAKE_COMMAND}" -E echo "install"
+  LOG_MERGED_STDOUTERR 1
+  LOG_DIR ${CMAKE_CURRENT_BINARY_DIR}/different_log
+  LOG_DOWNLOAD 1
+  LOG_PATCH 1
+  LOG_UPDATE 1
+  LOG_CONFIGURE 1
+  LOG_BUILD 1
+  LOG_INSTALL 1
+  )