From c09ec7998148e3c69bf0c7fd2d626a6ccc23e37e Mon Sep 17 00:00:00 2001
From: Ben Boeckel <ben.boeckel@kitware.com>
Date: Thu, 17 Jan 2019 13:34:45 -0500
Subject: ExternalProject: support SOURCE_SUBDIR for BUILD_IN_SOURCE

---
 .../dev/ExternalProject-non-cmake-source-subdir.rst  |  7 +++++++
 Modules/ExternalProject.cmake                        | 10 ++++++++--
 Tests/CMakeLists.txt                                 | 12 ++++++++++++
 .../CMakeLists.txt                                   | 20 ++++++++++++++++++++
 .../Example/subdir/Makefile                          |  2 ++
 5 files changed, 49 insertions(+), 2 deletions(-)
 create mode 100644 Help/release/dev/ExternalProject-non-cmake-source-subdir.rst
 create mode 100644 Tests/ExternalProjectSourceSubdirNotCMake/CMakeLists.txt
 create mode 100644 Tests/ExternalProjectSourceSubdirNotCMake/Example/subdir/Makefile

diff --git a/Help/release/dev/ExternalProject-non-cmake-source-subdir.rst b/Help/release/dev/ExternalProject-non-cmake-source-subdir.rst
new file mode 100644
index 0000000..29fe2ad
--- /dev/null
+++ b/Help/release/dev/ExternalProject-non-cmake-source-subdir.rst
@@ -0,0 +1,7 @@
+ExternalProject-non-cmake-source-subdir
+---------------------------------------
+
+* The :module:`ExternalProject` module's ``ExternalProject_Add`` command
+  learned to apply ``SOURCE_SUBDIR`` when ``BUILD_IN_SOURCE`` is also used.
+  The ``BUILD_COMMAND`` is run in the given ``SOURCE_SUBDIR`` of the
+  ``SOURCE_DIR``.
diff --git a/Modules/ExternalProject.cmake b/Modules/ExternalProject.cmake
index e763bab..c5d6b45 100644
--- a/Modules/ExternalProject.cmake
+++ b/Modules/ExternalProject.cmake
@@ -425,7 +425,9 @@ External Project Definition
       can be used to point to an alternative directory within the source tree
       to use as the top of the CMake source tree instead. This must be a
       relative path and it will be interpreted as being relative to
-      ``SOURCE_DIR``.
+      ``SOURCE_DIR``.  When ``BUILD_IN_SOURCE 1`` is specified, the
+      ``BUILD_COMMAND`` is used to point to an alternative directory within the
+      source tree.
 
   **Build Step Options:**
     If the configure step assumed the external project uses CMake as its build
@@ -1676,7 +1678,11 @@ function(_ep_set_directories name)
   endif()
   if(build_in_source)
     get_property(source_dir TARGET ${name} PROPERTY _EP_SOURCE_DIR)
-    set_property(TARGET ${name} PROPERTY _EP_BINARY_DIR "${source_dir}")
+    if(source_subdir)
+      set_property(TARGET ${name} PROPERTY _EP_BINARY_DIR "${source_dir}/${source_subdir}")
+    else()
+      set_property(TARGET ${name} PROPERTY _EP_BINARY_DIR "${source_dir}")
+    endif()
   endif()
 
   # Make the directories at CMake configure time *and* add a custom command
diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt
index 6b166d6..ef60c51 100644
--- a/Tests/CMakeLists.txt
+++ b/Tests/CMakeLists.txt
@@ -1635,6 +1635,18 @@ ${CMake_BINARY_DIR}/bin/cmake -DDIR=dev -P ${CMake_SOURCE_DIR}/Utilities/Release
     )
   list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/ExternalProjectSourceSubdir")
 
+  add_test(NAME ExternalProjectSourceSubdirNotCMake
+    COMMAND ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION>
+    --build-and-test
+    "${CMake_SOURCE_DIR}/Tests/ExternalProjectSourceSubdirNotCMake"
+    "${CMake_BINARY_DIR}/Tests/ExternalProjectSourceSubdirNotCMake"
+    ${build_generator_args}
+    --build-project ExternalProjectSourceSubdirNotCMake
+    --force-new-ctest-process
+    --build-options ${build_options}
+    )
+  list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/ExternalProjectSourceSubdirNotCMake")
+
   add_test(ExternalProjectLocal ${CMAKE_CTEST_COMMAND}
     --build-and-test
     "${CMake_SOURCE_DIR}/Tests/ExternalProjectLocal"
diff --git a/Tests/ExternalProjectSourceSubdirNotCMake/CMakeLists.txt b/Tests/ExternalProjectSourceSubdirNotCMake/CMakeLists.txt
new file mode 100644
index 0000000..f64df1a
--- /dev/null
+++ b/Tests/ExternalProjectSourceSubdirNotCMake/CMakeLists.txt
@@ -0,0 +1,20 @@
+cmake_minimum_required(VERSION 3.6)
+project(ExternalProjectSourceSubdirNotCMake NONE)
+include(ExternalProject)
+
+find_program(MAKE_EXECUTABLE
+  NAMES gmake make)
+
+if (NOT MAKE_EXECUTABLE)
+  message("No `make` executable found; skipping")
+  return ()
+endif ()
+
+ExternalProject_Add(Example
+  SOURCE_SUBDIR subdir
+  BUILD_IN_SOURCE 1
+  SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/Example
+  CONFIGURE_COMMAND ""
+  BUILD_COMMAND "${MAKE_EXECUTABLE}"
+  INSTALL_COMMAND ""
+  )
diff --git a/Tests/ExternalProjectSourceSubdirNotCMake/Example/subdir/Makefile b/Tests/ExternalProjectSourceSubdirNotCMake/Example/subdir/Makefile
new file mode 100644
index 0000000..cab3b8f
--- /dev/null
+++ b/Tests/ExternalProjectSourceSubdirNotCMake/Example/subdir/Makefile
@@ -0,0 +1,2 @@
+all:
+	echo "complete"
-- 
cgit v0.12