add python packaging fluff

This commit is contained in:
Arne Morten Kvarving 2024-08-23 13:03:48 +02:00
parent 1a6b063824
commit 0203f74b3f
10 changed files with 258 additions and 0 deletions

18
python/Dockerfile Normal file
View File

@ -0,0 +1,18 @@
# Dockerfile to generate PyPI packages. Needs to be run from the opm-common root folder
# Example use:
# sudo docker build -t manylinux2014_opm:built . -f python/Dockerfile
FROM quay.io/pypa/manylinux_2_28_x86_64 AS stage1
ARG version_tag=""
ARG build_jobs=4
WORKDIR /tmp/opm
RUN echo "Using package version tag: $version_tag"
ADD . .
RUN /bin/bash setup-docker-image.sh
FROM stage1 AS stage2
RUN /bin/bash build-deps.sh $build_jobs
FROM stage2 AS stage3
RUN /bin/bash generate-pypi-package.sh $version_tag $build_jobs
FROM scratch AS export_stage
COPY --from=stage3 /tmp/opm/wheelhouse .

2
python/MANIFEST.in Normal file
View File

@ -0,0 +1,2 @@
include opm/simulators/__init__.py
include opm/simulators/*.so

83
python/build-deps.sh Executable file
View File

@ -0,0 +1,83 @@
#!/bin/bash
set -e
BUILD_JOBS=$1
export CMAKE_GENERATOR=Ninja
pushd /tmp/opm
# Build boost
git clone --depth 1 --branch boost-1.84.0 https://github.com/boostorg/boost
pushd boost
git submodule init
git submodule update
mkdir build
cd build
cmake .. -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=0 -DCMAKE_POSITION_INDEPENDENT_CODE=1
cmake --build . -- -j${BUILD_JOBS}
cmake --build . --target install
popd
# Build dune-common
git clone --depth 1 --branch releases/opm/2024.04 https://gitlab.dune-project.org/core/dune-common.git
pushd dune-common
mkdir build
cd build
cmake .. -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=0 -DCMAKE_POSITION_INDEPENDENT_CODE=1 -DDUNE_ENABLE_PYTHONBINDINGS=0 -DBLA_STATIC=1 -DCMAKE_DISABLE_FIND_PACKAGE_QuadMath=1 -DBLAS_LIBRARIES=/usr/lib64/libblas.a -DLAPACK_LIBRARIES=/usr/lib64/liblapack.a
cmake --build . -- -j${BUILD_JOBS}
cmake --build . --target install
popd
# Build dune-geometry
git clone --depth 1 --branch v2.9.1 https://gitlab.dune-project.org/core/dune-geometry.git
pushd dune-geometry
mkdir build
cd build
cmake .. -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=0 -DCMAKE_POSITION_INDEPENDENT_CODE=1 -DDUNE_ENABLE_PYTHONBINDINGS=0 -DBLA_STATIC=1 -DCMAKE_DISABLE_FIND_PACKAGE_QuadMath=1 -DBLAS_LIBRARIES=/usr/lib64/libblas.a -DLAPACK_LIBRARIES=/usr/lib64/liblapack.a
cmake --build . -- -j${BUILD_JOBS}
cmake --build . --target install
popd
# Build dune-istl
git clone --depth 1 --branch releases/opm/2024.04 https://gitlab.dune-project.org/core/dune-istl.git
pushd dune-istl
mkdir build
cd build
cmake .. -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=0 -DCMAKE_POSITION_INDEPENDENT_CODE=1 -DDUNE_ENABLE_PYTHONBINDINGS=0 -DBLA_STATIC=1 -DCMAKE_DISABLE_FIND_PACKAGE_QuadMath=1 -DBLAS_LIBRARIES=/usr/lib64/libblas.a -DLAPACK_LIBRARIES=/usr/lib64/liblapack.a
cmake --build . -- -j${BUILD_JOBS}
cmake --build . --target install
popd
# Build dune-uggrid
git clone --depth 1 --branch v2.9.1 https://gitlab.dune-project.org/staging/dune-uggrid.git
pushd dune-uggrid
mkdir build
cd build
cmake .. -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=0 -DCMAKE_POSITION_INDEPENDENT_CODE=1 -DDUNE_ENABLE_PYTHONBINDINGS=0 -DBLA_STATIC=1 -DCMAKE_DISABLE_FIND_PACKAGE_QuadMath=1 -DBLAS_LIBRARIES=/usr/lib64/libblas.a -DLAPACK_LIBRARIES=/usr/lib64/liblapack.a
cmake --build . -- -j${BUILD_JOBS}
cmake --build . --target install
popd
# Build dune-grid
git clone --depth 1 --branch v2.9.1 https://gitlab.dune-project.org/core/dune-grid.git
pushd dune-grid
mkdir build
cd build
cmake .. -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=0 -DCMAKE_POSITION_INDEPENDENT_CODE=1 -DDUNE_ENABLE_PYTHONBINDINGS=0 -DBLA_STATIC=1 -DCMAKE_DISABLE_FIND_PACKAGE_QuadMath=1 -DBLAS_LIBRARIES=/usr/lib64/libblas.a -DLAPACK_LIBRARIES=/usr/lib64/liblapack.a
cmake --build . -- -j${BUILD_JOBS}
cmake --build . --target install
popd
# Build dune-localfunctions
git clone --depth 1 --branch v2.9.1 https://gitlab.dune-project.org/core/dune-localfunctions.git
pushd dune-localfunctions
mkdir build
cd build
cmake .. -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=0 -DCMAKE_POSITION_INDEPENDENT_CODE=1 -DDUNE_ENABLE_PYTHONBINDINGS=0 -DBLA_STATIC=1 -DCMAKE_DISABLE_FIND_PACKAGE_QuadMath=1 -DBLAS_LIBRARIES=/usr/lib64/libblas.a -DLAPACK_LIBRARIES=/usr/lib64/liblapack.a
cmake --build . -- -j${BUILD_JOBS}
cmake --build . --target install
popd
popd

76
python/generate-pypi-package.sh Executable file
View File

@ -0,0 +1,76 @@
#!/bin/bash
set -e
VERSION_TAG=${1:-""}
BUILD_JOBS=$2
export CMAKE_GENERATOR=Ninja
declare -A python_versions
python_versions[cp36-cp36m]=/opt/python/cp36-cp36m/bin/python
python_versions[cp37-cp37m]=/opt/python/cp37-cp37m/bin/python
python_versions[cp38-cp38]=/opt/python/cp38-cp38/bin/python
python_versions[cp39-cp39]=/opt/python/cp39-cp39/bin/python
python_versions[cp310-cp310]=/opt/python/cp310-cp310/bin/python
python_versions[cp311-cp311]=/opt/python/cp311-cp311/bin/python
python_versions[cp312-cp312]=/opt/python/cp312-cp312/bin/python
for python_bin in ${python_versions[*]}
do
${python_bin} -m pip install pip --upgrade
${python_bin} -m pip install wheel setuptools twine pytest-runner auditwheel scikit-build cmake
done
DIR=`pwd`
# Setup opm modules
git clone https://github.com/OPM/opm-common
git clone https://github.com/OPM/opm-grid
git clone https://github.com/OPM/opm-models
git clone https://github.com/OPM/opm-simulators
git clone https://github.com/OPM/opm-utilities
ln -sf opm-utilities/opm-super/CMakeLists.txt CMakeLists.txt
sed -e 's/add_subdirectory(opm-upscaling)//' -e 's/add_dependencies(opmupscaling opmgrid)//g' -i CMakeLists.txt
mkdir -p /tmp/opm/wheelhouse
for tag in ${!python_versions[@]}
do
# Build opm-common bindings
pushd opm-common
# Delete the folder if it already exists
if [ -d $tag ]; then
rm -rf $tag
fi
mkdir $tag && cd $tag
cmake -DPYTHON_EXECUTABLE=${python_versions[$tag]} -DWITH_NATIVE=0 \
-DOPM_ENABLE_PYTHON=ON -DOPM_PYTHON_PACKAGE_VERSION_TAG=${VERSION_TAG} ..
# make step is necessary until the generated ParserKeywords/*.hpp are generated in the Python step
cmake --build . --target opmcommon_python -- -j${BUILD_JOBS}
cd python
echo -e "include opm/*\ninclude opm/io/summary/__init__.py" > MANIFEST.in
cat MANIFEST.in
${python_versions[$tag]} setup.py sdist bdist_wheel --plat-name manylinux_2_28_x86_64 --python-tag $tag
${python_versions[$tag]} -m auditwheel repair dist/*$tag*.whl
cp dist/*$tag*.whl /tmp/opm/wheelhouse
popd
# Delete the folder if it already exists
if [ -d $tag ]; then
rm -rf $tag
fi
mkdir $tag && pushd $tag
cmake -DPYTHON_EXECUTABLE=${python_versions[$tag]} -DWITH_NATIVE=0 -DBoost_USE_STATIC_LIBS=1 \
-DOPM_ENABLE_PYTHON=ON -DOPM_PYTHON_PACKAGE_VERSION_TAG=${VERSION_TAG} -DBLA_STATIC=1 -DBLAS_LIBRARIES=/usr/lib64/libblas.a -DSUITESPARSE_USE_STATIC=1 -DCMAKE_DISABLE_FIND_PACKAGE_QuadMath=1 ..
# make step is necessary until the generated ParserKeywords/*.hpp are generated in the Python step
cmake --build . --target simulators -- -j${BUILD_JOBS}
cd opm-simulators/python
${python_versions[$tag]} setup.py sdist bdist_wheel --plat-name manylinux_2_28_x86_64 --python-tag $tag
${python_versions[$tag]} -m auditwheel repair dist/*$tag*.whl
cp dist/*$tag*.whl /tmp/opm/wheelhouse
popd
done

View File

@ -0,0 +1,5 @@
project(install_python_binding)
cmake_minimum_required(VERSION 3.15)
install(CODE "message(\"Dummy install\")")

7
python/pyproject.toml Normal file
View File

@ -0,0 +1,7 @@
[build-system]
requires= [
"setuptools>=42",
"scikit-build>=0.13",
"cmake>=3.15",
"ninja"
]

5
python/requirements.txt Normal file
View File

@ -0,0 +1,5 @@
six
future
decorator
opm
numpy

11
python/setup-docker-image.sh Executable file
View File

@ -0,0 +1,11 @@
#!/bin/bash
# Script to be run on a manylinux2014 docker image to complete it for OPM usage.
# i.e. docker run -i -t quay.io/pypa/manylinux2014_x86_64 < setup-docker-image.sh
# A ready made Docker image is available at Dockerhub:
# docker run -i -t lindkvis/manylinux2014_opm:latest
dnf install -y almalinux-release-devel
dnf install -y blas-static lapack-static suitesparse-static ninja-build

39
python/setup.py.in Normal file
View File

@ -0,0 +1,39 @@
from skbuild import setup
import os
setupdir = os.path.dirname(__file__)
if setupdir != '':
os.chdir( setupdir )
with open("README.md", "r") as fh:
long_description = fh.read()
with open("requirements.txt", "r") as fh:
requires = [line.rstrip() for line in fh]
setup(
name='opm-simulators',
version = '@opm-simulators_VERSION@' + '@opm-simulators_PYTHON_PACKAGE_VERSION@',
url='http://www.opm-project.org',
author='The Open Porous Media Project',
author_email='opmuser@gmail.com',
description='OPM-Simulators Python bindings',
long_description=long_description,
long_description_content_type="text/markdown",
packages=[
'opm',
'opm.simulators'
],
package_data={'opm' : ['$<TARGET_FILE_NAME:simulators>']},
include_package_data=True,
license='Open Source',
test_suite='tests',
setup_requires=["pytest-runner", 'setuptools_scm'],
install_requires=requires,
python_requires='>=3.6',
classifiers=[
"Programming Language :: Python :: 3",
"License :: OSI Approved :: GNU General Public License v3 (GPLv3)",
],
)

View File

@ -91,6 +91,18 @@ add_custom_target(copy_python ALL
${PROJECT_SOURCE_DIR}/python/test_data ${PROJECT_BINARY_DIR}/python 0
)
file(COPY ${PROJECT_SOURCE_DIR}/python/opm/CMakeLists.txt DESTINATION ${PROJECT_BINARY_DIR}/python)
file(COPY ${PROJECT_SOURCE_DIR}/python/requirements.txt DESTINATION ${PROJECT_BINARY_DIR}/python)
file(COPY ${PROJECT_SOURCE_DIR}/python/README.md DESTINATION ${PROJECT_BINARY_DIR}/python)
file(COPY ${PROJECT_SOURCE_DIR}/python/MANIFEST.in DESTINATION ${PROJECT_BINARY_DIR}/python)
file(COPY ${PROJECT_SOURCE_DIR}/python/pyproject.toml DESTINATION ${PROJECT_BINARY_DIR}/python)
# Generate versioned setup.py
configure_file(${PROJECT_SOURCE_DIR}/python/setup.py.in
${PROJECT_BINARY_DIR}/python/setup.py.tmp @ONLY)
file(GENERATE OUTPUT ${PROJECT_BINARY_DIR}/python/setup.py
INPUT ${PROJECT_BINARY_DIR}/python/setup.py.tmp)
# Since the installation of Python code is nonstandard it is protected by an
# extra cmake switch, OPM_INSTALL_PYTHON. If you prefer you can still invoke
# setup.py install manually - optionally with the generated script