From 407343a7a12385bba40e406f68270b95afabb09b Mon Sep 17 00:00:00 2001 From: Mohamed Gaber Date: Mon, 12 Aug 2024 14:21:05 +0300 Subject: [PATCH 1/8] Pyosys Wheels * Created `setup.py`: Python package manifest to build `pyosys` wheels with a custom extension to build and include `libyosys.so` using Make * `.gitignore`: Added byproducts of the Python wheel build process * `Makefile`: Added `-undefined dynamic_lookup` to `libyosys.so` so missing symbols can be resolved by importing into a Python interpreter * `kernel/yosys.cc`: Gated `PyImport_AppendInittab` with `!Py_IsInitialized`; as of Python 3.12, the interpreter is already initialized and `PyImport_AppendInittab` would cause an exception to be raised * Created `wheels.yml`: CI workflow for building wheels for CPython on: * Linux (glibc, musl) and Darwin * x86-64 and arm64 --- .github/workflows/wheels.yml | 111 +++++++++++++++++++++++++++++++++++ .gitignore | 7 ++- Makefile | 2 +- kernel/yosys.cc | 13 ++-- setup.py | 97 ++++++++++++++++++++++++++++++ 5 files changed, 224 insertions(+), 6 deletions(-) create mode 100644 .github/workflows/wheels.yml create mode 100644 setup.py diff --git a/.github/workflows/wheels.yml b/.github/workflows/wheels.yml new file mode 100644 index 00000000000..9f3394d84ed --- /dev/null +++ b/.github/workflows/wheels.yml @@ -0,0 +1,111 @@ +name: Build Wheels for PyPI +on: + workflow_dispatch: + push: + # tags: ["yosys-*"] +jobs: + build_wheels: + strategy: + matrix: + os: [ + # You can't cross-compile on Linux, so might as well do the emulated + # workload on its own + { + name: "Ubuntu 22.04", + family: "linux", + runner: "ubuntu-22.04", + archs: "x86_64", + }, + { + name: "Ubuntu 22.04", + family: "linux", + runner: "ubuntu-22.04", + archs: "aarch64", + }, + # While you can cross-compile on macOS, this is less of a headache + { + name: "macOS 13", + family: "macos", + runner: "macos-13", + archs: "x86_64", + }, + { + name: "macOS 14", + family: "macos", + runner: "macos-14", + archs: "arm64", + }, + # TODO: Make Windows Work + # { + # name: "Windows Server 2019", + # family: "windows", + # runner: "windows-2019", + # archs: "AMD64 ARM64", + # }, + ] + name: Build Wheels | ${{ matrix.os.name }} | ${{ matrix.os.archs }} + runs-on: ${{ matrix.os.runner }} + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 0 + submodules: true + - if: ${{ matrix.os.family == 'linux' }} + name: "[Linux] Set up QEMU" + uses: docker/setup-qemu-action@v2 + - uses: actions/setup-python@v3 + - name: Get Boost Source + run: | + mkdir -p boost + curl -L https://sourceforge.net/projects/boost/files/boost/1.83.0/boost_1_83_0.tar.bz2 | tar --strip-components=1 -xjC boost + - name: Seed Makefile.bak + # For every sed, a .bak is created so it can be copied over Makefile to + # rever the change for the next Python version to be built. + # + # This creates a .bak for the first Python version's cp to consume. + run: | + cp Makefile Makefile.bak + - if: ${{ matrix.os.family == 'macos' }} + name: "[macOS] Flex/Bison" + run: | + brew install flex bison + echo "PATH=$(brew --prefix flex)/bin:$PATH" >> $GITHUB_ENV + echo "PATH=$(brew --prefix bison)/bin:$PATH" >> $GITHUB_ENV + - if: ${{ matrix.os.family == 'macos' && matrix.os.archs == 'arm64' }} + name: "[macOS/arm64] Install Python 3.8 (see: https://cibuildwheel.pypa.io/en/stable/faq/#macos-building-cpython-38-wheels-on-arm64)" + uses: actions/setup-python@v5 + with: + python-version: 3.8 + - name: Build wheels + uses: pypa/cibuildwheel@v2.20.0 + env: + # Explaining the build steps: + # 1. Revert previous seds (if any) + # 2. Delete the libboost static archives from previous builds (if any) + # 3. Navigate to boost source extracted in previous GHA step + # 4-5. Build Boost against current version of Python, only for + # static linkage + # (Boost is statically linked because system boost packages + # wildly vary in versions, including the libboost_python3 + # version) + # 6-7. Return to package directory and sed the Makefile to point at + # the newly compiled libboost_python + CIBW_SKIP: pp* # The Makefile requires python3-config which is not in pypy + CIBW_ARCHS: ${{ matrix.os.archs }} + CIBW_BUILD_VERBOSITY: "1" + CIBW_BEFORE_ALL_LINUX: yum install -y libffi-devel flex bison || apk add libffi-dev flex bison + CIBW_BEFORE_ALL_MAC: brew install libffi + CIBW_BEFORE_BUILD: | + cp Makefile.bak Makefile &&\ + cd ./boost &&\ + rm -rf ./pfx &&\ + ./bootstrap.sh --prefix=./pfx &&\ + ./b2 --prefix=./pfx --with-filesystem --with-system --with-python cxxflags="$(python3-config --includes) -std=c++17 -fPIC" cflags="$(python3-config --includes) -fPIC" link=static variant=release install &&\ + ls ./pfx/lib/libboost_python*.a &&\ + cd {package} &&\ + sed -i'.bak' -e "1i\\ + LINKFLAGS = -L./boost/pfx/lib" -e "1i\\ + CXXFLAGS = -I./boost/pfx/include" -e "s@BOOST_PYTHON_LIB ?=@BOOST_PYTHON_LIB = $(ls ./boost/pfx/lib/libboost_python*.a)\nTrash =@" Makefile + - uses: actions/upload-artifact@v3 + with: + path: ./dist/*.whl diff --git a/.gitignore b/.gitignore index e82343e8947..5d6a466db68 100644 --- a/.gitignore +++ b/.gitignore @@ -45,4 +45,9 @@ __pycache__ /tests/unit/bintest/ /tests/unit/objtest/ /tests/ystests -/result \ No newline at end of file +/result +/dist +/*.egg-info +/build +/venv +/boost diff --git a/Makefile b/Makefile index 5b6fc3ff25d..ebea193cfd9 100644 --- a/Makefile +++ b/Makefile @@ -742,7 +742,7 @@ $(PROGRAM_PREFIX)yosys$(EXE): $(OBJS) libyosys.so: $(filter-out kernel/driver.o,$(OBJS)) ifeq ($(OS), Darwin) - $(P) $(CXX) -o libyosys.so -shared -Wl,-install_name,$(LIBDIR)/libyosys.so $(LINKFLAGS) $^ $(LIBS) $(LIBS_VERIFIC) + $(P) $(CXX) -o libyosys.so -shared -undefined dynamic_lookup -Wl,-install_name,$(LIBDIR)/libyosys.so $(LINKFLAGS) $^ $(LIBS) $(LIBS_VERIFIC) else $(P) $(CXX) -o libyosys.so -shared -Wl,-soname,$(LIBDIR)/libyosys.so $(LINKFLAGS) $^ $(LIBS) $(LIBS_VERIFIC) endif diff --git a/kernel/yosys.cc b/kernel/yosys.cc index efdc54b796c..510151479b6 100644 --- a/kernel/yosys.cc +++ b/kernel/yosys.cc @@ -555,10 +555,15 @@ void yosys_setup() #undef X #ifdef WITH_PYTHON - PyImport_AppendInittab((char*)"libyosys", INIT_MODULE); - Py_Initialize(); - PyRun_SimpleString("import sys"); - signal(SIGINT, SIG_DFL); + // With Python 3.12, calling PyImport_AppendInittab on an already + // initialized platform fails (such as when libyosys is imported + // from a Python interpreter) + if (!Py_IsInitialized()) { + PyImport_AppendInittab((char*)"libyosys", INIT_MODULE); + Py_Initialize(); + PyRun_SimpleString("import sys"); + signal(SIGINT, SIG_DFL); + } #endif Pass::init_register(); diff --git a/setup.py b/setup.py new file mode 100644 index 00000000000..02e6e5843de --- /dev/null +++ b/setup.py @@ -0,0 +1,97 @@ +#!/usr/bin/env python3 +# Copyright (C) 2024 Efabless Corporation +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +import os +import re +import shlex +import shutil +from setuptools import setup, Extension +from setuptools.command.build_ext import build_ext + +__dir__ = os.path.dirname(os.path.abspath(__file__)) + +yosys_version_rx = re.compile(r"YOSYS_VER\s*:=\s*([\w\-\+\.]+)") + +version = yosys_version_rx.search( + open(os.path.join(__dir__, "Makefile"), encoding="utf8").read() +)[1] + + +class libyosys_so_ext(Extension): + def __init__( + self, + ) -> None: + super().__init__( + "libyosys.so", + [], + ) + self.args = [ + "ENABLE_PYOSYS=1", + # Wheel meant to be imported from interpreter + "ENABLE_PYTHON_CONFIG_EMBED=0", + # Would need to be installed separately by the user + "ENABLE_TCL=0", + # Would need to be installed separately by the user + "ENABLE_READLINE=0", + # Show compile commands + "PRETTY=0", + ] + + def custom_build(self, bext: build_ext): + bext.spawn( + ["make", f"-j{os.cpu_count() or 1}", self.name] + + shlex.split(os.getenv("makeFlags", "")) + + self.args + ) + build_path = os.path.dirname(os.path.dirname(bext.get_ext_fullpath(self.name))) + pyosys_path = os.path.join(build_path, "pyosys") + target = os.path.join(pyosys_path, os.path.basename(self.name)) + os.makedirs(pyosys_path, exist_ok=True) + shutil.copyfile(self.name, target) + + # I don't know how debug info is getting here. + bext.spawn(["strip", "-S", target]) + + +class custom_build_ext(build_ext): + def build_extension(self, ext) -> None: + if not hasattr(ext, "custom_build"): + return super().build_extension(ext) + return ext.custom_build(self) + + +setup( + name="pyosys", + packages=["pyosys"], + version=version, + description="Python access to libyosys", + long_description=open(os.path.join(__dir__, "README.md")).read(), + long_description_content_type="text/markdown", + author="Claire Xenia Wolf", + author_email="claire@yosyshq.com", + install_requires=["wheel", "setuptools"], + classifiers=[ + "License :: OSI Approved :: MIT License", + "Programming Language :: Python :: 3", + "Intended Audience :: Developers", + "Operating System :: POSIX :: Linux", + "Operating System :: MacOS :: MacOS X", + ], + package_dir={"pyosys": "misc"}, + python_requires=">=3.8", + ext_modules=[libyosys_so_ext()], + cmdclass={ + "build_ext": custom_build_ext, + }, +) From ab4ea84679a9af5fa6172a4b4ce55c86d7a1ac5c Mon Sep 17 00:00:00 2001 From: Mohamed Gaber Date: Sat, 28 Sep 2024 21:03:43 +0300 Subject: [PATCH 2/8] wheels: more compatibility * Update manylinux images * FFI now built as a per-platform static library * Explicitly set minimum macOS deployment target, use clang on macOS * Try enabling Windows (as an experiment) * Disable aarch64-linux, aarch64-windows --- .github/workflows/_run_cibw_linux.py | 44 ++++++++++++ .github/workflows/cibw_before_all.sh | 21 ++++++ .github/workflows/cibw_before_build.sh | 23 +++++++ .github/workflows/wheels.yml | 92 +++++++++++++------------- .gitignore | 1 + 5 files changed, 134 insertions(+), 47 deletions(-) create mode 100644 .github/workflows/_run_cibw_linux.py create mode 100644 .github/workflows/cibw_before_all.sh create mode 100644 .github/workflows/cibw_before_build.sh diff --git a/.github/workflows/_run_cibw_linux.py b/.github/workflows/_run_cibw_linux.py new file mode 100644 index 00000000000..675817ae09a --- /dev/null +++ b/.github/workflows/_run_cibw_linux.py @@ -0,0 +1,44 @@ +#!/usr/bin/env python3 +# Copyright (C) 2024 Efabless Corporation +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +""" +This runs the cibuildwheel step from the wheels workflow locally. +""" + +import os +import yaml +import platform +import subprocess + +__dir__ = os.path.dirname(os.path.abspath(__file__)) + + +workflow = yaml.safe_load(open(os.path.join(__dir__, "wheels.yml"))) + +env = os.environ.copy() + +steps = workflow["jobs"]["build_wheels"]["steps"] +cibw_step = None +for step in steps: + if (step.get("uses") or "").startswith("pypa/cibuildwheel"): + cibw_step = step + break + +for key, value in cibw_step["env"].items(): + if key.endswith("WIN") or key.endswith("MAC"): + continue + env[key] = value + +env["CIBW_ARCHS"] = os.getenv("CIBW_ARCHS") or platform.machine() +subprocess.check_call(["cibuildwheel"], env=env) diff --git a/.github/workflows/cibw_before_all.sh b/.github/workflows/cibw_before_all.sh new file mode 100644 index 00000000000..934902380a4 --- /dev/null +++ b/.github/workflows/cibw_before_all.sh @@ -0,0 +1,21 @@ +set -e +set -x + +# Build-time dependencies +## Linux Docker Images +if command -v yum &> /dev/null; then + yum install -y flex bison +fi + +if command -v apk &> /dev/null; then + apk add flex bison +fi + +## macOS/Windows -- install in GitHub Action itself, not container + +# Build Static FFI (platform-dependent but not Python version dependent) +cd ffi +SHELL=bash CFLAGS=-fPIC CXXFLAGS=-fPIC ./configure --prefix=$PWD/pfx + +make install -j$(getconf _NPROCESSORS_ONLN 2>/dev/null || sysctl -n hw.ncpu) +sed -i.bak 's@-L${toolexeclibdir} -lffi@${toolexeclibdir}/libffi.a@' ./pfx/lib/pkgconfig/libffi.pc diff --git a/.github/workflows/cibw_before_build.sh b/.github/workflows/cibw_before_build.sh new file mode 100644 index 00000000000..03baf110bcd --- /dev/null +++ b/.github/workflows/cibw_before_build.sh @@ -0,0 +1,23 @@ +set -e +set -x + +# Build boost +cd ./boost +## Delete the artefacts from previous builds (if any) +rm -rf ./pfx +## Bootstrap bjam +./bootstrap.sh --prefix=./pfx +## Build Boost against current version of Python, only for +## static linkage (Boost is statically linked because system boost packages +## wildly vary in versions, including the libboost_python3 version) +./b2\ + -j$(getconf _NPROCESSORS_ONLN 2>/dev/null || sysctl -n hw.ncpu)\ + --prefix=./pfx\ + --with-filesystem\ + --with-system\ + --with-python\ + cxxflags="$(python3-config --includes) -std=c++17 -fPIC"\ + cflags="$(python3-config --includes) -fPIC"\ + link=static\ + variant=release\ + install diff --git a/.github/workflows/wheels.yml b/.github/workflows/wheels.yml index 9f3394d84ed..5961f364ae3 100644 --- a/.github/workflows/wheels.yml +++ b/.github/workflows/wheels.yml @@ -6,23 +6,25 @@ on: jobs: build_wheels: strategy: + fail-fast: false matrix: os: [ - # You can't cross-compile on Linux, so might as well do the emulated - # workload on its own { name: "Ubuntu 22.04", family: "linux", runner: "ubuntu-22.04", archs: "x86_64", }, - { - name: "Ubuntu 22.04", - family: "linux", - runner: "ubuntu-22.04", - archs: "aarch64", - }, - # While you can cross-compile on macOS, this is less of a headache + ## Aarch64 is disabled for now: GitHub is committing to EOY + ## for free aarch64 runners for open-source projects and + ## emulation times out: + ## https://github.com/orgs/community/discussions/19197#discussioncomment-10550689 + # { + # name: "Ubuntu 22.04", + # family: "linux", + # runner: "ubuntu-22.04", + # archs: "aarch64", + # }, { name: "macOS 13", family: "macos", @@ -35,13 +37,12 @@ jobs: runner: "macos-14", archs: "arm64", }, - # TODO: Make Windows Work - # { - # name: "Windows Server 2019", - # family: "windows", - # runner: "windows-2019", - # archs: "AMD64 ARM64", - # }, + { + name: "Windows Server 2019", + family: "windows", + runner: "windows-2019", + archs: "AMD64", + }, ] name: Build Wheels | ${{ matrix.os.name }} | ${{ matrix.os.archs }} runs-on: ${{ matrix.os.runner }} @@ -55,22 +56,27 @@ jobs: uses: docker/setup-qemu-action@v2 - uses: actions/setup-python@v3 - name: Get Boost Source + shell: bash run: | mkdir -p boost - curl -L https://sourceforge.net/projects/boost/files/boost/1.83.0/boost_1_83_0.tar.bz2 | tar --strip-components=1 -xjC boost - - name: Seed Makefile.bak - # For every sed, a .bak is created so it can be copied over Makefile to - # rever the change for the next Python version to be built. - # - # This creates a .bak for the first Python version's cp to consume. + curl -L https://github.com/boostorg/boost/releases/download/boost-1.86.0/boost-1.86.0-b2-nodocs.tar.gz | tar --strip-components=1 -xzC boost + - name: Get FFI + shell: bash run: | - cp Makefile Makefile.bak + mkdir -p ffi + curl -L https://github.com/libffi/libffi/releases/download/v3.4.6/libffi-3.4.6.tar.gz | tar --strip-components=1 -xzC ffi + ## Software installed by default in GitHub Action Runner VMs: + ## https://github.com/actions/runner-images - if: ${{ matrix.os.family == 'macos' }} name: "[macOS] Flex/Bison" run: | brew install flex bison echo "PATH=$(brew --prefix flex)/bin:$PATH" >> $GITHUB_ENV echo "PATH=$(brew --prefix bison)/bin:$PATH" >> $GITHUB_ENV + - if : ${{ matrix.os.family == 'windows' }} + name: "[Windows] Flex/Bison" + run: | + choco install winflexbison3 - if: ${{ matrix.os.family == 'macos' && matrix.os.archs == 'arm64' }} name: "[macOS/arm64] Install Python 3.8 (see: https://cibuildwheel.pypa.io/en/stable/faq/#macos-building-cpython-38-wheels-on-arm64)" uses: actions/setup-python@v5 @@ -79,33 +85,25 @@ jobs: - name: Build wheels uses: pypa/cibuildwheel@v2.20.0 env: - # Explaining the build steps: - # 1. Revert previous seds (if any) - # 2. Delete the libboost static archives from previous builds (if any) - # 3. Navigate to boost source extracted in previous GHA step - # 4-5. Build Boost against current version of Python, only for - # static linkage - # (Boost is statically linked because system boost packages - # wildly vary in versions, including the libboost_python3 - # version) - # 6-7. Return to package directory and sed the Makefile to point at - # the newly compiled libboost_python CIBW_SKIP: pp* # The Makefile requires python3-config which is not in pypy CIBW_ARCHS: ${{ matrix.os.archs }} CIBW_BUILD_VERBOSITY: "1" - CIBW_BEFORE_ALL_LINUX: yum install -y libffi-devel flex bison || apk add libffi-dev flex bison - CIBW_BEFORE_ALL_MAC: brew install libffi - CIBW_BEFORE_BUILD: | - cp Makefile.bak Makefile &&\ - cd ./boost &&\ - rm -rf ./pfx &&\ - ./bootstrap.sh --prefix=./pfx &&\ - ./b2 --prefix=./pfx --with-filesystem --with-system --with-python cxxflags="$(python3-config --includes) -std=c++17 -fPIC" cflags="$(python3-config --includes) -fPIC" link=static variant=release install &&\ - ls ./pfx/lib/libboost_python*.a &&\ - cd {package} &&\ - sed -i'.bak' -e "1i\\ - LINKFLAGS = -L./boost/pfx/lib" -e "1i\\ - CXXFLAGS = -I./boost/pfx/include" -e "s@BOOST_PYTHON_LIB ?=@BOOST_PYTHON_LIB = $(ls ./boost/pfx/lib/libboost_python*.a)\nTrash =@" Makefile + # manylinux2014 (default) does not have a modern enough C++ compiler for Yosys + CIBW_MANYLINUX_X86_64_IMAGE: manylinux_2_28 + CIBW_MANYLINUX_AARCH64_IMAGE: manylinux_2_28 + CIBW_BEFORE_ALL: bash ./.github/workflows/cibw_before_all.sh + CIBW_ENVIRONMENT: > + CXXFLAGS=-I./boost/pfx/include + LINKFLAGS=-L./boost/pfx/lib + PKG_CONFIG_PATH=./ffi/pfx/lib/pkgconfig + makeFlags='BOOST_PYTHON_LIB=./boost/pfx/lib/libboost_python*.a' + CIBW_ENVIRONMENT_MACOS: > + CXXFLAGS=-I./boost/pfx/include + LINKFLAGS=-L./boost/pfx/lib + PKG_CONFIG_PATH=./ffi/pfx/lib/pkgconfig + MACOSX_DEPLOYMENT_TARGET=11 + makeFlags='BOOST_PYTHON_LIB=./boost/pfx/lib/libboost_python*.a CONFIG=clang' + CIBW_BEFORE_BUILD: bash ./.github/workflows/cibw_before_build.sh - uses: actions/upload-artifact@v3 with: path: ./dist/*.whl diff --git a/.gitignore b/.gitignore index 5d6a466db68..5c3d8f4e963 100644 --- a/.gitignore +++ b/.gitignore @@ -51,3 +51,4 @@ __pycache__ /build /venv /boost +/ffi From ab84c105c14bfca00a6b87828cb665b40740b35b Mon Sep 17 00:00:00 2001 From: Mohamed Gaber Date: Sat, 28 Sep 2024 23:11:45 +0300 Subject: [PATCH 3/8] Add test, shell for windows --- .github/workflows/wheels.yml | 5 +++-- .github/workflows/{ => wheels}/_run_cibw_linux.py | 2 +- .github/workflows/{ => wheels}/cibw_before_all.sh | 10 ++++++---- .github/workflows/{ => wheels}/cibw_before_build.sh | 7 +++++++ 4 files changed, 17 insertions(+), 7 deletions(-) rename .github/workflows/{ => wheels}/_run_cibw_linux.py (94%) rename .github/workflows/{ => wheels}/cibw_before_all.sh (55%) rename .github/workflows/{ => wheels}/cibw_before_build.sh (80%) diff --git a/.github/workflows/wheels.yml b/.github/workflows/wheels.yml index 5961f364ae3..c6af2c8b2c0 100644 --- a/.github/workflows/wheels.yml +++ b/.github/workflows/wheels.yml @@ -91,7 +91,7 @@ jobs: # manylinux2014 (default) does not have a modern enough C++ compiler for Yosys CIBW_MANYLINUX_X86_64_IMAGE: manylinux_2_28 CIBW_MANYLINUX_AARCH64_IMAGE: manylinux_2_28 - CIBW_BEFORE_ALL: bash ./.github/workflows/cibw_before_all.sh + CIBW_BEFORE_ALL: bash ./.github/workflows/wheels/cibw_before_all.sh CIBW_ENVIRONMENT: > CXXFLAGS=-I./boost/pfx/include LINKFLAGS=-L./boost/pfx/lib @@ -103,7 +103,8 @@ jobs: PKG_CONFIG_PATH=./ffi/pfx/lib/pkgconfig MACOSX_DEPLOYMENT_TARGET=11 makeFlags='BOOST_PYTHON_LIB=./boost/pfx/lib/libboost_python*.a CONFIG=clang' - CIBW_BEFORE_BUILD: bash ./.github/workflows/cibw_before_build.sh + CIBW_BEFORE_BUILD: bash ./.github/workflows/wheels/cibw_before_build.sh + CIBW_TEST_COMMAND: python3 -c "from pyosys import libyosys as ys;d=ys.Design();ys.run_pass('help', d)" - uses: actions/upload-artifact@v3 with: path: ./dist/*.whl diff --git a/.github/workflows/_run_cibw_linux.py b/.github/workflows/wheels/_run_cibw_linux.py similarity index 94% rename from .github/workflows/_run_cibw_linux.py rename to .github/workflows/wheels/_run_cibw_linux.py index 675817ae09a..894470a5a8d 100644 --- a/.github/workflows/_run_cibw_linux.py +++ b/.github/workflows/wheels/_run_cibw_linux.py @@ -24,7 +24,7 @@ __dir__ = os.path.dirname(os.path.abspath(__file__)) -workflow = yaml.safe_load(open(os.path.join(__dir__, "wheels.yml"))) +workflow = yaml.safe_load(open(os.path.join(os.path.dirname(__dir__), "wheels.yml"))) env = os.environ.copy() diff --git a/.github/workflows/cibw_before_all.sh b/.github/workflows/wheels/cibw_before_all.sh similarity index 55% rename from .github/workflows/cibw_before_all.sh rename to .github/workflows/wheels/cibw_before_all.sh index 934902380a4..28aae85aca1 100644 --- a/.github/workflows/cibw_before_all.sh +++ b/.github/workflows/wheels/cibw_before_all.sh @@ -11,11 +11,13 @@ if command -v apk &> /dev/null; then apk add flex bison fi -## macOS/Windows -- install in GitHub Action itself, not container +## macOS/Windows -- installed in GitHub Action itself, not container # Build Static FFI (platform-dependent but not Python version dependent) cd ffi -SHELL=bash CFLAGS=-fPIC CXXFLAGS=-fPIC ./configure --prefix=$PWD/pfx - -make install -j$(getconf _NPROCESSORS_ONLN 2>/dev/null || sysctl -n hw.ncpu) +## Ultimate libyosys.so will be shared, so we need fPIC for the static libraries +CFLAGS=-fPIC CXXFLAGS=-fPIC ./configure --prefix=$PWD/pfx +## Without this, SHELL has a space in its path which breaks the makefile +make install -j$(getconf _NPROCESSORS_ONLN 2>/dev/null || sysctl -n hw.ncpu) SHELL=bash +## Forces static library to be used in all situations sed -i.bak 's@-L${toolexeclibdir} -lffi@${toolexeclibdir}/libffi.a@' ./pfx/lib/pkgconfig/libffi.pc diff --git a/.github/workflows/cibw_before_build.sh b/.github/workflows/wheels/cibw_before_build.sh similarity index 80% rename from .github/workflows/cibw_before_build.sh rename to .github/workflows/wheels/cibw_before_build.sh index 03baf110bcd..29fffe0901e 100644 --- a/.github/workflows/cibw_before_build.sh +++ b/.github/workflows/wheels/cibw_before_build.sh @@ -1,6 +1,13 @@ set -e set -x +# Don't use objects from previous compiles on Windows/macOS +make clean + +# DEBUG: show python3 and python3-config outputs +python3 --version +python3-config --includes + # Build boost cd ./boost ## Delete the artefacts from previous builds (if any) From 67f17a1c97a097eb59d8a7d1b81fc5aff66f0da8 Mon Sep 17 00:00:00 2001 From: Mohamed Gaber Date: Sun, 29 Sep 2024 12:28:18 +0300 Subject: [PATCH 4/8] wheels: symlink python3-config --- .github/workflows/wheels.yml | 2 +- .github/workflows/wheels/cibw_before_build.sh | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/wheels.yml b/.github/workflows/wheels.yml index c6af2c8b2c0..eafaa957fd3 100644 --- a/.github/workflows/wheels.yml +++ b/.github/workflows/wheels.yml @@ -83,7 +83,7 @@ jobs: with: python-version: 3.8 - name: Build wheels - uses: pypa/cibuildwheel@v2.20.0 + uses: pypa/cibuildwheel@v2.21.1 env: CIBW_SKIP: pp* # The Makefile requires python3-config which is not in pypy CIBW_ARCHS: ${{ matrix.os.archs }} diff --git a/.github/workflows/wheels/cibw_before_build.sh b/.github/workflows/wheels/cibw_before_build.sh index 29fffe0901e..018b0e0df96 100644 --- a/.github/workflows/wheels/cibw_before_build.sh +++ b/.github/workflows/wheels/cibw_before_build.sh @@ -5,6 +5,10 @@ set -x make clean # DEBUG: show python3 and python3-config outputs +if [ "$(uname)" != "Linux" ]; then + # https://github.com/pypa/cibuildwheel/issues/2021 + ln -s $(dirname $(readlink -f $(which python3)))/python3-config $(dirname $(which python3))/python3-config +fi python3 --version python3-config --includes From 08c23b7632a744c1bf3a42f035611757cb64a1ea Mon Sep 17 00:00:00 2001 From: Mohamed Gaber Date: Sun, 29 Sep 2024 16:02:37 +0300 Subject: [PATCH 5/8] wheels: skip musllinux for now --- .github/workflows/wheels.yml | 8 ++++++-- .github/workflows/wheels/cibw_before_all.sh | 2 +- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/.github/workflows/wheels.yml b/.github/workflows/wheels.yml index eafaa957fd3..a91c873fbc3 100644 --- a/.github/workflows/wheels.yml +++ b/.github/workflows/wheels.yml @@ -85,7 +85,11 @@ jobs: - name: Build wheels uses: pypa/cibuildwheel@v2.21.1 env: - CIBW_SKIP: pp* # The Makefile requires python3-config which is not in pypy + # * APIs not supported by PyPy + # * Musllinux temporarily disabled because it takes too much time + CIBW_SKIP: > + pp* + *musllinux* CIBW_ARCHS: ${{ matrix.os.archs }} CIBW_BUILD_VERBOSITY: "1" # manylinux2014 (default) does not have a modern enough C++ compiler for Yosys @@ -107,4 +111,4 @@ jobs: CIBW_TEST_COMMAND: python3 -c "from pyosys import libyosys as ys;d=ys.Design();ys.run_pass('help', d)" - uses: actions/upload-artifact@v3 with: - path: ./dist/*.whl + path: ./wheelhouse/*.whl diff --git a/.github/workflows/wheels/cibw_before_all.sh b/.github/workflows/wheels/cibw_before_all.sh index 28aae85aca1..fbb8dcad830 100644 --- a/.github/workflows/wheels/cibw_before_all.sh +++ b/.github/workflows/wheels/cibw_before_all.sh @@ -18,6 +18,6 @@ cd ffi ## Ultimate libyosys.so will be shared, so we need fPIC for the static libraries CFLAGS=-fPIC CXXFLAGS=-fPIC ./configure --prefix=$PWD/pfx ## Without this, SHELL has a space in its path which breaks the makefile -make install -j$(getconf _NPROCESSORS_ONLN 2>/dev/null || sysctl -n hw.ncpu) SHELL=bash +make install -j$(getconf _NPROCESSORS_ONLN 2>/dev/null || sysctl -n hw.ncpu) ## Forces static library to be used in all situations sed -i.bak 's@-L${toolexeclibdir} -lffi@${toolexeclibdir}/libffi.a@' ./pfx/lib/pkgconfig/libffi.pc From 0bb1f899e84f97b53a765581a5e91450a8074215 Mon Sep 17 00:00:00 2001 From: Mohamed Gaber Date: Fri, 4 Oct 2024 16:14:26 +0300 Subject: [PATCH 6/8] wheels: convert versions to match pypa spec, add uploading * wheel versions now replace `+` with `.post` to match spec at https://packaging.python.org/en/latest/specifications/version-specifiers/ * CI updates: * Bump action versions * Disabled Windows for now and documented why * Added a new job to upload all wheels * Added new variable, `PYPI_INDEX`: fallback 'https://pypi.org/' if unset * Added new secret, `PYPI_TOKEN` * .editorconfig now uses 2 spaces for YML (it kept setting mine to tabs and GitHub Actions doesn't like that) --- .editorconfig | 4 +++ .github/workflows/wheels.yml | 49 +++++++++++++++++++++++++----------- setup.py | 2 +- 3 files changed, 40 insertions(+), 15 deletions(-) diff --git a/.editorconfig b/.editorconfig index f5444d81a74..572b73bd2ed 100644 --- a/.editorconfig +++ b/.editorconfig @@ -10,3 +10,7 @@ insert_final_newline = true indent_style = space indent_size = 2 trim_trailing_whitespace = false + +[*.yml] +indent_style = space +indent_size = 2 diff --git a/.github/workflows/wheels.yml b/.github/workflows/wheels.yml index a91c873fbc3..c6132685b5d 100644 --- a/.github/workflows/wheels.yml +++ b/.github/workflows/wheels.yml @@ -1,8 +1,7 @@ name: Build Wheels for PyPI on: workflow_dispatch: - push: - # tags: ["yosys-*"] + jobs: build_wheels: strategy: @@ -37,24 +36,27 @@ jobs: runner: "macos-14", archs: "arm64", }, - { - name: "Windows Server 2019", - family: "windows", - runner: "windows-2019", - archs: "AMD64", - }, + ## Windows is disabled because of an issue with compiling FFI as + ## under MinGW in the GitHub Actions environment (SHELL variable has + ## whitespace.) + # { + # name: "Windows Server 2019", + # family: "windows", + # runner: "windows-2019", + # archs: "AMD64", + # }, ] name: Build Wheels | ${{ matrix.os.name }} | ${{ matrix.os.archs }} runs-on: ${{ matrix.os.runner }} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: fetch-depth: 0 submodules: true - if: ${{ matrix.os.family == 'linux' }} name: "[Linux] Set up QEMU" - uses: docker/setup-qemu-action@v2 - - uses: actions/setup-python@v3 + uses: docker/setup-qemu-action@v3 + - uses: actions/setup-python@v5 - name: Get Boost Source shell: bash run: | @@ -73,7 +75,7 @@ jobs: brew install flex bison echo "PATH=$(brew --prefix flex)/bin:$PATH" >> $GITHUB_ENV echo "PATH=$(brew --prefix bison)/bin:$PATH" >> $GITHUB_ENV - - if : ${{ matrix.os.family == 'windows' }} + - if: ${{ matrix.os.family == 'windows' }} name: "[Windows] Flex/Bison" run: | choco install winflexbison3 @@ -86,7 +88,7 @@ jobs: uses: pypa/cibuildwheel@v2.21.1 env: # * APIs not supported by PyPy - # * Musllinux temporarily disabled because it takes too much time + # * Musllinux disabled because it increases build time from 48m to ~3h CIBW_SKIP: > pp* *musllinux* @@ -109,6 +111,25 @@ jobs: makeFlags='BOOST_PYTHON_LIB=./boost/pfx/lib/libboost_python*.a CONFIG=clang' CIBW_BEFORE_BUILD: bash ./.github/workflows/wheels/cibw_before_build.sh CIBW_TEST_COMMAND: python3 -c "from pyosys import libyosys as ys;d=ys.Design();ys.run_pass('help', d)" - - uses: actions/upload-artifact@v3 + - uses: actions/upload-artifact@v4 with: + name: python-wheels path: ./wheelhouse/*.whl + upload_wheels: + name: Upload Wheels + runs-on: ubuntu-latest + needs: build_wheels + steps: + - uses: actions/download-artifact@v4 + with: + name: python-wheels + path: "." + - run: | + ls + mkdir -p ./dist + mv *.whl ./dist + - name: Publish + uses: pypa/gh-action-pypi-publish@release/v1 + with: + password: ${{ secrets.PYPI_TOKEN }} + repository-url: ${{ vars.PYPI_INDEX || 'https://upload.pypi.org/legacy/' }} diff --git a/setup.py b/setup.py index 02e6e5843de..f9d455f0bbf 100644 --- a/setup.py +++ b/setup.py @@ -25,7 +25,7 @@ version = yosys_version_rx.search( open(os.path.join(__dir__, "Makefile"), encoding="utf8").read() -)[1] +)[1].replace("+", ".post") class libyosys_so_ext(Extension): From 43128f628311e7dd69fc5aab802b9a0242efef87 Mon Sep 17 00:00:00 2001 From: Mohamed Gaber Date: Mon, 7 Oct 2024 16:51:17 +0300 Subject: [PATCH 7/8] wheels: move from postreleases to minor versions, remove authors --- setup.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/setup.py b/setup.py index f9d455f0bbf..22196597109 100644 --- a/setup.py +++ b/setup.py @@ -25,7 +25,9 @@ version = yosys_version_rx.search( open(os.path.join(__dir__, "Makefile"), encoding="utf8").read() -)[1].replace("+", ".post") +)[1].replace( + "+", "." +) # Convert to patch version class libyosys_so_ext(Extension): @@ -78,8 +80,6 @@ def build_extension(self, ext) -> None: description="Python access to libyosys", long_description=open(os.path.join(__dir__, "README.md")).read(), long_description_content_type="text/markdown", - author="Claire Xenia Wolf", - author_email="claire@yosyshq.com", install_requires=["wheel", "setuptools"], classifiers=[ "License :: OSI Approved :: MIT License", From d7cf0238fda76e6a7f565dc4b521828e164c00f6 Mon Sep 17 00:00:00 2001 From: Mohamed Gaber Date: Mon, 7 Oct 2024 20:17:05 +0300 Subject: [PATCH 8/8] wheels: properly migrate to artifact@v4 --- .github/workflows/wheels.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/wheels.yml b/.github/workflows/wheels.yml index c6132685b5d..d59f8e1ec61 100644 --- a/.github/workflows/wheels.yml +++ b/.github/workflows/wheels.yml @@ -113,7 +113,7 @@ jobs: CIBW_TEST_COMMAND: python3 -c "from pyosys import libyosys as ys;d=ys.Design();ys.run_pass('help', d)" - uses: actions/upload-artifact@v4 with: - name: python-wheels + name: python-wheels-${{ matrix.os.runner }} path: ./wheelhouse/*.whl upload_wheels: name: Upload Wheels @@ -122,8 +122,9 @@ jobs: steps: - uses: actions/download-artifact@v4 with: - name: python-wheels path: "." + pattern: python-wheels-* + merge-multiple: true - run: | ls mkdir -p ./dist