Page Menu
Home
c4science
Search
Configure Global Search
Log In
Files
F92619087
UseCython.cmake
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Subscribers
None
File Metadata
Details
File Info
Storage
Attached
Created
Fri, Nov 22, 02:41
Size
11 KB
Mime Type
text/x-c
Expires
Sun, Nov 24, 02:41 (1 d, 23 h)
Engine
blob
Format
Raw Data
Handle
22461849
Attached To
rSPECMICP SpecMiCP / ReactMiCP
UseCython.cmake
View Options
# 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( <module_name> <src1> <src2> ... <srcN> )
#
# To create a standalone executable, the function
#
# cython_add_standalone_executable( <executable_name> [MAIN_MODULE src1] <src1> <src2> ... <srcN> )
#
# To avoid dependence on Python, set the PYTHON_LIBRARY cache variable to point
# to a static library. If a MAIN_MODULE source is specified,
# the "if __name__ == '__main__':" from that module is used as the C main() method
# for the executable. If MAIN_MODULE, the source with the same basename as
# <executable_name> is assumed to be the MAIN_MODULE.
#
# Where <module_name> is the name of the resulting Python module and
# <src1> <src2> ... are source files to be compiled into the module, e.g. *.pyx,
# *.py, *.c, *.cxx, etc. A CMake target is created with name <module_name>. This can
# be used for target_link_libraries(), etc.
#
# The sample paths set with the CMake include_directories() command will be used
# for include directories to search for *.pxd when running the Cython complire.
#
# 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
#
# If this is set of a *.pyx file with CMake set_source_files_properties()
# command, the file will be compiled as a C++ file.
#
# 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
(
PythonLibs
REQUIRED
)
set
(
CYTHON_CXX_EXTENSION
"cxx"
)
set
(
CYTHON_C_EXTENSION
"c"
)
# Create a *.c or *.cxx file from a *.pyx file.
# Input the generated file basename. The generate file will put into the variable
# placed in the "generated_file" argument. Finally all the *.py and *.pyx files.
function
(
compile_pyx
_name
generated_file
)
# Default to assuming all files are C.
set
(
cxx_arg
""
)
set
(
extension
${
CYTHON_C_EXTENSION
}
)
set
(
pyx_lang
"C"
)
set
(
comment
"Compiling Cython C source for ${_name}..."
)
set
(
cython_include_directories
""
)
set
(
pxd_dependencies
""
)
set
(
c_header_dependencies
""
)
set
(
pyx_locations
""
)
foreach
(
pyx_file
${
ARGN
}
)
get_filename_component
(
pyx_file_basename
"${pyx_file}"
NAME_WE
)
# Determine if it is a C or C++ file.
get_source_file_property
(
property_is_cxx
${
pyx_file
}
CYTHON_IS_CXX
)
if
(
${
property_is_cxx
}
)
set
(
cxx_arg
"--cplus"
)
set
(
extension
${
CYTHON_CXX_EXTENSION
}
)
set
(
pyx_lang
"CXX"
)
set
(
comment
"Compiling Cython CXX source for ${_name}..."
)
endif
()
# Get the include directories.
get_source_file_property
(
pyx_location
${
pyx_file
}
LOCATION
)
get_filename_component
(
pyx_path
${
pyx_location
}
PATH
)
get_directory_property
(
cmake_include_directories
DIRECTORY
${
pyx_path
}
INCLUDE_DIRECTORIES
)
list
(
APPEND
cython_include_directories
${
cmake_include_directories
}
)
list
(
APPEND
pyx_locations
"${pyx_location}"
)
# Determine dependencies.
# Add the pxd file will the same name as the given pyx file.
unset
(
corresponding_pxd_file
CACHE
)
find_file
(
corresponding_pxd_file
${
pyx_file_basename
}
.pxd
PATHS
"${pyx_path}"
${
cmake_include_directories
}
NO_DEFAULT_PATH
)
if
(
corresponding_pxd_file
)
list
(
APPEND
pxd_dependencies
"${corresponding_pxd_file}"
)
endif
()
# pxd files to check for additional dependencies.
set
(
pxds_to_check
"${pyx_file}"
"${pxd_dependencies}"
)
set
(
pxds_checked
""
)
set
(
number_pxds_to_check
1
)
while
(
${
number_pxds_to_check
}
GREATER
0
)
foreach
(
pxd
${
pxds_to_check
}
)
list
(
APPEND
pxds_checked
"${pxd}"
)
list
(
REMOVE_ITEM
pxds_to_check
"${pxd}"
)
# check for C header dependencies
file
(
STRINGS
"${pxd}"
extern_from_statements
REGEX
"cdef[ ]+extern[ ]+from.*$"
)
foreach
(
statement
${
extern_from_statements
}
)
# Had trouble getting the quote in the regex
string
(
REGEX
REPLACE
"cdef[ ]+extern[ ]+from[ ]+[\"
]([^\
"]+)[\"
].*
" "
\\1"
header
"${statement}"
)
unset
(
header_location
CACHE
)
find_file
(
header_location
${
header
}
PATHS
${
cmake_include_directories
}
)
if
(
header_location
)
list
(
FIND
c_header_dependencies
"${header_location}"
header_idx
)
if
(
${
header_idx
}
LESS
0
)
list
(
APPEND
c_header_dependencies
"${header_location}"
)
endif
()
endif
()
endforeach
()
# check for pxd dependencies
# Look for cimport statements.
set
(
module_dependencies
""
)
file
(
STRINGS
"${pxd}"
cimport_statements
REGEX
cimport
)
foreach
(
statement
${
cimport_statements
}
)
if
(
${
statement
}
MATCHES
from
)
string
(
REGEX
REPLACE
"from[ ]+([^ ]+).*"
"\\1"
module
"${statement}"
)
else
()
string
(
REGEX
REPLACE
"cimport[ ]+([^ ]+).*"
"\\1"
module
"${statement}"
)
endif
()
list
(
APPEND
module_dependencies
${
module
}
)
endforeach
()
list
(
REMOVE_DUPLICATES
module_dependencies
)
# Add the module to the files to check, if appropriate.
foreach
(
module
${
module_dependencies
}
)
unset
(
pxd_location
CACHE
)
find_file
(
pxd_location
${
module
}
.pxd
PATHS
"${pyx_path}"
${
cmake_include_directories
}
NO_DEFAULT_PATH
)
if
(
pxd_location
)
list
(
FIND
pxds_checked
${
pxd_location
}
pxd_idx
)
if
(
${
pxd_idx
}
LESS
0
)
list
(
FIND
pxds_to_check
${
pxd_location
}
pxd_idx
)
if
(
${
pxd_idx
}
LESS
0
)
list
(
APPEND
pxds_to_check
${
pxd_location
}
)
list
(
APPEND
pxd_dependencies
${
pxd_location
}
)
endif
()
# if it is not already going to be checked
endif
()
# if it has not already been checked
endif
()
# if pxd file can be found
endforeach
()
# for each module dependency discovered
endforeach
()
# for each pxd file to check
list
(
LENGTH
pxds_to_check
number_pxds_to_check
)
endwhile
()
endforeach
()
# pyx_file
# Set additional flags.
if
(
CYTHON_ANNOTATE
)
set
(
annotate_arg
"--annotate"
)
endif
()
if
(
CYTHON_NO_DOCSTRINGS
)
set
(
no_docstrings_arg
"--no-docstrings"
)
endif
()
if
(
"${CMAKE_BUILD_TYPE}"
STREQUAL
"Debug"
OR
"${CMAKE_BUILD_TYPE}"
STREQUAL
"RelWithDebInfo"
)
set
(
cython_debug_arg
"--gdb"
)
endif
()
if
(
"${PYTHONLIBS_VERSION_STRING}"
MATCHES
"^2."
)
set
(
version_arg
"-2"
)
elseif
(
"${PYTHONLIBS_VERSION_STRING}"
MATCHES
"^3."
)
set
(
version_arg
"-3"
)
else
()
set
(
version_arg
)
endif
()
# Include directory arguments.
list
(
REMOVE_DUPLICATES
cython_include_directories
)
set
(
include_directory_arg
""
)
foreach
(
_include_dir
${
cython_include_directories
}
)
set
(
include_directory_arg
${
include_directory_arg
}
"-I"
"${_include_dir}"
)
endforeach
()
# Determining generated file name.
set
(
_generated_file
"${CMAKE_CURRENT_BINARY_DIR}/${_name}.${extension}"
)
set_source_files_properties
(
${
_generated_file
}
PROPERTIES
GENERATED
TRUE
)
set
(
${
generated_file
}
${
_generated_file
}
PARENT_SCOPE
)
list
(
REMOVE_DUPLICATES
pxd_dependencies
)
list
(
REMOVE_DUPLICATES
c_header_dependencies
)
# Add the command to run the compiler.
add_custom_command
(
OUTPUT
${
_generated_file
}
COMMAND
${
CYTHON_EXECUTABLE
}
ARGS
${
cxx_arg
}
${
include_directory_arg
}
${
version_arg
}
${
annotate_arg
}
${
no_docstrings_arg
}
${
cython_debug_arg
}
${
CYTHON_FLAGS
}
--output-file
${
_generated_file
}
${
pyx_locations
}
DEPENDS
${
pyx_locations
}
${
pxd_dependencies
}
IMPLICIT_DEPENDS
${
pyx_lang
}
${
c_header_dependencies
}
COMMENT
${
comment
}
)
# Remove their visibility to the user.
set
(
corresponding_pxd_file
""
CACHE
INTERNAL
""
)
set
(
header_location
""
CACHE
INTERNAL
""
)
set
(
pxd_location
""
CACHE
INTERNAL
""
)
endfunction
()
# cython_add_module( <name> src1 src2 ... srcN )
# Build the Cython Python module.
function
(
cython_add_module
_name
)
set
(
pyx_module_sources
""
)
set
(
other_module_sources
""
)
foreach
(
_file
${
ARGN
}
)
if
(
${
_file
}
MATCHES
".*\\.py[x]?$"
)
list
(
APPEND
pyx_module_sources
${
_file
}
)
else
()
list
(
APPEND
other_module_sources
${
_file
}
)
endif
()
endforeach
()
compile_pyx
(
${
_name
}
generated_file
${
pyx_module_sources
}
)
include_directories
(
${
PYTHON_INCLUDE_DIRS
}
)
python_add_module
(
${
_name
}
${
generated_file
}
${
other_module_sources
}
)
if
(
APPLE
)
set_target_properties
(
${
_name
}
PROPERTIES
LINK_FLAGS
"-undefined dynamic_lookup"
)
else
()
target_link_libraries
(
${
_name
}
${
PYTHON_LIBRARIES
}
)
endif
()
endfunction
()
include
(
CMakeParseArguments
)
# cython_add_standalone_executable( _name [MAIN_MODULE src3.py] src1 src2 ... srcN )
# Creates a standalone executable the given sources.
function
(
cython_add_standalone_executable
_name
)
set
(
pyx_module_sources
""
)
set
(
other_module_sources
""
)
set
(
main_module
""
)
cmake_parse_arguments
(
cython_arguments
""
"MAIN_MODULE"
""
${
ARGN
}
)
include_directories
(
${
PYTHON_INCLUDE_DIRS
}
)
foreach
(
_file
${
cython_arguments_UNPARSED_ARGUMENTS
}
)
if
(
${
_file
}
MATCHES
".*\\.py[x]?$"
)
get_filename_component
(
_file_we
${
_file
}
NAME_WE
)
if
(
"${_file_we}"
STREQUAL
"${_name}"
)
set
(
main_module
"${_file}"
)
elseif
(
NOT
"${_file}"
STREQUAL
"${cython_arguments_MAIN_MODULE}"
)
set
(
PYTHON_MODULE_
${
_file_we
}
_static_BUILD_SHARED
OFF
)
compile_pyx
(
"${_file_we}_static"
generated_file
"${_file}"
)
list
(
APPEND
pyx_module_sources
"${generated_file}"
)
endif
()
else
()
list
(
APPEND
other_module_sources
${
_file
}
)
endif
()
endforeach
()
if
(
cython_arguments_MAIN_MODULE
)
set
(
main_module
${
cython_arguments_MAIN_MODULE
}
)
endif
()
if
(
NOT
main_module
)
message
(
FATAL_ERROR
"main module not found."
)
endif
()
get_filename_component
(
main_module_we
"${main_module}"
NAME_WE
)
set
(
CYTHON_FLAGS
${
CYTHON_FLAGS
}
--embed
)
compile_pyx
(
"${main_module_we}_static"
generated_file
${
main_module
}
)
add_executable
(
${
_name
}
${
generated_file
}
${
pyx_module_sources
}
${
other_module_sources
}
)
target_link_libraries
(
${
_name
}
${
PYTHON_LIBRARIES
}
${
pyx_module_libs
}
)
endfunction
()
Event Timeline
Log In to Comment