From a7bfe0621a108b8ab38b76e76be0617ad3dcbd33 Mon Sep 17 00:00:00 2001 From: Amin Solhizadeh Date: Sun, 25 Oct 2026 11:20:18 +0100 Subject: [PATCH 1/4] Build lxml from source for cp315 on manylinux2014 lxml 6.1.3 ships no cp315 manylinux2014_x86_64 wheel, so pip falls back to the sdist, which fails without libxml2/libxslt dev packages. For this combination only, build lxml with STATIC_DEPS using the same libxml2 and libxslt versions xmlsec links. Remove once lxml publishes the wheel. --- .github/scripts/manylinux_build_and_test.sh | 11 +++++++++++ .github/workflows/manylinux.yml | 2 ++ 2 files changed, 13 insertions(+) diff --git a/.github/scripts/manylinux_build_and_test.sh b/.github/scripts/manylinux_build_and_test.sh index ce8301a..f2b9ad1 100644 --- a/.github/scripts/manylinux_build_and_test.sh +++ b/.github/scripts/manylinux_build_and_test.sh @@ -26,6 +26,17 @@ case "$MANYLINUX_IMAGE" in ;; esac +# Step: Build lxml from source with static deps (temporary) +# TODO: remove once lxml publishes cp315 manylinux2014_x86_64 wheels. +echo "== [container] Step: Configure lxml static build (cp315 manylinux2014 only) ==" +case "$PY_ABI/$MANYLINUX_IMAGE" in + cp315-*/manylinux2014_*) + export STATIC_DEPS=true + export LIBXML2_VERSION="${LIBXML2_VERSION:?}" LIBXSLT_VERSION="${LIBXSLT_VERSION:?}" + echo "STATIC_DEPS=$STATIC_DEPS LIBXML2_VERSION=$LIBXML2_VERSION LIBXSLT_VERSION=$LIBXSLT_VERSION" + ;; +esac + # Step: Install python build dependencies echo "== [container] Step: Install python build dependencies ==" /opt/python/${PY_ABI}/bin/pip install --upgrade pip setuptools wheel build 'setuptools_scm>=8' diff --git a/.github/workflows/manylinux.yml b/.github/workflows/manylinux.yml index 52619c6..d1138b1 100644 --- a/.github/workflows/manylinux.yml +++ b/.github/workflows/manylinux.yml @@ -61,6 +61,8 @@ jobs: -e PYXMLSEC_STATIC_DEPS \ -e PY_ABI \ -e MANYLINUX_IMAGE \ + -e LIBXML2_VERSION \ + -e LIBXSLT_VERSION \ -e HOST_UID="$(id -u)" \ -e HOST_GID="$(id -g)" \ "quay.io/pypa/${MANYLINUX_IMAGE}" \ From b08a0f0a52378c10ffdedd9e7376655897905c51 Mon Sep 17 00:00:00 2001 From: Amin Solhizadeh Date: Sun, 25 Oct 2026 11:28:42 +0100 Subject: [PATCH 2/4] Run push-triggered CI only on master Every workflow ran on both push and pull_request, so each push to a branch with an open PR started every workflow twice. The concurrency group is keyed on github.ref, which differs between the two events (refs/heads/ vs refs/pull//merge), so the duplicates never cancelled each other. Restricting push to master leaves PR branches covered by pull_request alone. --- .github/workflows/linuxbrew.yml | 5 ++++- .github/workflows/macosx.yml | 5 ++++- .github/workflows/manylinux.yml | 5 ++++- .github/workflows/sdist.yml | 5 ++++- .github/workflows/wheels.yml | 1 + 5 files changed, 17 insertions(+), 4 deletions(-) diff --git a/.github/workflows/linuxbrew.yml b/.github/workflows/linuxbrew.yml index 4f48bef..5bdacd0 100644 --- a/.github/workflows/linuxbrew.yml +++ b/.github/workflows/linuxbrew.yml @@ -1,5 +1,8 @@ name: linuxbrew -on: [push, pull_request] +on: + push: + branches: [master] + pull_request: concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: ${{ github.ref_name != 'master' }} diff --git a/.github/workflows/macosx.yml b/.github/workflows/macosx.yml index 503a029..43cbb56 100644 --- a/.github/workflows/macosx.yml +++ b/.github/workflows/macosx.yml @@ -1,5 +1,8 @@ name: macOS -on: [push, pull_request] +on: + push: + branches: [master] + pull_request: concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: ${{ github.ref_name != 'master' }} diff --git a/.github/workflows/manylinux.yml b/.github/workflows/manylinux.yml index d1138b1..36bd2ac 100644 --- a/.github/workflows/manylinux.yml +++ b/.github/workflows/manylinux.yml @@ -1,5 +1,8 @@ name: manylinux -on: [push, pull_request] +on: + push: + branches: [master] + pull_request: concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: ${{ github.ref_name != 'master' }} diff --git a/.github/workflows/sdist.yml b/.github/workflows/sdist.yml index e20c45a..cf2284b 100644 --- a/.github/workflows/sdist.yml +++ b/.github/workflows/sdist.yml @@ -1,5 +1,8 @@ name: sdist -on: [push, pull_request] +on: + push: + branches: [master] + pull_request: concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: ${{ github.ref_name != 'master' }} diff --git a/.github/workflows/wheels.yml b/.github/workflows/wheels.yml index a9a2750..b4a1177 100644 --- a/.github/workflows/wheels.yml +++ b/.github/workflows/wheels.yml @@ -12,6 +12,7 @@ on: # │ │ │ │ │ - cron: "42 3 * * 4" push: + branches: [master] pull_request: workflow_dispatch: From 73c87fbb4fdf17af71a3439250df9952086674f6 Mon Sep 17 00:00:00 2001 From: Amin Solhizadeh Date: Sun, 25 Oct 2026 20:50:15 +0100 Subject: [PATCH 3/4] Use GNU make 4.2 on manylinux2014 libiconv 1.19's po/Makefile uses the '!=' shell assignment, which needs GNU make >= 4.0. CentOS 7 ships make 3.82, so all manylinux2014 builds fail with 'missing separator'. Install devtoolset-10-make, which is already first on the image's PATH. --- .github/scripts/manylinux_build_and_test.sh | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.github/scripts/manylinux_build_and_test.sh b/.github/scripts/manylinux_build_and_test.sh index f2b9ad1..273df3f 100644 --- a/.github/scripts/manylinux_build_and_test.sh +++ b/.github/scripts/manylinux_build_and_test.sh @@ -25,6 +25,13 @@ case "$MANYLINUX_IMAGE" in yum install -y perl-core ;; esac +# libiconv >= 1.19 needs GNU make >= 4.0 (po/Makefile uses '!='); CentOS 7 ships 3.82. +case "$MANYLINUX_IMAGE" in + manylinux2014_*) + yum install -y devtoolset-10-make + make --version | head -n 1 + ;; +esac # Step: Build lxml from source with static deps (temporary) # TODO: remove once lxml publishes cp315 manylinux2014_x86_64 wheels. From 6effd5d4ec38eaca28ae36dcd6df2965f17dcbee Mon Sep 17 00:00:00 2001 From: Amin Solhizadeh Date: Sun, 25 Oct 2026 21:46:08 +0100 Subject: [PATCH 4/4] Build lxml static deps with -fPIC for cp315 on manylinux2014 lxml's static build doesn't add -fPIC on Linux, so linking the static libiconv/libxslt into the etree extension fails with R_X86_64_32 relocation errors. --- .github/scripts/manylinux_build_and_test.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/scripts/manylinux_build_and_test.sh b/.github/scripts/manylinux_build_and_test.sh index 273df3f..caedc5e 100644 --- a/.github/scripts/manylinux_build_and_test.sh +++ b/.github/scripts/manylinux_build_and_test.sh @@ -40,7 +40,9 @@ case "$PY_ABI/$MANYLINUX_IMAGE" in cp315-*/manylinux2014_*) export STATIC_DEPS=true export LIBXML2_VERSION="${LIBXML2_VERSION:?}" LIBXSLT_VERSION="${LIBXSLT_VERSION:?}" - echo "STATIC_DEPS=$STATIC_DEPS LIBXML2_VERSION=$LIBXML2_VERSION LIBXSLT_VERSION=$LIBXSLT_VERSION" + # lxml links its static deps into a shared extension, so they need -fPIC. + export CFLAGS="${CFLAGS:+$CFLAGS }-fPIC" + echo "STATIC_DEPS=$STATIC_DEPS LIBXML2_VERSION=$LIBXML2_VERSION LIBXSLT_VERSION=$LIBXSLT_VERSION CFLAGS=$CFLAGS" ;; esac