Skip to content

Commit 4fc068b

Browse files
jcfrvyasr
andcommitted
wip(UseCython): Add Cython_compile_pyx
Co-authored-by: Vyas Ramasubramani <[email protected]>
1 parent c1b6c88 commit 4fc068b

File tree

1 file changed

+129
-81
lines changed

1 file changed

+129
-81
lines changed

src/cython_cmake/cmake/UseCython.cmake

Lines changed: 129 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,58 @@
22
#
33
# The following functions are defined:
44
#
5+
# .. cmake:command:: Cython_compile_pyx
6+
#
7+
# Create a custom rule to generate the source code for a Python extension module
8+
# using cython.
9+
#
10+
# Cython_compile_pyx(<CythonInput>
11+
# [TARGET_LANGUAGE C | CXX]
12+
# [LANGUAGE_LEVEL 2 | 3 | 3str]
13+
# [OUTPUT_VAR <OutputVar>])
14+
#
15+
# Options:
16+
#
17+
# ``TARGET_LANGUAGE [C | CXX]``
18+
# Force the generation of either a C or C++ file. By default, a C file is
19+
# generated, unless the C language is not enabled for the project; in this
20+
# case, a C++ file is generated by default.
21+
#
22+
# ``LANGUAGE_LEVEL [2 | 3 | 3str]``
23+
# Force compilation using either Python-2, Python-3 or Python-3str syntax and
24+
# code semantics.
25+
# By default, Python-3str syntax and semantics are used if the major version
26+
# of Python found is 3 and Cython >=3 is used. Otherwise, Python-2 syntax and
27+
# semantics are used.
28+
# Using the Python-3str syntax and semantics means there cython does not assume
29+
# unicode is used by by default for string literals under Python 2
30+
#
31+
# ``OUTPUT_VAR <OutputVar>``
32+
# Set the variable ``<OutputVar>`` in the parent scope to the path to the
33+
# generated source file. By default, ``<Name>`` is used as the output
34+
# variable name.
35+
#
36+
# Defined variables:
37+
#
38+
# ``<OutputVar>``
39+
# The path of the generated source file.
40+
#
41+
# Usage example:
42+
#
43+
# .. code-block:: cmake
44+
#
45+
# find_package(Cython)
46+
#
47+
# Cython_compile_pyx(_hello.pyx
48+
# OUTPUT_VAR _hello_source_file
49+
# )
50+
#
51+
# Python_add_library(_hello
52+
# MODULE ${_hello_source_file}
53+
# WITH_SOABI
54+
# )
55+
#
56+
#
557
# .. cmake:command:: add_cython_target
658
#
759
# Create a custom rule to generate the source code for a Python extension module
@@ -30,26 +82,12 @@
3082
#
3183
# Options:
3284
#
33-
# ``TARGET_LANGUAGE [C | CXX]``
34-
# Force the generation of either a C or C++ file. By default, a C file is
35-
# generated, unless the C language is not enabled for the project; in this
36-
# case, a C++ file is generated by default.
37-
#
38-
# ``C | CXX`` (deprecated)
85+
# ``C | CXX``
3986
# Force the generation of either a C or C++ file. By default, a C file is
4087
# generated, unless the C language is not enabled for the project; in this
4188
# case, a C++ file is generated by default.
4289
#
43-
# ``LANGUAGE_LEVEL [2 | 3 | 3str]``
44-
# Force compilation using either Python-2, Python-3 or Python-3str syntax and
45-
# code semantics.
46-
# By default, Python-3str syntax and semantics are used if the major version
47-
# of Python found is 3 and Cython >=3 is used. Otherwise, Python-2 syntax and
48-
# semantics are used.
49-
# Using the Python-3str syntax and semantics means there cython does not assume
50-
# unicode is used by by default for string literals under Python 2
51-
#
52-
# ``PY2 | PY3`` (deprecated)
90+
# ``PY2 | PY3``
5391
# Force compilation using either Python-2 or Python-3 syntax and code
5492
# semantics. By default, Python-2 syntax and semantics are used if the major
5593
# version of Python found is 2. Otherwise, Python-3 syntax and semantics are
@@ -73,8 +111,7 @@
73111
# ``CYTHON_FLAGS``
74112
# Additional flags to pass to the Cython compiler.
75113
#
76-
# Example usage
77-
# ^^^^^^^^^^^^^
114+
# Usage example:
78115
#
79116
# .. code-block:: cmake
80117
#
@@ -103,45 +140,39 @@
103140
# limitations under the License.
104141
#=============================================================================
105142

106-
# Configuration options.
107-
set(CYTHON_ANNOTATE OFF
108-
CACHE BOOL "Create an annotated .html file when compiling *.pyx.")
109-
110-
set(CYTHON_FLAGS "" CACHE STRING
111-
"Extra flags to the cython compiler.")
112-
mark_as_advanced(CYTHON_ANNOTATE CYTHON_FLAGS)
113143

114144
function(add_cython_target _name)
115-
set(_deprecated_options C CXX PY2 PY3)
116-
set(_options )
117-
set(_one_value TARGET_LANGUAGE OUTPUT_VAR)
145+
set(_options C CXX PY2 PY3)
146+
set(_one_value OUTPUT_VAR)
118147
set(_multi_value )
119148

120149
cmake_parse_arguments(_args
121-
"${_options} ${_deprecated_options}"
150+
"${_options}"
122151
"${_one_value}"
123152
"${_multi_value}"
124153
${ARGN}
125154
)
126155

127-
# Support deprecated options: C, CXX
128-
if(NOT _args_TARGET_LANGUAGE)
129-
if(_args_C)
130-
set(_args_TARGET_LANGUAGE "C")
131-
endif()
132-
if(_args_CXX)
133-
set(_args_TARGET_LANGUAGE "CXX")
134-
endif()
156+
# Configuration options.
157+
set(CYTHON_ANNOTATE OFF
158+
CACHE BOOL "Create an annotated .html file when compiling *.pyx.")
159+
160+
set(CYTHON_FLAGS "" CACHE STRING
161+
"Extra flags to the cython compiler.")
162+
mark_as_advanced(CYTHON_ANNOTATE CYTHON_FLAGS)
163+
164+
if(_args_C)
165+
set(_target_language "C")
166+
endif()
167+
if(_args_CXX)
168+
set(_target_language "CXX")
135169
endif()
136170

137-
# Support deprecated options: PY2, PY3
138-
if(NOT _args_LANGUAGE_LEVEL)
139-
if(_args_PY2)
140-
set(_args_LANGUAGE_LEVEL "2")
141-
endif()
142-
if(_args_PY3)
143-
set(_args_LANGUAGE_LEVEL "3")
144-
endif()
171+
if(_args_PY2)
172+
set(_language_level "2")
173+
endif()
174+
if(_args_PY3)
175+
set(_language_level "3")
145176
endif()
146177

147178
list(GET _args_UNPARSED_ARGUMENTS 0 _arg0)
@@ -165,6 +196,57 @@ function(add_cython_target _name)
165196
endif()
166197
endif()
167198

199+
# Set additional flags.
200+
set(_cython_args)
201+
if(CYTHON_ANNOTATE)
202+
list(APPEND _cython_args "--annotate")
203+
endif()
204+
if(CMAKE_BUILD_TYPE STREQUAL "Debug" OR
205+
CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo")
206+
list(APPEND _cython_args
207+
"--gdb"
208+
"--line-directives"
209+
)
210+
endif()
211+
string(STRIP "${CYTHON_FLAGS}" _stripped_cython_flags)
212+
if(_stripped_cython_flags)
213+
string(REGEX REPLACE " " ";" CYTHON_FLAGS_LIST "${_stripped_cython_flags}")
214+
list(APPEND _cython_args ${CYTHON_FLAGS_LIST})
215+
endif()
216+
217+
Cython_compile_pyx(
218+
TARGET_LANGUAGE ${_target_language}
219+
LANGUAGE_LEVEL ${_language_level}
220+
CYTHON_ARGS ${_cython_args}
221+
OUTPUT_VAR ${_args_OUTPUT_VAR}
222+
${_source_file}
223+
)
224+
225+
if(_args_OUTPUT_VAR)
226+
set(${_args_OUTPUT_VAR} ${${_args_OUTPUT_VAR}} PARENT_SCOPE)
227+
endif()
228+
endfunction()
229+
230+
function(Cython_compile_pyx)
231+
set(_options )
232+
set(_one_value LANGUAGE_LEVEL TARGET_LANGUAGE OUTPUT_VAR)
233+
set(_multi_value CYTHON_ARGS)
234+
235+
cmake_parse_arguments(_args
236+
"${_options}"
237+
"${_one_value}"
238+
"${_multi_value}"
239+
${ARGN}
240+
)
241+
242+
# Get source file location
243+
set(_source_files ${_args_UNPARSED_ARGUMENTS})
244+
list(GET _source_files 0 _source_file)
245+
list(LENGTH _source_files _source_file_count)
246+
if (_source_file_count GREATER 1)
247+
message(AUTHOR_WARNING "Cython_compile_pyx supports compiling only one file: ${_source_files}")
248+
endif()
249+
168250
# Set target language
169251
get_property(_languages GLOBAL PROPERTY ENABLED_LANGUAGES)
170252
set(_target_language ${_args_TARGET_LANGUAGE})
@@ -204,6 +286,7 @@ function(add_cython_target _name)
204286

205287
set(_language_level_arg "${_language_level_${_language_level}_arg}")
206288

289+
cmake_path(GET _source_file STEM _name)
207290
set(generated_file "${CMAKE_CURRENT_BINARY_DIR}/${_name}.${_target_language_extension}")
208291
set_source_files_properties(${generated_file} PROPERTIES GENERATED TRUE)
209292

@@ -225,33 +308,14 @@ function(add_cython_target _name)
225308
set(_depfile ${generated_file}.dep)
226309
set(_depfile_arg "-M")
227310

228-
# Set additional flags.
229-
set(annotate_arg "")
230-
if(CYTHON_ANNOTATE)
231-
set(annotate_arg "--annotate")
232-
endif()
233-
234-
set(cython_debug_arg "")
235-
set(line_directives_arg "")
236-
if(CMAKE_BUILD_TYPE STREQUAL "Debug" OR
237-
CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo")
238-
set(cython_debug_arg "--gdb")
239-
set(line_directives_arg "--line-directives")
240-
endif()
241-
242-
string(REGEX REPLACE " " ";" CYTHON_FLAGS_LIST "${CYTHON_FLAGS}")
243-
244311
# Add the command to run the compiler.
245312
add_custom_command(
246313
OUTPUT ${generated_file}
247314
COMMAND ${CYTHON_EXECUTABLE}
248315
ARGS
249316
${_target_language_arg}
250317
${_language_level_arg}
251-
${annotate_arg}
252-
${cython_debug_arg}
253-
${line_directives_arg}
254-
${CYTHON_FLAGS_LIST}
318+
${_args_CYTHON_ARGS}
255319
${_depfile_arg}
256320
${pyx_location}
257321
--output-file ${generated_file}
@@ -263,20 +327,4 @@ function(add_cython_target _name)
263327
COMMENT ${comment}
264328
)
265329

266-
# NOTE(opadron): I thought about making a proper target, but after trying it
267-
# out, I decided that it would be far too convenient to use the same name as
268-
# the target for the extension module (e.g.: for single-file modules):
269-
#
270-
# ...
271-
# add_cython_target(_module.pyx)
272-
# add_library(_module ${_module})
273-
# ...
274-
#
275-
# The above example would not be possible since the "_module" target name
276-
# would already be taken by the cython target. Since I can't think of a
277-
# reason why someone would need the custom target instead of just using the
278-
# generated file directly, I decided to leave this commented out.
279-
#
280-
# add_custom_target(${_name} DEPENDS ${generated_file})
281330
endfunction()
282-

0 commit comments

Comments
 (0)