Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
81 changes: 81 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
# Continuous integration for gcc-python-plugin
#
# Stage 1 of the CI plan: one reproducible Linux x86_64 job using Python 3
# and a single GCC release. Further GCC releases (14, 15, 16 and trunk) and
# architectures (ppc64le, aarch64) will be added as their compatibility work
# lands.

name: CI

on:
push:
pull_request:
workflow_dispatch:

permissions:
contents: read

jobs:
build-and-test:
name: GCC ${{ matrix.gcc }}, Python 3, ${{ matrix.image }}
runs-on: ubuntu-latest
container: ${{ matrix.image }}
strategy:
fail-fast: false
matrix:
include:
# GCC 11 and later do not build the current sources yet, so use
# GCC 10. Ubuntu 22.04 provides it together with Python 3.10; the
# test tooling still relies on distutils and
# configparser.SafeConfigParser, which Python 3.12 removed.
- image: ubuntu:22.04
gcc: 10
defaults:
run:
shell: bash
env:
DEBIAN_FRONTEND: noninteractive
steps:
- name: Install build dependencies
run: |
apt-get update
apt-get install -y --no-install-recommends \
ca-certificates git make \
gcc-${{ matrix.gcc }} g++-${{ matrix.gcc }} \
gcc-${{ matrix.gcc }}-plugin-dev \
python3 python3-dev python-is-python3 \
python3-six python3-pygments python3-lxml graphviz
# Make plain "gcc" and "g++" refer to the GCC under test
update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-${{ matrix.gcc }} 100
update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-${{ matrix.gcc }} 100

- name: Check out the sources
uses: actions/checkout@v7

- name: Show the toolchain
run: |
gcc --version | head -n 1
python3 --version

- name: Build the plugin
# Serial build: the Makefile is not yet safe for "make -j"
run: make CC=gcc plugin

- name: Check that GCC loads the plugin
run: |
printf 'int main (void) { return 0; }\n' > ci-smoke.c
printf 'import gcc\nprint("gcc-python-plugin loaded")\n' > ci-smoke.py
LD_LIBRARY_PATH=gcc-c-api gcc -fplugin="$PWD/python.so" \
-fplugin-arg-python-script=ci-smoke.py -c ci-smoke.c -o /dev/null \
| tee ci-smoke.out
grep -q 'gcc-python-plugin loaded' ci-smoke.out

- name: Run the Python selftests
run: make CC=gcc testcpybuilder testdejagnu

- name: Run the test suite
# Some tests are expected to fail with current Python releases (for
# example, SyntaxError reports place the caret differently). Report
# the results without failing the job until those are fixed.
continue-on-error: true
run: make CC=gcc test-suite
90 changes: 0 additions & 90 deletions .travis.yml

This file was deleted.

11 changes: 4 additions & 7 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -83,19 +83,16 @@ GENERATOR_DEPS=cpybuilder.py wrapperbuilder.py print-gcc-version
# as we're linking against, and that the cpychecker will be testing that same
# version of Python
#
# By default, build against "python", using "python-config" to query for
# By default, build against "python3", using "python3-config" to query for
# compilation options. You can override this by passing other values for
# PYTHON and PYTHON_CONFIG when invoking "make" (or by simply hacking up this
# file): e.g.
# make PYTHON=python3 PYTHON_CONFIG=python3-config all
# make PYTHON=python3.12 PYTHON_CONFIG=python3.12-config all

# The python interpreter to use:
PYTHON=python
PYTHON=python3
# The python-config executable to use:
PYTHON_CONFIG=python-config

#PYTHON=python3
#PYTHON_CONFIG=python3-config
PYTHON_CONFIG=python3-config

#PYTHON=python-debug
#PYTHON_CONFIG=python-debug-config
Expand Down
39 changes: 30 additions & 9 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -28,17 +28,38 @@ The documentation can be seen at:
http://gcc-python-plugin.readthedocs.io/en/latest/index.html


Requirements
------------
Maintenance status
------------------

The plugin is being modernized and maintained at
https://github.com/mmatti-sw/gcc-python-plugin.

It was originally developed against GCC 4.6 through 8 and Python 2.7 and 3.x.
That support is historical and is no longer maintained.

GCC does not provide a stable plugin API: its internals change from one
release to the next, so compatibility has to be established, and tested,
separately for each GCC release. Compatibility with current GCC releases is
being re-established, and no GCC release is claimed as supported until the
plugin has been built and its test suite run against it. Verified GCC
releases will be listed here.

* GCC: 4.6 or later (it uses APIs that weren't exposed to plugins in 4.5)
Python 3 is the maintenance target; Python 2 is no longer supported.

* tested with 4.8, 4.9, 5, 6, 7, and 8.
x86_64 and ppc64le are the intended test platforms.


Requirements
------------

* GCC plugin development package: usually available in distribution packages
such as ``gcc-N-plugin-dev`` or ``gcc-plugin-devel``.
* GCC, with the plugin development headers for that exact GCC version: usually
available in distribution packages such as ``gcc-N-plugin-dev`` or
``gcc-plugin-devel``. The plugin is compiled as C++, so the matching C++
compiler (e.g. ``g++-N``) is needed as well. See "Maintenance status" above
for which GCC releases have been verified.

* Python: requires 2.7 or 3.2 or later
* Python 3, with its development headers (e.g. ``python3-dev`` or
``python3-devel``)

* "six": The libcpychecker code uses the "six_" Python compatibility library to
smooth over Python 2 vs Python 3 differences, both at build-time and
Expand All @@ -62,8 +83,8 @@ You can also use::

to demonstrate the new compiler errors.

Development has been on x86_64 and I don't know to what extent it will be
compatible with other architectures.
The plugin was originally developed on x86_64. x86_64 and ppc64le are the
intended test platforms; other architectures have not been verified.

There isn't an installer yet. In theory you should be able to add these
arguments to the gcc invocation::
Expand Down
31 changes: 14 additions & 17 deletions docs/basics.rst
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,15 @@ Requirements

The plugin has the following requirements:

* GCC: 4.6 or later (it uses APIs that weren't exposed to plugins in 4.5)
* GCC, with the plugin development headers for that exact GCC version
(e.g. the ``gcc-N-plugin-dev`` or ``gcc-plugin-devel`` package), and the
matching C++ compiler, since the plugin is compiled as C++.

* Python: requires 2.7 or 3.2 or later
GCC's internals change between releases, so compatibility is established
and tested separately for each GCC release. Support for GCC 4.6 through
8 is historical; see the README for the GCC releases currently verified.

* Python 3, with its development headers. Python 2 is no longer supported.

* "six": The libcpychecker code uses the "six" Python compatibility library to
smooth over Python 2 vs Python 3 differences, both at build-time and
Expand Down Expand Up @@ -79,15 +85,7 @@ On a Fedora box you can install them by running the following as root:

.. code-block:: bash

yum install gcc-plugin-devel python-devel python-six python-pygments graphviz

for building against Python 2, or:

.. code-block:: bash

yum install gcc-plugin-devel python3-devel python3-six python3-pygments graphviz

when building for Python 3.
dnf install gcc-c++ gcc-plugin-devel python3-devel python3-six python3-pygments graphviz

Building the code
------------------
Expand All @@ -113,15 +111,14 @@ You can also use::

to demonstrate the new compiler errors.

By default, the `Makefile` builds the plugin using the first ``python-config``
tool found in `$PATH` (e.g. `/usr/bin/python-config`), which is typically the
system copy of Python 2. You can override this (e.g. to build against
Python 3) by overriding the `PYTHON` and `PYTHON_CONFIG` Makefile variables
with:
By default, the `Makefile` builds the plugin with the ``python3`` and
``python3-config`` tools found in `$PATH`. You can select a different Python 3
installation by overriding the `PYTHON` and `PYTHON_CONFIG` Makefile variables,
e.g.:

.. code-block:: bash

make PYTHON=python3 PYTHON_CONFIG=python3-config
make PYTHON=python3.12 PYTHON_CONFIG=python3.12-config

There isn't a well-defined process yet for installing the plugin (though the
rpm specfile in the source tree contains some work-in-progress towards this).
Expand Down
42 changes: 42 additions & 0 deletions gcc-python-callbacks.c
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,24 @@ PyGcc_CallbackFor_tree(void *gcc_data, void *user_data)
}


static void
PyGcc_CallbackFor_PLUGIN_INCLUDE_FILE(void *gcc_data, void *user_data)
{
PyGILState_STATE gstate;
const char *filename = (const char *)gcc_data;
PyObject *filename_obj;

gstate = PyGILState_Ensure();

filename_obj = filename ? PyGccString_FromString(filename) : Py_None;
if (filename == NULL)
Py_INCREF(Py_None);

PyGcc_FinishInvokingCallback(gstate,
1, filename_obj,
user_data);
}

static void
PyGcc_CallbackFor_PLUGIN_ATTRIBUTES(void *gcc_data, void *user_data)
{
Expand Down Expand Up @@ -386,6 +404,30 @@ PyGcc_RegisterCallback(PyObject *self, PyObject *args, PyObject *kwargs)
break;
#endif /* GCC_PYTHON_PLUGIN_CONFIG_has_PLUGIN_FINISH_DECL */

/* PLUGIN_START_PARSE_FUNCTION and PLUGIN_FINISH_PARSE_FUNCTION were
added in GCC 10; gcc_data is a tree (the function decl). */
case PLUGIN_START_PARSE_FUNCTION:
register_callback("python", // FIXME
(enum plugin_event)event,
PyGcc_CallbackFor_tree,
closure);
break;

case PLUGIN_FINISH_PARSE_FUNCTION:
register_callback("python", // FIXME
(enum plugin_event)event,
PyGcc_CallbackFor_tree,
closure);
break;

/* PLUGIN_INCLUDE_FILE: gcc_data is a const char* filename. */
case PLUGIN_INCLUDE_FILE:
register_callback("python", // FIXME
(enum plugin_event)event,
PyGcc_CallbackFor_PLUGIN_INCLUDE_FILE,
closure);
break;

default:
PyErr_Format(PyExc_ValueError, "event type %i invalid (or not wired up yet)", event);
return NULL;
Expand Down
5 changes: 4 additions & 1 deletion gcc-python-compat.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,11 @@ dump_generic_node (pretty_printer *buffer, tree node, int spc, dump_flags_t flag
bool is_stmt);
#endif

/* Within gcc/gcc-internal.h, not exposed by plugin API */
/* Within gcc/gcc-internal.h, not exposed by plugin API.
Removed in GCC 12; replaced by ggc_collect(GGC_COLLECT_FORCE). */
#if (GCC_VERSION < 12000)
extern bool ggc_force_collect;
#endif

/* From c-family/c-common.h */
#if GCC_VERSION < 4008
Expand Down
5 changes: 4 additions & 1 deletion gcc-python-wrapper.c
Original file line number Diff line number Diff line change
Expand Up @@ -337,11 +337,14 @@ PyGcc_wrapper_init(void)
static void
force_gcc_gc(void)
{
#if (GCC_VERSION >= 12000)
ggc_collect(GGC_COLLECT_FORCE);
#else
bool stored = ggc_force_collect;

ggc_force_collect = true;
ggc_collect();
ggc_force_collect = stored;
#endif
}

PyObject *
Expand Down
Loading