From 9b3cf0bee4726430a19ffa08a6b61bda7a989034 Mon Sep 17 00:00:00 2001 From: Carlos Zoido Date: Thu, 11 Jun 2026 14:03:14 +0200 Subject: [PATCH 01/31] migrate build system from setuptools to conan-py-build --- .github/workflows/wheels.yml | 3 +- .gitignore | 1 - CMakeLists.txt | 66 +++++++++ _custom_build/backend.py | 29 ---- buildutils/__init__.py | 0 buildutils/build.py | 87 ------------ buildutils/bundle.py | 96 ------------- capnp/version.py | 9 ++ conan-build.profile | 5 + conanfile.py | 23 ++++ pyproject.toml | 48 ++++++- setup.cfg | 3 - setup.py | 258 ----------------------------------- 13 files changed, 150 insertions(+), 478 deletions(-) create mode 100644 CMakeLists.txt delete mode 100644 _custom_build/backend.py delete mode 100644 buildutils/__init__.py delete mode 100644 buildutils/build.py delete mode 100644 buildutils/bundle.py create mode 100644 capnp/version.py create mode 100644 conan-build.profile create mode 100644 conanfile.py delete mode 100644 setup.cfg delete mode 100644 setup.py diff --git a/.github/workflows/wheels.yml b/.github/workflows/wheels.yml index 093d2e28f..ff72dd9cc 100644 --- a/.github/workflows/wheels.yml +++ b/.github/workflows/wheels.yml @@ -48,6 +48,7 @@ jobs: CIBW_SKIP: "cp38-*" CIBW_TEST_REQUIRES: pytest pytest-asyncio CIBW_TEST_COMMAND: pytest {project} + CIBW_BEFORE_ALL_LINUX: "yum install -y m4 autoconf automake libtool" # Force libcapnp to build for the target arch on macOS (the runner # is arm64, so without this an x86_64 wheel ends up linking against # an arm64 libkj/libcapnp and failing to load at test time). @@ -62,7 +63,7 @@ jobs: # on release tags rather than every push/PR. build_wheels_exotic: name: Build wheels (exotic) ${{ matrix.arch }} - if: startsWith(github.ref, 'refs/tags/v') + if: startsWith(github.ref, 'refs/tags/v') || github.ref == 'refs/heads/conan-py-build' runs-on: ubuntu-latest strategy: fail-fast: false diff --git a/.gitignore b/.gitignore index 428343efe..d692ce664 100644 --- a/.gitignore +++ b/.gitignore @@ -40,7 +40,6 @@ nosetests.xml # Cpp files capnp/*.cpp -capnp/version.py MANIFEST docs/_build diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 000000000..d9d883bc1 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,66 @@ +cmake_minimum_required(VERSION 3.15) +project(pycapnp LANGUAGES CXX) + +find_package(Python3 REQUIRED COMPONENTS Interpreter Development.Module) +find_package(CapnProto REQUIRED) + +set(CAPNP_PYX "${CMAKE_SOURCE_DIR}/capnp/lib/capnp.pyx") +set(CAPNP_CPP "${CMAKE_CURRENT_BINARY_DIR}/capnp/lib/capnp.cpp") + +file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/capnp/lib") + +add_custom_command( + OUTPUT "${CAPNP_CPP}" + COMMAND "${Python3_EXECUTABLE}" -m cython + --cplus + -I "${CMAKE_SOURCE_DIR}" + "${CAPNP_PYX}" + -o "${CAPNP_CPP}" + DEPENDS "${CAPNP_PYX}" + "${CMAKE_SOURCE_DIR}/capnp/includes/capnp_cpp.pxd" + "${CMAKE_SOURCE_DIR}/capnp/includes/schema_cpp.pxd" + "${CMAKE_SOURCE_DIR}/capnp/helpers/helpers.pxd" + "${CMAKE_SOURCE_DIR}/capnp/lib/capnp.pxd" + COMMENT "Running Cython on capnp/lib/capnp.pyx" +) + +Python3_add_library(capnp_ext MODULE WITH_SOABI + "${CAPNP_CPP}" + "${CMAKE_SOURCE_DIR}/capnp/helpers/capabilityHelper.cpp" + "${CMAKE_SOURCE_DIR}/capnp/includes/PyCustomMessageBuilder.cpp" +) + +set_target_properties(capnp_ext PROPERTIES + OUTPUT_NAME "capnp" + CXX_STANDARD 14 + CXX_STANDARD_REQUIRED ON +) + +target_include_directories(capnp_ext PRIVATE + "${CMAKE_SOURCE_DIR}" + "${CMAKE_CURRENT_BINARY_DIR}" + "${CMAKE_SOURCE_DIR}/capnp/includes" +) + +target_link_libraries(capnp_ext PRIVATE + CapnProto::capnpc + CapnProto::capnp-rpc + CapnProto::capnp + CapnProto::kj-async + CapnProto::kj +) + +install(TARGETS capnp_ext DESTINATION capnp/lib) + +install(FILES "${CMAKE_CURRENT_BINARY_DIR}/capnp/lib/capnp_api.h" + DESTINATION capnp/lib) + +get_target_property(_capnp_inc_dirs CapnProto::capnp INTERFACE_INCLUDE_DIRECTORIES) +foreach(_inc_dir IN LISTS _capnp_inc_dirs) + string(REGEX REPLACE "\\$<\\$]+>:([^>]+)>" "\\1" _inc_dir_resolved "${_inc_dir}") + if(EXISTS "${_inc_dir_resolved}/capnp/schema.capnp") + file(GLOB _capnp_schemas "${_inc_dir_resolved}/capnp/*.capnp") + install(FILES ${_capnp_schemas} DESTINATION capnp) + break() + endif() +endforeach() diff --git a/_custom_build/backend.py b/_custom_build/backend.py deleted file mode 100644 index 883035433..000000000 --- a/_custom_build/backend.py +++ /dev/null @@ -1,29 +0,0 @@ -import sys - -from setuptools.build_meta import * # noqa: F401, F403 -from setuptools.build_meta import build_wheel - -backend_class = build_wheel.__self__.__class__ - - -class _CustomBuildMetaBackend(backend_class): - def run_setup(self, setup_script="setup.py"): - if self.config_settings: - flags = [] - if self.config_settings.get("force-bundled-libcapnp"): - flags.append("--force-bundled-libcapnp") - if self.config_settings.get("force-system-libcapnp"): - flags.append("--force-system-libcapnp") - if self.config_settings.get("libcapnp-url"): - flags.append("--libcapnp-url") - flags.append(self.config_settings["libcapnp-url"]) - if flags: - sys.argv = sys.argv[:1] + ["build_ext"] + flags + sys.argv[1:] - return super().run_setup(setup_script) - - def build_wheel(self, wheel_directory, config_settings=None, metadata_directory=None): - self.config_settings = config_settings - return super().build_wheel(wheel_directory, config_settings, metadata_directory) - - -build_wheel = _CustomBuildMetaBackend().build_wheel diff --git a/buildutils/__init__.py b/buildutils/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/buildutils/build.py b/buildutils/build.py deleted file mode 100644 index e79bdf09f..000000000 --- a/buildutils/build.py +++ /dev/null @@ -1,87 +0,0 @@ -"Build the bundled capnp distribution" - -import subprocess -import os -import shutil -import struct -import sys - - -def build_libcapnp(bundle_dir, build_dir): # noqa: C901 - """ - Build capnproto - """ - bundle_dir = os.path.abspath(bundle_dir) - capnp_dir = os.path.join(bundle_dir, "capnproto-c++") - build_dir = os.path.abspath(build_dir) - tmp_dir = os.path.join(capnp_dir, "build{}".format(8 * struct.calcsize("P"))) - - # Clean the tmp build directory every time - if os.path.exists(tmp_dir): - shutil.rmtree(tmp_dir) - os.mkdir(tmp_dir) - - cxxflags = os.environ.get("CXXFLAGS", None) - ldflags = os.environ.get("LDFLAGS", None) - os.environ["CXXFLAGS"] = (cxxflags or "") + " -O2 -DNDEBUG" - os.environ["LDFLAGS"] = ldflags or "" - - # Enable ninja for compilation if available - build_type = [] - if shutil.which("ninja") and os.name != "nt": - build_type = ["-G", "Ninja"] - - # Determine python shell architecture for Windows - python_arch = 8 * struct.calcsize("P") - build_arch = [] - build_flags = [] - if os.name == "nt": - if python_arch == 64: - build_arch_flag = "x64" - elif python_arch == 32: - build_arch_flag = "Win32" - else: - raise RuntimeError("Unknown windows build arch") - build_arch = ["-A", build_arch_flag] - build_flags = ["--config", "Release"] - print("Building module for {}".format(python_arch)) - - if not shutil.which("cmake"): - raise RuntimeError("Could not find cmake in your path!") - - args = [ - "cmake", - "-DCMAKE_POSITION_INDEPENDENT_CODE=1", - "-DBUILD_TESTING=OFF", - "-DBUILD_SHARED_LIBS=OFF", - "-DCMAKE_INSTALL_PREFIX:PATH={}".format(build_dir), - capnp_dir, - ] - args.extend(build_type) - args.extend(build_arch) - conf = subprocess.Popen(args, cwd=tmp_dir, stdout=sys.stdout) - returncode = conf.wait() - if returncode != 0: - raise RuntimeError("CMake failed {}".format(returncode)) - - # Run build through cmake - args = [ - "cmake", - "--build", - ".", - "--target", - "install", - ] - args.extend(build_flags) - build = subprocess.Popen(args, cwd=tmp_dir, stdout=sys.stdout) - returncode = build.wait() - if cxxflags is None: - del os.environ["CXXFLAGS"] - else: - os.environ["CXXFLAGS"] = cxxflags - if ldflags is None: - del os.environ["LDFLAGS"] - else: - os.environ["LDFLAGS"] = ldflags - if returncode != 0: - raise RuntimeError("capnproto compilation failed: {}".format(returncode)) diff --git a/buildutils/bundle.py b/buildutils/bundle.py deleted file mode 100644 index f6c28eea5..000000000 --- a/buildutils/bundle.py +++ /dev/null @@ -1,96 +0,0 @@ -"""utilities for fetching build dependencies.""" - -# -# Copyright (C) PyZMQ Developers -# Distributed under the terms of the Modified BSD License. -# -# This bundling code is largely adapted from pyzmq-static's get.sh by -# Brandon Craig-Rhodes, which is itself BSD licensed. -# -# Adapted for use in pycapnp from pyzmq. See https://github.com/zeromq/pyzmq -# for original project. - -import fileinput # noqa -import os -import shutil -import tarfile - -from urllib.request import urlopen - -pjoin = os.path.join - - -# -# Constants -# - - -bundled_version = (1, 0, 1) -libcapnp_name = "capnproto-c++-%i.%i.%i.tar.gz" % (bundled_version) -libcapnp_url = "https://capnproto.org/" + libcapnp_name - -HERE = os.path.dirname(__file__) -ROOT = os.path.dirname(HERE) - - -# -# Utilities -# - - -def untgz(archive): - """Remove .tar.gz""" - return archive.replace(".tar.gz", "") - - -def localpath(*args): - """construct an absolute path from a list relative to the root pycapnp directory""" - plist = [ROOT] + list(args) - return os.path.abspath(pjoin(*plist)) - - -def fetch_archive(savedir, url, force=False): - """download an archive to a specific location""" - req = urlopen(url) - # Lookup filename - fname = req.info().get_filename() - if not fname: - fname = os.path.basename(url) - dest = pjoin(savedir, fname) - if os.path.exists(dest) and not force: - print("already have %s" % fname) - return dest - print("fetching %s into %s" % (url, savedir)) - if not os.path.exists(savedir): - os.makedirs(savedir) - with open(dest, "wb") as f: - f.write(req.read()) - return dest - - -# -# libcapnp -# - - -def fetch_libcapnp(savedir, url=None): - """download and extract libcapnp""" - is_preconfigured = False - if url is None: - url = libcapnp_url - is_preconfigured = True - dest = pjoin(savedir, "capnproto-c++") - if os.path.exists(dest): - print("already have %s" % dest) - return - fname = fetch_archive(savedir, url) - tf = tarfile.open(fname) - with_version = pjoin(savedir, tf.firstmember.path) - tf.extractall(savedir) - tf.close() - # remove version suffix: - if is_preconfigured: - shutil.move(with_version, dest) - else: - cpp_dir = os.path.join(with_version, "c++") - shutil.move(cpp_dir, dest) diff --git a/capnp/version.py b/capnp/version.py new file mode 100644 index 000000000..97450bef5 --- /dev/null +++ b/capnp/version.py @@ -0,0 +1,9 @@ +from importlib.metadata import version as _pkg_version + +from .lib.capnp import _CAPNP_VERSION_MAJOR as LIBCAPNP_VERSION_MAJOR # noqa: F401 +from .lib.capnp import _CAPNP_VERSION_MINOR as LIBCAPNP_VERSION_MINOR # noqa: F401 +from .lib.capnp import _CAPNP_VERSION_MICRO as LIBCAPNP_VERSION_MICRO # noqa: F401 +from .lib.capnp import _CAPNP_VERSION as LIBCAPNP_VERSION # noqa: F401 + +version = _pkg_version("pycapnp") +short_version = version diff --git a/conan-build.profile b/conan-build.profile new file mode 100644 index 000000000..f34a0455b --- /dev/null +++ b/conan-build.profile @@ -0,0 +1,5 @@ +[platform_tool_requires] +m4/1.4.19 +autoconf/2.71 +automake/1.16.5 +libtool/2.4.7 diff --git a/conanfile.py b/conanfile.py new file mode 100644 index 000000000..68dfc1351 --- /dev/null +++ b/conanfile.py @@ -0,0 +1,23 @@ +from conan import ConanFile +from conan.tools.cmake import CMake, cmake_layout + + +class PycapnpConan(ConanFile): + name = "pycapnp" + settings = "os", "compiler", "build_type", "arch" + generators = "CMakeToolchain", "CMakeDeps" + + def requirements(self): + self.requires("capnproto/1.0.1") + + def layout(self): + cmake_layout(self) + + def build(self): + cmake = CMake(self) + cmake.configure() + cmake.build() + + def package(self): + cmake = CMake(self) + cmake.install() diff --git a/pyproject.toml b/pyproject.toml index 925cc2238..8acab145a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,7 +1,49 @@ [build-system] -requires = ["setuptools", "wheel", "pkgconfig", "cython>=3.0"] -build-backend = "backend" -backend-path = ["_custom_build"] +requires = ["conan-py-build>=0.5.3", "cython>=3.0"] +build-backend = "conan_py_build.build" + +[project] +name = "pycapnp" +version = "2.2.3" +description = "A cython wrapping of the C++ Cap'n Proto library" +readme = "README.md" +requires-python = ">=3.8" +license = "BSD-2-Clause" +license-files = ["LICENSE.md"] +authors = [ + {name = "Jacob Alexander", email = "haata@kiibohd.com"}, +] +keywords = ["capnp", "capnproto", "Cap'n Proto", "pycapnp"] +classifiers = [ + "Development Status :: 5 - Production/Stable", + "Intended Audience :: Developers", + "Operating System :: MacOS :: MacOS X", + "Operating System :: Microsoft :: Windows :: Windows 10", + "Operating System :: POSIX", + "Programming Language :: C++", + "Programming Language :: Cython", + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: Implementation :: PyPy", + "Topic :: Communications", +] + +[project.scripts] +capnpc-cython = "capnp._gen:main" + +[tool.conan-py-build] +extra-arguments = ["-o=capnproto/*:with_openssl=False", "-o=capnproto/*:with_zlib=False"] +extra-profile-build = "conan-build.profile" + +[tool.conan-py-build.wheel] +packages = ["capnp"] +exclude = ["**/*.cpp"] + +[tool.conan-py-build.sdist] +include = ["capnp", "CHANGELOG.md", "MANIFEST.in", "requirements.txt"] [tool.pytest.ini_options] asyncio_mode = "auto" diff --git a/setup.cfg b/setup.cfg deleted file mode 100644 index 04ef73cab..000000000 --- a/setup.cfg +++ /dev/null @@ -1,3 +0,0 @@ -[metadata] -description_file = README.md -license_files = LICENSE.md diff --git a/setup.py b/setup.py deleted file mode 100644 index 4ec9c47c7..000000000 --- a/setup.py +++ /dev/null @@ -1,258 +0,0 @@ -#!/usr/bin/env python -""" -pycapnp distutils setup.py -""" - -import glob -import os -import shutil -import struct -import sys - -import pkgconfig - -from distutils.command.clean import clean as _clean - -from setuptools import setup, Extension - -_this_dir = os.path.dirname(__file__) -sys.path.insert(1, _this_dir) - -from buildutils.build import build_libcapnp -from buildutils.bundle import fetch_libcapnp - -MAJOR = 2 -MINOR = 2 -MICRO = 3 -TAG = "" -VERSION = "%d.%d.%d%s" % (MAJOR, MINOR, MICRO, TAG) - - -# Write version info -def write_version_py(filename=None): - """ - Generate pycapnp version - """ - cnt = """\ -from .lib.capnp import _CAPNP_VERSION_MAJOR as LIBCAPNP_VERSION_MAJOR # noqa: F401 -from .lib.capnp import _CAPNP_VERSION_MINOR as LIBCAPNP_VERSION_MINOR # noqa: F401 -from .lib.capnp import _CAPNP_VERSION_MICRO as LIBCAPNP_VERSION_MICRO # noqa: F401 -from .lib.capnp import _CAPNP_VERSION as LIBCAPNP_VERSION # noqa: F401 - -version = '%s' -short_version = '%s' -""" - if not filename: - filename = os.path.join(os.path.dirname(__file__), "capnp", "version.py") - - a = open(filename, "w") - try: - a.write(cnt % (VERSION, VERSION)) - finally: - a.close() - - -write_version_py() - -# Try to use README.md and CHANGELOG.md as description and changelog -with open("README.md", encoding="utf-8") as f: - long_description = f.read() -with open("CHANGELOG.md", encoding="utf-8") as f: - changelog = f.read() -changelog = "\nChangelog\n=============\n" + changelog -long_description += changelog - - -class clean(_clean): - """ - Clean command, invoked with `python setup.py clean` - """ - - def run(self): - _clean.run(self) - for x in [ - os.path.join("capnp", "lib", "capnp.cpp"), - os.path.join("capnp", "lib", "capnp.h"), - os.path.join("capnp", "version.py"), - "build", - "build32", - "build64", - "bundled", - ] + glob.glob(os.path.join("capnp", "*.capnp")): - print("removing %s" % x) - try: - os.remove(x) - except OSError: - shutil.rmtree(x, ignore_errors=True) - - -from Cython.Distutils import build_ext as build_ext_c # noqa: E402 - - -class build_libcapnp_ext(build_ext_c): - """ - Build capnproto library - """ - - user_options = build_ext_c.user_options + [ - ("force-bundled-libcapnp", None, "Bundle capnp library into the installer"), - ("force-system-libcapnp", None, "Use system capnp library"), - ("libcapnp-url=", "u", "URL to download libcapnp from (only if bundled)"), - ] - - def initialize_options(self): - build_ext_c.initialize_options(self) - self.force_bundled_libcapnp = None - self.force_system_libcapnp = None - self.libcapnp_url = None - - def finalize_options(self): - # print('The custom option for install is ', self.custom_option) - build_ext_c.finalize_options(self) - - def build_extension(self, ext): - build_ext_c.build_extension(self, ext) - - def run(self): # noqa: C901 - if self.force_bundled_libcapnp: - need_build = True - elif self.force_system_libcapnp: - need_build = False - else: - # Try to use capnp executable to find include and lib path - capnp_executable = shutil.which("capnp") - if capnp_executable: - capnp_dir = os.path.dirname(capnp_executable) - self.include_dirs += [os.path.join(capnp_dir, "..", "include")] - self.library_dirs += [os.path.join(capnp_dir, "..", "lib{}".format(8 * struct.calcsize("P")))] - self.library_dirs += [os.path.join(capnp_dir, "..", "lib")] - - # Look for capnproto using pkg-config (and minimum version) - try: - if pkgconfig.installed("capnp", ">= 0.7.0"): - need_build = False - else: - need_build = True - except EnvironmentError: - # pkg-config not available in path - need_build = True - - if need_build: - print( - "*WARNING* no libcapnp detected or rebuild forced. " - "Attempting to build it from source now. " - "If you have C++ Cap'n Proto installed, it may be out of date or is not being detected. " - "This may take a while..." - ) - bundle_dir = os.path.join(_this_dir, "bundled") - if not os.path.exists(bundle_dir): - os.mkdir(bundle_dir) - build_dir = os.path.join(_this_dir, "build{}".format(8 * struct.calcsize("P"))) - if not os.path.exists(build_dir): - os.mkdir(build_dir) - - # Check if we've already built capnproto - capnp_bin = os.path.join(build_dir, "bin", "capnp") - if os.name == "nt": - capnp_bin = os.path.join(build_dir, "bin", "capnp.exe") - - if not os.path.exists(capnp_bin): - # Not built, fetch and build - fetch_libcapnp(bundle_dir, self.libcapnp_url) - build_libcapnp(bundle_dir, build_dir) - else: - print("capnproto already built at {}".format(build_dir)) - - self.include_dirs = [os.path.join(build_dir, "include")] + self.include_dirs - self.library_dirs = [ - os.path.join(build_dir, "lib{}".format(8 * struct.calcsize("P"))), - os.path.join(build_dir, "lib"), - ] + self.library_dirs - - # Copy .capnp files from source - src_glob = glob.glob(os.path.join(build_dir, "include", "capnp", "*.capnp")) - dst_dir = os.path.join(self.build_lib, "capnp") - os.makedirs(dst_dir, exist_ok=True) - for file in src_glob: - print("copying {} -> {}".format(file, dst_dir)) - shutil.copy(file, dst_dir) - - return build_ext_c.run(self) - - -extra_compile_args = ["--std=c++14"] -extra_link_args = [] -if os.name == "nt": - extra_compile_args = ["/std:c++14", "/MD"] - extra_link_args = ["/MANIFEST"] - -import Cython.Build # noqa: E402 -import Cython # noqa: E402 - -extensions = [ - Extension( - "*", - [ - "capnp/helpers/capabilityHelper.cpp", - "capnp/includes/PyCustomMessageBuilder.cpp", - "capnp/lib/*.pyx", - ], - extra_compile_args=extra_compile_args, - extra_link_args=extra_link_args, - language="c++", - ) -] - -setup( - python_requires=">=3.8", - name="pycapnp", - packages=["capnp"], - version=VERSION, - package_data={ - "capnp": [ - "*.pxd", - "*.h", - "*.capnp", - "helpers/*.pxd", - "helpers/*.h", - "includes/*.h", - "includes/*.pxd", - "lib/*.pxd", - "lib/*.py", - "lib/*.pyx", - "lib/*.h", - "templates/*", - ] - }, - ext_modules=Cython.Build.cythonize(extensions), - cmdclass={"clean": clean, "build_ext": build_libcapnp_ext}, - install_requires=[], - entry_points={"console_scripts": ["capnpc-cython = capnp._gen:main"]}, - # PyPi info - description="A cython wrapping of the C++ Cap'n Proto library", - long_description=long_description, - long_description_content_type="text/markdown", - license="BSD-2-Clause", - # (setup.py only supports 1 author...) - author="Jacob Alexander", # <- Current maintainer; Original author -> Jason Paryani - author_email="haata@kiibohd.com", - url="https://github.com/capnproto/pycapnp", - download_url="https://github.com/haata/pycapnp/archive/v%s.zip" % VERSION, - keywords=["capnp", "capnproto", "Cap'n Proto", "pycapnp"], - classifiers=[ - "Development Status :: 5 - Production/Stable", - "Intended Audience :: Developers", - "Operating System :: MacOS :: MacOS X", - "Operating System :: Microsoft :: Windows :: Windows 10", - "Operating System :: POSIX", - "Programming Language :: C++", - "Programming Language :: Cython", - "Programming Language :: Python :: 3.8", - "Programming Language :: Python :: 3.9", - "Programming Language :: Python :: 3.10", - "Programming Language :: Python :: 3.11", - "Programming Language :: Python :: 3.12", - "Programming Language :: Python :: Implementation :: PyPy", - "Topic :: Communications", - ], -) From e77756b3e3e6b05168f9bb49f8a72832403c9c4a Mon Sep 17 00:00:00 2001 From: Carlos Zoido Date: Thu, 11 Jun 2026 14:09:21 +0200 Subject: [PATCH 02/31] force build m4 --- .github/workflows/wheels.yml | 1 - conan-build.profile | 5 ----- pyproject.toml | 3 +-- 3 files changed, 1 insertion(+), 8 deletions(-) delete mode 100644 conan-build.profile diff --git a/.github/workflows/wheels.yml b/.github/workflows/wheels.yml index ff72dd9cc..a44a590d7 100644 --- a/.github/workflows/wheels.yml +++ b/.github/workflows/wheels.yml @@ -48,7 +48,6 @@ jobs: CIBW_SKIP: "cp38-*" CIBW_TEST_REQUIRES: pytest pytest-asyncio CIBW_TEST_COMMAND: pytest {project} - CIBW_BEFORE_ALL_LINUX: "yum install -y m4 autoconf automake libtool" # Force libcapnp to build for the target arch on macOS (the runner # is arm64, so without this an x86_64 wheel ends up linking against # an arm64 libkj/libcapnp and failing to load at test time). diff --git a/conan-build.profile b/conan-build.profile deleted file mode 100644 index f34a0455b..000000000 --- a/conan-build.profile +++ /dev/null @@ -1,5 +0,0 @@ -[platform_tool_requires] -m4/1.4.19 -autoconf/2.71 -automake/1.16.5 -libtool/2.4.7 diff --git a/pyproject.toml b/pyproject.toml index 8acab145a..06133852e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -35,8 +35,7 @@ classifiers = [ capnpc-cython = "capnp._gen:main" [tool.conan-py-build] -extra-arguments = ["-o=capnproto/*:with_openssl=False", "-o=capnproto/*:with_zlib=False"] -extra-profile-build = "conan-build.profile" +extra-arguments = ["-o=capnproto/*:with_openssl=False", "-o=capnproto/*:with_zlib=False", "--build=m4*"] [tool.conan-py-build.wheel] packages = ["capnp"] From cdd4c7b6cf33853f79d7bfbe375746c04f2177e7 Mon Sep 17 00:00:00 2001 From: Carlos Zoido Date: Thu, 11 Jun 2026 14:22:18 +0200 Subject: [PATCH 03/31] pre-install m4 --- .github/workflows/wheels.yml | 4 ++++ conanfile.py | 3 ++- pyproject.toml | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/.github/workflows/wheels.yml b/.github/workflows/wheels.yml index a44a590d7..fa6759340 100644 --- a/.github/workflows/wheels.yml +++ b/.github/workflows/wheels.yml @@ -48,6 +48,9 @@ jobs: CIBW_SKIP: "cp38-*" CIBW_TEST_REQUIRES: pytest pytest-asyncio CIBW_TEST_COMMAND: pytest {project} + # Pre-build m4 from source inside manylinux so Conan uses a glibc-2.28-compatible + # binary instead of ConanCenter's Ubuntu binary (glibc 2.35, crashes in manylinux_2_28). + CIBW_BEFORE_ALL_LINUX: "pip install conan && conan install --requires=m4/1.4.19 --build=m4*" # Force libcapnp to build for the target arch on macOS (the runner # is arm64, so without this an x86_64 wheel ends up linking against # an arm64 libkj/libcapnp and failing to load at test time). @@ -81,6 +84,7 @@ jobs: env: CIBW_ARCHS: ${{ matrix.arch }} CIBW_SKIP: "cp38-*" + CIBW_BEFORE_ALL_LINUX: "pip install conan && conan install --requires=m4/1.4.19 --build=m4*" # Tests under QEMU are extremely slow; skip them for these arches. CIBW_TEST_SKIP: "*" diff --git a/conanfile.py b/conanfile.py index 68dfc1351..ab19d897f 100644 --- a/conanfile.py +++ b/conanfile.py @@ -14,8 +14,9 @@ def layout(self): cmake_layout(self) def build(self): + import sys cmake = CMake(self) - cmake.configure() + cmake.configure(variables={"Python3_EXECUTABLE": sys.executable}) cmake.build() def package(self): diff --git a/pyproject.toml b/pyproject.toml index 06133852e..828f06f7f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -35,7 +35,7 @@ classifiers = [ capnpc-cython = "capnp._gen:main" [tool.conan-py-build] -extra-arguments = ["-o=capnproto/*:with_openssl=False", "-o=capnproto/*:with_zlib=False", "--build=m4*"] +extra-arguments = ["-o=capnproto/*:with_openssl=False", "-o=capnproto/*:with_zlib=False"] [tool.conan-py-build.wheel] packages = ["capnp"] From 3ec21a8120e6e21a65f485a3113ff758fb1cf853 Mon Sep 17 00:00:00 2001 From: Carlos Zoido Date: Thu, 11 Jun 2026 14:23:44 +0200 Subject: [PATCH 04/31] ruff conanfile --- conanfile.py | 1 + 1 file changed, 1 insertion(+) diff --git a/conanfile.py b/conanfile.py index ab19d897f..e07fe37f5 100644 --- a/conanfile.py +++ b/conanfile.py @@ -15,6 +15,7 @@ def layout(self): def build(self): import sys + cmake = CMake(self) cmake.configure(variables={"Python3_EXECUTABLE": sys.executable}) cmake.build() From 25159ff322e4f17044f163abb979133737a5d9c2 Mon Sep 17 00:00:00 2001 From: Carlos Zoido Date: Thu, 11 Jun 2026 14:24:18 +0200 Subject: [PATCH 05/31] profile detect --- .github/workflows/wheels.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/wheels.yml b/.github/workflows/wheels.yml index fa6759340..c1c595213 100644 --- a/.github/workflows/wheels.yml +++ b/.github/workflows/wheels.yml @@ -50,7 +50,7 @@ jobs: CIBW_TEST_COMMAND: pytest {project} # Pre-build m4 from source inside manylinux so Conan uses a glibc-2.28-compatible # binary instead of ConanCenter's Ubuntu binary (glibc 2.35, crashes in manylinux_2_28). - CIBW_BEFORE_ALL_LINUX: "pip install conan && conan install --requires=m4/1.4.19 --build=m4*" + CIBW_BEFORE_ALL_LINUX: "pip install conan && conan profile detect && conan install --requires=m4/1.4.19 --build=m4*" # Force libcapnp to build for the target arch on macOS (the runner # is arm64, so without this an x86_64 wheel ends up linking against # an arm64 libkj/libcapnp and failing to load at test time). @@ -84,7 +84,7 @@ jobs: env: CIBW_ARCHS: ${{ matrix.arch }} CIBW_SKIP: "cp38-*" - CIBW_BEFORE_ALL_LINUX: "pip install conan && conan install --requires=m4/1.4.19 --build=m4*" + CIBW_BEFORE_ALL_LINUX: "pip install conan && conan profile detect && conan install --requires=m4/1.4.19 --build=m4*" # Tests under QEMU are extremely slow; skip them for these arches. CIBW_TEST_SKIP: "*" From 9bed86289c0ad290b231f3cafda670343bdfe7e2 Mon Sep 17 00:00:00 2001 From: Carlos Zoido Date: Thu, 11 Jun 2026 15:11:55 +0200 Subject: [PATCH 06/31] use profile for macos x86 --- .github/workflows/wheels.yml | 8 ++++---- profiles/macos-x86_64 | 4 ++++ 2 files changed, 8 insertions(+), 4 deletions(-) create mode 100644 profiles/macos-x86_64 diff --git a/.github/workflows/wheels.yml b/.github/workflows/wheels.yml index c1c595213..7d14389c1 100644 --- a/.github/workflows/wheels.yml +++ b/.github/workflows/wheels.yml @@ -21,6 +21,7 @@ jobs: - os: macos-15 arch: x86_64 + host_profile: profiles/macos-x86_64 - os: macos-15 arch: arm64 # Disabled until someone figures out how to build capnproto for arm64 and x86_64 simultaneously @@ -51,10 +52,9 @@ jobs: # Pre-build m4 from source inside manylinux so Conan uses a glibc-2.28-compatible # binary instead of ConanCenter's Ubuntu binary (glibc 2.35, crashes in manylinux_2_28). CIBW_BEFORE_ALL_LINUX: "pip install conan && conan profile detect && conan install --requires=m4/1.4.19 --build=m4*" - # Force libcapnp to build for the target arch on macOS (the runner - # is arm64, so without this an x86_64 wheel ends up linking against - # an arm64 libkj/libcapnp and failing to load at test time). - CMAKE_OSX_ARCHITECTURES: "${{ runner.os == 'macOS' && matrix.arch || '' }}" + # For macOS x86_64 on the arm64 runner, override the host profile so + # Conan builds capnproto and the extension for the right architecture. + CIBW_CONFIG_SETTINGS: "${{ matrix.host_profile && format('host-profile=./{0}', matrix.host_profile) || '' }}" - uses: actions/upload-artifact@v6 with: diff --git a/profiles/macos-x86_64 b/profiles/macos-x86_64 new file mode 100644 index 000000000..7148176e8 --- /dev/null +++ b/profiles/macos-x86_64 @@ -0,0 +1,4 @@ +include(default) + +[settings] +arch=x86_64 From 612c9b3fc74ffefe303980e05818dc67d9f40545 Mon Sep 17 00:00:00 2001 From: Carlos Zoido Date: Thu, 11 Jun 2026 15:13:34 +0200 Subject: [PATCH 07/31] fix wind x86 --- .github/workflows/wheels.yml | 1 + profiles/windows-x86 | 4 ++++ 2 files changed, 5 insertions(+) create mode 100644 profiles/windows-x86 diff --git a/.github/workflows/wheels.yml b/.github/workflows/wheels.yml index 7d14389c1..9e3b42ff0 100644 --- a/.github/workflows/wheels.yml +++ b/.github/workflows/wheels.yml @@ -32,6 +32,7 @@ jobs: arch: AMD64 - os: windows-2022 arch: x86 + host_profile: profiles/windows-x86 # Does not build currently # - os: windows-2019 # arch: ARM64 diff --git a/profiles/windows-x86 b/profiles/windows-x86 new file mode 100644 index 000000000..151a68fb5 --- /dev/null +++ b/profiles/windows-x86 @@ -0,0 +1,4 @@ +include(default) + +[settings] +arch=x86 From 9c55243939dbb4cc32d462e6cb41f38d4105604e Mon Sep 17 00:00:00 2001 From: Carlos Zoido Date: Thu, 11 Jun 2026 15:14:48 +0200 Subject: [PATCH 08/31] trigger CI From 5c1416b1b58b2b41abc77ebc16613c72647c0313 Mon Sep 17 00:00:00 2001 From: Carlos Zoido Date: Thu, 11 Jun 2026 15:36:30 +0200 Subject: [PATCH 09/31] wip --- .github/workflows/wheels.yml | 5 ----- conan-host.profile | 7 +++++++ profiles/macos-x86_64 | 4 ---- profiles/windows-x86 | 4 ---- pyproject.toml | 1 + 5 files changed, 8 insertions(+), 13 deletions(-) create mode 100644 conan-host.profile delete mode 100644 profiles/macos-x86_64 delete mode 100644 profiles/windows-x86 diff --git a/.github/workflows/wheels.yml b/.github/workflows/wheels.yml index 9e3b42ff0..7bfd1f7e6 100644 --- a/.github/workflows/wheels.yml +++ b/.github/workflows/wheels.yml @@ -21,7 +21,6 @@ jobs: - os: macos-15 arch: x86_64 - host_profile: profiles/macos-x86_64 - os: macos-15 arch: arm64 # Disabled until someone figures out how to build capnproto for arm64 and x86_64 simultaneously @@ -32,7 +31,6 @@ jobs: arch: AMD64 - os: windows-2022 arch: x86 - host_profile: profiles/windows-x86 # Does not build currently # - os: windows-2019 # arch: ARM64 @@ -53,9 +51,6 @@ jobs: # Pre-build m4 from source inside manylinux so Conan uses a glibc-2.28-compatible # binary instead of ConanCenter's Ubuntu binary (glibc 2.35, crashes in manylinux_2_28). CIBW_BEFORE_ALL_LINUX: "pip install conan && conan profile detect && conan install --requires=m4/1.4.19 --build=m4*" - # For macOS x86_64 on the arm64 runner, override the host profile so - # Conan builds capnproto and the extension for the right architecture. - CIBW_CONFIG_SETTINGS: "${{ matrix.host_profile && format('host-profile=./{0}', matrix.host_profile) || '' }}" - uses: actions/upload-artifact@v6 with: diff --git a/conan-host.profile b/conan-host.profile new file mode 100644 index 000000000..656b713a0 --- /dev/null +++ b/conan-host.profile @@ -0,0 +1,7 @@ +{% set cibw_arch = os.environ.get("CIBW_ARCHS", "") %} +{% set arch_map = {"x86_64": "x86_64", "arm64": "armv8", "x86": "x86"} %} +{% set arch = arch_map.get(cibw_arch, "") %} +{% if arch %} +[settings] +arch={{ arch }} +{% endif %} diff --git a/profiles/macos-x86_64 b/profiles/macos-x86_64 deleted file mode 100644 index 7148176e8..000000000 --- a/profiles/macos-x86_64 +++ /dev/null @@ -1,4 +0,0 @@ -include(default) - -[settings] -arch=x86_64 diff --git a/profiles/windows-x86 b/profiles/windows-x86 deleted file mode 100644 index 151a68fb5..000000000 --- a/profiles/windows-x86 +++ /dev/null @@ -1,4 +0,0 @@ -include(default) - -[settings] -arch=x86 diff --git a/pyproject.toml b/pyproject.toml index 828f06f7f..141e4b5fa 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -36,6 +36,7 @@ capnpc-cython = "capnp._gen:main" [tool.conan-py-build] extra-arguments = ["-o=capnproto/*:with_openssl=False", "-o=capnproto/*:with_zlib=False"] +extra-profile-host = "conan-host.profile" [tool.conan-py-build.wheel] packages = ["capnp"] From 3f8868465450b9e5727f48f0fa950300f749c2bf Mon Sep 17 00:00:00 2001 From: Carlos Zoido Date: Thu, 11 Jun 2026 16:10:47 +0200 Subject: [PATCH 10/31] wip --- conan-host.profile | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/conan-host.profile b/conan-host.profile index 656b713a0..63e42d091 100644 --- a/conan-host.profile +++ b/conan-host.profile @@ -1,7 +1,14 @@ {% set cibw_arch = os.environ.get("CIBW_ARCHS", "") %} {% set arch_map = {"x86_64": "x86_64", "arm64": "armv8", "x86": "x86"} %} -{% set arch = arch_map.get(cibw_arch, "") %} -{% if arch %} +{% set conan_arch = arch_map.get(cibw_arch, "") %} +{% if conan_arch %} [settings] -arch={{ arch }} +arch={{ conan_arch }} +{% endif %} +{% set is_macos = os.path.isdir('/System') %} +{% set wheel_mac_arch = {"x86_64": "x86_64", "arm64": "arm64"}.get(cibw_arch, "") %} +{% if is_macos and wheel_mac_arch %} +{% set dt = os.environ.get("MACOSX_DEPLOYMENT_TARGET", "").replace(".", "_") or ("10_9" if cibw_arch == "x86_64" else "11_0") %} +[buildenv] +WHEEL_ARCH=macosx_{{ dt }}_{{ wheel_mac_arch }} {% endif %} From 3cc62a89f17cec49c81410df9a5a5c08ba11b209 Mon Sep 17 00:00:00 2001 From: Carlos Zoido Date: Thu, 11 Jun 2026 16:38:23 +0200 Subject: [PATCH 11/31] use profile for mac --- conan-host.profile | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/conan-host.profile b/conan-host.profile index 63e42d091..c88ead274 100644 --- a/conan-host.profile +++ b/conan-host.profile @@ -1,14 +1,14 @@ {% set cibw_arch = os.environ.get("CIBW_ARCHS", "") %} -{% set arch_map = {"x86_64": "x86_64", "arm64": "armv8", "x86": "x86"} %} -{% set conan_arch = arch_map.get(cibw_arch, "") %} +{% set conan_arch = {"x86_64": "x86_64", "arm64": "armv8", "x86": "x86"}.get(cibw_arch, "") %} +{% set dt = os.environ.get("MACOSX_DEPLOYMENT_TARGET", "").replace(".", "_") %} +include(default) {% if conan_arch %} + [settings] arch={{ conan_arch }} {% endif %} -{% set is_macos = os.path.isdir('/System') %} -{% set wheel_mac_arch = {"x86_64": "x86_64", "arm64": "arm64"}.get(cibw_arch, "") %} -{% if is_macos and wheel_mac_arch %} -{% set dt = os.environ.get("MACOSX_DEPLOYMENT_TARGET", "").replace(".", "_") or ("10_9" if cibw_arch == "x86_64" else "11_0") %} +{% if platform.system() == 'Darwin' and cibw_arch in ("x86_64", "arm64") and dt %} + [buildenv] -WHEEL_ARCH=macosx_{{ dt }}_{{ wheel_mac_arch }} +WHEEL_ARCH=macosx_{{ dt }}_{{ cibw_arch }} {% endif %} From 4fd72a47bd580c38fd3d629522656339e3e0c3a7 Mon Sep 17 00:00:00 2001 From: Carlos Zoido Date: Thu, 11 Jun 2026 16:40:13 +0200 Subject: [PATCH 12/31] trigger CI From 3d802a899df0719de72787a55d8255456bd29ff1 Mon Sep 17 00:00:00 2001 From: Carlos Zoido Date: Thu, 11 Jun 2026 17:00:58 +0200 Subject: [PATCH 13/31] use freethreading_compatible --- .github/workflows/wheels.yml | 1 - CMakeLists.txt | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/wheels.yml b/.github/workflows/wheels.yml index 7bfd1f7e6..8cd5140cf 100644 --- a/.github/workflows/wheels.yml +++ b/.github/workflows/wheels.yml @@ -44,7 +44,6 @@ jobs: output-dir: wheelhouse env: CIBW_ARCHS: ${{ matrix.arch }} - # Drop EOL CPython 3.8 (also avoids the macOS x86_64-only-installer warning) CIBW_SKIP: "cp38-*" CIBW_TEST_REQUIRES: pytest pytest-asyncio CIBW_TEST_COMMAND: pytest {project} diff --git a/CMakeLists.txt b/CMakeLists.txt index d9d883bc1..50ba540d0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,6 +13,7 @@ add_custom_command( OUTPUT "${CAPNP_CPP}" COMMAND "${Python3_EXECUTABLE}" -m cython --cplus + -X freethreading_compatible=True -I "${CMAKE_SOURCE_DIR}" "${CAPNP_PYX}" -o "${CAPNP_CPP}" From d135b1e2f45498a3319dfb4963a151c96fdb4e3d Mon Sep 17 00:00:00 2001 From: Carlos Zoido Date: Thu, 11 Jun 2026 17:44:01 +0200 Subject: [PATCH 14/31] try to fix free-threaded --- .github/workflows/wheels.yml | 22 +--------------------- CMakeLists.txt | 1 - conanfile.py | 17 ++++++++++++----- 3 files changed, 13 insertions(+), 27 deletions(-) diff --git a/.github/workflows/wheels.yml b/.github/workflows/wheels.yml index 8cd5140cf..47f70f74f 100644 --- a/.github/workflows/wheels.yml +++ b/.github/workflows/wheels.yml @@ -11,29 +11,8 @@ jobs: fail-fast: false matrix: include: - - os: ubuntu-latest - arch: x86_64 - - os: ubuntu-latest - arch: i686 - # Native ARM runner — no QEMU, drastically faster than emulated aarch64 - - os: ubuntu-24.04-arm - arch: aarch64 - - os: macos-15 arch: x86_64 - - os: macos-15 - arch: arm64 - # Disabled until someone figures out how to build capnproto for arm64 and x86_64 simultaneously - # - os: macOS-latest - # arch: universal2 - - - os: windows-2022 - arch: AMD64 - - os: windows-2022 - arch: x86 - # Does not build currently - # - os: windows-2019 - # arch: ARM64 steps: - uses: actions/checkout@v5 @@ -44,6 +23,7 @@ jobs: output-dir: wheelhouse env: CIBW_ARCHS: ${{ matrix.arch }} + CIBW_BUILD: "cp314t-*" CIBW_SKIP: "cp38-*" CIBW_TEST_REQUIRES: pytest pytest-asyncio CIBW_TEST_COMMAND: pytest {project} diff --git a/CMakeLists.txt b/CMakeLists.txt index 50ba540d0..d9d883bc1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,7 +13,6 @@ add_custom_command( OUTPUT "${CAPNP_CPP}" COMMAND "${Python3_EXECUTABLE}" -m cython --cplus - -X freethreading_compatible=True -I "${CMAKE_SOURCE_DIR}" "${CAPNP_PYX}" -o "${CAPNP_CPP}" diff --git a/conanfile.py b/conanfile.py index e07fe37f5..762ef1238 100644 --- a/conanfile.py +++ b/conanfile.py @@ -1,11 +1,13 @@ +import sys +import sysconfig + from conan import ConanFile -from conan.tools.cmake import CMake, cmake_layout +from conan.tools.cmake import CMake, CMakeDeps, CMakeToolchain, cmake_layout class PycapnpConan(ConanFile): name = "pycapnp" settings = "os", "compiler", "build_type", "arch" - generators = "CMakeToolchain", "CMakeDeps" def requirements(self): self.requires("capnproto/1.0.1") @@ -13,11 +15,16 @@ def requirements(self): def layout(self): cmake_layout(self) - def build(self): - import sys + def generate(self): + tc = CMakeToolchain(self) + tc.cache_variables["Python3_EXECUTABLE"] = sys.executable + tc.cache_variables["Python3_INCLUDE_DIR"] = sysconfig.get_path("include") + tc.generate() + CMakeDeps(self).generate() + def build(self): cmake = CMake(self) - cmake.configure(variables={"Python3_EXECUTABLE": sys.executable}) + cmake.configure() cmake.build() def package(self): From a06a37e4ace596f4f4f3bf4c3b691768b8a066b8 Mon Sep 17 00:00:00 2001 From: Carlos Zoido Date: Thu, 11 Jun 2026 17:56:07 +0200 Subject: [PATCH 15/31] restore builds --- .github/workflows/wheels.yml | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/.github/workflows/wheels.yml b/.github/workflows/wheels.yml index 47f70f74f..8cd5140cf 100644 --- a/.github/workflows/wheels.yml +++ b/.github/workflows/wheels.yml @@ -11,8 +11,29 @@ jobs: fail-fast: false matrix: include: + - os: ubuntu-latest + arch: x86_64 + - os: ubuntu-latest + arch: i686 + # Native ARM runner — no QEMU, drastically faster than emulated aarch64 + - os: ubuntu-24.04-arm + arch: aarch64 + - os: macos-15 arch: x86_64 + - os: macos-15 + arch: arm64 + # Disabled until someone figures out how to build capnproto for arm64 and x86_64 simultaneously + # - os: macOS-latest + # arch: universal2 + + - os: windows-2022 + arch: AMD64 + - os: windows-2022 + arch: x86 + # Does not build currently + # - os: windows-2019 + # arch: ARM64 steps: - uses: actions/checkout@v5 @@ -23,7 +44,6 @@ jobs: output-dir: wheelhouse env: CIBW_ARCHS: ${{ matrix.arch }} - CIBW_BUILD: "cp314t-*" CIBW_SKIP: "cp38-*" CIBW_TEST_REQUIRES: pytest pytest-asyncio CIBW_TEST_COMMAND: pytest {project} From da14df93f6d59f8508b8d623392a284ff4fb2c26 Mon Sep 17 00:00:00 2001 From: Carlos Zoido Date: Fri, 12 Jun 2026 08:11:14 +0200 Subject: [PATCH 16/31] add soabi --- conanfile.py | 1 + pyproject.toml | 3 +++ 2 files changed, 4 insertions(+) diff --git a/conanfile.py b/conanfile.py index 762ef1238..a7cf9d2ce 100644 --- a/conanfile.py +++ b/conanfile.py @@ -19,6 +19,7 @@ def generate(self): tc = CMakeToolchain(self) tc.cache_variables["Python3_EXECUTABLE"] = sys.executable tc.cache_variables["Python3_INCLUDE_DIR"] = sysconfig.get_path("include") + tc.cache_variables["Python3_SOABI"] = sysconfig.get_config_var("SOABI") tc.generate() CMakeDeps(self).generate() diff --git a/pyproject.toml b/pyproject.toml index 141e4b5fa..19e9ee161 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -31,6 +31,9 @@ classifiers = [ "Topic :: Communications", ] +[project.urls] +Homepage = "https://github.com/capnproto/pycapnp" + [project.scripts] capnpc-cython = "capnp._gen:main" From 29735f186f1fbd153fdca0c8aa3a63ddfde132a5 Mon Sep 17 00:00:00 2001 From: Carlos Zoido Date: Fri, 12 Jun 2026 08:12:48 +0200 Subject: [PATCH 17/31] test wheels --- .github/workflows/wheels.yml | 54 ++++++++++++++++++------------------ 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/.github/workflows/wheels.yml b/.github/workflows/wheels.yml index 8cd5140cf..35a3b73ba 100644 --- a/.github/workflows/wheels.yml +++ b/.github/workflows/wheels.yml @@ -58,35 +58,35 @@ jobs: # Exotic arches built via QEMU emulation — very slow (often >1h), so only run # on release tags rather than every push/PR. - build_wheels_exotic: - name: Build wheels (exotic) ${{ matrix.arch }} - if: startsWith(github.ref, 'refs/tags/v') || github.ref == 'refs/heads/conan-py-build' - runs-on: ubuntu-latest - strategy: - fail-fast: false - matrix: - arch: [ppc64le, s390x] - steps: - - uses: actions/checkout@v5 - - - name: Set up QEMU - uses: docker/setup-qemu-action@v4 + # build_wheels_exotic: + # name: Build wheels (exotic) ${{ matrix.arch }} + # if: startsWith(github.ref, 'refs/tags/v') || github.ref == 'refs/heads/conan-py-build' + # runs-on: ubuntu-latest + # strategy: + # fail-fast: false + # matrix: + # arch: [ppc64le, s390x] + # steps: + # - uses: actions/checkout@v5 - - name: Build wheels - uses: pypa/cibuildwheel@v3.4.1 - with: - output-dir: wheelhouse - env: - CIBW_ARCHS: ${{ matrix.arch }} - CIBW_SKIP: "cp38-*" - CIBW_BEFORE_ALL_LINUX: "pip install conan && conan profile detect && conan install --requires=m4/1.4.19 --build=m4*" - # Tests under QEMU are extremely slow; skip them for these arches. - CIBW_TEST_SKIP: "*" + # - name: Set up QEMU + # uses: docker/setup-qemu-action@v4 - - uses: actions/upload-artifact@v6 - with: - name: cibw-wheels-${{ matrix.arch }} - path: ./wheelhouse/*.whl + # - name: Build wheels + # uses: pypa/cibuildwheel@v3.4.1 + # with: + # output-dir: wheelhouse + # env: + # CIBW_ARCHS: ${{ matrix.arch }} + # CIBW_SKIP: "cp38-*" + # CIBW_BEFORE_ALL_LINUX: "pip install conan && conan profile detect && conan install --requires=m4/1.4.19 --build=m4*" + # # Tests under QEMU are extremely slow; skip them for these arches. + # CIBW_TEST_SKIP: "*" + + # - uses: actions/upload-artifact@v6 + # with: + # name: cibw-wheels-${{ matrix.arch }} + # path: ./wheelhouse/*.whl build_sdist: name: Build source distribution From d96831dbaa2ce0ef41742a8e70aed5c39e16565b Mon Sep 17 00:00:00 2001 From: Carlos Zoido Date: Fri, 12 Jun 2026 10:06:14 +0200 Subject: [PATCH 18/31] use variables --- conanfile.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/conanfile.py b/conanfile.py index a7cf9d2ce..56bb53027 100644 --- a/conanfile.py +++ b/conanfile.py @@ -17,9 +17,9 @@ def layout(self): def generate(self): tc = CMakeToolchain(self) - tc.cache_variables["Python3_EXECUTABLE"] = sys.executable - tc.cache_variables["Python3_INCLUDE_DIR"] = sysconfig.get_path("include") - tc.cache_variables["Python3_SOABI"] = sysconfig.get_config_var("SOABI") + tc.variables["Python3_EXECUTABLE"] = sys.executable + tc.variables["Python3_INCLUDE_DIR"] = sysconfig.get_path("include") + tc.variables["Python3_SOABI"] = sysconfig.get_config_var("SOABI") or "" tc.generate() CMakeDeps(self).generate() From be309139e67bbe28dd0cc15bf607a8edf583ea86 Mon Sep 17 00:00:00 2001 From: Carlos Zoido Date: Fri, 12 Jun 2026 10:14:14 +0200 Subject: [PATCH 19/31] transform path --- conanfile.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/conanfile.py b/conanfile.py index 56bb53027..f4e2ca08e 100644 --- a/conanfile.py +++ b/conanfile.py @@ -1,5 +1,6 @@ import sys import sysconfig +from pathlib import Path from conan import ConanFile from conan.tools.cmake import CMake, CMakeDeps, CMakeToolchain, cmake_layout @@ -17,8 +18,8 @@ def layout(self): def generate(self): tc = CMakeToolchain(self) - tc.variables["Python3_EXECUTABLE"] = sys.executable - tc.variables["Python3_INCLUDE_DIR"] = sysconfig.get_path("include") + tc.variables["Python3_EXECUTABLE"] = Path(sys.executable).as_posix() + tc.variables["Python3_INCLUDE_DIR"] = Path(sysconfig.get_path("include")).as_posix() tc.variables["Python3_SOABI"] = sysconfig.get_config_var("SOABI") or "" tc.generate() CMakeDeps(self).generate() From 621a0c4372305dcb84186098433a288b5c5dedc7 Mon Sep 17 00:00:00 2001 From: Carlos Zoido Date: Fri, 12 Jun 2026 11:16:54 +0200 Subject: [PATCH 20/31] set PYTHON3_SOABI_HINT --- CMakeLists.txt | 5 +++++ conanfile.py | 9 ++++++--- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d9d883bc1..d3404d59e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,6 +2,11 @@ cmake_minimum_required(VERSION 3.15) project(pycapnp LANGUAGES CXX) find_package(Python3 REQUIRED COMPONENTS Interpreter Development.Module) +# FindPython3 clears Python3_SOABI via PARENT_SCOPE when CMAKE_OSX_ARCHITECTURES differs +# from the runner arch (macOS cross-compile). Restore from the Conan-provided hint. +if(PYTHON3_SOABI_HINT AND NOT Python3_SOABI) + set(Python3_SOABI "${PYTHON3_SOABI_HINT}") +endif() find_package(CapnProto REQUIRED) set(CAPNP_PYX "${CMAKE_SOURCE_DIR}/capnp/lib/capnp.pyx") diff --git a/conanfile.py b/conanfile.py index f4e2ca08e..603b6f716 100644 --- a/conanfile.py +++ b/conanfile.py @@ -18,9 +18,12 @@ def layout(self): def generate(self): tc = CMakeToolchain(self) - tc.variables["Python3_EXECUTABLE"] = Path(sys.executable).as_posix() - tc.variables["Python3_INCLUDE_DIR"] = Path(sysconfig.get_path("include")).as_posix() - tc.variables["Python3_SOABI"] = sysconfig.get_config_var("SOABI") or "" + tc.cache_variables["Python3_EXECUTABLE"] = Path(sys.executable).as_posix() + tc.cache_variables["Python3_INCLUDE_DIR"] = Path(sysconfig.get_path("include")).as_posix() + # FindPython3 overwrites Python3_SOABI via PARENT_SCOPE on macOS cross-compile + # (CMAKE_OSX_ARCHITECTURES != runner arch), clearing any pre-set value. Pass the + # correct SOABI under a different name; CMakeLists.txt restores it after find_package. + tc.cache_variables["PYTHON3_SOABI_HINT"] = sysconfig.get_config_var("SOABI") or "" tc.generate() CMakeDeps(self).generate() From 2ff4274adfde4dc3e603338778e4e041ab577533 Mon Sep 17 00:00:00 2001 From: Carlos Zoido Date: Fri, 12 Jun 2026 11:41:10 +0200 Subject: [PATCH 21/31] set Python3_SOABI in CMakeLists --- CMakeLists.txt | 14 ++++++++++---- conanfile.py | 4 ---- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d3404d59e..60210e9b7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,10 +2,16 @@ cmake_minimum_required(VERSION 3.15) project(pycapnp LANGUAGES CXX) find_package(Python3 REQUIRED COMPONENTS Interpreter Development.Module) -# FindPython3 clears Python3_SOABI via PARENT_SCOPE when CMAKE_OSX_ARCHITECTURES differs -# from the runner arch (macOS cross-compile). Restore from the Conan-provided hint. -if(PYTHON3_SOABI_HINT AND NOT Python3_SOABI) - set(Python3_SOABI "${PYTHON3_SOABI_HINT}") +# FindPython3 skips SOABI detection when CMAKE_OSX_ARCHITECTURES differs from the runner +# arch (e.g. x86_64 wheel on arm64 runner), leaving Python3_SOABI empty. On macOS, +# Rosetta 2 can transparently execute the cross-compile target Python, so re-derive it. +if(APPLE AND NOT Python3_SOABI) + execute_process( + COMMAND "${Python3_EXECUTABLE}" -c + "import sysconfig; print(sysconfig.get_config_var('SOABI') or '', end='')" + OUTPUT_VARIABLE Python3_SOABI + OUTPUT_STRIP_TRAILING_WHITESPACE + ) endif() find_package(CapnProto REQUIRED) diff --git a/conanfile.py b/conanfile.py index 603b6f716..82ac6da43 100644 --- a/conanfile.py +++ b/conanfile.py @@ -20,10 +20,6 @@ def generate(self): tc = CMakeToolchain(self) tc.cache_variables["Python3_EXECUTABLE"] = Path(sys.executable).as_posix() tc.cache_variables["Python3_INCLUDE_DIR"] = Path(sysconfig.get_path("include")).as_posix() - # FindPython3 overwrites Python3_SOABI via PARENT_SCOPE on macOS cross-compile - # (CMAKE_OSX_ARCHITECTURES != runner arch), clearing any pre-set value. Pass the - # correct SOABI under a different name; CMakeLists.txt restores it after find_package. - tc.cache_variables["PYTHON3_SOABI_HINT"] = sysconfig.get_config_var("SOABI") or "" tc.generate() CMakeDeps(self).generate() From 30be05b6a43b5c58430e87256ab6e9116bbc76e1 Mon Sep 17 00:00:00 2001 From: Carlos Zoido Date: Fri, 12 Jun 2026 12:05:41 +0200 Subject: [PATCH 22/31] minor changes --- conanfile.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/conanfile.py b/conanfile.py index 82ac6da43..762ef1238 100644 --- a/conanfile.py +++ b/conanfile.py @@ -1,6 +1,5 @@ import sys import sysconfig -from pathlib import Path from conan import ConanFile from conan.tools.cmake import CMake, CMakeDeps, CMakeToolchain, cmake_layout @@ -18,8 +17,8 @@ def layout(self): def generate(self): tc = CMakeToolchain(self) - tc.cache_variables["Python3_EXECUTABLE"] = Path(sys.executable).as_posix() - tc.cache_variables["Python3_INCLUDE_DIR"] = Path(sysconfig.get_path("include")).as_posix() + tc.cache_variables["Python3_EXECUTABLE"] = sys.executable + tc.cache_variables["Python3_INCLUDE_DIR"] = sysconfig.get_path("include") tc.generate() CMakeDeps(self).generate() From 48e6bb108a2a68ffb5b26122f7a1372cbc133253 Mon Sep 17 00:00:00 2001 From: Carlos Zoido Date: Fri, 12 Jun 2026 14:06:30 +0200 Subject: [PATCH 23/31] simplify --- CMakeLists.txt | 10 ---------- conanfile.py | 4 ++++ 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 60210e9b7..8a6c13ddd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -65,13 +65,3 @@ install(TARGETS capnp_ext DESTINATION capnp/lib) install(FILES "${CMAKE_CURRENT_BINARY_DIR}/capnp/lib/capnp_api.h" DESTINATION capnp/lib) - -get_target_property(_capnp_inc_dirs CapnProto::capnp INTERFACE_INCLUDE_DIRECTORIES) -foreach(_inc_dir IN LISTS _capnp_inc_dirs) - string(REGEX REPLACE "\\$<\\$]+>:([^>]+)>" "\\1" _inc_dir_resolved "${_inc_dir}") - if(EXISTS "${_inc_dir_resolved}/capnp/schema.capnp") - file(GLOB _capnp_schemas "${_inc_dir_resolved}/capnp/*.capnp") - install(FILES ${_capnp_schemas} DESTINATION capnp) - break() - endif() -endforeach() diff --git a/conanfile.py b/conanfile.py index 762ef1238..d51ecbc7d 100644 --- a/conanfile.py +++ b/conanfile.py @@ -1,8 +1,10 @@ +import os import sys import sysconfig from conan import ConanFile from conan.tools.cmake import CMake, CMakeDeps, CMakeToolchain, cmake_layout +from conan.tools.files import copy class PycapnpConan(ConanFile): @@ -30,3 +32,5 @@ def build(self): def package(self): cmake = CMake(self) cmake.install() + capnp_include = os.path.join(str(self.dependencies["capnproto"].package_folder), "include", "capnp") + copy(self, "*.capnp", src=capnp_include, dst=os.path.join(self.package_folder, "capnp")) From 26d97c289623bada51e313081b458c27a5faba21 Mon Sep 17 00:00:00 2001 From: Carlos Zoido Date: Sat, 13 Jun 2026 08:27:54 +0200 Subject: [PATCH 24/31] exclude subdir schemas --- conanfile.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/conanfile.py b/conanfile.py index d51ecbc7d..3aad5c616 100644 --- a/conanfile.py +++ b/conanfile.py @@ -33,4 +33,5 @@ def package(self): cmake = CMake(self) cmake.install() capnp_include = os.path.join(str(self.dependencies["capnproto"].package_folder), "include", "capnp") - copy(self, "*.capnp", src=capnp_include, dst=os.path.join(self.package_folder, "capnp")) + # excludes="*/*" skips subdirectories, top-level schemas only + copy(self, "*.capnp", src=capnp_include, dst=os.path.join(self.package_folder, "capnp"), excludes="*/*") From f8c6072ad20570a06491292e95ef7f6ea49bf493 Mon Sep 17 00:00:00 2001 From: Carlos Zoido Date: Sat, 13 Jun 2026 09:06:01 +0200 Subject: [PATCH 25/31] build exotic --- .github/workflows/wheels.yml | 61 ++++++++++++++++++++---------------- 1 file changed, 34 insertions(+), 27 deletions(-) diff --git a/.github/workflows/wheels.yml b/.github/workflows/wheels.yml index 35a3b73ba..3e07c6253 100644 --- a/.github/workflows/wheels.yml +++ b/.github/workflows/wheels.yml @@ -58,35 +58,42 @@ jobs: # Exotic arches built via QEMU emulation — very slow (often >1h), so only run # on release tags rather than every push/PR. - # build_wheels_exotic: - # name: Build wheels (exotic) ${{ matrix.arch }} - # if: startsWith(github.ref, 'refs/tags/v') || github.ref == 'refs/heads/conan-py-build' - # runs-on: ubuntu-latest - # strategy: - # fail-fast: false - # matrix: - # arch: [ppc64le, s390x] - # steps: - # - uses: actions/checkout@v5 + build_wheels_exotic: + name: Build wheels (exotic) ${{ matrix.arch }} + if: startsWith(github.ref, 'refs/tags/v') || github.ref == 'refs/heads/conan-py-build' + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + arch: [ppc64le, s390x] + steps: + - uses: actions/checkout@v5 - # - name: Set up QEMU - # uses: docker/setup-qemu-action@v4 + - name: Set up QEMU + uses: docker/setup-qemu-action@v4 - # - name: Build wheels - # uses: pypa/cibuildwheel@v3.4.1 - # with: - # output-dir: wheelhouse - # env: - # CIBW_ARCHS: ${{ matrix.arch }} - # CIBW_SKIP: "cp38-*" - # CIBW_BEFORE_ALL_LINUX: "pip install conan && conan profile detect && conan install --requires=m4/1.4.19 --build=m4*" - # # Tests under QEMU are extremely slow; skip them for these arches. - # CIBW_TEST_SKIP: "*" - - # - uses: actions/upload-artifact@v6 - # with: - # name: cibw-wheels-${{ matrix.arch }} - # path: ./wheelhouse/*.whl + - name: Restore Conan cache + uses: actions/cache@v4 + with: + path: ~/.conan2/p + key: conan-exotic-${{ matrix.arch }}-${{ hashFiles('conanfile.py') }} + restore-keys: conan-exotic-${{ matrix.arch }}- + + - name: Build wheels + uses: pypa/cibuildwheel@v3.4.1 + with: + output-dir: wheelhouse + env: + CIBW_ARCHS: ${{ matrix.arch }} + CIBW_SKIP: "cp38-*" + CIBW_BEFORE_ALL_LINUX: "pip install conan && conan profile detect && conan install --requires=m4/1.4.19 --build=m4*" + # Tests under QEMU are extremely slow; skip them for these arches. + CIBW_TEST_SKIP: "*" + + - uses: actions/upload-artifact@v6 + with: + name: cibw-wheels-${{ matrix.arch }} + path: ./wheelhouse/*.whl build_sdist: name: Build source distribution From a80b92b137d627c09a08367e9062582b668d87f6 Mon Sep 17 00:00:00 2001 From: Carlos Zoido Date: Sat, 13 Jun 2026 20:40:46 +0200 Subject: [PATCH 26/31] try to cache --- .github/workflows/wheels.yml | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/.github/workflows/wheels.yml b/.github/workflows/wheels.yml index 3e07c6253..9e86b4a4e 100644 --- a/.github/workflows/wheels.yml +++ b/.github/workflows/wheels.yml @@ -38,6 +38,15 @@ jobs: steps: - uses: actions/checkout@v5 + - name: Restore Conan cache + uses: actions/cache@v4 + with: + path: | + ${{ github.workspace }}/.conan_home + ~/.conan2/p + key: conan-${{ matrix.os }}-${{ matrix.arch }}-${{ hashFiles('conanfile.py') }} + restore-keys: conan-${{ matrix.os }}-${{ matrix.arch }}- + - name: Build wheels uses: pypa/cibuildwheel@v3.4.1 with: @@ -49,7 +58,10 @@ jobs: CIBW_TEST_COMMAND: pytest {project} # Pre-build m4 from source inside manylinux so Conan uses a glibc-2.28-compatible # binary instead of ConanCenter's Ubuntu binary (glibc 2.35, crashes in manylinux_2_28). - CIBW_BEFORE_ALL_LINUX: "pip install conan && conan profile detect && conan install --requires=m4/1.4.19 --build=m4*" + # CONAN_HOME points to the project dir so the cache persists to the host runner. + # --force regenerates the compiler profile for each container image (manylinux vs musllinux). + CIBW_ENVIRONMENT_LINUX: CONAN_HOME=/project/.conan_home + CIBW_BEFORE_ALL_LINUX: "pip install conan && conan profile detect --force && conan install --requires=m4/1.4.19 --build=m4*" - uses: actions/upload-artifact@v6 with: @@ -75,7 +87,7 @@ jobs: - name: Restore Conan cache uses: actions/cache@v4 with: - path: ~/.conan2/p + path: ${{ github.workspace }}/.conan_home key: conan-exotic-${{ matrix.arch }}-${{ hashFiles('conanfile.py') }} restore-keys: conan-exotic-${{ matrix.arch }}- @@ -86,7 +98,8 @@ jobs: env: CIBW_ARCHS: ${{ matrix.arch }} CIBW_SKIP: "cp38-*" - CIBW_BEFORE_ALL_LINUX: "pip install conan && conan profile detect && conan install --requires=m4/1.4.19 --build=m4*" + CIBW_ENVIRONMENT_LINUX: CONAN_HOME=/project/.conan_home + CIBW_BEFORE_ALL_LINUX: "pip install conan && conan profile detect --force && conan install --requires=m4/1.4.19 --build=m4*" # Tests under QEMU are extremely slow; skip them for these arches. CIBW_TEST_SKIP: "*" From 6704eb83450c6251b62514f17e4c2f496ab724ab Mon Sep 17 00:00:00 2001 From: Carlos Zoido Date: Sun, 14 Jun 2026 17:53:19 +0200 Subject: [PATCH 27/31] trigger CI From 254ee6c27c96e54e97fd458124e0e177a714ef57 Mon Sep 17 00:00:00 2001 From: Carlos Zoido Date: Mon, 15 Jun 2026 07:19:08 +0200 Subject: [PATCH 28/31] try to cache --- .github/workflows/wheels.yml | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/.github/workflows/wheels.yml b/.github/workflows/wheels.yml index 9e86b4a4e..41dce1443 100644 --- a/.github/workflows/wheels.yml +++ b/.github/workflows/wheels.yml @@ -41,12 +41,14 @@ jobs: - name: Restore Conan cache uses: actions/cache@v4 with: - path: | - ${{ github.workspace }}/.conan_home - ~/.conan2/p + path: ~/.conan2/p key: conan-${{ matrix.os }}-${{ matrix.arch }}-${{ hashFiles('conanfile.py') }} restore-keys: conan-${{ matrix.os }}-${{ matrix.arch }}- + - name: Ensure Conan package dir exists + run: mkdir -p ~/.conan2/p + shell: bash + - name: Build wheels uses: pypa/cibuildwheel@v3.4.1 with: @@ -56,11 +58,10 @@ jobs: CIBW_SKIP: "cp38-*" CIBW_TEST_REQUIRES: pytest pytest-asyncio CIBW_TEST_COMMAND: pytest {project} - # Pre-build m4 from source inside manylinux so Conan uses a glibc-2.28-compatible - # binary instead of ConanCenter's Ubuntu binary (glibc 2.35, crashes in manylinux_2_28). - # CONAN_HOME points to the project dir so the cache persists to the host runner. + # Mount the runner's ~/.conan2 directly into the container so packages built + # inside (m4, capnproto) persist to the host and are cached by actions/cache. # --force regenerates the compiler profile for each container image (manylinux vs musllinux). - CIBW_ENVIRONMENT_LINUX: CONAN_HOME=/project/.conan_home + CIBW_CONTAINER_ENGINE: "docker; create_args: -v /home/runner/.conan2:/root/.conan2" CIBW_BEFORE_ALL_LINUX: "pip install conan && conan profile detect --force && conan install --requires=m4/1.4.19 --build=m4*" - uses: actions/upload-artifact@v6 @@ -87,10 +88,13 @@ jobs: - name: Restore Conan cache uses: actions/cache@v4 with: - path: ${{ github.workspace }}/.conan_home + path: ~/.conan2/p key: conan-exotic-${{ matrix.arch }}-${{ hashFiles('conanfile.py') }} restore-keys: conan-exotic-${{ matrix.arch }}- + - name: Ensure Conan package dir exists + run: mkdir -p ~/.conan2/p + - name: Build wheels uses: pypa/cibuildwheel@v3.4.1 with: @@ -98,7 +102,7 @@ jobs: env: CIBW_ARCHS: ${{ matrix.arch }} CIBW_SKIP: "cp38-*" - CIBW_ENVIRONMENT_LINUX: CONAN_HOME=/project/.conan_home + CIBW_CONTAINER_ENGINE: "docker; create_args: -v /home/runner/.conan2:/root/.conan2" CIBW_BEFORE_ALL_LINUX: "pip install conan && conan profile detect --force && conan install --requires=m4/1.4.19 --build=m4*" # Tests under QEMU are extremely slow; skip them for these arches. CIBW_TEST_SKIP: "*" From e11d07729e6493da864d01a1988332878e6857ec Mon Sep 17 00:00:00 2001 From: Carlos Zoido Date: Mon, 15 Jun 2026 07:54:47 +0200 Subject: [PATCH 29/31] wip --- .github/workflows/wheels.yml | 79 +++++++++++++++++------------------- 1 file changed, 38 insertions(+), 41 deletions(-) diff --git a/.github/workflows/wheels.yml b/.github/workflows/wheels.yml index 41dce1443..5c436c6b2 100644 --- a/.github/workflows/wheels.yml +++ b/.github/workflows/wheels.yml @@ -41,12 +41,12 @@ jobs: - name: Restore Conan cache uses: actions/cache@v4 with: - path: ~/.conan2/p + path: ~/.conan2-cibw/p key: conan-${{ matrix.os }}-${{ matrix.arch }}-${{ hashFiles('conanfile.py') }} restore-keys: conan-${{ matrix.os }}-${{ matrix.arch }}- - name: Ensure Conan package dir exists - run: mkdir -p ~/.conan2/p + run: mkdir -p ~/.conan2-cibw/p shell: bash - name: Build wheels @@ -58,10 +58,7 @@ jobs: CIBW_SKIP: "cp38-*" CIBW_TEST_REQUIRES: pytest pytest-asyncio CIBW_TEST_COMMAND: pytest {project} - # Mount the runner's ~/.conan2 directly into the container so packages built - # inside (m4, capnproto) persist to the host and are cached by actions/cache. # --force regenerates the compiler profile for each container image (manylinux vs musllinux). - CIBW_CONTAINER_ENGINE: "docker; create_args: -v /home/runner/.conan2:/root/.conan2" CIBW_BEFORE_ALL_LINUX: "pip install conan && conan profile detect --force && conan install --requires=m4/1.4.19 --build=m4*" - uses: actions/upload-artifact@v6 @@ -71,46 +68,46 @@ jobs: # Exotic arches built via QEMU emulation — very slow (often >1h), so only run # on release tags rather than every push/PR. - build_wheels_exotic: - name: Build wheels (exotic) ${{ matrix.arch }} - if: startsWith(github.ref, 'refs/tags/v') || github.ref == 'refs/heads/conan-py-build' - runs-on: ubuntu-latest - strategy: - fail-fast: false - matrix: - arch: [ppc64le, s390x] - steps: - - uses: actions/checkout@v5 + # build_wheels_exotic: + # name: Build wheels (exotic) ${{ matrix.arch }} + # if: startsWith(github.ref, 'refs/tags/v') || github.ref == 'refs/heads/conan-py-build' + # runs-on: ubuntu-latest + # strategy: + # fail-fast: false + # matrix: + # arch: [ppc64le, s390x] + # steps: + # - uses: actions/checkout@v5 - - name: Set up QEMU - uses: docker/setup-qemu-action@v4 + # - name: Set up QEMU + # uses: docker/setup-qemu-action@v4 - - name: Restore Conan cache - uses: actions/cache@v4 - with: - path: ~/.conan2/p - key: conan-exotic-${{ matrix.arch }}-${{ hashFiles('conanfile.py') }} - restore-keys: conan-exotic-${{ matrix.arch }}- + # - name: Restore Conan cache + # uses: actions/cache@v4 + # with: + # path: ~/.conan2/p + # key: conan-exotic-${{ matrix.arch }}-${{ hashFiles('conanfile.py') }} + # restore-keys: conan-exotic-${{ matrix.arch }}- - - name: Ensure Conan package dir exists - run: mkdir -p ~/.conan2/p + # - name: Ensure Conan package dir exists + # run: mkdir -p ~/.conan2/p - - name: Build wheels - uses: pypa/cibuildwheel@v3.4.1 - with: - output-dir: wheelhouse - env: - CIBW_ARCHS: ${{ matrix.arch }} - CIBW_SKIP: "cp38-*" - CIBW_CONTAINER_ENGINE: "docker; create_args: -v /home/runner/.conan2:/root/.conan2" - CIBW_BEFORE_ALL_LINUX: "pip install conan && conan profile detect --force && conan install --requires=m4/1.4.19 --build=m4*" - # Tests under QEMU are extremely slow; skip them for these arches. - CIBW_TEST_SKIP: "*" - - - uses: actions/upload-artifact@v6 - with: - name: cibw-wheels-${{ matrix.arch }} - path: ./wheelhouse/*.whl + # - name: Build wheels + # uses: pypa/cibuildwheel@v3.4.1 + # with: + # output-dir: wheelhouse + # env: + # CIBW_ARCHS: ${{ matrix.arch }} + # CIBW_SKIP: "cp38-*" + # CIBW_CONTAINER_ENGINE: "docker; create_args: -v /home/runner/.conan2:/root/.conan2" + # CIBW_BEFORE_ALL_LINUX: "pip install conan && conan profile detect --force && conan install --requires=m4/1.4.19 --build=m4*" + # # Tests under QEMU are extremely slow; skip them for these arches. + # CIBW_TEST_SKIP: "*" + + # - uses: actions/upload-artifact@v6 + # with: + # name: cibw-wheels-${{ matrix.arch }} + # path: ./wheelhouse/*.whl build_sdist: name: Build source distribution From 8838004b2af25da58b4be402ab680d479ee6506b Mon Sep 17 00:00:00 2001 From: Carlos Zoido Date: Mon, 15 Jun 2026 08:09:26 +0200 Subject: [PATCH 30/31] revert changes --- .github/workflows/wheels.yml | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/.github/workflows/wheels.yml b/.github/workflows/wheels.yml index 5c436c6b2..b23666b04 100644 --- a/.github/workflows/wheels.yml +++ b/.github/workflows/wheels.yml @@ -38,17 +38,6 @@ jobs: steps: - uses: actions/checkout@v5 - - name: Restore Conan cache - uses: actions/cache@v4 - with: - path: ~/.conan2-cibw/p - key: conan-${{ matrix.os }}-${{ matrix.arch }}-${{ hashFiles('conanfile.py') }} - restore-keys: conan-${{ matrix.os }}-${{ matrix.arch }}- - - - name: Ensure Conan package dir exists - run: mkdir -p ~/.conan2-cibw/p - shell: bash - - name: Build wheels uses: pypa/cibuildwheel@v3.4.1 with: @@ -58,7 +47,6 @@ jobs: CIBW_SKIP: "cp38-*" CIBW_TEST_REQUIRES: pytest pytest-asyncio CIBW_TEST_COMMAND: pytest {project} - # --force regenerates the compiler profile for each container image (manylinux vs musllinux). CIBW_BEFORE_ALL_LINUX: "pip install conan && conan profile detect --force && conan install --requires=m4/1.4.19 --build=m4*" - uses: actions/upload-artifact@v6 From 1de64ead297a29920ce1c325e36d7629523fe844 Mon Sep 17 00:00:00 2001 From: Carlos Zoido Date: Mon, 15 Jun 2026 09:49:11 +0200 Subject: [PATCH 31/31] buld exotic too --- .github/workflows/wheels.yml | 63 +++++++++++++++--------------------- 1 file changed, 26 insertions(+), 37 deletions(-) diff --git a/.github/workflows/wheels.yml b/.github/workflows/wheels.yml index b23666b04..dcd4364da 100644 --- a/.github/workflows/wheels.yml +++ b/.github/workflows/wheels.yml @@ -56,46 +56,35 @@ jobs: # Exotic arches built via QEMU emulation — very slow (often >1h), so only run # on release tags rather than every push/PR. - # build_wheels_exotic: - # name: Build wheels (exotic) ${{ matrix.arch }} - # if: startsWith(github.ref, 'refs/tags/v') || github.ref == 'refs/heads/conan-py-build' - # runs-on: ubuntu-latest - # strategy: - # fail-fast: false - # matrix: - # arch: [ppc64le, s390x] - # steps: - # - uses: actions/checkout@v5 - - # - name: Set up QEMU - # uses: docker/setup-qemu-action@v4 + build_wheels_exotic: + name: Build wheels (exotic) ${{ matrix.arch }} + if: startsWith(github.ref, 'refs/tags/v') || github.ref == 'refs/heads/conan-py-build' + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + arch: [ppc64le, s390x] + steps: + - uses: actions/checkout@v5 - # - name: Restore Conan cache - # uses: actions/cache@v4 - # with: - # path: ~/.conan2/p - # key: conan-exotic-${{ matrix.arch }}-${{ hashFiles('conanfile.py') }} - # restore-keys: conan-exotic-${{ matrix.arch }}- + - name: Set up QEMU + uses: docker/setup-qemu-action@v4 - # - name: Ensure Conan package dir exists - # run: mkdir -p ~/.conan2/p + - name: Build wheels + uses: pypa/cibuildwheel@v3.4.1 + with: + output-dir: wheelhouse + env: + CIBW_ARCHS: ${{ matrix.arch }} + CIBW_SKIP: "cp38-*" + CIBW_BEFORE_ALL_LINUX: "pip install conan && conan profile detect --force && conan install --requires=m4/1.4.19 --build=m4*" + # Tests under QEMU are extremely slow; skip them for these arches. + CIBW_TEST_SKIP: "*" - # - name: Build wheels - # uses: pypa/cibuildwheel@v3.4.1 - # with: - # output-dir: wheelhouse - # env: - # CIBW_ARCHS: ${{ matrix.arch }} - # CIBW_SKIP: "cp38-*" - # CIBW_CONTAINER_ENGINE: "docker; create_args: -v /home/runner/.conan2:/root/.conan2" - # CIBW_BEFORE_ALL_LINUX: "pip install conan && conan profile detect --force && conan install --requires=m4/1.4.19 --build=m4*" - # # Tests under QEMU are extremely slow; skip them for these arches. - # CIBW_TEST_SKIP: "*" - - # - uses: actions/upload-artifact@v6 - # with: - # name: cibw-wheels-${{ matrix.arch }} - # path: ./wheelhouse/*.whl + - uses: actions/upload-artifact@v6 + with: + name: cibw-wheels-${{ matrix.arch }} + path: ./wheelhouse/*.whl build_sdist: name: Build source distribution