Skip to content

Upgrade 4.0.X, it failed in ubuntu-latest #77

Closed

Description

@Freed-Wu

4.0.X failed
3.X.Y works

Activity

  1. elijahr commented on Oct 21, 2026

    @elijahr
    Owner

    Hi @Freed-Wu,

    Thanks for reporting this!

    Root Cause

    In your GitHub Actions workflow run 39543153124, although the job runs on an ubuntu-latest runner host, pyrime’s pyproject.toml skips manylinux wheels:

    [tool.cibuildwheel]
    skip = "*37-* *38-* *39-* *310-* cp314t-macosx_* *_universal2 *-macosx_x86_64 *-win* *-manylinux_*"

    As a result, cibuildwheel builds wheels inside an Alpine Linux container (musllinux_1_2_x86_64).

    • In autopxd2 3.x, the parser was pycparser, which was pure Python and had no external C library dependencies.
    • In autopxd2 4.0.x, autopxd2 migrated to headerkit. The default backend is libclang, which requires the system libclang.so shared library.
    • In your Alpine container, before-all only installed apk add librime-dev. Because neither libclang.so was installed nor the optional autopxd2[treesitter] extra was present in the isolated build environment, autopxd exited with status 1 because no parser backend was available.

    How to Fix

    You have two options depending on which backend you prefer:

    Option 1 (recommended): Install clang-dev in the musllinux container (Recommended for full libclang support)

    In pyrime's pyproject.toml, update the musllinux cibuildwheel override to install clang-dev:

    [[tool.cibuildwheel.overrides]]
    select = ["*-musllinux_*"]
    before-all = "apk add librime-dev clang-dev"

    Option 2: Use the tree-sitter backend (No LLVM / system package required)

    rime_api.h parses cleanly with Tree-sitter without requiring system Clang libraries. Note that Tree-sitter operates only on the single input file (it does not follow #include directives or extract #define macros). To use it in headless builds:

    1. In pyrime's pyproject.toml, request the treesitter extra:

      [build-system]
      requires = ['meson-python', 'cython', 'autopxd2[treesitter] != 3.0.*, !=3.1.*']
      build-backend = 'mesonpy'
    2. In src/pyrime/meson.build, pass --backend tree-sitter:

      configure_file(
        command: ['autopxd', '--backend', 'tree-sitter', header_path, 'rime_api.pxd'],
        output: 'rime_api.pxd',
      )

    We have also released autopxd2 v4.0.2, which includes:

    • Clearer CLI error messages listing platform package manager commands (including Alpine apk add clang-dev) and explaining the Tree-sitter fallback and its limitations.
    • Comprehensive documentation for headless CI & build containers (cibuildwheel, Docker) and system package managers.
  2. Freed-Wu commented on Oct 21, 2026

    @Freed-Wu
    Author

    https://github.com/rimeinn/pyrime/actions/runs/39602387878/job/119229879488

    After apk add clang-dev, it still failed in:

    [1](https://github.com/rimeinn/pyrime/actions/runs/39602387878/job/119229879488#step:5:5159)
        * Installing packages in isolated environment:
          - autopxd2 != 3.0.*, !=3.1.*
          - cython
          - meson-python
        * Getting build dependencies for wheel...
        * Installing packages in isolated environment:
          - ninja >= 1.8.2
        * Building wheel...
        + meson setup /project /project/.mesonpy-01q5ove8 -Dbuildtype=release -Db_ndebug=if-release -Db_vscrt=md --native-file=/project/.mesonpy-01q5ove8/meson-python-native-file.ini
        The Meson build system
        Version: 1.12.1
        Source dir: /project
        Build dir: /project/.mesonpy-01q5ove8
        Build type: native build
        Project name: pyrime
        Project version: 0.2.4
        C compiler for the host machine: cc (gcc 14.2.0 "cc (Alpine 14.2.0) 14.2.0")
        C linker for the host machine: cc ld.bfd 2.44
        Cython compiler for the host machine: cython (cython 3.3.0)
        Host machine cpu family: s390x
        Host machine cpu: s390x
        Run-time dependency rime found: YES 1.13.1
        Program python found: YES (/tmp/build-env-924x4xil/bin/python)
        Configuring rime_api.pxd with command
        Found pkg-config: YES (/usr/bin/pkg-config) 2.4.3
        Run-time dependency python found: YES 3.11
        Configuring __init__.py using configuration
        Build targets in project: 1
        
        pyrime 0.2.4
        
          User defined options
            Native files: /project/.mesonpy-01q5ove8/meson-python-native-file.ini
            b_ndebug    : if-release
            b_vscrt     : md
            buildtype   : release
        
        Found ninja-1.13.2.git.kitware.jobserver-pipe-1 at /tmp/build-env-924x4xil/bin/ninja
        + /tmp/build-env-924x4xil/bin/ninja
        [1/3] Compiling Cython source /project/.mesonpy-01q5ove8/src/pyrime/api.pyx
        FAILED: [code=1] src/pyrime/api.cpython-311-s390x-linux-musl.so.p/api.pyx.c 
        cython -M --fast-fail -3 -3I/project/.mesonpy-01q5ove8/src/pyrime /project/.mesonpy-01q5ove8/src/pyrime/api.pyx -o src/pyrime/api.cpython-311-s390x-linux-musl.so.p/api.pyx.c
        
        Error compiling Cython file:
        ------------------------------------------------------------
        ...
        import os
        from dataclasses import dataclass
        
        import cython as c
        from cython.cimports.cpython.long import PyLong_AsVoidPtr, PyLong_FromVoidPtr
        from cython.cimports.rime_api import (
        ^
        ------------------------------------------------------------
        src/pyrime/api.pyx:12:0: 'rime_api/RimeApi.pxd' not found
        ninja: build stopped: subcommand failed.
        
        ERROR Backend subprocess exited when trying to invoke build_wheel
    

    In autopxd2 3.x, the parser was pycparser, which was pure Python and had no external C library dependencies.

    Why not keep original autopxd depending on pycparser?

    • if someone want clang/tree-sitter, they can use headerkit XXX.h -wcython
    • if someone want no external C library dependencies, they can use autopxd

    Now autopxd is same as headerkit, which means we don't have any reason not to switch headerkit and give up this project.

  3. elijahr commented on Oct 21, 2026

    @elijahr
    Owner

    Hi @Freed-Wu,

    A quick clarification on the CI run: apk add clang-dev actually did work on Alpine musl! In that run (39602387878), 20 out of 21 wheel builds succeeded (all x86_64, i686, aarch64, and ppc64le builds across Python 3.11–3.14 passed).

    The single failure was on s390x (IBM System/390 Big-Endian architecture running under QEMU software emulation on GitHub Actions). I can look into what is going on with that architecture at some point soon - perhaps some difference in the clang toolchain or capabilities available for that distro on that architecture.

    Regarding autopxd <= 3.x vs autopxd now:

    • autopxd <= 3.x used pycparser, but pycparser cannot parse real system libc headers (it required bundling a fake_libc_include stub directory) and has no support for C++. Additionally, autopxd still had to invoke an external preprocessor (gcc -E or cpp on PATH) to expand macros and resolve includes before feeding source to pycparser. There were often subtle differences in what pycparser could parse and what clang or gcc could parse, and many library headers simply failed to work with that version of autopxd. The project was a pain to maintain.
    • I wanted to breathe new life into the project. After researching better solutions, libclang was the winner because it provides excellent structured output, can parse more dialects, and is the actual compiler many projects use so compatibility is not an issue. This was essentially going to be a rewrite. Since a lot of the work in writing that new tool would not be specific to output of .pxd files, I decided to make it more general-purpose - and that became headerkit. I also wanted to decouple it from libclang, so it supports pluggable backends. The tree-sitter backend exists primarily as a proof of concept for headerkit's backend pluggability, but is also a perfectly useful alternative to the clang backend in many use cases.

    rime_api.h specifically wraps typedefs in a preprocessor macro (RIME_FLAVORED(RimeApi)) so a real C preprocessor of some sort would be required to expand RIME_FLAVORED into RimeApi regardless of using autopxd <= 3 or current autopxd.

    If you prefer to invoke headerkit directly instead of autopxd2, that is fully supported, as autopxd2 wraps the more general purpose headerkit tool, but the autopxd project now is intended to provide some degree of backwards compatibility for users who are already using autopxd in their projects. And of course versions of autopxd <= 3.0 are still available on pypi and in the git tree - those versions are just unlikely to receive any bugfixes since that was difficult to maintain and focus is on supporting the headerkit integration which is easier to maintain and more useful.

  4. Freed-Wu commented on Oct 21, 2026

    @Freed-Wu
    Author

    I agree pycparser has many disadvantages and will switch to headerkit, however, I still hope we can have a different alternative unrelated to headerkit:

    for new users who are glad to use headerkit

    let them switch to headerkit from autopxd directly, which will reduce troublesome such as bug belonging to headerkit be reported to incorrect repo (autopxd)

    provide some degree of backwards compatibility

    I think let user switch to headerkit is enough. not need to break original autopxd.

    for old users who are insist on using autopxd2

    those versions are just unlikely to receive any bugfixes

    if someone want to use it, they can take over it, not create a new fork named autopxd3.

    Now autopxd is same as headerkit, which defeats the purpose of its existence.

    for packagers of many Linux distributions

    don't need to rewrite the package scripts of autopxd2, which will reduce the maintenance cost:

    Now autopxd 4.0 introduce breaking changes, we must create two packages named autopxd2_3 and autopxd2 (latest version), like

    for the maintainer of headerkit

    headerkit is a new project, shouldn't be mixed with autopxd based on pycparser, which will occupy its honor.

  5. elijahr commented on Oct 21, 2026

    @elijahr
    Owner

    if someone want to use it, they can take over it, not create a new fork named autopxd3.

    I understand where you're coming from, especially from the perspective of a Linux distribution packager. Major architectural shifts are always an inconvenience for downstream packaging scripts and multi-architecture builds.

    However, keeping autopxd2 alive on pycparser was simply no longer viable for me as a maintainer. This project had already been abandoned twice in its history—first by the original author around 2016, and later by the second maintainer—before being transferred to me in 2022. Nobody wanted to maintain the existing codebase because, frankly, it had many structural issues: subtle parsing bugs, inability to parse real libc headers or C++, and fragile bundled fake_libc_include workarounds. Rather than abandon it a third time, I decided to breathe new life into the project by giving it a modern foundation.

    That is why this was released as a major version bump (4.0.0). Under Semantic Versioning, major version increments exist specifically to communicate breaking changes and architectural shifts.

    For projects, Linux distributions, or environments that specifically require the old pure-Python pycparser implementation without libclang or tree-sitter dependencies:

    • autopxd2 < 4.0.0 remains permanently available on PyPI and in git tags.
    • Distro packages and build scripts that rely on the legacy behavior should simply pin autopxd2 < 4.0.0 (or package autopxd2_3 if both need to coexist, as is standard practice for major version breaks).
    • If community members wish to maintain a 3.x-lts backport branch in this repository for critical fixes, I am totally open to that. Nobody has been contributing to this project much—I am the sole contributor since December 2024.

    Going forward, autopxd2 >= 4.0 continues to serve as a dedicated, focused tool for generating Cython .pxd headers—just now backed by a modern engine. Calling headerkit directly is simply a more direct alternative if you want to bypass the autopxd CLI layer or need its broader multi-language capabilities.

    I appreciate you taking the time to report the NixOS and external path issues in HeaderKit and I am very happy to continue working through those so it works seamlessly in NixOS and across your downstream packages.

  6. elijahr commented on Oct 21, 2026

    @elijahr
    Owner

    FYI, headerkit 0.47.2 is now live on PyPI with a fix for the s390x / 64-bit big-endian libclang AST traversal callback issue (CPython issue gh-156933) that caused the musllinux_s390x build failure in pyrime's cibuildwheel run. Since autopxd2 depends on headerkit>=0.46.2, any fresh install will automatically pick up this fix.

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions