Skip to content

Add a 32-bit autotools CI job - #489

Merged
oschwald merged 2 commits into
mainfrom
wstorey/32bit-ci
Sep 14, 2026
Merged

oschwald merged 2 commits into
mainfrom
wstorey/32bit-ci

Conversation

@horgh

@horgh horgh commented Sep 13, 2026

Copy link
Copy Markdown
Contributor

ssize_t and long are 32 bits wide on i686. That exposes signedness and range problems that the 64-bit jobs cannot see, such as the -Wsign-compare error fixed in #487, which only showed up in Fedora's i686 build (#486).

The new job builds and tests with -m32 using gcc and clang on ubuntu-latest. The flags are set for the whole job so that the libtap build, which has its own Makefile, and the test scripts that compile code themselves pick them up.

The decoder limits test kept only -f flags from the environment when it rebuilt the library, so it would have dropped -m32 and checked 64-bit code. It now keeps -m flags as well.

Verification

I emulated the job locally with the same environment as the workflow:

Run Result
gcc, current main all 34 test programs pass
clang, current main all 34 test programs pass
gcc, #487 fix reverted make fails with the original -Wsign-compare error

With the #487 fix reverted, the old decoder limits script also passed at 32-bit and the new one fails with the original error, so the perl change is needed for that test to give 32-bit coverage.

The existing jobs are not affected by the perl change. None of them have an -m flag in CFLAGS or LDFLAGS while make check runs.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Tests
    • Added automated 32-bit build and test coverage across supported compiler environments.
    • Improved test compilation handling for target-specific flags, including 32-bit builds and sanitizers.
    • Updated test setup to support compiler commands that include additional compilation options.
    • Added required 32-bit build tooling in the Ubuntu test environment.

Copilot AI lite review requested due to automatic review settings September 13, 2026 18:13
@coderabbitai

coderabbitai Bot commented Sep 13, 2026

Copy link
Copy Markdown

Review Change StackReview Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Advanced

Run ID: 344fad40-f579-43a9-abc8-3d885c885234

📥 Commits

Reviewing files that changed from the base of the PR and between 13ae6f1 and 0502f98.

📒 Files selected for processing (2)
  • .github/workflows/test.yml
  • t/decoder_limits_t.pl

Included review availability: Your plan provides up to 4 included reviews per hour; 2 remain after this review.


📝 Walkthrough

Walkthrough

The workflow adds 32-bit autoconf build and test variants. The decoder limit test now accepts compiler commands that include flags and uses them for compiler probes and test-library builds.

Changes

32-bit CI coverage

Layer / File(s) Summary
32-bit build and test flow
.github/workflows/test.yml, t/decoder_limits_t.pl
The workflow adds an architecture matrix, multilib packages, and job-wide architecture flags. The decoder limit test splits CC into a command list and forwards the command and its flags to compiler invocations.

Priority: ⬇️ Low

Estimated code review effort: 2 (Simple) | ~10 minutes

Change: Feature

Suggested reviewers: oschwald

Merge Risk: ⚪ Minimal · up to 0502f

The 32-bit workflow forwards its compiler flags correctly across the inspected build and test consumers, with no identified regression.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: adding a 32-bit Autotools CI job.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 0…
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch wstorey/32bit-ci

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

I twitch my nose at flags in flight
The little builds now test just right
Thirty-two bits march in line
Compiler commands stay defined
A rabbit cheers the passing byte
And hops away into the night

Comment @coderabbitai help to get the list of available commands.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

The reviewed changes are complete with no unresolved blocking issues.

Pull request overview

Adds 32-bit Autotools CI coverage to detect i686-specific issues.

Changes:

  • Adds GCC and Clang -m32 CI jobs.
  • Preserves target flags in decoder limit test rebuilds.
File summaries
File Summary
t/decoder_limits_t.pl Retains -m target flags when rebuilding the library.
.github/workflows/test.yml Adds the 32-bit GCC/Clang CI matrix.
Review details
  • Files reviewed: 2/2 changed files
  • Comments generated: 0
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Copilot AI review requested due to automatic review settings September 13, 2026 18:15
ssize_t and long are 32 bits wide on i686. That exposes signedness and
range problems that the 64-bit jobs cannot see, such as the
-Wsign-compare error fixed in #487, which only showed up in Fedora's
i686 build.

The new job builds and tests with -m32 using gcc and clang. The flags
are set for the whole job so that the libtap build, which has its own
Makefile, and the test scripts that compile code themselves pick them
up.

The decoder limits test kept only -f flags from the environment when it
rebuilt the library, so it would have dropped -m32 and checked 64-bit
code. It now keeps -m flags as well. With the #487 fix reverted, the old
script passed at 32-bit and the new one fails with the original error.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

No unresolved issues remain, and the requested coverage changes are addressed.

Review details
  • Files reviewed: 2/2 changed files
  • Comments generated: 0 new
  • Review effort level: Lite

Copilot AI review requested due to automatic review settings September 13, 2026 18:17

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

No unresolved review issues remain.

Review details
  • Files reviewed: 2/2 changed files
  • Comments generated: 0 new
  • Review effort level: Lite

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

The workflow and test-script changes correctly provide consistent 32-bit coverage.

Review details
  • Files reviewed: 2/2 changed files
  • Comments generated: 0 new
  • Review effort level: Balanced

Comment on lines 9 to 34
test-autoconf:
strategy:
matrix:
os: [ubuntu-latest, macos-latest]
cc: [gcc, clang]
posix: ['', -D_POSIX_C_SOURCE=200112L]
name: Autotools build on ${{matrix.os}} using ${{matrix.cc}} ${{matrix.posix}}
runs-on: ${{ matrix.os }}
env:
CC: ${{ matrix.cc }}
VERBOSE: 1
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
submodules: true
persist-credentials: false
- run: sudo apt install libipc-run3-perl
if: ${{ matrix.os == 'ubuntu-latest' }}
- run: brew install autoconf automake libtool
if: ${{ matrix.os == 'macos-latest' }}
- run: ./bootstrap
- run: ./configure
env:
CFLAGS: -std=c99 -Wall -Wextra -Werror -Wno-unused-function -Wno-unused-parameter ${{ matrix.posix }}
- run: make
- run: make check

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we do something like this rather than having a separate job?

Suggested change
- run: make check
test-autoconf:
strategy:
matrix:
os: [ubuntu-latest, macos-latest]
cc: [gcc, clang]
posix: ['', -D_POSIX_C_SOURCE=200112L]
arch: ['', -m32]
exclude:
- os: macos-latest
arch: -m32
name: Autotools build on ${{matrix.os}} using ${{matrix.cc}} ${{matrix.posix}} ${{matrix.arch}}
runs-on: ${{ matrix.os }}
env:
CC: ${{ matrix.cc }}
CFLAGS: -std=c99 -Wall -Wextra -Werror -Wno-unused-function -Wno-unused-parameter ${{ matrix.posix }} ${{ matrix.arch }}
CXXFLAGS: ${{ matrix.arch }}
LDFLAGS: ${{ matrix.arch }}
VERBOSE: 1
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
submodules: true
persist-credentials: false
- run: sudo apt-get update && sudo apt-get install -y gcc-multilib g++-multilib libipc-run3-perl
if: ${{ matrix.os == 'ubuntu-latest' }}
- run: brew install autoconf automake libtool
if: ${{ matrix.os == 'macos-latest' }}
- run: ./bootstrap
- run: ./configure
- run: make
- run: make check

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, that suggestion didn't work that well, maybe because it was outside the diff.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good idea. Done in f7f4fef.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One adjustment in 13ae6f1: the warning and posix flags stay on the configure step. Setting them job-wide broke the libtap build on macOS, because _POSIX_C_SOURCE hides MAP_ANONYMOUS there. Only the -m32 flags are job-wide now.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That did not fix it either. When CFLAGS is in the environment at all, even empty, make exports the configured CFLAGS to the libtap sub-make, so libtap saw _POSIX_C_SOURCE on macOS. 0502f98 passes -m32 through CC="gcc -m32" instead, which reaches configure, libtap, and the test scripts, and keeps CFLAGS and LDFLAGS out of the job environment. Verified locally with a 32-bit build and full make check.

Copilot AI review requested due to automatic review settings September 14, 2026 14:59

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

The architecture flags propagate correctly throughout builds and tests; only an optional CI efficiency improvement remains.

Review details
  • Files reviewed: 2/2 changed files
  • Comments generated: 1
  • Review effort level: Balanced

Comment thread .github/workflows/test.yml Outdated
Copilot AI review requested due to automatic review settings September 14, 2026 15:03

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Job-level flags leak the POSIX define into the macOS libtap build, causing that matrix variant to fail.

Get a fresh assessment by requesting another Copilot review.

Review details
  • Files reviewed: 2/2 changed files
  • Comments generated: 1
  • Review effort level: Balanced

Comment thread .github/workflows/test.yml Outdated
Copilot AI review requested due to automatic review settings September 14, 2026 15:09

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

The changes consistently provide 32-bit coverage across the build and self-compiling tests.

Review details
  • Files reviewed: 2/2 changed files
  • Comments generated: 0 new
  • Review effort level: Balanced

Copilot AI review requested due to automatic review settings September 14, 2026 15:15

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

The focused changes correctly provide end-to-end 32-bit coverage without affecting existing matrix variants.

Review details
  • Files reviewed: 2/2 changed files
  • Comments generated: 0 new
  • Review effort level: Balanced

Add an arch dimension to the existing autoconf job instead of keeping a
separate 32-bit job. macOS is excluded from the -m32 variant, and the
multilib packages install only for the -m32 builds.

The flag goes through CC="gcc -m32" rather than CFLAGS and LDFLAGS.
CFLAGS must stay out of the job environment: when it is set, even
empty, make exports the configured CFLAGS to the libtap sub-make, and
libtap does not build on macOS with _POSIX_C_SOURCE defined. CC reaches
configure, libtap, and the test scripts.

The decoder limits test now splits CC on whitespace and no longer needs
to pick -m flags out of CFLAGS. CXXFLAGS stays job-wide for the C++
compile test, which reads it from the environment.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

@horgh horgh left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I verified this locally rather than reading it: built and ran the full suite at -m32, confirmed the artifacts are ELF 32-bit, and confirmed that reverting cd138a6 reproduces the exact -Wsign-compare error from #486. The design is right and the motivating bug is genuinely caught. Notes inline are polish, not blockers.

🤖 Comment by Claude (Claude Code) on behalf of Will.

- cron: '3 20 * * SUN'
permissions: {}
jobs:
# The -m32 variants build and test as 32-bit. ssize_t and long are 32 bits

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The PR description still describes the approach that 665789d replaced. It says the decoder limits test "now keeps -m flags as well" and that "The flags are set for the whole job", but the final diff does neither: the filter at t/decoder_limits_t.pl:45 is still /^-f/, -m32 arrives through CC, and keeping CFLAGS out of the job env is the whole point of the current design. The verification table also describes runs of the old approach.

The commit message on 665789d is accurate — worth copying over the PR body before merge, since that text is what ends up in the merge record.

(Commenting here because the PR body has no line to anchor to.)

🤖 Comment by Claude (Claude Code) on behalf of Will.

Comment thread t/decoder_limits_t.pl
my $cc = $ENV{CC} || 'cc';

# CC may carry flags, such as CC="gcc -m32".
my @cc = split ' ', $ENV{CC} || 'cc';

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

t/compile_c++_t.pl:51 still has the exact bug this line fixes:

my $cxx = $ENV{CXX} || 'c++';

No split, and $cxx is passed as a single element of the run3 command list. It does not bite today only because the arch flag is routed through CXXFLAGS rather than CXX. But the comment in test.yml argues the flag belongs in the compiler variable, so CXX="g++ -m32" is the natural next edit, and it would silently fail to exec exactly the way CC="gcc -m32" did here.

Worth applying the same split ' ' to both scripts in this PR so the two don't drift.

(The real target is t/compile_c++_t.pl:51, which is outside this diff.)

🤖 Comment by Claude (Claude Code) on behalf of Will.

# The -m32 variants build and test as 32-bit. ssize_t and long are 32 bits
# wide on i686, which exposes signedness and range problems that the 64-bit
# builds cannot see. The flag goes in CC rather than CFLAGS so that the
# libtap build, which has its own Makefile, and the test scripts that

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"the test scripts that compile code themselves pick it up too" is only true for decoder_limits_t.pl. The other script that compiles code, t/compile_c++_t.pl, reads $ENV{CXX} and $ENV{CXXFLAGS} and never looks at CC — it gets -m32 from the CXXFLAGS entry below, not from CC. external_symbols_t.pl only runs nm, and mmdblookup_t.pl compiles nothing.

The plural sends a reader looking for a mechanism that doesn't exist, and hides the one that does.

🤖 Comment by Claude (Claude Code) on behalf of Will.

persist-credentials: false
- run: sudo apt install libipc-run3-perl
if: ${{ matrix.os == 'ubuntu-latest' }}
- run: sudo apt-get update && sudo apt-get install -y gcc-multilib g++-multilib

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider asserting that the artifacts really are 32-bit, near these steps:

- run: file src/.libs/libmaxminddb.so | grep -q 'ELF 32-bit'
  if: ${{ matrix.arch == '-m32' }}

I checked every current way -m32 could get dropped and they all fail loudly — missing multilib dies at "C compiler cannot create executables", and a 64-bit libtap fails the link with an architecture mismatch. So this is not a present bug.

The risk is later drift: if someone edits the CC line or the matrix, the job keeps its -m32 name, tests 64-bit code, and goes green. The guard is one line and pins down the property the whole job exists for.

(The natural spot is after - run: make, which is outside this diff.)

🤖 Comment by Claude (Claude Code) on behalf of Will.

env:
CC: ${{ matrix.cc }}
CC: ${{ matrix.cc }} ${{ matrix.arch }}
CXXFLAGS: ${{ matrix.arch }}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This entry deserves a sentence in the comment above. It exists solely for t/compile_c++_t.pl:52, which reads $ENV{CXXFLAGS} and would otherwise link a 64-bit C++ binary against the 32-bit library. The reasoning is in 665789d's commit message but didn't make it into the file.

Without it, a reader applying the stated CFLAGS rule symmetrically ("when it is set, even empty...") may well delete this line and silently drop -m32 from the C++ test.

For what it's worth, the CFLAGS hazard genuinely does not apply here: there's no AC_PROG_CXX, CXXFLAGS appears zero times in every generated Makefile, and libtap's Makefile never reads it. So the empty value on the 64-bit rows is inert — but that's exactly the kind of thing worth stating rather than leaving the asymmetry looking accidental.

🤖 Comment by Claude (Claude Code) on behalf of Will.

Comment thread t/decoder_limits_t.pl
my ( $cc_version, $cc_stderr ) = ( q{}, q{} );
my $cc_status = eval {
run3( [ $cc, '--version' ], \undef, \$cc_version, \$cc_stderr );
run3( [ @cc, '--version' ], \undef, \$cc_version, \$cc_stderr );

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now that CC can carry flags, this probe has a wider failure surface worth tightening. run3 dies on exec failure rather than returning a status, so $cc_status comes back undef and the file hits skip_all at line 40 — reporting green — for causes the skip message never mentions: a compiler that isn't on PATH, a CC that word-splits into nothing, or a permissions problem. $@ and $cc_stderr are both discarded, and the command is never printed.

This is worth fixing because it's the failure mode this PR just fixed: I confirmed that on main, CC="gcc -m32" made this file skip silently rather than fail. Since CI always uses gcc or clang, a skip here is by definition a bug, and nothing notices.

Suggest skipping only on the condition the message actually describes, and dying otherwise:

die "CC is set but contains no command\n" unless @cc;
die "could not run '@cc --version': $@" if !defined $cc_status;

🤖 Comment by Claude (Claude Code) on behalf of Will.

exclude:
- os: macos-latest
arch: -m32
name: Autotools build on ${{matrix.os}} using ${{matrix.cc}} ${{matrix.posix}} ${{matrix.arch}}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two small things from appending ${{matrix.arch}} here.

The rendered names get a double space when posix is empty and a trailing one when arch is empty — the current run shows Autotools build on ubuntu-latest using clang -m32. Cosmetic, but easy to tidy.

More worth checking: all 8 pre-existing job names changed as a result. If any are configured as required status checks under branch protection, they'll need updating or merges will block on names that no longer exist.

🤖 Comment by Claude (Claude Code) on behalf of Will.

jobs:
# The -m32 variants build and test as 32-bit. ssize_t and long are 32 bits
# wide on i686, which exposes signedness and range problems that the 64-bit
# builds cannot see. The flag goes in CC rather than CFLAGS so that the

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor, but the comment undersells the strongest argument for this choice. It frames CC as being about reaching libtap, while the next sentence says CFLAGS reaches libtap too (and that this is the problem). The more compelling reason is that -m32 has to apply to linking as well as compiling, and t/libtap/Makefile:13,22 build their link lines from $(CC) $(LDFLAGS) with no CFLAGS at all — so -m32 in CFLAGS alone would compile 32-bit objects and link them 64-bit.

Also worth citing the concrete motivation, which 4a8984e's message had and this comment dropped: the -Wsign-compare error in #486/#487 that only Fedora's i686 build caught. It turns a plausible-sounding claim into a checkable one.

🤖 Comment by Claude (Claude Code) on behalf of Will.

@oschwald
oschwald merged commit 120ec19 into main Sep 14, 2026
44 checks passed
@oschwald
oschwald deleted the wstorey/32bit-ci branch September 14, 2026 15:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

3 participants