Skip to content

Commit 3c1b93d

Browse files
committed
feat: rewrite
Signed-off-by: Henry Schreiner <[email protected]> feat: deduce C/CXX if possible Signed-off-by: Henry Schreiner <[email protected]> fix: better handling of output Signed-off-by: Henry Schreiner <[email protected]> docs: add info Signed-off-by: Henry Schreiner <[email protected]>
1 parent 55afedb commit 3c1b93d

File tree

1 file changed

+72
-118
lines changed

1 file changed

+72
-118
lines changed

src/cython_cmake/cmake/UseCython.cmake

Lines changed: 72 additions & 118 deletions
Original file line numberDiff line numberDiff line change
@@ -79,15 +79,12 @@ if(CMAKE_VERSION VERSION_LESS "3.8")
7979
endif()
8080

8181
function(Cython_transpile)
82-
set(_options )
83-
set(_one_value LANGUAGE OUTPUT OUTPUT_VARIABLE)
84-
set(_multi_value CYTHON_ARGS)
85-
86-
cmake_parse_arguments(_args
87-
"${_options}"
88-
"${_one_value}"
89-
"${_multi_value}"
90-
${ARGN}
82+
cmake_parse_arguments(
83+
PARSE_ARGV 0
84+
CYTHON
85+
""
86+
"OUTPUT;LANGUAGE;OUTPUT_VARIABLE"
87+
"CYTHON_ARGS"
9188
)
9289

9390
if(DEFINED CYTHON_EXECUTABLE)
@@ -101,142 +98,99 @@ function(Cython_transpile)
10198
endif()
10299

103100
# Default to CYTHON_ARGS if argument not specified
104-
if(NOT _args_CYTHON_ARGS AND DEFINED CYTHON_ARGS)
105-
set(_args_CYTHON_ARGS "${CYTHON_ARGS}")
101+
if(NOT CYTHON_CYTHON_ARGS AND DEFINED CYTHON_ARGS)
102+
set(CYTHON_CYTHON_ARGS "${CYTHON_ARGS}")
106103
endif()
107104

108105
# Get input
109-
set(_source_files ${_args_UNPARSED_ARGUMENTS})
110-
list(LENGTH _source_files input_length)
111-
if(NOT input_length EQUAL 1)
112-
message(FATAL_ERROR "One and only one input file must be specified, got '${_source_files}'")
106+
set(ALL_INPUT ${CYTHON_UNPARSED_ARGUMENTS})
107+
list(LENGTH ALL_INPUT INPUT_LENGTH)
108+
if(NOT INPUT_LENGTH EQUAL 1)
109+
message(FATAL_ERROR "One and only one input file must be specified, got '${ALL_INPUT}'")
113110
endif()
114-
115-
function(_transpile _source_file generated_file language)
116-
117-
if(language STREQUAL "C")
118-
set(_language_arg "")
119-
elseif(language STREQUAL "CXX")
120-
set(_language_arg "--cplus")
121-
else()
122-
message(FATAL_ERROR "_transpile language must be one of C or CXX")
123-
endif()
124-
125-
set_source_files_properties(${generated_file} PROPERTIES GENERATED TRUE)
126-
127-
# Generated depfile is expected to have the ".dep" extension and be located along
128-
# side the generated source file.
129-
set(_depfile ${generated_file}.dep)
130-
set(_depfile_arg "-M")
131-
132-
# Normalize the input path
133-
get_filename_component(_source_file "${_source_file}" ABSOLUTE)
134-
135-
# Pretty-printed output names
136-
file(RELATIVE_PATH generated_file_relative
137-
"${CMAKE_BINARY_DIR}" "${generated_file}")
138-
file(RELATIVE_PATH source_file_relative
139-
"${CMAKE_SOURCE_DIR}" "${_source_file}")
140-
set(comment "Generating ${_language} source '${generated_file_relative}' from '${source_file_relative}'")
141-
142-
# Get output directory to ensure its exists
143-
get_filename_component(output_directory "${generated_file}" DIRECTORY)
144-
145-
get_source_file_property(pyx_location ${_source_file} LOCATION)
146-
147-
# Add the command to run the compiler.
148-
add_custom_command(
149-
OUTPUT "${generated_file}"
150-
COMMAND
151-
"${CMAKE_COMMAND}" -E make_directory "${output_directory}"
152-
COMMAND
153-
${_cython_command}
154-
${_language_arg}
155-
"${_args_CYTHON_ARGS}"
156-
${_depfile_arg}
157-
"${pyx_location}"
158-
--output-file "${generated_file}"
159-
COMMAND_EXPAND_LISTS
160-
MAIN_DEPENDENCY
161-
"${_source_file}"
162-
DEPFILE
163-
"${_depfile}"
164-
VERBATIM
165-
COMMENT "${comment}"
166-
)
167-
endfunction()
168-
169-
function(_set_output _input_file _language _output_var)
170-
if(_language STREQUAL "C")
171-
set(_language_extension "c")
172-
elseif(_language STREQUAL "CXX")
173-
set(_language_extension "cxx")
174-
else()
175-
message(FATAL_ERROR "_set_output language must be one of C or CXX")
176-
endif()
177-
178-
# Can use cmake_path for CMake 3.20+
179-
# cmake_path(GET _input_file STEM basename)
180-
get_filename_component(_basename "${_input_file}" NAME_WE)
181-
182-
if(IS_ABSOLUTE "${_input_file}")
183-
file(RELATIVE_PATH _input_relative "${CMAKE_CURRENT_SOURCE_DIR}" "${_input_file}")
184-
else()
185-
set(_input_relative "${_input_file}")
186-
endif()
187-
188-
get_filename_component(_output_relative_dir "${_input_relative}" DIRECTORY)
189-
string(REPLACE "." "_" _output_relative_dir "${_output_relative_dir}")
190-
if(_output_relative_dir)
191-
set(_output_relative_dir "${_output_relative_dir}/")
192-
endif()
193-
194-
set(${_output_var} "${CMAKE_CURRENT_BINARY_DIR}/${_output_relative_dir}${_basename}.${_language_extension}" PARENT_SCOPE)
195-
endfunction()
196-
197-
set(generated_files)
198-
199-
list(GET _source_files 0 _source_file)
111+
list(GET ALL_INPUT 0 INPUT)
200112

201113
# Set target language
202-
set(_language ${_args_LANGUAGE})
203-
if(NOT _language)
114+
if(NOT CYTHON_LANGUAGE)
204115
get_property(_languages GLOBAL PROPERTY ENABLED_LANGUAGES)
116+
205117
if("C" IN_LIST _languages AND "CXX" IN_LIST _languages)
206118
# Try to compute language. Returns falsy if not found.
207-
_cython_compute_language(_language ${_source_file})
119+
_cython_compute_language(CYTHON_LANGUAGE ${INPUT})
120+
message(STATUS "${CYTHON_LANGUAGE}")
208121
elseif("C" IN_LIST _languages)
209122
# If only C is enabled globally, assume C
210-
set(_language "C")
123+
set(CYTHON_LANGUAGE C)
211124
elseif("CXX" IN_LIST _languages)
212125
# Likewise for CXX
213-
set(_language "CXX")
126+
set(CYTHON_LANGUAGE CXX)
214127
else()
215128
message(FATAL_ERROR "LANGUAGE keyword required if neither C nor CXX enabled globally")
216129
endif()
217130
endif()
218131

219-
if(NOT _language MATCHES "^(C|CXX)$")
220-
message(FATAL_ERROR "Cython_transpile LANGUAGE must be one of C or CXX")
132+
# Default to C if not found
133+
if(NOT CYTHON_LANGUAGE)
134+
set(CYTHON_LANGUAGE C)
135+
endif()
136+
137+
if(CYTHON_LANGUAGE STREQUAL C)
138+
set(language_arg "")
139+
set(language_ext ".c")
140+
elseif(CYTHON_LANGUAGE STREQUAL CXX)
141+
set(language_arg "--cplus")
142+
set(language_ext ".cxx")
143+
else()
144+
message(FATAL_ERROR "cython_compile_pyx LANGUAGE must be one of C or CXX")
221145
endif()
222146

223147
# Place the cython files in the current binary dir if no path given
224-
if(NOT _args_OUTPUT)
225-
_set_output("${_source_file}" ${_language} _args_OUTPUT)
226-
elseif(NOT IS_ABSOLUTE "${_args_OUTPUT}")
227-
set(_args_OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${_args_OUTPUT}")
148+
# Can use cmake_path for CMake 3.20+
149+
if(NOT CYTHON_OUTPUT)
150+
get_filename_component(basename "${INPUT}" NAME_WE)
151+
152+
set(CYTHON_OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${basename}${language_ext}")
153+
elseif(NOT IS_ABSOLUTE CYTHON_OUTPUT)
154+
set(CYTHON_OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${CYTHON_OUTPUT}")
228155
endif()
229156

230-
set(generated_file "${_args_OUTPUT}")
231-
_transpile("${_source_file}" "${generated_file}" ${_language})
232-
list(APPEND generated_files "${generated_file}")
157+
# Normalize the input path
158+
get_filename_component(INPUT "${INPUT}" ABSOLUTE)
159+
set_source_files_properties("${INPUT}" PROPERTIES GENERATED TRUE)
233160

234161
# Output variable only if set
235-
if(_args_OUTPUT_VARIABLE)
236-
set(_output_variable ${_args_OUTPUT_VARIABLE})
237-
set(${_output_variable} "${generated_files}" PARENT_SCOPE)
162+
if(CYTHON_OUTPUT_VARIABLE)
163+
set(${CYTHON_OUTPUT_VARIABLE} "${CYTHON_OUTPUT}" PARENT_SCOPE)
238164
endif()
239165

166+
# Generated depfile is expected to have the ".dep" extension and be located
167+
# along side the generated source file.
168+
set(depfile_path "${CYTHON_OUTPUT}.dep")
169+
170+
# Pretty-printed output name
171+
file(RELATIVE_PATH generated_file_relative "${CMAKE_BINARY_DIR}" "${CYTHON_OUTPUT}")
172+
file(RELATIVE_PATH input_file_relative "${CMAKE_SOURCE_DIR}" "${INPUT}")
173+
174+
# Add the command to run the compiler.
175+
add_custom_command(
176+
OUTPUT
177+
"${CYTHON_OUTPUT}"
178+
"${depfile_path}"
179+
COMMAND
180+
${_cython_command}
181+
${language_arg}
182+
${CYTHON_CYTHON_ARGS}
183+
--depfile
184+
"${INPUT}"
185+
--output-file "${CYTHON_OUTPUT}"
186+
MAIN_DEPENDENCY
187+
"${INPUT}"
188+
DEPFILE
189+
"${depfile_path}"
190+
VERBATIM
191+
COMMENT
192+
"Cythonizing source ${input_file_relative} to output ${generated_file_relative}"
193+
)
240194
endfunction()
241195

242196
function(_cython_compute_language OUTPUT_VARIABLE FILENAME)

0 commit comments

Comments
 (0)