Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 67 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
cmake_minimum_required(VERSION 3.0)
project(GeneralizedDistanceTransform)


# Settings --------------------------------------------------------------------

option(ENABLE_TESTING "Compile tests")
option(ENABLE_PYTHON "Generate a python wrapper")
set(PYTHON_VERSION "" CACHE STRING "Desired python version for the bindings")

list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -O0 -Wall")


# Dependencies ----------------------------------------------------------------

find_package(OpenCV REQUIRED)
include(cmake/CPPyModule.cmake)


# Targets ---------------------------------------------------------------------

# C++ Library
add_library(gendistrans SHARED
gendistrans/src/gendistrans.cpp)
target_include_directories(gendistrans PUBLIC
${OpenCV_INCLUDE_DIRS}
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/gendistrans/include>
$<INSTALL_INTERFACE:include/gendistrans>)
target_link_libraries(gendistrans
${OpenCV_LIBS})
set_property(TARGET gendistrans
PROPERTY INTERFACE_POSITION_INDEPENDENT_CODE ON)

# Python module
if(${ENABLE_PYTHON})
as_python_module(gendistrans_py
NAMESPACE cv # C++ code is written as if it was an OpenCV module
MODULE_NAME gendistrans # but we cannot reuse the cv2 module name
# Library source files are alread formated as wrappers
HEADERS gendistrans/include/opencv2/gendistrans.hpp
# Add the whole source code to the module (standalone module)
SOURCES gendistrans/src/gendistrans.cpp)
# No linking because all source files have been put into the module
target_include_directories(gendistrans_py PUBLIC
${OpenCV_INCLUDE_DIRS}
gendistrans/include)
endif()


# Install ---------------------------------------------------------------------



# Testing ---------------------------------------------------------------------

if(${ENABLE_TESTING})
enable_testing()

add_executable(dontcrash
tests/dontcrash.cpp)
target_link_libraries(dontcrash
${OpenCV_LIBS}
gendistrans)
add_test(test_dontcrash
dontcrash)
endif()
138 changes: 138 additions & 0 deletions cmake/CPPyModule.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
# author: Nicolas Granger <[email protected]>


set(this_file_directory ${CMAKE_CURRENT_LIST_DIR})

include(CMakeParseArguments)
find_package(OpenCV REQUIRED)
find_package(PythonLibs REQUIRED)


function(as_python_module TARGET_NAME)
# as_python_module(<target>
# NAMESPACE namespace
# [MODULE_NAME module]
# HEADERS file1.hpp [file2.hpp ...]
# [SOURCES file1.cpp [file2.cpp ...]])
#
# `as_python_module` creates a binary python module from C++ source files. It
# relies on the header parsing tools from the OpenCV project, and thus uses
# the same conventions (TODO: add link to the conventions).
# The cmake target is specified as the first argument.
# For technical reasons, it is mandatory to pack up the exported items
# in one named namespace which is specified by NAMESPACE. Note that nested
# namespaces are automatically converted to submodules.
# `MODULE_NAME` specifies the name of the python module, and determines the name
# of the resulting file (the extension depends on the plateform), by default,
# the namespace name is used.
# HEADERS is a list of header files to parse in order to find exported items.
# SOURCES specifies source files that should be compiled in the library.
#
# Warning: Because of the way the code generation works, you may have unused
# compilation warning (unused functions for example) and symbol collisions
# (rather unlikely considering the names).
#
# Note 1: This resulting target is generated by an add_library call. Thus
# compilation features and target properties may be used as for any other
# library.
#
# Note 2: if you wish to set the version of the python libraries, use this:
# set(Python_ADDITIONAL_VERSIONS "3.4")
# if(NOT ("${ARG_PYVER}" STREQUAL "")
# AND NOT ("${PYTHONLIBS_VERSION_STRING}" MATCHES "^${ARG_PYVER}*"))
# message(FATAL_ERROR "Python version ${PYVER} was not found (note: \
# found ${PYTHON_VERSION_STRING}).")
# endif()

# Parse arguments ---------------------------------------------------------

set(options)
set(oneValueArgs NAMESPACE MODULE_NAME)
set(multiValueArgs HEADERS SOURCES)
cmake_parse_arguments(ARG
"${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
if("${ARG_NAMESPACE}" STREQUAL "")
message(FATAL_ERROR "NAMESPACE argument not specified")
endif()
if("${ARG_MODULE_NAME}" STREQUAL "")
set(ARG_MODULE_NAME ${ARG_NAMESPACE})
endif()

# Source code generation --------------------------------------------------

# List header files in headers.txt
set(gen_files_path ${CMAKE_CURRENT_BINARY_DIR}/${ARG_MODULE_NAME})
file(MAKE_DIRECTORY ${gen_files_path})
file(WRITE ${gen_files_path}/headers.txt "${ARG_HEADERS}")

# Parse headers and generate python bindings
add_custom_command(
OUTPUT ${gen_files_path}/pyopencv_generated_include.h
${gen_files_path}/pyopencv_generated_funcs.h
${gen_files_path}/pyopencv_generated_ns_reg.h
${gen_files_path}/pyopencv_generated_type_reg.h
${gen_files_path}/pyopencv_generated_types.h
DEPENDS ${ARG_HEADERS}
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
COMMAND ${this_file_directory}/bin/gen2.py
${gen_files_path}
${gen_files_path}/headers.txt
${ARG_NAMESPACE}
${ARG_MODULE_NAME})

# Make a target for cmake
add_custom_target(${TARGET_NAME}_generated_headers
DEPENDS ${gen_files_path}/pyopencv_generated_include.h
${gen_files_path}/pyopencv_generated_funcs.h
${gen_files_path}/pyopencv_generated_ns_reg.h
${gen_files_path}/pyopencv_generated_type_reg.h
${gen_files_path}/pyopencv_generated_types.h)

# Copy additional sources
file(COPY ${this_file_directory}/src/module.cpp
${this_file_directory}/src/pycompat.hpp
${this_file_directory}/src/py_cv_converters.hpp
${this_file_directory}/src/utils.hpp
DESTINATION ${gen_files_path})
configure_file(${this_file_directory}/src/init_func.cpp.in
${gen_files_path}/init_func.cpp)

# Module compilation ------------------------------------------------------

add_library(${TARGET_NAME} SHARED
${gen_files_path}/module.cpp
${ARG_SOURCES})

add_dependencies(${TARGET_NAME} ${TARGET_NAME}_generated_headers)

set_property(TARGET ${TARGET_NAME}
PROPERTY INTERFACE_POSITION_INDEPENDENT_CODE ON)
target_compile_features(${TARGET_NAME} PRIVATE cxx_long_long_type)

# Note: the module needn't provide a header, python opens the library
# and looks for internal symbols to find the entry point (namely the
# PyInit_<modulename> function)
target_include_directories(${TARGET_NAME} PRIVATE
${CMAKE_CURRENT_SOURCE_DIR} # parsed headers may have relative path
${gen_files_path}
${PYTHON_INCLUDE_DIRS}
${OpenCV_INCLUDE_DIRS})

target_link_libraries(${TARGET_NAME}
${PYTHON_LIBRARIES}
${OpenCV_LIBS})

# Output file name --------------------------------------------------------

if(WIN32 AND NOT CYGWIN)
set(module_extension ".pyd")
else()
set(module_extension ".so")
endif()
set_target_properties(${TARGET_NAME} PROPERTIES
PREFIX ""
OUTPUT_NAME ${ARG_MODULE_NAME}
EXTENSION ${module_extension})

endfunction()

Loading