ExternalProject: Add SOURCE_SUBDIR option

Add a new SOURCE_SUBDIR option to ExternalProject_Add that allows
specifying the location of the CMakeLists.txt to use as the project root
relative to the SOURCE_DIR.

This is helpful for projects that have unusual layouts, or projects that
provide both a superbuild and project-only build depending on which
CMakeLists.txt is used.

Fixes: #15118
This commit is contained in:
Matthew Woehlke 2016-08-15 14:42:22 -04:00 committed by Brad King
parent f59513140b
commit a8345d65f3
4 changed files with 47 additions and 5 deletions

View File

@ -98,6 +98,8 @@ Create custom targets to build projects in external trees
``SOURCE_DIR <dir>`` ``SOURCE_DIR <dir>``
Source dir to be used for build Source dir to be used for build
``SOURCE_SUBDIR <dir>``
Path to source CMakeLists.txt relative to ``SOURCE_DIR``
``CONFIGURE_COMMAND <cmd>...`` ``CONFIGURE_COMMAND <cmd>...``
Build tree configuration command Build tree configuration command
``CMAKE_COMMAND /.../cmake`` ``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 interpreted with respect to the build directory corresponding to the
source directory in which ``ExternalProject_Add`` is invoked. 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 If ``SOURCE_DIR`` is explicitly set to an existing directory the project
will be built from it. Otherwise a download step must be specified will be built from it. Otherwise a download step must be specified
using one of the ``DOWNLOAD_COMMAND``, ``CVS_*``, ``SVN_*``, or ``URL`` 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 The command line, comment, working directory, and byproducts of every
standard and custom step are processed to replace tokens ``<SOURCE_DIR>``, standard and custom step are processed to replace tokens ``<SOURCE_DIR>``,
``<BINARY_DIR>``, ``<INSTALL_DIR>``, and ``<TMP_DIR>`` with ``<SOURCE_SUBDIR>``, ``<BINARY_DIR>``, ``<INSTALL_DIR>``, and ``<TMP_DIR>``
corresponding property values. with corresponding property values.
Any builtin step that specifies a ``<step>_COMMAND cmd...`` or custom Any builtin step that specifies a ``<step>_COMMAND cmd...`` or custom
step that specifies a ``COMMAND cmd...`` may specify additional command step that specifies a ``COMMAND cmd...`` may specify additional command
@ -1064,6 +1071,13 @@ function(_ep_set_directories name)
endif() endif()
set_property(TARGET ${name} PROPERTY _EP_${VAR}_DIR "${${var}_dir}") set_property(TARGET ${name} PROPERTY _EP_${VAR}_DIR "${${var}_dir}")
endforeach() 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) if(build_in_source)
get_property(source_dir TARGET ${name} PROPERTY _EP_SOURCE_DIR) get_property(source_dir TARGET ${name} PROPERTY _EP_SOURCE_DIR)
set_property(TARGET ${name} PROPERTY _EP_BINARY_DIR "${source_dir}") set_property(TARGET ${name} PROPERTY _EP_BINARY_DIR "${source_dir}")
@ -1095,7 +1109,7 @@ macro(_ep_replace_location_tags target_name)
set(vars ${ARGN}) set(vars ${ARGN})
foreach(var ${vars}) foreach(var ${vars})
if(${var}) 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}) get_property(val TARGET ${target_name} PROPERTY _EP_${dir})
string(REPLACE "<${dir}>" "${val}" ${var} "${${var}}") string(REPLACE "<${dir}>" "${val}" ${var} "${${var}}")
endforeach() endforeach()
@ -2131,7 +2145,7 @@ endfunction()
# TODO: Make sure external projects use the proper compiler # TODO: Make sure external projects use the proper compiler
function(_ep_add_configure_command name) 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). # Depend on other external projects (file-level).
set(file_deps) set(file_deps)
@ -2209,7 +2223,11 @@ function(_ep_add_configure_command name)
endif() endif()
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() endif()
# If anything about the configure command changes, (command itself, cmake # If anything about the configure command changes, (command itself, cmake

View File

@ -1441,6 +1441,18 @@ ${CMake_BINARY_DIR}/bin/cmake -DDIR=dev -P ${CMake_SOURCE_DIR}/Utilities/Release
) )
list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/ExternalProjectSubdir") list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/ExternalProjectSubdir")
add_test(NAME ExternalProjectSourceSubdir
COMMAND ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION>
--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} add_test(ExternalProjectLocal ${CMAKE_CTEST_COMMAND}
--build-and-test --build-and-test
"${CMake_SOURCE_DIR}/Tests/ExternalProjectLocal" "${CMake_SOURCE_DIR}/Tests/ExternalProjectLocal"

View File

@ -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 ""
)

View File

@ -0,0 +1,2 @@
cmake_minimum_required(VERSION 3.0)
project(empty)