diff --git a/.github/actions/setup/action.yml b/.github/actions/setup/action.yml index d51400d5..014b398b 100644 --- a/.github/actions/setup/action.yml +++ b/.github/actions/setup/action.yml @@ -28,10 +28,14 @@ runs: shell: bash - run: sudo apt-get install -y build-essential valgrind clang-tools lcov gperf astyle codespell shell: bash + - name: Set up Python environment + uses: actions/setup-python@v5 + with: + python-version: '3.13' - run: | - sudo apt-get install -y python3 python3-setuptools python3-pip - python3 -m pip install --upgrade pip + python3 -m pip install build python3 -m pip install cython + python3 -m pip install setuptools # Add cython to the path echo "$HOME/.local/bin" >> $GITHUB_PATH shell: bash diff --git a/.github/workflows/python-ci.yml b/.github/workflows/python-ci.yml new file mode 100644 index 00000000..f6b703f5 --- /dev/null +++ b/.github/workflows/python-ci.yml @@ -0,0 +1,75 @@ +# +# Continuous Integration Workflow libseccomp Python Code +# +# Copyright (c) 2025 Oracle and/or its affiliates. +# Author: Tom Hromatka +# + +# +# This library is free software; you can redistribute it and/or modify it +# under the terms of version 2.1 of the GNU Lesser General Public License as +# published by the Free Software Foundation. +# +# This library is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License +# for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this library; if not, see . +# + +name: Python Continuous Integration +on: ["push", "pull_request"] + +jobs: + build-wheel: + name: Build Wheel + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Initialize libseccomp + uses: ./.github/actions/setup + - name: Build libseccomp + run: | + ./configure --enable-python + make check-build + - name: Build wheel + run: make python-wheel + + build-wheels: + name: Build Wheels + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [ubuntu-24.04, ubuntu-24.04-arm, ubuntu-22.04, ubuntu-22.04-arm] + steps: + - uses: actions/checkout@v2 + - name: Initialize libseccomp + uses: ./.github/actions/setup + - name: Install cibuildwheel + run: python -m pip install cibuildwheel + - name: Build libseccomp + run: | + ./configure --enable-python + make check-build + - name: Build wheels + run: make python-wheels + - uses: actions/upload-artifact@v4 + with: + name: cibw-wheels-${{ matrix.os }}-${{ strategy.job-index }} + path: src/python/wheelhouse/*.whl + + flake: + name: Run Flake + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Initialize libseccomp + uses: ./.github/actions/setup + - name: Install Flake Dependencies + run: sudo apt-get install python3-flake8-quotes + - name: flake8 Lint + uses: reviewdog/action-flake8@v3 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} diff --git a/Makefile.am b/Makefile.am index 5e8aa835..c0f97a89 100644 --- a/Makefile.am +++ b/Makefile.am @@ -75,6 +75,14 @@ coverity-tarball: coverity-build ls -l libseccomp-coverity_$$rev.tar.gz endif +if ENABLE_PYTHON +python-wheel: all + ${MAKE} ${AM_MAKEFLAGS} -C src/python $@ + +python-wheels: all + ${MAKE} ${AM_MAKEFLAGS} -C src/python $@ +endif + help: @echo "libseccomp build system" @echo " make targets:" @@ -86,6 +94,8 @@ help: @echo " distcheck: verify the build for distribution" @echo " dist-gzip: build a release tarball" @echo " coverity-tarball: build a tarball for use with Coverity (opt)" + @echo " python-wheel: build a python wheel for this system" + @echo " python-wheels: build python wheels for distribution to pip" clean-local: ${RM} -rf cov-int libseccomp-coverity_*.tar.gz diff --git a/configure.ac b/configure.ac index f2f68621..7d96fc86 100644 --- a/configure.ac +++ b/configure.ac @@ -146,6 +146,7 @@ dnl #### AC_CONFIG_FILES([ libseccomp.pc include/seccomp.h + src/python/setup.py ]) dnl #### diff --git a/include/seccomp.h.in b/include/seccomp.h.in index 38c50d29..e3d7f539 100644 --- a/include/seccomp.h.in +++ b/include/seccomp.h.in @@ -897,7 +897,7 @@ int seccomp_precompute(const scmp_filter_ctx ctx); #define __NR_SCMP_ERROR -1 #define __NR_SCMP_UNDEF -2 -#include +#include "seccomp-syscalls.h" #ifdef __cplusplus } diff --git a/src/python/.gitignore b/src/python/.gitignore index fc8966d1..f36e5783 100644 --- a/src/python/.gitignore +++ b/src/python/.gitignore @@ -1,2 +1,9 @@ -build +build/ +dist/ +libseccomp.a seccomp.c +seccomp.h +seccomp-syscalls.h +seccomp.egg-info/ +setup.py +wheelhouse/ diff --git a/src/python/MANIFEST.in b/src/python/MANIFEST.in new file mode 100644 index 00000000..f3414130 --- /dev/null +++ b/src/python/MANIFEST.in @@ -0,0 +1,6 @@ +include seccomp.pyx +include libseccomp.pxd +include libseccomp.a +include seccomp.h +include seccomp-syscalls.h +include __init__.py diff --git a/src/python/Makefile.am b/src/python/Makefile.am index c858832e..e68d3b4b 100644 --- a/src/python/Makefile.am +++ b/src/python/Makefile.am @@ -31,22 +31,34 @@ PY_BUILD = ${PY_BUILD_@AM_V@} PY_INSTALL = ${PY_DISTUTILS} install -EXTRA_DIST = libseccomp.pxd seccomp.pyx setup.py +EXTRA_DIST = libseccomp.pxd seccomp.pyx setup.py __init__.py MANIFEST.in pyproject.toml all-local: build build: ../libseccomp.la libseccomp.pxd seccomp.pyx setup.py [ ${srcdir} = ${builddir} ] || cp ${srcdir}/seccomp.pyx ${builddir} + cp ${srcdir}/../.libs/libseccomp.a ${builddir} + cp ${top_srcdir}/include/seccomp.h ${builddir} + cp ${top_srcdir}/include/seccomp-syscalls.h ${builddir} ${PY_BUILD} && touch build install-exec-local: build ${PY_INSTALL} --install-lib=${DESTDIR}/${pyexecdir} \ --record=${DESTDIR}/${pyexecdir}/install_files.txt +python-wheel: build + ${PYTHON} -m build + +python-wheels: build + ${PYTHON} -m cibuildwheel --output-dir wheelhouse + uninstall-local: cat ${DESTDIR}/${pyexecdir}/install_files.txt | xargs ${RM} -f ${RM} -f ${DESTDIR}/${pyexecdir}/install_files.txt clean-local: [ ${srcdir} = ${builddir} ] || ${RM} -f ${builddir}/seccomp.pyx + ${RM} -f ${builddir}/libseccomp.a + ${RM} -f ${builddir}/seccomp.h + ${RM} -f ${builddir}/seccomp-syscalls.h ${RM} -rf seccomp.c build dist seccomp.egg-info diff --git a/src/python/__init__.py b/src/python/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/src/python/pyproject.toml b/src/python/pyproject.toml new file mode 100644 index 00000000..1f88263e --- /dev/null +++ b/src/python/pyproject.toml @@ -0,0 +1,2 @@ +[build-system] +requires = ["cython", "setuptools"] diff --git a/src/python/setup.py b/src/python/setup.py.in similarity index 73% rename from src/python/setup.py rename to src/python/setup.py.in index 46f9a731..4276709e 100755 --- a/src/python/setup.py +++ b/src/python/setup.py.in @@ -3,8 +3,9 @@ # # Enhanced Seccomp Library Python Module Build Script # -# Copyright (c) 2012 Red Hat +# Copyright (c) 2012-2025 Red Hat # Author: Paul Moore +# Author: Tom Hromatka # # @@ -29,17 +30,20 @@ setup( name = "seccomp", - version = os.environ["VERSION_RELEASE"], + version = "@VERSION_MAJOR@.@VERSION_MINOR@.@VERSION_MICRO@", description = "Python binding for libseccomp", long_description = "Python API for the Linux Kernel's syscall filtering capability, seccomp.", url = "https://github.com/seccomp/libseccomp", maintainer = "Paul Moore", maintainer_email = "paul@paul-moore.com", - license = "LGPLv2.1", + license = "LGPL-2.1", platforms = "Linux", ext_modules = cythonize([ Extension("seccomp", ["seccomp.pyx"], - # unable to handle libtool libraries directly - extra_objects=["../.libs/libseccomp.a"]), + # Unable to handle libtool libraries directly. Also note that + # python wheel builds cannot use files outside of the build + # directory, so libseccomp.a is manually copied into src/python + # by Makefile.am + extra_objects=["libseccomp.a"]), ]) )