# Define a function to create Cython modules. # # For more information on the Cython project, see http://cython.org/. # "Cython is a language that makes writing C extensions for the Python language # as easy as Python itself." # # This file defines a CMake function to build a Cython Python module. # To use it, first include this file. # # include( UseCython ) # # Then call cython_add_module to create a module. # # cython_add_module( ... ) # # Where is the import path for the resulting Python module # (e.g. mymodule.submodule.other_submodule.this_extension), # is the desired name of the target that runs the Cython compiler # to generate the needed C or C++ files, and ... are additional source files # to be compiled with the C or C++ file created by Cython. # The Cython file to be built is found using the . # is also used as the name of the target for the desired Python module. # A list of output files is provided as the attribute # of the target corresponding to the Cython compilation call. # # Cache variables that effect the behavior include: # # CYTHON_ANNOTATE # CYTHON_NO_DOCSTRINGS # CYTHON_FLAGS # # Source file properties that effect the build process are # # CYTHON_IS_CXX # CYTHON_IS_PUBLIC # CYTHON_IS_API # # For a given Cython file, if CYTHON_IS_CXX is set (using set_source_files_properties) # Cython will output a C++ file. The CYTHON_IS_PUBLIC and CYTHON_IS_API variables # are used to provide the list of output files given in the # property of the target corresponding to the Cython call to build the needed # C/C++ source files. # # The Python modules created are written into the CMAKE_CURRENT_BINARY_DIR # with the same folder structure they have in your project. For example, # the module name mymodule.submodule.other_submodule.this_extension would # cause the target mymodule.submodule.other_submodule.this_extension to be created, # the file ${CMAKE_CURRENT_SOURCE_DIR}/mymodule/submodule/other_submodule/this_extension.pyx # would be used to build the desired module, and the Python module resulting from # the compilation would be written to # ${CMAKE_CURRENT_BINARY_DIR}/mymodule/submodule/other_submodule/this_extension.${ext} # where ${ext} is the file extension for Python extensions for the target platform # and Python version. # # See also FindCython.cmake #============================================================================= # Copyright 2011 Kitware, Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. #============================================================================= # Configuration options. set( CYTHON_ANNOTATE OFF CACHE BOOL "Create an annotated .html file when compiling *.pyx." ) set( CYTHON_NO_DOCSTRINGS OFF CACHE BOOL "Strip docstrings from the compiled module." ) set( CYTHON_FLAGS "" CACHE STRING "Extra flags to the cython compiler." ) mark_as_advanced( CYTHON_ANNOTATE CYTHON_NO_DOCSTRINGS CYTHON_FLAGS ) find_package( Cython REQUIRED ) find_package( PythonLibsNew REQUIRED ) set( CYTHON_CXX_EXTENSION "cxx" ) set( CYTHON_C_EXTENSION "c" ) # Create a *.c or *.cxx file from a *.pyx file. function( compile_pyx _name _pyx_target_name _module_name _directories _pyx_file) # Default to assuming all files are C. set( _cxx_arg "" ) set( _extension ${CYTHON_C_EXTENSION} ) # Make sure the output directory is created. file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${_directories}) # Determine if it is a C or C++ file. get_source_file_property( _is_cxx ${_pyx_file} CYTHON_IS_CXX ) if( ${_is_cxx} ) set( _cxx_arg "--cplus" ) set( _extension ${CYTHON_CXX_EXTENSION} ) endif() get_source_file_property( _pyx_location ${_pyx_file} LOCATION ) # Set additional flags. if( CYTHON_ANNOTATE ) set( _annotate_arg "--annotate" ) endif() if( CYTHON_NO_DOCSTRINGS ) set( _no_docstrings_arg "--no-docstrings" ) endif() if(NOT WIN32) if( "${CMAKE_BUILD_TYPE}" STREQUAL "Debug" OR "${CMAKE_BUILD_TYPE}" STREQUAL "RelWithDebInfo" ) set( _cython_debug_arg "--gdb" ) endif() endif() # Determining generated file names. get_source_file_property( _is_public ${_pyx_file} CYTHON_PUBLIC ) get_source_file_property( _is_api ${_pyx_file} CYTHON_API ) if( "${_is_api}" AND "${is_public}" ) set( _generated_files ${CMAKE_CURRENT_BINARY_DIR}/${_directories}/${_module_name}.${_extension} ${CMAKE_CURRENT_BINARY_DIR}/${_directories}/${_module_name}.h ${CMAKE_CURRENT_BINARY_DIR}/${_directories}/${_module_name}_api.h) elseif( "${_is_public}" ) set( _generated_files ${CMAKE_CURRENT_BINARY_DIR}/${_directories}/${_module_name}.${_extension} ${CMAKE_CURRENT_BINARY_DIR}/${_directories}/${_module_name}.h) elseif( "${_is_api}" ) set( _generated_files ${CMAKE_CURRENT_BINARY_DIR}/${_directories}/${_module_name}.${_extension} ${CMAKE_CURRENT_BINARY_DIR}/${_directories}/${_module_name}_api.h) else() set( _generated_files ${CMAKE_CURRENT_BINARY_DIR}/${_directories}/${_module_name}.${_extension}) endif() set_source_files_properties( ${_generated_files} PROPERTIES GENERATED TRUE ) set(_cython_command ${CYTHON_EXECUTABLE} ${_cxx_arg} ${_annotate_arg} ${_no_docstrings_arg} ${_cython_debug_arg} ${CYTHON_FLAGS} --timestamps --output-file "${CMAKE_CURRENT_BINARY_DIR}/${_directories}/${_module_name}.${_extension}" ${_pyx_location}) string(REPLACE ";" " " _cython_comment "${_cython_command}") # Add the command to run the compiler. add_custom_target(${_pyx_target_name} COMMAND ${_cython_command} DEPENDS ${_pyx_location} # do not specify byproducts for now since they don't work with the older # version of cmake available in the apt repositories. #BYPRODUCTS ${_generated_files} COMMENT "${_cython_comment}" WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/${_directories} VERBATIM ) set_target_properties(${_pyx_target_name} PROPERTIES generated_files "${_generated_files}") # Remove internal variables' visibility to the user. foreach(_v _cxx_arg _extension _is_cxx _pyx_location _annotate_arg _no_docstrings_arg _cython_debug_arg _is_public _is_api _generated_files _cython_command _cython_comment) set( ${_v} "" CACHE INTERNAL "" ) endforeach(_v) endfunction() # cython_add_module( src1 src2 ... srcN ) # Build the Cython Python module. function( cython_add_module _name _pyx_target_name _is_cxx) string(REPLACE "." "/" _module_source ${_name}) set(_module_source ${_module_source}.pyx) get_filename_component( _directories "${_module_source}" PATH ) get_filename_component( _module_name "${_module_source}" NAME_WE) if(${_is_cxx}) set_source_files_properties(${_module_source} PROPERTIES CYTHON_IS_CXX 1) endif() compile_pyx( ${_name} ${_pyx_target_name} ${_module_name} "${_directories}" ${_module_source} ) include_directories( ${PYTHON_INCLUDE_DIRS} ) # Set up the Python module corresponding to this pyx file. get_target_property(_generated_files ${_pyx_target_name} generated_files) python_add_module( ${_name} ${_generated_files} ${_other_module_sources} ${ARGN}) # Force output to not be written to the Release or Debug subdirectory of the target # directory. The difference in build configuration should already be taken care of in # the CMAKE_CURRENT_BINARY_DIR on generators where that matters. set(_output_dir ${CMAKE_CURRENT_BINARY_DIR}/${_directories}) set_target_properties(${_name} PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${_output_dir}) foreach( _build_type RELEASE DEBUG RELWITHDEBINFO MINSIZEREL ) set_target_properties(${_name} PROPERTIES LIBRARY_OUTPUT_DIRECTORY_${_build_type} ${_output_dir}) endforeach(_build_type) set_target_properties(${_name} PROPERTIES OUTPUT_NAME ${_module_name}) add_dependencies( ${_name} ${_pyx_target_name}) target_link_libraries( ${_name} ${PYTHON_LIBRARIES} ) # Remove internal variables' visibility to the user. foreach(_v _module_source _directories _module_name _generated_files _output_dir) set( ${_v} "" CACHE INTERNAL "" ) endforeach(_v) endfunction() include( CMakeParseArguments )