Skip to content

build: build the vendored Capstone from the autotools build - #40

Open
moha-bekh wants to merge 2 commits into
masterfrom
cod-3465-create-a-self-contained-valgrind-build-script
Open

build: build the vendored Capstone from the autotools build#40
moha-bekh wants to merge 2 commits into
masterfrom
cod-3465-create-a-self-contained-valgrind-build-script

Conversation

@moha-bekh

Copy link
Copy Markdown
Member

Callgrind's cycle estimation links a static Capstone, which until now had to be built by hand before Valgrind: configure hard-failed unless it was given --with-capstone=PATH or CAPSTONE_DIR. That put the same cmake invocation in a wrapper script and in a CI action, where the two copies of the required compiler flags could drift apart, and every new consumer had to repeat it.

This compiles the submodule as an automake convenience library instead, so a plain ./autogen.sh && ./configure && make && make install is the whole build. --with-capstone stays as an override for the Nix dev shell and the Debian packaging, but nothing needs it any more.

The CodSpeed logic lives in files of its own (m4/codspeed_capstone.m4 and third_party/Makefile.am), leaving three one-line touch points in upstream files -- the macro call, an AC_CONFIG_FILES entry and a SUBDIRS entry -- in place of the 28-line block this removes from configure.ac, so rebasing onto upstream conflicts on single lines.

Two things the wrapper script was hiding, now handled by the build system

  • The tool CFLAGS pass -fno-builtin, so GCC no longer folds Capstone's fprintf(stderr, "...") guard into fwrite. The tool shimmed only fwrite and thus only linked by accident of that optimisation; this shims fprintf and strcat explicitly, and compiles Capstone -DNDEBUG as its own Release build does so assert() does not pull in __assert_fail.
  • CFLAGS=-std=gnu17 was passed by the script alone, so builds through debian/rules or nix never got it. AC_PROG_CC picks gnu23 on GCC 15+, under which glibc 2.42+ defines strchr/strrchr/strstr as _Generic macros that clash with Callgrind's own definitions. It is pinned in configure instead.

@greptile-apps

greptile-apps Bot commented Sep 3, 2026

Copy link
Copy Markdown

Greptile Summary

This PR moves the vendored Capstone build into Autotools, retains support for an external Capstone installation, pins C compilation to GNU17, and adds the libc shims needed by the newly integrated static library.

  • Adds a conditional Automake convenience library containing Capstone’s x86 and AArch64 sources.
  • Replaces the inline configure logic with dedicated Capstone and C-standard macros.
  • Removes the standalone CMake build action from CI and release workflows.
  • Updates source-distribution inputs and Callgrind’s libc compatibility shims.

Confidence Score: 4/5

The external-Capstone build path should be fixed before merging because an offline Git checkout can fail during autogen even though vendoring was explicitly bypassed.

The new fatal submodule update runs before the configuration layer honors CAPSTONE_DIR, making the supported prebuilt-library override unusable when the checkout lacks initialized submodules and cannot access the network.

Files Needing Attention: autogen.sh and m4/codspeed_capstone.m4

Important Files Changed

Filename Overview
autogen.sh Adds fatal, unconditional submodule initialization for Git worktrees, preventing offline external-Capstone builds when the submodule is absent.
m4/codspeed_capstone.m4 Defines vendored-versus-external Capstone configuration and pins GNU17, but its override is evaluated too late to prevent autogen.sh from cloning.
third_party/Makefile.am Builds a primary-platform x86/AArch64 Capstone convenience archive and declares the vendored distribution inputs.
callgrind/cycledecode_capstone.c Adds fprintf and strcat shims required by Capstone when compiled under Valgrind’s tool flags.
configure.ac Integrates the new configuration macros and generates the third-party Makefile.
.github/workflows/release.yml Removes the redundant standalone CMake Capstone build and relies on the integrated Autotools path.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart LR
  A[Git checkout] --> B[autogen.sh]
  B --> C[Configure]
  C --> D{External Capstone supplied?}
  D -- No --> E[Build vendored libcapstone.a]
  D -- Yes --> F[Use prebuilt libcapstone.a]
  E --> G[Link primary Callgrind]
  F --> G
Loading

Fix all with Greploop Fix All in Claude Code Fix All in Codex

Prompt To Fix All With AI
### Issue 1
autogen.sh:25
**Override still initializes submodule**

When a Git checkout has no initialized Capstone submodule and runs offline with `CAPSTONE_DIR` set, this fatal update attempts to clone the vendored source before configure can honor the external-library override, causing `autogen.sh` to exit and preventing the supported prebuilt-Capstone build.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Reviews (1): Last reviewed commit: "build: build the vendored Capstone from ..." | Re-trigger Greptile

Comment thread autogen.sh Outdated
git config blame.ignoreRevsFile .git-blame-ignore-revs
# CodSpeed: the vendored Capstone decoder that Callgrind's cycle estimation
# links against. A clone without --recurse-submodules leaves it empty.
run git submodule update --init third_party/capstone

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Override still initializes submodule

When a Git checkout has no initialized Capstone submodule and runs offline with CAPSTONE_DIR set, this fatal update attempts to clone the vendored source before configure can honor the external-library override, causing autogen.sh to exit and preventing the supported prebuilt-Capstone build.

Knowledge Base Used:

Prompt To Fix With AI
This is a comment left during a code review.
Path: autogen.sh
Line: 25

Comment:
**Override still initializes submodule**

When a Git checkout has no initialized Capstone submodule and runs offline with `CAPSTONE_DIR` set, this fatal update attempts to clone the vendored source before configure can honor the external-library override, causing `autogen.sh` to exit and preventing the supported prebuilt-Capstone build.

**Knowledge Base Used:**
- [Build, platform, and testing infrastructure](https://app.greptile.com/codspeed/-/custom-context/knowledge-base/codspeedhq/valgrind-codspeed/-/docs/build-platform-and-testing.md)
- [Build and packaging workflows](https://app.greptile.com/codspeed/-/custom-context/knowledge-base/codspeedhq/valgrind-codspeed/-/docs/build-and-packaging.md)

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Fix in Claude Code Fix in Codex

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

We should not run this unconditionnally IMO, especially if people provide a CAPSTONE_DIR argument

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Agreed. Making the update non-fatal still causes an unnecessary network attempt, and it can fail before configure gets a chance to honor CAPSTONE_DIR. The submodule initialization should be conditional on CAPSTONE_DIR being unset. --with-capstone=PATH is only parsed by configure, so autogen.sh cannot detect that form unless configure arguments are explicitly passed through to it.

Tip: You can customize Greptile's behavior for this repo with .greptile/rules.md and .greptile/config.json.

@moha-bekh
moha-bekh force-pushed the cod-3465-create-a-self-contained-valgrind-build-script branch from 219de63 to 1f523ac Compare September 3, 2026 15:41
@codspeed-hq

codspeed-hq Bot commented Sep 3, 2026

Copy link
Copy Markdown

Merging this PR will not alter performance

✅ 84 untouched benchmarks
⏩ 60 skipped benchmarks1


Comparing cod-3465-create-a-self-contained-valgrind-build-script (9cea895) with master (aaa0946)

Open in CodSpeed

Footnotes

  1. 60 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

Comment thread m4/codspeed_capstone.m4 Outdated
Comment thread .gitmodules Outdated
Comment thread flake.nix Outdated
Mohamed and others added 2 commits September 4, 2026 15:20
Callgrind's cycle estimation links a static Capstone, which until now had to
be built by hand before Valgrind: configure hard-failed unless it was given
--with-capstone=PATH or CAPSTONE_DIR. That put the same cmake invocation in a
wrapper script and in a CI action, where the two copies of the required
compiler flags could drift apart, and every new consumer had to repeat it.

Compile the submodule as an automake convenience library instead, so a plain
`./autogen.sh && ./configure && make && make install` is the whole build.
--with-capstone (or CAPSTONE_DIR) stays as an override for a prebuilt decoder,
which the Debian packaging still wires through, but nothing needs it any more:
the Nix dev shell no longer sets it either.

The submodule sources are compiled through one-line stub units in
third_party/capstone-stubs/ rather than where they live. Automake is configured
with subdir-objects, so it writes an object next to its source, and Valgrind
only builds in-tree: compiling them in place would drop objects, .deps
directories and .dirstamp files into the capstone checkout and leave the
submodule permanently reported as dirty. The stubs keep every build artefact in
this repository, where .gitignore covers it, instead of asking git to look away
from a submodule that is genuinely being written to.

The CodSpeed logic lives in files of its own (m4/codspeed_capstone.m4 and
third_party/Makefile.am), leaving three one-line touch points in upstream
files -- the macro call, an AC_CONFIG_FILES entry and a SUBDIRS entry -- in
place of the 28-line block this removes from configure.ac, so rebasing onto
upstream conflicts on single lines.

Two things the wrapper script was hiding, now handled by the build system:

  - The tool CFLAGS pass -fno-builtin, so GCC no longer folds Capstone's
    fprintf(stderr, "...") guard into fwrite. The tool shimmed only fwrite and
    thus only linked by accident of that optimisation; shim fprintf and strcat
    explicitly, and compile Capstone -DNDEBUG as its own Release build does so
    assert() does not pull in __assert_fail.

  - CFLAGS=-std=gnu17 was passed by the script alone, so builds through
    debian/rules or nix never got it. AC_PROG_CC picks gnu23 on GCC 15+, under
    which glibc 2.42+ defines strchr/strrchr/strstr as _Generic macros that
    clash with Callgrind's own definitions. Pin it in configure instead.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
CAPSTONE_LIBS is named in callgrind's _LDADD but not in its _DEPENDENCIES, and
automake cannot tell that a configure substitution expands to a file, so it
derived no dependency of its own either. Rebuilding the decoder therefore left
callgrind-<platform> linked against the previous archive, silently, until
something else forced a relink.

Add it to the _DEPENDENCIES line the fork already sets for the primary
platform. The secondary platform has no Capstone and needs nothing.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@moha-bekh
moha-bekh force-pushed the cod-3465-create-a-self-contained-valgrind-build-script branch from 1f523ac to 9cea895 Compare September 4, 2026 13:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants