/
UseCython.cmake
212 lines (184 loc) · 8.62 KB
/
UseCython.cmake
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
# 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( <target_name> <pyx_target_name> <src1> <src2> ... <srcN> )
#
# Where <module_name> is the import path for the resulting Python module
# (e.g. mymodule.submodule.other_submodule.this_extension),
# <pyx_target_name> is the desired name of the target that runs the Cython compiler
# to generate the needed C or C++ files, and <src1> <src2> ... 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 <module_name>.
# <module_name> is also used as the name of the target for the desired Python module.
# A list of output files is provided as the <generated_files> 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 <generated_files>
# 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( <name> 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 )