diff --git a/.circleci/config.yml b/.circleci/config.yml index 59deadba9f..6559558c32 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -100,7 +100,7 @@ jobs: cmake -DWITH_GUDHI_THIRD_PARTY=OFF -DUSER_VERSION_DIR=version .. make user_version cd version - cmake -DCMAKE_BUILD_TYPE=Release -DWITH_GUDHI_EXAMPLE=OFF -DWITH_GUDHI_UTILITIES=OFF -DWITH_GUDHI_PYTHON=ON -DPython_ADDITIONAL_VERSIONS=3 -DWITH_GUDHI_REMOTE_TEST=ON . + cmake -DCMAKE_BUILD_TYPE=Release -DWITH_GUDHI_EXAMPLE=OFF -DWITH_GUDHI_UTILITIES=OFF -DWITH_GUDHI_PYTHON=ON -DWITH_GUDHI_REMOTE_TEST=ON . cd python python3 setup.py build_ext --inplace ctest --output-on-failure @@ -243,7 +243,7 @@ jobs: command: | mkdir build cd build - cmake -DCMAKE_BUILD_TYPE=Release -DWITH_GUDHI_EXAMPLE=OFF -DWITH_GUDHI_UTILITIES=OFF -DWITH_GUDHI_PYTHON=ON -DPython_ADDITIONAL_VERSIONS=3 .. + cmake -DCMAKE_BUILD_TYPE=Release -DWITH_GUDHI_EXAMPLE=OFF -DWITH_GUDHI_UTILITIES=OFF -DWITH_GUDHI_PYTHON=ON .. cd src/python python3 setup.py build_ext --inplace ctest --output-on-failure @@ -323,7 +323,7 @@ jobs: command: | mkdir build cd build - cmake -DCMAKE_BUILD_TYPE=Release -DEIGEN3_INCLUDE_DIR=/eigen-3.3.9 -DWITH_GUDHI_EXAMPLE=OFF -DWITH_GUDHI_UTILITIES=OFF -DWITH_GUDHI_PYTHON=ON -DPython_ADDITIONAL_VERSIONS=3 .. + cmake -DCMAKE_BUILD_TYPE=Release -DEIGEN3_INCLUDE_DIR=/eigen-3.3.9 -DWITH_GUDHI_EXAMPLE=OFF -DWITH_GUDHI_UTILITIES=OFF -DWITH_GUDHI_PYTHON=ON .. cd src/python python3 setup.py build_ext --inplace ctest --output-on-failure diff --git a/.github/for_maintainers/new_gudhi_version_creation.md b/.github/for_maintainers/new_gudhi_version_creation.md index afb4e707ac..1bb6382bba 100644 --- a/.github/for_maintainers/new_gudhi_version_creation.md +++ b/.github/for_maintainers/new_gudhi_version_creation.md @@ -32,7 +32,7 @@ Checkin the modifications, build and test the version: ```bash git submodule update --init rm -rf build; mkdir build; cd build -cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH=$CONDA_PREFIX -DWITH_GUDHI_REMOTE_TEST=ON -DWITH_GUDHI_EXAMPLE=ON -DWITH_GUDHI_BENCHMARK=ON -DUSER_VERSION_DIR=gudhi.@GUDHI_VERSION@ -DPython_ADDITIONAL_VERSIONS=3 .. +cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH=$CONDA_PREFIX -DWITH_GUDHI_REMOTE_TEST=ON -DWITH_GUDHI_EXAMPLE=ON -DWITH_GUDHI_BENCHMARK=ON -DUSER_VERSION_DIR=gudhi.@GUDHI_VERSION@ .. make user_version date +"%d-%m-%Y-%T" > gudhi.@GUDHI_VERSION@/timestamp.txt tar -czvf gudhi.@GUDHI_VERSION@.tar.gz gudhi.@GUDHI_VERSION@ @@ -54,7 +54,7 @@ mkdir gudhi.doc.@GUDHI_VERSION@ ```bash cd gudhi.@GUDHI_VERSION@ rm -rf build; mkdir build; cd build -cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH=$CONDA_PREFIX -DWITH_GUDHI_EXAMPLE=ON -DPython_ADDITIONAL_VERSIONS=3 .. +cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH=$CONDA_PREFIX -DWITH_GUDHI_EXAMPLE=ON .. make doxygen && grep warning doxygen.log ``` diff --git a/.github/next_release.md b/.github/next_release.md index 75db646175..abd2ebd1bd 100644 --- a/.github/next_release.md +++ b/.github/next_release.md @@ -18,6 +18,9 @@ Below is a list of changes: - [Module](link) - **...** +- Installation + - CMake ≥ 3.15 is now required (was ≥ 3.8). + - Miscellaneous - The [list of bugs that were solved](https://github.com/GUDHI/gudhi-devel/issues?q=label%3A3.11.0+is%3Aclosed) is available on GitHub. diff --git a/.github/workflows/pip-build-linux.yml b/.github/workflows/pip-build-linux.yml index e9b02c282a..628dd4b6b1 100644 --- a/.github/workflows/pip-build-linux.yml +++ b/.github/workflows/pip-build-linux.yml @@ -21,7 +21,7 @@ jobs: run: | mkdir build_39 cd build_39 - cmake -DCMAKE_BUILD_TYPE=Release -DPYTHON_EXECUTABLE=$PYTHON39/bin/python .. + cmake -DCMAKE_BUILD_TYPE=Release -DPython_EXECUTABLE=$PYTHON39/bin/python .. cd src/python $PYTHON39/bin/python -m build -n -w auditwheel repair dist/*.whl diff --git a/.github/workflows/pip-build-osx.yml b/.github/workflows/pip-build-osx.yml index 09362a697e..5334ce178d 100644 --- a/.github/workflows/pip-build-osx.yml +++ b/.github/workflows/pip-build-osx.yml @@ -46,7 +46,7 @@ jobs: python --version mkdir build cd build - cmake -DCMAKE_BUILD_TYPE=Release -DPython_ADDITIONAL_VERSIONS=3 .. + cmake -DCMAKE_BUILD_TYPE=Release .. cd src/python python -m build -n -w export PATH="$PATH:`python -m site --user-base`/bin" diff --git a/.github/workflows/pip-packaging-linux.yml b/.github/workflows/pip-packaging-linux.yml index cb4a4d9f6e..bec8e4a62b 100644 --- a/.github/workflows/pip-packaging-linux.yml +++ b/.github/workflows/pip-packaging-linux.yml @@ -22,7 +22,7 @@ jobs: rm -rf src/python/gudhi/*.cpp mkdir build_38 cd build_38 - cmake -DCMAKE_BUILD_TYPE=Release -DPYTHON_EXECUTABLE=$PYTHON38/bin/python .. + cmake -DCMAKE_BUILD_TYPE=Release -DPython_EXECUTABLE=$PYTHON38/bin/python .. cd src/python $PYTHON38/bin/python -m build -n -w auditwheel repair dist/*.whl @@ -41,7 +41,7 @@ jobs: rm -rf src/python/gudhi/*.cpp mkdir build_39 cd build_39 - cmake -DCMAKE_BUILD_TYPE=Release -DPYTHON_EXECUTABLE=$PYTHON39/bin/python .. + cmake -DCMAKE_BUILD_TYPE=Release -DPython_EXECUTABLE=$PYTHON39/bin/python .. cd src/python $PYTHON39/bin/python -m build -n -w auditwheel repair dist/*.whl @@ -64,7 +64,7 @@ jobs: rm -rf src/python/gudhi/*.cpp mkdir build_310 cd build_310 - cmake -DCMAKE_BUILD_TYPE=Release -DPYTHON_EXECUTABLE=$PYTHON310/bin/python .. + cmake -DCMAKE_BUILD_TYPE=Release -DPython_EXECUTABLE=$PYTHON310/bin/python .. cd src/python $PYTHON310/bin/python -m build -n -w auditwheel repair dist/*.whl @@ -83,7 +83,7 @@ jobs: rm -rf src/python/gudhi/*.cpp mkdir build_311 cd build_311 - cmake -DCMAKE_BUILD_TYPE=Release -DPYTHON_EXECUTABLE=$PYTHON311/bin/python .. + cmake -DCMAKE_BUILD_TYPE=Release -DPython_EXECUTABLE=$PYTHON311/bin/python .. cd src/python $PYTHON311/bin/python -m build -n -w auditwheel repair dist/*.whl @@ -102,7 +102,7 @@ jobs: rm -rf src/python/gudhi/*.cpp mkdir build_312 cd build_312 - cmake -DCMAKE_BUILD_TYPE=Release -DPYTHON_EXECUTABLE=$PYTHON312/bin/python .. + cmake -DCMAKE_BUILD_TYPE=Release -DPython_EXECUTABLE=$PYTHON312/bin/python .. cd src/python $PYTHON312/bin/python -m build -n -w auditwheel repair dist/*.whl diff --git a/.github/workflows/pip-packaging-osx.yml b/.github/workflows/pip-packaging-osx.yml index d46c3c476c..563e08cb13 100644 --- a/.github/workflows/pip-packaging-osx.yml +++ b/.github/workflows/pip-packaging-osx.yml @@ -42,7 +42,7 @@ jobs: python --version mkdir build cd build - cmake -DCMAKE_BUILD_TYPE=Release -DPython_ADDITIONAL_VERSIONS=3 .. + cmake -DCMAKE_BUILD_TYPE=Release .. cd src/python python -m build -n -w - name: Install and test python wheel @@ -112,7 +112,7 @@ jobs: python --version mkdir build cd build - cmake -DCMAKE_BUILD_TYPE=Release -DPython_ADDITIONAL_VERSIONS=3 .. + cmake -DCMAKE_BUILD_TYPE=Release .. cd src/python python -m build -n -w # Test ABI compatibility with numpy 1.X diff --git a/CMakeLists.txt b/CMakeLists.txt index ccd0635dd5..6a8169ea9d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.8) +cmake_minimum_required(VERSION 3.15) project(GUDHIdev) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index dca19be29a..4896615006 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -8,6 +8,10 @@ jobs: variables: pythonVersion: "3.9" cmakeBuildType: Release + gudhiCmakeOptions: -DWITH_GUDHI_EXAMPLE=ON -DWITH_GUDHI_TEST=ON -DWITH_GUDHI_UTILITIES=ON -DWITH_GUDHI_PYTHON=ON -DWITH_GUDHI_REMOTE_TEST=ON + # On this VM, 2 versions of python are installed. Default Python_FIND_FRAMEWORK is FIRST, which means asks frameworks first + # LAST means consult frameworks in last resort, use the PATH first + extraCmakeOptions: -DPython_FIND_FRAMEWORK=LAST steps: # Use a specific Python version @@ -29,7 +33,8 @@ jobs: - bash: | mkdir build cd build - cmake -DCMAKE_BUILD_TYPE:STRING=$(cmakeBuildType) -GNinja -DWITH_GUDHI_EXAMPLE=ON -DWITH_GUDHI_TEST=ON -DWITH_GUDHI_UTILITIES=ON -DWITH_GUDHI_PYTHON=ON -DWITH_GUDHI_REMOTE_TEST=ON .. + which python + cmake -DCMAKE_BUILD_TYPE:STRING=$(cmakeBuildType) $(extraCmakeOptions) -GNinja $(gudhiCmakeOptions) .. ninja ninja doxygen ctest --output-on-failure @@ -44,7 +49,11 @@ jobs: variables: pythonVersion: "3.9" cmakeVcpkgFlags: -DVCPKG_TARGET_TRIPLET=x64-windows -DCMAKE_TOOLCHAIN_FILE=c:\vcpkg\scripts\buildsystems\vcpkg.cmake - cmakeFlags: -DWITH_GUDHI_EXAMPLE=ON -DWITH_GUDHI_TEST=ON -DWITH_GUDHI_UTILITIES=ON -DWITH_GUDHI_PYTHON=OFF + # WITH_GUDHI_PYTHON=OFF on purpose. It is set to ON on a second cmake call + gudhiCmakeOptions: -DWITH_GUDHI_EXAMPLE=ON -DWITH_GUDHI_TEST=ON -DWITH_GUDHI_UTILITIES=ON -DWITH_GUDHI_PYTHON=OFF + # On this VM, 2 versions of python are installed. Default Python_FIND_REGISTRY is FIRST, which means asks registry first + # LAST means consult registry in last resort, use the standard libraries or headers first + extraCmakeOptions: -DPython_FIND_REGISTRY=LAST steps: # Use a specific Python version @@ -69,16 +78,16 @@ jobs: IF %ERRORLEVEL% NEQ 0 EXIT 1 displayName: "Install build dependencies" - script: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" amd64 + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat" mkdir build cd build - cmake -DCMAKE_BUILD_TYPE=Release -G "Ninja" -DFORCE_EIGEN_DEFAULT_DENSE_INDEX_TYPE_TO_INT=ON $(cmakeVcpkgFlags) $(cmakeFlags) .. + cmake -DCMAKE_BUILD_TYPE=Release -G "Ninja" -DFORCE_EIGEN_DEFAULT_DENSE_INDEX_TYPE_TO_INT=ON $(cmakeVcpkgFlags) $(gudhiCmakeOptions) .. IF %ERRORLEVEL% NEQ 0 EXIT 1 ninja IF %ERRORLEVEL% NEQ 0 EXIT 1 ctest --output-on-failure -C Release -E diff_files IF %ERRORLEVEL% NEQ 0 EXIT 1 - cmake -DWITH_GUDHI_PYTHON=ON -DWITH_GUDHI_REMOTE_TEST=ON . + cmake $(extraCmakeOptions) -DWITH_GUDHI_PYTHON=ON -DWITH_GUDHI_REMOTE_TEST=ON . IF %ERRORLEVEL% NEQ 0 EXIT 1 cd src\python copy "C:\vcpkg\installed\x64-windows\bin\mpfr*.dll" ".\gudhi\" diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index b7992e03b8..53a22f8fd5 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.8) +cmake_minimum_required(VERSION 3.15) project(GUDHI) diff --git a/src/cmake/modules/GUDHI_third_party_libraries.cmake b/src/cmake/modules/GUDHI_third_party_libraries.cmake index 9fcb4f3930..7c03103cba 100644 --- a/src/cmake/modules/GUDHI_third_party_libraries.cmake +++ b/src/cmake/modules/GUDHI_third_party_libraries.cmake @@ -134,15 +134,19 @@ add_definitions( -DBOOST_SYSTEM_NO_DEPRECATED ) if (WITH_GUDHI_PYTHON) # Find the correct Python interpreter. - # Can be set with -DPYTHON_EXECUTABLE=/usr/bin/python3 or -DPython_ADDITIONAL_VERSIONS=3 for instance. - find_package( PythonInterp ) - + # Can be set with -DPython_EXECUTABLE=/usr/bin/python3 for instance. + # Default Python_FIND_STRATEGY to LOCATION: Stops lookup as soon as a version satisfying version constraints is founded + # (as opposed to VERSION: Try to find the most recent version in all specified locations.) + cmake_policy(SET CMP0094 NEW) + # Should be Development.Module (Development also includes Development.Embed) but it would require cmake 3.18. TODO in a later version + find_package( Python COMPONENTS Interpreter Development NumPy) + # find_python_module tries to import module in Python interpreter and to retrieve its version number # returns ${PYTHON_MODULE_NAME_UP}_VERSION and ${PYTHON_MODULE_NAME_UP}_FOUND function( find_python_module PYTHON_MODULE_NAME ) string(TOUPPER ${PYTHON_MODULE_NAME} PYTHON_MODULE_NAME_UP) execute_process( - COMMAND ${PYTHON_EXECUTABLE} -c "import ${PYTHON_MODULE_NAME}; print(${PYTHON_MODULE_NAME}.__version__)" + COMMAND ${Python_EXECUTABLE} -c "import ${PYTHON_MODULE_NAME}; print(${PYTHON_MODULE_NAME}.__version__)" RESULT_VARIABLE PYTHON_MODULE_RESULT OUTPUT_VARIABLE PYTHON_MODULE_VERSION ERROR_VARIABLE PYTHON_MODULE_ERROR) @@ -150,7 +154,7 @@ if (WITH_GUDHI_PYTHON) # Remove all carriage returns as it can be multiline string(REGEX REPLACE "\n" " " PYTHON_MODULE_VERSION "${PYTHON_MODULE_VERSION}") message ("++ Python module ${PYTHON_MODULE_NAME} - Version ${PYTHON_MODULE_VERSION} found") - + set(${PYTHON_MODULE_NAME_UP}_VERSION ${PYTHON_MODULE_VERSION} PARENT_SCOPE) set(${PYTHON_MODULE_NAME_UP}_FOUND TRUE PARENT_SCOPE) else() @@ -167,7 +171,7 @@ if (WITH_GUDHI_PYTHON) function( find_python_module_no_version PYTHON_MODULE_NAME ) string(TOUPPER ${PYTHON_MODULE_NAME} PYTHON_MODULE_NAME_UP) execute_process( - COMMAND ${PYTHON_EXECUTABLE} -c "import ${PYTHON_MODULE_NAME}" + COMMAND ${Python_EXECUTABLE} -c "import ${PYTHON_MODULE_NAME}" RESULT_VARIABLE PYTHON_MODULE_RESULT ERROR_VARIABLE PYTHON_MODULE_ERROR) if(PYTHON_MODULE_RESULT EQUAL 0) @@ -181,8 +185,8 @@ if (WITH_GUDHI_PYTHON) set(${PYTHON_MODULE_NAME_UP}_FOUND FALSE PARENT_SCOPE) endif() endfunction( find_python_module_no_version ) - - if( PYTHONINTERP_FOUND ) + + if( TARGET Python::Interpreter ) find_python_module("cython") find_python_module("pytest") find_python_module("matplotlib") @@ -202,19 +206,11 @@ if (WITH_GUDHI_PYTHON) find_python_module_no_version("sphinxcontrib.bibtex") find_python_module("networkx") endif() - + if(NOT GUDHI_PYTHON_PATH) message(FATAL_ERROR "ERROR: GUDHI_PYTHON_PATH is not valid.") endif(NOT GUDHI_PYTHON_PATH) - + option(WITH_GUDHI_PYTHON_RUNTIME_LIBRARY_DIRS "Build with setting runtime_library_dirs. Useful when setting rpath is not allowed" ON) - - if(PYTHONINTERP_FOUND AND CYTHON_FOUND) - if(SPHINX_FOUND) - # Documentation generation is available through sphinx - #find_program( SPHINX_PATH sphinx-build ) - # Calling sphinx-build may use a different version of python and fail - set(SPHINX_PATH "${PYTHON_EXECUTABLE}" "-m" "sphinx.cmd.build") - endif(SPHINX_FOUND) - endif(PYTHONINTERP_FOUND AND CYTHON_FOUND) + endif (WITH_GUDHI_PYTHON) diff --git a/src/common/doc/installation.h b/src/common/doc/installation.h index f068bde921..ca5f03299a 100644 --- a/src/common/doc/installation.h +++ b/src/common/doc/installation.h @@ -6,7 +6,7 @@ * * \section compiling Compiling * The library uses c++17 and requires Boost ≥ 1.71.0 - * and CMake ≥ 3.8. + * and CMake ≥ 3.15. * It is a multi-platform library and compiles on Linux, Mac OSX and Visual Studio 2017. * * \subsection utilities Utilities and examples diff --git a/src/python/CMakeLists.txt b/src/python/CMakeLists.txt index e953fee2b7..c60f7b9460 100644 --- a/src/python/CMakeLists.txt +++ b/src/python/CMakeLists.txt @@ -1,3 +1,24 @@ +if (NOT TARGET Python::Interpreter) + message("++ Python module will not be compiled because no Python interpreter was found") + set(GUDHI_MISSING_MODULES ${GUDHI_MISSING_MODULES} "python" CACHE INTERNAL "GUDHI_MISSING_MODULES") + return() +endif() +if (NOT NUMPY_FOUND) + message("++ Python module will not be compiled because numpy was not found") + set(GUDHI_MISSING_MODULES ${GUDHI_MISSING_MODULES} "python" CACHE INTERNAL "GUDHI_MISSING_MODULES") + return() +endif() +if(NOT CYTHON_FOUND) + message("++ Python module will not be compiled because cython was not found") + set(GUDHI_MISSING_MODULES ${GUDHI_MISSING_MODULES} "python" CACHE INTERNAL "GUDHI_MISSING_MODULES") + return() +endif() +if(NOT PYBIND11_FOUND) + message("++ Python module will not be compiled because pybind11 was not found") + set(GUDHI_MISSING_MODULES ${GUDHI_MISSING_MODULES} "python" CACHE INTERNAL "GUDHI_MISSING_MODULES") + return() +endif() + function( add_GUDHI_PYTHON_lib THE_LIB ) if(EXISTS ${THE_LIB}) get_filename_component(THE_LIB_FILE_NAME ${THE_LIB} NAME_WE) @@ -27,11 +48,11 @@ endfunction( add_GUDHI_PYTHON_lib_dir ) # THE_TEST is the python test file name (without .py extension) containing tests functions function( add_gudhi_py_test THE_TEST ) if(PYTEST_FOUND) - # use ${PYTHON_EXECUTABLE} -B, otherwise a __pycache__ directory is created in sources by python + # use ${Python_EXECUTABLE} -B, otherwise a __pycache__ directory is created in sources by python # use py.test no cache provider, otherwise a .cache file is created in sources by py.test add_test(NAME ${THE_TEST}_py_test WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - COMMAND ${PYTHON_EXECUTABLE} -B -m pytest -p no:cacheprovider ${CMAKE_CURRENT_SOURCE_DIR}/test/${THE_TEST}.py) + COMMAND ${Python_EXECUTABLE} -B -m pytest -p no:cacheprovider ${CMAKE_CURRENT_SOURCE_DIR}/test/${THE_TEST}.py) endif() endfunction( add_gudhi_py_test ) @@ -41,663 +62,632 @@ function( add_gudhi_debug_info DEBUG_INFO ) set(GUDHI_PYTHON_DEBUG_INFO "${GUDHI_PYTHON_DEBUG_INFO} \"${DEBUG_INFO}\\n\" \\\n" PARENT_SCOPE) endfunction( add_gudhi_debug_info ) -if(PYTHONINTERP_FOUND) - if(NUMPY_FOUND AND PYBIND11_FOUND AND CYTHON_FOUND) - add_gudhi_debug_info("Pybind11 version ${PYBIND11_VERSION}") - # PyBind11 modules - set(GUDHI_PYTHON_MODULES "${GUDHI_PYTHON_MODULES}'bottleneck', ") - set(GUDHI_PYTHON_MODULES_EXTRA "${GUDHI_PYTHON_MODULES_EXTRA}'hera', ") - set(GUDHI_PYTHON_MODULES_EXTRA "${GUDHI_PYTHON_MODULES_EXTRA}'clustering', ") - set(GUDHI_PYTHON_MODULES_EXTRA "${GUDHI_PYTHON_MODULES_EXTRA}'datasets', ") - - # Cython modules - set(GUDHI_PYTHON_MODULES "${GUDHI_PYTHON_MODULES}'off_utils', ") - set(GUDHI_PYTHON_MODULES "${GUDHI_PYTHON_MODULES}'simplex_tree', ") - set(GUDHI_PYTHON_MODULES "${GUDHI_PYTHON_MODULES}'rips_complex', ") - set(GUDHI_PYTHON_MODULES "${GUDHI_PYTHON_MODULES}'cubical_complex', ") - set(GUDHI_PYTHON_MODULES "${GUDHI_PYTHON_MODULES}'periodic_cubical_complex', ") - set(GUDHI_PYTHON_MODULES "${GUDHI_PYTHON_MODULES}'persistence_graphical_tools', ") - set(GUDHI_PYTHON_MODULES "${GUDHI_PYTHON_MODULES}'reader_utils', ") - set(GUDHI_PYTHON_MODULES "${GUDHI_PYTHON_MODULES}'witness_complex', ") - set(GUDHI_PYTHON_MODULES "${GUDHI_PYTHON_MODULES}'strong_witness_complex', ") - set(GUDHI_PYTHON_MODULES "${GUDHI_PYTHON_MODULES}'nerve_gic', ") - set(GUDHI_PYTHON_MODULES "${GUDHI_PYTHON_MODULES}'subsampling', ") - set(GUDHI_PYTHON_MODULES "${GUDHI_PYTHON_MODULES}'tangential_complex', ") - set(GUDHI_PYTHON_MODULES "${GUDHI_PYTHON_MODULES}'delaunay_complex', ") - set(GUDHI_PYTHON_MODULES "${GUDHI_PYTHON_MODULES}'euclidean_witness_complex', ") - set(GUDHI_PYTHON_MODULES "${GUDHI_PYTHON_MODULES}'euclidean_strong_witness_complex', ") - # Modules that should not be auto-imported in __init__.py - set(GUDHI_PYTHON_MODULES_EXTRA "${GUDHI_PYTHON_MODULES_EXTRA}'representations', ") - set(GUDHI_PYTHON_MODULES_EXTRA "${GUDHI_PYTHON_MODULES_EXTRA}'sklearn', ") - set(GUDHI_PYTHON_MODULES_EXTRA "${GUDHI_PYTHON_MODULES_EXTRA}'tensorflow', ") - set(GUDHI_PYTHON_MODULES_EXTRA "${GUDHI_PYTHON_MODULES_EXTRA}'wasserstein', ") - set(GUDHI_PYTHON_MODULES_EXTRA "${GUDHI_PYTHON_MODULES_EXTRA}'point_cloud', ") - set(GUDHI_PYTHON_MODULES_EXTRA "${GUDHI_PYTHON_MODULES_EXTRA}'weighted_rips_complex', ") - set(GUDHI_PYTHON_MODULES_EXTRA "${GUDHI_PYTHON_MODULES_EXTRA}'dtm_rips_complex', ") - set(GUDHI_PYTHON_MODULES_EXTRA "${GUDHI_PYTHON_MODULES_EXTRA}'cover_complex', ") - set(GUDHI_PYTHON_MODULES_EXTRA "${GUDHI_PYTHON_MODULES_EXTRA}'flag_filtration', ") - - add_gudhi_debug_info("Python version ${PYTHON_VERSION_STRING}") - add_gudhi_debug_info("Cython version ${CYTHON_VERSION}") - if(PYTEST_FOUND) - add_gudhi_debug_info("Pytest version ${PYTEST_VERSION}") - endif() - if(MATPLOTLIB_FOUND) - add_gudhi_debug_info("Matplotlib version ${MATPLOTLIB_VERSION}") - endif() - if(NUMPY_FOUND) - add_gudhi_debug_info("Numpy version ${NUMPY_VERSION}") - endif() - if(SCIPY_FOUND) - add_gudhi_debug_info("Scipy version ${SCIPY_VERSION}") - endif() - if(SKLEARN_FOUND) - add_gudhi_debug_info("Scikit-learn version ${SKLEARN_VERSION}") - endif() - if(OT_FOUND) - add_gudhi_debug_info("POT version ${OT_VERSION}") - endif() - if(HNSWLIB_FOUND) - # Does not have a version number... - add_gudhi_debug_info("HNSWlib found") - endif() - if(TORCH_FOUND) - add_gudhi_debug_info("PyTorch version ${TORCH_VERSION}") - endif() - if(PYKEOPS_FOUND) - add_gudhi_debug_info("PyKeOps version ${PYKEOPS_VERSION}") - endif() - if(EAGERPY_FOUND) - add_gudhi_debug_info("EagerPy version ${EAGERPY_VERSION}") - endif() - if(TENSORFLOW_FOUND) - add_gudhi_debug_info("TensorFlow version ${TENSORFLOW_VERSION}") - endif() - if(SPHINX_FOUND) - add_gudhi_debug_info("Sphinx version ${SPHINX_VERSION}") - endif() - if(SPHINX_PARAMLINKS_FOUND) - add_gudhi_debug_info("Sphinx-paramlinks version ${SPHINX_PARAMLINKS_VERSION}") - endif() - if(PYDATA_SPHINX_THEME_FOUND) - add_gudhi_debug_info("pydata_sphinx_theme version ${PYDATA_SPHINX_THEME_VERSION}") - endif() - if(SPHINXCONTRIB.BIBTEX_FOUND) - # Does not have a version number... - add_gudhi_debug_info("sphinxcontrib-bibtex found") - endif() - if(NETWORKX_FOUND) - add_gudhi_debug_info("NetworkX version ${NETWORKX_VERSION}") - endif() - - set(GUDHI_PYTHON_EXTRA_COMPILE_ARGS "${GUDHI_PYTHON_EXTRA_COMPILE_ARGS}'-DBOOST_RESULT_OF_USE_DECLTYPE', ") - set(GUDHI_PYTHON_EXTRA_COMPILE_ARGS "${GUDHI_PYTHON_EXTRA_COMPILE_ARGS}'-DBOOST_ALL_NO_LIB', ") - set(GUDHI_PYTHON_EXTRA_COMPILE_ARGS "${GUDHI_PYTHON_EXTRA_COMPILE_ARGS}'-DBOOST_SYSTEM_NO_DEPRECATED', ") - - # Gudhi and CGAL compilation option - if(MSVC) - set(GUDHI_PYTHON_EXTRA_COMPILE_ARGS "${GUDHI_PYTHON_EXTRA_COMPILE_ARGS}'/std:c++17', ") - set(GUDHI_PYTHON_EXTRA_COMPILE_ARGS "${GUDHI_PYTHON_EXTRA_COMPILE_ARGS}'/fp:strict', ") - # cf. https://github.com/oneapi-src/oneTBB/issues/573 - set(GUDHI_PYTHON_EXTRA_COMPILE_ARGS "${GUDHI_PYTHON_EXTRA_COMPILE_ARGS}'-DNOMINMAX', ") - else(MSVC) - set(GUDHI_PYTHON_EXTRA_COMPILE_ARGS "${GUDHI_PYTHON_EXTRA_COMPILE_ARGS}'-std=c++17', ") - endif(MSVC) - if(CMAKE_COMPILER_IS_GNUCXX) - set(GUDHI_PYTHON_EXTRA_COMPILE_ARGS "${GUDHI_PYTHON_EXTRA_COMPILE_ARGS}'-frounding-math', ") - set(GUDHI_PYBIND11_EXTRA_COMPILE_ARGS "${GUDHI_PYBIND11_EXTRA_COMPILE_ARGS}'-fvisibility=hidden', ") - endif(CMAKE_COMPILER_IS_GNUCXX) - if (CMAKE_CXX_COMPILER_ID MATCHES Intel) - set(GUDHI_PYTHON_EXTRA_COMPILE_ARGS "${GUDHI_PYTHON_EXTRA_COMPILE_ARGS}'-fp-model strict', ") - endif(CMAKE_CXX_COMPILER_ID MATCHES Intel) - if (DEBUG_TRACES) - # For programs to be more verbose - set(GUDHI_PYTHON_EXTRA_COMPILE_ARGS "${GUDHI_PYTHON_EXTRA_COMPILE_ARGS}'-DDEBUG_TRACES', ") - endif() - - if (TARGET Eigen3::Eigen) - add_gudhi_debug_info("Eigen3 version ${EIGEN3_VERSION_STRING}") - # No problem, even if no CGAL found - set(GUDHI_PYTHON_EXTRA_COMPILE_ARGS "${GUDHI_PYTHON_EXTRA_COMPILE_ARGS}'-DCGAL_EIGEN3_ENABLED', ") - set(GUDHI_PYTHON_INCLUDE_DIRS "${GUDHI_PYTHON_INCLUDE_DIRS}'${EIGEN3_INCLUDE_DIRS}', ") - endif (TARGET Eigen3::Eigen) - - set(GUDHI_CYTHON_MODULES "${GUDHI_CYTHON_MODULES}'off_utils', ") - set(GUDHI_CYTHON_MODULES "${GUDHI_CYTHON_MODULES}'simplex_tree', ") - set(GUDHI_CYTHON_MODULES "${GUDHI_CYTHON_MODULES}'rips_complex', ") - set(GUDHI_CYTHON_MODULES "${GUDHI_CYTHON_MODULES}'cubical_complex', ") - set(GUDHI_CYTHON_MODULES "${GUDHI_CYTHON_MODULES}'periodic_cubical_complex', ") - set(GUDHI_CYTHON_MODULES "${GUDHI_CYTHON_MODULES}'reader_utils', ") - set(GUDHI_CYTHON_MODULES "${GUDHI_CYTHON_MODULES}'witness_complex', ") - set(GUDHI_CYTHON_MODULES "${GUDHI_CYTHON_MODULES}'strong_witness_complex', ") - set(GUDHI_PYBIND11_MODULES "${GUDHI_PYBIND11_MODULES}'clustering/_tomato', ") - set(GUDHI_PYBIND11_MODULES "${GUDHI_PYBIND11_MODULES}'hera/wasserstein', ") - set(GUDHI_PYBIND11_MODULES "${GUDHI_PYBIND11_MODULES}'hera/bottleneck', ") - set(GUDHI_CYTHON_MODULES "${GUDHI_CYTHON_MODULES}'nerve_gic', ") - set(GUDHI_CYTHON_MODULES "${GUDHI_CYTHON_MODULES}'subsampling', ") - if (TARGET CGAL::CGAL) - set(GUDHI_PYBIND11_MODULES "${GUDHI_PYBIND11_MODULES}'bottleneck', ") - endif () - if (TARGET CGAL::CGAL AND TARGET Eigen3::Eigen) - set(GUDHI_CYTHON_MODULES "${GUDHI_CYTHON_MODULES}'tangential_complex', ") - set(GUDHI_CYTHON_MODULES "${GUDHI_CYTHON_MODULES}'euclidean_witness_complex', ") - set(GUDHI_CYTHON_MODULES "${GUDHI_CYTHON_MODULES}'euclidean_strong_witness_complex', ") - set(GUDHI_CYTHON_MODULES "${GUDHI_CYTHON_MODULES}'delaunay_complex', ") - set(GUDHI_PYBIND11_MODULES "${GUDHI_PYBIND11_MODULES}'datasets/generators/_points', ") - endif () - set(GUDHI_PYBIND11_MODULES "${GUDHI_PYBIND11_MODULES}'_pers_cub_low_dim', ") - set(GUDHI_PYBIND11_MODULES "${GUDHI_PYBIND11_MODULES}'_edge_collapse', ") - - # from windows vcpkg eigen 3.4.0#2 : build fails with - # error C2440: '': cannot convert from 'Eigen::EigenBase::Index' to '__gmp_expr' - # cf. https://gitlab.com/libeigen/eigen/-/issues/2476 - # Workaround is to compile with '-DEIGEN_DEFAULT_DENSE_INDEX_TYPE=int' - if (FORCE_EIGEN_DEFAULT_DENSE_INDEX_TYPE_TO_INT) - set(GUDHI_PYTHON_EXTRA_COMPILE_ARGS "${GUDHI_PYTHON_EXTRA_COMPILE_ARGS}'-DEIGEN_DEFAULT_DENSE_INDEX_TYPE=int', ") - endif() - - - add_gudhi_debug_info("Boost version ${Boost_VERSION}") - set(GUDHI_PYTHON_INCLUDE_DIRS "${GUDHI_PYTHON_INCLUDE_DIRS}'${Boost_INCLUDE_DIRS}', ") - if(TARGET CGAL::CGAL) - foreach(CGAL_INCLUDE_DIR ${CGAL_INCLUDE_DIRS}) - set(GUDHI_PYTHON_INCLUDE_DIRS "${GUDHI_PYTHON_INCLUDE_DIRS}'${CGAL_INCLUDE_DIR}', ") - endforeach() - if(NOT CGAL_VERSION VERSION_LESS 5.3.0) - # CGAL_HEADER_ONLY has been dropped for CGAL >= 5.3. Only the header-only version is supported. - set(CGAL_HEADER_ONLY True) - endif(NOT CGAL_VERSION VERSION_LESS 5.3.0) - # Add CGAL compilation args - if(CGAL_HEADER_ONLY) - add_gudhi_debug_info("CGAL header only version ${CGAL_VERSION}") - set(GUDHI_PYTHON_EXTRA_COMPILE_ARGS "${GUDHI_PYTHON_EXTRA_COMPILE_ARGS}'-DCGAL_HEADER_ONLY', ") - else(CGAL_HEADER_ONLY) - add_gudhi_debug_info("CGAL version ${CGAL_VERSION}") - add_GUDHI_PYTHON_lib("${CGAL_LIBRARY}") - add_GUDHI_PYTHON_lib_dir(${CGAL_LIBRARIES_DIR}) - message("** Add CGAL ${CGAL_LIBRARIES_DIR}") - # If CGAL is not header only, CGAL library may link with boost system, - if(CMAKE_BUILD_TYPE MATCHES Debug) - add_GUDHI_PYTHON_lib("${Boost_SYSTEM_LIBRARY_DEBUG}") - else() - add_GUDHI_PYTHON_lib("${Boost_SYSTEM_LIBRARY_RELEASE}") - endif() - add_GUDHI_PYTHON_lib_dir(${Boost_LIBRARY_DIRS}) - message("** Add Boost ${Boost_LIBRARY_DIRS}") - endif(CGAL_HEADER_ONLY) - # GMP and GMPXX are not required, but if present, CGAL will link with them. - if(GMP_FOUND) - add_gudhi_debug_info("GMP_LIBRARIES = ${GMP_LIBRARIES}") - set(GUDHI_PYTHON_EXTRA_COMPILE_ARGS "${GUDHI_PYTHON_EXTRA_COMPILE_ARGS}'-DCGAL_USE_GMP', ") - add_GUDHI_PYTHON_lib("${GMP_LIBRARIES}") - if(NOT GMP_LIBRARIES_DIR) - get_filename_component(GMP_LIBRARIES_DIR ${GMP_LIBRARIES} PATH) - message("GMP_LIBRARIES_DIR from GMP_LIBRARIES set to ${GMP_LIBRARIES_DIR}") - endif(NOT GMP_LIBRARIES_DIR) - add_GUDHI_PYTHON_lib_dir(${GMP_LIBRARIES_DIR}) - message("** Add gmp ${GMP_LIBRARIES_DIR}") - # When FORCE_CGAL_NOT_TO_BUILD_WITH_GMPXX is set, not defining CGAL_USE_GMPXX is sufficient enough - if(GMPXX_FOUND) - add_gudhi_debug_info("GMPXX_LIBRARIES = ${GMPXX_LIBRARIES}") - set(GUDHI_PYTHON_EXTRA_COMPILE_ARGS "${GUDHI_PYTHON_EXTRA_COMPILE_ARGS}'-DCGAL_USE_GMPXX', ") - add_GUDHI_PYTHON_lib("${GMPXX_LIBRARIES}") - add_GUDHI_PYTHON_lib_dir(${GMPXX_LIBRARIES_DIR}) - message("** Add gmpxx ${GMPXX_LIBRARIES_DIR}") - endif() - endif(GMP_FOUND) - if(MPFR_FOUND) - add_gudhi_debug_info("MPFR_LIBRARIES = ${MPFR_LIBRARIES}") - set(GUDHI_PYTHON_EXTRA_COMPILE_ARGS "${GUDHI_PYTHON_EXTRA_COMPILE_ARGS}'-DCGAL_USE_MPFR', ") - add_GUDHI_PYTHON_lib("${MPFR_LIBRARIES}") - # In case CGAL is not header only, all MPFR variables are set except MPFR_LIBRARIES_DIR - Just set it - if(NOT MPFR_LIBRARIES_DIR) - get_filename_component(MPFR_LIBRARIES_DIR ${MPFR_LIBRARIES} PATH) - message("MPFR_LIBRARIES_DIR from MPFR_LIBRARIES set to ${MPFR_LIBRARIES_DIR}") - endif(NOT MPFR_LIBRARIES_DIR) - add_GUDHI_PYTHON_lib_dir(${MPFR_LIBRARIES_DIR}) - message("** Add mpfr ${MPFR_LIBRARIES_DIR}") - endif(MPFR_FOUND) - endif(TARGET CGAL::CGAL) - - # Specific for Mac - if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin") - # CMAKE_OSX_DEPLOYMENT_TARGET is always set on OSx - # but it can be modified by the user by setting MACOSX_DEPLOYMENT_TARGET environment variable - if(CMAKE_OSX_DEPLOYMENT_TARGET) - set(GUDHI_PYTHON_EXTRA_COMPILE_ARGS "${GUDHI_PYTHON_EXTRA_COMPILE_ARGS}'-mmacosx-version-min=${CMAKE_OSX_DEPLOYMENT_TARGET}', ") - set(GUDHI_PYTHON_EXTRA_LINK_ARGS "${GUDHI_PYTHON_EXTRA_LINK_ARGS}'-mmacosx-version-min=${CMAKE_OSX_DEPLOYMENT_TARGET}', ") - endif() - endif(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") - - # Strip dynamic libraries in release mode for smaller pip packages under linux - if(CMAKE_COMPILER_IS_GNUCXX) - if(CMAKE_BUILD_TYPE MATCHES Release) - set(GUDHI_PYTHON_EXTRA_LINK_ARGS "${GUDHI_PYTHON_EXTRA_LINK_ARGS}'-s', ") - endif(CMAKE_BUILD_TYPE MATCHES Release) - endif(CMAKE_COMPILER_IS_GNUCXX) - - # Loop on INCLUDE_DIRECTORIES PROPERTY - get_property(GUDHI_INCLUDE_DIRECTORIES DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY INCLUDE_DIRECTORIES) - foreach(GUDHI_INCLUDE_DIRECTORY ${GUDHI_INCLUDE_DIRECTORIES}) - set(GUDHI_PYTHON_INCLUDE_DIRS "${GUDHI_PYTHON_INCLUDE_DIRS}'${GUDHI_INCLUDE_DIRECTORY}', ") - endforeach() - set(GUDHI_PYTHON_INCLUDE_DIRS "${GUDHI_PYTHON_INCLUDE_DIRS}'${CMAKE_SOURCE_DIR}/${GUDHI_PYTHON_PATH}/include', ") - - if (TBB_FOUND AND WITH_GUDHI_USE_TBB) - add_gudhi_debug_info("TBB version ${TBB_VERSION} found and used") - add_gudhi_debug_info("TBB_LIBRARY = ${TBB_LIBRARY}") - add_gudhi_debug_info("TBB_MALLOC_LIBRARY = ${TBB_MALLOC_LIBRARY}") - - set(GUDHI_PYTHON_EXTRA_COMPILE_ARGS "${GUDHI_PYTHON_EXTRA_COMPILE_ARGS}'-DGUDHI_USE_TBB', ") - add_GUDHI_PYTHON_lib("${TBB_LIBRARY}") - add_GUDHI_PYTHON_lib("${TBB_MALLOC_LIBRARY}") - add_GUDHI_PYTHON_lib_dir(${TBB_LIBRARY_DIRS}) - message("** Add tbb ${TBB_LIBRARY_DIRS}") - set(GUDHI_PYTHON_INCLUDE_DIRS "${GUDHI_PYTHON_INCLUDE_DIRS}'${TBB_INCLUDE_DIRS}', ") - endif() - - if(DEBUG_TRACES) - set(GUDHI_PYTHON_EXTRA_COMPILE_ARGS "${GUDHI_PYTHON_EXTRA_COMPILE_ARGS}'-DDEBUG_TRACES', ") - endif(DEBUG_TRACES) - - if(UNIX AND WITH_GUDHI_PYTHON_RUNTIME_LIBRARY_DIRS) - set( GUDHI_PYTHON_RUNTIME_LIBRARY_DIRS "${GUDHI_PYTHON_LIBRARY_DIRS}") - endif(UNIX AND WITH_GUDHI_PYTHON_RUNTIME_LIBRARY_DIRS) - - # doc/pip_introduction.inc is a restructured text file (extension changed because of sphinx warning) that describes - # the GUDHI project on https://pypi.org/project/gudhi/ - file(READ "doc/pypi_introduction.inc" GUDHI_LONG_DESCRIPTION_WITH_UNPROPER_CR) - string(REPLACE "\n" "\\n' \\\n '" GUDHI_LONG_DESCRIPTION ${GUDHI_LONG_DESCRIPTION_WITH_UNPROPER_CR}) - - # Generate setup.py file to cythonize Gudhi - This file must be named setup.py by convention - configure_file(setup.py.in "${CMAKE_CURRENT_BINARY_DIR}/setup.py" @ONLY) - - # Generate gudhi/__init__.py - file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/gudhi") - configure_file("gudhi/__init__.py.in" "${CMAKE_CURRENT_BINARY_DIR}/gudhi/__init__.py" @ONLY) - - # Other .py files - file(COPY "gudhi/persistence_graphical_tools.py" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/gudhi") - file(COPY "gudhi/representations" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/gudhi/") - file(COPY "gudhi/tensorflow" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/gudhi/") - file(COPY "gudhi/wasserstein" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/gudhi") - file(COPY "gudhi/point_cloud" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/gudhi") - file(COPY "gudhi/clustering" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/gudhi" FILES_MATCHING PATTERN "*.py") - file(COPY "gudhi/weighted_rips_complex.py" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/gudhi") - file(COPY "gudhi/dtm_rips_complex.py" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/gudhi") - file(COPY "gudhi/cover_complex.py" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/gudhi") - file(COPY "gudhi/_kepler_mapper.py" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/gudhi") - file(COPY "gudhi/_kepler_mapper.py.COPYRIGHT" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/gudhi") - file(COPY "gudhi/hera/__init__.py" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/gudhi/hera") - file(COPY "gudhi/datasets" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/gudhi" FILES_MATCHING PATTERN "*.py") - file(COPY "gudhi/sklearn" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/gudhi/") - file(COPY "gudhi/flag_filtration" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/gudhi/") - - - # Some files for pip package - file(COPY "pyproject.toml" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/") - - add_custom_command( - OUTPUT gudhi.so - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - COMMAND ${PYTHON_EXECUTABLE} "${CMAKE_CURRENT_BINARY_DIR}/setup.py" "build_ext" "--inplace") - - add_custom_target(python ALL DEPENDS gudhi.so - COMMENT "Do not forget to add ${CMAKE_CURRENT_BINARY_DIR}/ to your PYTHONPATH before using examples or tests") - - # Path separator management for windows - if (WIN32) - set(GUDHI_PYTHON_PATH_ENV "PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR};$ENV{PYTHONPATH}") - else(WIN32) - set(GUDHI_PYTHON_PATH_ENV "PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}:$ENV{PYTHONPATH}") - endif(WIN32) - # Documentation generation is available through sphinx - requires all modules - # Make it first as sphinx test is by far the longest test which is nice when testing in parallel - if(SPHINX_PATH) - if(SPHINX_PARAMLINKS_FOUND) - if(SPHINXCONTRIB.BIBTEX_FOUND) - if(PYDATA_SPHINX_THEME_FOUND) - if(MATPLOTLIB_FOUND) - if(NUMPY_FOUND) - if(SCIPY_FOUND) - if(SKLEARN_FOUND) - if(OT_FOUND) - if(TARGET CGAL::CGAL AND TARGET Eigen3::Eigen) - set (GUDHI_SPHINX_MESSAGE "Generating API documentation with Sphinx in ${CMAKE_CURRENT_BINARY_DIR}/sphinx/") - # User warning - Sphinx is a static pages generator, and configured to work fine with user_version - # Images and biblio warnings because not found on developer version - if (GUDHI_PYTHON_PATH STREQUAL "src/python") - set (GUDHI_SPHINX_MESSAGE "${GUDHI_SPHINX_MESSAGE} \n WARNING : Sphinx is configured for user version, you run it on developer version. Images and biblio will miss") - endif() - # sphinx target requires gudhi.so, because conf.py reads gudhi version from it - add_custom_target(sphinx - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/doc - COMMAND ${CMAKE_COMMAND} -E env "${GUDHI_PYTHON_PATH_ENV}" - ${SPHINX_PATH} -b html ${CMAKE_CURRENT_SOURCE_DIR}/doc ${CMAKE_CURRENT_BINARY_DIR}/sphinx - DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/gudhi.so" - COMMENT "${GUDHI_SPHINX_MESSAGE}" VERBATIM) - add_test(NAME sphinx_py_test - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - COMMAND ${CMAKE_COMMAND} -E env "${GUDHI_PYTHON_PATH_ENV}" - ${SPHINX_PATH} -b doctest ${CMAKE_CURRENT_SOURCE_DIR}/doc ${CMAKE_CURRENT_BINARY_DIR}/doctest) - # Set missing or not modules - set(GUDHI_MODULES ${GUDHI_MODULES} "python-documentation" CACHE INTERNAL "GUDHI_MODULES") - else(TARGET CGAL::CGAL AND TARGET Eigen3::Eigen) - message("++ Python documentation module will not be compiled because it requires Eigen3 >= 3.3.0 and CGAL >= 5.1.0") - set(GUDHI_MISSING_MODULES ${GUDHI_MISSING_MODULES} "python-documentation" CACHE INTERNAL "GUDHI_MISSING_MODULES") - endif(TARGET CGAL::CGAL AND TARGET Eigen3::Eigen) - else(OT_FOUND) - message("++ Python documentation module will not be compiled because POT was not found") - set(GUDHI_MISSING_MODULES ${GUDHI_MISSING_MODULES} "python-documentation" CACHE INTERNAL "GUDHI_MISSING_MODULES") - endif(OT_FOUND) - else(SKLEARN_FOUND) - message("++ Python documentation module will not be compiled because scikit-learn was not found") - set(GUDHI_MISSING_MODULES ${GUDHI_MISSING_MODULES} "python-documentation" CACHE INTERNAL "GUDHI_MISSING_MODULES") - endif(SKLEARN_FOUND) - else(SCIPY_FOUND) - message("++ Python documentation module will not be compiled because scipy was not found") - set(GUDHI_MISSING_MODULES ${GUDHI_MISSING_MODULES} "python-documentation" CACHE INTERNAL "GUDHI_MISSING_MODULES") - endif(SCIPY_FOUND) - else(NUMPY_FOUND) - message("++ Python documentation module will not be compiled because numpy was not found") - set(GUDHI_MISSING_MODULES ${GUDHI_MISSING_MODULES} "python-documentation" CACHE INTERNAL "GUDHI_MISSING_MODULES") - endif(NUMPY_FOUND) - else(MATPLOTLIB_FOUND) - message("++ Python documentation module will not be compiled because matplotlib was not found") - set(GUDHI_MISSING_MODULES ${GUDHI_MISSING_MODULES} "python-documentation" CACHE INTERNAL "GUDHI_MISSING_MODULES") - endif(MATPLOTLIB_FOUND) - else(PYDATA_SPHINX_THEME_FOUND) - message("++ Python documentation module will not be compiled because pydata_sphinx_theme was not found") - set(GUDHI_MISSING_MODULES ${GUDHI_MISSING_MODULES} "python-documentation" CACHE INTERNAL "GUDHI_MISSING_MODULES") - endif(PYDATA_SPHINX_THEME_FOUND) - else(SPHINXCONTRIB.BIBTEX_FOUND) - message("++ Python documentation module will not be compiled because sphinxcontrib-bibtex was not found") - set(GUDHI_MISSING_MODULES ${GUDHI_MISSING_MODULES} "python-documentation" CACHE INTERNAL "GUDHI_MISSING_MODULES") - endif(SPHINXCONTRIB.BIBTEX_FOUND) - else(SPHINX_PARAMLINKS_FOUND) - message("++ Python documentation module will not be compiled because sphinxcontrib-paramlinks was not found") - set(GUDHI_MISSING_MODULES ${GUDHI_MISSING_MODULES} "python-documentation" CACHE INTERNAL "GUDHI_MISSING_MODULES") - endif(SPHINX_PARAMLINKS_FOUND) - else(SPHINX_PATH) - message("++ Python documentation module will not be compiled because sphinx was not found") - set(GUDHI_MISSING_MODULES ${GUDHI_MISSING_MODULES} "python-documentation" CACHE INTERNAL "GUDHI_MISSING_MODULES") - endif(SPHINX_PATH) - - # Cubical - add_test(NAME periodic_cubical_complex_barcode_persistence_from_perseus_file_example_py_test - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - COMMAND ${CMAKE_COMMAND} -E env "${GUDHI_PYTHON_PATH_ENV}" - ${PYTHON_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/example/periodic_cubical_complex_barcode_persistence_from_perseus_file_example.py" - --no-barcode -f ${CMAKE_SOURCE_DIR}/data/bitmap/CubicalTwoSphere.txt) - - add_test(NAME random_cubical_complex_persistence_example_py_test - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - COMMAND ${CMAKE_COMMAND} -E env "${GUDHI_PYTHON_PATH_ENV}" - ${PYTHON_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/example/random_cubical_complex_persistence_example.py" - 10 10 10) - - add_gudhi_py_test(test_cubical_complex) - - # Datasets are fetched for these tests - if(SKLEARN_FOUND AND WITH_GUDHI_REMOTE_TEST) - add_gudhi_py_test(test_sklearn_cubical_persistence) - - add_test(NAME cubical_complex_sklearn_itf_py_test - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - COMMAND ${CMAKE_COMMAND} -E env "${GUDHI_PYTHON_PATH_ENV}" - ${PYTHON_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/example/cubical_complex_sklearn_itf.py") - endif() - - # Test examples - if (TARGET CGAL::CGAL AND TARGET Eigen3::Eigen) - # Bottleneck and Alpha - add_test(NAME alpha_rips_persistence_bottleneck_distance_py_test - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - COMMAND ${CMAKE_COMMAND} -E env "${GUDHI_PYTHON_PATH_ENV}" - ${PYTHON_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/example/alpha_rips_persistence_bottleneck_distance.py" - -f ${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off -t 0.15 -d 3) - endif (TARGET CGAL::CGAL AND TARGET Eigen3::Eigen) - if (TARGET CGAL::CGAL AND TARGET Eigen3::Eigen) - # Tangential - add_test(NAME tangential_complex_plain_homology_from_off_file_example_py_test - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - COMMAND ${CMAKE_COMMAND} -E env "${GUDHI_PYTHON_PATH_ENV}" - ${PYTHON_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/example/tangential_complex_plain_homology_from_off_file_example.py" - --no-diagram -i 2 -f ${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off) - - add_gudhi_py_test(test_tangential_complex) - - # Witness complex - add_test(NAME euclidean_strong_witness_complex_diagram_persistence_from_off_file_example_py_test - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - COMMAND ${CMAKE_COMMAND} -E env "${GUDHI_PYTHON_PATH_ENV}" - ${PYTHON_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/example/euclidean_strong_witness_complex_diagram_persistence_from_off_file_example.py" - --no-diagram -f ${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off -a 1.0 -n 20 -d 2) - - add_test(NAME euclidean_witness_complex_diagram_persistence_from_off_file_example_py_test - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - COMMAND ${CMAKE_COMMAND} -E env "${GUDHI_PYTHON_PATH_ENV}" - ${PYTHON_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/example/euclidean_witness_complex_diagram_persistence_from_off_file_example.py" - --no-diagram -f ${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off -a 1.0 -n 20 -d 2) - - endif (TARGET CGAL::CGAL AND TARGET Eigen3::Eigen) - if (TARGET CGAL::CGAL) - # Bottleneck - add_test(NAME bottleneck_basic_example_py_test - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - COMMAND ${CMAKE_COMMAND} -E env "${GUDHI_PYTHON_PATH_ENV}" - ${PYTHON_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/example/bottleneck_basic_example.py") - - add_gudhi_py_test(test_bottleneck_distance) - endif (TARGET CGAL::CGAL) - - # Cover complex - file(COPY ${CMAKE_SOURCE_DIR}/data/points/human.off DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/) - file(COPY ${CMAKE_SOURCE_DIR}/data/points/COIL_database/lucky_cat.off DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/) - file(COPY ${CMAKE_SOURCE_DIR}/data/points/COIL_database/lucky_cat_PCA1 DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/) - add_test(NAME cover_complex_nerve_example_py_test - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - COMMAND ${CMAKE_COMMAND} -E env "${GUDHI_PYTHON_PATH_ENV}" - ${PYTHON_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/example/nerve_of_a_covering.py" - -f human.off -c 2 -r 10 -g 0.3) - - add_test(NAME cover_complex_coordinate_gic_example_py_test - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - COMMAND ${CMAKE_COMMAND} -E env "${GUDHI_PYTHON_PATH_ENV}" - ${PYTHON_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/example/coordinate_graph_induced_complex.py" - -f human.off -c 0 -v) - - add_test(NAME cover_complex_functional_gic_example_py_test - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - COMMAND ${CMAKE_COMMAND} -E env "${GUDHI_PYTHON_PATH_ENV}" - ${PYTHON_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/example/functional_graph_induced_complex.py" - -o lucky_cat.off - -f lucky_cat_PCA1 -v) - - add_test(NAME cover_complex_voronoi_gic_example_py_test - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - COMMAND ${CMAKE_COMMAND} -E env "${GUDHI_PYTHON_PATH_ENV}" - ${PYTHON_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/example/voronoi_graph_induced_complex.py" - -f human.off -n 700 -v) - - if (TARGET CGAL::CGAL AND TARGET Eigen3::Eigen) - # Alpha - add_test(NAME alpha_complex_from_points_example_py_test - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - COMMAND ${CMAKE_COMMAND} -E env "${GUDHI_PYTHON_PATH_ENV}" - ${PYTHON_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/example/alpha_complex_from_points_example.py") - add_test(NAME alpha_complex_from_generated_points_on_sphere_example_py_test - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - COMMAND ${CMAKE_COMMAND} -E env "${GUDHI_PYTHON_PATH_ENV}" - ${PYTHON_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/example/alpha_complex_from_generated_points_on_sphere_example.py") - add_test(NAME alpha_complex_diagram_persistence_from_off_file_example_py_test - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - COMMAND ${CMAKE_COMMAND} -E env "${GUDHI_PYTHON_PATH_ENV}" - ${PYTHON_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/example/alpha_complex_diagram_persistence_from_off_file_example.py" - --no-diagram -f ${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off) - add_gudhi_py_test(test_alpha_complex) - add_gudhi_py_test(test_delaunay_complex) - endif (TARGET CGAL::CGAL AND TARGET Eigen3::Eigen) - - if (TARGET CGAL::CGAL AND TARGET Eigen3::Eigen) - # Euclidean witness - add_gudhi_py_test(test_euclidean_witness_complex) - - # Datasets generators - add_gudhi_py_test(test_datasets_generators) # TODO separate full python datasets generators in another test file independent from CGAL ? - - endif (TARGET CGAL::CGAL AND TARGET Eigen3::Eigen) - - # Rips - add_test(NAME rips_complex_diagram_persistence_from_distance_matrix_file_example_py_test - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - COMMAND ${CMAKE_COMMAND} -E env "${GUDHI_PYTHON_PATH_ENV}" - ${PYTHON_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/example/rips_complex_diagram_persistence_from_distance_matrix_file_example.py" - --no-diagram -f ${CMAKE_SOURCE_DIR}/data/distance_matrix/lower_triangular_distance_matrix.csv -s , -e 12.0 -d 3) - - add_test(NAME rips_complex_diagram_persistence_from_off_file_example_py_test - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - COMMAND ${CMAKE_COMMAND} -E env "${GUDHI_PYTHON_PATH_ENV}" - ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/example/rips_complex_diagram_persistence_from_off_file_example.py - --no-diagram -f ${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off -e 0.25 -d 3) - - add_test(NAME rips_complex_from_points_example_py_test - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - COMMAND ${CMAKE_COMMAND} -E env "${GUDHI_PYTHON_PATH_ENV}" - ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/example/rips_complex_from_points_example.py) - - add_gudhi_py_test(test_rips_complex) - - if(SKLEARN_FOUND) - # test_sklearn_rips_persistence is using gudhi.datasets.generators - if (TARGET CGAL::CGAL AND TARGET Eigen3::Eigen) - add_gudhi_py_test(test_sklearn_rips_persistence) - endif() - - # Datasets are fetched for these tests - if(WITH_GUDHI_REMOTE_TEST) - add_test(NAME rips_complex_sklearn_itf_py_test - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - COMMAND ${CMAKE_COMMAND} -E env "${GUDHI_PYTHON_PATH_ENV}" - ${PYTHON_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/example/rips_complex_sklearn_itf.py" "--no-plot") - endif() - endif() - - # Simplex tree - add_test(NAME simplex_tree_example_py_test - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - COMMAND ${CMAKE_COMMAND} -E env "${GUDHI_PYTHON_PATH_ENV}" - ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/example/simplex_tree_example.py) - - add_gudhi_py_test(test_simplex_tree) - add_gudhi_py_test(test_simplex_generators) - add_gudhi_py_test(test_simplex_tree_serialization) - - # Edge collapse - if(SCIPY_FOUND) - add_gudhi_py_test(test_collapse_edges) - endif() - - # Subsampling - add_gudhi_py_test(test_subsampling) +function(disable_python_documentation MISSING_MODULE) + set(GUDHI_PYTHON_DOCUMENTATION_MISSING_MODULES "${GUDHI_PYTHON_DOCUMENTATION_MISSING_MODULES}'${MISSING_MODULE}', " PARENT_SCOPE) + set(GUDHI_MISSING_MODULES ${GUDHI_MISSING_MODULES} "python-documentation" CACHE INTERNAL "GUDHI_MISSING_MODULES") +endfunction( disable_python_documentation ) + +add_gudhi_debug_info("Python version ${Python_VERSION}") +add_gudhi_debug_info("Pybind11 version ${PYBIND11_VERSION}") +# PyBind11 modules +set(GUDHI_PYTHON_MODULES "${GUDHI_PYTHON_MODULES}'bottleneck', ") +set(GUDHI_PYTHON_MODULES_EXTRA "${GUDHI_PYTHON_MODULES_EXTRA}'hera', ") +set(GUDHI_PYTHON_MODULES_EXTRA "${GUDHI_PYTHON_MODULES_EXTRA}'clustering', ") +set(GUDHI_PYTHON_MODULES_EXTRA "${GUDHI_PYTHON_MODULES_EXTRA}'datasets', ") + +# Cython modules +set(GUDHI_PYTHON_MODULES "${GUDHI_PYTHON_MODULES}'off_utils', ") +set(GUDHI_PYTHON_MODULES "${GUDHI_PYTHON_MODULES}'simplex_tree', ") +set(GUDHI_PYTHON_MODULES "${GUDHI_PYTHON_MODULES}'rips_complex', ") +set(GUDHI_PYTHON_MODULES "${GUDHI_PYTHON_MODULES}'cubical_complex', ") +set(GUDHI_PYTHON_MODULES "${GUDHI_PYTHON_MODULES}'periodic_cubical_complex', ") +set(GUDHI_PYTHON_MODULES "${GUDHI_PYTHON_MODULES}'persistence_graphical_tools', ") +set(GUDHI_PYTHON_MODULES "${GUDHI_PYTHON_MODULES}'reader_utils', ") +set(GUDHI_PYTHON_MODULES "${GUDHI_PYTHON_MODULES}'witness_complex', ") +set(GUDHI_PYTHON_MODULES "${GUDHI_PYTHON_MODULES}'strong_witness_complex', ") +set(GUDHI_PYTHON_MODULES "${GUDHI_PYTHON_MODULES}'nerve_gic', ") +set(GUDHI_PYTHON_MODULES "${GUDHI_PYTHON_MODULES}'subsampling', ") +set(GUDHI_PYTHON_MODULES "${GUDHI_PYTHON_MODULES}'tangential_complex', ") +set(GUDHI_PYTHON_MODULES "${GUDHI_PYTHON_MODULES}'delaunay_complex', ") +set(GUDHI_PYTHON_MODULES "${GUDHI_PYTHON_MODULES}'euclidean_witness_complex', ") +set(GUDHI_PYTHON_MODULES "${GUDHI_PYTHON_MODULES}'euclidean_strong_witness_complex', ") +# Modules that should not be auto-imported in __init__.py +set(GUDHI_PYTHON_MODULES_EXTRA "${GUDHI_PYTHON_MODULES_EXTRA}'representations', ") +set(GUDHI_PYTHON_MODULES_EXTRA "${GUDHI_PYTHON_MODULES_EXTRA}'sklearn', ") +set(GUDHI_PYTHON_MODULES_EXTRA "${GUDHI_PYTHON_MODULES_EXTRA}'tensorflow', ") +set(GUDHI_PYTHON_MODULES_EXTRA "${GUDHI_PYTHON_MODULES_EXTRA}'wasserstein', ") +set(GUDHI_PYTHON_MODULES_EXTRA "${GUDHI_PYTHON_MODULES_EXTRA}'point_cloud', ") +set(GUDHI_PYTHON_MODULES_EXTRA "${GUDHI_PYTHON_MODULES_EXTRA}'weighted_rips_complex', ") +set(GUDHI_PYTHON_MODULES_EXTRA "${GUDHI_PYTHON_MODULES_EXTRA}'dtm_rips_complex', ") +set(GUDHI_PYTHON_MODULES_EXTRA "${GUDHI_PYTHON_MODULES_EXTRA}'cover_complex', ") +set(GUDHI_PYTHON_MODULES_EXTRA "${GUDHI_PYTHON_MODULES_EXTRA}'flag_filtration', ") + +add_gudhi_debug_info("Cython version ${CYTHON_VERSION}") +add_gudhi_debug_info("Numpy version ${NUMPY_VERSION}") + +if(PYTEST_FOUND) + add_gudhi_debug_info("Pytest version ${PYTEST_VERSION}") +endif() +if(MATPLOTLIB_FOUND) + add_gudhi_debug_info("Matplotlib version ${MATPLOTLIB_VERSION}") +else() + disable_python_documentation("matplotlib") +endif() +if(SCIPY_FOUND) + add_gudhi_debug_info("Scipy version ${SCIPY_VERSION}") +else() + disable_python_documentation("scipy") +endif() +if(SKLEARN_FOUND) + add_gudhi_debug_info("Scikit-learn version ${SKLEARN_VERSION}") +else() + disable_python_documentation("sklearn") +endif() +if(OT_FOUND) + add_gudhi_debug_info("POT version ${OT_VERSION}") +else() + disable_python_documentation("ot") +endif() +if(HNSWLIB_FOUND) + # Does not have a version number... + add_gudhi_debug_info("HNSWlib found") +endif() +if(TORCH_FOUND) + add_gudhi_debug_info("PyTorch version ${TORCH_VERSION}") +endif() +if(PYKEOPS_FOUND) + add_gudhi_debug_info("PyKeOps version ${PYKEOPS_VERSION}") +endif() +if(EAGERPY_FOUND) + add_gudhi_debug_info("EagerPy version ${EAGERPY_VERSION}") +endif() +if(TENSORFLOW_FOUND) + add_gudhi_debug_info("TensorFlow version ${TENSORFLOW_VERSION}") +endif() +if(SPHINX_FOUND) + add_gudhi_debug_info("Sphinx version ${SPHINX_VERSION}") + # Calling sphinx-build executable (that could be found find_program) may use a different version of python and fail + set(SPHINX_PATH "${Python_EXECUTABLE}" "-m" "sphinx.cmd.build") +else() + disable_python_documentation("sphinx") +endif() +if(SPHINX_PARAMLINKS_FOUND) + add_gudhi_debug_info("Sphinx-paramlinks version ${SPHINX_PARAMLINKS_VERSION}") +else() + disable_python_documentation("sphinx-paramlinks") +endif() +if(PYDATA_SPHINX_THEME_FOUND) + add_gudhi_debug_info("pydata_sphinx_theme version ${PYDATA_SPHINX_THEME_VERSION}") +else() + disable_python_documentation("pydata_sphinx_theme") +endif() +if(SPHINXCONTRIB.BIBTEX_FOUND) + # Does not have a version number... + add_gudhi_debug_info("sphinxcontrib-bibtex found") +else() + disable_python_documentation("sphinxcontrib-bibtex") +endif() +if(NETWORKX_FOUND) + add_gudhi_debug_info("NetworkX version ${NETWORKX_VERSION}") +endif() +if(NOT TARGET CGAL::CGAL) + disable_python_documentation("CGAL") +endif() +if (NOT TARGET Eigen3::Eigen) + disable_python_documentation("Eigen3") +endif() + +set(GUDHI_PYTHON_EXTRA_COMPILE_ARGS "${GUDHI_PYTHON_EXTRA_COMPILE_ARGS}'-DBOOST_RESULT_OF_USE_DECLTYPE', ") +set(GUDHI_PYTHON_EXTRA_COMPILE_ARGS "${GUDHI_PYTHON_EXTRA_COMPILE_ARGS}'-DBOOST_ALL_NO_LIB', ") +set(GUDHI_PYTHON_EXTRA_COMPILE_ARGS "${GUDHI_PYTHON_EXTRA_COMPILE_ARGS}'-DBOOST_SYSTEM_NO_DEPRECATED', ") + +# Gudhi and CGAL compilation option +if(MSVC) + set(GUDHI_PYTHON_EXTRA_COMPILE_ARGS "${GUDHI_PYTHON_EXTRA_COMPILE_ARGS}'/std:c++17', ") + set(GUDHI_PYTHON_EXTRA_COMPILE_ARGS "${GUDHI_PYTHON_EXTRA_COMPILE_ARGS}'/fp:strict', ") + # cf. https://github.com/oneapi-src/oneTBB/issues/573 + set(GUDHI_PYTHON_EXTRA_COMPILE_ARGS "${GUDHI_PYTHON_EXTRA_COMPILE_ARGS}'-DNOMINMAX', ") +else(MSVC) + set(GUDHI_PYTHON_EXTRA_COMPILE_ARGS "${GUDHI_PYTHON_EXTRA_COMPILE_ARGS}'-std=c++17', ") +endif(MSVC) +if(CMAKE_COMPILER_IS_GNUCXX) + set(GUDHI_PYTHON_EXTRA_COMPILE_ARGS "${GUDHI_PYTHON_EXTRA_COMPILE_ARGS}'-frounding-math', ") + set(GUDHI_PYBIND11_EXTRA_COMPILE_ARGS "${GUDHI_PYBIND11_EXTRA_COMPILE_ARGS}'-fvisibility=hidden', ") +endif(CMAKE_COMPILER_IS_GNUCXX) +if (CMAKE_CXX_COMPILER_ID MATCHES Intel) + set(GUDHI_PYTHON_EXTRA_COMPILE_ARGS "${GUDHI_PYTHON_EXTRA_COMPILE_ARGS}'-fp-model strict', ") +endif(CMAKE_CXX_COMPILER_ID MATCHES Intel) +if (DEBUG_TRACES) + # For programs to be more verbose + set(GUDHI_PYTHON_EXTRA_COMPILE_ARGS "${GUDHI_PYTHON_EXTRA_COMPILE_ARGS}'-DDEBUG_TRACES', ") +endif() + +if (TARGET Eigen3::Eigen) + add_gudhi_debug_info("Eigen3 version ${EIGEN3_VERSION_STRING}") + # No problem, even if no CGAL found + set(GUDHI_PYTHON_EXTRA_COMPILE_ARGS "${GUDHI_PYTHON_EXTRA_COMPILE_ARGS}'-DCGAL_EIGEN3_ENABLED', ") + set(GUDHI_PYTHON_INCLUDE_DIRS "${GUDHI_PYTHON_INCLUDE_DIRS}'${EIGEN3_INCLUDE_DIRS}', ") +endif (TARGET Eigen3::Eigen) + +set(GUDHI_CYTHON_MODULES "${GUDHI_CYTHON_MODULES}'off_utils', ") +set(GUDHI_CYTHON_MODULES "${GUDHI_CYTHON_MODULES}'simplex_tree', ") +set(GUDHI_CYTHON_MODULES "${GUDHI_CYTHON_MODULES}'rips_complex', ") +set(GUDHI_CYTHON_MODULES "${GUDHI_CYTHON_MODULES}'cubical_complex', ") +set(GUDHI_CYTHON_MODULES "${GUDHI_CYTHON_MODULES}'periodic_cubical_complex', ") +set(GUDHI_CYTHON_MODULES "${GUDHI_CYTHON_MODULES}'reader_utils', ") +set(GUDHI_CYTHON_MODULES "${GUDHI_CYTHON_MODULES}'witness_complex', ") +set(GUDHI_CYTHON_MODULES "${GUDHI_CYTHON_MODULES}'strong_witness_complex', ") +set(GUDHI_PYBIND11_MODULES "${GUDHI_PYBIND11_MODULES}'clustering/_tomato', ") +set(GUDHI_PYBIND11_MODULES "${GUDHI_PYBIND11_MODULES}'hera/wasserstein', ") +set(GUDHI_PYBIND11_MODULES "${GUDHI_PYBIND11_MODULES}'hera/bottleneck', ") +set(GUDHI_CYTHON_MODULES "${GUDHI_CYTHON_MODULES}'nerve_gic', ") +set(GUDHI_CYTHON_MODULES "${GUDHI_CYTHON_MODULES}'subsampling', ") +if (TARGET CGAL::CGAL) + set(GUDHI_PYBIND11_MODULES "${GUDHI_PYBIND11_MODULES}'bottleneck', ") +endif () +if (TARGET CGAL::CGAL AND TARGET Eigen3::Eigen) + set(GUDHI_CYTHON_MODULES "${GUDHI_CYTHON_MODULES}'tangential_complex', ") + set(GUDHI_CYTHON_MODULES "${GUDHI_CYTHON_MODULES}'euclidean_witness_complex', ") + set(GUDHI_CYTHON_MODULES "${GUDHI_CYTHON_MODULES}'euclidean_strong_witness_complex', ") + set(GUDHI_CYTHON_MODULES "${GUDHI_CYTHON_MODULES}'delaunay_complex', ") + set(GUDHI_PYBIND11_MODULES "${GUDHI_PYBIND11_MODULES}'datasets/generators/_points', ") +endif () +set(GUDHI_PYBIND11_MODULES "${GUDHI_PYBIND11_MODULES}'_pers_cub_low_dim', ") +set(GUDHI_PYBIND11_MODULES "${GUDHI_PYBIND11_MODULES}'_edge_collapse', ") + +# from windows vcpkg eigen 3.4.0#2 : build fails with +# error C2440: '': cannot convert from 'Eigen::EigenBase::Index' to '__gmp_expr' +# cf. https://gitlab.com/libeigen/eigen/-/issues/2476 +# Workaround is to compile with '-DEIGEN_DEFAULT_DENSE_INDEX_TYPE=int' +if (FORCE_EIGEN_DEFAULT_DENSE_INDEX_TYPE_TO_INT) + set(GUDHI_PYTHON_EXTRA_COMPILE_ARGS "${GUDHI_PYTHON_EXTRA_COMPILE_ARGS}'-DEIGEN_DEFAULT_DENSE_INDEX_TYPE=int', ") +endif() + +add_gudhi_debug_info("Boost version ${Boost_VERSION}") +set(GUDHI_PYTHON_INCLUDE_DIRS "${GUDHI_PYTHON_INCLUDE_DIRS}'${Boost_INCLUDE_DIRS}', ") +if(TARGET CGAL::CGAL) + foreach(CGAL_INCLUDE_DIR ${CGAL_INCLUDE_DIRS}) + set(GUDHI_PYTHON_INCLUDE_DIRS "${GUDHI_PYTHON_INCLUDE_DIRS}'${CGAL_INCLUDE_DIR}', ") + endforeach() + if(NOT CGAL_VERSION VERSION_LESS 5.3.0) + # CGAL_HEADER_ONLY has been dropped for CGAL >= 5.3. Only the header-only version is supported. + set(CGAL_HEADER_ONLY True) + endif(NOT CGAL_VERSION VERSION_LESS 5.3.0) + # Add CGAL compilation args + if(CGAL_HEADER_ONLY) + add_gudhi_debug_info("CGAL header only version ${CGAL_VERSION}") + set(GUDHI_PYTHON_EXTRA_COMPILE_ARGS "${GUDHI_PYTHON_EXTRA_COMPILE_ARGS}'-DCGAL_HEADER_ONLY', ") + else(CGAL_HEADER_ONLY) + add_gudhi_debug_info("CGAL version ${CGAL_VERSION}") + add_GUDHI_PYTHON_lib("${CGAL_LIBRARY}") + add_GUDHI_PYTHON_lib_dir(${CGAL_LIBRARIES_DIR}) + message("** Add CGAL ${CGAL_LIBRARIES_DIR}") + # If CGAL is not header only, CGAL library may link with boost system, + if(CMAKE_BUILD_TYPE MATCHES Debug) + add_GUDHI_PYTHON_lib("${Boost_SYSTEM_LIBRARY_DEBUG}") + else() + add_GUDHI_PYTHON_lib("${Boost_SYSTEM_LIBRARY_RELEASE}") + endif() + add_GUDHI_PYTHON_lib_dir(${Boost_LIBRARY_DIRS}) + message("** Add Boost ${Boost_LIBRARY_DIRS}") + endif(CGAL_HEADER_ONLY) + # GMP and GMPXX are not required, but if present, CGAL will link with them. + if(GMP_FOUND) + add_gudhi_debug_info("GMP_LIBRARIES = ${GMP_LIBRARIES}") + set(GUDHI_PYTHON_EXTRA_COMPILE_ARGS "${GUDHI_PYTHON_EXTRA_COMPILE_ARGS}'-DCGAL_USE_GMP', ") + add_GUDHI_PYTHON_lib("${GMP_LIBRARIES}") + if(NOT GMP_LIBRARIES_DIR) + get_filename_component(GMP_LIBRARIES_DIR ${GMP_LIBRARIES} PATH) + message("GMP_LIBRARIES_DIR from GMP_LIBRARIES set to ${GMP_LIBRARIES_DIR}") + endif(NOT GMP_LIBRARIES_DIR) + add_GUDHI_PYTHON_lib_dir(${GMP_LIBRARIES_DIR}) + message("** Add gmp ${GMP_LIBRARIES_DIR}") + # When FORCE_CGAL_NOT_TO_BUILD_WITH_GMPXX is set, not defining CGAL_USE_GMPXX is sufficient enough + if(GMPXX_FOUND) + add_gudhi_debug_info("GMPXX_LIBRARIES = ${GMPXX_LIBRARIES}") + set(GUDHI_PYTHON_EXTRA_COMPILE_ARGS "${GUDHI_PYTHON_EXTRA_COMPILE_ARGS}'-DCGAL_USE_GMPXX', ") + add_GUDHI_PYTHON_lib("${GMPXX_LIBRARIES}") + add_GUDHI_PYTHON_lib_dir(${GMPXX_LIBRARIES_DIR}) + message("** Add gmpxx ${GMPXX_LIBRARIES_DIR}") + endif() + endif(GMP_FOUND) + if(MPFR_FOUND) + add_gudhi_debug_info("MPFR_LIBRARIES = ${MPFR_LIBRARIES}") + set(GUDHI_PYTHON_EXTRA_COMPILE_ARGS "${GUDHI_PYTHON_EXTRA_COMPILE_ARGS}'-DCGAL_USE_MPFR', ") + add_GUDHI_PYTHON_lib("${MPFR_LIBRARIES}") + # In case CGAL is not header only, all MPFR variables are set except MPFR_LIBRARIES_DIR - Just set it + if(NOT MPFR_LIBRARIES_DIR) + get_filename_component(MPFR_LIBRARIES_DIR ${MPFR_LIBRARIES} PATH) + message("MPFR_LIBRARIES_DIR from MPFR_LIBRARIES set to ${MPFR_LIBRARIES_DIR}") + endif(NOT MPFR_LIBRARIES_DIR) + add_GUDHI_PYTHON_lib_dir(${MPFR_LIBRARIES_DIR}) + message("** Add mpfr ${MPFR_LIBRARIES_DIR}") + endif(MPFR_FOUND) +endif(TARGET CGAL::CGAL) + +# Specific for Mac +if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + # CMAKE_OSX_DEPLOYMENT_TARGET is always set on OSx + # but it can be modified by the user by setting MACOSX_DEPLOYMENT_TARGET environment variable + if(CMAKE_OSX_DEPLOYMENT_TARGET) + set(GUDHI_PYTHON_EXTRA_COMPILE_ARGS "${GUDHI_PYTHON_EXTRA_COMPILE_ARGS}'-mmacosx-version-min=${CMAKE_OSX_DEPLOYMENT_TARGET}', ") + set(GUDHI_PYTHON_EXTRA_LINK_ARGS "${GUDHI_PYTHON_EXTRA_LINK_ARGS}'-mmacosx-version-min=${CMAKE_OSX_DEPLOYMENT_TARGET}', ") + endif() +endif(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + +# Strip dynamic libraries in release mode for smaller pip packages under linux +if(CMAKE_COMPILER_IS_GNUCXX) + if(CMAKE_BUILD_TYPE MATCHES Release) + set(GUDHI_PYTHON_EXTRA_LINK_ARGS "${GUDHI_PYTHON_EXTRA_LINK_ARGS}'-s', ") + endif(CMAKE_BUILD_TYPE MATCHES Release) +endif(CMAKE_COMPILER_IS_GNUCXX) + +# Loop on INCLUDE_DIRECTORIES PROPERTY +get_property(GUDHI_INCLUDE_DIRECTORIES DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY INCLUDE_DIRECTORIES) +foreach(GUDHI_INCLUDE_DIRECTORY ${GUDHI_INCLUDE_DIRECTORIES}) + set(GUDHI_PYTHON_INCLUDE_DIRS "${GUDHI_PYTHON_INCLUDE_DIRS}'${GUDHI_INCLUDE_DIRECTORY}', ") +endforeach() +set(GUDHI_PYTHON_INCLUDE_DIRS "${GUDHI_PYTHON_INCLUDE_DIRS}'${CMAKE_SOURCE_DIR}/${GUDHI_PYTHON_PATH}/include', ") + +if (TBB_FOUND AND WITH_GUDHI_USE_TBB) + add_gudhi_debug_info("TBB version ${TBB_VERSION} found and used") + add_gudhi_debug_info("TBB_LIBRARY = ${TBB_LIBRARY}") + add_gudhi_debug_info("TBB_MALLOC_LIBRARY = ${TBB_MALLOC_LIBRARY}") + + set(GUDHI_PYTHON_EXTRA_COMPILE_ARGS "${GUDHI_PYTHON_EXTRA_COMPILE_ARGS}'-DGUDHI_USE_TBB', ") + add_GUDHI_PYTHON_lib("${TBB_LIBRARY}") + add_GUDHI_PYTHON_lib("${TBB_MALLOC_LIBRARY}") + add_GUDHI_PYTHON_lib_dir(${TBB_LIBRARY_DIRS}) + message("** Add tbb ${TBB_LIBRARY_DIRS}") + set(GUDHI_PYTHON_INCLUDE_DIRS "${GUDHI_PYTHON_INCLUDE_DIRS}'${TBB_INCLUDE_DIRS}', ") +endif() + +if(DEBUG_TRACES) + set(GUDHI_PYTHON_EXTRA_COMPILE_ARGS "${GUDHI_PYTHON_EXTRA_COMPILE_ARGS}'-DDEBUG_TRACES', ") +endif(DEBUG_TRACES) + +if(UNIX AND WITH_GUDHI_PYTHON_RUNTIME_LIBRARY_DIRS) + set( GUDHI_PYTHON_RUNTIME_LIBRARY_DIRS "${GUDHI_PYTHON_LIBRARY_DIRS}") +endif(UNIX AND WITH_GUDHI_PYTHON_RUNTIME_LIBRARY_DIRS) + +# doc/pip_introduction.inc is a restructured text file (extension changed because of sphinx warning) that describes +# the GUDHI project on https://pypi.org/project/gudhi/ +file(READ "doc/pypi_introduction.inc" GUDHI_LONG_DESCRIPTION_WITH_UNPROPER_CR) +string(REPLACE "\n" "\\n' \\\n '" GUDHI_LONG_DESCRIPTION ${GUDHI_LONG_DESCRIPTION_WITH_UNPROPER_CR}) + +# Generate setup.py file to cythonize Gudhi - This file must be named setup.py by convention +configure_file(setup.py.in "${CMAKE_CURRENT_BINARY_DIR}/setup.py" @ONLY) + +# Generate gudhi/__init__.py +file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/gudhi") +configure_file("gudhi/__init__.py.in" "${CMAKE_CURRENT_BINARY_DIR}/gudhi/__init__.py" @ONLY) + +# Other .py files +file(COPY "gudhi/persistence_graphical_tools.py" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/gudhi") +file(COPY "gudhi/representations" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/gudhi/") +file(COPY "gudhi/tensorflow" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/gudhi/") +file(COPY "gudhi/wasserstein" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/gudhi") +file(COPY "gudhi/point_cloud" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/gudhi") +file(COPY "gudhi/clustering" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/gudhi" FILES_MATCHING PATTERN "*.py") +file(COPY "gudhi/weighted_rips_complex.py" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/gudhi") +file(COPY "gudhi/dtm_rips_complex.py" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/gudhi") +file(COPY "gudhi/cover_complex.py" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/gudhi") +file(COPY "gudhi/_kepler_mapper.py" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/gudhi") +file(COPY "gudhi/_kepler_mapper.py.COPYRIGHT" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/gudhi") +file(COPY "gudhi/hera/__init__.py" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/gudhi/hera") +file(COPY "gudhi/datasets" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/gudhi" FILES_MATCHING PATTERN "*.py") +file(COPY "gudhi/sklearn" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/gudhi/") +file(COPY "gudhi/flag_filtration" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/gudhi/") + +# Some files for pip package +file(COPY "pyproject.toml" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/") + +add_custom_command( + OUTPUT gudhi.so + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + COMMAND ${Python_EXECUTABLE} "${CMAKE_CURRENT_BINARY_DIR}/setup.py" "build_ext" "--inplace") + +add_custom_target(python ALL DEPENDS gudhi.so + COMMENT "Do not forget to add ${CMAKE_CURRENT_BINARY_DIR}/ to your PYTHONPATH before using examples or tests") + +# Path separator management for windows +if (WIN32) + set(GUDHI_PYTHON_PATH_ENV "PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR};$ENV{PYTHONPATH}") +else(WIN32) + set(GUDHI_PYTHON_PATH_ENV "PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}:$ENV{PYTHONPATH}") +endif(WIN32) + +# Documentation generation is available through sphinx - requires all modules +# Make it first as sphinx test is by far the longest test which is nice when testing in parallel +if(GUDHI_PYTHON_DOCUMENTATION_MISSING_MODULES) + message("++ Python documentation will not be compilable because of the following missing modules: ${GUDHI_PYTHON_DOCUMENTATION_MISSING_MODULES}") +else() + set (GUDHI_SPHINX_MESSAGE "Generating API documentation with Sphinx in ${CMAKE_CURRENT_BINARY_DIR}/sphinx/") + # User warning - Sphinx is a static pages generator, and configured to work fine with user_version + # Images and biblio warnings because not found on developer version + if (GUDHI_PYTHON_PATH STREQUAL "src/python") + set (GUDHI_SPHINX_MESSAGE "${GUDHI_SPHINX_MESSAGE} \n WARNING : Sphinx is configured for user version, you run it on developer version. Images and biblio will miss") + endif() + # sphinx target requires gudhi.so, because conf.py reads gudhi version from it + add_custom_target(sphinx + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/doc + COMMAND ${CMAKE_COMMAND} -E env "${GUDHI_PYTHON_PATH_ENV}" + ${SPHINX_PATH} -b html ${CMAKE_CURRENT_SOURCE_DIR}/doc ${CMAKE_CURRENT_BINARY_DIR}/sphinx + DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/gudhi.so" + COMMENT "${GUDHI_SPHINX_MESSAGE}" VERBATIM) + add_test(NAME sphinx_py_test + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + COMMAND ${CMAKE_COMMAND} -E env "${GUDHI_PYTHON_PATH_ENV}" + ${SPHINX_PATH} -b doctest ${CMAKE_CURRENT_SOURCE_DIR}/doc ${CMAKE_CURRENT_BINARY_DIR}/doctest) + # Set missing or not modules + set(GUDHI_MODULES ${GUDHI_MODULES} "python-documentation" CACHE INTERNAL "GUDHI_MODULES") +endif() + +# Cubical +add_test(NAME periodic_cubical_complex_barcode_persistence_from_perseus_file_example_py_test + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + COMMAND ${CMAKE_COMMAND} -E env "${GUDHI_PYTHON_PATH_ENV}" + ${Python_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/example/periodic_cubical_complex_barcode_persistence_from_perseus_file_example.py" + --no-barcode -f ${CMAKE_SOURCE_DIR}/data/bitmap/CubicalTwoSphere.txt) + +add_test(NAME random_cubical_complex_persistence_example_py_test + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + COMMAND ${CMAKE_COMMAND} -E env "${GUDHI_PYTHON_PATH_ENV}" + ${Python_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/example/random_cubical_complex_persistence_example.py" + 10 10 10) + +add_gudhi_py_test(test_cubical_complex) + +# Datasets are fetched for these tests +if(SKLEARN_FOUND AND WITH_GUDHI_REMOTE_TEST) + add_gudhi_py_test(test_sklearn_cubical_persistence) + + add_test(NAME cubical_complex_sklearn_itf_py_test + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + COMMAND ${CMAKE_COMMAND} -E env "${GUDHI_PYTHON_PATH_ENV}" + ${Python_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/example/cubical_complex_sklearn_itf.py") +endif() + +# Test examples +if (TARGET CGAL::CGAL AND TARGET Eigen3::Eigen) + # Bottleneck and Alpha + add_test(NAME alpha_rips_persistence_bottleneck_distance_py_test + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + COMMAND ${CMAKE_COMMAND} -E env "${GUDHI_PYTHON_PATH_ENV}" + ${Python_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/example/alpha_rips_persistence_bottleneck_distance.py" + -f ${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off -t 0.15 -d 3) +endif (TARGET CGAL::CGAL AND TARGET Eigen3::Eigen) +if (TARGET CGAL::CGAL AND TARGET Eigen3::Eigen) + # Tangential + add_test(NAME tangential_complex_plain_homology_from_off_file_example_py_test + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + COMMAND ${CMAKE_COMMAND} -E env "${GUDHI_PYTHON_PATH_ENV}" + ${Python_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/example/tangential_complex_plain_homology_from_off_file_example.py" + --no-diagram -i 2 -f ${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off) + + add_gudhi_py_test(test_tangential_complex) + + # Witness complex + add_test(NAME euclidean_strong_witness_complex_diagram_persistence_from_off_file_example_py_test + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + COMMAND ${CMAKE_COMMAND} -E env "${GUDHI_PYTHON_PATH_ENV}" + ${Python_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/example/euclidean_strong_witness_complex_diagram_persistence_from_off_file_example.py" + --no-diagram -f ${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off -a 1.0 -n 20 -d 2) + + add_test(NAME euclidean_witness_complex_diagram_persistence_from_off_file_example_py_test + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + COMMAND ${CMAKE_COMMAND} -E env "${GUDHI_PYTHON_PATH_ENV}" + ${Python_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/example/euclidean_witness_complex_diagram_persistence_from_off_file_example.py" + --no-diagram -f ${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off -a 1.0 -n 20 -d 2) + +endif (TARGET CGAL::CGAL AND TARGET Eigen3::Eigen) +if (TARGET CGAL::CGAL) + # Bottleneck + add_test(NAME bottleneck_basic_example_py_test + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + COMMAND ${CMAKE_COMMAND} -E env "${GUDHI_PYTHON_PATH_ENV}" + ${Python_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/example/bottleneck_basic_example.py") + + add_gudhi_py_test(test_bottleneck_distance) +endif (TARGET CGAL::CGAL) + +# Cover complex +file(COPY ${CMAKE_SOURCE_DIR}/data/points/human.off DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/) +file(COPY ${CMAKE_SOURCE_DIR}/data/points/COIL_database/lucky_cat.off DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/) +file(COPY ${CMAKE_SOURCE_DIR}/data/points/COIL_database/lucky_cat_PCA1 DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/) +add_test(NAME cover_complex_nerve_example_py_test + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + COMMAND ${CMAKE_COMMAND} -E env "${GUDHI_PYTHON_PATH_ENV}" + ${Python_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/example/nerve_of_a_covering.py" + -f human.off -c 2 -r 10 -g 0.3) + +add_test(NAME cover_complex_coordinate_gic_example_py_test + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + COMMAND ${CMAKE_COMMAND} -E env "${GUDHI_PYTHON_PATH_ENV}" + ${Python_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/example/coordinate_graph_induced_complex.py" + -f human.off -c 0 -v) + +add_test(NAME cover_complex_functional_gic_example_py_test + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + COMMAND ${CMAKE_COMMAND} -E env "${GUDHI_PYTHON_PATH_ENV}" + ${Python_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/example/functional_graph_induced_complex.py" + -o lucky_cat.off + -f lucky_cat_PCA1 -v) + +add_test(NAME cover_complex_voronoi_gic_example_py_test + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + COMMAND ${CMAKE_COMMAND} -E env "${GUDHI_PYTHON_PATH_ENV}" + ${Python_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/example/voronoi_graph_induced_complex.py" + -f human.off -n 700 -v) + +if (TARGET CGAL::CGAL AND TARGET Eigen3::Eigen) + # Alpha + add_test(NAME alpha_complex_from_points_example_py_test + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + COMMAND ${CMAKE_COMMAND} -E env "${GUDHI_PYTHON_PATH_ENV}" + ${Python_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/example/alpha_complex_from_points_example.py") + add_test(NAME alpha_complex_from_generated_points_on_sphere_example_py_test + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + COMMAND ${CMAKE_COMMAND} -E env "${GUDHI_PYTHON_PATH_ENV}" + ${Python_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/example/alpha_complex_from_generated_points_on_sphere_example.py") + add_test(NAME alpha_complex_diagram_persistence_from_off_file_example_py_test + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + COMMAND ${CMAKE_COMMAND} -E env "${GUDHI_PYTHON_PATH_ENV}" + ${Python_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/example/alpha_complex_diagram_persistence_from_off_file_example.py" + --no-diagram -f ${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off) + add_gudhi_py_test(test_alpha_complex) + add_gudhi_py_test(test_delaunay_complex) +endif (TARGET CGAL::CGAL AND TARGET Eigen3::Eigen) + +if (TARGET CGAL::CGAL AND TARGET Eigen3::Eigen) + # Euclidean witness + add_gudhi_py_test(test_euclidean_witness_complex) + + # Datasets generators + add_gudhi_py_test(test_datasets_generators) # TODO separate full python datasets generators in another test file independent from CGAL ? + +endif (TARGET CGAL::CGAL AND TARGET Eigen3::Eigen) + +# Rips +add_test(NAME rips_complex_diagram_persistence_from_distance_matrix_file_example_py_test + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + COMMAND ${CMAKE_COMMAND} -E env "${GUDHI_PYTHON_PATH_ENV}" + ${Python_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/example/rips_complex_diagram_persistence_from_distance_matrix_file_example.py" + --no-diagram -f ${CMAKE_SOURCE_DIR}/data/distance_matrix/lower_triangular_distance_matrix.csv -s , -e 12.0 -d 3) + +add_test(NAME rips_complex_diagram_persistence_from_off_file_example_py_test + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + COMMAND ${CMAKE_COMMAND} -E env "${GUDHI_PYTHON_PATH_ENV}" + ${Python_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/example/rips_complex_diagram_persistence_from_off_file_example.py + --no-diagram -f ${CMAKE_SOURCE_DIR}/data/points/tore3D_300.off -e 0.25 -d 3) + +add_test(NAME rips_complex_from_points_example_py_test + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + COMMAND ${CMAKE_COMMAND} -E env "${GUDHI_PYTHON_PATH_ENV}" + ${Python_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/example/rips_complex_from_points_example.py) + +add_gudhi_py_test(test_rips_complex) + +if(SKLEARN_FOUND) + # test_sklearn_rips_persistence is using gudhi.datasets.generators + if (TARGET CGAL::CGAL AND TARGET Eigen3::Eigen) + add_gudhi_py_test(test_sklearn_rips_persistence) + endif() - # Witness - add_test(NAME witness_complex_from_nearest_landmark_table_py_test + # Datasets are fetched for these tests + if(WITH_GUDHI_REMOTE_TEST) + add_test(NAME rips_complex_sklearn_itf_py_test WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} COMMAND ${CMAKE_COMMAND} -E env "${GUDHI_PYTHON_PATH_ENV}" - ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/example/witness_complex_from_nearest_landmark_table.py) - - add_gudhi_py_test(test_witness_complex) - - # Reader utils - add_gudhi_py_test(test_reader_utils) - add_gudhi_py_test(test_off) - - # Wasserstein - if(OT_FOUND) - # EagerPy dependency because of enable_autodiff=True - if(EAGERPY_FOUND) - add_gudhi_py_test(test_wasserstein_distance) - endif() - - add_gudhi_py_test(test_wasserstein_barycenter) - - if(TORCH_FOUND AND TENSORFLOW_FOUND AND EAGERPY_FOUND) - add_gudhi_py_test(test_wasserstein_with_tensors) - endif() - endif() - - # Representations - if(SKLEARN_FOUND AND MATPLOTLIB_FOUND AND OT_FOUND AND TARGET CGAL::CGAL) - add_gudhi_py_test(test_representations) - endif() - - # Differentiation - if(TENSORFLOW_FOUND) - add_gudhi_py_test(test_diff) - endif() - - # Perslay - if(TENSORFLOW_FOUND AND SKLEARN_FOUND) - add_gudhi_py_test(test_perslay) - endif() - - # Betti curves - if(SKLEARN_FOUND AND SCIPY_FOUND) - add_gudhi_py_test(test_betti_curve_representations) - endif() - - # Representations preprocessing - if(SKLEARN_FOUND) - add_gudhi_py_test(test_representations_preprocessing) - endif() - - # Time Delay - add_gudhi_py_test(test_time_delay) - - # DTM - if(SCIPY_FOUND AND SKLEARN_FOUND AND TORCH_FOUND AND HNSWLIB_FOUND AND PYKEOPS_FOUND AND EAGERPY_FOUND) - add_gudhi_py_test(test_knn) - add_gudhi_py_test(test_dtm) - endif() - - # Tomato - if(SCIPY_FOUND AND SKLEARN_FOUND) - add_gudhi_py_test(test_tomato) - endif() - - # Weighted Rips - if(SCIPY_FOUND) - add_gudhi_py_test(test_weighted_rips_complex) - endif() - - # DTM Rips - if(SCIPY_FOUND) - add_gudhi_py_test(test_dtm_rips_complex) - endif() - - # Cover complex - if(SKLEARN_FOUND) - add_gudhi_py_test(test_cover_complex) - endif() - - # Fetch remote datasets - if(WITH_GUDHI_REMOTE_TEST) - add_gudhi_py_test(test_remote_datasets) - endif() - - # persistence graphical tools - if(MATPLOTLIB_FOUND) - add_gudhi_py_test(test_persistence_graphical_tools) - endif() - - # Set missing or not modules - set(GUDHI_MODULES ${GUDHI_MODULES} "python" CACHE INTERNAL "GUDHI_MODULES") - else(NUMPY_FOUND AND PYBIND11_FOUND AND CYTHON_FOUND) - message("++ Python module will not be compiled because numpy and/or cython and/or pybind11 was/were not found") - set(GUDHI_MISSING_MODULES ${GUDHI_MISSING_MODULES} "python" CACHE INTERNAL "GUDHI_MISSING_MODULES") - endif(NUMPY_FOUND AND PYBIND11_FOUND AND CYTHON_FOUND) -else(PYTHONINTERP_FOUND) - message("++ Python module will not be compiled because no Python interpreter was found") - set(GUDHI_MISSING_MODULES ${GUDHI_MISSING_MODULES} "python" CACHE INTERNAL "GUDHI_MISSING_MODULES") -endif(PYTHONINTERP_FOUND) + ${Python_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/example/rips_complex_sklearn_itf.py" "--no-plot") + endif() +endif() + +# Simplex tree +add_test(NAME simplex_tree_example_py_test + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + COMMAND ${CMAKE_COMMAND} -E env "${GUDHI_PYTHON_PATH_ENV}" + ${Python_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/example/simplex_tree_example.py) + +add_gudhi_py_test(test_simplex_tree) +add_gudhi_py_test(test_simplex_generators) +add_gudhi_py_test(test_simplex_tree_serialization) + +# Edge collapse +if(SCIPY_FOUND) + add_gudhi_py_test(test_collapse_edges) +endif() + +# Subsampling +add_gudhi_py_test(test_subsampling) + +# Witness +add_test(NAME witness_complex_from_nearest_landmark_table_py_test + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + COMMAND ${CMAKE_COMMAND} -E env "${GUDHI_PYTHON_PATH_ENV}" + ${Python_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/example/witness_complex_from_nearest_landmark_table.py) + +add_gudhi_py_test(test_witness_complex) + +# Reader utils +add_gudhi_py_test(test_reader_utils) +add_gudhi_py_test(test_off) + +# Wasserstein +if(OT_FOUND) + # EagerPy dependency because of enable_autodiff=True + if(EAGERPY_FOUND) + add_gudhi_py_test(test_wasserstein_distance) + endif() + add_gudhi_py_test(test_wasserstein_barycenter) + if(TORCH_FOUND AND TENSORFLOW_FOUND AND EAGERPY_FOUND) + add_gudhi_py_test(test_wasserstein_with_tensors) + endif() +endif() + +# Representations +if(SKLEARN_FOUND AND MATPLOTLIB_FOUND AND OT_FOUND AND TARGET CGAL::CGAL) + add_gudhi_py_test(test_representations) +endif() + +# Differentiation +if(TENSORFLOW_FOUND) + add_gudhi_py_test(test_diff) +endif() + +# Perslay +if(TENSORFLOW_FOUND AND SKLEARN_FOUND) + add_gudhi_py_test(test_perslay) +endif() + +# Betti curves +if(SKLEARN_FOUND AND SCIPY_FOUND) + add_gudhi_py_test(test_betti_curve_representations) +endif() + +# Representations preprocessing +if(SKLEARN_FOUND) + add_gudhi_py_test(test_representations_preprocessing) +endif() + +# Time Delay +add_gudhi_py_test(test_time_delay) + +# DTM +if(SCIPY_FOUND AND SKLEARN_FOUND AND TORCH_FOUND AND HNSWLIB_FOUND AND PYKEOPS_FOUND AND EAGERPY_FOUND) + add_gudhi_py_test(test_knn) + add_gudhi_py_test(test_dtm) +endif() + +# Tomato +if(SCIPY_FOUND AND SKLEARN_FOUND) + add_gudhi_py_test(test_tomato) +endif() + +# Weighted Rips +if(SCIPY_FOUND) + add_gudhi_py_test(test_weighted_rips_complex) +endif() + +# DTM Rips +if(SCIPY_FOUND) + add_gudhi_py_test(test_dtm_rips_complex) +endif() + +# Cover complex +if(SKLEARN_FOUND) + add_gudhi_py_test(test_cover_complex) +endif() + +# Fetch remote datasets +if(WITH_GUDHI_REMOTE_TEST) + add_gudhi_py_test(test_remote_datasets) +endif() + +# persistence graphical tools +if(MATPLOTLIB_FOUND) + add_gudhi_py_test(test_persistence_graphical_tools) +endif() + +# Set missing or not modules +set(GUDHI_MODULES ${GUDHI_MODULES} "python" CACHE INTERNAL "GUDHI_MODULES") \ No newline at end of file diff --git a/src/python/doc/installation.rst b/src/python/doc/installation.rst index e1b7680b58..639a89d652 100644 --- a/src/python/doc/installation.rst +++ b/src/python/doc/installation.rst @@ -40,13 +40,13 @@ different, and in particular the `python/` subdirectory is actually `src/python/ there. The library uses c++17 and requires `Boost `_ :math:`\geq` 1.71.0, -`CMake `_ :math:`\geq` 3.8, +`CMake `_ :math:`\geq` 3.15, Python :math:`\geq` 3.5, `NumPy `_ :math:`\geq` 1.15.0, `Cython `_ :math:`\geq` 0.27 and `pybind11 `_ to compile the GUDHI Python module. It is a multi-platform library and compiles on Linux, Mac OSX and Visual Studio 2017 or later. -If you have several Python/python installed, the version 2.X may be used by default, but you can force it by adding -:code:`-DPython_ADDITIONAL_VERSIONS=3` to the cmake command. +If you have several Python/python installed, you can force it by adding +:code:`-DPython_EXECUTABLE=/custom/path/to/python3` to the cmake command (requires CMake :math:`\geq` 3.16). GUDHI Python module compilation ===============================