Skip to content

Commit

Permalink
GitHubAction builds for espeak-py (#2)
Browse files Browse the repository at this point in the history
Use maturin tooling on GitHub action, turn the steps from README into a build script, and get it to build our key target python versions. Support both python 3.9 and 3.11 CPython for now (other autodetected versions fail, particularly PyPy builds).

Fix up macOS ARM, where homebrew puts files and libraries in different locations.
Fixed up C compile options so that doesn't fail on newer gcc on Ubuntu 22.04+

Added GHA/pypi publish step as per redis-wheel.
  • Loading branch information
paulannetts authored Oct 7, 2024
1 parent 31c5d1f commit 9d4d77d
Show file tree
Hide file tree
Showing 6 changed files with 150 additions and 4 deletions.
88 changes: 88 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
# This file is autogenerated by maturin v1.7.4
# To update, run
#
# maturin generate-ci github --platform linux --platform macos
#
# manual edits:
# - to limit the number of ubuntu variants
# - do the rust build step
# - to add the RUSTFLAGS environment variable
# - to specify python version used by maturin

name: CI

on:
push:
branches:
- master
pull_request:
workflow_call:

permissions:
contents: read

jobs:
linux:
runs-on: ${{ matrix.platform.runner }}
strategy:
matrix:
platform:
- runner: ubuntu-22.04
target: x86_64
steps:
- uses: actions/checkout@v4
with:
submodules: true
- uses: actions/setup-python@v5
- name: Build bindings
run: |
tools/build.sh
- name: Build wheels
uses: PyO3/maturin-action@v1
env:
RUSTFLAGS: -L espeak-ng/src/.libs
with:
target: ${{ matrix.platform.target }}
# only CPython and PyPy (which fail) so specify the full path to the CPythons
args: --release --out dist --interpreter /usr/local/bin/python3.9 --interpreter /usr/local/bin/python3.11
sccache: 'true'
manylinux: auto
- name: Upload wheels
uses: actions/upload-artifact@v4
with:
name: wheels-linux-${{ matrix.platform.target }}
path: dist

macos:
runs-on: ${{ matrix.platform.runner }}
strategy:
matrix:
# Fix up the python versions that maturin detects, as some break
platform:
- runner: macos-13
target: x86_64
python_args: --interpreter /Users/runner/hostedtoolcache/Python/3.9.20/x64/bin/python3.9 --interpreter /usr/local/bin/python3.11
- runner: macos-14
target: aarch64
python_args: --interpreter python3.9 --interpreter python3.11
steps:
- uses: actions/checkout@v4
with:
submodules: true
- uses: actions/setup-python@v5
- name: Build bindings
run: |
tools/build.sh
- name: Build wheels
uses: PyO3/maturin-action@v1
env:
RUSTFLAGS: -L espeak-ng/src/.libs
with:
target: ${{ matrix.platform.target }}
args: --release --out dist ${{ matrix.platform.python_args }}
sccache: 'true'
- name: Upload wheels
uses: actions/upload-artifact@v4
with:
name: wheels-macos-${{ matrix.platform.target }}
path: dist
31 changes: 31 additions & 0 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
name: Publish Wheels

on:
release:
types: [published]

permissions:
contents: read

jobs:
run-build-workflow:
uses: ./.github/workflows/build.yml

pypi-publish:
name: Publish to PyPi
needs: run-build-workflow
runs-on: ubuntu-latest
environment: release
permissions:
id-token: write
steps:
- name: Download artifacts
uses: actions/download-artifact@v4
with:
pattern: wheels-*
merge-multiple: true
path: dist/
- name: List artifacts downloaded
run: ls -R dist
- name: Publish package
uses: pypa/gh-action-pypi-publish@release/v1.8
7 changes: 6 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ Currently, this only provides text phonemization functions, not invoking full TT
On Linux, espeak is statically linked into the built wheel, but there is a runtime dependency on espeak-ng-data.
This can be satisfied by `sudo apt install espeak-ng-data` (or the equivalent for your distro).

On Mac the data and necessary shared library can be installed with `brew tap bplevin36/espeak-ng && brew install espeak-ng --without-pcaudiolib --without-waywardgeek-sonic`. You will need to have XCode tools and GNU autotools installed (if they aren't already).
On Mac the data and necessary shared library can be installed with `brew tap bplevin36/espeak-ng && brew install bplevin36/espeak-ng/espeak-ng --without-pcaudiolib --without-waywardgeek-sonic`. You will need to have XCode tools and GNU autotools installed (if they aren't already).

On macOS under ARM you will need to set `export DYLD_FALLBACK_LIBRARY_PATH=/opt/homebrew/lib` for the example to work, due to a failure at import to find the dynamic link as ARM homebrew lib directories aren't in the standard search path.

## Usage Example
```
Expand All @@ -26,6 +28,7 @@ On Mac the data and necessary shared library can be installed with `brew tap bpl
## Building

Requires Rust (and cargo) as well as GNU autotools and python packages [`maturin`](https://github.com/PyO3/maturin) and `twine`
On Mac GNU autotools can be installed with `brew install libtool automake autoconf`

1. Clone (including submodules)
2. Build espeak-ng in-tree with:
Expand All @@ -39,3 +42,5 @@ Requires Rust (and cargo) as well as GNU autotools and python packages [`maturin
3. Build wheels with `RUSTFLAGS='-L espeak-ng/src/.libs' maturin build --release` (on Linux this requires the [maturin docker container](https://hub.docker.com/r/konstin2/maturin))
4. Install to local python with `pip install target/wheels/<generated_wheel_name>.whl`
5. Publish to PyPi using `twine`

tools/build.sh will automate 1-3 for you if you have the correct tools configured, it is designed to work in a GitHub Action.
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[build-system]
requires = ["maturin>=0.10,<0.11"]
requires = ["maturin>=1,<2"]
build-backend = "maturin"

[project]
Expand Down
5 changes: 3 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ fn ensure_initialized() -> PyResult<()> {
}
let try_paths = [
"/usr/lib/x86_64-linux-gnu/espeak-ng-data", // linux apt install location
"/usr/local/Cellar/espeak-ng/1.50/share/espeak-ng-data", // mac brew install location
"/opt/homebrew/Cellar/espeak-ng/1.50/share/espeak-ng-data", // mac ARM brew install location
"/usr/local/Cellar/espeak-ng/1.50/share/espeak-ng-data", // mac x64 brew install location
"/usr/local/share/espeak-ng-data", // source install locations
"/usr/share/espeak-ng-data",
];
Expand All @@ -50,7 +51,7 @@ fn ensure_initialized() -> PyResult<()> {

#[cfg(target_os = "macos")]
let msg = r#"Error while initializing espeak. If it's not installed, try running:
`brew install anarchivist/espeak-ng/espeak-ng --without-pcaudiolib --without-waywardgeek-sonic`"#;
`brew tap bplevin36/espeak-ng && brew install bplevin36/espeak-ng/espeak-ng --without-pcaudiolib --without-waywardgeek-sonic`"#;
#[cfg(target_os = "linux")]
let msg = r#"Error while initializing espeak. If you haven't installed the data files, run:
`sudo apt install espeak-ng-data`"#;
Expand Down
21 changes: 21 additions & 0 deletions tools/build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#!/bin/bash
set -e
SCRIPT_DIR=$(cd $(dirname $0); pwd)
PARENT_DIR=$(dirname $SCRIPT_DIR)

echo $PARENT_DIR
cd $PARENT_DIR/espeak-ng
if [[ "$(uname)" == "Darwin" ]]; then
brew install automake libtool autoconf
rm CHANGELOG.md
echo "Changelog dummy" > ChangeLog.md
fi
ls

# Fix error on Ubuntu 22.04+
# See https://stackoverflow.com/questions/76060903/gcc-multiple-definition-of-error-on-ubuntu-22-04-after-updating-from-ubuntu-2
export CFLAGS="-fcommon"

./autogen.sh
./configure --without-klatt --without-pcaudiolib --without-mbrola --without-sonic --without-async
make

0 comments on commit 9d4d77d

Please sign in to comment.