diff --git a/Modules/ExternalProject.cmake b/Modules/ExternalProject.cmake
index e27eb728c..5ea309fbb 100644
--- a/Modules/ExternalProject.cmake
+++ b/Modules/ExternalProject.cmake
@@ -98,6 +98,8 @@ Create custom targets to build projects in external trees
``SOURCE_DIR
``
Source dir to be used for build
+ ``SOURCE_SUBDIR ``
+ Path to source CMakeLists.txt relative to ``SOURCE_DIR``
``CONFIGURE_COMMAND ...``
Build tree configuration command
``CMAKE_COMMAND /.../cmake``
@@ -236,6 +238,11 @@ Create custom targets to build projects in external trees
interpreted with respect to the build directory corresponding to the
source directory in which ``ExternalProject_Add`` is invoked.
+ If ``SOURCE_SUBDIR`` is set and no ``CONFIGURE_COMMAND`` is specified, the
+ configure command will run CMake using the ``CMakeLists.txt`` located in the
+ relative path specified by ``SOURCE_SUBDIR``, relative to the ``SOURCE_DIR``.
+ If no ``SOURCE_SUBDIR`` is given, ``SOURCE_DIR`` is used.
+
If ``SOURCE_DIR`` is explicitly set to an existing directory the project
will be built from it. Otherwise a download step must be specified
using one of the ``DOWNLOAD_COMMAND``, ``CVS_*``, ``SVN_*``, or ``URL``
@@ -287,8 +294,8 @@ Create custom targets to build projects in external trees
The command line, comment, working directory, and byproducts of every
standard and custom step are processed to replace tokens ````,
- ````, ````, and ```` with
- corresponding property values.
+ ````, ````, ````, and ````
+ with corresponding property values.
Any builtin step that specifies a ``_COMMAND cmd...`` or custom
step that specifies a ``COMMAND cmd...`` may specify additional command
@@ -1065,6 +1072,13 @@ function(_ep_set_directories name)
endif()
set_property(TARGET ${name} PROPERTY _EP_${VAR}_DIR "${${var}_dir}")
endforeach()
+ get_property(source_subdir TARGET ${name} PROPERTY _EP_SOURCE_SUBDIR)
+ if(NOT source_subdir)
+ set_property(TARGET ${name} PROPERTY _EP_SOURCE_SUBDIR ".")
+ elseif(IS_ABSOLUTE "${source_subdir}")
+ message(FATAL_ERROR
+ "External project ${name} has non-relative SOURCE_SUBDIR!")
+ 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}")
@@ -1096,7 +1110,7 @@ macro(_ep_replace_location_tags target_name)
set(vars ${ARGN})
foreach(var ${vars})
if(${var})
- foreach(dir SOURCE_DIR BINARY_DIR INSTALL_DIR TMP_DIR DOWNLOADED_FILE)
+ foreach(dir SOURCE_DIR SOURCE_SUBDIR BINARY_DIR INSTALL_DIR TMP_DIR DOWNLOADED_FILE)
get_property(val TARGET ${target_name} PROPERTY _EP_${dir})
string(REPLACE "<${dir}>" "${val}" ${var} "${${var}}")
endforeach()
@@ -2148,7 +2162,7 @@ endfunction()
# TODO: Make sure external projects use the proper compiler
function(_ep_add_configure_command name)
- ExternalProject_Get_Property(${name} source_dir binary_dir tmp_dir)
+ ExternalProject_Get_Property(${name} source_dir source_subdir binary_dir tmp_dir)
# Depend on other external projects (file-level).
set(file_deps)
@@ -2226,7 +2240,11 @@ function(_ep_add_configure_command name)
endif()
endif()
- list(APPEND cmd "${source_dir}")
+ if(source_subdir STREQUAL ".")
+ list(APPEND cmd "${source_dir}")
+ else()
+ list(APPEND cmd "${source_dir}/${source_subdir}")
+ endif()
endif()
# If anything about the configure command changes, (command itself, cmake
diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt
index 2d234db1d..6f1805b04 100644
--- a/Tests/CMakeLists.txt
+++ b/Tests/CMakeLists.txt
@@ -1464,6 +1464,18 @@ ${CMake_BINARY_DIR}/bin/cmake -DDIR=dev -P ${CMake_SOURCE_DIR}/Utilities/Release
)
list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/ExternalProjectSubdir")
+ add_test(NAME ExternalProjectSourceSubdir
+ COMMAND ${CMAKE_CTEST_COMMAND} -C $
+ --build-and-test
+ "${CMake_SOURCE_DIR}/Tests/ExternalProjectSourceSubdir"
+ "${CMake_BINARY_DIR}/Tests/ExternalProjectSourceSubdir"
+ ${build_generator_args}
+ --build-project ExternalProjectSourceSubdir
+ --force-new-ctest-process
+ --build-options ${build_options}
+ )
+ list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/ExternalProjectSourceSubdir")
+
add_test(ExternalProjectLocal ${CMAKE_CTEST_COMMAND}
--build-and-test
"${CMake_SOURCE_DIR}/Tests/ExternalProjectLocal"
diff --git a/Tests/ExternalProjectSourceSubdir/CMakeLists.txt b/Tests/ExternalProjectSourceSubdir/CMakeLists.txt
new file mode 100644
index 000000000..4688acfb0
--- /dev/null
+++ b/Tests/ExternalProjectSourceSubdir/CMakeLists.txt
@@ -0,0 +1,10 @@
+cmake_minimum_required(VERSION 3.6)
+project(ExternalProjectSourceSubdir NONE)
+include(ExternalProject)
+
+ExternalProject_Add(Example
+ SOURCE_SUBDIR subdir
+ SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/Example
+ BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/Example
+ INSTALL_COMMAND ""
+ )
diff --git a/Tests/ExternalProjectSourceSubdir/Example/subdir/CMakeLists.txt b/Tests/ExternalProjectSourceSubdir/Example/subdir/CMakeLists.txt
new file mode 100644
index 000000000..bbc3ca0a2
--- /dev/null
+++ b/Tests/ExternalProjectSourceSubdir/Example/subdir/CMakeLists.txt
@@ -0,0 +1,2 @@
+cmake_minimum_required(VERSION 3.0)
+project(empty)