Commit 754e1b38 authored by Michael Davidsaver's avatar Michael Davidsaver

sphinx doc

parent 912a8e15
......@@ -7,247 +7,6 @@ libraries in Python Wheel packages. This replaces an external
build system (eg. Makefile), allowing non-python libraries to be
built from source within the python ecosystem.
See [example/setup.py](example/setup.py) for a working example.
[![setuptools-dso](https://github.com/mdavidsaver/setuptools_dso/workflows/setuptools-dso/badge.svg)](https://github.com/mdavidsaver/setuptools_dso/actions)
## Building packages
Packages using `setuptools_dso` can for the most part be treated like any other python package.
Distribution through [pypi.org](https://pypi.org/) as source and/or binary (wheels) is possible.
Like other packages containing compiled code, use of egg binaries is not supported.
Use of PIP is encouraged.
The `setuptools_dso` package needs to be installed when manually invoking `setup.py` scripts in dependent packages.
eg. to generate source tars with `setup.py sdist`.
Developers wishing to work with an in-place build will need to use the added `build_dso` command,
which functions like the `build_ext` command.
```sh
python setup.py build_dso -i
python setup.py build_ext -i
```
## Usage
The [example/](example/) demonstrates building a non-python library,
and linking it with a python extension module.
### pyproject.toml
To properly support `pip install ...`, it is recommended to include a
[`pyproject.toml`](https://www.python.org/dev/peps/pep-0518/)
file containing at least:
```
[build-system]
requires = ["setuptools", "wheel", "setuptools_dso"]
```
This ensures that `setuptools_dso` is available to be imported by `setup.py`.
### MANIFEST.in
Add a `MANIFEST.in` to ensure that `setup.py sdist` includes everything necessary
for a successful source build.
```
include pyproject.toml
include src/*.h
include src/*.c
include src/*.cpp
```
### Building a DSO
The [source](example/src/) files while make up the non-python `demo` library are: `mylib.h`, `foo.c`, `bar.cpp`.
This library will be expressed as a `setuptools_dso.DSO` object.
The first argument is a directory path and library base name encoded like a python module.
eg. the result of `dsodemo.lib.demo` will be eg. `dsodemo/lib/libdemo.so` or `dsodemo\lib\demo.dll`
installed in the python module tree along-side any other python code or C extensions.
Note that there need not be a `dsodemo/lib/__init__.py` as `dsodemo.lib` need not be a python package.
However, if this file is present, then the generated `dsodemo/lib/demo_dsoinfo.py` will be accessible.
```py
from setuptools_dso import DSO, Extension, setup
dso = DSO('dsodemo.lib.demo', ['src/foo.c', 'src/bar.cpp'], ...)
setup(
...
x_dsos = [dso],
zip_safe = False, # setuptools_dso is not compatible with eggs!
)
```
The `DSO` constructor understands the same keyword arguments as `setuptools.Extension`
and [`distutils.core.Extension`](https://docs.python.org/3/distutils/apiref.html#distutils.core.Extension),
with the addition of `dsos=[...]`, `soversion='...'`, and `lang_compile_args={'...':'...'}`.
The `dsos=` argument is a list of other `DSO` names (eg. `'dsodemo.lib.demo'`) to allow
one `DSO` to be linked against others.
eg. `dsos=['some.lib.foo']` will result in something like `gcc ... -L.../some/lib -lfoo`.
### Building an Extension
`setuptools_dso.Extension` is a wrapper around `setuptools.Extension` which adds the `dsos=[...]` keyword argument.
This allows a C extension module to be linked against a `DSO` by name.
The named `DSO` may be built by the same `setup.py`, or may already be present in `$PYTHONPATH`.
```py
from setuptools_dso import DSO, Extension, setup
ext = Extension('dsodemo.ext.dtest', ['src/extension.cpp'],
dsos=['dsodemo.lib.demo'],
)
setup(
...
ext_modules = [ext],
zip_safe = False, # setuptools_dso is not compatible with eggs!
)
```
### Cython
Version 1.3 added a `setuptools_dso.cythonize()` wrapper to correctly handle `Extension(dso=...)`.
### Runtime
Beginning with setuptools-dso 2.0 a file `*_dsoinfo.py` will be generated alongside each DSO.
eg. dso `mypkg.lib.thelib` will create `mypkg/lib/thelib_dsoinfo.py`.
If `mypkg.lib` is a valid python packages (contains `__init__.py`)
then `mypkg.lib.thelib_dsoinfo` can be imported, and will contain the attributes:
- `.dsoname` eg. "mypkg.lib.thelib"
- `.libname` eg. "thelib.so"
- `.soname` eg. "thelib.so.0"
- `.filename` eg. "/full/path/to/thelib.so"
- `.sofilename` eg. "/full/path/to/thelib.so.0"
Beginning with 2.0 `os.add_dll_directory()` is called by the generated `*_dsoinfo.py` module.
Prior to 2.0, or if the generated module is not used,
some additional runtime preparation is needed in order to find the `'dsodemo.lib.demo'` library
when the `dsodemo.ext.dtest` Extension is imported on Windows.
This could be placed in eg. `example/src/dsodemo/__init__.py`
to ensure it always runs before the extension library is loaded.
```py
import sys, os
def fixpath():
# If this file is
# .../__init__.py
# DSOs are under
# .../lib/
libdir = os.path.join(os.path.dirname(__file__), 'lib')
if hasattr(os, 'add_dll_directory'):
os.add_dll_directory(libdir)
else:
path = os.environ.get('PATH', '').split(os.pathsep)
path.append(libdir)
os.environ['PATH'] = os.pathsep.join(path)
if sys.platform == "win32":
fixpath()
```
## Mechanics
Libraries build with setuptools-dso will typically be linked, directly or indirectly, to python extension modules.
Such libraries should be loaded implicitly when the extension module is imported by the python runtime.
For this to work the OS runtime loader must be able to find these libraries.
This is complicated by OS differences, and a desire to support virtualenv and similar.
Supporting virtualenv prevents the use of absolute build time paths.
The resolutions to this complication differ for each OS depending on the
capabilities of the executable format used.
### ELF (Linux, *NIX, *BSD)
For ELF (Executable and Linking Format) targets the RPATH mechanism is used with the magic $ORIGIN/ prefix.
Take as an example the following installed module tree:
```
* modulea
* __init__.py
* _ext.so
* lib
* libsup.so
* libsup.so.0
```
The supporting library is then linked with a library name of `libsup.so.0`
(eg. `gcc -o libsup.so.0 -shared -Wl,-soname,libsup.so.0 ...`)
When linking a dependent library or extension module `-Wl,-rpath,'$ORIGIN/lib'`
is given since the relative path from `_ext.so` to `libsup.so.0` is `./lib`.
Note that on Linux runtime linking is really a function of the libc (eg. glibc).
### Mach-O (OSX)
Historically Mach-O did not support anything like RPATH.
However, it now does (cf. 'man dyld')
The equivalence with GCC+ELF is for `-Wl,-soname,libsup.so.0` to become `-install\_name @rpath/libsup.0.dylib`.
Then `-Wl,-rpath,'$ORIGIN/lib'` becomes `-Wl,-rpath,@loader_path/lib`.
### PE (Windows)
There is no equivalent for RPATH.
It is necessary to adjust the loader search path to include the directory
containing the support library dll explicitly from python code prior to loading the extension.
(eg. from an `__init__.py`)
With earlier versions of Windows it is sufficient to adjust `%PATH%`.
Recent versions require use of the `AddDllDirectory()` API call.
Python wraps this as `os.add_dll_directory()`.
## Changelog
### 2.0 (UNRELEASED)
- Generate info module for each DSO (Kaleb Barrett)
### 1.7 (May 2020)
- Fix support for develop install (pip install -e). (Kirill Smelkov)
### 1.6 (May 2020)
- Use @rpath as install_name prefix on MacOS (Mehul Tikekar)
### 1.5 (Jan. 2020)
- Correct parallel compile on Mac
### 1.4 (Jan. 2020)
- Take package_dir into account (Kirill Smelkov)
- Parallel compile of DSO source when supported (py >= 3.4 and not windows)
- Fake `cythonize()` wrapper when Cython not installed
### 1.3 (Nov. 2019)
- Handle DSO in root (not in a package)
- setup() wrapper correct 'cmdclass' handling (Kirill Smelkov)
- Add `setuptools_dso.cythonize()` wrapper
### 1.2 (Aug. 2019)
- Add LICENSE and COPYRIGHT to MANIFEST
### 1.1 (Aug. 2019)
- Fix inplace build (Kirill Smelkov)
### 1.0 (Oct. 2018)
- Initial Release
- Documentation at https://mdavidsaver.github.io/setuptools_dso
- Github project https://github.com/mdavidsaver/setuptools_dso
- PYPI https://pypi.org/project/setuptools-dso/
PYTHON ?= python3
SPHINXOPTS =
SPHINXBUILD = $(PYTHON) -m sphinx
BUILDDIR = $(CURDIR)/_build
ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) $(CURDIR)
all: html
html:
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
clean:
rm -rf $(BUILDDIR)
commit: html
touch _build/html/.nojekyll
./commit-gh.sh _build/html documentation/_build/html
.PHONY: all html clean commit
#!/bin/sh
set -e -x
# Usage: commit-gh <sub-directory>
#
# Creates a commit containing only the files in the sub-directory provided as an argument
#
# Does not disturb the working copy or index
# directory to search
[ -d "$1" ] || exit 1
# prefix to strip (relative to repo root)
[ "$2" ] || exit 1
# Commit to this branch
BRANCH=refs/heads/gh-pages
# Use the main branch description as the gh-pages commit message
MSG=`git describe --tags --always`
# Scratch space
TDIR=`mktemp -d -p $PWD`
# Automatic cleanup of scratch space
trap 'rm -rf "$TDIR"' INT TERM QUIT EXIT
export GIT_INDEX_FILE="$TDIR/index"
# Add listed files to a new (empty) index
find "$1" -type f -print0 | xargs -0 git update-index --add
# Write the index into the repo, get tree hash
TREE=`git write-tree --prefix="$2"`
echo "TREE $TREE"
git cat-file -p $TREE
# Create a commit with our new tree
# Reference current branch head as parent (if any)
CMT=`git commit-tree -m "$MSG" $TREE`
echo "COMMIT $CMT"
git cat-file -p $CMT
# Update the branch with the new commit tree hash
git update-ref $BRANCH $CMT
echo "Done"
import sys
import os
sys.path.insert(0, os.path.join(os.path.dirname(os.path.dirname(__file__)), 'src'))
project = u'setuptools_dso'
copyright = u'2021, Michael Davidsaver'
master_doc = 'index'
extensions = [
'sphinx.ext.autodoc',
]
#default_role = "any"
html_theme = 'alabaster'
html_theme_options = {
'page_width': '1200px', # better on my 8/5 ratio screen
'sidebar_width': '270px', # avoid wrapping 'setuptools_dso' at top of sidebar
'github_banner': True,
'github_button': True,
'github_user': 'mdavidsaver',
'github_repo': 'setuptools_dso',
}
.. currentmodule:: setuptools_dso
Mechanics
---------
Libraries build with setuptools-dso will typically be linked, directly or indirectly, to python extension modules.
Such libraries should be loaded implicitly when the extension module is imported by the python runtime.
For this to work the OS runtime loader must be able to find these libraries.
This is complicated by OS differences, and a desire to support virtualenv and similar.
Supporting virtualenv prevents the use of absolute build time paths.
The resolutions to this complication differ for each OS depending on the
capabilities of the executable format used.
ELF (Linux, \*NIX, \*BSD)
~~~~~~~~~~~~~~~~~~~~~~~~~
For ELF (Executable and Linking Format) targets the RPATH mechanism is used with the magic $ORIGIN/ prefix.
Take as an example the following installed module tree:
* modulea/
* __init__.py
* _ext.so
* lib/
* libsup.so
* libsup.so.0
The supporting library is then linked with a library name of ``libsup.so.0``
(eg. ``gcc -o libsup.so.0 -shared -Wl,-soname,libsup.so.0 ...``)
When linking a dependent library or extension module ``-Wl,-rpath,'$ORIGIN/lib'``
is given since the relative path from ``_ext.so`` to ``libsup.so.0`` is ``./lib``.
Note that on Linux runtime linking is really a function of the libc (eg. glibc).
Mach-O (OSX)
~~~~~~~~~~~~
Historically Mach-O did not support anything like RPATH.
However, it now does (cf. 'man dyld')
The equivalence with GCC+ELF is for ``-Wl,-soname,libsup.so.0`` to become ``-install\_name @rpath/libsup.0.dylib``.
Then ``-Wl,-rpath,'$ORIGIN/lib'`` becomes ``-Wl,-rpath,@loader_path/lib``.
PE (Windows)
~~~~~~~~~~~~
There is no equivalent for RPATH.
It is necessary to adjust the loader search path to include the directory
containing the support library dll explicitly from python code prior to loading the extension.
(eg. from an ``__init__.py``)
With earlier versions of Windows it is sufficient to adjust ``%PATH%``.
Recent versions require use of the ``AddDllDirectory()`` API call.
Python wraps this as ``os.add_dll_directory()``.
Changelog
---------
* 2.0 (UNRELEASED)
- Generate info module for each DSO (Kaleb Barrett)
- Runtime access to info modules.
* 1.7 (May 2020)
- Fix support for develop install (pip install -e). (Kirill Smelkov)
* 1.6 (May 2020)
- Use @rpath as install_name prefix on MacOS (Mehul Tikekar)
* 1.5 (Jan. 2020)
- Correct parallel compile on Mac
* 1.4 (Jan. 2020)
- Take package_dir into account (Kirill Smelkov)
- Parallel compile of DSO source when supported (py >= 3.4 and not windows)
- Fake :py:func:`cythonize()` wrapper when Cython not installed
* 1.3 (Nov. 2019)
- Handle DSO in root (not in a package)
- setup() wrapper correct 'cmdclass' handling (Kirill Smelkov)
- Add :py:func:`setuptools_dso.cythonize()` wrapper
* 1.2 (Aug. 2019)
- Add LICENSE and COPYRIGHT to MANIFEST
* 1.1 (Aug. 2019)
- Fix inplace build (Kirill Smelkov)
* 1.0 (Oct. 2018)
- Initial Release
setuptools extension for building non-Python Dynamic Shared Objects
===================================================================
.. module:: setuptools_dso
Building non-python shared libraries (eg. `libY.so`, `libY.dylib`, or `Y.dll`) for inclusion in a Python Wheel.
This `setuptools <https://pypi.org/project/setuptools/>`_ extension
provides at alternative to bundling externally built libraries in Python Wheel packages.
This replaces an external build system (eg. Makefile),
allowing non-python libraries to be built from source within a python ecosystem.
- `Issue tracker <https://github.com/mdavidsaver/setuptools_dso/issues>`_
- On `PYPI <https://pypi.org/project/setuptools-dso/>`_
- `VCS repository <https://github.com/mdavidsaver/setuptools_dso>`_
- Canonical `documentation <https://mdavidsaver.github.io/setuptools_dso>`_
- `Example usage <https://github.com/mdavidsaver/setuptools_dso/tree/master/example>`_
- CI status |cistatus|
.. |cistatus| image:: https://github.com/mdavidsaver/setuptools_dso/workflows/setuptools-dso/badge.svg
:target: https://github.com/mdavidsaver/setuptools_dso/actions
:alt: github actions status badge
.. toctree::
:maxdepth: 2
usage
details
Working with packages using setuptools_dso
==========================================
.. currentmodule:: setuptools_dso
Packages using `setuptools_dso` can for the most part be treated like any other python package.
Distribution through `pypi.org <https://pypi.org/>`_ as source and/or binary (wheels) is possible.
Like other packages containing compiled code, use of egg binaries is not supported.
Use of PIP is encouraged.
The :py:mod:`setuptools_dso` package needs to be installed when manually invoking ``setup.py`` scripts in dependent packages.
eg. to generate source tars with ``setup.py sdist``.
Developers wishing to work with an in-place build will need to use the added ``build_dso`` command,
which functions like the ``build_ext`` command. ::
python setup.py build_dso -i
python setup.py build_ext -i
Usage
-----
The `example/ <https://github.com/mdavidsaver/setuptools_dso/tree/master/example>`_ demonstrates building a non-python library,
and linking it with a python extension module.
pyproject.toml
^^^^^^^^^^^^^^
To properly support ``pip install ...``, it is recommended to include a
`pyproject.toml <https://www.python.org/dev/peps/pep-0518/>`_
file containing at least: ::
[build-system]
requires = ["setuptools", "wheel", "setuptools_dso"]
This ensures that ``setuptools_dso`` is available to be imported by ``setup.py``.
MANIFEST.in
^^^^^^^^^^^
Add a ``MANIFEST.in`` to ensure that ``setup.py sdist`` includes everything necessary
for a successful source build. ::
include pyproject.toml
include src/*.h
include src/*.c
include src/*.cpp
Building a DSO
^^^^^^^^^^^^^^
.. autofunction:: setup
.. autoclass:: DSO
The `example source <https://github.com/mdavidsaver/setuptools_dso/tree/master/example/src>`_
files while make up the non-python ``demo`` library are: ``mylib.h``, ``foo.c``, ``bar.cpp``.
This library will be expressed as a `setuptools_dso.DSO` object.
The first argument is a directory path and library base name encoded like a python module.
eg. the result of ``dsodemo.lib.demo`` will be eg. ``dsodemo/lib/libdemo.so`` or ``dsodemo\lib\demo.dll``
installed in the python module tree along-side any other python code or C extensions.
Note that there need not be a ``dsodemo/lib/__init__.py`` as ``dsodemo.lib`` need not be a python package.
However, if this file is present, then the generated `dsodemo/lib/demo_dsoinfo.py` will be accessible. ::
from setuptools_dso import DSO, Extension, setup
dso = DSO('dsodemo.lib.demo', ['src/foo.c', 'src/bar.cpp'], ...)
setup(
...
x_dsos = [dso],
zip_safe = False, # setuptools_dso is not compatible with eggs!
)
The :py:class:`DSO` constructor understands the same keyword arguments as `setuptools.Extension`
and `distutils.core.Extension <https://docs.python.org/3/distutils/apiref.html#distutils.core.Extension>`_,
with the addition of ``dsos=[...]``, ``soversion='...'``, and ``lang_compile_args={'...':'...'}``.
The ``dsos=`` argument is a list of other :py:class:`DSO` names (eg. ``'dsodemo.lib.demo'``) to allow
one :py:class:`DSO` to be linked against others.
eg. ``dsos=['some.lib.foo']`` will result in something like ``gcc ... -L.../some/lib -lfoo``.
Building an Extension
^^^^^^^^^^^^^^^^^^^^^
.. autoclass:: Extension
:py:class:`setuptools_dso.Extension` is a wrapper around ``setuptools.Extension`` which adds the ``dsos=[...]`` keyword argument.
This allows a C extension module to be linked against a ``DSO`` by name.
The named ``DSO`` may be built by the same ``setup.py``, or may already be present in ``$PYTHONPATH``. ::
from setuptools_dso import DSO, Extension, setup
ext = Extension('dsodemo.ext.dtest', ['src/extension.cpp'],
dsos=['dsodemo.lib.demo'],
)
setup(
...
ext_modules = [ext],
zip_safe = False, # setuptools_dso is not compatible with eggs!
)
Cython
^^^^^^
.. autofunction:: cythonize
Version 1.3 added a :py:func:`setuptools_dso.cythonize()` wrapper to correctly handle ``Extension(dso=...)``.
Runtime
-------
Beginning with setuptools-dso 2.0 a file ``*_dsoinfo.py`` will be generated alongside each DSO.
eg. dso ``"mypkg.lib.thelib"`` will create ``mypkg/lib/thelib_dsoinfo.py``.
If ``mypkg.lib`` is a valid python packages (contains ``__init__.py``)
then :py:func:`setuptools_dso.runtime.import_dsoinfo` may be used to retrieve
build time information about the DSO including platform specific filename
(eg. ``thelib.dll`` vs. ``libthelib.so``).
Beginning with 2.0 the necessary additions to ``$PATH`` or calls to ``os.add_dll_directory()``
can be made via `:py:func:`dylink_prepare_dso`.
.. autofunction:: dylink_prepare_dso
Prior to 2.0, or if the generated module is not used,
some additional runtime preparation is needed in order to find the ``"dsodemo.lib.demo"`` library
when the ``dsodemo.ext.dtest`` Extension is imported on Windows.
This could be placed in eg. ``example/src/dsodemo/__init__.py``
to ensure it always runs before the extension library is loaded. ::
# with setuptools_dso >= 2.0a1
#from setuptools_dso import dylink_prepare_dso
#dylink_prepare_dso('..lib.demo')
# or as previously:
import sys, os
def fixpath():
# If this file is
# .../ext/__init__.py
# DSOs are under
# .../lib/
libdir = os.path.join(os.path.dirname(os.path.dirname(__file__)))
if hasattr(os, 'add_dll_directory'): # py >= 3.8
os.add_dll_directory(libdir)
else:
path = os.environ.get('PATH', '').split(os.pathsep)
path.append(libdir)
os.environ['PATH'] = os.pathsep.join(path)
if sys.platform == "win32":
fixpath()
Use with ctypes
^^^^^^^^^^^^^^^
.. autofunction:: find_dso
Info
^^^^
.. autofunction:: setuptools_dso.runtime.import_dsoinfo
......@@ -16,6 +16,9 @@ build system (eg. Makefile).
If you have to ask "why", then keep moving along. There is nothing for you to see here.
""",
url='https://github.com/mdavidsaver/setuptools_dso',
project_urls={
'Documentation':'https://mdavidsaver.github.io/setuptools_dso',
},
author='Michael Davidsaver',
author_email='mdavidsaver@gmail.com',
......
......@@ -20,8 +20,11 @@ __all__ = (
)
def setup(**kws):
"""Wrapper around setuptools.setup() which injects extra Commands
needed to build DSOs.
"""setup(..., x_dsos=[DSO(...)])
Wrapper around setuptools.setup() which injects extra Commands needed to build DSOs.
Unknown keywords are passed through.
:param x_dsos: A list of :py:class:`DSO` instances.
"""
cmdclass = kws.setdefault('cmdclass', {})
# cmdclass_setdefault sets default to cmdclass[name]=klass and verifies
......@@ -43,7 +46,7 @@ try:
from Cython.Build import cythonize as _cythonize
except ImportError:
def _cythonize(extensions, **kws):
"""dummy cythonize() used when Cython not installed.
"""Dummy cythonize() used when Cython not installed.
Assumes that generated source files are distributed.
Cython docs say "It is strongly recommended that you
distribute the generated .c ...".
......@@ -68,7 +71,7 @@ except ImportError:
def cythonize(orig, **kws):
"""Wrapper around Cython.Build.cythonize() to correct handling of
DSO()s and Extension()s using them.
:py:class:`DSO` s and :py:class:`Extension` s using them.
"""
cmods = _cythonize(orig, **kws)
for new, old in zip(cmods, orig):
......
......@@ -18,6 +18,14 @@ from distutils.dep_util import newer_group
from distutils.util import get_platform
from distutils import log
__all__ = (
'DSO',
'Extension',
'build_dso',
'build_ext',
'bdist_egg',
)
Distribution.x_dsos = None
if sys.version_info<(3,4) or MP.get_start_method()!='fork':
......@@ -74,6 +82,11 @@ def expand_sources(cmd, sources):
raise RuntimeError("Missing source file: %s"%src)
class Extension(_Extension):
"""Extension(name, sources, ..., dsos=[DSO(...)])
Wrapper around setuptools.Extension which accepts a list of :py:class:`DSO` dependencies.
:param dsos: A list of :py:class:`DSO` s which this Extension will be linked against.
"""
def __init__(self, name, sources,
dsos=None,
**kws):
......@@ -81,6 +94,21 @@ class Extension(_Extension):
self.dsos = dsos or []
class DSO(_Extension):
"""DSO(name, sources, ..., dsos=[DSO(...)], soversion=None)
A Dynamic Shared Object to be built.
Accepts the same options as :py:class:`Extension` with additions:
:param dsos: A list of :py:class:`DSO` s which this DSO will be linked against.
:param str soversion: None (default) or a string. On supported targerts, this string
which will be appended to create the SONAME. eg. ``soversion="0"``
will turn ``libfoo.so`` into ``libfoo.so.0``.
:param dict lang_compile_args: Language specific ("c" or "c++") compiler flags.
eg. ``{'c':['-DMAGIC']}``
:param str gen_info: Controls generation of "info" module.
True (default) uses the conventional filename,
False disableds generation,
or a string to use a specific filename.
"""
def __init__(self, name, sources,
soversion=None,
lang_compile_args=None,
......
......@@ -62,11 +62,19 @@ def _auto_pkg():
return caller_mod.__name__
def import_dsoinfo(dso, package=None):
"""Import and return info module for the named DSO
"""Import and return "info" module for the named DSO.
:param str dso: DSO name string (eg. 'my.pkg.libs.adso').
:param str package: Package name to resolve relative imports. cf. importlib.import_module
:returns: Info module
For example, on a ELF target the "info" module for a DSO "mypkg.lib.thelib" would contain the attributes:
- `.dsoname` eg. "mypkg.lib.thelib"
- `.libname` eg. "thelib.so"
- `.soname` eg. "thelib.so.0"
- `.filename` eg. "/full/path/to/thelib.so"
- `.sofilename` eg. "/full/path/to/thelib.so.0"
"""
if package is None:
package = _auto_pkg()
......@@ -107,10 +115,10 @@ def find_dso(dso, package=None, so=True):
No effect on Windows.
:returns: Absolute path string of DSO file.
eg.
eg. ::
>>> fname = setuptools_dso.find_dso('my.pkg.libs.adso')
>>> lib = ctypes.CDLL(fname, , ctypes.RTLD_GLOBAL)
fname = setuptools_dso.find_dso('my.pkg.libs.adso')
lib = ctypes.CDLL(fname, ctypes.RTLD_GLOBAL)
"""
if package is None:
package = _auto_pkg()
......@@ -119,7 +127,7 @@ def find_dso(dso, package=None, so=True):
def cli_info(args):
def _cli_info(args):
mod = import_dsoinfo(args.dso)
if args.var:
print(getattr(mod, args.var))
......@@ -137,7 +145,7 @@ def getargs():
S = SP.add_parser('info')
S.add_argument('dso')
S.add_argument('var', nargs='?')
S.set_defaults(func=cli_info)
S.set_defaults(func=_cli_info)
return P
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment