forked from openslide/openslide-bin
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Build Python wheel containing OpenSlide shared object
Generate a wheel for an openslide-bin Python package, containing the OpenSlide shared object and an __init__.py that loads it with ctypes. OpenSlide Python can look for this package and use its shared object rather than requiring OpenSlide to be installed directly on the system. Hand-roll the wheel rather than building it with an existing tool like meson-python. Existing Python build tools expect to be in control of the entire build process, but we want to produce the wheel as a side effect of an existing build. Our needs are simple, so just implement the underlying packaging specs directly. Signed-off-by: Benjamin Gilbert <bgilbert@cs.cmu.edu>
- Loading branch information
Showing
18 changed files
with
694 additions
and
13 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
/openslide-bin-* | ||
/openslide[-_]bin-* | ||
/override | ||
/work | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
# openslide-bin | ||
|
||
[OpenSlide Python][] requires a copy of [OpenSlide][]. You could install | ||
it from your package manager, or you could download binaries from the | ||
OpenSlide website. Either choice might be inconvenient, and depending on | ||
your package manager, it might get you an old version of OpenSlide. | ||
|
||
[openslide-bin][] is a pip-installable, self-contained build of OpenSlide | ||
for Linux, macOS, and Windows. It's built by the OpenSlide maintainers, | ||
ships the same binaries as the OpenSlide website, and has no dependencies | ||
you don't already have on your system. And it always has the latest version | ||
of OpenSlide. | ||
|
||
[OpenSlide Python]: https://pypi.org/project/openslide-python/ | ||
[OpenSlide]: https://openslide.org/ | ||
[openslide-bin]: https://github.com/openslide/openslide-bin/ | ||
|
||
## Installing | ||
|
||
Install with `pip install openslide-bin`. OpenSlide Python ≥ 1.4.0 will | ||
automatically find openslide-bin and use it. | ||
|
||
openslide-bin is available for Python 3.8+ on the following platforms: | ||
|
||
- Linux x86_64 with glibc 2.28+ (Debian, Fedora, RHEL 8+, Ubuntu, many others) | ||
- macOS 11+ (arm64 and x86_64) | ||
- Windows 10+ and Windows Server 2016+ (x64) | ||
|
||
pip older than 20.3 cannot install openslide-bin, claiming that it `is not a | ||
supported wheel on this platform`. On platforms with these versions of pip | ||
(RHEL 8 and Ubuntu 20.04), upgrade pip first with `pip install --upgrade | ||
pip`. | ||
|
||
## Using | ||
|
||
Use OpenSlide via [OpenSlide Python][]. The OpenSlide Python | ||
[API documentation][] will get you started. | ||
|
||
[API documentation]: https://openslide.org/api/python/ | ||
|
||
## Building from source | ||
|
||
You should probably [build OpenSlide from source][openslide-build] instead. | ||
|
||
The wheels are built by a [custom script][] that runs [Meson][] in builder | ||
containers. The source tarball includes all the source code and scripts, | ||
and the wheels are built directly from the tarball, but the build cannot be | ||
invoked from a [PEP 517][] frontend like `build` or `pip`. If wheels are | ||
not available for your system, building openslide-bin from source is not | ||
likely to help, and you'll likely have better luck installing OpenSlide from | ||
source directly. | ||
|
||
[openslide-build]: https://github.com/openslide/openslide/#compiling | ||
[custom script]: https://github.com/openslide/openslide-bin/#readme | ||
[Meson]: https://mesonbuild.com/ | ||
[PEP 517]: https://peps.python.org/pep-0517/ | ||
|
||
## License | ||
|
||
OpenSlide and openslide-bin are released under the terms of the | ||
[GNU Lesser General Public License, version 2.1][lgpl]. | ||
|
||
openslide-bin includes components released under the LGPL 2.1 and other | ||
compatible licenses. A complete set of component licenses is installed in | ||
the `licenses` subdirectory of openslide-bin's `dist-info` metadata. | ||
|
||
OpenSlide and openslide-bin are distributed in the hope that they will be | ||
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser | ||
General Public License for more details. | ||
|
||
[lgpl]: https://openslide.org/license/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
# | ||
# openslide-bin - Wrapper for OpenSlide binary build | ||
# | ||
# Copyright (c) 2023 Benjamin Gilbert | ||
# | ||
# This library is free software; you can redistribute it and/or modify it | ||
# under the terms of version 2.1 of the GNU Lesser General Public License | ||
# as published by the Free Software Foundation. | ||
# | ||
# This library is distributed in the hope that it will be useful, but | ||
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY | ||
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public | ||
# License for more details. | ||
# | ||
# You should have received a copy of the GNU Lesser General Public License | ||
# along with this library; if not, write to the Free Software Foundation, | ||
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
# | ||
|
||
from __future__ import annotations | ||
|
||
from ctypes import CDLL, cdll | ||
import importlib.resources as res | ||
import platform | ||
|
||
|
||
def _load_openslide() -> CDLL: | ||
if platform.system() == 'Windows': | ||
name = 'libopenslide-1.dll' | ||
elif platform.system() == 'Darwin': | ||
name = 'libopenslide.1.dylib' | ||
else: | ||
name = 'libopenslide.so.1' | ||
try: | ||
# Python >= 3.9 | ||
with res.as_file(res.files(__name__).joinpath(name)) as path: | ||
return cdll.LoadLibrary(path.as_posix()) | ||
except AttributeError: | ||
with res.path(__name__, name) as path: | ||
return cdll.LoadLibrary(path.as_posix()) | ||
|
||
|
||
libopenslide1 = _load_openslide() | ||
__version__ = '@version@' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
py_config = { | ||
'version': meson.project_version(), | ||
} | ||
|
||
py_artifacts = [ | ||
configure_file( | ||
configuration : py_config, | ||
input : 'pyproject.in.toml', | ||
output : 'pyproject.toml', | ||
), | ||
configure_file( | ||
configuration : py_config, | ||
input : '__init__.in.py', | ||
output : '__init__.py', | ||
), | ||
libopenslide_postprocessed, | ||
licenses, | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
[project] | ||
name = "openslide-bin" | ||
version = "@version@" | ||
maintainers = [ | ||
{name = "OpenSlide project", email = "openslide-users@lists.andrew.cmu.edu"} | ||
] | ||
description = "Binary build of OpenSlide" | ||
readme = "artifacts/python/README.md" | ||
license = {text = "GNU Lesser General Public License, version 2.1"} | ||
keywords = ["OpenSlide", "whole-slide image", "virtual slide", "library"] | ||
classifiers = [ | ||
"Development Status :: 5 - Production/Stable", | ||
"Intended Audience :: Developers", | ||
"Intended Audience :: Healthcare Industry", | ||
"Intended Audience :: Science/Research", | ||
"License :: OSI Approved :: GNU Lesser General Public License v2 (LGPLv2)", | ||
"Operating System :: MacOS :: MacOS X", | ||
"Operating System :: Microsoft :: Windows", | ||
"Operating System :: POSIX :: Linux", | ||
"Programming Language :: Python", | ||
"Programming Language :: Python :: 3", | ||
"Programming Language :: Python :: 3.8", | ||
"Programming Language :: Python :: 3.9", | ||
"Programming Language :: Python :: 3.10", | ||
"Programming Language :: Python :: 3.11", | ||
"Programming Language :: Python :: 3.12", | ||
"Topic :: Scientific/Engineering :: Bio-Informatics", | ||
] | ||
requires-python = ">= 3.8" | ||
|
||
[project.urls] | ||
Homepage = "https://openslide.org/" | ||
# use GitHub Releases page because it has subproject versions | ||
"Release notes" = "https://github.com/openslide/openslide-bin/releases" | ||
Repository = "https://github.com/openslide/openslide-bin" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
#!/usr/bin/env python3 | ||
# | ||
# Tools for building OpenSlide and its dependencies | ||
# | ||
# Copyright (c) 2023 Benjamin Gilbert | ||
# All rights reserved. | ||
# | ||
# This script is free software: you can redistribute it and/or modify it | ||
# under the terms of the GNU Lesser General Public License, version 2.1, | ||
# as published by the Free Software Foundation. | ||
# | ||
# This script is distributed in the hope that it will be useful, but WITHOUT | ||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License | ||
# for more details. | ||
# | ||
# You should have received a copy of the GNU Lesser General Public License | ||
# along with this script. If not, see <http://www.gnu.org/licenses/>. | ||
# | ||
|
||
from __future__ import annotations | ||
|
||
import argparse | ||
from contextlib import ExitStack | ||
from email.message import Message | ||
from io import BytesIO | ||
import os | ||
from pathlib import Path | ||
import re | ||
import subprocess | ||
from typing import BinaryIO | ||
|
||
from common.archive import FileMember, WheelWriter | ||
from common.argparse import TypedArgs | ||
from common.meson import meson_host | ||
from common.python import pyproject_to_message | ||
|
||
|
||
class Args(TypedArgs): | ||
artifacts: list[Path] | ||
output: BinaryIO | ||
|
||
|
||
args = Args('write-wheel', description='Write Python wheel.') | ||
args.add_arg( | ||
'-o', | ||
'--output', | ||
type=argparse.FileType('wb'), | ||
required=True, | ||
help='output file', | ||
) | ||
args.add_arg( | ||
'artifacts', | ||
metavar='artifact', | ||
nargs='+', | ||
type=Path, | ||
help='built artifact', | ||
) | ||
args.parse() | ||
|
||
with ExitStack() as inputs: | ||
with WheelWriter(args.output) as whl: | ||
for path in args.artifacts: | ||
if path.is_file(): | ||
fh = inputs.enter_context(path.open('rb')) | ||
if path.name == 'pyproject.toml': | ||
meta = pyproject_to_message(fh.read().decode()) | ||
whl.add( | ||
FileMember( | ||
whl.metadir / 'METADATA', BytesIO(meta.as_bytes()) | ||
) | ||
) | ||
elif path.name == 'licenses': | ||
whl.add_tree(whl.metadir, path) | ||
else: | ||
name = re.sub('(\\.so\\.[0-9]+)\\.[0-9.]+', '\\1', path.name) | ||
whl.add(FileMember(whl.datadir / name, fh)) | ||
|
||
meta = Message() | ||
meta['Wheel-Version'] = '1.0' | ||
meta['Generator'] = 'openslide-bin' | ||
meta['Root-Is-Purelib'] = 'false' | ||
meta['Tag'] = whl.tag | ||
whl.add(FileMember(whl.metadir / 'WHEEL', BytesIO(meta.as_bytes()))) | ||
|
||
if meson_host() == 'linux': | ||
report = subprocess.check_output( | ||
[ | ||
os.environ['AUDITWHEEL'], | ||
'show', | ||
args.output.name, | ||
], | ||
).decode() | ||
if f'"{whl.platform}"' not in report: | ||
raise Exception(f'Wheel audit failed: {report}') |
Oops, something went wrong.