improve cmake Cython wrapper scripts to be usable in other projects

release/4.3a0
Duy-Nguyen Ta 2016-12-16 00:26:03 -05:00
parent f154be176f
commit 70552e9f6d
3 changed files with 46 additions and 45 deletions

View File

@ -18,6 +18,7 @@ install(FILES
GtsamMakeConfigFile.cmake GtsamMakeConfigFile.cmake
GtsamMatlabWrap.cmake GtsamMatlabWrap.cmake
GtsamPythonWrap.cmake GtsamPythonWrap.cmake
GtsamCythonWrap.cmake
GtsamTesting.cmake GtsamTesting.cmake
README.html README.html
DESTINATION "${SCRIPT_INSTALL_DIR}/GTSAMCMakeTools") DESTINATION "${SCRIPT_INSTALL_DIR}/GTSAMCMakeTools")

View File

@ -4,76 +4,72 @@ if(NOT GTSAM_CYTHON_INSTALL_PATH)
set(GTSAM_CYTHON_INSTALL_PATH "${CMAKE_INSTALL_PREFIX}/gtsam_cython") set(GTSAM_CYTHON_INSTALL_PATH "${CMAKE_INSTALL_PREFIX}/gtsam_cython")
endif() endif()
# User-friendly wrapping function. Builds a mex module from the provided # User-friendly Cython wrapping and installing function.
# interfaceHeader. For example, for the interface header gtsam.h, # Builds a Cython module from the provided interface_header.
# For example, for the interface header gtsam.h,
# this will build the wrap module 'gtsam'. # this will build the wrap module 'gtsam'.
# #
# Arguments: # Arguments:
# #
# interfaceHeader: The relative path to the wrapper interface definition file. # interface_header: The relative path to the wrapper interface definition file.
# linkLibraries: Any *additional* libraries to link. Your project library # extra_imports: extra header to import in the Cython pxd file.
# (e.g. `lba`), libraries it depends on, and any necessary # For example, to use Cython gtsam.pxd in your own module,
# MATLAB libraries will be linked automatically. So normally, # use "from gtsam cimport *"
# leave this empty. # setup_py_in_path: Path to the setup.py.in config file, which will be converted
# extraIncludeDirs: Any *additional* include paths required by dependent # to setup.py file by cmake and used to compile the Cython module
# libraries that have not already been added by # by invoking "python setup.py build_ext --inplace"
# include_directories. Again, normally, leave this empty. # install_path: destination to install the library
function(wrap_and_install_library_cython interfaceHeader linkLibraries extraIncludeDirs) function(wrap_and_install_library_cython interface_header extra_imports setup_py_in_path install_path)
wrap_library_internal_cython("${interfaceHeader}" "${linkLibraries}" "${extraIncludeDirs}") # Paths for generated files
install_wrapped_library_internal_cython("${interfaceHeader}") get_filename_component(module_name "${interface_header}" NAME_WE)
set(generated_files_path "${PROJECT_BINARY_DIR}/cython/${module_name}")
wrap_library_cython("${interface_header}" "${generated_files_path}" "${extra_imports}" "${setup_py_in_path}")
install_cython_wrapped_library("${interface_header}" "${generated_files_path}" "${install_path}")
endfunction() endfunction()
# Internal function that wraps a library and compiles the wrapper # Internal function that wraps a library and compiles the wrapper
function(wrap_library_internal_cython interfaceHeader linkLibraries extraIncludeDirs) function(wrap_library_cython interface_header generated_files_path extra_imports setup_py_in_path)
# Wrap codegen interface # Wrap codegen interface
#usage: wrap --cython interfacePath moduleName toolboxPath headerPath # Extract module path and name from interface header file name
# interfacePath : *absolute* path to directory of module interface file get_filename_component(interface_header "${interface_header}" ABSOLUTE)
# moduleName : the name of the module, interface file must be called moduleName.h get_filename_component(module_path "${interface_header}" PATH)
# toolboxPath : the directory in which to generate the wrappers get_filename_component(module_name "${interface_header}" NAME_WE)
# headerPath : path to matlab.h
# Extract module name from interface header file name set(generated_cpp_file "${generated_files_path}/${module_name}.cpp")
get_filename_component(interfaceHeader "${interfaceHeader}" ABSOLUTE)
get_filename_component(modulePath "${interfaceHeader}" PATH)
get_filename_component(moduleName "${interfaceHeader}" NAME_WE)
# Paths for generated files message(STATUS "Building wrap module ${module_name}")
set(generated_files_path "${PROJECT_BINARY_DIR}/cython/${moduleName}")
set(generated_cpp_file "${generated_files_path}/${moduleName}.cpp")
message(STATUS "Building wrap module ${moduleName}")
# Set up generation of module source file # Set up generation of module source file
file(MAKE_DIRECTORY "${generated_files_path}") file(MAKE_DIRECTORY "${generated_files_path}")
configure_file(../cython/setup.py.in ${generated_files_path}/setup.py) configure_file(${setup_py_in_path}/setup.py.in ${generated_files_path}/setup.py)
add_custom_command( add_custom_command(
OUTPUT ${generated_cpp_file} OUTPUT ${generated_cpp_file}
DEPENDS ${interfaceHeader} wrap ${module_library_target} DEPENDS ${interface_header} wrap
COMMAND COMMAND
wrap --cython wrap --cython
${modulePath} ${module_path}
${moduleName} ${module_name}
${generated_files_path} ${generated_files_path}
. "${extra_imports}"
&& python setup.py build_ext --inplace && python setup.py build_ext --inplace
VERBATIM VERBATIM
WORKING_DIRECTORY ${generated_files_path}) WORKING_DIRECTORY ${generated_files_path})
# Set up building of mex module # Set up building of mex module
add_custom_target(${moduleName}_cython_wrapper ALL DEPENDS ${generated_cpp_file} ${interfaceHeader}) add_custom_target(${module_name}_cython_wrapper ALL DEPENDS ${generated_cpp_file} ${interface_header})
add_custom_target(wrap_${moduleName}_cython_distclean add_custom_target(wrap_${module_name}_cython_distclean
COMMAND cmake -E remove_directory ${generated_files_path}) COMMAND cmake -E remove_directory ${generated_files_path})
endfunction() endfunction()
# Internal function that installs a wrap toolbox # Internal function that installs a wrap toolbox
function(install_wrapped_library_internal_cython interfaceHeader) function(install_cython_wrapped_library interface_header generated_files_path install_path)
get_filename_component(moduleName "${interfaceHeader}" NAME_WE) get_filename_component(module_name "${interface_header}" NAME_WE)
set(generated_files_path "${PROJECT_BINARY_DIR}/cython/${moduleName}")
# NOTE: only installs .pxd and .pyx and binary files (not .cpp) - the trailing slash on the directory name # NOTE: only installs .pxd and .pyx and binary files (not .cpp) - the trailing slash on the directory name
# here prevents creating the top-level module name directory in the destination. # here prevents creating the top-level module name directory in the destination.
message(STATUS "Installing Cython Toolbox to ${GTSAM_CYTHON_INSTALL_PATH}") message(STATUS "Installing Cython Toolbox to ${install_path}") #${GTSAM_CYTHON_INSTALL_PATH}")
message(generated_files_path: "${generated_files_path}")
if(GTSAM_BUILD_TYPE_POSTFIXES) if(GTSAM_BUILD_TYPE_POSTFIXES)
foreach(build_type ${CMAKE_CONFIGURATION_TYPES}) foreach(build_type ${CMAKE_CONFIGURATION_TYPES})
string(TOUPPER "${build_type}" build_type_upper) string(TOUPPER "${build_type}" build_type_upper)
@ -83,9 +79,9 @@ function(install_wrapped_library_internal_cython interfaceHeader)
set(build_type_tag "${build_type}") set(build_type_tag "${build_type}")
endif() endif()
# Split up filename to strip trailing '/' in GTSAM_CYTHON_INSTALL_PATH if there is one # Split up filename to strip trailing '/' in GTSAM_CYTHON_INSTALL_PATH if there is one
get_filename_component(location "${GTSAM_CYTHON_INSTALL_PATH}" PATH) get_filename_component(location "${install_path}" PATH)
get_filename_component(name "${GTSAM_CYTHON_INSTALL_PATH}" NAME) get_filename_component(name "${install_path}" NAME)
install(DIRECTORY "${generated_files_path}/../" DESTINATION "${location}/${name}${build_type_tag}" install(DIRECTORY "${generated_files_path}/" DESTINATION "${location}/${name}${build_type_tag}"
CONFIGURATIONS "${build_type}" CONFIGURATIONS "${build_type}"
PATTERN "build" EXCLUDE PATTERN "build" EXCLUDE
PATTERN "CMakeFiles" EXCLUDE PATTERN "CMakeFiles" EXCLUDE
@ -95,7 +91,7 @@ function(install_wrapped_library_internal_cython interfaceHeader)
PATTERN "*.py" EXCLUDE) PATTERN "*.py" EXCLUDE)
endforeach() endforeach()
else() else()
install(DIRECTORY "${generated_files_path}/../" DESTINATION ${GTSAM_CYTHON_INSTALL_PATH} install(DIRECTORY "${generated_files_path}/" DESTINATION ${install_path}
PATTERN "build" EXCLUDE PATTERN "build" EXCLUDE
PATTERN "CMakeFiles" EXCLUDE PATTERN "CMakeFiles" EXCLUDE
PATTERN "Makefile" EXCLUDE PATTERN "Makefile" EXCLUDE

View File

@ -172,5 +172,9 @@ if (GTSAM_INSTALL_CYTHON_TOOLBOX)
include(GtsamCythonWrap) include(GtsamCythonWrap)
# Wrap # Wrap
wrap_and_install_library_cython(../cython/gtsam.h "${GTSAM_ADDITIONAL_LIBRARIES}" "") wrap_and_install_library_cython("../cython/gtsam.h" # interface_header
"" # extra imports
"../cython" # path to setup.py.in
"${GTSAM_CYTHON_INSTALL_PATH}/gtsam" # install path
)
endif () endif ()