cmake: allow providing list of extra modules paths

This commit is contained in:
Maksim Shabunin 2018-02-01 17:08:01 +03:00
parent f780ee12a0
commit 82aff110b7
4 changed files with 153 additions and 82 deletions

View File

@ -497,7 +497,7 @@ ocv_include_directories(${OPENCV_CONFIG_FILE_INCLUDE_DIR})
# ----------------------------------------------------------------------------
# Path for additional modules
# ----------------------------------------------------------------------------
set(OPENCV_EXTRA_MODULES_PATH "" CACHE PATH "Where to look for additional OpenCV modules")
set(OPENCV_EXTRA_MODULES_PATH "" CACHE PATH "Where to look for additional OpenCV modules (can be ;-separated list of paths)")
# ----------------------------------------------------------------------------
# Autodetect if we are in a GIT repository

View File

@ -251,57 +251,118 @@ macro(ocv_module_disable module)
return() # leave the current folder
endmacro()
# gather acceptable locations and generate names for them
# if folder contains CMakeLists.txt - it is accepted,
# otherwise all first-level subfolders containing CMakeLists.txt are accepted.
# Usage: _glob_locations(<output paths list> <output names list> <folder> [<folder> ...])
function(_glob_locations out_paths out_names)
foreach(path ${ARGN})
message(STATUS "Inspect: ${path}")
list(LENGTH paths before)
get_filename_component(path "${path}" ABSOLUTE)
# Either module itself
if(NOT path STREQUAL CMAKE_CURRENT_SOURCE_DIR AND EXISTS "${path}/CMakeLists.txt")
get_filename_component(name "${path}" NAME)
list(APPEND paths "${path}")
list(APPEND names "${name}")
else()
# Either flat collection of modules
file(GLOB subdirs RELATIVE "${path}" "${path}/*")
foreach(subdir ${subdirs})
message(STATUS "Inspect: ${path}/${subdir}")
if(EXISTS "${path}/${subdir}/CMakeLists.txt")
list(APPEND paths "${path}/${subdir}")
list(APPEND names "${subdir}")
endif()
endforeach()
endif()
list(LENGTH paths after)
if(before EQUAL after)
message(SEND_ERROR "No modules has been found: ${path}")
endif()
endforeach()
# Return
set(${out_paths} ${paths} PARENT_SCOPE)
set(${out_names} ${names} PARENT_SCOPE)
endfunction()
# Calls 'add_subdirectory' for each location.
# Note: both input lists should have same length.
# Usage: _add_modules_1(<list with paths> <list with names>)
function(_add_modules_1 paths names)
list(LENGTH ${paths} len)
if(len EQUAL 0)
return()
endif()
list(LENGTH ${names} len_verify)
if(NOT len EQUAL len_verify)
message(FATAL_ERROR "Bad configuration! ${len} != ${len_verify}")
endif()
math(EXPR len "${len} - 1")
foreach(i RANGE ${len})
list(GET ${paths} ${i} path)
list(GET ${names} ${i} name)
message(STATUS "First pass: ${name} => ${path}")
include("${path}/cmake/init.cmake" OPTIONAL)
add_subdirectory("${path}" "${CMAKE_CURRENT_BINARY_DIR}/.firstpass/${name}")
endforeach()
endfunction()
# Calls 'add_subdirectory' for each module name.
# Usage: _add_modules_2([<module> ...])
function(_add_modules_2)
foreach(m ${ARGN})
set(the_module "${m}")
if(BUILD_opencv_world AND m STREQUAL "opencv_world"
OR NOT BUILD_opencv_world
OR NOT OPENCV_MODULE_${m}_IS_PART_OF_WORLD)
if(NOT m MATCHES "^opencv_")
message(WARNING "Incorrect module name: ${m}")
endif()
string(REGEX REPLACE "^opencv_" "" name "${m}")
message(STATUS "Second pass: ${name} => ${OPENCV_MODULE_${m}_LOCATION}")
add_subdirectory("${OPENCV_MODULE_${m}_LOCATION}" "${CMAKE_CURRENT_BINARY_DIR}/${name}")
endif()
endforeach()
endfunction()
# Check if list of input items is unique.
# Usage: _assert_uniqueness(<failure message> <element> [<element> ...])
function(_assert_uniqueness msg)
ocv_get_duplicates(dups ${ARGN})
if(dups)
foreach(e ${ARGN})
list(FIND dups "${e}" idx)
if(NOT idx EQUAL -1)
set(prefix " > ")
else()
set(prefix " ")
endif()
message("${prefix}${e}")
endforeach()
message(FATAL_ERROR "${msg}")
endif()
endfunction()
# collect modules from specified directories
# NB: must be called only once!
macro(ocv_glob_modules)
# Usage: ocv_glob_modules(<main location> [<extra location> ...])
macro(ocv_glob_modules main_root)
if(DEFINED OPENCV_INITIAL_PASS)
message(FATAL_ERROR "OpenCV has already loaded its modules. Calling ocv_glob_modules second time is not allowed.")
endif()
set(__directories_observed "")
# collect modules
set(OPENCV_INITIAL_PASS ON)
_glob_locations(__main_paths __main_names ${main_root})
_glob_locations(__extra_paths __extra_names ${ARGN})
_assert_uniqueness("Duplicated modules LOCATIONS has been found" ${__main_paths} ${__extra_paths})
_assert_uniqueness("Duplicated modules NAMES has been found" ${__main_names} ${__extra_names})
set(OPENCV_PROCESSING_EXTRA_MODULES 0)
foreach(__path ${ARGN})
if("${__path}" STREQUAL "EXTRA")
set(OPENCV_PROCESSING_EXTRA_MODULES 1)
else()
get_filename_component(__path "${__path}" ABSOLUTE)
list(FIND __directories_observed "${__path}" __pathIdx)
if(__pathIdx GREATER -1)
message(FATAL_ERROR "The directory ${__path} is observed for OpenCV modules second time.")
endif()
list(APPEND __directories_observed "${__path}")
set(__count 0)
file(GLOB __ocvmodules RELATIVE "${__path}" "${__path}/*")
if(__ocvmodules)
list(SORT __ocvmodules)
foreach(mod ${__ocvmodules})
get_filename_component(__modpath "${__path}/${mod}" ABSOLUTE)
if(EXISTS "${__modpath}/CMakeLists.txt")
list(FIND __directories_observed "${__modpath}" __pathIdx)
if(__pathIdx GREATER -1)
message(FATAL_ERROR "The module from ${__modpath} is already loaded.")
endif()
list(APPEND __directories_observed "${__modpath}")
add_subdirectory("${__modpath}" "${CMAKE_CURRENT_BINARY_DIR}/${mod}/.${mod}")
if (DEFINED OPENCV_MODULE_opencv_${mod}_LOCATION)
math(EXPR __count "${__count} + 1")
endif()
endif()
endforeach()
endif()
if (OPENCV_PROCESSING_EXTRA_MODULES AND ${__count} LESS 1)
message(SEND_ERROR "No extra modules found in folder: ${__path}\nPlease provide path to 'opencv_contrib/modules' folder.")
endif()
endif()
endforeach()
ocv_clear_vars(__ocvmodules __directories_observed __path __modpath __pathIdx)
_add_modules_1(__main_paths __main_names)
set(OPENCV_PROCESSING_EXTRA_MODULES 1)
_add_modules_1(__extra_paths __extra_names)
ocv_clear_vars(__main_names __extra_names __main_paths __extra_paths)
# resolve dependencies
__ocv_resolve_dependencies()
@ -309,35 +370,7 @@ macro(ocv_glob_modules)
# create modules
set(OPENCV_INITIAL_PASS OFF PARENT_SCOPE)
set(OPENCV_INITIAL_PASS OFF)
if(${BUILD_opencv_world})
foreach(m ${OPENCV_MODULES_BUILD})
set(the_module "${m}")
if("${m}" STREQUAL opencv_world)
add_subdirectory("${OPENCV_MODULE_opencv_world_LOCATION}" "${CMAKE_CURRENT_BINARY_DIR}/world")
elseif(NOT OPENCV_MODULE_${m}_IS_PART_OF_WORLD AND NOT ${m} STREQUAL opencv_world)
message(STATUS "Processing module ${m}...")
if(m MATCHES "^opencv_")
string(REGEX REPLACE "^opencv_" "" __shortname "${m}")
add_subdirectory("${OPENCV_MODULE_${m}_LOCATION}" "${CMAKE_CURRENT_BINARY_DIR}/${__shortname}")
else()
message(WARNING "Check module name: ${m}")
add_subdirectory("${OPENCV_MODULE_${m}_LOCATION}" "${CMAKE_CURRENT_BINARY_DIR}/${m}")
endif()
endif()
endforeach()
else()
foreach(m ${OPENCV_MODULES_BUILD})
set(the_module "${m}")
if(m MATCHES "^opencv_")
string(REGEX REPLACE "^opencv_" "" __shortname "${m}")
add_subdirectory("${OPENCV_MODULE_${m}_LOCATION}" "${CMAKE_CURRENT_BINARY_DIR}/${__shortname}")
else()
message(WARNING "Check module name: ${m}")
add_subdirectory("${OPENCV_MODULE_${m}_LOCATION}" "${CMAKE_CURRENT_BINARY_DIR}/${m}")
endif()
endforeach()
endif()
unset(__shortname)
_add_modules_2(${OPENCV_MODULES_BUILD})
endmacro()

View File

@ -116,15 +116,36 @@ macro(_ocv_fix_target target_var)
endif()
endmacro()
function(ocv_is_opencv_directory result_var dir)
get_filename_component(__abs_dir "${dir}" ABSOLUTE)
if("${__abs_dir}" MATCHES "^${OpenCV_SOURCE_DIR}"
OR "${__abs_dir}" MATCHES "^${OpenCV_BINARY_DIR}"
OR (OPENCV_EXTRA_MODULES_PATH AND "${__abs_dir}" MATCHES "^${OPENCV_EXTRA_MODULES_PATH}"))
set(${result_var} 1 PARENT_SCOPE)
else()
set(${result_var} 0 PARENT_SCOPE)
# check if "sub" (file or dir) is below "dir"
function(is_subdir res dir sub )
get_filename_component(dir "${dir}" ABSOLUTE)
get_filename_component(sub "${sub}" ABSOLUTE)
file(TO_CMAKE_PATH "${dir}" dir)
file(TO_CMAKE_PATH "${sub}" sub)
set(dir "${dir}/")
string(LENGTH "${dir}" len)
string(LENGTH "${sub}" len_sub)
if(NOT len GREATER len_sub)
string(SUBSTRING "${sub}" 0 ${len} prefix)
endif()
if(prefix AND prefix STREQUAL dir)
set(${res} TRUE PARENT_SCOPE)
else()
set(${res} FALSE PARENT_SCOPE)
endif()
endfunction()
function(ocv_is_opencv_directory result_var dir)
set(result FALSE)
foreach(parent ${OpenCV_SOURCE_DIR} ${OpenCV_BINARY_DIR} ${OPENCV_EXTRA_MODULES_PATH})
is_subdir(result "${parent}" "${dir}")
if(result)
break()
endif()
endforeach()
set(${result_var} ${result} PARENT_SCOPE)
endfunction()
@ -688,7 +709,7 @@ endif() # NOT DEFINED CMAKE_ARGC
# EXCLUSIVE: break after first successful condition
#
# Usage:
# ocv_build_features_string(out [EXLUSIVE] [IF feature THEN title] ... [ELSE title])
# ocv_build_features_string(out [EXCLUSIVE] [IF feature THEN title] ... [ELSE title])
#
function(ocv_build_features_string out)
set(result)
@ -807,6 +828,23 @@ macro(ocv_list_pop_front LST VAR)
endif()
endmacro()
# Get list of duplicates in the list of input items.
# ocv_get_duplicates(<output list> <element> [<element> ...])
function(ocv_get_duplicates res)
if(ARGC LESS 2)
message(FATAL_ERROR "Invalid call to ocv_get_duplicates")
endif()
set(lst ${ARGN})
list(SORT lst)
set(prev_item)
foreach(item ${lst})
if(item STREQUAL prev_item)
list(APPEND dups ${item})
endif()
set(prev_item ${item})
endforeach()
set(${res} ${dups} PARENT_SCOPE)
endfunction()
# simple regex escaping routine (does not cover all cases!!!)
macro(ocv_regex_escape var regex)

View File

@ -4,7 +4,7 @@ if(NOT OPENCV_MODULES_PATH)
set(OPENCV_MODULES_PATH "${CMAKE_CURRENT_SOURCE_DIR}")
endif()
ocv_glob_modules(${OPENCV_MODULES_PATH} EXTRA ${OPENCV_EXTRA_MODULES_PATH})
ocv_glob_modules(${OPENCV_MODULES_PATH} ${OPENCV_EXTRA_MODULES_PATH})
# build lists of modules to be documented
set(OPENCV_MODULES_MAIN "")