瀏覽代碼

Generalize how superbuild CMake variables can be passed to inner project.

This commit add the following set of convenience functions/macros:
  mark_as_superbuild
  superbuild_append_to_external_project_property
  _sb_append_to_cmake_args
  _sb_remove_duplicates_from_global_property
  _sb_get_global_property
  _sb_get_external_project_arguments

Also renames:
  "superbuild_cmakevar_to_cmakearg" into "_sb_cmakevar_to_cmakearg"
  "ctkMacroEmptyExternalProject" into "superbuild_add_empty_external_project"
  "ctkMacroCheckExternalProjectDependency" into "superbuild_include_dependencies"
  "__epd_first_pass" variable into "SUPERBUILD_FIRST_PASS"

For specific details about each function, consider reading the
inlined description and parameter documentation.

To update external project files living in your
fork of ExternalProjectsContrib, the ExternalProject migration guide
has been written to help you transition.

See http://www.commontk.org/index.php/Documentation/MigrationGuide/ExternalProject

See #418
Jean-Christophe Fillion-Robin 11 年之前
父節點
當前提交
dc70d038df

+ 1 - 2
CMake/LastConfigureStep/CTKGenerateCTKConfig.cmake

@@ -73,9 +73,8 @@ else()
 endif()
 
 # CTK external projects variables
-string(REPLACE "^" ";" CTK_SUPERBUILD_EP_VARNAMES "${CTK_SUPERBUILD_EP_VARNAMES}")
 set(CTK_SUPERBUILD_EP_VARS_CONFIG)
-foreach(varname ${CTK_SUPERBUILD_EP_VARNAMES})
+foreach(varname ${CTK_EP_LABEL_FIND_PACKAGE})
   set(CTK_SUPERBUILD_EP_VARS_CONFIG
    "${CTK_SUPERBUILD_EP_VARS_CONFIG}
 set(CTK_${varname} \"${${varname}}\")")

+ 28 - 1
CMake/Testing/CMakeLists.txt

@@ -10,8 +10,35 @@ macro(add_cmakescript_test testname script)
     PASS_REGULAR_EXPRESSION "SUCCESS")
 endmacro()
 
+set(CMAKE_TEST_GENERATOR "${CMAKE_GENERATOR}")
+set(CMAKE_TEST_GENERATOR_TOOLSET "${CMAKE_GENERATOR_TOOLSET}")
+set(CMAKE_TEST_MAKEPROGRAM "${CMAKE_MAKE_PROGRAM}")
+
+set(build_generator_args
+  --build-generator ${CMAKE_TEST_GENERATOR}
+  --build-makeprogram ${CMAKE_TEST_MAKEPROGRAM}
+  )
+if(CMAKE_TEST_GENERATOR_TOOLSET)
+  list(APPEND build_generator_args
+    --build-generator-toolset ${CMAKE_TEST_GENERATOR_TOOLSET}
+    )
+endif()
+
 #
 # Add 'CMake script' Tests
 #
 add_cmakescript_test(ctk_list_to_string_test ctkListToString)
-add_cmakescript_test(superbuild_cmakevar_to_cmakearg_test ctkMacroCheckExternalProjectDependencyTest)
+add_cmakescript_test(_sb_cmakevar_to_cmakearg_test ctkMacroCheckExternalProjectDependencyTest)
+add_cmakescript_test(_sb_extract_varname_and_vartype_test ctkMacroCheckExternalProjectDependencyTest)
+
+add_test(cmake_superbuild_test ${CMAKE_CTEST_COMMAND}
+    --build-and-test
+    "${CMAKE_SOURCE_DIR}/CMake/Testing/SuperBuildTest"
+    "${CMAKE_BINARY_DIR}/CMake/Testing/SuperBuildTest"
+    ${build_generator_args}
+    --build-project SuperBuildTest
+    --build-exe-dir "${CMAKE_BINARY_DIR}/CMake/Testing/SuperBuildTest"
+    --force-new-ctest-process
+    --test-command ${CMAKE_CTEST_COMMAND} -V
+    )
+set_tests_properties(cmake_superbuild_test PROPERTIES LABELS CMake)

+ 90 - 0
CMake/Testing/SuperBuildTest/CMakeLists.txt

@@ -0,0 +1,90 @@
+cmake_minimum_required(VERSION 2.8.7)
+
+set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/../../" ${CMAKE_MODULE_PATH})
+set(EXTERNAL_PROJECT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/TheExternals)
+set(EXTERNAL_PROJECT_FILE_PREFIX "TheExternal_")
+include(ExternalProject)
+include(ctkMacroCheckExternalProjectDependency)
+
+project(SuperBuildTest NONE)
+
+option(${PROJECT_NAME}_SUPERBUILD "Build ${PROJECT_NAME} and the projects it depends" ON)
+mark_as_advanced(${PROJECT_NAME}_SUPERBUILD)
+
+if(${PROJECT_NAME}_SUPERBUILD)
+  option(FOO_OPTION "Option mark_as_superbuild" ON)
+  mark_as_superbuild(FOO_OPTION)
+
+  set(FOO_VAR "FooVar")
+  mark_as_superbuild(FOO_VAR)
+
+  set(FOO_LIST Item1 Item2)
+  mark_as_superbuild(FOO_LIST)
+
+  set(FOO_LIST_FOR_CMAKE_CMD "Item1${EP_LIST_SEPARATOR}Item2")
+  mark_as_superbuild(FOO_LIST_FOR_CMAKE_CMD CMAKE_CMD)
+
+  set(FOO_VAR_WITH_LABELS "FooVarWithLabels")
+  mark_as_superbuild(VARS FOO_VAR_WITH_LABELS LABELS "LABEL_A" "LABEL_B")
+
+  set(BAR_VAR_WITH_LABELS "BarVarWithLabels")
+  mark_as_superbuild(VARS BAR_VAR_WITH_LABELS LABELS "LABEL_B")
+
+  set(LibA_VAR "LibA")
+  mark_as_superbuild(VARS LibA_VAR PROJECT LibA)
+
+  set(LibA_VAR_WITH_LABELS "LibAWithLabels")
+  mark_as_superbuild(VARS LibA_VAR_WITH_LABELS PROJECT LibA LABELS "LABEL_A")
+
+  # Since LibC depends on LibD, LibD will also be expected to be found on the system
+  set(${CMAKE_PROJECT_NAME}_USE_SYSTEM_LibC 1)
+endif()
+
+set(${PROJECT_NAME}_DEPENDENCIES LibA LibB LibC)
+
+superbuild_include_dependencies(${PROJECT_NAME})
+
+if(${PROJECT_NAME}_SUPERBUILD)
+  ExternalProject_Add(${PROJECT_NAME}
+    ${${PROJECT_NAME}_EXTERNAL_PROJECT_ARGS}
+    DOWNLOAD_COMMAND ""
+    CMAKE_CACHE_ARGS
+      -D${PROJECT_NAME}_SUPERBUILD:BOOL=OFF
+    SOURCE_DIR ${${PROJECT_NAME}_SOURCE_DIR}
+    BINARY_DIR ${${PROJECT_NAME}_BINARY_DIR}/${PROJECT_NAME}-build
+    BUILD_COMMAND ""
+    INSTALL_COMMAND ""
+    DEPENDS
+      ${${PROJECT_NAME}_DEPENDENCIES}
+    )
+  return()
+endif()
+
+function(check_variable var_name expected_value)
+  if(NOT "x${${var_name}}" STREQUAL "x${expected_value}")
+    message(FATAL_ERROR "Problem with mark_as_superbuild() - CMake variable [${var_name}] is incorrectly set !\n"
+                        "current:${${var_name}}\n"
+                        "expected:${expected_value}")
+  endif()
+endfunction()
+
+check_variable(FOO_OPTION "ON")
+check_variable(FOO_VAR "FooVar")
+check_variable(FOO_LIST "Item1;Item2")
+check_variable(FOO_LIST_FOR_CMAKE_CMD "Item1;Item2")
+check_variable(FOO_VAR_WITH_LABELS "FooVarWithLabels")
+check_variable(BAR_VAR_WITH_LABELS "BarVarWithLabels")
+
+check_variable(SuperBuildTest_EP_LABEL_LABEL_A "FOO_VAR_WITH_LABELS")
+check_variable(SuperBuildTest_EP_LABEL_LABEL_B "FOO_VAR_WITH_LABELS;BAR_VAR_WITH_LABELS")
+
+check_variable(SuperBuildTest_EP_LABEL_FIND_PACKAGE "LibA_DIR")
+get_filename_component(expected_LibA_DIR "${CMAKE_CURRENT_BINARY_DIR}/../LibA-build" REALPATH)
+check_variable(LibA_DIR ${expected_LibA_DIR})
+
+check_variable(SuperBuildTest_EP_LABEL_USE_SYSTEM
+  "${CMAKE_PROJECT_NAME}_USE_SYSTEM_LibA;${CMAKE_PROJECT_NAME}_USE_SYSTEM_LibB;${CMAKE_PROJECT_NAME}_USE_SYSTEM_LibC;${CMAKE_PROJECT_NAME}_USE_SYSTEM_LibD")
+check_variable(${CMAKE_PROJECT_NAME}_USE_SYSTEM_LibA "")
+check_variable(${CMAKE_PROJECT_NAME}_USE_SYSTEM_LibB "")
+check_variable(${CMAKE_PROJECT_NAME}_USE_SYSTEM_LibC 1)
+check_variable(${CMAKE_PROJECT_NAME}_USE_SYSTEM_LibD 1)

+ 15 - 0
CMake/Testing/SuperBuildTest/LibA/CMakeLists.txt

@@ -0,0 +1,15 @@
+cmake_minimum_required(VERSION 2.8.7)
+
+project(LibA NONE)
+
+function(check_variable var_name expected_value)
+  if(NOT "x${${var_name}}" STREQUAL "x${expected_value}")
+    message(FATAL_ERROR "Problem with mark_as_superbuild() - CMake variable [${var_name}] is incorrectly set !\n"
+                        "current:${${var_name}}\n"
+                        "expected:${expected_value}")
+  endif()
+endfunction()
+
+check_variable(LibA_VAR "LibA")
+
+check_variable(LibA_EP_LABEL_LABEL_A "LibA_VAR_WITH_LABELS")

+ 47 - 0
CMake/Testing/SuperBuildTest/TheExternals/TheExternal_LibA.cmake

@@ -0,0 +1,47 @@
+#
+# LibA
+#
+
+superbuild_include_once()
+
+set(LibA_DEPENDENCIES "")
+
+superbuild_include_dependencies(LibA)
+set(proj LibA)
+
+if(${CMAKE_PROJECT_NAME}_USE_SYSTEM_${proj})
+  message(FATAL_ERROR "Enabling ${CMAKE_PROJECT_NAME}_USE_SYSTEM_${proj} is not supported !")
+endif()
+
+mark_as_superbuild(
+  VARS ${CMAKE_PROJECT_NAME}_USE_SYSTEM_${proj}:BOOL
+  LABELS "USE_SYSTEM"
+  )
+
+# Sanity checks
+if(DEFINED LibA_DIR AND NOT EXISTS ${LibA_DIR})
+  message(FATAL_ERROR "LibA_DIR variable is defined but corresponds to non-existing directory")
+endif()
+
+if(NOT DEFINED LibA_DIR AND NOT ${CMAKE_PROJECT_NAME}_USE_SYSTEM_${proj})
+
+  ExternalProject_Add(${proj}
+    ${${proj}_EXTERNAL_PROJECT_ARGS}
+    SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/${proj}
+    BINARY_DIR ${proj}-build
+    DOWNLOAD_COMMAND ""
+    BUILD_COMMAND ""
+    INSTALL_COMMAND ""
+    DEPENDS
+      ${${proj}_DEPENDENCIES}
+    )
+  set(LibA_DIR ${CMAKE_BINARY_DIR}/${proj}-build)
+
+else()
+  superbuild_add_empty_external_project(${proj} "${${proj}_DEPENDENCIES}")
+endif()
+
+mark_as_superbuild(
+  VARS LibA_DIR:PATH
+  LABELS "FIND_PACKAGE"
+  )

+ 43 - 0
CMake/Testing/SuperBuildTest/TheExternals/TheExternal_LibB.cmake

@@ -0,0 +1,43 @@
+#
+# LibB
+#
+
+superbuild_include_once()
+
+set(LibB_DEPENDENCIES LibA)
+
+superbuild_include_dependencies(LibB)
+set(proj LibB)
+
+if(${CMAKE_PROJECT_NAME}_USE_SYSTEM_${proj})
+   message(FATAL_ERROR "Enabling ${CMAKE_PROJECT_NAME}_USE_SYSTEM_${proj} is not supported !")
+endif()
+
+mark_as_superbuild(
+  VARS ${CMAKE_PROJECT_NAME}_USE_SYSTEM_${proj}:BOOL
+  LABELS "USE_SYSTEM"
+  )
+
+# Sanity checks
+if(DEFINED LibB_DIR AND NOT EXISTS ${LibB_DIR})
+  message(FATAL_ERROR "LibB_DIR variable is defined but corresponds to non-existing directory")
+endif()
+
+if(NOT DEFINED LibB_DIR AND NOT ${CMAKE_PROJECT_NAME}_USE_SYSTEM_${proj})
+
+  ExternalProject_Add(${proj}
+    ${${proj}_EXTERNAL_PROJECT_ARGS}
+    BINARY_DIR ${proj}-build
+    DOWNLOAD_COMMAND ""
+    CONFIGURE_COMMAND ""
+    BUILD_COMMAND ""
+    INSTALL_COMMAND ""
+    DEPENDS
+      ${${proj}_DEPENDENCIES}
+    )
+  set(LibB_DIR ${CMAKE_BINARY_DIR}/${proj}-build)
+
+else()
+  superbuild_add_empty_external_project(${proj} "${${proj}_DEPENDENCIES}")
+endif()
+

+ 33 - 0
CMake/Testing/SuperBuildTest/TheExternals/TheExternal_LibC.cmake

@@ -0,0 +1,33 @@
+#
+# LibC
+#
+
+superbuild_include_once()
+
+set(LibC_DEPENDENCIES LibD)
+
+superbuild_include_dependencies(LibC)
+set(proj LibC)
+
+if(${CMAKE_PROJECT_NAME}_USE_SYSTEM_${proj})
+  unset(LibC_DIR CACHE)
+endif()
+
+mark_as_superbuild(
+  VARS ${CMAKE_PROJECT_NAME}_USE_SYSTEM_${proj}:BOOL
+  LABELS "USE_SYSTEM"
+  )
+
+# Sanity checks
+if(DEFINED LibC_DIR AND NOT EXISTS ${LibC_DIR})
+  message(FATAL_ERROR "LibC_DIR variable is defined but corresponds to non-existing directory")
+endif()
+
+if(NOT DEFINED LibC_DIR AND NOT ${CMAKE_PROJECT_NAME}_USE_SYSTEM_${proj})
+
+   message(FATAL_ERROR "Disabling ${CMAKE_PROJECT_NAME}_USE_SYSTEM_${proj} is not supported !")
+
+else()
+  superbuild_add_empty_external_project(${proj} "${${proj}_DEPENDENCIES}")
+endif()
+

+ 33 - 0
CMake/Testing/SuperBuildTest/TheExternals/TheExternal_LibD.cmake

@@ -0,0 +1,33 @@
+#
+# LibD
+#
+
+superbuild_include_once()
+
+set(LibD_DEPENDENCIES "")
+
+superbuild_include_dependencies(LibD)
+set(proj LibD)
+
+if(${CMAKE_PROJECT_NAME}_USE_SYSTEM_${proj})
+  unset(LibD_DIR CACHE)
+endif()
+
+mark_as_superbuild(
+  VARS ${CMAKE_PROJECT_NAME}_USE_SYSTEM_${proj}:BOOL
+  LABELS "USE_SYSTEM"
+  )
+
+# Sanity checks
+if(DEFINED LibD_DIR AND NOT EXISTS ${LibD_DIR})
+  message(FATAL_ERROR "LibD_DIR variable is defined but corresponds to non-existing directory")
+endif()
+
+if(NOT DEFINED LibD_DIR AND NOT ${CMAKE_PROJECT_NAME}_USE_SYSTEM_${proj})
+
+  message(FATAL_ERROR "Disabling ${CMAKE_PROJECT_NAME}_USE_SYSTEM_${proj} is not supported !")
+
+else()
+  superbuild_add_empty_external_project(${proj} "${${proj}_DEPENDENCIES}")
+endif()
+

+ 1 - 33
CMake/ctkBlockCheckDependencies.cmake

@@ -32,12 +32,6 @@ ctkMacroGetAllNonProjectTargetLibraries("${ALL_TARGET_LIBRARIES}" NON_CTK_DEPEND
 #
 
 if(CTK_SUPERBUILD)
-  include(ExternalProject)
-  include(ctkMacroEmptyExternalProject)
-
-  #set(ep_base "${CMAKE_BINARY_DIR}/CMakeExternals")
-  #set_property(DIRECTORY PROPERTY EP_BASE ${ep_base})
-
   set(ep_install_dir ${CMAKE_BINARY_DIR}/CMakeExternals/Install)
   set(ep_suffix      "-cmake")
 
@@ -54,45 +48,19 @@ if(CTK_SUPERBUILD)
       -DBUILD_TESTING:BOOL=OFF
      )
 
-  # Set CMake OSX variable to pass down the external projects
-  set(CMAKE_OSX_EXTERNAL_PROJECT_ARGS)
-  if(APPLE)
-    list(APPEND CMAKE_OSX_EXTERNAL_PROJECT_ARGS
-         -DCMAKE_OSX_ARCHITECTURES:STRING=${CMAKE_OSX_ARCHITECTURES}
-         -DCMAKE_OSX_SYSROOT:STRING=${CMAKE_OSX_SYSROOT}
-         -DCMAKE_OSX_DEPLOYMENT_TARGET:STRING=${CMAKE_OSX_DEPLOYMENT_TARGET}
-        )
-    list(APPEND ep_common_cache_args ${CMAKE_OSX_EXTERNAL_PROJECT_ARGS})
-  endif()
-
   # Compute -G arg for configuring external projects with the same CMake generator:
   if(CMAKE_EXTRA_GENERATOR)
     set(gen "${CMAKE_EXTRA_GENERATOR} - ${CMAKE_GENERATOR}")
   else()
     set(gen "${CMAKE_GENERATOR}")
   endif()
-
-  # Use this value where semi-colons are needed in ep_add args:
-  set(sep "^^")
-
-  # This variable will contain the list of CMake variable specific to each external project
-  # that should passed to CTK.
-  # The item of this list should have the following form: <EP_VAR>:<TYPE>
-  # where '<EP_VAR>' is an external project variable and TYPE is either BOOL, PATH or FILEPATH.
-  # Variable appended to this list will be automatically exported in CTKConfig.cmake, prefix 'CTK_'
-  # will be prepended if it applied.
-  set(CTK_SUPERBUILD_EP_VARS)
 endif()
 
 if(NOT DEFINED CTK_DEPENDENCIES)
   message(FATAL_ERROR "error: CTK_DEPENDENCIES variable is not defined !")
 endif()
 
-set(EXTERNAL_PROJECT_DIR ${${CMAKE_PROJECT_NAME}_SOURCE_DIR}/CMakeExternals)
-set(EXTERNAL_PROJECT_FILE_PREFIX "")
-include(ctkMacroCheckExternalProjectDependency)
-
-ctkMacroCheckExternalProjectDependency(CTK)
+superbuild_include_dependencies(CTK)
 
 #message("Updated CTK_DEPENDENCIES:")
 #foreach(dep ${CTK_DEPENDENCIES})

+ 1 - 1
CMake/ctkMacroAddCtkLibraryOptions.cmake

@@ -35,7 +35,7 @@ macro(ctkMacroAddCtkLibraryOptions lib)
       ctkFunctionExtractOptionNameAndValue(${option} option_name option_value)
       option(CTK_LIB_${lib}_${option_name} "Enable ${lib} Library ${option_name} option." ${option_value})
       mark_as_advanced(CTK_LIB_${lib}_${option_name})
-      list(APPEND ctk_lib_options_list CTK_LIB_${lib}_${option_name})
+      mark_as_superbuild(CTK_LIB_${lib}_${option_name})
     endforeach()
     
   endif()

+ 239 - 19
CMake/ctkMacroCheckExternalProjectDependency.cmake

@@ -18,6 +18,12 @@
 #
 ###########################################################################
 
+include(CMakeParseArguments)
+include(ctkListToString)
+
+# Use this value where semi-colons are needed in ep_add args:
+set(sep "^^")
+
 if(NOT EXISTS "${EXTERNAL_PROJECT_DIR}")
   set(EXTERNAL_PROJECT_DIR ${${CMAKE_PROJECT_NAME}_SOURCE_DIR}/SuperBuild)
 endif()
@@ -50,7 +56,92 @@ macro(superbuild_include_once)
 endmacro()
 
 #!
-#! superbuild_cmakevar_to_cmakearg(<cmake_varname_and_type> <cmake_arg_var> <cmake_arg_type> [<varname_var> [<vartype_var>]])
+#! mark_as_superbuild(<varname1>[:<vartype1>] [<varname2>[:<vartype2>] [...]])
+#!
+#! mark_as_superbuild(
+#!     VARS <varname1>[:<vartype1>] [<varname2>[:<vartype2>] [...]]
+#!     [PROJECT <projectname>]
+#!     [LABELS <label1> [<label2> [...]]]
+#!     [CMAKE_CMD]
+#!   )
+#!
+#! PROJECT corresponds to a <projectname> that will be added using 'ExternalProject_Add' function.
+#!         If not specified and called within a project file, it defaults to the value of 'SUPERBUILD_TOPLEVEL_PROJECT'
+#!         Otherwise, it defaults to 'CMAKE_PROJECT_NAME'.
+#!
+#! VARS is an expected list of variables specified as <varname>:<vartype> to pass to <projectname>
+#!
+#!
+#! LABELS is an optional list of label to associate with the variable names specified using 'VARS' and passed to
+#!        the <projectname> as CMake CACHE args of the form:
+#!          -D<projectname>_EP_LABEL_<label1>=<varname1>;<varname2>[...]
+#!          -D<projectname>_EP_LABEL_<label2>=<varname1>;<varname2>[...]
+#!
+function(mark_as_superbuild)
+  set(options CMAKE_CMD)
+  set(oneValueArgs PROJECT)
+  set(multiValueArgs VARS LABELS)
+  cmake_parse_arguments(_sb "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
+
+  set(_vars ${_sb_UNPARSED_ARGUMENTS})
+
+  set(_named_parameters_expected 0)
+  if(_sb_PROJECT OR _sb_LABELS OR _sb_VARS)
+    set(_named_parameters_expected 1)
+    set(_vars ${_sb_VARS})
+  endif()
+
+  if(_named_parameters_expected AND _sb_UNPARSED_ARGUMENTS)
+    message(FATAL_ERROR "Arguments '${_sb_UNPARSED_ARGUMENTS}' should be associated with VARS parameter !")
+  endif()
+
+  foreach(var ${_vars})
+    set(_type_specified 0)
+    if(${var} MATCHES ":")
+      set(_type_specified 1)
+    endif()
+    # XXX Display warning with variable type is also specified for cache variable.
+    set(_var ${var})
+    if(NOT _type_specified)
+      get_property(_type_set_in_cache CACHE ${_var} PROPERTY TYPE SET)
+      set(_var_name ${_var})
+      set(_var_type "STRING")
+      if(_type_set_in_cache)
+        get_property(_var_type CACHE ${_var_name} PROPERTY TYPE)
+      endif()
+      set(_var ${_var_name}:${_var_type})
+    endif()
+    list(APPEND _vars_with_type ${_var})
+  endforeach()
+
+  if(_sb_CMAKE_CMD)
+    set(optional_arg_CMAKE_CMD "CMAKE_CMD")
+  endif()
+
+  _sb_append_to_cmake_args(VARS ${_vars_with_type} PROJECT ${_sb_PROJECT} LABELS ${_sb_LABELS} ${optional_arg_CMAKE_CMD})
+endfunction()
+
+#!
+#! _sb_extract_varname_and_vartype(<cmake_varname_and_type> <varname_var> [<vartype_var>])
+#!
+#! <cmake_varname_and_type> corresponds to variable name and variable type passed as "<varname>:<vartype>"
+#!
+#! <varname_var> will be set to "<varname>"
+#!
+#! <vartype_var> is an optional variable name that will be set to "<vartype>"
+function(_sb_extract_varname_and_vartype cmake_varname_and_type varname_var)
+  set(_vartype_var ${ARGV2})
+  string(REPLACE ":" ";" varname_and_vartype ${cmake_varname_and_type})
+  list(GET varname_and_vartype 0 _varname)
+  list(GET varname_and_vartype 1 _vartype)
+  set(${varname_var} ${_varname} PARENT_SCOPE)
+  if(_vartype_var MATCHES ".+")
+    set(${_vartype_var} ${_vartype} PARENT_SCOPE)
+  endif()
+endfunction()
+
+#!
+#! _sb_cmakevar_to_cmakearg(<cmake_varname_and_type> <cmake_arg_var> <cmake_arg_type> [<varname_var> [<vartype_var>]])
 #!
 #! <cmake_varname_and_type> corresponds to variable name and variable type passed as "<varname>:<vartype>"
 #!
@@ -65,20 +156,20 @@ endmacro()
 #! <varname_var> is an optional variable name that will be set to "<varname>"
 #!
 #! <vartype_var> is an optional variable name that will be set to "<vartype>"
-function(superbuild_cmakevar_to_cmakearg cmake_varname_and_type cmake_arg_var cmake_arg_type)
+function(_sb_cmakevar_to_cmakearg cmake_varname_and_type cmake_arg_var cmake_arg_type)
   set(_varname_var ${ARGV3})
   set(_vartype_var ${ARGV4})
-  string(REPLACE ":" ";" varname_and_vartype ${cmake_varname_and_type})
-  list(GET varname_and_vartype 0 _varname)
-  list(GET varname_and_vartype 1 _vartype)
+
+  # XXX Add check for <cmake_arg_type> value
+
+  _sb_extract_varname_and_vartype(${cmake_varname_and_type} _varname _vartype)
+
   set(_var_value "${${_varname}}")
   get_property(_value_set_in_cache CACHE ${_varname} PROPERTY VALUE SET)
   if(_value_set_in_cache)
     get_property(_var_value CACHE ${_varname} PROPERTY VALUE)
   endif()
 
-  # XXX Add check for <cmake_arg_type> value
-
   if(cmake_arg_type STREQUAL "CMAKE_CMD")
     # Separate list item with <sep>
     set(ep_arg_as_string "")
@@ -95,13 +186,119 @@ function(superbuild_cmakevar_to_cmakearg cmake_varname_and_type cmake_arg_var cm
   endif()
 endfunction()
 
+#!
+#! _sb_append_to_cmake_args(
+#!     VARS <varname1>:<vartype1> [<varname2>:<vartype2> [...]]
+#!     [PROJECT <projectname>]
+#!     [LABELS <label1> [<label2> [...]]]
+#!     [CMAKE_CMD]
+#!   )
+#!
+#! PROJECT corresponds to a <projectname> that will be added using 'ExternalProject_Add' function.
+#!         If not specified and called within a project file, it defaults to the value of 'SUPERBUILD_TOPLEVEL_PROJECT'
+#!         Otherwise, it defaults to 'CMAKE_PROJECT_NAME'.
+#!
+#! VARS is an expected list of variables specified as <varname>:<vartype> to pass to <projectname>
+#!
+#!
+#! LABELS is an optional list of label to associate with the variable names specified using 'VARS' and passed to
+#!        the <projectname> as CMake CACHE args of the form:
+#!          -D<projectname>_EP_LABEL_<label1>=<varname1>;<varname2>[...]
+#!          -D<projectname>_EP_LABEL_<label2>=<varname1>;<varname2>[...]
+#!
+function(_sb_append_to_cmake_args)
+  set(options CMAKE_CMD)
+  set(oneValueArgs PROJECT)
+  set(multiValueArgs VARS LABELS)
+  cmake_parse_arguments(_sb "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
+
+  if(NOT _sb_PROJECT)
+    if(SUPERBUILD_TOPLEVEL_PROJECT)
+      set(_sb_PROJECT ${SUPERBUILD_TOPLEVEL_PROJECT})
+    else()
+      set(_sb_PROJECT ${CMAKE_PROJECT_NAME})
+    endif()
+  endif()
+
+  set(_cmake_arg_type "CMAKE_CACHE")
+  if(_sb_CMAKE_CMD)
+    set(_cmake_arg_type "CMAKE")
+    set(optional_arg_CMAKE_CMD "CMAKE_CMD")
+  endif()
+  set(_ep_property "${_cmake_arg_type}_ARGS")
+  set(_ep_varnames "")
+  foreach(varname_and_vartype ${_sb_VARS})
+    if(NOT TARGET ${_sb_PROJECT})
+      set_property(GLOBAL APPEND PROPERTY ${_sb_PROJECT}_EP_${_ep_property} ${varname_and_vartype})
+      _sb_extract_varname_and_vartype(${varname_and_vartype} _varname)
+      set_property(GLOBAL APPEND PROPERTY ${_sb_PROJECT}_EP_PROPERTIES ${_ep_property})
+    else()
+      message(FATAL_ERROR "Function _sb_append_to_cmake_args not allowed is project already added !")
+    endif()
+    list(APPEND _ep_varnames ${_varname})
+  endforeach()
+
+  if(_sb_LABELS)
+    set_property(GLOBAL APPEND PROPERTY ${_sb_PROJECT}_EP_LABELS ${_sb_LABELS})
+    foreach(label ${_sb_LABELS})
+      set_property(GLOBAL APPEND PROPERTY ${_sb_PROJECT}_EP_LABEL_${label} ${_ep_varnames})
+    endforeach()
+  endif()
+endfunction()
+
+function(_sb_get_external_project_arguments proj varname)
+
+  mark_as_superbuild(${SUPERBUILD_TOPLEVEL_PROJECT}_USE_SYSTEM_${proj}:BOOL)
+
+  # Set list of CMake args associated with each label
+  get_property(_labels GLOBAL PROPERTY ${proj}_EP_LABELS)
+  if(_labels)
+    list(REMOVE_DUPLICATES _labels)
+    foreach(label ${_labels})
+      get_property(${proj}_EP_LABEL_${label} GLOBAL PROPERTY ${proj}_EP_LABEL_${label})
+      list(REMOVE_DUPLICATES ${proj}_EP_LABEL_${label})
+      _sb_append_to_cmake_args(PROJECT ${proj}
+        VARS ${proj}_EP_LABEL_${label}:STRING)
+    endforeach()
+  endif()
+
+  foreach(cmake_arg_type CMAKE_CMD CMAKE_CACHE)
+
+    set(_ep_property "CMAKE_CACHE_ARGS")
+    if(cmake_arg_type STREQUAL "CMAKE_CMD")
+      set(_ep_property "CMAKE_ARGS")
+    endif()
+
+    get_property(_args GLOBAL PROPERTY ${proj}_EP_${_ep_property})
+    foreach(var ${_args})
+      _sb_cmakevar_to_cmakearg(${var} cmake_arg ${cmake_arg_type})
+      set_property(GLOBAL APPEND PROPERTY ${proj}_EP_PROPERTY_${_ep_property} ${cmake_arg})
+    endforeach()
+
+  endforeach()
+
+  set(_ep_arguments "")
+  get_property(_properties GLOBAL PROPERTY ${proj}_EP_PROPERTIES)
+  if(_properties)
+    list(REMOVE_DUPLICATES _properties)
+    foreach(property ${_properties})
+      get_property(${proj}_EP_PROPERTY_${property} GLOBAL PROPERTY ${proj}_EP_PROPERTY_${property})
+      list(APPEND _ep_arguments ${property} ${${proj}_EP_PROPERTY_${property}})
+    endforeach()
+  endif()
+
+  set(${varname} ${_ep_arguments} PARENT_SCOPE)
+endfunction()
+
 macro(_epd_status txt)
-  if(NOT __epd_first_pass)
+  if(NOT SUPERBUILD_FIRST_PASS)
     message(STATUS ${txt})
   endif()
 endmacro()
 
-macro(ctkMacroCheckExternalProjectDependency proj)
+#
+# superbuild_include_dependencies(<project>)
+macro(superbuild_include_dependencies proj)
 
   # Set indent variable if needed
   if(NOT DEFINED __indent)
@@ -123,9 +320,9 @@ macro(ctkMacroCheckExternalProjectDependency proj)
   list(APPEND __epd_${SUPERBUILD_TOPLEVEL_PROJECT}_projects ${proj})
 
   # Is this the first run ? (used to set the <SUPERBUILD_TOPLEVEL_PROJECT>_USE_SYSTEM_* variables)
-  if(${proj} STREQUAL ${SUPERBUILD_TOPLEVEL_PROJECT} AND NOT DEFINED __epd_first_pass)
+  if(${proj} STREQUAL ${SUPERBUILD_TOPLEVEL_PROJECT} AND NOT DEFINED SUPERBUILD_FIRST_PASS)
     message(STATUS "SuperBuild - First pass")
-    set(__epd_first_pass TRUE)
+    set(SUPERBUILD_FIRST_PASS TRUE)
   endif()
 
   # Set message strings
@@ -155,7 +352,7 @@ macro(ctkMacroCheckExternalProjectDependency proj)
     if(${${SUPERBUILD_TOPLEVEL_PROJECT}_USE_SYSTEM_${proj}})
       set(${SUPERBUILD_TOPLEVEL_PROJECT}_USE_SYSTEM_${dep} ${${SUPERBUILD_TOPLEVEL_PROJECT}_USE_SYSTEM_${proj}})
     endif()
-    #if(__epd_first_pass)
+    #if(SUPERBUILD_FIRST_PASS)
     #  message("${SUPERBUILD_TOPLEVEL_PROJECT}_USE_SYSTEM_${dep} set to [${SUPERBUILD_TOPLEVEL_PROJECT}_USE_SYSTEM_${proj}:${${SUPERBUILD_TOPLEVEL_PROJECT}_USE_SYSTEM_${proj}}]")
     #endif()
   endforeach()
@@ -189,15 +386,14 @@ macro(ctkMacroCheckExternalProjectDependency proj)
     string(SUBSTRING "${__indent}" 0 ${__indent_length} __indent)
   endif()
 
-  if(${proj} STREQUAL ${SUPERBUILD_TOPLEVEL_PROJECT} AND __epd_first_pass)
+  if(${proj} STREQUAL ${SUPERBUILD_TOPLEVEL_PROJECT} AND SUPERBUILD_FIRST_PASS)
     message(STATUS "SuperBuild - First pass - done")
     unset(__indent)
-    if(${SUPERBUILD_TOPLEVEL_PROJECT}_SUPERBUILD)
-      set(__epd_first_pass FALSE)
-    endif()
 
     unset(${SUPERBUILD_TOPLEVEL_PROJECT}_DEPENDENCIES) # XXX - Refactor
 
+    set(SUPERBUILD_FIRST_PASS FALSE)
+
     foreach(possible_proj ${__epd_${SUPERBUILD_TOPLEVEL_PROJECT}_projects})
       if(NOT ${possible_proj} STREQUAL ${SUPERBUILD_TOPLEVEL_PROJECT})
 
@@ -235,13 +431,37 @@ macro(ctkMacroCheckExternalProjectDependency proj)
     list(REMOVE_DUPLICATES ${SUPERBUILD_TOPLEVEL_PROJECT}_DEPENDENCIES)
 
     if(${SUPERBUILD_TOPLEVEL_PROJECT}_SUPERBUILD)
-
-      ctkMacroCheckExternalProjectDependency(${SUPERBUILD_TOPLEVEL_PROJECT})
+      superbuild_include_dependencies(${SUPERBUILD_TOPLEVEL_PROJECT})
     endif()
 
+    set(SUPERBUILD_FIRST_PASS TRUE)
   endif()
 
-  if(__epd_first_pass)
+  if(SUPERBUILD_FIRST_PASS)
     return()
+  else()
+    unset(${proj}_EXTERNAL_PROJECT_ARGS)
+    _sb_get_external_project_arguments(${proj} ${proj}_EXTERNAL_PROJECT_ARGS)
+    #message("${proj}_EXTERNAL_PROJECT_ARGS:${${proj}_EXTERNAL_PROJECT_ARGS}")
   endif()
 endmacro()
+
+#!
+#! Convenient macro allowing to define a "empty" project in case an external one is provided
+#! using for example <proj>_DIR.
+#! Doing so allows to keep the external project dependency system happy.
+#!
+#! \ingroup CMakeUtilities
+macro(superbuild_add_empty_external_project proj dependencies)
+
+  ExternalProject_Add(${proj}
+    SOURCE_DIR ${CMAKE_BINARY_DIR}/${proj}
+    BINARY_DIR ${proj}-build
+    DOWNLOAD_COMMAND ""
+    CONFIGURE_COMMAND ""
+    BUILD_COMMAND ""
+    INSTALL_COMMAND ""
+    DEPENDS
+      ${dependencies}
+    )
+endmacro()

+ 55 - 11
CMake/ctkMacroCheckExternalProjectDependencyTest.cmake

@@ -3,24 +3,24 @@ set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR} ${CMAKE_MODULE_PATH})
 include(ctkMacroCheckExternalProjectDependency)
 
 #
-# cmake -DTEST_superbuild_cmakevar_to_cmakearg_test:BOOL=ON -P ctkMacroCheckExternalProjectDependencyTest.cmake
+# cmake -DTEST__sb_cmakevar_to_cmakearg_test:BOOL=ON -P ctkMacroCheckExternalProjectDependencyTest.cmake
 #
-function(superbuild_cmakevar_to_cmakearg_test)
+function(_sb_cmakevar_to_cmakearg_test)
   function(check_test_result id current_output expected_output
       current_varname expected_varname
       current_vartype expected_vartype)
     if(NOT "${current_output}" STREQUAL "${expected_output}")
-      message(FATAL_ERROR "Problem with superbuild_cmakevar_to_cmakearg() - See testcase: ${id}\n"
+      message(FATAL_ERROR "Problem with _sb_cmakevar_to_cmakearg() - See testcase: ${id}\n"
                           "current_output:${current_output}\n"
                           "expected_output:${expected_output}")
     endif()
     if(NOT "${current_varname}" STREQUAL "${expected_varname}")
-      message(FATAL_ERROR "Problem with superbuild_cmakevar_to_cmakearg() - See testcase: ${id}\n"
+      message(FATAL_ERROR "Problem with _sb_cmakevar_to_cmakearg() - See testcase: ${id}\n"
                           "current_varname:${current_varname}\n"
                           "expected_varname:${expected_varname}")
     endif()
     if(NOT "${current_vartype}" STREQUAL "${expected_vartype}")
-      message(FATAL_ERROR "Problem with superbuild_cmakevar_to_cmakearg() - See testcase: ${id}\n"
+      message(FATAL_ERROR "Problem with _sb_cmakevar_to_cmakearg() - See testcase: ${id}\n"
                           "current_vartype:${current_vartype}\n"
                           "expected_vartype:${expected_vartype}")
     endif()
@@ -31,7 +31,7 @@ function(superbuild_cmakevar_to_cmakearg_test)
   set(case${id}_expected_varname "")
   set(case${id}_expected_vartype "")
   set(case${id}_expected_cmake_arg_var "-Dcase${id}_input:STRING=${case${id}_input}")
-  superbuild_cmakevar_to_cmakearg("case${id}_input:STRING"
+  _sb_cmakevar_to_cmakearg("case${id}_input:STRING"
       case${id}_cmake_arg_var CMAKE_CACHE
       )
   check_test_result(${id}
@@ -44,7 +44,7 @@ function(superbuild_cmakevar_to_cmakearg_test)
   set(case${id}_expected_varname "case${id}_input")
   set(case${id}_expected_vartype "STRING")
   set(case${id}_expected_cmake_arg_var "-Dcase${id}_input:STRING=${case${id}_input}")
-  superbuild_cmakevar_to_cmakearg("case${id}_input:STRING"
+  _sb_cmakevar_to_cmakearg("case${id}_input:STRING"
       case${id}_cmake_arg_var CMAKE_CACHE
       case${id}_varname case${id}_vartype)
   check_test_result(${id}
@@ -57,7 +57,7 @@ function(superbuild_cmakevar_to_cmakearg_test)
   set(case${id}_expected_varname "case${id}_input")
   set(case${id}_expected_vartype "STRING")
   set(case${id}_expected_cmake_arg_var "-Dcase${id}_input:STRING=${case${id}_input}")
-  superbuild_cmakevar_to_cmakearg("case${id}_input:STRING"
+  _sb_cmakevar_to_cmakearg("case${id}_input:STRING"
       case${id}_cmake_arg_var CMAKE_CACHE
       case${id}_varname case${id}_vartype)
   check_test_result(${id}
@@ -70,7 +70,7 @@ function(superbuild_cmakevar_to_cmakearg_test)
   set(case${id}_expected_varname "case${id}_input")
   set(case${id}_expected_vartype "STRING")
   set(case${id}_expected_cmake_arg_var "-Dcase${id}_input:STRING=Hello^^World")
-  superbuild_cmakevar_to_cmakearg("case${id}_input:STRING"
+  _sb_cmakevar_to_cmakearg("case${id}_input:STRING"
       case${id}_cmake_arg_var CMAKE_CMD
       case${id}_varname case${id}_vartype)
   check_test_result(${id}
@@ -80,6 +80,50 @@ function(superbuild_cmakevar_to_cmakearg_test)
 
   message("SUCCESS")
 endfunction()
-if(TEST_superbuild_cmakevar_to_cmakearg_test)
-  superbuild_cmakevar_to_cmakearg_test()
+if(TEST__sb_cmakevar_to_cmakearg_test)
+  _sb_cmakevar_to_cmakearg_test()
+endif()
+
+#
+# cmake -DTEST__sb_extract_varname_and_vartype_test:BOOL=ON -P ctkMacroCheckExternalProjectDependencyTest.cmake
+#
+function(_sb_extract_varname_and_vartype_test)
+  function(check_test_result id current_varname expected_varname
+      current_vartype expected_vartype)
+    if(NOT "${current_varname}" STREQUAL "${expected_varname}")
+      message(FATAL_ERROR "Problem with _sb_extract_varname_and_vartype() - See testcase: ${id}\n"
+                          "current_varname:${current_varname}\n"
+                          "expected_varname:${expected_varname}")
+    endif()
+    if(NOT "${current_vartype}" STREQUAL "${expected_vartype}")
+      message(FATAL_ERROR "Problem with _sb_extract_varname_and_vartype() - See testcase: ${id}\n"
+                          "current_vartype:${current_vartype}\n"
+                          "expected_vartype:${expected_vartype}")
+    endif()
+  endfunction()
+
+  set(id 1)
+  set(case${id}_input "VAR:STRING")
+  set(case${id}_expected_varname "VAR")
+  set(case${id}_expected_vartype "STRING")
+  _sb_extract_varname_and_vartype("${case${id}_input}"
+      case${id}_varname case${id}_vartype)
+  check_test_result(${id}
+      "${case${id}_varname}" "${case${id}_expected_varname}"
+      "${case${id}_vartype}" "${case${id}_expected_vartype}")
+
+  set(id 2)
+  set(case${id}_input "VAR:STRING")
+  set(case${id}_expected_varname "VAR")
+  set(case${id}_expected_vartype "")
+  _sb_extract_varname_and_vartype("${case${id}_input}"
+      case${id}_varname)
+  check_test_result(${id}
+      "${case${id}_varname}" "${case${id}_expected_varname}"
+      "${case${id}_vartype}" "${case${id}_expected_vartype}")
+
+  message("SUCCESS")
+endfunction()
+if(TEST__sb_extract_varname_and_vartype_test)
+  _sb_extract_varname_and_vartype_test()
 endif()

+ 0 - 39
CMake/ctkMacroEmptyExternalProject.cmake

@@ -1,39 +0,0 @@
-###########################################################################
-#
-#  Library:   CTK
-#
-#  Copyright (c) Kitware Inc.
-#
-#  Licensed under the Apache License, Version 2.0 (the "License");
-#  you may not use this file except in compliance with the License.
-#  You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0.txt
-#
-#  Unless required by applicable law or agreed to in writing, software
-#  distributed under the License is distributed on an "AS IS" BASIS,
-#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-#  See the License for the specific language governing permissions and
-#  limitations under the License.
-#
-###########################################################################
-
-#!
-#! Convenient macro allowing to define a "empty" project in case an external one is provided
-#! using for example <proj>_DIR.
-#! Doing so allows to keep the external project dependency system happy.
-#!
-#! \ingroup CMakeUtilities
-macro(ctkMacroEmptyExternalProject proj dependencies)
-
-  ExternalProject_Add(${proj}
-    SOURCE_DIR ${CMAKE_BINARY_DIR}/${proj}
-    BINARY_DIR ${proj}-build
-    DOWNLOAD_COMMAND ""
-    CONFIGURE_COMMAND ""
-    BUILD_COMMAND ""
-    INSTALL_COMMAND ""
-    DEPENDS 
-      ${dependencies}
-    )
-endmacro()

+ 1 - 0
CMake/ctkMacroOptionUtils.cmake

@@ -18,6 +18,7 @@ endfunction()
 macro(ctk_option option_prefix name doc default)
   option(${option_prefix}_${name} ${doc} ${default})
   mark_as_advanced(${option_prefix}_${name})
+  mark_as_superbuild(${option_prefix}_${name})
   list(APPEND ${option_prefix}S ${name})
   set(_logical_expr ${ARGN})
   if(_logical_expr AND NOT ${option_prefix}_${name})

+ 2 - 0
CMake/ctkMacroSetupQt.cmake

@@ -46,6 +46,8 @@ macro(ctkMacroSetupQt)
       get_filename_component(QT_INSTALLED_LIBRARY_DIR ${QT_QMAKE_EXECUTABLE} PATH)
     endif()
 
+    mark_as_superbuild(QT_QMAKE_EXECUTABLE)
+
   else()
     message(FATAL_ERROR "error: Qt4 was not found on your system. You probably need to set the QT_QMAKE_EXECUTABLE variable")
   endif()

+ 7 - 3
CMakeExternals/CTKData.cmake

@@ -6,7 +6,7 @@ superbuild_include_once()
 
 set(CTKData_DEPENDENCIES "")
 
-ctkMacroCheckExternalProjectDependency(CTKData)
+superbuild_include_dependencies(CTKData)
 set(proj CTKData)
 
 if(${CMAKE_PROJECT_NAME}_USE_SYSTEM_${proj})
@@ -37,6 +37,7 @@ if(NOT DEFINED CTKData_DIR)
   endif()
 
   ExternalProject_Add(${proj}
+    ${${proj}_EXTERNAL_PROJECT_ARGS}
     SOURCE_DIR ${CMAKE_BINARY_DIR}/${proj}
     BINARY_DIR ${proj}-build
     PREFIX ${proj}${ep_suffix}
@@ -51,7 +52,10 @@ if(NOT DEFINED CTKData_DIR)
     )
   set(CTKData_DIR ${CMAKE_BINARY_DIR}/${proj})
 else()
-  ctkMacroEmptyExternalproject(${proj} "${${proj}_DEPENDENCIES}")
+  superbuild_add_empty_external_project(${proj} "${${proj}_DEPENDENCIES}")
 endif()
 
-list(APPEND CTK_SUPERBUILD_EP_VARS CTKData_DIR:PATH)
+mark_as_superbuild(
+  VARS CTKData_DIR:PATH
+  LABELS "FIND_PACKAGE"
+  )

+ 6 - 4
CMakeExternals/DCMTK.cmake

@@ -10,7 +10,7 @@ set(${DCMTK_enabling_variable}_FIND_PACKAGE_CMD DCMTK)
 
 set(DCMTK_DEPENDENCIES "")
 
-ctkMacroCheckExternalProjectDependency(DCMTK)
+superbuild_include_dependencies(DCMTK)
 set(proj DCMTK)
 
 if(${CMAKE_PROJECT_NAME}_USE_SYSTEM_${proj})
@@ -47,6 +47,7 @@ if(NOT DEFINED DCMTK_DIR AND NOT ${CMAKE_PROJECT_NAME}_USE_SYSTEM_${proj})
   endif()
 
   ExternalProject_Add(${proj}
+    ${${proj}_EXTERNAL_PROJECT_ARGS}
     SOURCE_DIR ${CMAKE_BINARY_DIR}/${proj}
     BINARY_DIR ${proj}-build
     PREFIX ${proj}${ep_suffix}
@@ -93,10 +94,11 @@ if(NOT DEFINED DCMTK_DIR AND NOT ${CMAKE_PROJECT_NAME}_USE_SYSTEM_${proj})
   # library output directory to CTK_EXTERNAL_LIBRARY_DIRS
 
 else()
-  ctkMacroEmptyExternalproject(${proj} "${${proj}_DEPENDENCIES}")
+  superbuild_add_empty_external_project(${proj} "${${proj}_DEPENDENCIES}")
 endif()
 
-list(APPEND CTK_SUPERBUILD_EP_VARS
-  DCMTK_DIR:PATH
+mark_as_superbuild(
+  VARS DCMTK_DIR:PATH
+  LABELS "FIND_PACKAGE"
   )
 

+ 7 - 3
CMakeExternals/ITK.cmake

@@ -11,7 +11,7 @@ set(${ITK_enabling_variable}_FIND_PACKAGE_CMD ITK)
 
 set(ITK_DEPENDENCIES "")
 
-ctkMacroCheckExternalProjectDependency(ITK)
+superbuild_include_dependencies(ITK)
 set(proj ITK)
 
 if(${CMAKE_PROJECT_NAME}_USE_SYSTEM_${proj})
@@ -49,6 +49,7 @@ if(NOT DEFINED ITK_DIR AND NOT ${CMAKE_PROJECT_NAME}_USE_SYSTEM_${proj})
   endif()
 
   ExternalProject_Add(${proj}
+    ${${proj}_EXTERNAL_PROJECT_ARGS}
     SOURCE_DIR ${CMAKE_BINARY_DIR}/${proj}
     BINARY_DIR ${proj}-build
     PREFIX ${proj}${ep_suffix}
@@ -79,7 +80,10 @@ if(NOT DEFINED ITK_DIR AND NOT ${CMAKE_PROJECT_NAME}_USE_SYSTEM_${proj})
   list(APPEND CTK_EXTERNAL_LIBRARY_DIRS ${ITK_DIR}/bin)
 
 else()
-  ctkMacroEmptyExternalproject(${proj} "${${proj}_DEPENDENCIES}")
+  superbuild_add_empty_external_project(${proj} "${${proj}_DEPENDENCIES}")
 endif()
 
-list(APPEND CTK_SUPERBUILD_EP_VARS ITK_DIR:PATH)
+mark_as_superbuild(
+  VARS ITK_DIR:PATH
+  LABELS "FIND_PACKAGE"
+  )

+ 7 - 3
CMakeExternals/KWStyle.cmake

@@ -6,7 +6,7 @@ superbuild_include_once()
 
 set(KWStyle_DEPENDENCIES "")
 
-ctkMacroCheckExternalProjectDependency(KWStyle)
+superbuild_include_dependencies(KWStyle)
 set(proj KWStyle)
 
 if(${CMAKE_PROJECT_NAME}_USE_SYSTEM_${proj})
@@ -33,6 +33,7 @@ if(NOT DEFINED KWSTYLE_EXECUTABLE)
   endif()
 
   ExternalProject_Add(${proj}
+    ${${proj}_EXTERNAL_PROJECT_ARGS}
     SOURCE_DIR ${CMAKE_BINARY_DIR}/${proj}
     BINARY_DIR ${proj}-build
     PREFIX ${proj}${ep_suffix}
@@ -49,7 +50,10 @@ if(NOT DEFINED KWSTYLE_EXECUTABLE)
   # Since KWStyle is an executable, there is not need to add its corresponding
   # library output directory to CTK_EXTERNAL_LIBRARY_DIRS
 else()
-  ctkMacroEmptyExternalproject(${proj} "${${proj}_DEPENDENCIES}")
+  superbuild_add_empty_external_project(${proj} "${${proj}_DEPENDENCIES}")
 endif()
 
-list(APPEND CTK_SUPERBUILD_EP_VARS KWSTYLE_EXECUTABLE:PATH)
+mark_as_superbuild(
+  VARS KWSTYLE_EXECUTABLE:FILEPATH
+  LABELS "FIND_PACKAGE"
+  )

+ 7 - 3
CMakeExternals/Log4Qt.cmake

@@ -10,7 +10,7 @@ set(${Log4Qt_enabling_variable}_FIND_PACKAGE_CMD Log4Qt)
 
 set(Log4Qt_DEPENDENCIES "")
 
-ctkMacroCheckExternalProjectDependency(Log4Qt)
+superbuild_include_dependencies(Log4Qt)
 set(proj Log4Qt)
 
 if(${CMAKE_PROJECT_NAME}_USE_SYSTEM_${proj})
@@ -41,6 +41,7 @@ if(NOT DEFINED Log4Qt_DIR)
   endif()
 
   ExternalProject_Add(${proj}
+    ${${proj}_EXTERNAL_PROJECT_ARGS}
     SOURCE_DIR ${CMAKE_BINARY_DIR}/${proj}
     BINARY_DIR ${proj}-build
     PREFIX ${proj}${ep_suffix}
@@ -61,7 +62,10 @@ if(NOT DEFINED Log4Qt_DIR)
   # library output directory to CTK_EXTERNAL_LIBRARY_DIRS
 
 else()
-  ctkMacroEmptyExternalproject(${proj} "${${proj}_DEPENDENCIES}")
+  superbuild_add_empty_external_project(${proj} "${${proj}_DEPENDENCIES}")
 endif()
 
-list(APPEND CTK_SUPERBUILD_EP_VARS Log4Qt_DIR:PATH)
+mark_as_superbuild(
+  VARS Log4Qt_DIR:PATH
+  LABELS "FIND_PACKAGE"
+  )

+ 7 - 3
CMakeExternals/OpenIGTLink.cmake

@@ -11,7 +11,7 @@ set(${OpenIGTLink_enabling_variable}_FIND_PACKAGE_CMD OpenIGTLink)
 
 set(OpenIGTLink_DEPENDENCIES "")
 
-ctkMacroCheckExternalProjectDependency(OpenIGTLink)
+superbuild_include_dependencies(OpenIGTLink)
 set(proj OpenIGTLink)
 
 if(${CMAKE_PROJECT_NAME}_USE_SYSTEM_${proj})
@@ -40,6 +40,7 @@ if(NOT DEFINED OpenIGTLink_DIR AND NOT ${CMAKE_PROJECT_NAME}_USE_SYSTEM_${proj})
   endif()
 
   ExternalProject_Add(${proj}
+    ${${proj}_EXTERNAL_PROJECT_ARGS}
     SOURCE_DIR ${CMAKE_BINARY_DIR}/${proj}
     BINARY_DIR ${proj}-build
     PREFIX ${proj}${ep_suffix}
@@ -56,7 +57,10 @@ if(NOT DEFINED OpenIGTLink_DIR AND NOT ${CMAKE_PROJECT_NAME}_USE_SYSTEM_${proj})
   set(OpenIGTLink_DIR ${CMAKE_BINARY_DIR}/${proj}-build)
 
 else()
-  ctkMacroEmptyExternalproject(${proj} "${${proj}_DEPENDENCIES}")
+  superbuild_add_empty_external_project(${proj} "${${proj}_DEPENDENCIES}")
 endif()
 
-list(APPEND CTK_SUPERBUILD_EP_VARS OpenIGTLink_DIR:PATH)
+mark_as_superbuild(
+  VARS OpenIGTLink_DIR:PATH
+  LABELS "FIND_PACKAGE"
+  )

+ 10 - 7
CMakeExternals/PythonQt.cmake

@@ -10,7 +10,7 @@ set(${PythonQt_enabling_variable}_FIND_PACKAGE_CMD PythonQt)
 
 set(PythonQt_DEPENDENCIES "")
 
-ctkMacroCheckExternalProjectDependency(PythonQt)
+superbuild_include_dependencies(PythonQt)
 set(proj PythonQt)
 
 if(${CMAKE_PROJECT_NAME}_USE_SYSTEM_${proj})
@@ -69,6 +69,7 @@ if(NOT DEFINED PYTHONQT_INSTALL_DIR)
   endif()
 
   ExternalProject_Add(${proj}
+    ${${proj}_EXTERNAL_PROJECT_ARGS}
     SOURCE_DIR ${CMAKE_BINARY_DIR}/${proj}
     BINARY_DIR ${proj}-build
     PREFIX ${proj}${ep_suffix}
@@ -92,12 +93,14 @@ if(NOT DEFINED PYTHONQT_INSTALL_DIR)
   # its corresponding library output directory to CTK_EXTERNAL_LIBRARY_DIRS
 
 else()
-  ctkMacroEmptyExternalproject(${proj} "${${proj}_DEPENDENCIES}")
+  superbuild_add_empty_external_project(${proj} "${${proj}_DEPENDENCIES}")
 endif()
 
-list(APPEND CTK_SUPERBUILD_EP_VARS
-  PYTHONQT_INSTALL_DIR:PATH
-  PYTHON_EXECUTABLE:FILEPATH # FindPythonInterp expects PYTHON_EXECUTABLE variable to be defined
-  PYTHON_INCLUDE_DIR:PATH # FindPythonQt expects PYTHON_INCLUDE_DIR variable to be defined
-  PYTHON_LIBRARY:FILEPATH # FindPythonQt expects PYTHON_LIBRARY variable to be defined
+mark_as_superbuild(
+  VARS
+    PYTHONQT_INSTALL_DIR:PATH
+    PYTHON_EXECUTABLE:FILEPATH # FindPythonInterp expects PYTHON_EXECUTABLE variable to be defined
+    PYTHON_INCLUDE_DIR:PATH # FindPythonQt expects PYTHON_INCLUDE_DIR variable to be defined
+    PYTHON_LIBRARY:FILEPATH # FindPythonQt expects PYTHON_LIBRARY variable to be defined
+  LABELS "FIND_PACKAGE"
   )

+ 7 - 3
CMakeExternals/PythonQtGenerator.cmake

@@ -11,7 +11,7 @@ endif()
 
 set(PythonQtGenerator_DEPENDENCIES PythonQt)
 
-ctkMacroCheckExternalProjectDependency(PythonQtGenerator)
+superbuild_include_dependencies(PythonQtGenerator)
 set(proj PythonQtGenerator)
 
 if(${CMAKE_PROJECT_NAME}_USE_SYSTEM_${proj})
@@ -30,6 +30,7 @@ if(NOT DEFINED PYTHONQTGENERATOR_EXECUTABLE)
   #
 
   ExternalProject_Add(${proj}
+    ${${proj}_EXTERNAL_PROJECT_ARGS}
     SOURCE_DIR ${CMAKE_BINARY_DIR}/PythonQt/generator
     BINARY_DIR ${proj}-build
     PREFIX ${proj}${ep_suffix}
@@ -50,7 +51,10 @@ if(NOT DEFINED PYTHONQTGENERATOR_EXECUTABLE)
   # library output directory to CTK_EXTERNAL_LIBRARY_DIRS
 
 else()
-  ctkMacroEmptyExternalproject(${proj} "${${proj}_DEPENDENCIES}")
+  superbuild_add_empty_external_project(${proj} "${${proj}_DEPENDENCIES}")
 endif()
 
-list(APPEND CTK_SUPERBUILD_EP_VARS PYTHONQTGENERATOR_EXECUTABLE:FILEPATH)
+mark_as_superbuild(
+  VARS PYTHONQTGENERATOR_EXECUTABLE:FILEPATH
+  LABELS "FIND_PACKAGE"
+  )

+ 7 - 3
CMakeExternals/QtSOAP.cmake

@@ -11,7 +11,7 @@ set(${QtSOAP_enabling_variable}_FIND_PACKAGE_CMD QtSOAP)
 
 set(QtSOAP_DEPENDENCIES "")
 
-ctkMacroCheckExternalProjectDependency(QtSOAP)
+superbuild_include_dependencies(QtSOAP)
 set(proj QtSOAP)
 
 if(${CMAKE_PROJECT_NAME}_USE_SYSTEM_${proj})
@@ -42,6 +42,7 @@ if(NOT DEFINED QtSOAP_DIR)
   endif()
 
   ExternalProject_Add(${proj}
+    ${${proj}_EXTERNAL_PROJECT_ARGS}
     SOURCE_DIR ${CMAKE_BINARY_DIR}/${proj}
     BINARY_DIR ${proj}-build
     PREFIX ${proj}${ep_suffix}
@@ -63,7 +64,10 @@ if(NOT DEFINED QtSOAP_DIR)
   # library output directory to CTK_EXTERNAL_LIBRARY_DIRS
 
 else()
-  ctkMacroEmptyExternalproject(${proj} "${${proj}_DEPENDENCIES}")
+  superbuild_add_empty_external_project(${proj} "${${proj}_DEPENDENCIES}")
 endif()
 
-list(APPEND CTK_SUPERBUILD_EP_VARS QtSOAP_DIR:PATH)
+mark_as_superbuild(
+  VARS QtSOAP_DIR:PATH
+  LABELS "FIND_PACKAGE"
+  )

+ 8 - 5
CMakeExternals/QtTesting.cmake

@@ -8,7 +8,7 @@ set(QtTesting_DEPENDS)
 
 set(QtTesting_DEPENDENCIES "")
 
-ctkMacroCheckExternalProjectDependency(QtTesting)
+superbuild_include_dependencies(QtTesting)
 set(proj QtTesting)
 
 if(${CMAKE_PROJECT_NAME}_USE_SYSTEM_${proj})
@@ -49,6 +49,7 @@ if(NOT DEFINED QtTesting_DIR)
 
   message(STATUS "Adding project:${proj}")
   ExternalProject_Add(${proj}
+    ${${proj}_EXTERNAL_PROJECT_ARGS}
     SOURCE_DIR ${CMAKE_BINARY_DIR}/${proj}
     BINARY_DIR ${proj}-build
     PREFIX ${proj}${ep_suffix}
@@ -70,10 +71,12 @@ if(NOT DEFINED QtTesting_DIR)
   # library output directory to CTK_EXTERNAL_LIBRARY_DIRS
 
 else()
-  ctkMacroEmptyExternalproject(${proj} "${${proj}_DEPENDENCIES}")
+  superbuild_add_empty_external_project(${proj} "${${proj}_DEPENDENCIES}")
 endif()
 
-list(APPEND CTK_SUPERBUILD_EP_VARS
-  QtTesting_INSTALL_DIR:PATH
-  QtTesting_DIR:PATH
+mark_as_superbuild(
+  VARS
+    QtTesting_INSTALL_DIR:PATH
+    QtTesting_DIR:PATH
+  LABELS "FIND_PACKAGE"
   )

+ 7 - 3
CMakeExternals/VTK.cmake

@@ -11,7 +11,7 @@ set(${VTK_enabling_variable}_FIND_PACKAGE_CMD VTK)
 
 set(VTK_DEPENDENCIES "")
 
-ctkMacroCheckExternalProjectDependency(VTK)
+superbuild_include_dependencies(VTK)
 set(proj VTK)
 
 if(${CMAKE_PROJECT_NAME}_USE_SYSTEM_${proj})
@@ -56,6 +56,7 @@ if(NOT DEFINED VTK_DIR AND NOT ${CMAKE_PROJECT_NAME}_USE_SYSTEM_${proj})
   endif()
 
   ExternalProject_Add(${proj}
+    ${${proj}_EXTERNAL_PROJECT_ARGS}
     SOURCE_DIR ${CMAKE_BINARY_DIR}/${proj}
     BINARY_DIR ${proj}-build
     PREFIX ${proj}${ep_suffix}
@@ -88,7 +89,10 @@ if(NOT DEFINED VTK_DIR AND NOT ${CMAKE_PROJECT_NAME}_USE_SYSTEM_${proj})
   list(APPEND CTK_EXTERNAL_LIBRARY_DIRS ${VTK_DIR}/bin)
 
 else()
-  ctkMacroEmptyExternalproject(${proj} "${${proj}_DEPENDENCIES}")
+  superbuild_add_empty_external_project(${proj} "${${proj}_DEPENDENCIES}")
 endif()
 
-list(APPEND CTK_SUPERBUILD_EP_VARS VTK_DIR:PATH)
+mark_as_superbuild(
+  VARS VTK_DIR:PATH
+  LABELS "FIND_PACKAGE"
+  )

+ 7 - 3
CMakeExternals/XIP.cmake

@@ -11,7 +11,7 @@ set(${XIP_enabling_variable}_FIND_PACKAGE_CMD XIP)
 
 set(XIP_DEPENDENCIES "")
 
-ctkMacroCheckExternalProjectDependency(XIP)
+superbuild_include_dependencies(XIP)
 set(proj XIP)
 
 if(${CMAKE_PROJECT_NAME}_USE_SYSTEM_${proj})
@@ -35,6 +35,7 @@ if(NOT DEFINED XIP_DIR)
   endif()
 
   ExternalProject_Add(${proj}
+    ${${proj}_EXTERNAL_PROJECT_ARGS}
     SOURCE_DIR ${CMAKE_BINARY_DIR}/${proj}
     BINARY_DIR ${proj}-build
     PREFIX ${proj}${ep_suffix}
@@ -52,7 +53,10 @@ if(NOT DEFINED XIP_DIR)
   set(XIP_DIR ${CMAKE_BINARY_DIR}/${proj}-build)
 
 else()
-  ctkMacroEmptyExternalproject(${proj} "${${proj}_DEPENDENCIES}")
+  superbuild_add_empty_external_project(${proj} "${${proj}_DEPENDENCIES}")
 endif()
 
-list(APPEND CTK_SUPERBUILD_EP_VARS XIP_DIR:PATH)
+mark_as_superbuild(
+  VARS XIP_DIR:PATH
+  LABELS "FIND_PACKAGE"
+  )

+ 7 - 3
CMakeExternals/ZMQ.cmake

@@ -11,7 +11,7 @@ set(${ZMQ_enabling_variable}_FIND_PACKAGE_CMD ZMQ)
 
 set(ZMQ_DEPENDENCIES "")
 
-ctkMacroCheckExternalProjectDependency(ZMQ)
+superbuild_include_dependencies(ZMQ)
 set(proj ZMQ)
 
 if(${CMAKE_PROJECT_NAME}_USE_SYSTEM_${proj})
@@ -42,6 +42,7 @@ if(NOT DEFINED ZMQ_DIR)
   endif()
 
   ExternalProject_Add(${proj}
+    ${${proj}_EXTERNAL_PROJECT_ARGS}
     SOURCE_DIR ${CMAKE_BINARY_DIR}/${proj}
     BINARY_DIR ${proj}-build
     PREFIX ${proj}${ep_suffix}
@@ -61,7 +62,10 @@ if(NOT DEFINED ZMQ_DIR)
   set(ZMQ_DIR ${CMAKE_BINARY_DIR}/${proj}-build)
 
 else()
-  ctkMacroEmptyExternalproject(${proj} "${${proj}_DEPENDENCIES}")
+  superbuild_add_empty_external_project(${proj} "${${proj}_DEPENDENCIES}")
 endif()
 
-list(APPEND CTK_SUPERBUILD_EP_VARS ZMQ_DIR:PATH)
+mark_as_superbuild(
+  VARS ZMQ_DIR:PATH
+  LABELS "FIND_PACKAGE"
+  )

+ 7 - 3
CMakeExternals/qxmlrpc.cmake

@@ -11,7 +11,7 @@ set(${qxmlrpc_enabling_variable}_FIND_PACKAGE_CMD qxmlrpc)
 
 set(qxmlrpc_DEPENDENCIES "")
 
-ctkMacroCheckExternalProjectDependency(qxmlrpc)
+superbuild_include_dependencies(qxmlrpc)
 set(proj qxmlrpc)
 
 if(${CMAKE_PROJECT_NAME}_USE_SYSTEM_${proj})
@@ -42,6 +42,7 @@ if(NOT DEFINED qxmlrpc_DIR)
   endif()
 
   ExternalProject_Add(${proj}
+    ${${proj}_EXTERNAL_PROJECT_ARGS}
     SOURCE_DIR ${CMAKE_BINARY_DIR}/${proj}
     BINARY_DIR ${proj}-build
     PREFIX ${proj}${ep_suffix}
@@ -61,7 +62,10 @@ if(NOT DEFINED qxmlrpc_DIR)
   # library output directory to CTK_EXTERNAL_LIBRARY_DIRS
 
 else()
-  ctkMacroEmptyExternalproject(${proj} "${${proj}_DEPENDENCIES}")
+  superbuild_add_empty_external_project(${proj} "${${proj}_DEPENDENCIES}")
 endif()
 
-list(APPEND CTK_SUPERBUILD_EP_VARS qxmlrpc_DIR:PATH)
+mark_as_superbuild(
+  VARS qxmlrpc_DIR:PATH
+  LABELS "FIND_PACKAGE"
+  )

+ 50 - 3
CMakeLists.txt

@@ -21,10 +21,23 @@
 cmake_minimum_required(VERSION 2.8.4)
 
 #-----------------------------------------------------------------------------
+# Superbuild
+#
+set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMake" ${CMAKE_MODULE_PATH})
+set(EXTERNAL_PROJECT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/CMakeExternals)
+set(EXTERNAL_PROJECT_FILE_PREFIX "")
+include(ExternalProject)
+include(ctkMacroCheckExternalProjectDependency)
+
+#-----------------------------------------------------------------------------
 if(APPLE)
   # Note: By setting CMAKE_OSX_* variables before any enable_language() or project() calls,
   #       we ensure that the bitness will be properly detected.
   include(${CMAKE_SOURCE_DIR}/CMake/ctkBlockSetCMakeOSXVariables.cmake)
+  mark_as_superbuild(
+    VARS CMAKE_OSX_ARCHITECTURES:STRING CMAKE_OSX_SYSROOT:PATH CMAKE_OSX_DEPLOYMENT_TARGET:STRING
+    PROJECT CTK
+    )
 endif()
 
 #-----------------------------------------------------------------------------
@@ -38,6 +51,7 @@ set(CTK_LIBRARY_MODE "SHARED")
 
 option(CTK_BUILD_SHARED_LIBS "Build CTK libraries as shared module." ON)
 mark_as_advanced(CTK_BUILD_SHARED_LIBS)
+mark_as_superbuild(CTK_BUILD_SHARED_LIBS)
 if(NOT CTK_BUILD_SHARED_LIBS)
   set(CTK_LIBRARY_MODE "STATIC")
 endif()
@@ -75,6 +89,7 @@ foreach(type LIBRARY RUNTIME ARCHIVE)
     if(NOT DEFINED CTK_CMAKE_${type}_OUTPUT_DIRECTORY)
       set(CTK_CMAKE_${type}_OUTPUT_DIRECTORY ${CTK_BINARY_DIR}/CTK-build/bin)
     endif()
+    mark_as_superbuild(CTK_CMAKE_${type}_OUTPUT_DIRECTORY:PATH)
   else()
     if(NOT DEFINED CTK_CMAKE_${type}_OUTPUT_DIRECTORY)
       set(output_dir ${CTK_BINARY_DIR}/bin)
@@ -135,13 +150,23 @@ if(NOT CTK_INSTALL_DOC_DIR)
   set(CTK_INSTALL_DOC_DIR "doc")
 endif()
 
+mark_as_superbuild(
+  CTK_INSTALL_BIN_DIR:STRING
+  CTK_INSTALL_LIB_DIR:STRING
+  CTK_INSTALL_PLUGIN_DIR:STRING
+  CTK_INSTALL_CMAKE_DIR:STRING
+  CTK_INSTALL_INCLUDE_DIR:STRING
+  CTK_INSTALL_PLUGIN_INCLUDE_DIR:STRING
+  CTK_INSTALL_QTPLUGIN_DIR:STRING
+  CTK_INSTALL_DOC_DIR:STRING
+  )
+
 #-----------------------------------------------------------------------------
 # Update CMake module path
 # Note: FindXXX.cmake script specific to utility should be copied into Utilities/CMake
 #
 set(CMAKE_MODULE_PATH
   "${CMAKE_CURRENT_SOURCE_DIR}/Utilities/CMake"
-  "${CMAKE_CURRENT_SOURCE_DIR}/CMake"
   ${CMAKE_MODULE_PATH})
 
 #-----------------------------------------------------------------------------
@@ -219,6 +244,7 @@ install(FILES
 #
 include(CTest)
 mark_as_advanced(BUILD_TESTING)
+mark_as_superbuild(BUILD_TESTING)
 
 if(BUILD_TESTING)
   set(CPP_TEST_PATH ${CMAKE_RUNTIME_OUTPUT_DIRECTORY})
@@ -258,30 +284,41 @@ endif()
 #
 option(CTK_USE_QTTESTING "Enable/Disable QtTesting" OFF)
 mark_as_advanced(CTK_USE_QTTESTING)
+mark_as_superbuild(CTK_USE_QTTESTING)
 
 #-----------------------------------------------------------------------------
 # Coverage
 #
 option(WITH_COVERAGE "Enable/Disable coverage" OFF)
 mark_as_advanced(WITH_COVERAGE)
+mark_as_superbuild(WITH_COVERAGE)
 
 #-----------------------------------------------------------------------------
 # Documentation
 #
 option(DOCUMENTATION_TARGET_IN_ALL "Include the custom target for building documentation in 'all'" OFF)
 mark_as_advanced(DOCUMENTATION_TARGET_IN_ALL)
+mark_as_superbuild(DOCUMENTATION_TARGET_IN_ALL)
 
 set(DOCUMENTATION_ARCHIVES_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
  CACHE PATH "Where documentation archives should be stored")
 mark_as_advanced(DOCUMENTATION_ARCHIVES_OUTPUT_DIRECTORY)
+mark_as_superbuild(DOCUMENTATION_ARCHIVES_OUTPUT_DIRECTORY)
+
+# Attempt to discover Doxygen so that DOXYGEN_EXECUTABLE is set to an appropriate default value
+find_package(Doxygen QUIET)
+mark_as_superbuild(DOXYGEN_EXECUTABLE)
 
 #-----------------------------------------------------------------------------
 # Additional CXX/C Flags
 #
 set(ADDITIONAL_C_FLAGS "" CACHE STRING "Additional C Flags")
 mark_as_advanced(ADDITIONAL_C_FLAGS)
+mark_as_superbuild(ADDITIONAL_C_FLAGS)
+
 set(ADDITIONAL_CXX_FLAGS "" CACHE STRING "Additional CXX Flags")
 mark_as_advanced(ADDITIONAL_CXX_FLAGS)
+mark_as_superbuild(ADDITIONAL_CXX_FLAGS)
 
 #-----------------------------------------------------------------------------
 # Set symbol visibility Flags
@@ -400,15 +437,19 @@ ctk_enable_option(PluginFramework "Enable Plugin Framework" OFF
 
 # Build all CTK plug-ins
 option(CTK_BUILD_ALL_PLUGINS "Build all CTK plug-ins" OFF)
+mark_as_superbuild(CTK_BUILD_ALL_PLUGINS)
 
 # Build all CTK libraries
 option(CTK_BUILD_ALL_LIBRARIES "Build all CTK libraries" OFF)
+mark_as_superbuild(CTK_BUILD_ALL_LIBRARIES)
 
 # Build all CTK applications
 option(CTK_BUILD_ALL_APPS "Build all CTK applications" OFF)
+mark_as_superbuild(CTK_BUILD_ALL_APPS)
 
 # Build everything
 option(CTK_BUILD_ALL "Build everything in CTK" OFF)
+mark_as_superbuild(CTK_BUILD_ALL)
 if(CTK_BUILD_ALL)
   set(CTK_BUILD_ALL_PLUGINS 1)
   set(CTK_BUILD_ALL_LIBRARIES 1)
@@ -421,6 +462,7 @@ endif()
 # The CTK Python Wrapping
 ctk_enable_option(Python_Wrapping "Wrap CTK classes using Qt meta-object system into Python language" OFF
                   CTK_LIB_Scripting/Python/Core)
+mark_as_superbuild(CTK_ENABLE_Python_Wrapping)
 
 # Build examples
 # Create the logical expression containing the minium set of required options
@@ -451,10 +493,12 @@ mark_as_advanced(DART_TESTING_TIMEOUT)
 # KWStyle
 option(CTK_USE_KWSTYLE     "Enable sourcecode-based style tests." OFF)
 mark_as_advanced(CTK_USE_KWSTYLE)
+mark_as_superbuild(CTK_USE_KWSTYLE)
 
 # Qt Designer Plugins
 option(CTK_BUILD_QTDESIGNER_PLUGINS "Build Qt Designer plugins" ON)
 mark_as_advanced(CTK_BUILD_QTDESIGNER_PLUGINS)
+mark_as_superbuild(CTK_BUILD_QTDESIGNER_PLUGINS)
 
 #-----------------------------------------------------------------------------
 # CTK Libraries
@@ -674,11 +718,13 @@ ctk_plugin_option(org.commontk.eventbus
 # Add the PluginsContrib repo to the build system
 option(CTK_USE_CONTRIBUTED_PLUGINS OFF "Use CTK plug-ins from the PluginsContrib repository")
 mark_as_advanced(CTK_USE_CONTRIBUTED_PLUGINS)
+mark_as_superbuild(CTK_USE_CONTRIBUTED_PLUGINS)
 if(CTK_USE_CONTRIBUTED_PLUGINS)
   ctkFunctionAddPluginRepo(NAME PluginsContrib
                            GIT_URL github.com/commontk/PluginsContrib.git
                            GIT_TAG 7fc37f400c
                           )
+  mark_as_superbuild(PluginsContrib_DIR:PATH)
 endif()
 
 #-----------------------------------------------------------------------------
@@ -705,7 +751,6 @@ endif()
 # Create list of directories corresponding to the enabled targets
 set(target_directories)
 
-set(ctk_lib_options_list) # This list will be updated in ctkMacroAddCtkLibraryOptions
 foreach(lib ${CTK_LIBS})
   if(CTK_LIB_${lib})
     ctkMacroAddCtkLibraryOptions(${lib})
@@ -762,6 +807,7 @@ ctkMacroValidateBuildOptions("${CTK_BINARY_DIR}" "${DGraph_EXECUTABLE}" "${targe
 set(CTK_WRAP_PYTHONQT_LIGHT ${CTK_ENABLE_Python_Wrapping})
 option(CTK_WRAP_PYTHONQT_FULL "Experimental - Wrap CTK classes using Qt meta-object system into Python language" OFF)
 mark_as_advanced(CTK_WRAP_PYTHONQT_FULL)
+mark_as_superbuild(CTK_WRAP_PYTHONQT_FULL)
 if(CTK_WRAP_PYTHONQT_FULL AND CTK_WRAP_PYTHONQT_LIGHT)
   message(FATAL_ERROR "CTK_ENABLE_Python_Wrapping AND CTK_WRAP_PYTHONQT_FULL options are mutually exclusive. Please enable only one !")
 endif()
@@ -875,8 +921,9 @@ if(CTK_USE_CONTRIBUTED_PLUGINS)
     ctkFunctionCheckoutRepo(
       NAME ExternalProjectsContrib
       GIT_URL github.com/commontk/ExternalProjectsContrib.git
-      GIT_TAG 80ce3d5
+      GIT_TAG 2bed266
       )
+    mark_as_superbuild(ExternalProjectsContrib_DIR:PATH)
   endif()
 
   file(GLOB _contrib_scripts ${ExternalProjectsContrib_DIR}/*.cmake)

+ 1 - 110
SuperBuild.cmake

@@ -40,132 +40,23 @@ if(NOT EXISTS ${CTK_BINARY_DIR}/CTK-build/bin)
 endif()
 
 #-----------------------------------------------------------------------------
-# Qt is expected to be setup by CTK/CMakeLists.txt just before it includes the SuperBuild script
-#
-
-#-----------------------------------------------------------------------------
-# Attempt to discover Doxygen so that DOXYGEN_EXECUTABLE is set to an appropriate default value
-#
-find_package(Doxygen QUIET)
-
-#-----------------------------------------------------------------------------
-# Generate cmake variable name corresponding to Libs, Plugins and Applications
-#
-set(ctk_libs_bool_vars)
-foreach(lib ${CTK_LIBS})
-  list(APPEND ctk_libs_bool_vars CTK_LIB_${lib})
-endforeach()
-
-set(ctk_plugins_bool_vars)
-foreach(plugin ${CTK_PLUGINS})
-  list(APPEND ctk_plugins_bool_vars CTK_PLUGIN_${plugin})
-endforeach()
-
-set(ctk_applications_bool_vars)
-foreach(app ${CTK_APPS})
-  list(APPEND ctk_applications_bool_vars CTK_APP_${app})
-endforeach()
-
-#-----------------------------------------------------------------------------
-# Set superbuild boolean args
-#
-
-set(ctk_cmake_boolean_args
-  BUILD_TESTING
-  CTK_BUILD_ALL
-  CTK_BUILD_ALL_APPS
-  CTK_BUILD_ALL_LIBRARIES
-  CTK_BUILD_ALL_PLUGINS
-  CTK_BUILD_QTDESIGNER_PLUGINS
-  CTK_USE_QTTESTING
-  CTK_USE_KWSTYLE
-  CTK_USE_CONTRIBUTED_PLUGINS
-  WITH_COVERAGE
-  DOCUMENTATION_TARGET_IN_ALL
-  CTK_WRAP_PYTHONQT_FULL
-  CTK_ENABLE_Python_Wrapping
-  ${ctk_lib_options_list}
-  )
-
-set(ctk_superbuild_boolean_args)
-foreach(ctk_cmake_arg ${ctk_cmake_boolean_args})
-  list(APPEND ctk_superbuild_boolean_args -D${ctk_cmake_arg}:BOOL=${${ctk_cmake_arg}})
-endforeach()
-
-foreach(ctk_cmake_arg ${ctk_libs_bool_vars} ${ctk_plugins_bool_vars} ${ctk_applications_bool_vars})
-  # Use the cached value of the option in case the current value has been
-  # overridden by a "CTK_BUILD_ALL" option.
-  get_property(arg_value CACHE ${ctk_cmake_arg} PROPERTY VALUE)
-  list(APPEND ctk_superbuild_boolean_args -D${ctk_cmake_arg}:BOOL=${arg_value})
-endforeach()
-
-# message("CMake boolean args:")
-# foreach(arg ${ctk_superbuild_boolean_args})
-#   message("  ${arg}")
-# endforeach()
-
-#-----------------------------------------------------------------------------
-# Expand superbuild external project args
-#
-set(CTK_SUPERBUILD_EP_ARGS)
-set(CTK_SUPERBUILD_EP_VARNAMES)
-foreach(arg ${CTK_SUPERBUILD_EP_VARS})
-  superbuild_cmakevar_to_cmakearg(${arg} cmake_arg varname)
-  list(APPEND CTK_SUPERBUILD_EP_ARGS ${cmake_arg})
-  list(APPEND CTK_SUPERBUILD_EP_VARNAMES ${varname})
-endforeach()
-string(REPLACE ";" "^" CTK_SUPERBUILD_EP_VARNAMES "${CTK_SUPERBUILD_EP_VARNAMES}")
-
-# message("CMake external project args:")
-# foreach(arg ${CTK_SUPERBUILD_EP_ARGS})
-#   message("  ${arg}")
-# endforeach()
-
-#-----------------------------------------------------------------------------
-if(CTK_USE_CONTRIBUTED_PLUGINS)
-  list(APPEND CTK_SUPERBUILD_EP_ARGS
-    -DExternalProjectsContrib_DIR:STRING=${ExternalProjectsContrib_DIR}
-    -DPluginsContrib_DIR:STRING=${PluginsContrib_DIR}
-    )
-endif()
-
-#-----------------------------------------------------------------------------
 set(proj CTK)
 
 ExternalProject_Add(${proj}
+  ${CTK_EXTERNAL_PROJECT_ARGS}
   DOWNLOAD_COMMAND ""
   CMAKE_GENERATOR ${gen}
   LIST_SEPARATOR ${sep}
   CMAKE_CACHE_ARGS
     -DCTK_SUPERBUILD:BOOL=OFF
     -DCTK_SUPERBUILD_BINARY_DIR:PATH=${CTK_BINARY_DIR}
-    ${ctk_superbuild_boolean_args}
     -DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE}
     -DCMAKE_C_COMPILER:FILEPATH=${CMAKE_C_COMPILER}
     -DCMAKE_CXX_COMPILER:FILEPATH=${CMAKE_CXX_COMPILER}
     -DCMAKE_CXX_FLAGS_INIT:STRING=${CMAKE_CXX_FLAGS_INIT}
     -DCMAKE_C_FLAGS_INIT:STRING=${CMAKE_C_FLAGS_INIT}
-    -DADDITIONAL_C_FLAGS:STRING=${ADDITIONAL_C_FLAGS}
-    -DADDITIONAL_CXX_FLAGS:STRING=${ADDITIONAL_CXX_FLAGS}
     -DCMAKE_INSTALL_PREFIX:PATH=${CMAKE_INSTALL_PREFIX}
-    -DCTK_BUILD_SHARED_LIBS:BOOL=${CTK_BUILD_SHARED_LIBS}
-    ${CMAKE_OSX_EXTERNAL_PROJECT_ARGS}
-    -DDOCUMENTATION_ARCHIVES_OUTPUT_DIRECTORY:PATH=${DOCUMENTATION_ARCHIVES_OUTPUT_DIRECTORY}
-    -DDOXYGEN_EXECUTABLE:FILEPATH=${DOXYGEN_EXECUTABLE}
-    -DCTK_CMAKE_ARCHIVE_OUTPUT_DIRECTORY:PATH=${CTK_CMAKE_ARCHIVE_OUTPUT_DIRECTORY}
-    -DCTK_CMAKE_LIBRARY_OUTPUT_DIRECTORY:PATH=${CTK_CMAKE_LIBRARY_OUTPUT_DIRECTORY}
-    -DCTK_CMAKE_RUNTIME_OUTPUT_DIRECTORY:PATH=${CTK_CMAKE_RUNTIME_OUTPUT_DIRECTORY}
-    -DCTK_INSTALL_BIN_DIR:STRING=${CTK_INSTALL_BIN_DIR}
-    -DCTK_INSTALL_LIB_DIR:STRING=${CTK_INSTALL_LIB_DIR}
-    -DCTK_INSTALL_PLUGIN_DIR:STRING=${CTK_INSTALL_PLUGIN_DIR}
-    -DCTK_INSTALL_INCLUDE_DIR:STRING=${CTK_INSTALL_INCLUDE_DIR}
-    -DCTK_INSTALL_PLUGIN_INCLUDE_DIR:STRING=${CTK_INSTALL_PLUGIN_INCLUDE_DIR}
-    -DCTK_INSTALL_QTPLUGIN_DIR:STRING=${CTK_INSTALL_QTPLUGIN_DIR}
-    -DCTK_INSTALL_DOC_DIR:STRING=${CTK_INSTALL_DOC_DIR}
     -DCTK_EXTERNAL_LIBRARY_DIRS:STRING=${CTK_EXTERNAL_LIBRARY_DIRS}
-    -DQT_QMAKE_EXECUTABLE:FILEPATH=${QT_QMAKE_EXECUTABLE}
-    ${CTK_SUPERBUILD_EP_ARGS}
-    -DCTK_SUPERBUILD_EP_VARNAMES:STRING=${CTK_SUPERBUILD_EP_VARNAMES}
   SOURCE_DIR ${CTK_SOURCE_DIR}
   BINARY_DIR ${CTK_BINARY_DIR}/CTK-build
   INSTALL_COMMAND ""