77# Create custom rules to generate the source code for a Python extension module
88# using cython.
99#
10- # Cython_compile_pyx(<pyx_file1> [<pyx_file2> ...]
11- # [ LANGUAGE C | CXX]
10+ # Cython_compile_pyx(<pyx_file>
11+ # LANGUAGE C | CXX
1212# [CYTHON_ARGS <args> ...]
13- # [OUTPUT_VARIABLE <OutputVariable>])
13+ # [OUTPUT <OutputFile>]
14+ # [OUTPUT_VARIABLE <OutputVariable>]
15+ # )
1416#
1517# Options:
1618#
1719# ``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.
20+ # Force the generation of either a C or C++ file. Required.
2121#
2222# ``CYTHON_ARGS <args>``
2323# Specify additional arguments for the cythonization process. Will default to
2424# the ``CYTHON_ARGS`` variable if not specified.
2525#
26+ # ``OUTPUT <OutputFile>``
27+ # Specify a specific path for the output file as ``<OutputFile>``. By
28+ # default, this will output into the current binary dir. A depfile will be
29+ # created alongside this file as well.
30+ #
2631# ``OUTPUT_VARIABLE <OutputVariable>``
2732# Set the variable ``<OutputVariable>`` in the parent scope to the path to the
28- # generated source file. By default, ``<Name>`` is used as the output
29- # variable name.
33+ # generated source file.
3034#
3135# Defined variables:
3236#
4145# include(UseCython)
4246#
4347# Cython_compile_pyx(_hello.pyx
44- # OUTPUT_VARIABLE _hello_source_files
48+ # LANGUAGE C
49+ # OUTPUT_VARIABLE _hello_source_file
4550# )
4651#
4752# Python_add_library(_hello
48- # MODULE ${_hello_source_files}
53+ # MODULE "${_hello_source_file}"
4954# WITH_SOABI
5055# )
5156#
6772#=============================================================================
6873
6974if (CMAKE_VERSION VERSION_LESS "3.7" )
70- message (SEND_ERROR "CMake 3.7 required for DEPFILE" )
75+ message (FATAL_ERROR "CMake 3.7 required for DEPFILE" )
7176endif ()
7277
73- function (Cython_compile_pyx)
74- set (_options )
75- set (_one_value LANGUAGE OUTPUT_VARIABLE )
76- set (_multi_value CYTHON_ARGS)
77-
78- cmake_parse_arguments (_args
79- "${_options} "
80- "${_one_value} "
81- "${_multi_value} "
82- ${ARGN}
78+ function (Cython_compile_pyx INPUT )
79+ cmake_parse_arguments (
80+ PARSE_ARGV 1
81+ CYTHON
82+ ""
83+ "OUTPUT;LANGUAGE;OUTPUT_VARIABLE"
84+ "CYTHON_ARGS"
8385 )
8486
8587 if (DEFINED CYTHON_EXECUTABLE)
@@ -93,83 +95,73 @@ function(Cython_compile_pyx)
9395 endif ()
9496
9597 # Default to CYTHON_ARGS if argument not specified
96- if (NOT _args_CYTHON_ARGS AND DEFINED CYTHON_ARGS)
97- set (_args_CYTHON_ARGS "${CYTHON_ARGS} " )
98+ if (NOT CYTHON_CYTHON_ARGS AND DEFINED CYTHON_ARGS)
99+ set (CYTHON_CYTHON_ARGS "${CYTHON_ARGS} " )
98100 endif ()
99101
100- # Get source file location
101- set (_source_files ${_args_UNPARSED_ARGUMENTS} )
102-
103- # Set target language
104- get_property (_languages GLOBAL PROPERTY ENABLED_LANGUAGES )
105- set (_language ${_args_LANGUAGE} )
106- if (NOT _language)
107- if ("C" IN_LIST _languages)
108- set (_language "C" )
109- elseif ("CXX" IN_LIST _languages)
110- set (_language "CXX" )
111- endif ()
102+ # Set target language (required)
103+ if (NOT CYTHON_LANGUAGE)
104+ message (SEND_ERROR "cython_compile_pyx LANGUAGE keyword is required" )
105+ elseif (CYTHON_LANGUAGE STREQUAL C)
106+ set (language_arg "" )
107+ set (language_ext ".c" )
108+ elseif (CYTHON_LANGUAGE STREQUAL CXX)
109+ set (language_arg "--cplus" )
110+ set (language_ext ".cxx" )
112111 else ()
113- if (NOT _language MATCHES "^(C|CXX)$" )
114- message (FATAL_ERROR "LANGUAGE must be one of C or CXX" )
115- endif ()
112+ message (SEND_ERROR "cython_compile_pyx LANGUAGE must be one of C or CXX" )
116113 endif ()
117114
118- set (_language_C_arg "" )
119- set (_language_C_extension "c" )
120- set (_language_CXX_arg "--cplus" )
121- set (_language_CXX_extension "cxx" )
122-
123- set (_language_arg ${_language_${_language} _arg})
124- set (_language_extension ${_language_${_language} _extension})
125-
126- set (generated_files)
127-
128- foreach (_source_file IN LISTS _source_files)
129-
130- # Can use cmake_path for CMake 3.20+
131- # cmake_path(GET _source_file STEM _name)
132- get_filename_component (_name "${_source_file} " NAME_WE )
115+ # Place the cython files in the current binary dir if no path given
116+ # Can use cmake_path for CMake 3.20+
117+ if (NOT CYTHON_OUTPUT)
118+ # cmake_path(GET INPUT STEM basename)
119+ get_filename_component (basename "${INPUT} " NAME_WE )
133120
134- set (generated_file "${CMAKE_CURRENT_BINARY_DIR} /${_name} .${_language_extension} " )
135- set_source_files_properties (${generated_file} PROPERTIES GENERATED TRUE )
136-
137- # Generated depfile is expected to have the ".dep" extension and be located along
138- # side the generated source file.
139- set (_depfile ${generated_file} .dep)
140- set (_depfile_arg "-M" )
141-
142- file (RELATIVE_PATH generated_file_relative
143- ${CMAKE_BINARY_DIR} ${generated_file} )
144-
145- set (comment "Generating ${_language} source ${generated_file_relative} " )
121+ # cmake_path(APPEND CMAKE_CURRENT_BINARY_DIR "${basename}${language_ext}" OUTPUT_VARIABLE CYTHON_OUTPUT)
122+ set (CYTHON_OUPUT "${CMAKE_CURRENT_BINARY_DIR} /${basename}${language_ext} " )
123+ endif ()
146124
147- get_source_file_property (pyx_location ${_source_file} LOCATION )
125+ # cmake_path(ABSOLUTE_PATH CYTHON_OUTPUT)
126+ get_filename_component (CYTHON_OUTPUT "${CYTHON_OUPUT} " ABSOLUTE )
148127
149- # Add the command to run the compiler.
150- add_custom_command (
151- OUTPUT ${generated_file}
152- COMMAND
153- ${_cython_command}
154- ARGS
155- ${_language_arg}
156- ${_args_CYTHON_ARGS}
157- ${_depfile_arg}
158- ${pyx_location}
159- --output -file ${generated_file}
160- DEPENDS
161- ${_source_file}
162- DEPFILE
163- ${_depfile}
164- VERBATIM
165- COMMENT ${comment}
166- )
167- list (APPEND generated_files ${generated_file} )
168- endforeach ()
128+ # Normalize the input path
129+ # cmake_path(ABSOLUTE_PATH INPUT)
130+ get_filename_component (INPUT "${INPUT} " ABSOLUTE )
131+ set_source_files_properties ("${INPUT} " PROPERTIES GENERATED TRUE )
169132
170- if (_args_OUTPUT_VARIABLE)
171- set (_output_variable ${_args_OUTPUT_VARIABLE} )
172- set (${_output_variable} ${generated_files} PARENT_SCOPE)
133+ # Output variable only if set
134+ if (CYTHON_OUTPUT_VARIABLE )
135+ set (${CYTHON_OUTPUT_VARIABLE} " ${CYTHON_OUTPUT} " PARENT_SCOPE)
173136 endif ()
174137
138+ # Generated depfile is expected to have the ".dep" extension and be located
139+ # along side the generated source file.
140+ set (depfile_path "${CYTHON_OUTPUT} .dep" )
141+
142+ # Pretty-printed output name
143+ file (RELATIVE_PATH generated_file_relative "${CMAKE_BINARY_DIR} " "${CYTHON_OUTPUT} " )
144+ file (RELATIVE_PATH input_file_relative "${CMAKE_SOURCE_DIR} " "${INPUT} " )
145+
146+ # Add the command to run the compiler.
147+ add_custom_command (
148+ OUTPUT
149+ "${CYTHON_OUTPUT} "
150+ "${depfile_path} "
151+ COMMAND
152+ ${_cython_command}
153+ ${language_arg}
154+ ${CYTHON_CYTHON_ARGS}
155+ --depfile
156+ "${INPUT} "
157+ --output -file "${CYTHON_OUTPUT} "
158+ DEPENDS
159+ "${INPUT} "
160+ DEPFILE
161+ "${depfile_path} "
162+ VERBATIM
163+ COMMENT
164+ "Cythonizing source ${input_file_relative} to output ${generated_file_relative} "
165+ )
166+
175167endfunction ()
0 commit comments