From 84fdf87a74a7104a0eccaf7a817597b086c3afa9 Mon Sep 17 00:00:00 2001 From: makaimann Date: Fri, 21 May 2021 00:20:30 -0400 Subject: [PATCH] Use scikit-build CMake files for pycvc5 (#6543) This PR removes copied CMake files for the pycvc5 Cython target, and instead adds a dependency on scikit-build (where those CMake files originated anyway). This keeps us up to date with fixes. Furthermore, the PR switches from distutils to the more modern setuptools. This does add another dependency but it's a fairly reasonable one. setuptools is not part of the base Python distribution, but my understanding is that it is now the de facto standard, and most package managers install it automatically with Python. The main motivation for switching is in preparation for building wheels. This PR is a piece of this old one (#5657) which I am closing and splitting up. --- .github/workflows/ci.yml | 1 + INSTALL.md | 7 + cmake/FindCython.cmake | 77 --- cmake/FindPythonExtensions.cmake | 503 ------------------ cmake/UseCython.cmake | 402 -------------- ...targetLinkLibrariesWithDynamicLookup.cmake | 478 ----------------- src/api/python/CMakeLists.txt | 38 +- src/api/python/setup.py.in | 26 +- 8 files changed, 54 insertions(+), 1478 deletions(-) delete mode 100644 cmake/FindCython.cmake delete mode 100644 cmake/FindPythonExtensions.cmake delete mode 100644 cmake/UseCython.cmake delete mode 100644 cmake/targetLinkLibrariesWithDynamicLookup.cmake 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 ---bindings` to build with language bindings for ``. +### 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( -# [LINKED_MODULES_VAR ] -# [FORWARD_DECL_MODULES_VAR ]) -# -# 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 ```` 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 `` -# 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 `` -# 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() -# -# 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( [HeaderFilename] -# [FORWARD_DECL_MODULES_LIST ] -# [HEADER_OUTPUT_VAR ] -# [INCLUDE_DIR_OUTPUT_VAR ]) -# -# Generate a header file that contains the forward declarations and -# initialization routines for the given list of Python extension modules. -# ```` is the logical name for the header file (no file extensions). -# ```` is the actual destination filename for the header file -# (e.g.: decl_modules.h). -# -# If only ```` is provided, and it ends in the ".h" extension, then it -# is assumed to be the ````. The filename of the header file -# without the extension is used as the logical name. If only ```` is -# provided, and it does not end in the ".h" extension, then the -# ```` is assumed to ``.h``. -# -# The exact contents of the generated header file depend on the logical -# ````. 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 _(void)`` -# Initializes the python extension module, ````. Returns an integer -# handle to the module. -# -# ``void _LoadAllPythonModules(void)`` -# Initializes all listed python extension modules. -# -# ``void CMakeLoadAllPythonModules(void);`` -# Alias for ``_LoadAllPythonModules`` whose name does not depend on -# ````. 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 `` -# 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 `` -# Name of the variable to set to the path to the generated header file. By -# default, ```` is used. -# -# ``INCLUDE_DIR_OUTPUT_VAR `` -# Name of the variable to set to the path to the directory containing the -# generated header file. By default, ``_INCLUDE_DIRS`` is used. -# -# Defined variables: -# -# ```` -# The path to the generated header file -# -# ```` -# 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 \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( [] -# [EMBED_MAIN] -# [C | CXX] -# [PY2 | PY3] -# [OUTPUT_VAR ]) -# -# Create a custom rule to generate the source code for a Python extension module -# using cython. ```` is the name of the new target, and ```` -# 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 ```` is provided, and it ends in the ".pyx" extension, then it -# is assumed to be the ````. The name of the input without the -# extension is used as the target name. If only ```` is provided, and it -# does not end in the ".pyx" extension, then the ```` is assumed to -# be ``.pyx``. -# -# The Cython include search path is amended with any entries found in the -# ``INCLUDE_DIRECTORIES`` property of the directory containing the -# ```` 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 `` -# Set the variable ```` in the parent scope to the path to the -# generated source file. By default, ```` is used as the output -# variable name. -# -# Defined variables: -# -# ```` -# 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( ) -# -# **INTERNAL** Shorthand for querying an abbreviated version of the target type -# of the given ````. ```` 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: -# -# ```` -# The abbreviated version of the ````'s type. -# -# -# _test_weak_link_project( -# -# -# ) -# -# **INTERNAL** Attempt to compile and run a test project where a target of type -# ```` is weakly-linked against a dependency of type ````. -# ```` can be one of "STATIC", "SHARED", "MODULE", or "EXE". -# ```` can be one of "STATIC", "SHARED", or "MODULE". -# -# Defined variables: -# -# ```` -# Whether the current C toolchain can produce a working target binary of type -# ```` that is weakly-linked against a dependency target of type -# ````. -# -# ```` -# List of flags to add to the linker command to produce a working target -# binary of type ```` that is weakly-linked against a dependency -# target of type ````. -# -# -# check_dynamic_lookup( -# -# -# ) -# -# Check if the linker requires a command line flag to allow leaving symbols -# unresolved when producing a target of type ```` that is -# weakly-linked against a dependency of type ````. ```` -# can be one of "STATIC", "SHARED", "MODULE", or "EXE". ```` 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 ```` is "STATIC", and -# ``CMAKE_SHARED_LINKER_FLAGS`` otherwise. -# -# -# Defined variables: -# -# ```` -# Whether the current C toolchain supports weak-linking for target binaries of -# type ```` that are weakly-linked against a dependency target of -# type ````. -# -# ```` -# List of flags to add to the linker command to produce a working target -# binary of type ```` that is weakly-linked against a dependency -# target of type ````. -# -# ``HAS_DYNAMIC_LOOKUP__`` -# Cached, global alias for ```` -# -# ``DYNAMIC_LOOKUP_FLAGS__`` -# Cached, global alias for ```` -# -# -# target_link_libraries_with_dynamic_lookup( []) -# -# Like proper linking, except that the given ```` are not necessarily -# linked. Instead, the ```` is produced in a manner that allows for -# symbols unresolved within it to be resolved at runtime, presumably by the -# given ````. If such a target can be produced, the provided -# ```` 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 - - 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 - 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 - #include - #include - ") - - if(NOT link_exe_mod) - file(APPEND "${test_project_src_dir}/main.c" " - #include - ") - 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 /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']}) -- 2.30.2