From c8e23782339a1590319ef017c0da23540022359c Mon Sep 17 00:00:00 2001 From: Ryan Burns Date: Thu, 20 Jun 2024 14:15:59 -0700 Subject: [PATCH 1/8] Remove numpy.distutils usage from setuptools build As setuptools cannot natively call f2py, we call it ourselves by using a custom build extension. --- setup.py | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/setup.py b/setup.py index fe0a858..0f1c74b 100644 --- a/setup.py +++ b/setup.py @@ -3,13 +3,39 @@ # always prefer setuptools over distutils import setuptools -from numpy.distutils.core import setup, Extension +from setuptools import setup, Extension +from setuptools.command.build_ext import build_ext +from numpy import f2py +import os +import subprocess +import sys # read the contents of README file def readme(): with open("README.md") as f: return f.read() +class f2py_build(build_ext): + def run(self): + for ext in self.extensions: + self.build_extension(ext) + + def build_extension(self, ext): + # Reuse setuptools build_ext logic for output location and name + build_dir, fname = os.path.split(super().get_ext_fullpath(ext.name)) + module = fname.split(".")[0] + + # Compile a Fortran module using f2py + c = [sys.executable, "-m", "numpy.f2py", "-c"] + # Specify module name and source file paths + c += ["-m", module] + [os.path.abspath(x) for x in ext.sources] + # Use meson backend (enforces python 3.12+ behavior, not needed) + #c += ["--backend", "meson"] + + # No way to specify the output location, + # so we have to run with CWD as the destination directory + subprocess.run(c, cwd=build_dir) + setup( ## add the following redundant setup for setuptools<60, the latter is required for numpy.distutils name="pysolid", @@ -58,4 +84,6 @@ def readme(): ext_modules=[ Extension(name="pysolid.solid", sources=["src/pysolid/solid.for"]) ], + + cmdclass=dict(build_ext=f2py_build), ) From 464da9a5fd9e75cef5927cb2b9a0ba0f561768de Mon Sep 17 00:00:00 2001 From: Zhang Yunjun Date: Fri, 21 Jun 2024 10:16:52 +0800 Subject: [PATCH 2/8] circleci: update docker image to cimg/base as a attempt to fix the spin up environment error below: Error response from daemon: Head "https://registry-1.docker.io/v2/library/ubuntu/manifests/bionic": received unexpected HTTP status: 503 Service Unavailable --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 4ca5a14..e8ae932 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -23,7 +23,7 @@ jobs: # The executor is the environment in which the steps below will be executed - below will use a python 3.9 container # Change the version below to your required version of python docker: - - image: ubuntu:bionic + - image: cimg/base:current environment: CONDA_PREFIX: /root/tools/miniforge PYSOLID_HOME: /root/tools/PySolid From 31cd0d53bdb146a4ae50e7e08f17ef529503498b Mon Sep 17 00:00:00 2001 From: Zhang Yunjun Date: Fri, 21 Jun 2024 10:29:02 +0800 Subject: [PATCH 3/8] replace np.NaN with np.nan as `np.NaN` was removed in the NumPy 2.0 release. --- src/pysolid/point.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pysolid/point.py b/src/pysolid/point.py index 9486d61..77b4df8 100644 --- a/src/pysolid/point.py +++ b/src/pysolid/point.py @@ -62,7 +62,7 @@ Tag('Shallow water terdiurnal' , r'$MK_3$' , 8.177140247, 44.0251729, 365.555, 8 ), Tag('Shallow water overtides of principal solar', r'$S_4$' , 6.0 , 60.0 , 491.555, 9 ), Tag('Shallow water quarter diurnal' , r'$MN_4$' , 6.269173724, 57.4238337, 445.655, 10), - Tag('Shallow water overtides of principal solar', r'$S_6$' , 4.0 , 90.0 , np.NaN , 12), + Tag('Shallow water overtides of principal solar', r'$S_6$' , 4.0 , 90.0 , np.nan , 12), Tag('Lunar terdiurnal' , r'$M_3$' , 8.280400802, 43.4761563, 355.555, 32), Tag('Shallow water terdiurnal' , '2"MK'+r'$_3$', 8.38630265 , 42.9271398, 345.555, 34), Tag('Shallow water eighth diurnal' , r'$M_8$' , 3.105150301, 115.9364166, 855.555, 36), From 65ded8ac623445b17bf29ede0c0fb22950c30744 Mon Sep 17 00:00:00 2001 From: Zhang Yunjun Date: Fri, 21 Jun 2024 15:45:55 +0800 Subject: [PATCH 4/8] pyproject.toml: unpin setuptools/numpy versions --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 19637c7..7814bdb 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,5 +1,5 @@ [build-system] -requires = ["setuptools<60.0", "setuptools_scm[toml]>=6.2", "numpy<1.23.0", "wheel"] +requires = ["setuptools", "setuptools_scm[toml]>=6.2", "numpy", "wheel"] build-backend = "setuptools.build_meta" [project] From 7ab60af00233d5402ca30ea4dc1d2318f8f1077a Mon Sep 17 00:00:00 2001 From: Ryan Burns Date: Sat, 22 Jun 2024 02:03:09 +0000 Subject: [PATCH 5/8] Convert build system to scikit-build-core --- .gitignore | 3 +++ CMakeLists.txt | 37 +++++++++++++++++++++++++++++++++++++ pyproject.toml | 7 +++++-- setup.py | 32 +------------------------------- 4 files changed, 46 insertions(+), 33 deletions(-) create mode 100644 CMakeLists.txt diff --git a/.gitignore b/.gitignore index 4d545e6..a97b3e2 100644 --- a/.gitignore +++ b/.gitignore @@ -131,3 +131,6 @@ dmypy.json # Pyre type checker .pyre/ + +# Scikit-build temp directory +/_skbuild/ diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..380a41f --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,37 @@ +# Based on: +# https://github.com/scikit-build/scikit-build-core/tree/main/docs/examples/getting_started/fortran + +cmake_minimum_required(VERSION 3.17.2...3.29) +project(${SKBUILD_PROJECT_NAME} LANGUAGES C Fortran) + +find_package( + Python + COMPONENTS Interpreter Development.Module NumPy + REQUIRED) + +# F2PY headers +execute_process( + COMMAND "${PYTHON_EXECUTABLE}" -c + "import numpy.f2py; print(numpy.f2py.get_include())" + OUTPUT_VARIABLE F2PY_INCLUDE_DIR + OUTPUT_STRIP_TRAILING_WHITESPACE) + +add_library(fortranobject OBJECT "${F2PY_INCLUDE_DIR}/fortranobject.c") +target_link_libraries(fortranobject PUBLIC Python::NumPy) +target_include_directories(fortranobject PUBLIC "${F2PY_INCLUDE_DIR}") +set_property(TARGET fortranobject PROPERTY POSITION_INDEPENDENT_CODE ON) + +add_custom_command( + OUTPUT solidmodule.c solid-f2pywrappers.f + DEPENDS src/pysolid/solid.for + VERBATIM + COMMAND "${Python_EXECUTABLE}" -m numpy.f2py + "${CMAKE_CURRENT_SOURCE_DIR}/src/pysolid/solid.for" -m solid --lower) + +python_add_library( + solid MODULE "${CMAKE_CURRENT_BINARY_DIR}/solidmodule.c" + "${CMAKE_CURRENT_BINARY_DIR}/solid-f2pywrappers.f" + "${CMAKE_CURRENT_SOURCE_DIR}/src/pysolid/solid.for" WITH_SOABI) +target_link_libraries(solid PRIVATE fortranobject) + +install(TARGETS solid DESTINATION pysolid) diff --git a/pyproject.toml b/pyproject.toml index 7814bdb..0c28680 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [build-system] -requires = ["setuptools", "setuptools_scm[toml]>=6.2", "numpy", "wheel"] -build-backend = "setuptools.build_meta" +requires = ["cmake", "scikit-build-core", "setuptools", "setuptools_scm[toml]>=6.2", "numpy", "wheel"] +build-backend = "scikit_build_core.build" [project] name = "pysolid" @@ -54,3 +54,6 @@ pysolid = ["*.for"] [tool.setuptools_scm] version_scheme = "post-release" local_scheme = "no-local-version" + +[tool.scikit-build] +metadata.version.provider = "scikit_build_core.metadata.setuptools_scm" diff --git a/setup.py b/setup.py index 0f1c74b..8b3dcb3 100644 --- a/setup.py +++ b/setup.py @@ -3,9 +3,7 @@ # always prefer setuptools over distutils import setuptools -from setuptools import setup, Extension -from setuptools.command.build_ext import build_ext -from numpy import f2py +from skbuild import setup import os import subprocess import sys @@ -15,27 +13,6 @@ def readme(): with open("README.md") as f: return f.read() -class f2py_build(build_ext): - def run(self): - for ext in self.extensions: - self.build_extension(ext) - - def build_extension(self, ext): - # Reuse setuptools build_ext logic for output location and name - build_dir, fname = os.path.split(super().get_ext_fullpath(ext.name)) - module = fname.split(".")[0] - - # Compile a Fortran module using f2py - c = [sys.executable, "-m", "numpy.f2py", "-c"] - # Specify module name and source file paths - c += ["-m", module] + [os.path.abspath(x) for x in ext.sources] - # Use meson backend (enforces python 3.12+ behavior, not needed) - #c += ["--backend", "meson"] - - # No way to specify the output location, - # so we have to run with CWD as the destination directory - subprocess.run(c, cwd=build_dir) - setup( ## add the following redundant setup for setuptools<60, the latter is required for numpy.distutils name="pysolid", @@ -79,11 +56,4 @@ def build_extension(self, ext): package_data={ "pysolid": ["solid.for"], }, - - ## fortran extensions to build with numpy.f2py - ext_modules=[ - Extension(name="pysolid.solid", sources=["src/pysolid/solid.for"]) - ], - - cmdclass=dict(build_ext=f2py_build), ) From 04de0e30f1419ddb667317a22e8949ed8c98d9fe Mon Sep 17 00:00:00 2001 From: Ryan Burns Date: Sat, 22 Jun 2024 02:28:22 +0000 Subject: [PATCH 6/8] Remove unused imports --- setup.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/setup.py b/setup.py index 8b3dcb3..950ba53 100644 --- a/setup.py +++ b/setup.py @@ -4,9 +4,6 @@ # always prefer setuptools over distutils import setuptools from skbuild import setup -import os -import subprocess -import sys # read the contents of README file def readme(): From 09cb81f96d798ba0eabb0ea4a7e7534343966aff Mon Sep 17 00:00:00 2001 From: Zhang Yunjun Date: Sat, 22 Jun 2024 12:56:53 +0800 Subject: [PATCH 7/8] README: rm SETUPTOOLS_ENABLE_FEATURES as it's not needed anymore --- README.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/README.md b/README.md index 1545ea6..3f12142 100644 --- a/README.md +++ b/README.md @@ -59,8 +59,6 @@ python -m pip install -r PySolid/requirements.txt -r PySolid/tests/requirements. python -m pip install PySolid # option 2: use pip to install pysolid in develop mode (editable) into the current environment -# setting an environmental variable as below is required for editable installs via pyproject.toml -export SETUPTOOLS_ENABLE_FEATURES="legacy-editable" python -m pip install -e PySolid # option 3: manually compile the Fortran code and setup environment variable From 0574583436fa8034c51ff85e8878cc835b944d40 Mon Sep 17 00:00:00 2001 From: Zhang Yunjun Date: Sat, 22 Jun 2024 20:58:40 +0800 Subject: [PATCH 8/8] add meson to tests/requirements.txt --- tests/requirements.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/requirements.txt b/tests/requirements.txt index 9277b34..7561558 100644 --- a/tests/requirements.txt +++ b/tests/requirements.txt @@ -1,5 +1,6 @@ # for packaging and installation #fortran-compiler # Fortran compiler across platforms through conda-forge channel +meson pip setuptools_scm>=6.2 # for testing