summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Cole <david.cole@kitware.com>2008-12-05 20:18:32 (GMT)
committerDavid Cole <david.cole@kitware.com>2008-12-05 20:18:32 (GMT)
commitdba2c51d90e28e4780a948bb06cbf17a2db1253e (patch)
treecdb954a6a8e6edf6a28005e4dbfa0fc2cc9d3108
parent4da124e9681e1c06b511505a0cef42364e14e680 (diff)
downloadCMake-dba2c51d90e28e4780a948bb06cbf17a2db1253e.zip
CMake-dba2c51d90e28e4780a948bb06cbf17a2db1253e.tar.gz
CMake-dba2c51d90e28e4780a948bb06cbf17a2db1253e.tar.bz2
ENH: Make it easier to use configure/make/make-install as the build steps for an external project. Add capability of customizing the download step. Add tests of empty projects. Better comments and error checking in AddExternalProject.cmake. In tests, use KWStyle from CVSHEAD to see if QNX continuous can build the latest KWStyle. Make KWStyle test depend on all previous test external projects so it builds last to catch other issues before any KWStyle compile errors.
-rw-r--r--Modules/AddExternalProject.cmake225
-rw-r--r--Tests/ExternalProject/CMakeLists.txt97
2 files changed, 217 insertions, 105 deletions
diff --git a/Modules/AddExternalProject.cmake b/Modules/AddExternalProject.cmake
index 9e14bd2..5fd6df0 100644
--- a/Modules/AddExternalProject.cmake
+++ b/Modules/AddExternalProject.cmake
@@ -36,6 +36,36 @@ function(get_configure_build_working_dir name working_dir_var)
endfunction(get_configure_build_working_dir)
+function(get_configure_command_id name cfg_cmd_id_var)
+ get_target_property(cmd ${name} AEP_CONFIGURE_COMMAND)
+
+ if(cmd STREQUAL "")
+ # Explicit empty string means no configure step for this project
+ set(${cfg_cmd_id_var} "none" PARENT_SCOPE)
+ else()
+ if(NOT cmd)
+ # Default is "use cmake":
+ set(${cfg_cmd_id_var} "cmake" PARENT_SCOPE)
+ else()
+ # Otherwise we have to analyze the value:
+ if(cmd MATCHES "/configure$")
+ set(${cfg_cmd_id_var} "configure" PARENT_SCOPE)
+ else()
+ if(cmd MATCHES "cmake")
+ set(${cfg_cmd_id_var} "cmake" PARENT_SCOPE)
+ else()
+ if(cmd MATCHES "config")
+ set(${cfg_cmd_id_var} "configure" PARENT_SCOPE)
+ else()
+ set(${cfg_cmd_id_var} "unknown:${cmd}" PARENT_SCOPE)
+ endif()
+ endif()
+ endif()
+ endif()
+ endif()
+endfunction(get_configure_command_id)
+
+
function(add_external_project_download_command name)
set(added 0)
get_external_project_directories(base_dir build_dir downloads_dir install_dir
@@ -43,6 +73,42 @@ function(add_external_project_download_command name)
if(NOT added)
+ get_target_property(cmd ${name} AEP_DOWNLOAD_COMMAND)
+ if(cmd STREQUAL "")
+ # Explicit empty string means no download step for this project
+ add_custom_command(
+ OUTPUT ${sentinels_dir}/${name}-download
+ COMMAND ${CMAKE_COMMAND} -E touch ${sentinels_dir}/${name}-download
+ WORKING_DIRECTORY ${sentinels_dir}
+ COMMENT "No download step for '${name}'"
+ )
+ set(added 1)
+ else()
+ if(cmd)
+ set(args "")
+ get_target_property(download_args ${name} AEP_DOWNLOAD_ARGS)
+ if(download_args)
+ set(args "${download_args}")
+ separate_arguments(args)
+ endif()
+
+ add_custom_command(
+ OUTPUT ${sentinels_dir}/${name}-download
+ COMMAND ${cmd} ${args}
+ COMMAND ${CMAKE_COMMAND} -E touch ${sentinels_dir}/${name}-download
+ WORKING_DIRECTORY ${downloads_dir}
+ COMMENT "Performing download step for '${name}'"
+ )
+ set(added 1)
+ else()
+ # No explicit DOWNLOAD_COMMAND property. Look for other properties
+ # indicating which download method to use in the logic below...
+ endif()
+ endif()
+ endif()
+
+
+ if(NOT added)
get_target_property(cvs_repository ${name} AEP_CVS_REPOSITORY)
if(cvs_repository)
if(NOT CVS_EXECUTABLE)
@@ -275,13 +341,21 @@ function(add_external_project_build_command name)
DEPENDS ${sentinels_dir}/${name}-configure
)
else()
+ get_configure_command_id(${name} cfg_cmd_id)
+
if(NOT cmd)
- set(cmd ${CMAKE_COMMAND})
+ set(cmd make)
+ if(cfg_cmd_id STREQUAL "cmake")
+ set(cmd ${CMAKE_COMMAND})
+ endif()
endif()
get_target_property(args ${name} AEP_BUILD_ARGS)
if(NOT args)
- set(args --build ${working_dir} --config ${CMAKE_CFG_INTDIR})
+ set(args)
+ if(cfg_cmd_id STREQUAL "cmake")
+ set(args --build ${working_dir} --config ${CMAKE_CFG_INTDIR})
+ endif()
endif()
add_custom_command(
@@ -312,13 +386,24 @@ function(add_external_project_install_command name)
DEPENDS ${sentinels_dir}/${name}-build
)
else()
+ get_configure_command_id(${name} cfg_cmd_id)
+
if(NOT cmd)
- set(cmd ${CMAKE_COMMAND})
+ set(cmd make)
+ if(cfg_cmd_id STREQUAL "cmake")
+ set(cmd ${CMAKE_COMMAND})
+ endif()
endif()
get_target_property(args ${name} AEP_INSTALL_ARGS)
if(NOT args)
- set(args --build ${working_dir} --config ${CMAKE_CFG_INTDIR} --target install)
+ set(args)
+ if(cfg_cmd_id STREQUAL "cmake")
+ set(args --build ${working_dir} --config ${CMAKE_CFG_INTDIR} --target install)
+ endif()
+ if(cfg_cmd_id STREQUAL "configure")
+ set(args "install")
+ endif()
endif()
add_custom_command(
@@ -339,123 +424,101 @@ function(add_CMakeExternals_target)
sentinels_dir source_dir tmp_dir)
add_custom_command(
- OUTPUT ${tmp_dir}
+ OUTPUT ${sentinels_dir}/CMakeExternals-directories
COMMAND ${CMAKE_COMMAND} -E make_directory ${build_dir}
COMMAND ${CMAKE_COMMAND} -E make_directory ${downloads_dir}
COMMAND ${CMAKE_COMMAND} -E make_directory ${install_dir}
COMMAND ${CMAKE_COMMAND} -E make_directory ${sentinels_dir}
COMMAND ${CMAKE_COMMAND} -E make_directory ${source_dir}
COMMAND ${CMAKE_COMMAND} -E make_directory ${tmp_dir}
+ COMMAND ${CMAKE_COMMAND} -E touch ${sentinels_dir}/CMakeExternals-directories
+ COMMENT "Creating CMakeExternals directories"
)
add_custom_target(CMakeExternals ALL
- DEPENDS ${tmp_dir}
+ DEPENDS ${sentinels_dir}/CMakeExternals-directories
)
endif()
endfunction(add_CMakeExternals_target)
+function(is_known_aep_property_key key result_var)
+ set(${result_var} 0 PARENT_SCOPE)
+
+ if(key MATCHES "^BUILD_ARGS|BUILD_COMMAND|CONFIGURE_ARGS|CONFIGURE_COMMAND|CONFIGURE_DIR|CVS_REPOSITORY|CVS_MODULE|CVS_TAG|DEPENDS|DOWNLOAD_ARGS|DOWNLOAD_COMMAND|DIR|INSTALL_ARGS|INSTALL_COMMAND|SVN_REPOSITORY|SVN_TAG|TAR|TAR_URL|TGZ|TGZ_URL$"
+ )
+ #message(STATUS "info: recognized via MATCHES - key='${key}'")
+ set(${result_var} 1 PARENT_SCOPE)
+ else()
+ message(STATUS "warning: is_known_aep_property_key unknown key='${key}'")
+ endif()
+endfunction(is_known_aep_property_key)
+
+
function(add_external_project name)
get_external_project_directories(base_dir build_dir downloads_dir install_dir
sentinels_dir source_dir tmp_dir)
+
+ # Ensure root CMakeExternals target and directories are created.
+ # All external projects will depend on this root CMakeExternals target.
+ #
add_CMakeExternals_target()
+
+ # Add a custom target for the external project and make its DEPENDS
+ # the output of the final build step:
+ #
add_custom_target(${name} ALL
DEPENDS ${sentinels_dir}/${name}-install
)
set_target_properties(${name} PROPERTIES AEP_IS_EXTERNAL_PROJECT 1)
+ add_dependencies(${name} CMakeExternals)
- # Loop over ARGN by 2's extracting key/value pairs from
- # the non-explicit arguments to the function:
+
+ # Transfer the arguments to this function into target properties for the
+ # new custom target we just added so that we can set up all the build steps
+ # correctly based on target properties.
+ #
+ # Loop over ARGN by 2's extracting key/value pairs from the non-explicit
+ # arguments to this function:
#
list(LENGTH ARGN n)
set(i 0)
while(i LESS n)
math(EXPR j ${i}+1)
+
list(GET ARGN ${i} key)
list(GET ARGN ${j} value)
- #message(STATUS " ${key}='${value}'")
-
- if(key STREQUAL "BUILD_ARGS")
- set_target_properties(${name} PROPERTIES AEP_BUILD_ARGS "${value}")
- endif()
-
- if(key STREQUAL "BUILD_COMMAND")
- set_target_properties(${name} PROPERTIES AEP_BUILD_COMMAND "${value}")
- endif()
-
- if(key STREQUAL "CONFIGURE_ARGS")
- set_target_properties(${name} PROPERTIES AEP_CONFIGURE_ARGS "${value}")
- endif()
-
- if(key STREQUAL "CONFIGURE_COMMAND")
- set_target_properties(${name} PROPERTIES AEP_CONFIGURE_COMMAND "${value}")
- endif()
-
- if(key STREQUAL "CONFIGURE_DIR")
- set_target_properties(${name} PROPERTIES AEP_CONFIGURE_DIR "${value}")
- endif()
-
- if(key STREQUAL "CVS_REPOSITORY")
- set_target_properties(${name} PROPERTIES AEP_CVS_REPOSITORY "${value}")
- endif()
-
- if(key STREQUAL "CVS_MODULE")
- set_target_properties(${name} PROPERTIES AEP_CVS_MODULE "${value}")
- endif()
-
- if(key STREQUAL "CVS_TAG")
- set_target_properties(${name} PROPERTIES AEP_CVS_TAG "${value}")
- endif()
-
- if(key STREQUAL "DEPENDS")
- add_dependencies(${name} ${value})
- endif()
-
- if(key STREQUAL "DIR")
- set_target_properties(${name} PROPERTIES AEP_DIR "${value}")
- endif()
- if(key STREQUAL "INSTALL_ARGS")
- set_target_properties(${name} PROPERTIES AEP_INSTALL_ARGS "${value}")
- endif()
-
- if(key STREQUAL "INSTALL_COMMAND")
- set_target_properties(${name} PROPERTIES AEP_INSTALL_COMMAND "${value}")
- endif()
-
- if(key STREQUAL "SVN_REPOSITORY")
- set_target_properties(${name} PROPERTIES AEP_SVN_REPOSITORY "${value}")
- endif()
-
- if(key STREQUAL "SVN_TAG")
- set_target_properties(${name} PROPERTIES AEP_SVN_TAG "${value}")
- endif()
-
- if(key STREQUAL "TAR")
- set_target_properties(${name} PROPERTIES AEP_TAR "${value}")
- endif()
-
- if(key STREQUAL "TAR_URL")
- set_target_properties(${name} PROPERTIES AEP_TAR_URL "${value}")
- endif()
-
- if(key STREQUAL "TGZ")
- set_target_properties(${name} PROPERTIES AEP_TGZ "${value}")
- endif()
-
- if(key STREQUAL "TGZ_URL")
- set_target_properties(${name} PROPERTIES AEP_TGZ_URL "${value}")
+ is_known_aep_property_key("${key}" is_known_key)
+
+ if(is_known_key)
+ if(key STREQUAL "DEPENDS")
+ if(NOT value STREQUAL "")
+ add_dependencies(${name} ${value})
+ else()
+ message(STATUS "warning: empty DEPENDS value in add_external_project")
+ endif()
+ else()
+ set_target_properties(${name} PROPERTIES AEP_${key} "${value}")
+ endif()
+ else()
+ message(SEND_ERROR "error: unknown add_external_project key with name='${name}' key='${key}' value='${value}'")
endif()
math(EXPR i ${i}+2)
endwhile()
+
+ # Set up custom build steps based on the target properties.
+ # Each step depends on the previous one.
+ #
+ # The target depends on the output of the final step.
+ # (Already set up above in the DEPENDS of the add_custom_target command.)
+ #
add_external_project_download_command(${name})
add_external_project_configure_command(${name})
add_external_project_build_command(${name})
add_external_project_install_command(${name})
-
- add_dependencies(${name} CMakeExternals)
endfunction(add_external_project)
diff --git a/Tests/ExternalProject/CMakeLists.txt b/Tests/ExternalProject/CMakeLists.txt
index c894037..00fffc9 100644
--- a/Tests/ExternalProject/CMakeLists.txt
+++ b/Tests/ExternalProject/CMakeLists.txt
@@ -16,23 +16,64 @@ set(prefix "${install_dir}")
#
include("${CMAKE_CURRENT_SOURCE_DIR}/TryCheckout.cmake")
-try_cvs_checkout(
- ":pserver:anonymous:cmake@www.cmake.org:/cvsroot/CMake"
- "CMake/Tests/Tutorial/Step1"
- "${CMAKE_CURRENT_BINARY_DIR}/TryCheckout/TutorialStep1"
- can_use_cvs
- )
+if(NOT DEFINED can_use_cvs)
+ try_cvs_checkout(
+ ":pserver:anonymous:cmake@www.cmake.org:/cvsroot/CMake"
+ "CMake/Tests/Tutorial/Step1"
+ "${CMAKE_CURRENT_BINARY_DIR}/TryCheckout/TutorialStep1"
+ can_use_cvs
+ )
+ set(can_use_cvs ${can_use_cvs} CACHE STRING "Was try_cvs_checkout successful?")
+endif()
-try_svn_checkout(
- "http://gdcm.svn.sourceforge.net/svnroot/gdcm/trunk/Utilities/gdcmmd5"
- "${CMAKE_CURRENT_BINARY_DIR}/TryCheckout/gdcmmd5"
- can_use_svn
- )
+if(NOT DEFINED can_use_svn)
+ try_svn_checkout(
+ "http://gdcm.svn.sourceforge.net/svnroot/gdcm/trunk/Utilities/gdcmmd5"
+ "${CMAKE_CURRENT_BINARY_DIR}/TryCheckout/gdcmmd5"
+ can_use_svn
+ )
+ set(can_use_svn ${can_use_svn} CACHE STRING "Was try_svn_checkout successful?")
+endif()
message(STATUS "can_use_cvs='${can_use_cvs}'")
message(STATUS "can_use_svn='${can_use_svn}'")
+# Empty projects that test all the known add_external_project argument key words:
+#
+set(proj MinimalNoOpProject)
+add_external_project(${proj}
+ BUILD_COMMAND ""
+ CONFIGURE_COMMAND ""
+ DOWNLOAD_COMMAND ""
+ INSTALL_COMMAND ""
+)
+
+set(proj EmptyNoOpProject)
+add_external_project(${proj}
+ BUILD_ARGS ""
+ BUILD_COMMAND ""
+ CONFIGURE_ARGS ""
+ CONFIGURE_COMMAND ""
+ CONFIGURE_DIR ""
+ CVS_REPOSITORY ""
+ CVS_MODULE ""
+ CVS_TAG ""
+ DEPENDS "MinimalNoOpProject"
+ DIR ""
+ DOWNLOAD_ARGS ""
+ DOWNLOAD_COMMAND ""
+ INSTALL_ARGS ""
+ INSTALL_COMMAND ""
+ SVN_REPOSITORY ""
+ SVN_TAG ""
+ TAR ""
+ TAR_URL ""
+ TGZ ""
+ TGZ_URL ""
+)
+
+
# Local DIR:
#
set(proj TutorialStep5-Local)
@@ -70,7 +111,7 @@ add_external_project(${proj}
set(proj TutorialStep1-LocalNoDirTGZ)
add_external_project(${proj}
- TGZ "${CMAKE_CURRENT_SOURCE_DIR}/Step1.tgz"
+ TGZ "${CMAKE_CURRENT_SOURCE_DIR}/Step1NoDir.tgz"
CONFIGURE_ARGS "\"-DCMAKE_INSTALL_PREFIX:PATH=${prefix}\" -G \"${CMAKE_GENERATOR}\" \"${source_dir}/${proj}\""
INSTALL_COMMAND ""
)
@@ -91,12 +132,13 @@ add_external_project(${proj}
if(can_use_cvs)
# CVS by date stamp:
#
- set(proj KWStyle-20081201)
+ set(proj TutorialStep1-20081201)
add_external_project(${proj}
- CVS_REPOSITORY ":pserver:anoncvs@public.kitware.com:/cvsroot/KWStyle"
- CVS_MODULE "KWStyle"
+ CVS_REPOSITORY ":pserver:anonymous:cmake@www.cmake.org:/cvsroot/CMake"
+ CVS_MODULE "CMake/Tests/Tutorial/Step1"
CVS_TAG "-D\;2008-12-01 01:00:00 UTC"
CONFIGURE_ARGS "\"-DCMAKE_INSTALL_PREFIX:PATH=${prefix}\" -G \"${CMAKE_GENERATOR}\" \"${source_dir}/${proj}\""
+ INSTALL_COMMAND ""
)
# CVS by tag:
@@ -112,12 +154,19 @@ if(can_use_cvs)
# Live CVS / HEAD (no CVS_TAG):
#
- set(proj TutorialStep1-CVSHEAD)
+ set(proj KWStyle-CVSHEAD)
add_external_project(${proj}
- CVS_REPOSITORY ":pserver:anonymous:cmake@www.cmake.org:/cvsroot/CMake"
- CVS_MODULE "CMake/Tests/Tutorial/Step1"
+ CVS_REPOSITORY ":pserver:anoncvs@public.kitware.com:/cvsroot/KWStyle"
+ CVS_MODULE "KWStyle"
CONFIGURE_ARGS "\"-DCMAKE_INSTALL_PREFIX:PATH=${prefix}\" -G \"${CMAKE_GENERATOR}\" \"${source_dir}/${proj}\""
- INSTALL_COMMAND ""
+ DEPENDS "EmptyNoOpProject"
+ DEPENDS "TutorialStep5-Local"
+ DEPENDS "TutorialStep1-LocalTAR"
+ DEPENDS "TutorialStep1-LocalNoDirTAR"
+ DEPENDS "TutorialStep1-LocalTGZ"
+ DEPENDS "TutorialStep1-LocalNoDirTGZ"
+ DEPENDS "TutorialStep1-20081201"
+ DEPENDS "kwsys-from-CMake-2-6-2"
)
endif()
@@ -162,7 +211,7 @@ enable_testing()
# Use these as input to the KWStyle tests:
#
-set(kwstyleXmlFile "${source_dir}/KWStyle-20081201/Testing/Data/0001-KWStyleConfiguration.kws.xml")
+set(kwstyleXmlFile "${source_dir}/KWStyle-CVSHEAD/Testing/Data/0001-KWStyleConfiguration.kws.xml")
set(header "${install_dir}/include/TutorialConfig.h")
@@ -187,14 +236,14 @@ add_test(TutorialStep1-LocalNoDirTGZ-BuildTreeTest
"${build_dir}/TutorialStep1-LocalNoDirTGZ/Tutorial" 9)
if(can_use_cvs)
- add_test(KWStyle-20081201-BuildTreeTest
- "${build_dir}/KWStyle-20081201/KWStyle" -xml "${kwstyleXmlFile}" "${header}")
+ add_test(TutorialStep1-20081201-BuildTreeTest
+ "${build_dir}/TutorialStep1-20081201/Tutorial" 4)
add_test(kwsys-from-CMake-2-6-2-BuildTreeTest
"${build_dir}/kwsys-from-CMake-2-6-2/kwsysTestProcess" 1)
- add_test(TutorialStep1-CVSHEAD-BuildTreeTest
- "${build_dir}/TutorialStep1-LocalNoDirTGZ/Tutorial" 4)
+ add_test(KWStyle-CVSHEAD-BuildTreeTest
+ "${build_dir}/KWStyle-CVSHEAD/KWStyle" -xml "${kwstyleXmlFile}" "${header}")
endif()
if(can_use_svn)