From: Pietro Monteiro <[email protected]>

Build autoconf and automake and add autoregen.py from
https://sourceware.org/git/builder.git

Add forge action to build container images.

ChangeLog:

        * .forgejo/workflows/build-containers.yaml: New file.

contrib/ChangeLog:

        * ci-container/essential/Containerfile: New file.
        * ci-container/essential/autoregen.py: Likewise.

Signed-off-by: Pietro Monteiro <[email protected]>
---
 .forgejo/workflows/build-containers.yaml     |  55 +++++++
 contrib/ci-container/essential/Containerfile |  78 ++++++++++
 contrib/ci-container/essential/autoregen.py  | 146 +++++++++++++++++++
 3 files changed, 279 insertions(+)
 create mode 100644 .forgejo/workflows/build-containers.yaml
 create mode 100644 contrib/ci-container/essential/Containerfile
 create mode 100755 contrib/ci-container/essential/autoregen.py

diff --git a/.forgejo/workflows/build-containers.yaml 
b/.forgejo/workflows/build-containers.yaml
new file mode 100644
index 000000000000..e369a1a57113
--- /dev/null
+++ b/.forgejo/workflows/build-containers.yaml
@@ -0,0 +1,55 @@
+on:
+#  push:
+#    branches:
+#      - trunk
+#    # run on changes to any file for ci containers or to this file
+#    paths:
+#      - .forgejo/workflows/build-containers.yaml
+#      - 'contrib/ci-container/**/*'
+  # similar for pull requests
+  pull_request:
+    types: [opened, synchronize, reopened]
+    paths:
+      - .forgejo/workflows/build-containers.yaml
+      - 'contrib/ci-container/**/*'
+
+jobs:
+  containers:
+    runs-on: sourceware-runner
+    container:
+      image: fedora:latest
+      env:
+        # the default overlayfs doesn't work when running on docker, which 
uses overlayfs
+        STORAGE_DRIVER: vfs
+        # we can't run containers in docker, so use a chroot to build the image
+        BUILDAH_ISOLATION: chroot
+    steps:
+      - name: install dependencies
+        run: |
+          dnf -y --setopt=install_weak_deps=False install buildah git nodejs
+
+      # Checkout sources
+      - uses: actions/checkout@v4
+
+      - name: build containers
+        run: |
+          echo "Building containers from contrib/ci-container"
+          for DIR in ./contrib/ci-container/*
+          do
+            ! [ -d "$DIR" ] &&  continue
+            CONTAINER="$(basename "$DIR")"
+            if [ "$FORGEJO_EVENT_NAME" = pull_request ]; then
+              # branch name in lowercase, replace non-alphanumerics with '-', 
and remove leading and trailling '-'
+              TAG="$(echo "$FORGEJO_HEAD_REF" | sed -e 's/\(.*\)/\L\1/' -e 
's/[^[:alnum:]-]/-/g' -e 's/^-\+//;s/-\+$//')"
+            else
+              # branch name
+              TAG="$FORGEJO_REF_NAME"
+            fi
+            echo "Building $CONTAINER with tag $TAG"
+            buildah build --network=host -f "$DIR/Containerfile" -t 
"$CONTAINER:$TAG" "$DIR"
+            echo "Built $CONTAINER:$TAG should push it somewhere"
+            buildah images --json "$CONTAINER:$TAG"
+            echo "Removing container image from localhost"
+            buildah rmi "$CONTAINER:$TAG"
+            buildah rmi --prune
+          done
diff --git a/contrib/ci-container/essential/Containerfile 
b/contrib/ci-container/essential/Containerfile
new file mode 100644
index 000000000000..8105c6bd16cc
--- /dev/null
+++ b/contrib/ci-container/essential/Containerfile
@@ -0,0 +1,78 @@
+FROM debian:stable-slim
+
+# Run time deps
+RUN set -eux; \
+    apt-get update; \
+    apt-get upgrade -y; \
+    apt-get install -y --no-install-recommends \
+      autogen \
+      ca-certificates \
+      git \
+      m4 \
+      nodejs \
+      perl \
+      python3 \
+      python3-git \
+      python3-termcolor \
+      python3-unidiff \
+      wget; \
+    rm -rf /var/lib/apt/lists/*
+
+# Get and install the autoregen.py script
+COPY --chmod=755 autoregen.py /usr/local/bin/autoregen.py
+
+# Build and install autoconf-2.69 and automake-1.15.1
+# Automake depends on autoconf, which is built and installed first
+RUN set -eux; \
+    \
+    savedAptMark="$(apt-mark showmanual)"; \
+    apt-get update; \
+    apt-get install -y --no-install-recommends \
+      build-essential \
+      ca-certificates \
+      gzip \
+      m4 \
+      tar \
+      wget \
+    ; \
+    rm -r /var/lib/apt/lists/*; \
+    \
+    builddir="$(mktemp -d)"; \
+    cd "${builddir}"; \
+    \
+    wget https://ftp.gnu.org/gnu/autoconf/autoconf-2.69.tar.gz; \
+    tar xf autoconf-2.69.tar.gz; \
+    cd autoconf-2.69; \
+    ./configure --program-suffix=-2.69; \
+    make; \
+    make install; \
+    cd .. ;\
+    rm -rf autoconf*; \
+    cd /usr/local/bin; \
+    ln -s autoconf-2.69 autoconf; \
+    ln -s autoheader-2.69 autoheader; \
+    ln -s autom4te-2.69 autom4te; \
+    ln -s autoreconf-2.69 autoreconf; \
+    ln -s autoscan-2.69 autoscan; \
+    ln -s autoupdate-2.69 autoupdate; \
+    \
+    cd "${builddir}"; \
+    wget https://ftp.gnu.org/gnu/automake/automake-1.15.1.tar.gz; \
+    tar xf automake-1.15.1.tar.gz; \
+    cd automake-1.15.1; \
+    ./configure --program-suffix=-1.15.1; \
+    make; \
+    make install; \
+    cd ..; \
+    rm -rf automake*; \
+    cd /usr/local/bin; \
+    ln -s aclocal-1.15.1 aclocal-1.15; \
+    ln -s aclocal-1.15.1 aclocal; \
+    ln -s automake-1.15.1 automake-1.15; \
+    ln -s automake-1.15.1 automake; \
+    \
+    rm -rf "${builddir}"; \
+    \
+    apt-mark auto '.*' > /dev/null; \
+    [ -z "$savedAptMark" ] || apt-mark manual $savedAptMark; \
+    apt-get purge -y --auto-remove -o 
APT::AutoRemove::RecommendsImportant=false
diff --git a/contrib/ci-container/essential/autoregen.py 
b/contrib/ci-container/essential/autoregen.py
new file mode 100755
index 000000000000..7ac17c1b9dd8
--- /dev/null
+++ b/contrib/ci-container/essential/autoregen.py
@@ -0,0 +1,146 @@
+#!/usr/bin/env python3
+
+# This script helps to regenerate files managed by autotools and
+# autogen in binutils-gdb and gcc repositories.
+
+# It can be used by buildbots to check that the current repository
+# contents has been updated correctly, and by developers to update
+# such files as expected.
+
+import os
+import shutil
+import subprocess
+from pathlib import Path
+
+
+# On Gentoo, vanilla unpatched autotools are packaged separately.
+# We place the vanilla names first as we want to prefer those if both exist.
+AUTOCONF_NAMES = ["autoconf-vanilla-2.69", "autoconf-2.69", "autoconf"]
+AUTOMAKE_NAMES = ["automake-vanilla-1.15", "automake-1.15.1", "automake"]
+ACLOCAL_NAMES = ["aclocal-vanilla-1.15", "aclocal-1.15.1", "aclocal"]
+AUTOHEADER_NAMES = ["autoheader-vanilla-2.69", "autoheader-2.69", "autoheader"]
+AUTORECONF_NAMES = ["autoreconf-vanilla-2.69", "autoreconf-2.69", "autoreconf"]
+
+# Pick the first for each list that exists on this system.
+AUTOCONF_BIN = next(name for name in AUTOCONF_NAMES if shutil.which(name))
+AUTOMAKE_BIN = next(name for name in AUTOMAKE_NAMES if shutil.which(name))
+ACLOCAL_BIN = next(name for name in ACLOCAL_NAMES if shutil.which(name))
+AUTOHEADER_BIN = next(name for name in AUTOHEADER_NAMES if shutil.which(name))
+AUTORECONF_BIN = next(name for name in AUTORECONF_NAMES if shutil.which(name))
+
+AUTOGEN_BIN = "autogen"
+
+# autoconf-wrapper and automake-wrapper from Gentoo look at this environment 
variable.
+# It's harmless to set it on other systems though.
+EXTRA_ENV = {
+    "WANT_AUTOCONF": AUTOCONF_BIN.split("-", 1)[1] if "-" in AUTOCONF_BIN else 
"",
+    "WANT_AUTOMAKE": AUTOMAKE_BIN.split("-", 1)[1] if "-" in AUTOMAKE_BIN else 
"",
+    "AUTOCONF": AUTOCONF_BIN,
+    "ACLOCAL": ACLOCAL_BIN,
+    "AUTOMAKE": AUTOMAKE_BIN,
+    "AUTOGEN": AUTOGEN_BIN,
+}
+ENV = os.environ.copy()
+ENV.update(EXTRA_ENV)
+
+
+# Directories we should skip entirely because they're vendored or have 
different
+# autotools versions.
+SKIP_DIRS = [
+    # readline and minizip are maintained with different autotools versions
+    "readline",
+    "minizip",
+]
+
+MANUAL_CONF_DIRS = [
+    ".",
+    # autoreconf does not update aclocal.m4
+    "fixincludes",
+    ]
+
+# Run the shell command CMD.
+#
+# Print the command on stdout prior to running it.
+def run_shell(cmd: str):
+    print(f"+ {cmd}", flush=True)
+    res = subprocess.run(
+        f"{cmd}",
+        shell=True,
+        encoding="utf8",
+        env=ENV,
+    )
+    res.check_returncode()
+
+
+def regenerate_with_autoreconf():
+    run_shell(f"{AUTORECONF_BIN} -f")
+
+def regenerate_with_autogen():
+    run_shell(f"{AUTOGEN_BIN} Makefile.def")
+
+def regenerate_manually():
+    configure_lines = open("configure.ac").read().splitlines()
+    if folder.stem == "fixincludes" or any(
+            True for line in configure_lines if 
line.startswith("AC_CONFIG_MACRO_DIR")
+    ):
+        include_arg = ""
+        include_arg2 = ""
+        if (folder / ".." / "config").is_dir():
+            include_arg = "-I../config"
+
+        if folder.stem == "fixincludes":
+            include_arg = "-I.."
+            include_arg2 = "-I../config"
+
+        # aclocal does not support the -f short option for force
+        run_shell(f"{ACLOCAL_BIN} --force {include_arg} {include_arg2}")
+
+    if (folder / "config.in").is_file() or any(
+        True for line in configure_lines if 
line.startswith("AC_CONFIG_HEADERS")
+    ):
+        run_shell(f"{AUTOHEADER_BIN} -f")
+
+    # apparently automake is somehow unstable -> skip it for gotools
+    if any(
+        True for line in configure_lines if line.startswith("AM_INIT_AUTOMAKE")
+    ) and not str(folder).endswith("gotools"):
+        run_shell(f"{AUTOMAKE_BIN} -f")
+
+    run_shell(f"{AUTOCONF_BIN} -f")
+
+
+run_shell(f"{AUTOCONF_BIN} --version")
+run_shell(f"{AUTOMAKE_BIN} --version")
+run_shell(f"{ACLOCAL_BIN} --version")
+run_shell(f"{AUTOHEADER_BIN} --version")
+
+print(f"Extra environment: {EXTRA_ENV}", flush=True)
+
+config_folders: list[Path] = []
+autogen_folders: list[Path] = []
+repo_root = Path.cwd()
+
+for root, _, files in os.walk("."):
+    for file in files:
+        if file == "configure.ac":
+            config_folders.append(Path(root).resolve())
+        if file == "Makefile.tpl":
+            autogen_folders.append(Path(root).resolve())
+
+for folder in sorted(autogen_folders):
+    print(f"Entering directory {folder}", flush=True)
+    os.chdir(folder)
+    regenerate_with_autogen()
+
+for folder in sorted(config_folders):
+    if folder.stem in SKIP_DIRS:
+        print(f"Skipping directory {folder}", flush=True)
+        continue
+
+    print(f"Entering directory {folder}", flush=True)
+    os.chdir(folder)
+
+    if str(folder.relative_to(repo_root)) in MANUAL_CONF_DIRS:
+        regenerate_manually()
+    else:
+        regenerate_with_autoreconf()
-- 
2.52.0

Reply via email to