diff --git a/.github/workflows/build_python.yml b/.github/workflows/build_python.yml index be28171..5b4e74f 100644 --- a/.github/workflows/build_python.yml +++ b/.github/workflows/build_python.yml @@ -23,28 +23,26 @@ jobs: build_and_test: strategy: matrix: - os: [ubuntu-latest, windows-latest, macos-13, macos-14] + os: [ubuntu-latest, windows-latest, macos-14, macos-15-intel] name: Build and test, ${{ matrix.os }} runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v4 - - uses: actions/setup-python@v5 - uses: mamba-org/setup-micromamba@v1 with: cache-downloads: true - name: Build wheels run: | - $MAMBA_EXE create -n cibuildwheel python=3.12 + $MAMBA_EXE create -n cibuildwheel python=3.12 eigen pybind11 eval "$($MAMBA_EXE shell activate cibuildwheel)" python -m pip install cibuildwheel - if [[ $OSTYPE == "darwin23" ]] || [[ $OSTYPE == "darwin22" ]] + if [[ $OSTYPE == "linux-gnu" ]] then - # For some reason cibuildwheel on builds 3.9-3.12 arm64 on macos-latest - export CIBW_BUILD="cp39* cp310* cp311* cp312*" + export CIBW_ENVIRONMENT="CONDA_PREFIX=/host/$CONDA_PREFIX" fi python -m cibuildwheel --output-dir wheelhouse env: - CIBW_BUILD: "cp38-* cp39* cp310-* cp311-* cp312-*" + CIBW_BUILD: "cp310-* cp311-* cp312-* cp313-* cp314-*" CIBW_SKIP: "*musllinux* *win32* *i686*" CIBW_ARCHS_MACOS: "native" CIBW_BUILD_VERBOSITY: 1 @@ -52,13 +50,7 @@ jobs: run: | # set -e makes sure the script fails if any command in the loop fails set -e - if [[ $OSTYPE == "darwin23" ]] || [[ $OSTYPE == "darwin22" ]] - then - export PYVERS="3.9 3.10 3.11 3.12" - else - export PYVERS="3.8 3.9 3.10 3.11 3.12" - fi - for pyver in $PYVERS + for pyver in 3.10 3.11 3.12 3.13 3.14 do $MAMBA_EXE create -n py$pyver -c conda-forge python=$pyver numpy eval "$($MAMBA_EXE shell activate py$pyver)" @@ -67,6 +59,11 @@ jobs: python -m unittest cd .. done + - name: Build Pyodide wheel + if: matrix.os == 'ubuntu-latest' + run: | + eval "$($MAMBA_EXE shell activate cibuildwheel)" + CIBW_BUILD="cp312*" python -m cibuildwheel --output-dir wheelhouse --platform pyodide - name: Upload release wheels if: | contains(github.event.pull_request.title, 'RELEASE') && diff --git a/.gitignore b/.gitignore index 10fc3c4..c899876 100644 --- a/.gitignore +++ b/.gitignore @@ -2,8 +2,15 @@ *.swo *.o *.exe +*.whl __pycache__ +.pyodide-xbuildenv build dist libMcPhase.egg-info +libmcphase.egg-info +emsdk +Emscripten.cmake + +libmcphase/*pyd diff --git a/CMakeLists.txt b/CMakeLists.txt index eafcb81..26b2226 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,6 +5,7 @@ set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake) set(CMAKE_MACOSX_RPATH TRUE) set(CMAKE_CXX_STANDARD 11) set(CXX_STANDARD_REQUIRED 11) +cmake_policy(SET CMP0148 OLD) # New policy gives error when cannot find shared libs set(LIBMCPHASE_PYTHON_MODULE libmcphase) @@ -18,11 +19,26 @@ if(WIN32) set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -d2:-FH4-") endif(WIN32) -include(Eigen) -include_directories(${EIGEN3_INCLUDE_DIR}) +if (DEFINED ENV{CONDA_PREFIX}) + message(STATUS "Searching $ENV{CONDA_PREFIX} for Pybind11 and Eigen") + file(GLOB pybind11_search $ENV{CONDA_PREFIX}/share/cmake/pybind11/pybind11Config.cmake) + if (NOT pybind11_search STREQUAL "") + cmake_path(GET pybind11_search PARENT_PATH pybind11_DIR) + endif() + file(GLOB eigen_search $ENV{CONDA_PREFIX}/share/eigen3/cmake/Eigen3Config.cmake) + if (NOT eigen_search STREQUAL "") + cmake_path(GET eigen_search PARENT_PATH Eigen3_DIR) + endif() +endif() + +if (EMSCRIPTEN) + message(STATUS "Emscripten detected - setting Pybind to use cross-compiler") + set(PYBIND11_USE_CROSSCOMPILING TRUE) +endif() -include(PyBind11) -add_subdirectory(${PyBind11_DIR}) +find_package(Eigen3 REQUIRED NO_MODULE) +include_directories(${EIGEN3_INCLUDE_DIR}) +find_package(pybind11 CONFIG) add_subdirectory(src) diff --git a/cmake/Eigen.cmake b/cmake/Eigen.cmake deleted file mode 100644 index 129c26a..0000000 --- a/cmake/Eigen.cmake +++ /dev/null @@ -1,18 +0,0 @@ -include(ExternalProject) - -option(USE_SYSTEM_EIGEN "Use the system installed Eigen" OFF) - -if(USE_SYSTEM_EIGEN) - message(STATUS "Using system Eigen") - find_package(Eigen3 REQUIRED) -else() - message(STATUS "Using Eigen in ExternalProject") - - # Download and unpack Eigen at configure time - configure_file(${CMAKE_SOURCE_DIR}/cmake/Eigen.in ${CMAKE_BINARY_DIR}/extern-eigen/CMakeLists.txt) - - execute_process(COMMAND ${CMAKE_COMMAND} -G "${CMAKE_GENERATOR}" . WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/extern-eigen ) - execute_process(COMMAND ${CMAKE_COMMAND} --build . WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/extern-eigen ) - - set(EIGEN3_INCLUDE_DIR "${CMAKE_CURRENT_BINARY_DIR}/extern-eigen/source") -endif() diff --git a/cmake/Eigen.in b/cmake/Eigen.in deleted file mode 100644 index b54ae42..0000000 --- a/cmake/Eigen.in +++ /dev/null @@ -1,18 +0,0 @@ -cmake_minimum_required ( VERSION 3.1 ) -project(libMcPhase_Eigen) -include( ExternalProject ) - -ExternalProject_Add(eigen - URL https://gitlab.com/libeigen/eigen/-/archive/3.4.0/eigen-3.4.0.tar.gz - DOWNLOAD_DIR ${CMAKE_CURRENT_BINARY_DIR}/extern-eigen/download - SOURCE_DIR ${CMAKE_CURRENT_BINARY_DIR}/extern-eigen/source - INSTALL_DIR ${CMAKE_CURRENT_BINARY_DIR}/extern-eigen/install - CMAKE_CACHE_ARGS - -DCMAKE_BUILD_TYPE:STRING=Release - -DCMAKE_VERBOSE_MAKEFILE:BOOL=OFF - -DCMAKE_INSTALL_PREFIX:STRING=${CMAKE_CURRENT_BINARY_DIR}/extern-eigen/install - CONFIGURE_COMMAND "" - BUILD_COMMAND "" - INSTALL_COMMAND "" - TEST_COMMAND "" -) diff --git a/cmake/PyBind11.cmake b/cmake/PyBind11.cmake deleted file mode 100644 index dcf97ce..0000000 --- a/cmake/PyBind11.cmake +++ /dev/null @@ -1,19 +0,0 @@ -include(ExternalProject) - -if(USE_SYSTEM_PYBIND11) - message(STATUS "Using system Pybind11") -else() - message(STATUS "Using Pybind11 in ExternalProject") - - # Download and unpack Pybind11 at configure time - configure_file(${CMAKE_SOURCE_DIR}/cmake/PyBind11.in ${CMAKE_BINARY_DIR}/extern-pybind11/CMakeLists.txt) - - # The OLD behavior for this policy is to ignore the visibility properties - # for static libraries, object libraries, and executables without exports. - cmake_policy(SET CMP0063 "OLD") - - execute_process(COMMAND ${CMAKE_COMMAND} -G "${CMAKE_GENERATOR}" . WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/extern-pybind11 ) - execute_process(COMMAND ${CMAKE_COMMAND} --build . WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/extern-pybind11 ) - - set(PyBind11_DIR "${CMAKE_BINARY_DIR}/extern-pybind11/pybind11-prefix/src/pybind11/" CACHE PATH "") -endif() diff --git a/cmake/PyBind11.in b/cmake/PyBind11.in deleted file mode 100644 index 20e4bb7..0000000 --- a/cmake/PyBind11.in +++ /dev/null @@ -1,12 +0,0 @@ -cmake_minimum_required ( VERSION 3.1 ) -project(libMcPhase_Pybind11) -include( ExternalProject ) - -ExternalProject_Add(pybind11 - GIT_REPOSITORY https://github.com/pybind/pybind11.git - GIT_TAG v2.11.1 - CONFIGURE_COMMAND "" - BUILD_COMMAND "" - INSTALL_COMMAND "" -) - diff --git a/setup.py b/setup.py index 9abbd67..9e7f38f 100644 --- a/setup.py +++ b/setup.py @@ -2,7 +2,7 @@ import re import sys import subprocess -import pkgutil +import importlib.util from sysconfig import get_platform from subprocess import CalledProcessError, check_output, check_call from distutils.version import LooseVersion @@ -14,7 +14,7 @@ # Except that in the manylinux builds it's placed at /opt/python/[version]/bin/ # (as a symlink at least) which is *not* on the path. # If cmake is a known module, import it and use it tell us its binary directory -if pkgutil.find_loader('cmake') is not None: +if (cmakemod := importlib.util.find_spec('cmake')) and cmakemod.loader: import cmake CMAKE_BIN = cmake.CMAKE_BIN_DIR + os.path.sep + 'cmake' else: @@ -124,10 +124,10 @@ def build_extension(self, ext): cmdclass=cmdclass, url="https://github.com/mducle/libmcphase", zip_safe=False, + license="GPL-3.0-or-later", classifiers=[ "Development Status :: 2 - Pre-Alpha", "Intended Audience :: Science/Research", - "License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)", "Operating System :: Microsoft :: Windows :: Windows 10", "Operating System :: POSIX :: Linux", "Programming Language :: C++",