Commit 3d40f86f authored by Manuel Grizonnet's avatar Manuel Grizonnet

ENH: Add ITKModuleExternal.cmake

This allows a module to be built outside the OTB source tree by adding the
following to the module's top level CMakeLists.txt:

  project(MyModule)

  if(NOT OTB_SOURCE_DIR)
    find_package(OTB REQUIRED)
    list(APPEND CMAKE_MODULE_PATH ${OTB_CMAKE_DIR})
    include(OTBModuleExternal)
  else()
    otb_module_impl()
  endif()

Move otb_add_test into CMake/OTBModuleTest.cmake so
they can be re-used.

This can be used for building against an ITK build tree, not an install
tree.

This contribution is mostly inspired by Matt McCormick to ITK to support ITK
module outside the source tree:

https://github.com/InsightSoftwareConsortium/ITK/commit/387e9ff8712751a65ff65e36e526c92525d906aa

The OTB template module was also updated accordingly:

https://github.com/orfeotoolbox/otbExternalModuleTemplate
parent 3f395ad7
......@@ -16,6 +16,9 @@ set(OTB_VERSION_MAJOR "@OTB_VERSION_MAJOR@")
set(OTB_VERSION_MINOR "@OTB_VERSION_MINOR@")
set(OTB_VERSION_PATCH "@OTB_VERSION_PATCH@")
# OTB's CMake directory with modules OTB uses.
set(OTB_CMAKE_DIR "@OTB_CONFIG_CMAKE_DIR@")
# The location of the UseOTB.cmake file.
set(OTB_USE_FILE "@OTB_USE_FILE@")
......
......@@ -34,12 +34,13 @@ macro( otb_module_doxygen _name )
set( _content "${_content} \\enddot \n" )
set( _content "${_content} */\n" )
configure_file(
"${OTB_SOURCE_DIR}/Utilities/Doxygen/Module.dox.in"
"${OTB_BINARY_DIR}/Utilities/Doxygen/Modules/${_name}.dox"
@ONLY
if(ITK_SOURCE_DIR)
configure_file(
"${OTB_SOURCE_DIR}/Utilities/Doxygen/Module.dox.in"
"${OTB_BINARY_DIR}/Utilities/Doxygen/Modules/${_name}.dox"
@ONLY
)
endif()
if(NOT ${_name}_THIRD_PARTY AND EXISTS ${${_name}_SOURCE_DIR}/include)
if(PYTHON_EXECUTABLE)
otb_add_test(NAME ${_name}InDoxygenGroup COMMAND ${PYTHON_EXECUTABLE} "${OTB_SOURCE_DIR}/Utilities/Doxygen/mcdoc.py" check ${_name} ${${_name}_SOURCE_DIR}/include)
......
#Adapted from ITKModuleExternal.cmake
# This file ensures the appropriate variables are set up for a project extending
# OTB before including OTBModuleMacros. This is the preferred way to build an
# OTB module outside of the OTB source tree.
if(NOT OTB_FOUND)
message(FATAL_ERROR "OTB must be found before module macros can be used.")
endif()
if(NOT OTB_VERSION VERSION_GREATER "5.2")
message(FATAL_ERROR "Requires OTB 5.4 or later to work.")
endif()
if(NOT EXISTS ${OTB_CMAKE_DIR}/OTBModuleMacros.cmake)
message(FATAL_ERROR "Modules can only be built against an OTB build tree; they cannot be built against an OTB install tree.")
endif()
# Setup build locations.
if(NOT CMAKE_RUNTIME_OUTPUT_DIRECTORY)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${OTB_DIR}/bin)
endif()
if(NOT CMAKE_LIBRARY_OUTPUT_DIRECTORY)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${OTB_DIR}/lib)
endif()
if(NOT CMAKE_ARCHIVE_OUTPUT_DIRECTORY)
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${OTB_DIR}/lib)
endif()
# OTB installation structure
if(NOT OTB_INSTALL_RUNTIME_DIR)
set(OTB_INSTALL_RUNTIME_DIR bin)
endif()
if(NOT OTB_INSTALL_LIBRARY_DIR)
set(OTB_INSTALL_LIBRARY_DIR lib)
endif()
if(NOT OTB_INSTALL_ARCHIVE_DIR)
set(OTB_INSTALL_ARCHIVE_DIR lib)
endif()
if(NOT OTB_INSTALL_INCLUDE_DIR)
set(OTB_INSTALL_INCLUDE_DIR include/OTB-${OTB_VERSION_MAJOR}.${OTB_VERSION_MINOR})
endif()
if(NOT OTB_INSTALL_DATA_DIR)
set(OTB_INSTALL_DATA_DIR share/OTB-${OTB_VERSION_MAJOR}.${OTB_VERSION_MINOR})
endif()
if(NOT OTB_INSTALL_DOC_DIR)
set(OTB_INSTALL_DOC_DIR share/doc/OTB-${OTB_VERSION_MAJOR}.${OTB_VERSION_MINOR})
endif()
if(NOT OTB_INSTALL_PACKAGE_DIR)
set(OTB_INSTALL_PACKAGE_DIR "lib/cmake/OTB-${OTB_VERSION_MAJOR}.${OTB_VERSION_MINOR}")
endif()
# Use OTB's flags.
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OTB_REQUIRED_C_FLAGS}")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OTB_REQUIRED_CXX_FLAGS}")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${OTB_REQUIRED_LINK_FLAGS}")
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${OTB_REQUIRED_LINK_FLAGS}")
set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} ${OTB_REQUIRED_LINK_FLAGS}")
option(BUILD_SHARED_LIBS "Build OTB with shared libraries." ${OTB_BUILD_SHARED})
# Add the OTB_MODULES_DIR to the CMAKE_MODULE_PATH and then use the binary
# directory for the project to write out new ones to.
if(OTB_MODULES_DIR)
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${OTB_MODULES_DIR})
endif()
set(OTB_MODULES_DIR "${OTB_DIR}/${OTB_INSTALL_PACKAGE_DIR}/Modules")
#include(OTBExternalData)
if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/test/CMakeLists.txt)
include(CTest)
include(OTBModuleTest)
endif()
include(OTBModuleMacros)
include(otb-module.cmake)
set(${otb-module}-targets ${otb-module}Targets)
set(${otb-module}-targets-install "\${OTB_INSTALL_PREFIX}/${OTB_INSTALL_PACKAGE_DIR}/${otb-module}Targets.cmake")
set(${otb-module}_TARGETS_FILE_INSTALL "${${otb-module}-targets-install}")
set(${otb-module}-targets-build "${OTB_DIR}/${OTB_INSTALL_PACKAGE_DIR}/Modules/${otb-module}Targets.cmake")
set(${otb-module}_TARGETS_FILE_BUILD "${${otb-module}-targets-build}")
otb_module_impl()
if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/src/CMakeLists.txt AND NOT ${otb-module}_NO_SRC AND "${${otb-module}-targets}")
install(EXPORT ${${otb-module}-targets} DESTINATION "${OTB_INSTALL_PACKAGE_DIR}/Modules"
COMPONENT Development)
endif()
set(OTB_TEST_OUTPUT_DIR "${CMAKE_BINARY_DIR}/Testing/Temporary")
if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/test/CMakeLists.txt")
add_subdirectory(test)
endif()
......@@ -42,8 +42,8 @@ endif()
macro( otb_module_headertest _name )
if( NOT ${_name}_THIRD_PARTY AND
EXISTS ${${_name}_SOURCE_DIR}/include
if( NOT ${_name}_THIRD_PARTY
AND EXISTS ${${_name}_SOURCE_DIR}/include
AND PYTHON_EXECUTABLE
AND NOT (PYTHON_VERSION_STRING VERSION_LESS 2.6)
AND NOT (${_name} STREQUAL OTBTestKernel)
......
......@@ -137,6 +137,12 @@ macro(otb_module_impl)
list(APPEND ${otb-module}_INCLUDE_DIRS ${${otb-module}_SOURCE_DIR}/include)
install(DIRECTORY include/ DESTINATION ${${otb-module}_INSTALL_INCLUDE_DIR} COMPONENT Development)
endif()
if(NOT OTB_SOURCE_DIR)
# When building a module outside the OTB source tree, find the export
# header.
list(APPEND ${otb-module}_INCLUDE_DIRS ${${otb-module}_BINARY_DIR}/include)
endif()
if(${otb-module}_INCLUDE_DIRS)
include_directories(${${otb-module}_INCLUDE_DIRS})
......@@ -170,11 +176,11 @@ macro(otb_module_impl)
endif()
if( OTB_MODULE_${otb-module}_ENABLE_SHARED )
# Need to use relative path to work around CMake ISSUE 12645 fixed
# in CMake 2.8.8, to support older versions
set(_export_header_file "${OTBCommon_BINARY_DIR}/${otb-module}Export.h")
file(RELATIVE_PATH _export_header_file ${CMAKE_CURRENT_BINARY_DIR} ${_export_header_file} )
if(OTB_SOURCE_DIR)
set(_export_header_file "${OTBCommon_BINARY_DIR}/${otb-module}Export.h")
else()
set(_export_header_file "${${otb-module}_BINARY_DIR}/include/${otb-module}Export.h")
endif()
# Generate the export macro header for symbol visibility/Windows DLL declspec
generate_export_header(${otb-module}
......@@ -183,7 +189,7 @@ macro(otb_module_impl)
NO_EXPORT_MACRO_NAME ${otb-module}_HIDDEN
STATIC_DEFINE OTB_STATIC )
install(FILES
${OTBCommon_BINARY_DIR}/${otb-module}Export.h
${_export_header_file}
DESTINATION ${${otb-module}_INSTALL_INCLUDE_DIR}
COMPONENT Development
)
......@@ -225,7 +231,7 @@ macro(otb_module_impl)
DESTINATION ${OTB_INSTALL_PACKAGE_DIR}/Modules
COMPONENT Development
)
otb_module_doxygen( ${otb-module} ) # module name
otb_module_doxygen(${otb-module}) # module name
endmacro()
macro(otb_module_test)
......
# This file contains CMake functions and macros used when testing ITK modules.
#-----------------------------------------------------------------------------
# Create source code, compile and link a test driver
# Two variables must be defined before including this file.
# KIT should define a unique name for the test driver.
# KitTests should contain a list of test file names.
# Arguments - Input
# KIT - the name of the test directory
# KIT_LIBS - a list of libraries needed to link the test driver
# KitTests - a list of tests to be included in the test driver
# ADDITIONAL_SRC (optional) - additional source files, which don't contain tests
macro(CreateTestDriver KIT KIT_LIBS KitTests)
set(ADDITIONAL_SRC ${ARGN})
if(EMSCRIPTEN)
set(emscripten_before "
EM_ASM(
var cmake_source_dir = '${CMAKE_SOURCE_DIR}'.split('/');
// This is intentionally global so it can be unmounted at the end.
source_mount_dir = null;
if(cmake_source_dir[1] === 'home') {
source_mount_dir = cmake_source_dir.slice(0, 3).join('/');
}
else {
source_mount_dir = cmake_source_dir.slice(0, 2).join('/');
}
FS.mkdir(source_mount_dir);
FS.mount(NODEFS, { root: source_mount_dir }, source_mount_dir);
var cmake_binary_dir = '${CMAKE_BINARY_DIR}'.split('/');
// This is intentionally global so it can be unmounted at the end.
binary_mount_dir = null;
if(cmake_binary_dir[1] === 'home') {
binary_mount_dir = cmake_binary_dir.slice(0, 3).join('/');
}
else {
binary_mount_dir = cmake_binary_dir.slice(0, 2).join('/');
}
if(source_mount_dir != binary_mount_dir) {
FS.mkdir(binary_mount_dir);
FS.mount(NODEFS, { root: binary_mount_dir }, binary_mount_dir);
}
);
")
set(emscripten_after "
EM_ASM(
FS.unmount(source_mount_dir);
if(source_mount_dir != binary_mount_dir) {
FS.unmount(binary_mount_dir);
}
);
")
endif()
set(CMAKE_TESTDRIVER_BEFORE_TESTMAIN "${emscripten_before}#include \"otbTestDriverBeforeTest.inc\"")
set(CMAKE_TESTDRIVER_AFTER_TESTMAIN "#include \"otbTestDriverAfterTest.inc\"${emscripten_after}")
create_test_sourcelist(Tests ${KIT}TestDriver.cxx
${KitTests}
EXTRA_INCLUDE otbTestDriverIncludeRequiredIOFactories.h
FUNCTION ProcessArgumentsAndRegisterRequiredFactories
)
add_executable(${KIT}TestDriver ${KIT}TestDriver.cxx ${Tests} ${ADDITIONAL_SRC})
target_link_libraries(${KIT}TestDriver LINK_PUBLIC ${KIT_LIBS} ${OTBTestKernel_LIBRARIES})
otb_module_target_label(${KIT}TestDriver)
endmacro()
macro(CreateTestDriver_SupportBuildInIOFactories KIT KIT_LIBS KitTests)
set(ADDITIONAL_SRC ${ARGN} )
if(EMSCRIPTEN)
set(emscripten_before "
EM_ASM(
var cmake_source_dir = '${CMAKE_SOURCE_DIR}'.split('/');
// This is intentionally global so it can be unmounted at the end.
source_mount_dir = null;
if(cmake_source_dir[1] === 'home') {
source_mount_dir = cmake_source_dir.slice(0, 3).join('/');
}
else {
source_mount_dir = cmake_source_dir.slice(0, 2).join('/');
}
FS.mkdir(source_mount_dir);
FS.mount(NODEFS, { root: source_mount_dir }, source_mount_dir);
// This is intentionally global so it can be unmounted at the end.
binary_mount_dir = null;
var cmake_binary_dir = '${CMAKE_BINARY_DIR}'.split('/');
if(cmake_binary_dir[1] === 'home') {
binary_mount_dir = cmake_binary_dir.slice(0, 3).join('/');
}
else {
binary_mount_dir = cmake_binary_dir.slice(0, 2).join('/');
}
if(source_mount_dir != binary_mount_dir) {
FS.mkdir(binary_mount_dir);
FS.mount(NODEFS, { root: binary_mount_dir }, binary_mount_dir);
}
);
")
set(emscripten_after "
EM_ASM(
FS.unmount(source_mount_dir);
if(source_mount_dir != binary_mount_dir) {
FS.unmount(binary_mount_dir);
}
);
")
endif()
set(CMAKE_TESTDRIVER_BEFORE_TESTMAIN "${emscripten_before}#include \"otbTestDriverBeforeTest.inc\"")
set(CMAKE_TESTDRIVER_AFTER_TESTMAIN "#include \"otbTestDriverAfterTest.inc\"${emscripten_after}")
create_test_sourcelist(Tests ${KIT}TestDriver.cxx
${KitTests}
EXTRA_INCLUDE otbTestDriverIncludeBuiltInIOFactories.h
FUNCTION ProcessArgumentsAndRegisterBuiltInFactories
)
add_executable(${KIT}TestDriver ${KIT}TestDriver.cxx ${Tests} ${ADDITIONAL_SRC})
target_link_libraries(${KIT}TestDriver LINK_PUBLIC ${KIT_LIBS} ${OTBTestKernel_LIBRARIES})
otb_module_target_label(${KIT}TestDriver)
endmacro()
#-----------------------------------------------------------------------------
# OTB wrapper for add_test that automatically sets the test's LABELS property
# to the value of its containing module.
#
# function(otb_add_test)
# # Add tests with data in the OTBData group.
# ExternalData_add_test(OTBData ${ARGN})
# if("NAME" STREQUAL "${ARGV0}")
# set(_iat_testname ${ARGV1})
# else()
# set(_iat_testname ${ARGV0})
# endif()
# if(otb-module)
# set(_label ${otb-module})
# if(TARGET ${otb-module}-all AND "${ARGN}" MATCHES "DATA{")
# add_dependencies(${otb-module}-all OTBData)
# endif()
# else()
# set(_label ${main_project_name})
# endif()
# set_property(TEST ${_iat_testname} PROPERTY LABELS ${_label})
# endfunction()
#-----------------------------------------------------------------------------
# OTB wrapper for add_test that automatically sets the test's LABELS property
# to the value of its containing module.
#
function(otb_add_test)
set(largeinput_regex "LARGEINPUT{([^;{}\r\n]*)}")
set(_depends_on_largeinput OFF)
foreach(arg IN LISTS ARGN)
if("x${arg}" MATCHES "${largeinput_regex}")
string(REGEX REPLACE "${largeinput_regex}" "\\1" largeinput_relative_path "${arg}")
set(_fullpath "${OTB_DATA_LARGEINPUT_ROOT}/${largeinput_relative_path}")
list(APPEND _out_arg ${_fullpath})
set(_depends_on_largeinput ON)
else()
list(APPEND _out_arg ${arg})
endif()
endforeach()
if (_depends_on_largeinput AND NOT OTB_DATA_USE_LARGEINPUT)
return()
endif()
add_test(${_out_arg})
if("NAME" STREQUAL "${ARGV0}")
set(_iat_testname ${ARGV1})
else()
set(_iat_testname ${ARGV0})
endif()
if(otb-module)
set(_label ${otb-module})
else()
set(_label ${main_project_name})
endif()
set_property(TEST ${_iat_testname} PROPERTY LABELS ${_label})
endfunction()
#-----------------------------------------------------------------------------
# OTB function to ignore a test
#
function(otb_tests_ignore)
set_property(GLOBAL APPEND PROPERTY CTEST_CUSTOM_TESTS_IGNORE ${ARGN})
endfunction()
#-----------------------------------------------------------------------------
# OTB function to ignore a test during MemCheck
#
function(otb_memcheck_ignore)
set_property(GLOBAL APPEND PROPERTY CTEST_CUSTOM_MEMCHECK_IGNORE ${ARGN})
endfunction()
......@@ -54,12 +54,14 @@ if( CMAKE_HOST_WIN32 )
endif()
set(CMAKE_MODULE_PATH ${OTB_SOURCE_DIR}/CMake ${CMAKE_MODULE_PATH})
set(OTB_CMAKE_DIR ${OTB_SOURCE_DIR}/CMake)
set(CMAKE_MODULE_PATH ${OTB_CMAKE_DIR} ${CMAKE_MODULE_PATH})
include (SourceStatus)
include(PreventInSourceBuilds)
include(PreventInBuildInstalls)
include(OTBModuleMacros)
include(OTBModuleRemote)
include(OTBModuleTest)
set(main_project_name ${_OTBModuleMacros_DEFAULT_LABEL})
......@@ -243,63 +245,8 @@ set(EPSILON_13 0.0000000000001)
set(EPSILON_14 0.00000000000001)
set(EPSILON_15 0.000000000000001)
#-----------------------------------------------------------------------------
# OTB wrapper for add_test that automatically sets the test's LABELS property
# to the value of its containing module.
#
function(otb_add_test)
set(largeinput_regex "LARGEINPUT{([^;{}\r\n]*)}")
set(_depends_on_largeinput OFF)
foreach(arg IN LISTS ARGN)
if("x${arg}" MATCHES "${largeinput_regex}")
string(REGEX REPLACE "${largeinput_regex}" "\\1" largeinput_relative_path "${arg}")
set(_fullpath "${OTB_DATA_LARGEINPUT_ROOT}/${largeinput_relative_path}")
list(APPEND _out_arg ${_fullpath})
set(_depends_on_largeinput ON)
else()
list(APPEND _out_arg ${arg})
endif()
endforeach()
if (_depends_on_largeinput AND NOT OTB_DATA_USE_LARGEINPUT)
return()
endif()
add_test(${_out_arg})
if("NAME" STREQUAL "${ARGV0}")
set(_iat_testname ${ARGV1})
else()
set(_iat_testname ${ARGV0})
endif()
if(otb-module)
set(_label ${otb-module})
else()
set(_label ${main_project_name})
endif()
set_property(TEST ${_iat_testname} PROPERTY LABELS ${_label})
endfunction()
#-----------------------------------------------------------------------------
# OTB function to ignore a test
#
function(otb_tests_ignore)
set_property(GLOBAL APPEND PROPERTY CTEST_CUSTOM_TESTS_IGNORE ${ARGN})
endfunction()
#-----------------------------------------------------------------------------
# OTB function to ignore a test during MemCheck
#
function(otb_memcheck_ignore)
set_property(GLOBAL APPEND PROPERTY CTEST_CUSTOM_MEMCHECK_IGNORE ${ARGN})
endfunction()
# Location of OTB Example Data.
# set(OTB_EXAMPLE_DATA_ROOT "${OTB_SOURCE_DIR}/Examples/Data")
set(OTB_EXAMPLE_DATA_ROOT "${OTB_SOURCE_DIR}/Examples/Data")
#----------------------------------------------------------------------
# Make sure remote modules are downloaded before sorting out the module
......@@ -313,7 +260,8 @@ include(OTBModuleEnablement)
# Generate OTBConfig.cmake for the build tree.
set(OTB_CONFIG_CODE "
set(OTB_MODULES_DIR \"${OTB_MODULES_DIR}\")")
set(OTB_USE_FILE "${OTB_SOURCE_DIR}/CMake/UseOTB.cmake")
set(OTB_CONFIG_CMAKE_DIR "${OTB_SOURCE_DIR}/CMake")
set(OTB_USE_FILE "${OTB_CONFIG_CMAKE_DIR}/UseOTB.cmake")
set(OTB_CONFIG_TARGETS_CONDITION " AND NOT OTB_BINARY_DIR")
set(OTB_CONFIG_TARGETS_FILE "${OTB_BINARY_DIR}/OTBTargets.cmake")
set(OTB_CONFIG_MODULE_API_FILE "${OTB_SOURCE_DIR}/CMake/OTBModuleAPI.cmake")
......@@ -334,6 +282,7 @@ endforeach()
set(OTB_CONFIG_CODE "${OTB_CONFIG_CODE}
set(OTB_MODULES_DIR \"\${OTB_INSTALL_PREFIX}/${OTB_INSTALL_PACKAGE_DIR}/Modules\")")
set(OTB_USE_FILE "\${OTB_INSTALL_PREFIX}/${OTB_INSTALL_PACKAGE_DIR}/UseOTB.cmake")
set(OTB_CONFIG_CMAKE_DIR "\${OTB_INSTALL_PREFIX}/${OTB_INSTALL_PACKAGE_DIR}")
set(OTB_CONFIG_TARGETS_CONDITION "")
set(OTB_CONFIG_TARGETS_FILE "\${OTB_INSTALL_PREFIX}/${OTB_INSTALL_PACKAGE_DIR}/OTBTargets.cmake")
set(OTB_CONFIG_MODULE_API_FILE "\${OTB_INSTALL_PREFIX}/${OTB_INSTALL_PACKAGE_DIR}/OTBModuleAPI.cmake")
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment