diff options
-rw-r--r-- | .github/workflows/ci.yml | 1 | ||||
-rw-r--r-- | INSTALL.md | 7 | ||||
-rw-r--r-- | cmake/FindCython.cmake | 77 | ||||
-rw-r--r-- | cmake/FindPythonExtensions.cmake | 503 | ||||
-rw-r--r-- | cmake/UseCython.cmake | 402 | ||||
-rw-r--r-- | cmake/targetLinkLibrariesWithDynamicLookup.cmake | 478 | ||||
-rw-r--r-- | src/api/python/CMakeLists.txt | 38 | ||||
-rw-r--r-- | src/api/python/setup.py.in | 26 |
8 files changed, 54 insertions, 1478 deletions
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0d9ed04a3..b9ec42af3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -100,6 +100,7 @@ jobs: run: | python3 -m pip install pytest python3 -m pytest --version + python3 -m pip install scikit-build python3 -m pip install \ Cython==0.29.* --install-option="--no-cython-compile" echo "$(python3 -m site --user-base)/bin" >> $GITHUB_PATH diff --git a/INSTALL.md b/INSTALL.md index ca98d7c3a..41f770288 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -180,6 +180,13 @@ examples). It further provides Java (see `examples/SimpleVC.java` and Configure cvc5 with `configure.sh --<lang>-bindings` to build with language bindings for `<lang>`. +### Dependencies for Language Bindings + +* Python + * [Cython](https://cython.org/) + * [scikit-build](https://pypi.org/project/scikit-build/) + * [pytest](https://docs.pytest.org/en/6.2.x/) + If you're interested in helping to develop, maintain, and test a language binding, please contact one of the project leaders. diff --git a/cmake/FindCython.cmake b/cmake/FindCython.cmake deleted file mode 100644 index 6294d2429..000000000 --- a/cmake/FindCython.cmake +++ /dev/null @@ -1,77 +0,0 @@ -#.rst: -# FindCython -# ---------- -# -# Find ``cython`` executable. -# -# This module defines the following variables: -# -# ``CYTHON_EXECUTABLE`` -# path to the ``cython`` program -# -# ``CYTHON_VERSION`` -# version of ``cython`` -# -# ``CYTHON_FOUND`` -# true if the program was found -# -# See also UseCython.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. -#============================================================================= - -# Use the Cython executable that lives next to the Python executable -# if it is a local installation. -find_package(PythonInterp) -if(PYTHONINTERP_FOUND) - get_filename_component(_python_path ${PYTHON_EXECUTABLE} PATH) - find_program(CYTHON_EXECUTABLE - NAMES cython cython.bat cython3 - HINTS ${_python_path} - DOC "path to the cython executable") -else() - find_program(CYTHON_EXECUTABLE - NAMES cython cython.bat cython3 - DOC "path to the cython executable") -endif() - -if(CYTHON_EXECUTABLE) - set(CYTHON_version_command ${CYTHON_EXECUTABLE} --version) - - execute_process(COMMAND ${CYTHON_version_command} - OUTPUT_VARIABLE CYTHON_version_output - ERROR_VARIABLE CYTHON_version_error - RESULT_VARIABLE CYTHON_version_result - OUTPUT_STRIP_TRAILING_WHITESPACE) - - if(NOT ${CYTHON_version_result} EQUAL 0) - set(_error_msg "Command \"${CYTHON_version_command}\" failed with") - set(_error_msg "${_error_msg} output:\n${CYTHON_version_error}") - message(SEND_ERROR "${_error_msg}") - else() - if("${CYTHON_version_output}" MATCHES "^[Cc]ython version ([^,]+)") - set(CYTHON_VERSION "${CMAKE_MATCH_1}") - endif() - endif() -endif() - -include(FindPackageHandleStandardArgs) -FIND_PACKAGE_HANDLE_STANDARD_ARGS(Cython REQUIRED_VARS CYTHON_EXECUTABLE) - -mark_as_advanced(CYTHON_EXECUTABLE) - -include(UseCython) - diff --git a/cmake/FindPythonExtensions.cmake b/cmake/FindPythonExtensions.cmake deleted file mode 100644 index 892e17c08..000000000 --- a/cmake/FindPythonExtensions.cmake +++ /dev/null @@ -1,503 +0,0 @@ -#.rst -# Define functions to create Python modules and executables. -# -# This file defines CMake functions to build Python extension modules and -# stand-alone executables. To use it, first include this file. -# -# find_package(PythonExtensions) -# -# The following variables are defined: -# :: -# -# PYTHON_PREFIX - absolute path to the current Python -# distribution's prefix -# PYTHON_SITE_PACKAGES_DIR - absolute path to the current Python -# distribution's site-packages directory -# PYTHON_RELATIVE_SITE_PACKAGES_DIR - path to the current Python -# distribution's site-packages directory -# relative to its prefix -# PYTHON_SEPARATOR - separator string for file path -# components. Equivalent to ``os.sep`` in -# Python. -# PYTHON_PATH_SEPARATOR - separator string for PATH-style -# environment variables. Equivalent to -# ``os.pathsep`` in Python. -# -# The following functions are defined: -# -# python_extension_module(<Target> -# [LINKED_MODULES_VAR <LinkedModVar>] -# [FORWARD_DECL_MODULES_VAR <ForwardDeclModVar>]) -# -# For libraries meant to be used as Python extension modules, either dynamically -# loaded or directly linked. Amend the configuration of the library target -# (created using ``add_library``) with additional options needed to build and -# use the referenced library as a Python extension module. -# -# Only extension modules that are configured to be built as MODULE libraries can -# be runtime-loaded through the standard Python import mechanism. All other -# modules can only be included in standalone applications that are written to -# expect their presence. In addition to being linked against the libraries for -# these modules, such applications must forward declare their entry points and -# initialize them prior to use. To generate these forward declarations and -# initializations, see ``python_modules_header``. -# -# If ``<Target>`` does not refer to a target, then it is assumed to refer to an -# extension module that is not linked at all, but compiled along with other -# source files directly into an executable. Adding these modules does not cause -# any library configuration modifications, and they are not added to the list of -# linked modules. They still must be forward declared and initialized, however, -# and so are added to the forward declared modules list. -# -# Options: -# -# ``LINKED_MODULES_VAR <LinkedModVar>`` -# Name of the variable referencing a list of extension modules whose libraries -# must be linked into the executables of any stand-alone applications that use -# them. By default, the global property ``PY_LINKED_MODULES_LIST`` is used. -# -# ``FORWARD_DECL_MODULES_VAR <ForwardDeclModVar>`` -# Name of the variable referencing a list of extension modules whose entry -# points must be forward declared and called by any stand-alone applications -# that use them. By default, the global property -# ``PY_FORWARD_DECL_MODULES_LIST`` is used. -# -# -# python_standalone_executable(<Target>) -# -# For standalone executables that initialize their own Python runtime -# (such as when building source files that include one generated by Cython with -# the --embed option). Amend the configuration of the executable target -# (created using ``add_executable``) with additional options needed to properly -# build the referenced executable. -# -# python_modules_header(<Name> [HeaderFilename] -# [FORWARD_DECL_MODULES_LIST <ForwardDeclModList>] -# [HEADER_OUTPUT_VAR <HeaderOutputVar>] -# [INCLUDE_DIR_OUTPUT_VAR <IncludeDirOutputVar>]) -# -# Generate a header file that contains the forward declarations and -# initialization routines for the given list of Python extension modules. -# ``<Name>`` is the logical name for the header file (no file extensions). -# ``<HeaderFilename>`` is the actual destination filename for the header file -# (e.g.: decl_modules.h). -# -# If only ``<Name>`` is provided, and it ends in the ".h" extension, then it -# is assumed to be the ``<HeaderFilename>``. The filename of the header file -# without the extension is used as the logical name. If only ``<Name>`` is -# provided, and it does not end in the ".h" extension, then the -# ``<HeaderFilename>`` is assumed to ``<Name>.h``. -# -# The exact contents of the generated header file depend on the logical -# ``<Name>``. It should be set to a value that corresponds to the target -# application, or for the case of multiple applications, some identifier that -# conveyes its purpose. It is featured in the generated multiple inclusion -# guard as well as the names of the generated initialization routines. -# -# The generated header file includes forward declarations for all listed -# modules, as well as implementations for the following class of routines: -# -# ``int <Name>_<Module>(void)`` -# Initializes the python extension module, ``<Module>``. Returns an integer -# handle to the module. -# -# ``void <Name>_LoadAllPythonModules(void)`` -# Initializes all listed python extension modules. -# -# ``void CMakeLoadAllPythonModules(void);`` -# Alias for ``<Name>_LoadAllPythonModules`` whose name does not depend on -# ``<Name>``. This function is excluded during preprocessing if the -# preprocessing macro ``EXCLUDE_LOAD_ALL_FUNCTION`` is defined. -# -# ``void Py_Initialize_Wrapper();`` -# Wrapper arpund ``Py_Initialize()`` that initializes all listed python -# extension modules. This function is excluded during preprocessing if the -# preprocessing macro ``EXCLUDE_PY_INIT_WRAPPER`` is defined. If this -# function is generated, then ``Py_Initialize()`` is redefined to a macro -# that calls this function. -# -# Options: -# -# ``FORWARD_DECL_MODULES_LIST <ForwardDeclModList>`` -# List of extension modules for which to generate forward declarations of -# their entry points and their initializations. By default, the global -# property ``PY_FORWARD_DECL_MODULES_LIST`` is used. - -# ``HEADER_OUTPUT_VAR <HeaderOutputVar>`` -# Name of the variable to set to the path to the generated header file. By -# default, ``<Name>`` is used. -# -# ``INCLUDE_DIR_OUTPUT_VAR <IncludeDirOutputVar>`` -# Name of the variable to set to the path to the directory containing the -# generated header file. By default, ``<Name>_INCLUDE_DIRS`` is used. -# -# Defined variables: -# -# ``<HeaderOutputVar>`` -# The path to the generated header file -# -# ``<IncludeDirOutputVar>`` -# Directory containing the generated header file -# -# Example usage: -# -# .. code-block:: cmake -# -# find_package(PythonInterp) -# find_package(PythonLibs) -# find_package(PythonExtensions) -# find_package(Cython) -# find_package(Boost COMPONENTS python) -# -# # Simple Cython Module -- no executables -# add_cython_target(_module.pyx) -# add_library(_module MODULE ${_module}) -# python_extension_module(_module) -# -# # Mix of Cython-generated code and C++ code using Boost Python -# # Stand-alone executable -- no modules -# include_directories(${Boost_INCLUDE_DIRS}) -# add_cython_target(main.pyx CXX EMBED_MAIN) -# add_executable(main boost_python_module.cxx ${main}) -# target_link_libraries(main ${Boost_LIBRARIES}) -# python_standalone_executable(main) -# -# # stand-alone executable with three extension modules: -# # one statically linked, one dynamically linked, and one loaded at runtime -# # -# # Freely mixes Cython-generated code, code using Boost-Python, and -# # hand-written code using the CPython API. -# -# # module1 -- statically linked -# add_cython_target(module1.pyx) -# add_library(module1 STATIC ${module1}) -# python_extension_module(module1 -# LINKED_MODULES_VAR linked_module_list -# FORWARD_DECL_MODULES_VAR fdecl_module_list) -# -# # module2 -- dynamically linked -# include_directories({Boost_INCLUDE_DIRS}) -# add_library(module2 SHARED boost_module2.cxx) -# target_link_libraries(module2 ${Boost_LIBRARIES}) -# python_extension_module(module2 -# LINKED_MODULES_VAR linked_module_list -# FORWARD_DECL_MODULES_VAR fdecl_module_list) -# -# # module3 -- loaded at runtime -# add_cython_target(module3a.pyx) -# add_library(module1 MODULE ${module3a} module3b.cxx) -# target_link_libraries(module3 ${Boost_LIBRARIES}) -# python_extension_module(module3 -# LINKED_MODULES_VAR linked_module_list -# FORWARD_DECL_MODULES_VAR fdecl_module_list) -# -# # application executable -- generated header file + other source files -# python_modules_header(modules -# FORWARD_DECL_MODULES_LIST ${fdecl_module_list}) -# include_directories(${modules_INCLUDE_DIRS}) -# -# add_cython_target(mainA) -# add_cython_target(mainC) -# add_executable(main ${mainA} mainB.cxx ${mainC} mainD.c) -# -# target_link_libraries(main ${linked_module_list} ${Boost_LIBRARIES}) -# python_standalone_executable(main) -# -#============================================================================= -# 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. -#============================================================================= - -find_package(PythonInterp REQUIRED) -find_package(PythonLibs) -include(targetLinkLibrariesWithDynamicLookup) - -set(_command " -import distutils.sysconfig -import itertools -import os -import os.path -import site -import sys - -result = None -rel_result = None -candidate_lists = [] - -try: - candidate_lists.append((distutils.sysconfig.get_python_lib(),)) -except AttributeError: pass - -try: - candidate_lists.append(site.getsitepackages()) -except AttributeError: pass - -try: - candidate_lists.append((site.getusersitepackages(),)) -except AttributeError: pass - -candidates = itertools.chain.from_iterable(candidate_lists) - -for candidate in candidates: - rel_candidate = os.path.relpath( - candidate, sys.prefix) - if not rel_candidate.startswith(\"..\"): - result = candidate - rel_result = rel_candidate - break - -sys.stdout.write(\";\".join(( - os.sep, - os.pathsep, - sys.prefix, - result, - rel_result, -))) -") - -execute_process(COMMAND "${PYTHON_EXECUTABLE}" -c "${_command}" - OUTPUT_VARIABLE _list - RESULT_VARIABLE _result) - -list(GET _list 0 _item) -set(PYTHON_SEPARATOR "${_item}") -mark_as_advanced(PYTHON_SEPARATOR) - -list(GET _list 1 _item) -set(PYTHON_PATH_SEPARATOR "${_item}") -mark_as_advanced(PYTHON_PATH_SEPARATOR) - -list(GET _list 2 _item) -set(PYTHON_PREFIX "${_item}") -mark_as_advanced(PYTHON_PREFIX) - -list(GET _list 3 _item) -set(PYTHON_SITE_PACKAGES_DIR "${_item}") -mark_as_advanced(PYTHON_SITE_PACKAGES_DIR) - -list(GET _list 4 _item) -set(PYTHON_RELATIVE_SITE_PACKAGES_DIR "${_item}") -mark_as_advanced(PYTHON_RELATIVE_SITE_PACKAGES_DIR) - -function(python_extension_module _target) - set(one_ops LINKED_MODULES_VAR FORWARD_DECL_MODULES_VAR) - cmake_parse_arguments(_args "" "${one_ops}" "" ${ARGN}) - - set(_lib_type "NA") - if(TARGET ${_target}) - get_property(_lib_type TARGET ${_target} PROPERTY TYPE) - endif() - - set(_is_non_lib TRUE) - - set(_is_static_lib FALSE) - if(_lib_type STREQUAL "STATIC_LIBRARY") - set(_is_static_lib TRUE) - set(_is_non_lib FALSE) - endif() - - set(_is_shared_lib FALSE) - if(_lib_type STREQUAL "SHARED_LIBRARY") - set(_is_shared_lib TRUE) - set(_is_non_lib FALSE) - endif() - - set(_is_module_lib FALSE) - if(_lib_type STREQUAL "MODULE_LIBRARY") - set(_is_module_lib TRUE) - set(_is_non_lib FALSE) - endif() - - if(_is_static_lib OR _is_shared_lib OR _is_non_lib) - - if(_is_static_lib OR _is_shared_lib) - if(_args_LINKED_MODULES_VAR) - set(${_args_LINKED_MODULES_VAR} - ${${_args_LINKED_MODULES_VAR}} ${_target} PARENT_SCOPE) - else() - set_property(GLOBAL APPEND PROPERTY PY_LINKED_MODULES_LIST ${_target}) - endif() - endif() - - if(_args_FORWARD_DECL_MODULES_VAR) - set(${_args_FORWARD_DECL_MODULES_VAR} - ${${_args_FORWARD_DECL_MODULES_VAR}} ${_target} PARENT_SCOPE) - else() - set_property(GLOBAL APPEND PROPERTY - PY_FORWARD_DECL_MODULES_LIST ${_target}) - endif() - endif() - - if(NOT _is_non_lib) - include_directories("${PYTHON_INCLUDE_DIRS}") - endif() - - if(_is_module_lib) - set_target_properties(${_target} PROPERTIES - PREFIX "${PYTHON_MODULE_PREFIX}") - endif() - - if(_is_module_lib OR _is_shared_lib) - if(_is_module_lib AND WIN32 AND NOT CYGWIN) - set_target_properties(${_target} PROPERTIES SUFFIX ".pyd") - endif() - - target_link_libraries_with_dynamic_lookup(${_target} ${PYTHON_LIBRARIES}) - endif() -endfunction() - -function(python_standalone_executable _target) - include_directories(${PYTHON_INCLUDE_DIRS}) - target_link_libraries(${_target} ${PYTHON_LIBRARIES}) -endfunction() - -function(python_modules_header _name) - set(one_ops FORWARD_DECL_MODULES_LIST - HEADER_OUTPUT_VAR - INCLUDE_DIR_OUTPUT_VAR) - cmake_parse_arguments(_args "" "${one_ops}" "" ${ARGN}) - - list(GET _args_UNPARSED_ARGUMENTS 0 _arg0) - # if present, use arg0 as the input file path - if(_arg0) - set(_source_file ${_arg0}) - - # otherwise, must determine source file from name, or vice versa - else() - get_filename_component(_name_ext "${_name}" EXT) - - # if extension provided, _name is the source file - if(_name_ext) - set(_source_file ${_name}) - get_filename_component(_name "${_source_file}" NAME_WE) - - # otherwise, assume the source file is ${_name}.h - else() - set(_source_file ${_name}.h) - endif() - endif() - - if(_args_FORWARD_DECL_MODULES_LIST) - set(static_mod_list ${_args_FORWARD_DECL_MODULES_LIST}) - else() - get_property(static_mod_list GLOBAL PROPERTY PY_FORWARD_DECL_MODULES_LIST) - endif() - - string(REPLACE "." "_" _header_name "${_name}") - string(TOUPPER ${_header_name} _header_name_upper) - set(_header_name_upper "_${_header_name_upper}_H") - set(generated_file ${CMAKE_CURRENT_BINARY_DIR}/${_source_file}) - - set(generated_file_tmp "${generated_file}.in") - file(WRITE ${generated_file_tmp} - "/* Created by CMake. DO NOT EDIT; changes will be lost. */\n") - - set(_chunk "") - set(_chunk "${_chunk}#ifndef ${_header_name_upper}\n") - set(_chunk "${_chunk}#define ${_header_name_upper}\n") - set(_chunk "${_chunk}\n") - set(_chunk "${_chunk}#include <Python.h>\n") - set(_chunk "${_chunk}\n") - set(_chunk "${_chunk}#ifdef __cplusplus\n") - set(_chunk "${_chunk}extern \"C\" {\n") - set(_chunk "${_chunk}#endif /* __cplusplus */\n") - set(_chunk "${_chunk}\n") - set(_chunk "${_chunk}#if PY_MAJOR_VERSION < 3\n") - file(APPEND ${generated_file_tmp} "${_chunk}") - - foreach(_module ${static_mod_list}) - file(APPEND ${generated_file_tmp} - "PyMODINIT_FUNC init${PYTHON_MODULE_PREFIX}${_module}(void);\n") - endforeach() - - file(APPEND ${generated_file_tmp} "#else /* PY_MAJOR_VERSION >= 3*/\n") - - foreach(_module ${static_mod_list}) - file(APPEND ${generated_file_tmp} - "PyMODINIT_FUNC PyInit_${PYTHON_MODULE_PREFIX}${_module}(void);\n") - endforeach() - - set(_chunk "") - set(_chunk "${_chunk}#endif /* PY_MAJOR_VERSION >= 3*/\n\n") - set(_chunk "${_chunk}#ifdef __cplusplus\n") - set(_chunk "${_chunk}}\n") - set(_chunk "${_chunk}#endif /* __cplusplus */\n") - set(_chunk "${_chunk}\n") - file(APPEND ${generated_file_tmp} "${_chunk}") - - foreach(_module ${static_mod_list}) - set(_import_function "${_header_name}_${_module}") - set(_prefixed_module "${PYTHON_MODULE_PREFIX}${_module}") - - set(_chunk "") - set(_chunk "${_chunk}int ${_import_function}(void)\n") - set(_chunk "${_chunk}{\n") - set(_chunk "${_chunk} static char name[] = \"${_prefixed_module}\";\n") - set(_chunk "${_chunk} #if PY_MAJOR_VERSION < 3\n") - set(_chunk "${_chunk} return PyImport_AppendInittab(") - set(_chunk "${_chunk}name, init${_prefixed_module});\n") - set(_chunk "${_chunk} #else /* PY_MAJOR_VERSION >= 3 */\n") - set(_chunk "${_chunk} return PyImport_AppendInittab(") - set(_chunk "${_chunk}name, PyInit_${_prefixed_module});\n") - set(_chunk "${_chunk} #endif /* PY_MAJOR_VERSION >= 3 */\n") - set(_chunk "${_chunk}}\n\n") - file(APPEND ${generated_file_tmp} "${_chunk}") - endforeach() - - file(APPEND ${generated_file_tmp} - "void ${_header_name}_LoadAllPythonModules(void)\n{\n") - foreach(_module ${static_mod_list}) - file(APPEND ${generated_file_tmp} " ${_header_name}_${_module}();\n") - endforeach() - file(APPEND ${generated_file_tmp} "}\n\n") - - set(_chunk "") - set(_chunk "${_chunk}#ifndef EXCLUDE_LOAD_ALL_FUNCTION\n") - set(_chunk "${_chunk}void CMakeLoadAllPythonModules(void)\n") - set(_chunk "${_chunk}{\n") - set(_chunk "${_chunk} ${_header_name}_LoadAllPythonModules();\n") - set(_chunk "${_chunk}}\n") - set(_chunk "${_chunk}#endif /* !EXCLUDE_LOAD_ALL_FUNCTION */\n\n") - - set(_chunk "${_chunk}#ifndef EXCLUDE_PY_INIT_WRAPPER\n") - set(_chunk "${_chunk}static void Py_Initialize_Wrapper()\n") - set(_chunk "${_chunk}{\n") - set(_chunk "${_chunk} ${_header_name}_LoadAllPythonModules();\n") - set(_chunk "${_chunk} Py_Initialize();\n") - set(_chunk "${_chunk}}\n") - set(_chunk "${_chunk}#define Py_Initialize Py_Initialize_Wrapper\n") - set(_chunk "${_chunk}#endif /* !EXCLUDE_PY_INIT_WRAPPER */\n\n") - - set(_chunk "${_chunk}#endif /* !${_header_name_upper} */\n") - file(APPEND ${generated_file_tmp} "${_chunk}") - - # with configure_file() cmake complains that you may not use a file created - # using file(WRITE) as input file for configure_file() - execute_process(COMMAND ${CMAKE_COMMAND} -E copy_if_different - "${generated_file_tmp}" "${generated_file}" - OUTPUT_QUIET ERROR_QUIET) - - set(_header_output_var ${_name}) - if(_args_HEADER_OUTPUT_VAR) - set(_header_output_var ${_args_HEADER_OUTPUT_VAR}) - endif() - set(${_header_output_var} ${generated_file} PARENT_SCOPE) - - set(_include_dir_var ${_name}_INCLUDE_DIRS) - if(_args_INCLUDE_DIR_OUTPUT_VAR) - set(_include_dir_var ${_args_INCLUDE_DIR_OUTPUT_VAR}) - endif() - set(${_include_dirs_var} ${CMAKE_CURRENT_BINARY_DIR} PARENT_SCOPE) -endfunction() - diff --git a/cmake/UseCython.cmake b/cmake/UseCython.cmake deleted file mode 100644 index c79e43f01..000000000 --- a/cmake/UseCython.cmake +++ /dev/null @@ -1,402 +0,0 @@ -#.rst -# 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) -# -# The following functions are defined: -# -# add_cython_target(<Name> [<CythonInput>] -# [EMBED_MAIN] -# [C | CXX] -# [PY2 | PY3] -# [OUTPUT_VAR <OutputVar>]) -# -# Create a custom rule to generate the source code for a Python extension module -# using cython. ``<Name>`` is the name of the new target, and ``<CythonInput>`` -# is the path to a cython source file. Note that, despite the name, no new -# targets are created by this function. Instead, see ``OUTPUT_VAR`` for -# retrieving the path to the generated source for subsequent targets. -# -# If only ``<Name>`` is provided, and it ends in the ".pyx" extension, then it -# is assumed to be the ``<CythonInput>``. The name of the input without the -# extension is used as the target name. If only ``<Name>`` is provided, and it -# does not end in the ".pyx" extension, then the ``<CythonInput>`` is assumed to -# be ``<Name>.pyx``. -# -# The Cython include search path is amended with any entries found in the -# ``INCLUDE_DIRECTORIES`` property of the directory containing the -# ``<CythonInput>`` file. Use ``iunclude_directories`` to add to the Cython -# include search path. -# -# Options: -# -# ``EMBED_MAIN`` -# Embed a main() function in the generated output (for stand-alone -# applications that initialize their own Python runtime). -# -# ``C | CXX`` -# Force the generation of either a C or C++ file. By default, a C file is -# generated, unless the C language is not enabled for the project; in this -# case, a C++ file is generated by default. -# -# ``PY2 | PY3`` -# Force compilation using either Python-2 or Python-3 syntax and code -# semantics. By default, Python-2 syntax and semantics are used if the major -# version of Python found is 2. Otherwise, Python-3 syntax and sematics are -# used. -# -# ``OUTPUT_VAR <OutputVar>`` -# Set the variable ``<OutputVar>`` in the parent scope to the path to the -# generated source file. By default, ``<Name>`` is used as the output -# variable name. -# -# Defined variables: -# -# ``<OutputVar>`` -# The path of the generated source file. -# -# -# Example usage: -# -# .. code-block:: cmake -# -# find_package(Cython) -# -# # Note: In this case, either one of these arguments may be omitted; their -# # value would have been inferred from that of the other. -# add_cython_target(cy_code cy_code.pyx) -# -# add_library(cy_code MODULE ${cy_code}) -# target_link_libraries(cy_code ...) -# -# Cache variables that effect the behavior include: -# -# ``CYTHON_ANNOTATE`` -# whether to create an annotated .html file when compiling -# -# ``CYTHON_FLAGS`` -# additional flags to pass to the Cython compiler -# -# 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_FLAGS "" CACHE STRING - "Extra flags to the cython compiler.") -mark_as_advanced(CYTHON_ANNOTATE CYTHON_FLAGS) - -find_package(PythonLibs REQUIRED) - -set(CYTHON_CXX_EXTENSION "cxx") -set(CYTHON_C_EXTENSION "c") - -get_property(languages GLOBAL PROPERTY ENABLED_LANGUAGES) - -function(add_cython_target _name) - set(options EMBED_MAIN C CXX PY2 PY3) - set(options1 OUTPUT_VAR) - cmake_parse_arguments(_args "${options}" "${options1}" "" ${ARGN}) - - list(GET _args_UNPARSED_ARGUMENTS 0 _arg0) - - # if provided, use _arg0 as the input file path - if(_arg0) - set(_source_file ${_arg0}) - - # otherwise, must determine source file from name, or vice versa - else() - get_filename_component(_name_ext "${_name}" EXT) - - # if extension provided, _name is the source file - if(_name_ext) - set(_source_file ${_name}) - get_filename_component(_name "${_source_file}" NAME_WE) - - # otherwise, assume the source file is ${_name}.pyx - else() - set(_source_file ${_name}.pyx) - endif() - endif() - - set(_embed_main FALSE) - - if("C" IN_LIST languages) - set(_output_syntax "C") - elseif("CXX" IN_LIST languages) - set(_output_syntax "CXX") - else() - message(FATAL_ERROR "Either C or CXX must be enabled to use Cython") - endif() - - if("${PYTHONLIBS_VERSION_STRING}" MATCHES "^2.") - set(_input_syntax "PY2") - else() - set(_input_syntax "PY3") - endif() - - if(_args_EMBED_MAIN) - set(_embed_main TRUE) - endif() - - if(_args_C) - set(_output_syntax "C") - endif() - - if(_args_CXX) - set(_output_syntax "CXX") - endif() - - if(_args_PY2) - set(_input_syntax "PY2") - endif() - - if(_args_PY3) - set(_input_syntax "PY3") - endif() - - set(embed_arg "") - if(_embed_main) - set(embed_arg "--embed") - endif() - - set(cxx_arg "") - set(extension "c") - if(_output_syntax STREQUAL "CXX") - set(cxx_arg "--cplus") - set(extension "cxx") - endif() - - set(py_version_arg "") - if(_input_syntax STREQUAL "PY2") - set(py_version_arg "-2") - elseif(_input_syntax STREQUAL "PY3") - set(py_version_arg "-3") - endif() - - set(generated_file "${CMAKE_CURRENT_BINARY_DIR}/${_name}.${extension}") - set_source_files_properties(${generated_file} PROPERTIES GENERATED TRUE) - - set(_output_var ${_name}) - if(_args_OUTPUT_VAR) - set(_output_var ${_args_OUTPUT_VAR}) - endif() - set(${_output_var} ${generated_file} PARENT_SCOPE) - - file(RELATIVE_PATH generated_file_relative - ${CMAKE_BINARY_DIR} ${generated_file}) - - set(comment "Generating ${_output_syntax} source ${generated_file_relative}") - set(cython_include_directories "") - set(pxd_dependencies "") - set(c_header_dependencies "") - - # Get the include directories. - get_source_file_property(pyx_location ${_source_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}) - - # Determine dependencies. - # Add the pxd file with the same basename as the given pyx file. - get_filename_component(pyx_file_basename ${_source_file} NAME_WE) - 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 "${_source_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}") - - # look for C headers - 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() - - # check for pxi dependencies - # Look for include statements. - set(include_dependencies "") - file(STRINGS "${pxd}" include_statements REGEX include) - foreach(statement ${include_statements}) - string(REGEX REPLACE - "include[ ]+[\"]([^\"]+)[\"].*" "\\1" - module "${statement}") - list(APPEND include_dependencies ${module}) - endforeach() - - list(REMOVE_DUPLICATES module_dependencies) - list(REMOVE_DUPLICATES include_dependencies) - - # Add modules 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 - - # Add includes to the files to check, if appropriate. - foreach(_include ${include_dependencies}) - unset(pxi_location CACHE) - find_file(pxi_location ${_include} - PATHS "${pyx_path}" ${cmake_include_directories} - NO_DEFAULT_PATH) - if(pxi_location) - list(FIND pxds_checked ${pxi_location} pxd_idx) - if(${pxd_idx} LESS 0) - list(FIND pxds_to_check ${pxi_location} pxd_idx) - if(${pxd_idx} LESS 0) - list(APPEND pxds_to_check ${pxi_location}) - list(APPEND pxd_dependencies ${pxi_location}) - endif() # if it is not already going to be checked - endif() # if it has not already been checked - endif() # if include file can be found - endforeach() # for each include dependency discovered - endforeach() # for each include file to check - - list(LENGTH pxds_to_check number_pxds_to_check) - endwhile() - - # Set additional flags. - set(annotate_arg "") - if(CYTHON_ANNOTATE) - set(annotate_arg "--annotate") - endif() - - set(no_docstrings_arg "") - if(CMAKE_BUILD_TYPE STREQUAL "Release" OR - CMAKE_BUILD_TYPE STREQUAL "MinSizeRel") - set(no_docstrings_arg "--no-docstrings") - endif() - - set(cython_debug_arg "") - set(embed_pos_arg "") - set(line_directives_arg "") - if(CMAKE_BUILD_TYPE STREQUAL "Debug" OR - CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo") - set(cython_debug_arg "--gdb") - set(line_directives_arg "--line-directives") - 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} "--include-dir" "${_include_dir}") - endforeach() - - 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} ${py_version_arg} - ${embed_arg} ${annotate_arg} ${no_docstrings_arg} - ${cython_debug_arg} ${embed_pos_arg} - ${line_directives_arg} ${CYTHON_FLAGS} ${pyx_location} - --output-file ${generated_file} - DEPENDS ${_source_file} - ${pxd_dependencies} - IMPLICIT_DEPENDS ${_output_syntax} - ${c_header_dependencies} - COMMENT ${comment}) - - # NOTE(opadron): I thought about making a proper target, but after trying it - # out, I decided that it would be far too convenient to use the same name as - # the target for the extension module (e.g.: for single-file modules): - # - # ... - # add_cython_target(_module.pyx) - # add_library(_module ${_module}) - # ... - # - # The above example would not be possible since the "_module" target name - # would already be taken by the cython target. Since I can't think of a - # reason why someone would need the custom target instead of just using the - # generated file directly, I decided to leave this commented out. - # - # add_custom_target(${_name} DEPENDS ${generated_file}) - - # Remove their visibility to the user. - set(corresponding_pxd_file "" CACHE INTERNAL "") - set(header_location "" CACHE INTERNAL "") - set(pxd_location "" CACHE INTERNAL "") -endfunction() - diff --git a/cmake/targetLinkLibrariesWithDynamicLookup.cmake b/cmake/targetLinkLibrariesWithDynamicLookup.cmake deleted file mode 100644 index 60a0a1956..000000000 --- a/cmake/targetLinkLibrariesWithDynamicLookup.cmake +++ /dev/null @@ -1,478 +0,0 @@ -# -# - This module provides the function -# target_link_libraries_with_dynamic_lookup which can be used to -# "weakly" link a loadable module. -# -# Link a library to a target such that the symbols are resolved at -# run-time not link-time. This should be used when compiling a -# loadable module when the symbols should be resolve from the run-time -# environment where the module is loaded, and not a specific system -# library. -# -# Specifically, for OSX it uses undefined dynamic_lookup. This is -# similar to using "-shared" on Linux where undefined symbols are -# ignored. -# -# Additionally, the linker is checked to see if it supports undefined -# symbols when linking a shared library. If it does then the library -# is not linked when specified with this function. -# -# http://blog.tim-smith.us/2015/09/python-extension-modules-os-x/ -# -# -# The following functions are defined: -# -# _get_target_type(<ResultVar> <Target>) -# -# **INTERNAL** Shorthand for querying an abbreviated version of the target type -# of the given ``<Target>``. ``<ResultVar>`` is set to "STATIC" for a -# STATIC_LIBRARY, "SHARED" for a SHARED_LIBRARY, "MODULE" for a MODULE_LIBRARY, -# and "EXE" for an EXECUTABLE. -# -# Defined variables: -# -# ``<ResultVar>`` -# The abbreviated version of the ``<Target>``'s type. -# -# -# _test_weak_link_project(<TargetType> -# <LibType> -# <ResultVar> -# <LinkFlagsVar>) -# -# **INTERNAL** Attempt to compile and run a test project where a target of type -# ``<TargetType>`` is weakly-linked against a dependency of type ``<LibType>``. -# ``<TargetType>`` can be one of "STATIC", "SHARED", "MODULE", or "EXE". -# ``<LibType>`` can be one of "STATIC", "SHARED", or "MODULE". -# -# Defined variables: -# -# ``<ResultVar>`` -# Whether the current C toolchain can produce a working target binary of type -# ``<TargetType>`` that is weakly-linked against a dependency target of type -# ``<LibType>``. -# -# ``<LinkFlagsVar>`` -# List of flags to add to the linker command to produce a working target -# binary of type ``<TargetType>`` that is weakly-linked against a dependency -# target of type ``<LibType>``. -# -# -# check_dynamic_lookup(<TargetType> -# <LibType> -# <ResultVar> -# <LinkFlagsVar>) -# -# Check if the linker requires a command line flag to allow leaving symbols -# unresolved when producing a target of type ``<TargetType>`` that is -# weakly-linked against a dependency of type ``<LibType>``. ``<TargetType>`` -# can be one of "STATIC", "SHARED", "MODULE", or "EXE". ``<LibType>`` can be -# one of "STATIC", "SHARED", or "MODULE". The result is cached between -# invocations and recomputed only when the value of CMake's linker flag list -# changes; ``CMAKE_STATIC_LINKER_FLAGS`` if ``<TargetType>`` is "STATIC", and -# ``CMAKE_SHARED_LINKER_FLAGS`` otherwise. -# -# -# Defined variables: -# -# ``<ResultVar>`` -# Whether the current C toolchain supports weak-linking for target binaries of -# type ``<TargetType>`` that are weakly-linked against a dependency target of -# type ``<LibType>``. -# -# ``<LinkFlagsVar>`` -# List of flags to add to the linker command to produce a working target -# binary of type ``<TargetType>`` that is weakly-linked against a dependency -# target of type ``<LibType>``. -# -# ``HAS_DYNAMIC_LOOKUP_<TargetType>_<LibType>`` -# Cached, global alias for ``<ResultVar>`` -# -# ``DYNAMIC_LOOKUP_FLAGS_<TargetType>_<LibType>`` -# Cached, global alias for ``<LinkFlagsVar>`` -# -# -# target_link_libraries_with_dynamic_lookup(<Target> [<Libraries>]) -# -# Like proper linking, except that the given ``<Libraries>`` are not necessarily -# linked. Instead, the ``<Target>`` is produced in a manner that allows for -# symbols unresolved within it to be resolved at runtime, presumably by the -# given ``<Libraries>``. If such a target can be produced, the provided -# ``<Libraries>`` are not actually linked. On platforms that do not support -# weak-linking, this function works just like ``target_link_libraries``. - -function(_get_target_type result_var target) - set(target_type "SHARED_LIBRARY") - if(TARGET ${target}) - get_property(target_type TARGET ${target} PROPERTY TYPE) - endif() - - set(result "STATIC") - - if(target_type STREQUAL "STATIC_LIBRARY") - set(result "STATIC") - endif() - - if(target_type STREQUAL "SHARED_LIBRARY") - set(result "SHARED") - endif() - - if(target_type STREQUAL "MODULE_LIBRARY") - set(result "MODULE") - endif() - - if(target_type STREQUAL "EXECUTABLE") - set(result "EXE") - endif() - - set(${result_var} ${result} PARENT_SCOPE) -endfunction() - - -function(_test_weak_link_project - target_type - lib_type - can_weak_link_var - project_name) - - set(gnu_ld_ignore "-Wl,--unresolved-symbols=ignore-all") - set(osx_dynamic_lookup "-undefined dynamic_lookup") - set(no_flag "") - - foreach(link_flag_spec gnu_ld_ignore osx_dynamic_lookup no_flag) - set(link_flag "${${link_flag_spec}}") - - set(test_project_dir "${PROJECT_BINARY_DIR}/CMakeTmp") - set(test_project_dir "${test_project_dir}/${project_name}") - set(test_project_dir "${test_project_dir}/${link_flag_spec}") - set(test_project_dir "${test_project_dir}/${target_type}") - set(test_project_dir "${test_project_dir}/${lib_type}") - - set(test_project_src_dir "${test_project_dir}/src") - set(test_project_bin_dir "${test_project_dir}/build") - - file(MAKE_DIRECTORY ${test_project_src_dir}) - file(MAKE_DIRECTORY ${test_project_bin_dir}) - - set(mod_type "STATIC") - set(link_mod_lib TRUE) - set(link_exe_lib TRUE) - set(link_exe_mod FALSE) - - if("${target_type}" STREQUAL "EXE") - set(link_exe_lib FALSE) - set(link_exe_mod TRUE) - else() - set(mod_type "${target_type}") - endif() - - if("${mod_type}" STREQUAL "MODULE") - set(link_mod_lib FALSE) - endif() - - - file(WRITE "${test_project_src_dir}/CMakeLists.txt" " - cmake_minimum_required(VERSION ${CMAKE_VERSION}) - project(${project_name} C) - - include_directories(${test_project_src_dir}) - - add_library(number ${lib_type} number.c) - add_library(counter ${mod_type} counter.c) - ") - - if("${mod_type}" STREQUAL "MODULE") - file(APPEND "${test_project_src_dir}/CMakeLists.txt" " - set_target_properties(counter PROPERTIES PREFIX \"\") - ") - endif() - - if(link_mod_lib) - file(APPEND "${test_project_src_dir}/CMakeLists.txt" " - target_link_libraries(counter number) - ") - elseif(NOT link_flag STREQUAL "") - file(APPEND "${test_project_src_dir}/CMakeLists.txt" " - set_target_properties(counter PROPERTIES LINK_FLAGS \"${link_flag}\") - ") - endif() - - file(APPEND "${test_project_src_dir}/CMakeLists.txt" " - add_executable(main main.c) - ") - - if(link_exe_lib) - file(APPEND "${test_project_src_dir}/CMakeLists.txt" " - target_link_libraries(main number) - ") - elseif(NOT link_flag STREQUAL "") - file(APPEND "${test_project_src_dir}/CMakeLists.txt" " - target_link_libraries(main \"${link_flag}\") - ") - endif() - - if(link_exe_mod) - file(APPEND "${test_project_src_dir}/CMakeLists.txt" " - target_link_libraries(main counter) - ") - else() - file(APPEND "${test_project_src_dir}/CMakeLists.txt" " - target_link_libraries(main \"${CMAKE_DL_LIBS}\") - ") - endif() - - file(WRITE "${test_project_src_dir}/number.c" " - #include <number.h> - - static int _number; - void set_number(int number) { _number = number; } - int get_number() { return _number; } - ") - - file(WRITE "${test_project_src_dir}/number.h" " - #ifndef _NUMBER_H - #define _NUMBER_H - extern void set_number(int); - extern int get_number(void); - #endif - ") - - file(WRITE "${test_project_src_dir}/counter.c" " - #include <number.h> - int count() { - int result = get_number(); - set_number(result + 1); - return result; - } - ") - - file(WRITE "${test_project_src_dir}/counter.h" " - #ifndef _COUNTER_H - #define _COUNTER_H - extern int count(void); - #endif - ") - - file(WRITE "${test_project_src_dir}/main.c" " - #include <stdlib.h> - #include <stdio.h> - #include <number.h> - ") - - if(NOT link_exe_mod) - file(APPEND "${test_project_src_dir}/main.c" " - #include <dlfcn.h> - ") - endif() - - file(APPEND "${test_project_src_dir}/main.c" " - int my_count() { - int result = get_number(); - set_number(result + 1); - return result; - } - - int main(int argc, char **argv) { - int result; - ") - - if(NOT link_exe_mod) - file(APPEND "${test_project_src_dir}/main.c" " - void *counter_module; - int (*count)(void); - - counter_module = dlopen(\"./counter.so\", RTLD_LAZY | RTLD_GLOBAL); - if(!counter_module) goto error; - - count = dlsym(counter_module, \"count\"); - if(!count) goto error; - ") - endif() - - file(APPEND "${test_project_src_dir}/main.c" " - result = count() != 0 ? EXIT_FAILURE : - my_count() != 1 ? EXIT_FAILURE : - my_count() != 2 ? EXIT_FAILURE : - count() != 3 ? EXIT_FAILURE : - count() != 4 ? EXIT_FAILURE : - count() != 5 ? EXIT_FAILURE : - my_count() != 6 ? EXIT_FAILURE : EXIT_SUCCESS; - ") - - if(NOT link_exe_mod) - file(APPEND "${test_project_src_dir}/main.c" " - goto done; - error: - fprintf(stderr, \"Error occured:\\n %s\\n\", dlerror()); - result = 1; - - done: - if(counter_module) dlclose(counter_module); - ") - endif() - - file(APPEND "${test_project_src_dir}/main.c" " - return result; - } - ") - - set(_rpath_arg) - if(APPLE AND ${CMAKE_VERSION} VERSION_GREATER 2.8.11) - set(_rpath_arg "-DCMAKE_MACOSX_RPATH='${CMAKE_MACOSX_RPATH}'") - endif() - - try_compile(project_compiles - "${test_project_bin_dir}" - "${test_project_src_dir}" - "${project_name}" - CMAKE_FLAGS - "-DCMAKE_SHARED_LINKER_FLAGS='${CMAKE_SHARED_LINKER_FLAGS}'" - ${_rpath_arg} - OUTPUT_VARIABLE compile_output) - - set(project_works 1) - set(run_output) - - if(project_compiles) - execute_process(COMMAND ${CMAKE_CROSSCOMPILING_EMULATOR} - "${test_project_bin_dir}/main" - WORKING_DIRECTORY "${test_project_bin_dir}" - RESULT_VARIABLE project_works - OUTPUT_VARIABLE run_output - ERROR_VARIABLE run_output) - endif() - - set(test_description - "Weak Link ${target_type} -> ${lib_type} (${link_flag_spec})") - - if(project_works EQUAL 0) - set(project_works TRUE) - message(STATUS "Performing Test ${test_description} - Success") - else() - set(project_works FALSE) - message(STATUS "Performing Test ${test_description} - Failed") - file(APPEND ${CMAKE_BINARY_DIR}/${CMAKE_FILES_DIRECTORY}/CMakeError.log - "Performing Test ${test_description} failed with the " - "following output:\n" - "BUILD\n-----\n${compile_output}\nRUN\n---\n${run_output}\n") - endif() - - set(${can_weak_link_var} ${project_works} PARENT_SCOPE) - if(project_works) - set(${project_name} ${link_flag} PARENT_SCOPE) - break() - endif() - endforeach() -endfunction() - - -function(check_dynamic_lookup - target_type - lib_type - has_dynamic_lookup_var - link_flags_var) - - # hash the CMAKE_FLAGS passed and check cache to know if we need to rerun - if("${target_type}" STREQUAL "STATIC") - string(MD5 cmake_flags_hash "${CMAKE_STATIC_LINKER_FLAGS}") - else() - string(MD5 cmake_flags_hash "${CMAKE_SHARED_LINKER_FLAGS}") - endif() - - set(cache_var "HAS_DYNAMIC_LOOKUP_${target_type}_${lib_type}") - set(cache_hash_var "HAS_DYNAMIC_LOOKUP_${target_type}_${lib_type}_hash") - set(result_var "DYNAMIC_LOOKUP_FLAGS_${target_type}_${lib_type}") - - if( NOT DEFINED ${cache_hash_var} - OR NOT "${${cache_hash_var}}" STREQUAL "${cmake_flags_hash}") - unset(${cache_var} CACHE) - endif() - - if(NOT DEFINED ${cache_var}) - set(skip_test FALSE) - - if(NOT CMAKE_CROSSCOMPILING) - set(skip_test TRUE) - elseif(CMAKE_CROSSCOMPILING AND CMAKE_CROSSCOMPILING_EMULATOR) - set(skip_test TRUE) - endif() - - if(skip_test) - set(has_dynamic_lookup FALSE) - set(link_flags) - else() - _test_weak_link_project(${target_type} - ${lib_type} - has_dynamic_lookup - link_flags) - endif() - - set(caveat " (when linking ${target_type} against ${lib_type})") - - set(${cache_var} "${has_dynamic_lookup}" - CACHE BOOL - "linker supports dynamic lookup for undefined symbols${caveat}") - - set(${result_var} "${link_flags}" - CACHE BOOL - "linker flags for dynamic lookup${caveat}") - - set(${cache_hash_var} "${cmake_flags_hash}" - CACHE INTERNAL "hashed flags for ${cache_var} check") - endif() - - set(${has_dynamic_lookup_var} "${${cache_var}}" PARENT_SCOPE) - set(${link_flags_var} "${${result_var}}" PARENT_SCOPE) -endfunction() - - -function(target_link_libraries_with_dynamic_lookup target) - _get_target_type(target_type ${target}) - - set(link_props) - set(link_items) - set(link_libs) - - foreach(lib ${ARGN}) - _get_target_type(lib_type ${lib}) - check_dynamic_lookup(${target_type} - ${lib_type} - has_dynamic_lookup - dynamic_lookup_flags) - - if(has_dynamic_lookup) - if(dynamic_lookup_flags) - if("${target_type}" STREQUAL "EXE") - list(APPEND link_items "${dynamic_lookup_flags}") - else() - list(APPEND link_props "${dynamic_lookup_flags}") - endif() - endif() - else() - list(APPEND link_libs "${lib}") - endif() - endforeach() - - if(link_props) - list(REMOVE_DUPLICATES link_props) - endif() - - if(link_items) - list(REMOVE_DUPLICATES link_items) - endif() - - if(link_libs) - list(REMOVE_DUPLICATES link_libs) - endif() - - if(link_props) - set_target_properties(${target} - PROPERTIES LINK_FLAGS "${link_props}") - endif() - - set(links "${link_items}" "${link_libs}") - if(links) - target_link_libraries(${target} "${links}") - endif() -endfunction() - diff --git a/src/api/python/CMakeLists.txt b/src/api/python/CMakeLists.txt index c6686e32b..27e36f538 100644 --- a/src/api/python/CMakeLists.txt +++ b/src/api/python/CMakeLists.txt @@ -19,6 +19,36 @@ if(POLICY CMP0057) cmake_policy(SET CMP0057 NEW) endif() +# Check that scikit-build is installed +# Provides CMake files for Python bindings +check_python_module("skbuild" "scikit-build") + +# setuptools for installing the module +check_python_module("setuptools") + +# Find cmake modules distributed with scikit-build +# They are distributed under <scikit-build directory>/resources/cmake +execute_process( + COMMAND + ${PYTHON_EXECUTABLE} -c "from __future__ import print_function; \ + import os; import skbuild; \ + cmake_module_path=os.path.join(os.path.dirname(skbuild.__file__), \ + 'resources', 'cmake'); print(cmake_module_path, end='')" + OUTPUT_VARIABLE + SKBUILD_CMAKE_MODULE_PATH + RESULT_VARIABLE + RET_SKBUILD_CMAKE_MODULE_PATH +) + +if (NOT EXISTS ${SKBUILD_CMAKE_MODULE_PATH}) + message(FATAL_ERROR "Expected CMake module path from + scikit-build at ${SKBUILD_CMAKE_MODULE_PATH}") +endif() + +# Add scikit-build cmake files to cmake module path +# Required for Cython target below +list(APPEND CMAKE_MODULE_PATH ${SKBUILD_CMAKE_MODULE_PATH}) + find_package(PythonExtensions REQUIRED) find_package(Cython 0.29 REQUIRED) @@ -98,8 +128,14 @@ print('YES' if 'VIRTUAL_ENV' in os.environ else 'NO', end='')") set(INSTALL_CMD "${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/setup.py install") # if we're in a virtualenv, we install it in the virtualenv lib location +# otherwise install in site-packages +# option --single-version-externally-managed prevents it from being +# an .egg distribution and --record records the list of installed files if ("${IN_VIRTUALENV}" STREQUAL "NO") - set(INSTALL_CMD "${INSTALL_CMD} --prefix=${CMAKE_INSTALL_PREFIX}") + set(INSTALL_CMD "${INSTALL_CMD} + --prefix=${CMAKE_INSTALL_PREFIX} + --single-version-externally-managed + --record=pycvc5-installed-files.txt") endif() message("Python bindings install command: ${INSTALL_CMD}") diff --git a/src/api/python/setup.py.in b/src/api/python/setup.py.in index 231f27c2a..7f8783a28 100644 --- a/src/api/python/setup.py.in +++ b/src/api/python/setup.py.in @@ -20,24 +20,16 @@ # configured install prefix using the setup.py --prefix option ## -from distutils.core import setup -from distutils.command.clean import clean -from distutils.command.install import install +from setuptools import setup -class PyCVC5Install(install): - - # Calls the default run command, then deletes the build area - # (equivalent to "setup clean --all"). - def run(self): - install.run(self) - c = clean(self.distribution) - c.all = True - c.finalize_options() - c.run() +CVC5_VERSION='${CVC5_MAJOR}.${CVC5_MINOR}.${CVC5_RELEASE}' setup(name='pycvc5', - version='${CVC5_MAJOR}.${CVC5_MINOR}.${CVC5_RELEASE}', + version=CVC5_VERSION, + long_description='Python bindings for cvc5 ' + CVC5_VERSION, + url='https://github.com/cvc5/cvc5', + zip_safe=False, packages=['pycvc5'], - package_dir={'pycvc5': '${CMAKE_CURRENT_BINARY_DIR}/pycvc5'}, - package_data={'pycvc5': ['pycvc5.so']}, - cmdclass={'install': PyCVC5Install}) + package_dir={'':'${CMAKE_CURRENT_BINARY_DIR}'}, + package_data={'': ['pycvc5*.so']}, + extras_require={'test': ['pytest']}) |