Skip to content
Merged
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
168 changes: 165 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@
# LLVM apt repo is added so clang-format-20 is available on ubuntu-24.04
# (which ships clang-format-18 by default).
#
# All seven top-level jobs (lint, build, debug-build, sanitize, motif,
# osiris, xfig) run in parallel. Osiris and Xfig each have no Motif
# All eight top-level jobs (lint, build, debug-build, sanitize, motif,
# osiris, xfig, gimp) run in parallel. Osiris and Xfig each have no Motif
# dependency, so they live in their own jobs rather than queueing behind
# the Motif + ViolaWWW + Mosaic chain. The Xft and Xaw link tests
# the Motif + ViolaWWW + Mosaic chain. GIMP 0.54 is a Motif client but
# gets its own job too: its plug-in build pulls in libpng/jpeg/tiff that
# the Motif chain does not need. The Xft and Xaw link tests
# (test-xft-link, test-libxaw-link) run as part of make check-unit in
# the build / debug-build / sanitize jobs, so the Athena-stack link
# surface is gated even when the dedicated xfig job is skipped.
Expand Down Expand Up @@ -45,6 +47,14 @@ env:
# these are pulled in by COMMON_BUILD_PKGS, so install them in the
# osiris job (the only job that runs `make osiris`).
OSIRIS_BUILD_PKGS: "meson ninja-build libjpeg-dev libpng-dev libfreetype-dev"
# GIMP 0.54's image-format plug-ins (plug-ins/{png,jpeg}) link the system
# format libraries into the standalone plug-in executables, never into the
# compat .so, so the SDL2/SDL2_ttf/pixman core-dep boundary is preserved.
# zlib1g-dev backs libpng's -lz. TIFF is dropped on purpose (see
# compat/gimp-patches/0012-plugins-drop-tiff.patch), so no libtiff-dev. The
# GIMP autoconf step also needs the MOTIF_BUILD_PKGS chain (autoconf + the
# bundled Motif build).
GIMP_BUILD_PKGS: "libpng-dev libjpeg-dev zlib1g-dev"
DIFFERENTIAL_PKGS: "imagemagick openssh-client python3-pil rsync xauth xvfb"

jobs:
Expand Down Expand Up @@ -138,6 +148,8 @@ jobs:
!build/upstream/osiris
!build/upstream/xfig-*
!build/upstream/.cache/xfig-*
!build/upstream/gimp-*
!build/upstream/.cache/gimp-*
key: upstream-src-v2-${{ runner.os }}-${{ hashFiles('scripts/sync-upstream-headers.py') }}
restore-keys: |
upstream-src-v2-${{ runner.os }}-
Expand Down Expand Up @@ -211,6 +223,8 @@ jobs:
!build/upstream/osiris
!build/upstream/xfig-*
!build/upstream/.cache/xfig-*
!build/upstream/gimp-*
!build/upstream/.cache/gimp-*
key: upstream-src-v2-${{ runner.os }}-${{ hashFiles('scripts/sync-upstream-headers.py') }}
restore-keys: |
upstream-src-v2-${{ runner.os }}-
Expand Down Expand Up @@ -281,6 +295,8 @@ jobs:
!build/upstream/osiris
!build/upstream/xfig-*
!build/upstream/.cache/xfig-*
!build/upstream/gimp-*
!build/upstream/.cache/gimp-*
key: upstream-src-v2-${{ runner.os }}-${{ hashFiles('scripts/sync-upstream-headers.py') }}
restore-keys: |
upstream-src-v2-${{ runner.os }}-
Expand Down Expand Up @@ -380,6 +396,8 @@ jobs:
!build/upstream/osiris
!build/upstream/xfig-*
!build/upstream/.cache/xfig-*
!build/upstream/gimp-*
!build/upstream/.cache/gimp-*
key: upstream-src-v2-${{ runner.os }}-${{ hashFiles('scripts/sync-upstream-headers.py') }}
restore-keys: |
upstream-src-v2-${{ runner.os }}-
Expand Down Expand Up @@ -586,6 +604,8 @@ jobs:
!build/upstream/osiris
!build/upstream/xfig-*
!build/upstream/.cache/xfig-*
!build/upstream/gimp-*
!build/upstream/.cache/gimp-*
key: upstream-src-v2-${{ runner.os }}-${{ hashFiles('scripts/sync-upstream-headers.py') }}
restore-keys: |
upstream-src-v2-${{ runner.os }}-
Expand Down Expand Up @@ -728,6 +748,8 @@ jobs:
!build/upstream/osiris
!build/upstream/xfig-*
!build/upstream/.cache/xfig-*
!build/upstream/gimp-*
!build/upstream/.cache/gimp-*
key: upstream-src-v2-${{ runner.os }}-${{ hashFiles('scripts/sync-upstream-headers.py') }}
restore-keys: |
upstream-src-v2-${{ runner.os }}-
Expand Down Expand Up @@ -808,3 +830,143 @@ jobs:
- name: ccache stats
if: ${{ !cancelled() }}
run: ccache --show-stats

# ---- GIMP 0.54 (Motif image editor) integration and validation ----
#
# GIMP 0.54.1 (1996) is the last Motif-based GIMP. It builds against
# libX11-compat, libXt-compat, libXext-compat, libXmu-compat,
# libXpm-compat, and the bundled thentenaar/motif (libXm + libMrm), with
# the compat/gimp-patches/ balooii LP64 rework applied. `make gimp-motif`
# pulls in the bundled Motif build as a prerequisite, so this job carries
# the MOTIF_BUILD_PKGS autoreconf chain and the MOTIF_YACC override like
# the motif job, plus the libpng/jpeg/tiff dev packages the image-format
# plug-ins link. The job builds the editor and runs the replay-driven
# gimp-motif-startup toolbox smoke check. GIMP has no differential gate
# yet, so it does not appear in differential.yml.
gimp:
runs-on: ubuntu-24.04
env:
# Same bison yacc-compat shim the motif job uses for the Mrm parser
# generation; the bundled Motif is a build prerequisite of GIMP.
MOTIF_YACC: "bison -y"
steps:
- name: Checkout
uses: actions/checkout@v6

- name: Install build dependencies
run: |
sudo apt-get update
sudo apt-get install -y --no-install-recommends \
${{ env.COMMON_BUILD_PKGS }} ${{ env.MOTIF_BUILD_PKGS }} \
${{ env.GIMP_BUILD_PKGS }} ${{ env.DIFFERENTIAL_PKGS }}

- name: Cache upstream tarballs and extracted source/headers
uses: actions/cache@v5
with:
path: |
build/upstream
!build/upstream/**/*.o
!build/upstream/**/*.d
!build/upstream/motif
!build/upstream/mosaic
!build/upstream/osiris
!build/upstream/xfig-*
!build/upstream/.cache/xfig-*
!build/upstream/gimp-*
!build/upstream/.cache/gimp-*
key: upstream-src-v2-${{ runner.os }}-${{ hashFiles('scripts/sync-upstream-headers.py') }}
restore-keys: |
upstream-src-v2-${{ runner.os }}-

- name: Cache Motif source clone and autoreconf output
# GIMP reuses the in-tree thentenaar/motif as its libXm/libMrm
# provider, so cache the same clone+autoreconf the motif job does.
# Exact-match key only, matching the motif job's rationale.
uses: actions/cache@v5
with:
path: build/upstream/motif
key: motif-src-${{ runner.os }}-${{ hashFiles('mk/motif.mk', 'compat/motif-patches/**') }}

- name: Cache GIMP source tree
# Exact-match key only. GIMP_VERSION / GIMP_SHA256 in
# mk/gimp-motif.mk pin the tarball, and the compat/gimp-patches/
# set is applied to a throwaway work tree (build/gimp-motif/source),
# so the extracted tree here stays pristine. Cache the tarball too
# so a cache hit avoids both the re-download and the re-extract.
uses: actions/cache@v5
with:
path: |
build/upstream/gimp-0.54.1
build/upstream/.cache/gimp-0.54.1.fixed.tar.gz
key: gimp-src-${{ runner.os }}-${{ hashFiles('mk/gimp-motif.mk', 'compat/gimp-patches/**') }}

- name: Cache ccache
# Distinct key from motif/osiris/xfig so the GIMP .o set does not
# collide with objects compiled with a different include path.
uses: actions/cache@v5
with:
path: ~/.cache/ccache
key: ccache-gimp-v2-${{ runner.os }}-${{ github.sha }}
restore-keys: |
ccache-gimp-v2-${{ runner.os }}-

- name: Configure ccache
run: |
ccache --max-size=600M
ccache --zero-stats
echo "CC=ccache clang" >>"$GITHUB_ENV"

- name: Build libX11-compat (prerequisite for GIMP)
run: make -j"$(nproc)"

- name: Build Motif libXm and libMrm (prerequisite for GIMP)
run: make motif -j"$(nproc)"

- name: Build GIMP 0.54 against compat stack
id: gimp
# mk/gimp-motif.mk fetches gimp-0.54.1.fixed.tar.gz, applies the
# compat/gimp-patches/ balooii LP64 rework, stages the lib-aliases
# symlink farm and merged include sysroot, runs the 1996 autoconf
# build for app/gimp, then a second isolated make for the
# image-format plug-ins. The recursive make is invoked with
# built-in rules restored (the 1996 Makefiles depend on them).
# Full log lives at build/gimp-motif/build.log, uploaded on failure.
run: make gimp-motif -j"$(nproc)"

- name: Run GIMP replay smoke check
id: gimp-smoke
# gimp-motif-startup launches app/gimp under an empty HOME (which
# exercises the gimprc-default-build-paths patch) and asserts on
# the rendered toolbox region. Display 124 is distinct from motif
# (121), mosaic (122), and xfig (123) so a future shared runner
# does not collide.
if: ${{ !cancelled() && steps.gimp.outcome == 'success' }}
env:
UI_REPLAY_XVFB: --xvfb
UI_REPLAY_SCREENSHOT_COMMAND: import
UI_REPLAY_DISPLAY: 124
run: make check-smoke-gimp-motif

- name: Upload GIMP build log on failure
if: ${{ failure() && steps.gimp.outcome == 'failure' }}
uses: actions/upload-artifact@v7
with:
name: gimp-build-log
path: build/gimp-motif/build.log
if-no-files-found: warn
retention-days: 7

- name: Upload UI smoke artifacts on failure
# Distinct artifact name from the other jobs so concurrent uploads
# do not overwrite each other.
if: failure()
uses: actions/upload-artifact@v7
with:
name: ui-smoke-gimp
path: build/ui-smoke
if-no-files-found: warn
retention-days: 7

- name: ccache stats
if: ${{ !cancelled() }}
run: ccache --show-stats
118 changes: 116 additions & 2 deletions .github/workflows/differential.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Differential gates for the SDL2-based libx11-compat stack.
#
# Each downstream target (Motif, ViolaWWW, Mosaic, Osiris, Xfig) is
# Each downstream target (Motif, ViolaWWW, Mosaic, Osiris, Xfig, GIMP) is
# built twice on the same GitHub-hosted runner: once against the
# system libX11 stack from apt and once against libx11-compat. The
# resulting screenshots are compared under Xvfb. This is the local
Expand All @@ -10,7 +10,7 @@
# Differential gates live in a separate workflow from ci.yml so the
# fast PR feedback loop (lint / build / smoke) is not delayed by the
# heavier double-build pipeline, and so each downstream target reports
# its own status check independent of the others. The five jobs run
# its own status check independent of the others. The six jobs run
# in parallel; total wallclock is bounded by the slowest single job
# rather than the sum of all jobs.
#
Expand Down Expand Up @@ -91,6 +91,8 @@ jobs:
!build/upstream/osiris
!build/upstream/xfig-*
!build/upstream/.cache/xfig-*
!build/upstream/gimp-*
!build/upstream/.cache/gimp-*
key: upstream-src-v2-${{ runner.os }}-${{ hashFiles('scripts/sync-upstream-headers.py') }}
restore-keys: |
upstream-src-v2-${{ runner.os }}-
Expand Down Expand Up @@ -201,6 +203,8 @@ jobs:
!build/upstream/osiris
!build/upstream/xfig-*
!build/upstream/.cache/xfig-*
!build/upstream/gimp-*
!build/upstream/.cache/gimp-*
key: upstream-src-v2-${{ runner.os }}-${{ hashFiles('scripts/sync-upstream-headers.py') }}
restore-keys: |
upstream-src-v2-${{ runner.os }}-
Expand Down Expand Up @@ -283,6 +287,8 @@ jobs:
!build/upstream/osiris
!build/upstream/xfig-*
!build/upstream/.cache/xfig-*
!build/upstream/gimp-*
!build/upstream/.cache/gimp-*
key: upstream-src-v2-${{ runner.os }}-${{ hashFiles('scripts/sync-upstream-headers.py') }}
restore-keys: |
upstream-src-v2-${{ runner.os }}-
Expand Down Expand Up @@ -370,6 +376,8 @@ jobs:
!build/upstream/osiris
!build/upstream/xfig-*
!build/upstream/.cache/xfig-*
!build/upstream/gimp-*
!build/upstream/.cache/gimp-*
key: upstream-src-v2-${{ runner.os }}-${{ hashFiles('scripts/sync-upstream-headers.py') }}
restore-keys: |
upstream-src-v2-${{ runner.os }}-
Expand Down Expand Up @@ -465,6 +473,8 @@ jobs:
!build/upstream/osiris
!build/upstream/xfig-*
!build/upstream/.cache/xfig-*
!build/upstream/gimp-*
!build/upstream/.cache/gimp-*
key: upstream-src-v2-${{ runner.os }}-${{ hashFiles('scripts/sync-upstream-headers.py') }}
restore-keys: |
upstream-src-v2-${{ runner.os }}-
Expand Down Expand Up @@ -515,3 +525,107 @@ jobs:
- name: ccache stats
if: ${{ !cancelled() }}
run: ccache --show-stats

# ---- GIMP 0.54 toolbox-startup differential ----
#
# GIMP 0.54.1 is the heaviest Motif client here. It is built twice on
# the runner: once against system libX11 + OpenMotif (libmotif-dev,
# the same 2.3.x toolkit the balooii patch set targets) and once
# against libx11-compat + the bundled thentenaar/motif. Both render
# the Motif toolbox under Xvfb and the startup screen is compared.
# Validated on node11 (OpenMotif 2.3.8): MAE 0.072, changed 0.194 for
# the toolbox screen, comfortably under the 0.16 / 0.42 thresholds.
# The compat side builds the bundled Motif, so this job carries the
# MOTIF_BUILD_PKGS autoreconf chain and the MOTIF_YACC override.
gimp-differential:
runs-on: ubuntu-24.04
timeout-minutes: 25
env:
MOTIF_YACC: "bison -y"
steps:
- name: Checkout
uses: actions/checkout@v6

- name: Install build + system X11 dependencies
# libmotif-dev supplies the system OpenMotif baseline; libpng-dev
# / libjpeg-dev / zlib1g-dev back the GIMP image-format plug-ins
# (TIFF is dropped, see compat/gimp-patches/0012-plugins-drop-tiff.patch).
run: |
sudo apt-get update
sudo apt-get install -y --no-install-recommends \
${{ env.COMMON_BUILD_PKGS }} ${{ env.SYSTEM_X11_DEV_PKGS }} \
${{ env.DIFFERENTIAL_PKGS }} ${{ env.MOTIF_BUILD_PKGS }} \
libmotif-dev libpng-dev libjpeg-dev zlib1g-dev

- name: Cache upstream tarballs and extracted source/headers
uses: actions/cache@v5
with:
path: |
build/upstream
!build/upstream/**/*.o
!build/upstream/**/*.d
!build/upstream/motif
!build/upstream/mosaic
!build/upstream/osiris
!build/upstream/xfig-*
!build/upstream/.cache/xfig-*
!build/upstream/gimp-*
!build/upstream/.cache/gimp-*
key: upstream-src-v2-${{ runner.os }}-${{ hashFiles('scripts/sync-upstream-headers.py') }}
restore-keys: |
upstream-src-v2-${{ runner.os }}-

- name: Cache Motif source clone and autoreconf output
# The compat side reuses the in-tree thentenaar/motif as libXm /
# libMrm, so share the motif job's clone+autoreconf cache key.
uses: actions/cache@v5
with:
path: build/upstream/motif
key: motif-src-${{ runner.os }}-${{ hashFiles('mk/motif.mk', 'compat/motif-patches/**') }}

- name: Cache GIMP source tree
uses: actions/cache@v5
with:
path: |
build/upstream/gimp-0.54.1
build/upstream/.cache/gimp-0.54.1.fixed.tar.gz
key: gimp-src-${{ runner.os }}-${{ hashFiles('mk/gimp-motif.mk', 'compat/gimp-patches/**') }}

- name: Cache ccache
uses: actions/cache@v5
with:
path: ~/.cache/ccache
key: ccache-gimp-diff-v3-${{ runner.os }}-${{ github.sha }}
restore-keys: |
ccache-gimp-diff-v3-${{ runner.os }}-

- name: Configure ccache
run: |
ccache --max-size=2048M
ccache --zero-stats

- name: Run GIMP differential
env:
GIMP_DIFF_LOCAL: "1"
GIMP_DIFF_COMPARE_LOCATION: local
GIMP_DIFF_JOBS: "2"
run: make check-differential-gimp-motif

- name: Upload GIMP differential artifacts on failure
if: failure()
uses: actions/upload-artifact@v7
with:
name: gimp-differential
path: |
build/gimp-differential/report.tsv
build/gimp-differential/junit.xml
build/gimp-differential/logs
build/gimp-differential/diff
build/gimp-differential/system
build/gimp-differential/compat
if-no-files-found: warn
retention-days: 7

- name: ccache stats
if: ${{ !cancelled() }}
run: ccache --show-stats
Loading
Loading