Skip to content

Commit

Permalink
build: 📦 fix macos build, update manylinux images
Browse files Browse the repository at this point in the history
  • Loading branch information
darvid committed Aug 7, 2023
1 parent d8016c9 commit 4ee4e0d
Show file tree
Hide file tree
Showing 10 changed files with 177 additions and 87 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ jobs:

- name: Install dependencies
run: |
pip install pytest ruff black
pip install pytest ruff black
- name: Format with clang-format
uses: DoozyX/clang-format-lint-action@v0.11
Expand Down
46 changes: 46 additions & 0 deletions .github/workflows/wheels.yml
Original file line number Diff line number Diff line change
Expand Up @@ -87,23 +87,69 @@ jobs:
- name: Checkout python-hyperscan
uses: actions/checkout@v3

- name: Restore build artifacts cache
id: cache-dist
uses: actions/cache@v3
with:
key: ${{ runner.os }}-cp${{ matrix.python_id }}-${{ matrix.platform_id }}-${{ hashFiles('./src') }}
path: |
dist/*.tar.gz
wheelhouse/*.whl
- uses: pdm-project/setup-pdm@v3
if: steps.cache-dist.outputs.cache-hit != 'true'
with:
python-version: ${{ matrix.python }}
cache: true

- name: Cache build dependencies (macOS)
id: build-deps-macos
if: matrix.os == 'macos-latest' && steps.cache-dist.outputs.cache-hit != 'true'
uses: actions/cache@v3
with:
key: build-deps-${{ runner.os }}-${{ matrix.platform_id }}
path: |
/opt/hyperscan
/opt/pcre
- name: Build Hyperscan (macOS)
if: matrix.os == 'macos-latest' && steps.cache-dist.outputs.cache-hit != 'true'
run: |
./build_tools/macos/build_hyperscan.sh
env:
HYPERSCAN_VERSION: "v5.4.2"

- name: Upload build dependencies (macOS)
if: matrix.os == 'macos-latest' && steps.build-deps-macos.outputs.cache-hit != 'true'
uses: actions/cache/save@v3
with:
key: ${{ steps.build-deps-macos.outputs.cache-primary-key }}
path: |
/opt/hyperscan
/opt/pcre
- name: Build source distribution
if: steps.cache-dist.outputs.cache-hit != 'true'
run: |
pdm install -G build -G release --no-self --no-lock -v
pdm run semantic-release version
pdm build --no-wheel -v
- name: Build and test wheels
if: steps.cache-dist.outputs.cache-hit != 'true'
env:
CIBW_BUILD: cp${{ matrix.python_id }}-${{ matrix.platform_id }}
CIBW_BUILD_VERBOSITY: 1
run: bash ./build_tools/wheels/build_wheels.sh

- name: Cache build artifacts
uses: actions/cache/save@v3
with:
key: ${{ steps.cache-dist.outputs.cache-primary-key }}
path: |
dist/*.tar.gz
wheelhouse/*.whl
- name: Store artifacts
uses: actions/upload-artifact@v3
with:
Expand Down
38 changes: 38 additions & 0 deletions build_tools/macos/build_hyperscan.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
#!/bin/bash
PCRE_VERSION=${PCRE_VERSION:-8.45}

if pkg-config --validate libhs; then
echo "✅ libhs found, nothing to do"
exit 0
fi

if [ -z "$HYPERSCAN_VERSION" ]; then
>&2 echo "HYPERSCAN_VERSION must be set"
exit 1
fi

cd /tmp
git clone -b "${HYPERSCAN_VERSION}" https://github.com/01org/hyperscan.git
brew install boost cmake git pkg-config python@3.11 ragel wget
cd hyperscan

# build and install PCRE (static required for Chimera)
wget -qO- https://sourceforge.net/projects/pcre/files/pcre/${PCRE_VERSION}/pcre-${PCRE_VERSION}.tar.gz/download | tar xvz
cd "pcre-${PCRE_VERSION}"
./configure --prefix=/opt/pcre --enable-unicode-properties --enable-utf
nproc=$(sysctl -n hw.logicalcpu)
make -j${nproc} && sudo make install

# build and install Hyperscan
cd /tmp/hyperscan
cmake \
-B build \
-S . \
-DCMAKE_INSTALL_PREFIX=/opt/hyperscan \
-DBUILD_STATIC_AND_SHARED=ON \
-DCMAKE_BUILD_TYPE=${HYPERSCAN_BUILD_TYPE} \
-DPCRE_SOURCE=/tmp/hyperscan/pcre-${PCRE_VERSION} \
-DCMAKE_C_FLAGS="-fPIC" \
-DCMAKE_CXX_FLAGS="$CFLAGS -D_GLIBCXX_USE_CXX11_ABI=0"
cmake --build build --parallel ${nproc}
sudo cmake --install build
7 changes: 5 additions & 2 deletions build_tools/wheels/before_test.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
#!/bin/bash
set -euxo pipefail

export PDM_HOME=${PDM_HOME:-/tmp/pdm}
export PDM_SKIP_ADD_TO_PATH=${PDM_SKIP_ADD_TO_PATH:-true}
export PATH="${PDM_HOME}/bin:${PATH}"
curl -sSL https://pdm.fming.dev/install-pdm.py | python -
export PATH=/root/.local/bin:$PATH
pdm install -g --no-self --no-lock -p /project -G test
pdm export -G test -f requirements -o test_requirements.txt
pip install -r test_requirements.txt
28 changes: 3 additions & 25 deletions build_tools/wheels/build_wheels.sh
Original file line number Diff line number Diff line change
Expand Up @@ -8,31 +8,9 @@ PCRE_VERSION="${PCRE_VERSION:-8.45}"

if [[ $(uname) == "Darwin" ]]; then
export MACOSX_DEPLOYMENT_TARGET="10.14"
mkdir -p /tmp/hyperscan
cd /tmp/hyperscan
brew install boost cmake git pkg-config python@3.11 ragel wget
wget -qO- https://sourceforge.net/projects/pcre/files/pcre/${PCRE_VERSION}/pcre-${PCRE_VERSION}.tar.gz/download | tar xvz
cd "pcre-${PCRE_VERSION}"
./configure --prefix=/usr/local --enable-unicode-properties --enable-utf
nproc=$(sysctl -n hw.logicalcpu)
make -j${nproc} && make install

cd /tmp
mkdir -p build
git clone -b ${HYPERSCAN_VERSION} https://github.com/01org/hyperscan.git
export CFLAGS="-fPIC"
export CXXFLAGS="$CFLAGS -D_GLIBCXX_USE_CXX11_ABI=0"
cd hyperscan/build
cmake \
-DCMAKE_INSTALL_PREFIX=/opt/hyperscan \
-DFAT_RUNTIME=ON \
-DBUILD_STATIC_AND_SHARED=ON \
-DCMAKE_BUILD_TYPE=${HYPERSCAN_BUILD_TYPE} \
-DPCRE_SOURCE=../pcre2-${PCRE_VERSION} \
-DCMAKE_C_FLAGS="${CFLAGS}" \
-DCMAKE_CXX_FLAGS="${CXXFLAGS}" \
../
make -j${nproc} && make install
export LD_LIBRARY_PATH="${LD_LIBRARY_PATH:-/usr/local/lib}"
export PCRE_PATH="${PCRE_PATH:-/tmp/hyperscan/pcre-${PCRE_VERSION}/.libs}"
fi

cd "${GITHUB_WORKSPACE}"
pdm run cibuildwheel --output-dir wheelhouse
4 changes: 3 additions & 1 deletion build_tools/wheels/test_wheels.sh
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
#!/bin/bash
set -euxo pipefail

# Tests in cibuildwheel are NOT run in the project directory by default
PROJECT_DIR=${1:-/project}

XDIST_WORKERS=$(python -c "import joblib; print(joblib.cpu_count(only_physical_cores=True))")
echo "👷 Number of workers: $XDIST_WORKERS"
pip show hyperscan
pytest --pyargs "${PROJECT_DIR}/tests/" -n $XDIST_WORKERS -vvv
pytest --pyargs "${PROJECT_DIR}/tests" -n $XDIST_WORKERS -vvv
10 changes: 10 additions & 0 deletions build_tools/windows/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
ARG PYTHON_VERSION
FROM winamd64/python:$PYTHON_VERSION-windowsservercore

ARG WHEEL_NAME
ARG CONFTEST_NAME
ARG CIBW_TEST_REQUIRES

COPY $WHEEL_NAME $WHEEL_NAME
RUN pip install $env:WHEEL_NAME
RUN pip install $env:CIBW_TEST_REQUIRES.split(" ")
35 changes: 0 additions & 35 deletions pdm_build.py

This file was deleted.

20 changes: 16 additions & 4 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,14 +32,26 @@ src = ["hyperscan", "tests"]
known-first-party = ["hyperscan"]

[tool.cibuildwheel]
test-command = "bash {project}/build_tools/wheels/test_wheels.sh"
test-command = "bash {project}/build_tools/wheels/test_wheels.sh {project}"
before-test = "bash {project}/build_tools/wheels/before_test.sh"
# Will avoid testing on emulated architectures and macOS Apple silicon
test-skip = "*-*linux_{aarch64,ppc64le,s390x} *-macosx_arm64"

manylinux-x86_64-image = "ghcr.io/darvid/python_hyperscan_manylinux2014_x86_64:2023-08-04-14254a5"
manylinux-pypy_x86_64-image = "ghcr.io/darvid/python_hyperscan_manylinux2014_x86_64:2023-08-04-14254a5"
musllinux-x86_64-image = "ghcr.io/darvid/python_hyperscan_musllinux_1_1_x86_64:2023-08-04-14254a5"
manylinux-x86_64-image = "ghcr.io/darvid/python_hyperscan_manylinux2014_x86_64:2023-08-06-a7d76aa"
manylinux-pypy_x86_64-image = "ghcr.io/darvid/python_hyperscan_manylinux2014_x86_64:2023-08-06-a7d76aa"
musllinux-x86_64-image = "ghcr.io/darvid/python_hyperscan_musllinux_1_1_x86_64:2023-08-06-a7d76aa"

[tool.cibuildwheel.linux.environment]
LD_LIBRARY_PATH = "/opt/hyperscan/lib:/opt/hyperscan/lib64"
LIBRARY_PATH = "/opt/hyperscan/lib:/opt/hyperscan/lib64"
PCRE_PATH = "/opt/pcre/.libs"

[tool.cibuildwheel.macos.environment]
LD_LIBRARY_PATH = "/opt/hyperscan/lib:/usr/local/lib"
LIBRARY_PATH = "/opt/hyperscan/lib:/usr/local/lib"
DYLD_LIBRARY_PATH = "/opt/hyperscan/lib:/usr/local/lib"
PKG_CONFIG_PATH = "/opt/hyperscan/lib/pkgconfig:/opt/pcre/lib/pkgconfig:/usr/local/lib/pkgconfig:$PKG_CONFIG_PATH"
PDM_HOME = "/tmp/pdm"

[tool.semantic_release]
build_command = false
Expand Down
74 changes: 55 additions & 19 deletions setup.py
Original file line number Diff line number Diff line change
@@ -1,26 +1,62 @@
import glob
import os
import os.path
import subprocess
import sys
from distutils.sysconfig import get_python_inc

from setuptools import Extension, setup

pcre_path = os.getenv("PCRE_PATH", "/opt/pcre/.libs")
hs_cflags = subprocess.getoutput("pkg-config --cflags libhs").strip()

hyperscan_ext = Extension(
"hyperscan._ext",
sources=["src/hyperscan/hyperscanmodule.c"],
include_dirs=[hs_cflags[2:], get_python_inc(plat_specific=1)],
libraries=["hs", ":libchimera.a", "m", "stdc++"],
library_dirs=["/opt/hyperscan/lib64", "/usr/lib/x86_64-linux-gnu"],
extra_compile_args=["-O0", "-DPCRE_STATIC"],
extra_link_args=["-l:libhs.a", "-l:libchimera.a"],
extra_objects=[
os.path.join(pcre_path, "libpcre.a"),
*glob.glob(os.path.join(pcre_path, '*.o')),
],
)


setup(ext_modules=[hyperscan_ext])

def _pkgconfig(args):
return subprocess.getoutput(f"pkg-config {args}").strip()


def _pkgconfig_get_cflags(lib):
return _pkgconfig(f"--cflags {lib}")


def _pkgconfig_get_libdir(lib):
return _pkgconfig(f"--variable=libdir {lib}")


def get_platform_specific_options():
if sys.platform == "win32":
raise RuntimeError("win32 not currently supported")

hs_cflags = _pkgconfig_get_cflags("libhs")
pcre_libdir = _pkgconfig_get_libdir("libpcre")
hs_libdir = _pkgconfig_get_libdir("libhs")
pcre_static_libs = [
os.path.join(pcre_libdir, "libpcre.a"),
*glob.glob(os.path.join(pcre_libdir, '*.o')),
]
ext_kwargs = {
"extra_objects": pcre_static_libs,
"include_dirs": [hs_cflags[2:], get_python_inc(plat_specific=1)],
"libraries": ["m", "stdc++"],
}

hs_static_libs = [
os.path.join(hs_libdir, lib) for lib in ["libhs.a", "libchimera.a"]
]

ext_kwargs["extra_objects"] = [
*hs_static_libs,
*ext_kwargs["extra_objects"],
]
return ext_kwargs


if __name__ == "__main__":
setup(
ext_modules=[
Extension(
"hyperscan._ext",
sources=["src/hyperscan/hyperscanmodule.c"],
library_dirs=os.getenv("LIBRARY_PATH", "").split(":"),
extra_compile_args=["-O0", "-DPCRE_STATIC"],
**get_platform_specific_options(),
)
]
)

0 comments on commit 4ee4e0d

Please sign in to comment.