or
or
By clicking below, you agree to our terms of service.
New to HackMD? Sign up
Syntax | Example | Reference | |
---|---|---|---|
# Header | Header | 基本排版 | |
- Unordered List |
|
||
1. Ordered List |
|
||
- [ ] Todo List |
|
||
> Blockquote | Blockquote |
||
**Bold font** | Bold font | ||
*Italics font* | Italics font | ||
~~Strikethrough~~ | |||
19^th^ | 19th | ||
H~2~O | H2O | ||
++Inserted text++ | Inserted text | ||
==Marked text== | Marked text | ||
[link text](https:// "title") | Link | ||
 | Image | ||
`Code` | Code |
在筆記中貼入程式碼 | |
```javascript var i = 0; ``` |
|
||
:smile: | ![]() |
Emoji list | |
{%youtube youtube_id %} | Externals | ||
$L^aT_eX$ | LaTeX | ||
:::info This is a alert area. ::: |
This is a alert area. |
On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?
Please give us some advice and help us improve HackMD.
Do you want to remove this version name and description?
Syncing
xxxxxxxxxx
Building and distributing
tags:
book
Some introduction
The end goal is to be able to make our code installable with package managers such as
conda
orpip
without the end user having to worry about compiling code, setting up paths for shared libraries etc.f2py
Packaging Fortran code with
f2py
is embarrasingly easy thanks tonumpy.distutils
. We can tell setuptools to build Fortran source files by using thenumpy.distutils
drop-in replacements for the regularExtension
andsetup
.Let's start with our function that does addition.
We now write a minimal
setup.py
that will install our function within a Python package.We install with
pip install .
and can now import into Python:It does not get easier than this.
ctypes
ctypes
does not provide any tools for building or distribution. The most pragmatic solution is to package the shared library directly with the code using thepackage_data
keyword insetup.py
. We use the following package structure:and this
setup.py
:The
package_data
keyword will instruct setuptools to copy thelib/mod_add.so
into the built Python package.We have created the
add.py
module that loadsmod_add.so
using thepathlib
library and exports the addition function to the module namespace:After installing with
pip install .
, we can import the function from our new Python package.Supporting different platforms
Shared libraries need to be compiled separately for each platform that you want to support. One option is to distribute all of them with the package and use
sys.platform
to load the right one at runtime. Alternatively, tools like cibuildwheel can be used to set up an automatic build of (1) the shared library and (2) the Python package for multiple platforms.cffi
Cython
We start with the following project structure.
The files
c_mod_sum.pxd
,mod_sum.pyx
,mod_sum.h
andlibmod_sum.so
are the same files that we have worked with previously. Here is thesetup.py
:There are some changes to have we worked previously:
library_dirs
is set tolib
include
directory and link to it via theinclude_dirs
keyword.sum
, in thecython_example
package.The
pyproject.toml
now also lists Cython as a dependency:With everything set up, we can create a binary wheels file with setuptools:
If we try to install the wheels with
and import the package, we encounter the following error:
The problem is that the shared library is not available to Python at runtime. We could solve it by setting the
LD_LIBRARY_PATH
variable before running Python, but that option would not be available to the end user who installs our package from PyPi. Instead, we will patch the wheels.Patching the wheels
To package the shared library with the wheel file, we need to use external and platform-specific tools.
Patching the wheels is a very platform-specific procedure, and we illustrate it here exemplified using
delocate
on MacOS. Guides for how to use the other tools for Linux and Windows can reached through the links in the table above.First we need to change the install name of our shared library if it was generated with
gfortran
:We then go into the
dist
directory and patch the wheel file withdelocate
. We use theDYLD_LIBRARY_PATH
environment variable to telldelocate
where it can find our shared library.Now we are ready to install the patched wheels:
The Python package is now ready to use and could be uploaded to PyPi.