88# using cython.
99#
1010# Cython_compile_pyx(<pyx_file>
11- # LANGUAGE C | CXX
11+ # [ LANGUAGE C | CXX]
1212# [CYTHON_ARGS <args> ...]
1313# [OUTPUT <OutputFile>]
1414# [OUTPUT_VARIABLE <OutputVariable>]
1717# Options:
1818#
1919# ``LANGUAGE [C | CXX]``
20- # Force the generation of either a C or C++ file. Required.
20+ # Force the generation of either a C or C++ file. Recommended; will attempt
21+ # to be deduced if not specified, defaults to C unless only CXX is enabled.
2122#
2223# ``CYTHON_ARGS <args>``
2324# Specify additional arguments for the cythonization process. Will default to
@@ -75,14 +76,21 @@ if(CMAKE_VERSION VERSION_LESS "3.7")
7576 message (FATAL_ERROR "CMake 3.7 required for DEPFILE" )
7677endif ()
7778
78- function (Cython_compile_pyx INPUT )
79+
80+ function (Cython_compile_pyx)
7981 cmake_parse_arguments (
80- PARSE_ARGV 1
82+ PARSE_ARGV 0
8183 CYTHON
8284 ""
8385 "OUTPUT;LANGUAGE;OUTPUT_VARIABLE"
8486 "CYTHON_ARGS"
8587 )
88+ set (ALL_INPUT ${CYTHON_UNPARSED_ARGUMENTS} )
89+ list (LENGTH ALL_INPUT INPUT_LENGTH)
90+ if (NOT INPUT_LENGTH EQUAL 1)
91+ message (FATAL_ERROR "One and only one input file must be specified, got '${ALL_INPUT} '" )
92+ endif ()
93+ list (GET ALL_INPUT 0 INPUT )
8694
8795 if (DEFINED CYTHON_EXECUTABLE)
8896 set (_cython_command "${CYTHON_EXECUTABLE} " )
@@ -99,34 +107,51 @@ function(Cython_compile_pyx INPUT)
99107 set (CYTHON_CYTHON_ARGS "${CYTHON_ARGS} " )
100108 endif ()
101109
102- # Set target language (required)
110+ # Set target language
111+ if (NOT CYTHON_LANGUAGE)
112+ get_property (_languages GLOBAL PROPERTY ENABLED_LANGUAGES )
113+
114+ if ("C" IN_LIST _languages AND "CXX" IN_LIST _languages)
115+ # Try to compute language. Returns falsy if not found.
116+ _cython_compute_language(CYTHON_LANGUAGE ${INPUT} )
117+ message (STATUS "${CYTHON_LANGUAGE} " )
118+ elseif ("C" IN_LIST _languages)
119+ # If only C is enabled globally, assume C
120+ set (CYTHON_LANGUAGE C)
121+ elseif ("CXX" IN_LIST _languages)
122+ # Likewise for CXX
123+ set (CYTHON_LANGUAGE CXX)
124+ else ()
125+ message (FATAL_ERROR "LANGUAGE keyword required if neither C nor CXX enabled globally" )
126+ endif ()
127+ endif ()
128+
129+ # Default to C if not found
103130 if (NOT CYTHON_LANGUAGE)
104- message (SEND_ERROR "cython_compile_pyx LANGUAGE keyword is required" )
105- elseif (CYTHON_LANGUAGE STREQUAL C)
131+ set (CYTHON_LANGUAGE C)
132+ endif ()
133+
134+ if (CYTHON_LANGUAGE STREQUAL C)
106135 set (language_arg "" )
107136 set (language_ext ".c" )
108137 elseif (CYTHON_LANGUAGE STREQUAL CXX)
109138 set (language_arg "--cplus" )
110139 set (language_ext ".cxx" )
111140 else ()
112- message (SEND_ERROR "cython_compile_pyx LANGUAGE must be one of C or CXX" )
141+ message (FATAL_ERROR "cython_compile_pyx LANGUAGE must be one of C or CXX" )
113142 endif ()
114143
115144 # Place the cython files in the current binary dir if no path given
116145 # Can use cmake_path for CMake 3.20+
117146 if (NOT CYTHON_OUTPUT)
118- # cmake_path(GET INPUT STEM basename)
119147 get_filename_component (basename "${INPUT} " NAME_WE )
120148
121- # cmake_path(APPEND CMAKE_CURRENT_BINARY_DIR "${basename}${language_ext}" OUTPUT_VARIABLE CYTHON_OUTPUT)
122149 set (CYTHON_OUPUT "${CMAKE_CURRENT_BINARY_DIR} /${basename}${language_ext} " )
123150 endif ()
124151
125- # cmake_path(ABSOLUTE_PATH CYTHON_OUTPUT)
126152 get_filename_component (CYTHON_OUTPUT "${CYTHON_OUPUT} " ABSOLUTE )
127153
128154 # Normalize the input path
129- # cmake_path(ABSOLUTE_PATH INPUT)
130155 get_filename_component (INPUT "${INPUT} " ABSOLUTE )
131156 set_source_files_properties ("${INPUT} " PROPERTIES GENERATED TRUE )
132157
@@ -155,7 +180,7 @@ function(Cython_compile_pyx INPUT)
155180 --depfile
156181 "${INPUT} "
157182 --output -file "${CYTHON_OUTPUT} "
158- DEPENDS
183+ MAIN_DEPENDENCY
159184 "${INPUT} "
160185 DEPFILE
161186 "${depfile_path} "
@@ -165,3 +190,12 @@ function(Cython_compile_pyx INPUT)
165190 )
166191
167192endfunction ()
193+
194+ function (_cython_compute_language OUTPUT_VARIABLE FILENAME)
195+ file (READ "${FILENAME} " FILE_CONTENT)
196+ set (REGEX_PATTERN [=[^[[:space:]]*#[[:space:]]*distutils:.*language[[:space:]]*=[[:space:]]*(c\\+\\+|c)]=])
197+ string (REGEX MATCH "${REGEX_PATTERN} " MATCH_RESULT "${FILE_CONTENT} " )
198+ string (TOUPPER "${MATCH_RESULT} " LANGUAGE_NAME)
199+ string (REPLACE "+" "X" LANGUAGE_NAME "${LANGUAGE_NAME} " )
200+ set (${OUTPUT_VARIABLE} ${LANGUAGE_NAME} PARENT_SCOPE)
201+ endfunction ()
0 commit comments