Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TravisCI automation for building Python binaries #28

Open
wants to merge 6 commits into
base: master
Choose a base branch
from

Conversation

dtreskunov
Copy link

Finally my branch is in a good state. This should be a good addition allowing frequent releases for many platforms with minimal manual work.

Note on Linux builds

Python whl packages are cross-compiled for Linux platforms supported
by dockcross. It would be trivial to add more platforms.

  • linux-armv6: should work on RPi Zero
  • linux-armv7: tested on RPi 3
  • manylinux2010-x64: tested on Debian buster

Note that dockcross/windows-shared-x64 doesn't support building OpenFST
due to certain syscalls not being supported in the MinGW environment.
See Note below about Windows builds.

QEMU is registered as the binfmt handler inside Travis CI Docker host
(dockcross images already come with the qemu binaries in /usr/bin). This
allows the Docker container to run foreign binaries (e.g. x86-64 host becomes
able to run ARM binaries), and is needed for some Autoconf scripts to
work correctly.

Intermediate build stages are pushed to Docker Hub to work around the 50 min
limit imposed by Travis CI on unpaid users. Initial build will likely time
out, but can be restarted in Travis UI and will use the stages in the Dockerfile
which were built by previous jobs as cache. Fully-cached builds take 5-10
minutes depending on the number of Python versions we want to build for.

docker build -t vosk-api-build:linux-armv7 --build-arg DOCKCROSS_IMAGE=linux-armv7 --build-arg OPENBLAS_TARGET=ARMV7 .

docker build -t vosk-api-build:manylinux2010-x64 --build-arg DOCKCROSS_IMAGE=manylinux2010-x64 --build-arg OPENBLAS_TARGET=NEHALEM .

docker run --rm -v $(pwd):/io vosk-api-build:linux-armv7 /io/travis/build-wheels.sh

docker run --rm -v $(pwd):/io vosk-api-build:manylinux2010-x64 /io/travis/build-wheels.sh

Note on Windows builds

Windows releases are compiled using Visual Studio 15 2017 following the
official guide from the Kaldi project.

Windows builds use Windows VMs provided by Travis CI. Surprisingly,
commands specified in .travis-ci.yml are executed in a Git Bash (MinGW)
shell, so the scripts are implemented in Bash. Like in Linux builds,
the build is broken up into several steps and will cache intermediate
artifacts. So if a Travis CI job fails due to the 50-minute timeout,
restarting the job will pick up artifacts produced by earlier steps
(if they succeeded).

Note on deploying of build artifacts

Uploads whl files to PyPI if the build is for a tagged commit. This is
conditional on TWINE_USERNAME and TWINE_PASSWORD environment variables
being set.

Also creates a draft release on GitHub Releases if GITHUB_TOKEN is set.

The following variables affect the build, and should be defined in your
Travis project settings:

  • DOCKER_REGISTRY: name of your registry on Docker Hub, e.g. alphacep
  • DOCKER_USERNAME: your Docker Hub username
  • DOCKER_PASSWORD: your Docker Hub password
  • GITHUB_TOKEN: (optional) GitHub token authorizing Travis to create Releases in this project
  • TWINE_USERNAME: (optional) your PyPI username
  • TWINE_PASSWORD: (optional) your PyPI password
  • BUILD_OPENFST: (optional, Windows-only) if non-empty, OpenFST will be built *
  • BUILD_KALDI: (optional, Windows-only) if non-empty, Kaldi will be built *
  • REBUILD_OPENFST: (optional, Windows-only) if non-empty, OpenFST will be rebuilt from scratch *
  • REBUILD_KALDI: (optional, Windows-only) if non-empty, Kaldi will be rebuilt from scratch *

(*) even if cache contains artifacts from a successful build

*** Note on Linux builds ***
Python whl packages are cross-compiled for Linux platforms supported
by dockcross [1]. It would be trivial to add more platforms.

* linux-armv6: should work on RPi Zero
* linux-armv7: tested on RPi 3
* manylinux2010-x64: tested on Debian buster

Note that dockcross/windows-shared-x64 doesn't support building openfst
due to certain syscalls not being supported in the MinGW environment.
See Note below about Windows builds.

QEMU is registered as the binfmt handler inside Travis CI Docker host
(dockcross images already come with the qemu binaries in /usr/bin). This
allows the Docker container to run foreign binaries (e.g. x86-64 host becomes
able to run ARM binaries), and is needed for some Autoconf scripts to
work correctly.

Intermediate build stages are pushed to Docker Hub to work around the 50 min
limit imposed by Travis CI on unpaid users. Initial build will likely time
out, but can be restarted in Travis UI and will use the stages in the Dockerfile
which were built by previous jobs as cache. Fully-cached builds take 5-10
minutes depending on the number of Python versions we want to build for.

```
docker build -t vosk-api-build:linux-armv7 --build-arg DOCKCROSS_IMAGE=linux-armv7 --build-arg OPENBLAS_TARGET=ARMV7 .

docker build -t vosk-api-build:manylinux2010-x64 --build-arg DOCKCROSS_IMAGE=manylinux2010-x64 --build-arg OPENBLAS_TARGET=NEHALEM .

docker run --rm -v $(pwd):/io vosk-api-build:linux-armv7 /io/travis/build-wheels.sh

docker run --rm -v $(pwd):/io vosk-api-build:manylinux2010-x64 /io/travis/build-wheels.sh
```

*** Note on Windows builds ***
Windows releases are compiled using Visual Studio 15 2017 following the
official guide [2].

Windows builds use Windows VMs provided by Travis CI [3]. Surprisingly,
commands specified in .travis-ci.yml are executed in a Git Bash (MinGW)
shell, so the scripts are implemented in Bash. Like in Linux builds,
the build is broken up into several steps and will cache intermediate
artifacts. So if a Travis CI job fails due to the 50-minute timeout,
restarting the job will pick up artifacts produced by earlier steps
(if they succeeded).

*** Note on deploying of build artifacts ***
Uploads .whl files to PyPI if the build is for a tagged commit. This is
conditional on TWINE_USERNAME and TWINE_PASSWORD environment variables
being set.

Also creates a draft release on GitHub Releases if $GITHUB_TOKEN is set.

The following variables affect the build, and should be defined in your
Travis project settings:

DOCKER_REGISTRY: name of your registry on Docker Hub, e.g. alphacep
DOCKER_USERNAME: your Docker Hub username
DOCKER_PASSWORD: your Docker Hub password
GITHUB_TOKEN: (optional) GitHub token authorizing Travis to create Releases in this project
TWINE_USERNAME: (optional) your PyPI username
TWINE_PASSWORD: (optional) your PyPI password
BUILD_OPENFST: (optional, Windows-only) if non-empty, OpenFST will be built (4)
BUILD_KALDI: (optional, Windows-only) if non-empty, Kaldi will be built (4)
REBUILD_OPENFST: (optional, Windows-only) if non-empty, OpenFST will be rebuilt from scratch (4)
REBUILD_KALDI: (optional, Windows-only) if non-empty, Kaldi will be rebuilt from scratch (4)

1. https://github.com/dockcross/dockcross
2. https://github.com/kaldi-asr/kaldi/blob/master/windows/INSTALL.md
3. https://docs.travis-ci.com/user/reference/windows/
4. even if cache contains artifacts from a successful build
OPENFST and OPENFSTLIB in windows/variables.props werent getting edited properly
It would be goo to see if it works on Raspberry Pi 4
@nshmyrev
Copy link
Collaborator

Sounds great, thank you! I'll try to deploy it coming days.

Python compilation is broken with:

/usr/xcc/aarch64-unknown-linux-gnueabi/bin/aarch64-unknown-linux-gnueabi-gcc -pthread -fPIC -Wno-unused-result -Wsign-compare -DNDEBUG -g -fwrapv -O3 -Wall -I/usr/xcc/aarch64-unknown-linux-gnueabi/include -I/usr/xcc/aarch64-unknown-linux-gnueabi/include -std=c99 -Wextra -Wno-unused-result -Wno-unused-parameter -Wno-missing-field-initializers -Werror=implicit-function-declaration -IModules/_multiprocessing -I./Include -I. -I/usr/xcc/aarch64-unknown-linux-gnueabi/include -I/usr/include/x86_64-linux-gnu -I/usr/local/include -I/tmp/tmp.JY5YOL4mLZ/cpython-3.7.6/Include -I/tmp/tmp.JY5YOL4mLZ/cpython-3.7.6 -c /tmp/tmp.JY5YOL4mLZ/cpython-3.7.6/Modules/_multiprocessing/multiprocessing.c -o build/temp.linux-aarch64-3.7/tmp/tmp.JY5YOL4mLZ/cpython-3.7.6/Modules/_multiprocessing/multiprocessing.o
In file included from /usr/xcc/aarch64-unknown-linux-gnueabi/aarch64-unknown-linux-gnueabi/sysroot/usr/include/features.h:434:0,
                 from /usr/xcc/aarch64-unknown-linux-gnueabi/aarch64-unknown-linux-gnueabi/sysroot/usr/include/bits/libc-header-start.h:33,
                 from /usr/xcc/aarch64-unknown-linux-gnueabi/aarch64-unknown-linux-gnueabi/sysroot/usr/include/limits.h:26,
                 from /usr/xcc/aarch64-unknown-linux-gnueabi/lib/gcc/aarch64-unknown-linux-gnueabi/4.9.4/include-fixed/limits.h:168,
                 from /usr/xcc/aarch64-unknown-linux-gnueabi/lib/gcc/aarch64-unknown-linux-gnueabi/4.9.4/include-fixed/syslimits.h:7,
                 from /usr/xcc/aarch64-unknown-linux-gnueabi/lib/gcc/aarch64-unknown-linux-gnueabi/4.9.4/include-fixed/limits.h:34,
                 from ./Include/Python.h:11,
                 from /tmp/tmp.JY5YOL4mLZ/cpython-3.7.6/Modules/_multiprocessing/multiprocessing.h:6,
                 from /tmp/tmp.JY5YOL4mLZ/cpython-3.7.6/Modules/_multiprocessing/multiprocessing.c:10:
/usr/include/x86_64-linux-gnu/gnu/stubs.h:7:27: fatal error: gnu/stubs-32.h: No such file or directory
 # include <gnu/stubs-32.h>

Also, Python configure script prints "INFO: Could not locate ffi libs and/or headers"

The libffi install script (which runs before python) prints:

 /usr/bin/install -c -m 644 ffi.h ffitarget.h '/usr/xcc/aarch64-unknown-linux-gnueabi/include'

Libraries have been installed in:
   /usr/xcc/aarch64-unknown-linux-gnueabi/lib/../lib64
@dtreskunov
Copy link
Author

dtreskunov commented Feb 17, 2020 via email

@nshmyrev nshmyrev mentioned this pull request Feb 19, 2020
15 tasks
@nshmyrev
Copy link
Collaborator

nshmyrev commented Feb 19, 2020

Hi

Ok, I reviewed, thanks a lot for such a titanic work on making things working. I prefer we do this way:

  1. linux build - use manylinux-based docker with prebuilt kaldi, only build python in travis, like we are doing now
  2. armv6/v7 build - use dockcross-based docker with prebuilt kaldi just like above
  3. win64 - use prebuilt dlls hosted on our server and only build a python module like above
  4. No need to github/pypi provision yet, I want to do it slightly different with secret keys instead of environment variables, it could be a separate patch

Please let me know what do you think on this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

2 participants