opencv/modules/matlab/CMakeLists.txt
Michael Pratt cac1218eef Build both Python 2 and Python 3 bindings
If both Python 2 and Python 3 are found, then build bindings for both of
them during the build process.  Currently, one version of Python is
detected automatically, and building for the other requires changes the
CMake config.

The largest chunk of this change generalizes OpenCVDetectPython.cmake to
find both a Python 2 and Python 3 version of Python.  Secondly, the
opencv_python module is split into two modules, opencv_python2 and
opencv_python3.  Both are built from the same source. but for different
versions of Python.
2014-06-29 20:08:13 -04:00

312 lines
13 KiB
CMake

# ----------------------------------------------------------------------------
# CMake file for Matlab/Octave support
#
# Matlab code generation and compilation is broken down into two distinct
# stages: configure time and build time. The idea is that we want to give
# the user reasonable guarantees that once they type 'make', wrapper
# generation is unlikely to fail. Therefore we run a series of tests at
# configure time to check the working status of the core components.
#
# Configure Time
# During configure time, the script attempts to ascertain whether the
# generator and mex compiler are working for a given architecture.
# Currently this involves:
# 1) Generating a simple CV_EXPORTS_W symbol and checking whether a file
# of the symbol name is generated
# 2) Compiling a simple mex gateway to check that Bridge.hpp and mex.h
# can be found, and that a file with the mexext is produced
#
# Build Time
# If the configure time tests pass, then we assume Matlab wrapper generation
# will not fail during build time. We simply glob all of the symbols in
# the OpenCV module headers, generate intermediate .cpp files, then compile
# them with mex.
# ----------------------------------------------------------------------------
# PREPEND
# Given a list of strings IN and a TOKEN, prepend the token to each string
# and append to OUT. This is used for passing command line "-I", "-L" and "-l"
# arguments to mex. e.g.
# prepend("-I" OUT /path/to/include/dir) --> -I/path/to/include/dir
macro(PREPEND TOKEN OUT IN)
foreach(VAR ${IN} ${ARGN})
list(APPEND ${OUT} "${TOKEN}${VAR}")
endforeach()
endmacro()
# WARN_MIXED_PRECISION
# Formats a warning message if the compiler and Matlab bitness is different
macro(WARN_MIXED_PRECISION COMPILER_BITNESS MATLAB_BITNESS)
set(MSG "Your compiler is ${COMPILER_BITNESS}-bit")
set(MSG "${MSG} but your version of Matlab is ${MATLAB_BITNESS}-bit.")
set(MSG "${MSG} To build Matlab bindings, please switch to a ${MATLAB_BITNESS}-bit compiler.")
message(WARNING ${MSG})
endmacro()
# ----------------------------------------------------------------------------
# Architecture checks
# ----------------------------------------------------------------------------
# make sure we're on a supported architecture with Matlab and python installed
if (IOS OR ANDROID OR NOT MATLAB_FOUND)
ocv_module_disable(matlab)
return()
elseif (NOT PYTHON_DEFAULT_AVAILABLE)
message(WARNING "A required dependency of the matlab module (PythonLibs) was not found. Disabling Matlab bindings...")
ocv_module_disable(matlab)
return()
endif()
# If the user built OpenCV as X-bit, but they have a Y-bit version of Matlab,
# attempting to link to OpenCV during binding generation will fail, since
# mixed precision pointers are not allowed. Disable the bindings.
math(EXPR ARCH "${CMAKE_SIZEOF_VOID_P} * 8")
if (${ARCH} EQUAL 32 AND ${MATLAB_ARCH} MATCHES "64")
warn_mixed_precision("32" "64")
ocv_module_disable(matlab)
return()
elseif (${ARCH} EQUAL 64 AND NOT ${MATLAB_ARCH} MATCHES "64")
warn_mixed_precision("64" "32")
ocv_module_disable(matlab)
return()
endif()
# If it's MSVC, warn the user that bindings will only be built in Release mode.
# Debug mode seems to cause issues...
if (MSVC)
message(STATUS "Warning: Matlab bindings will only be built in Release configurations")
endif()
# ----------------------------------------------------------------------------
# Configure time components
# ----------------------------------------------------------------------------
set(the_description "The Matlab/Octave bindings")
ocv_add_module(matlab BINDINGS
OPTIONAL opencv_core
opencv_imgproc opencv_ml opencv_highgui
opencv_objdetect opencv_flann opencv_features2d
opencv_photo opencv_video opencv_videostab
opencv_calib opencv_calib3d
opencv_stitching opencv_superres
opencv_nonfree
)
# get the commit information
execute_process(COMMAND git log -1 --pretty=%H OUTPUT_VARIABLE GIT_COMMIT ERROR_QUIET)
string(REGEX REPLACE "(\r?\n)+$" "" GIT_COMMIT "${GIT_COMMIT}")
# set the path to the C++ header and doc parser, and template engine
set(JINJA2_PATH ${CMAKE_SOURCE_DIR}/3rdparty)
set(HDR_PARSER_PATH ${CMAKE_SOURCE_DIR}/modules/python/src2)
set(RST_PARSER_PATH ${CMAKE_SOURCE_DIR}/modules/java/generator)
# set mex compiler options
prepend("-I" MEX_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/include)
if (MSVC)
prepend("-L" MEX_LIB_DIR ${LIBRARY_OUTPUT_PATH}/${CMAKE_CFG_INTDIR})
else()
prepend("-L" MEX_LIB_DIR ${LIBRARY_OUTPUT_PATH})
endif()
set(MEX_OPTS "-largeArrayDims")
if (BUILD_TESTS)
add_subdirectory(test)
endif()
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include)
# intersection of available modules and optional dependencies
# 1. populate the command-line include directories (-I/path/to/module/header, ...)
# 2. populate the command-line link libraries (-lopencv_core, ...) for Debug and Release
set(MATLAB_DEPS ${OPENCV_MODULE_${the_module}_REQ_DEPS} ${OPENCV_MODULE_${the_module}_OPT_DEPS})
foreach(opencv_module ${MATLAB_DEPS})
if (HAVE_${opencv_module})
string(REPLACE "opencv_" "" module ${opencv_module})
list(APPEND opencv_modules ${module})
list(APPEND ${the_module}_ACTUAL_DEPS ${opencv_module})
prepend("-I" MEX_INCLUDE_DIRS "${OPENCV_MODULE_${opencv_module}_LOCATION}/include")
prepend("-l" MEX_LIBS ${opencv_module}${OPENCV_DLLVERSION})
prepend("-l" MEX_DEBUG_LIBS ${opencv_module}${OPENCV_DLLVERSION}${OPENCV_DEBUG_POSTFIX})
endif()
endforeach()
# add extra headers by hand
list(APPEND opencv_extra_hdrs "core=${OPENCV_MODULE_opencv_core_LOCATION}/include/opencv2/core/base.hpp")
list(APPEND opencv_extra_hdrs "video=${OPENCV_MODULE_opencv_video_LOCATION}/include/opencv2/video/tracking.hpp")
# pass the OPENCV_CXX_EXTRA_FLAGS through to the mex compiler
# remove the visibility modifiers, so the mex gateway is visible
# TODO: get mex working without warnings
string(REGEX REPLACE "[^\ ]*visibility[^\ ]*" "" MEX_CXXFLAGS "${OPENCV_EXTRA_FLAGS} ${OPENCV_EXTRA_CXX_FLAGS}")
# Configure checks
# Check to see whether the generator and the mex compiler are working.
# The checks currently test:
# - whether the python generator can be found
# - whether the python generator correctly outputs a file for a definition
# - whether the mex compiler can find the required headers
# - whether the mex compiler can compile a trivial definition
if (NOT MEX_WORKS)
# attempt to generate a gateway for a function
message(STATUS "Trying to generate Matlab code")
execute_process(
COMMAND ${PYTHON_DEFAULT_EXECUTABLE}
${CMAKE_CURRENT_SOURCE_DIR}/generator/gen_matlab.py
--jinja2 ${JINJA2_PATH}
--hdrparser ${HDR_PARSER_PATH}
--rstparser ${RST_PARSER_PATH}
--extra "test=${CMAKE_CURRENT_SOURCE_DIR}/test/test_generator.hpp"
--outdir ${CMAKE_BINARY_DIR}/junk
ERROR_VARIABLE GEN_ERROR
OUTPUT_QUIET
)
if (GEN_ERROR)
message(${GEN_ERROR})
message(STATUS "Error generating Matlab code. Disabling Matlab bindings...")
ocv_module_disable(matlab)
return()
else()
message(STATUS "Trying to generate Matlab code - OK")
endif()
# attempt to compile a gateway using mex
message(STATUS "Trying to compile mex file")
execute_process(
COMMAND ${MATLAB_MEX_SCRIPT} ${MEX_OPTS} "CXXFLAGS=\$CXXFLAGS ${MEX_CXX_FLAGS}"
${MEX_INCLUDE_DIRS} ${CMAKE_CURRENT_SOURCE_DIR}/test/test_compiler.cpp
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/junk
ERROR_VARIABLE MEX_ERROR
OUTPUT_QUIET
)
if (MEX_ERROR)
message(${MEX_ERROR})
message(STATUS "Error compiling mex file. Disabling Matlab bindings...")
ocv_module_disable(matlab)
return()
else()
message(STATUS "Trying to compile mex file - OK")
endif()
endif()
# if we make it here, mex works!
set(MEX_WORKS True CACHE BOOL ADVANCED)
# ----------------------------------------------------------------------------
# Build time components
# ----------------------------------------------------------------------------
# proxies
# these proxies are used to trigger the add_custom_commands
# (which do the real work) only when they're outdated
set(GENERATE_PROXY ${CMAKE_CURRENT_BINARY_DIR}/generate.proxy)
set(COMPILE_PROXY ${CMAKE_CURRENT_BINARY_DIR}/compile.proxy)
# TODO: Remove following line before merging with master
file(REMOVE ${GENERATE_PROXY} ${COMPILE_PROXY})
# generate
# call the python executable to generate the Matlab gateways
add_custom_command(
OUTPUT ${GENERATE_PROXY}
COMMAND ${PYTHON_DEFAULT_EXECUTABLE}
${CMAKE_CURRENT_SOURCE_DIR}/generator/gen_matlab.py
--jinja2 ${JINJA2_PATH}
--hdrparser ${HDR_PARSER_PATH}
--rstparser ${RST_PARSER_PATH}
--moduleroot ${CMAKE_SOURCE_DIR}/modules
--modules ${opencv_modules}
--extra ${opencv_extra_hdrs}
--outdir ${CMAKE_CURRENT_BINARY_DIR}
COMMAND ${PYTHON_DEFAULT_EXECUTABLE}
${CMAKE_CURRENT_SOURCE_DIR}/generator/build_info.py
--jinja2 ${JINJA2_PATH}
--os ${CMAKE_SYSTEM}
--arch ${ARCH} ${CMAKE_SYSTEM_PROCESSOR}
--compiler ${CMAKE_CXX_COMPILER_ID} ${CMAKE_CXX_COMPILER_VERSION}
--mex_arch ${MATLAB_ARCH}
--mex_script ${MATLAB_MEX_SCRIPT}
--cxx_flags ${MEX_CXXFLAGS}
--opencv_version ${OPENCV_VERSION}
--commit ${GIT_COMMIT}
--modules ${opencv_modules}
--configuration $<CONFIGURATION>
--outdir ${CMAKE_CURRENT_BINARY_DIR}
COMMAND ${PYTHON_DEFAULT_EXECUTABLE}
${CMAKE_CURRENT_SOURCE_DIR}/generator/cvmex.py
--jinja2 ${JINJA2_PATH}
--opts="${MEX_OPTS}"
--include_dirs="${MEX_INCLUDE_DIRS}"
--lib_dir="${MEX_LIB_DIR}"
--libs="${MEX_LIBS}"
--flags ${MEX_CXXFLAGS}
--outdir ${CMAKE_CURRENT_BINARY_DIR}
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/test/help.m ${CMAKE_CURRENT_BINARY_DIR}/+cv
COMMAND ${CMAKE_COMMAND} -E touch ${GENERATE_PROXY}
COMMENT "Generating Matlab source files"
)
# compile
# call the mex compiler to compile the gateways
# because we don't know the source files at configure-time, this
# has to be executed in a separate script in cmake's script processing mode
add_custom_command(
OUTPUT ${COMPILE_PROXY}
COMMAND ${CMAKE_COMMAND} -DMATLAB_MEX_SCRIPT=${MATLAB_MEX_SCRIPT}
-DMATLAB_MEXEXT=${MATLAB_MEXEXT}
-DMEX_OPTS=${MEX_OPTS}
-DMEX_CXXFLAGS=${MEX_CXX_FLAGS}
-DMEX_INCLUDE_DIRS="${MEX_INCLUDE_DIRS}"
-DMEX_LIB_DIR="${MEX_LIB_DIR}"
-DCONFIGURATION="$<CONFIGURATION>"
-DMEX_LIBS="${MEX_LIBS}"
-DMEX_DEBUG_LIBS="${MEX_DEBUG_LIBS}"
-P ${CMAKE_CURRENT_SOURCE_DIR}/compile.cmake
COMMAND ${CMAKE_COMMAND} -E touch ${COMPILE_PROXY}
COMMENT "Compiling Matlab source files. This could take a while..."
)
# targets
# opencv_matlab_sources --> opencv_matlab
add_custom_target(${the_module}_sources ALL DEPENDS ${GENERATE_PROXY})
add_custom_target(${the_module} ALL DEPENDS ${COMPILE_PROXY})
add_dependencies(${the_module} ${the_module}_sources ${${the_module}_ACTUAL_DEPS})
if (ENABLE_SOLUTION_FOLDERS)
set_target_properties(${the_module} PROPERTIES FOLDER "modules")
endif()
# ----------------------------------------------------------------------------
# Install time components
# ----------------------------------------------------------------------------
# NOTE: Trailing slashes on the DIRECTORY paths are important!
# TODO: What needs to be done with rpath????
# install the +cv directory verbatim
install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/include/ DESTINATION ${OPENCV_INCLUDE_INSTALL_PATH})
install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/+cv/ DESTINATION matlab/+cv)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/cv.m DESTINATION matlab)
# update the custom mex compiler to point to the install locations
string(REPLACE ";" "\\ " MEX_OPTS "${MEX_OPTS}")
string(REPLACE ";" "\\ " MEX_LIBS "${MEX_LIBS}")
string(REPLACE " " "\\ " MEX_CXXFLAGS ${MEX_CXXFLAGS})
string(REPLACE ";" "\\ " MEX_INCLUDE_DIRS "${MEX_INCLUDE_DIRS}")
install(CODE
"execute_process(
COMMAND ${PYTHON_DEFAULT_EXECUTABLE}
${CMAKE_CURRENT_SOURCE_DIR}/generator/cvmex.py
--jinja2 ${JINJA2_PATH}
--opts=${MEX_OPTS}
--include_dirs=-I${CMAKE_INSTALL_PREFIX}/${OPENCV_INCLUDE_INSTALL_PATH}
--lib_dir=-L${CMAKE_INSTALL_PREFIX}/${OPENCV_LIB_INSTALL_PATH}
--libs=${MEX_LIBS}
--flags=${MEX_CXXFLAGS}
--outdir ${CMAKE_INSTALL_PREFIX}/matlab
)"
)