Skip to content

Commit

Permalink
Get python bindings via nanobind, seemingly working.
Browse files Browse the repository at this point in the history
Tested on macOS - and everything now seems reasonable.
But I'm sure there will be a number of changes needed.
  • Loading branch information
wcjohns committed Dec 17, 2024
1 parent 0f6b213 commit 7b091ff
Show file tree
Hide file tree
Showing 8 changed files with 1,104 additions and 689 deletions.
9 changes: 4 additions & 5 deletions bindings/python/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,9 @@ set( SpecUtils_FLT_PARSE_METHOD "strtod" CACHE STRING "Float parsing method" )
add_subdirectory( ${CMAKE_CURRENT_SOURCE_DIR}/../.. ${CMAKE_CURRENT_BINARY_DIR}/LibSpecUtils )

if (NOT SKBUILD)
message(WARNING "\
This CMake file is meant to be executed using 'scikit-build'. Running
it directly will almost certainly not produce the desired result. If
you are a user trying to install this package, please use the command
message(FATAL_ERROR "\
This CMake file is must be executed using 'scikit-build'.
If you are a user trying to install this package, please use the command
below, which will install all necessary build dependencies, compile
the package in an isolated environment, and then install it.
=====================================================================
Expand All @@ -28,7 +27,7 @@ if (NOT SKBUILD)
in your environment once and use the following command that avoids
a costly creation of a new virtual environment at every compilation:
=====================================================================
$ pip install nanobind scikit-build-core[pyproject]
$ pip install nanobind scikit-build-core
$ pip install --no-build-isolation -ve .
=====================================================================
You may optionally add -Ceditable.rebuild=true to auto-rebuild when
Expand Down
89 changes: 20 additions & 69 deletions bindings/python/README.md
Original file line number Diff line number Diff line change
@@ -1,76 +1,27 @@
Instructions to build and install a python wheel file.
# Python bindings to SpecUtils

It could be more automated, or polished, or whatever, but this works.
[nanobind](https://github.com/wjakob/nanobind) is used to create the Python bindings to SpecUtils.


## macOS build instructions
Tested on M1 on Ventura, with Xcode 15.1
```bash
# Setup deployment target and path where you will install boost
export MACOSX_DEPLOYMENT_TARGET=10.13
export MY_BOOST_PREFIX=/path/to/install/prefix/to/macOS_boost_1_85_prefix


# Download and build boost with Python support (any non-ancient version of boost should work)
cd /tmp/
curl -L https://boostorg.jfrog.io/artifactory/main/release/1.85.0/source/boost_1_85_0.tar.gz -o boost_1_85_0.tar.gz
tar -xzvf boost_1_85_0.tar.gz
cd boost_1_85_0

# build the b2 executable
./bootstrap.sh cxxflags="--arch arm64 -mmacosx-version-min=10.13" cflags="-arch arm64 -mmacosx-version-min=10.13" linkflags="-arch arm64 -mmacosx-version-min=10.13" --prefix=${MY_BOOST_PREFIX}

# point boost to the Python install we want to use, by using a user-config.jam file
# Here I'm using the brew install of python 3.11
echo "using python : 3.11.6 : /opt/homebrew/opt/python3/bin/python3 : /opt/homebrew/opt/python3/Frameworks/Python.framework/Versions/3.11/include/python3.11/ : /opt/homebrew/opt/python3/Frameworks/Python.framework/Versions/3.11/lib/libpython3.11.dylib ;" > user-config.jam

# build and install boost for arm64 - we will only make static libs, so this way the
# final SpecUtils module library will be self contained.
./b2 --user-config=./user-config.jam toolset=clang-darwin target-os=darwin architecture=arm abi=aapcs cxxflags="-stdlib=libc++ -arch arm64 -std=c++14 -mmacosx-version-min=10.13" cflags="-arch arm64 -mmacosx-version-min=10.13" linkflags="-stdlib=libc++ -arch arm64 -std=c++14 -mmacosx-version-min=10.13" link=static variant=release threading=multi --build-dir=macOS_arm64_build --prefix=${MY_BOOST_PREFIX} -a install

# remove the boost src and build files
cd ..
rm -r boost_1_85_0.tar.gz boost_1_85_0

# build SpecUtils
cd /path/to/SpecUtils
mkdir build_python
cd build_python
cmake -DSpecUtils_PYTHON_BINDINGS=ON -DCMAKE_BUILD_TYPE=Release -DCMAKE_OSX_DEPLOYMENT_TARGET="10.13" -DCMAKE_PREFIX_PATH=${MY_BOOST_PREFIX} -DCMAKE_BUILD_TYPE=Release -DCMAKE_OSX_ARCHITECTURES="arm64" ..
cmake --build . --config Release -j10


# now, lets test it
mkdir pytest
cd pytest
# We need to rename the shared library to something that will work with Python
cp ../libSpecUtils.dylib ./SpecUtils.so
cp ../../bindings/python/test_python.py .
# The `test_python.py` script uses the `passthrough.n42` file from InterSpec, so
# we need to copy that into the current directory
cp /path/to/InterSpec/example_spectra/passthrough.n42 .

# Now run the test script, making sure to use the same Python we compiled boost against
/opt/homebrew/opt/python3/bin/python3 test_python.py
# You should see some output


# if you want, you can create a proper package (although these instructions may be out of date)
mkdir SpecUtils
cp ../bindings/python/__init__.py ./SpecUtils/
cp libSpecUtils.dylib ./SpecUtils/SpecUtils.so
ln -s ../bindings/python/setup.py .
python3 setup.py bdist_wheel
python3 -m pip install --user --force dist/SpecUtils-0.0.1-cp39-cp39-macosx_12_0_x86_64.whl
To compile the bindings, run the following commands:
```
mkdir my_venv
python3 -m venv my_venv
source my_venv/bin/activate
cd my_venv
pip install /path/to/SpecUtils/bindings/python
```

## Windows build instructions
Assumes you already compiled boost with Python support. The script `get-boost.ps1` will help you with this.

Run these powershell scripts to build SpecUtils with python bindings and install the bindings into your python environment. Tested with python 3.11.
To run the examples, run the following commands:
```
cd examples
python test_python.py
python make_file_example.py
python make_html_plot.py /some/path/to/a/file.n42
```

```ps1
# Run these in a Visual Studio Development Powershell Console
PS C:\Projects\code\SpecUtils\bindings\python> .\build-4-python.ps1
PS C:\Projects\code\SpecUtils\bindings\python> .\make-wheel.ps1
To run the tests, run the following commands:
```
python -m unittest tests/test_specutils.py
```

Loading

0 comments on commit 7b091ff

Please sign in to comment.