xiaohongshu
xiaohongshu
c-incremental-build-converter
Convert C/C++ project build.sh and test.sh scripts to support incremental builds. Use when fixing build scripts for re-execution after docker commit, converting to out-of-tree builds, or making scripts idempotent for repeated execution.
Full skill instructions
This skill converts C/C++ project build.sh and test.sh scripts to support incremental builds after docker commit.
NEVER modify these files:
oss-fuzz/infra/helper.pyoss-fuzz/infra/base-images/*ONLY modify:
oss-fuzz/projects/{project}/build.shoss-fuzz/projects/{project}/test.shoss-fuzz/projects/{project}/Dockerfile (if absolutely necessary)If the incremental build test framework (incremental_build_checker.py) has bugs or limitations:
Example report format:
## oss-crs Framework Issue Detected
**File:** bug_fixing/src/oss_patch/inc_build_checker/incremental_build_checker.py
**Issue:** The source copy command destroys build artifacts
**Current behavior:** `rm -rf $SRC/nginx && cp -r ...`
**Expected behavior:** Should preserve objs/ directory
**Suggested fix:** Use rsync with --exclude objs instead of rm+cp
IMPORTANT: $SRC is different between build.sh and test.sh.
/built-src → $SRC = /built-src/test-src → $SRC = /test-srcThese are completely separate directories. This separation means:
CRITICAL: Always use $SRC variable, never hardcode /src, /built-src, or /test-src.
# BAD - Hardcoded path breaks when $SRC changes
cd /src/project
cp -r /src/oniguruma modules/
# GOOD - Uses $SRC variable
cd $SRC/project
cp -r $SRC/oniguruma modules/
CRITICAL: Avoid using $WORK for build-related directories. Use $SRC subdirectories instead.
$WORK is shared between build.sh and test.sh, which causes problems:
Always use $SRC subdirectories for:
# BAD - Uses $WORK which is shared
BUILD_DIR="$WORK/build"
cmake "$SRC/project" -DCMAKE_INSTALL_PREFIX=$WORK
# GOOD - Uses $SRC subdirectories
BUILD_DIR="$SRC/project_build"
INSTALL_DIR="$SRC/project_install"
mkdir -p "$BUILD_DIR" "$INSTALL_DIR"
cd "$BUILD_DIR"
cmake "$SRC/project" -DCMAKE_INSTALL_PREFIX="$INSTALL_DIR"
In test.sh, also use $SRC subdirectories:
# BAD in test.sh - Uses shared $WORK with ASAN artifacts
./configure --prefix="$WORK"
# Error: undefined reference to __asan_*
# GOOD in test.sh - Uses separate prefix under $SRC
TEST_PREFIX="$SRC/test_deps"
mkdir -p "$TEST_PREFIX/lib" "$TEST_PREFIX/include"
if [ ! -f "$TEST_PREFIX/lib/libz.a" ]; then
pushd "$SRC/zlib"
./configure --static --prefix="$TEST_PREFIX"
make -j$(nproc) CFLAGS="-fPIC" # No ASAN flags
make install
popd
fi
IMPORTANT: test.sh runs unit tests, NOT fuzzing. Sanitizers are NOT needed and cause conflicts.
During incremental build testing, build.sh compiles with ASAN/sanitizer flags. When test.sh runs in the SAME directory, the object files from build.sh are ASAN-instrumented. If test.sh tries to link against these objects without ASAN runtime, you get undefined reference errors.
CRITICAL: Build artifacts from build.sh should NOT be reused in test.sh.
During incremental build testing:
.o files$SRC directory.o files, linking failsThe artifacts are incompatible because:
-fsanitize=address -fsanitize-address-use-after-scope -fsanitize=fuzzer-no-linkDO NOT use || true to ignore link failures - this hides the real problem. Fix the root cause by ensuring clean separation of build artifacts.
NEVER assume a script will only run once. Scripts must be idempotent.
# BAD - Runs configure every time
autoreconf -f -i
./configure
# GOOD - Only configure on first run
if [ ! -f Makefile ]; then
autoreconf -f -i
./configure
fi
make -j$(nproc)
Since $SRC is separate, there's no need to clean artifacts. Deleting them defeats incremental build.
# BAD - Destroys incremental build benefits
find . -name "*.o" -delete
find . -name "*.a" -delete
rm -rf .libs
# GOOD - Just build, artifacts from previous run will speed things up
if [ ! -f Makefile ]; then
./configure
fi
make -j$(nproc)
Only run configure-related commands on first execution.
# Pattern: Check for Makefile existence
if [ ! -f Makefile ]; then
autoreconf -fi # or ./bootstrap
./configure --options
fi
make -j$(nproc)
make check
cp Instead of mvmv removes the source file, causing failures on repeated runs.
# BAD - Fails on second run
mv scripts/config.temp scripts/config
# GOOD - Preserves source file
[ -f scripts/config.temp ] && cp scripts/config.temp scripts/config || true
# Build dependency only if not already built
if [ ! -f "$WORK/lib/libz.a" ]; then
pushd "$SRC/zlib"
./configure --static --prefix="$WORK"
make -j$(nproc)
make install
popd
fi
Remove failing test files directly instead of using TESTS variable (which can propagate to submodules).
# BAD - TESTS variable propagates to submodules
make check TESTS="tests/mantest tests/jqtest"
# GOOD - Remove failing test files directly
rm -f tests/shtest
rm -f tests/multiple.*
sed -i '/multiple/d' tests/Makefile.am
make check
# BAD - Deletes and recopies every time, breaks incremental build
rm -rf modules/oniguruma
rsync -a $SRC/oniguruma modules/
# GOOD - Only copy if not present
if [ ! -d modules/oniguruma ]; then
mkdir -p modules
cp -r $SRC/oniguruma modules/
fi
Files like dictionaries and seed corpus may not exist in all builds.
# BAD - Fails if file doesn't exist
cp $SRC/libtiff/contrib/oss-fuzz/tiff.dict $OUT/
# GOOD - Conditional copy with fallback
[ -f $SRC/libtiff/contrib/oss-fuzz/tiff.dict ] && cp $SRC/libtiff/contrib/oss-fuzz/tiff.dict $OUT/ || true
find . -name "*.tif" | xargs zip $OUT/seed_corpus.zip || true
make -k check || true for Potentially Failing TestsSome tests may fail in fuzzing environment. Use -k to continue and || true to not fail the script.
# BAD - Stops on first test failure
make check
# GOOD - Continue through failures
make -k check || true
echo "Tests completed"
When removing failing tests, modify Makefile.am BEFORE running autoreconf/configure.
# BAD - Removes test file but Makefile still references it
rm -f tests/shtest
autoreconf -fi
./configure
make check # Error: No rule to make target 'tests/shtest'
# GOOD - Remove from Makefile.am before configure
sed -i 's| tests/shtest||g' Makefile.am
autoreconf -fi
./configure
make check # Works
If the project's source contains its own build.sh (e.g., contrib/oss-fuzz/build.sh), it may use mv or other non-idempotent operations. Rewrite the logic in the project's build.sh instead.
# BAD - Sources internal build.sh that uses mv
source $SRC/project/contrib/oss-fuzz/build.sh
# GOOD - Rewrite the logic with cp instead of mv
if [ ! -f "$WORK/lib/libjbig.a" ]; then
pushd "$SRC/jbigkit"
make lib
# Use cp instead of mv for incremental build support
cp "$SRC"/jbigkit/libjbig/*.a "$WORK/lib/"
cp "$SRC"/jbigkit/libjbig/*.h "$WORK/include/"
popd
fi
sed -i Insertions with Pattern ChecksWhen using sed -i to insert content, check BOTH the original pattern exists AND the new content doesn't exist yet.
# BAD - Only checks if new content exists (can't distinguish original vs added)
if ! grep -q '%destructor' file.y; then
sed -i '/^%%$/i%destructor { free ($$); } ID' file.y
fi
# GOOD - Check original pattern exists AND new content not yet added
if grep -q '^%%$' file.y && ! grep -q '%destructor' file.y; then
sed -i '/^%%$/i%destructor { free ($$); } ID' file.y
fi
>>)Don't blindly use > (overwrite) or >> (append). Check if content already exists.
# BAD - Overwrites every time (inefficient, may lose state)
sed 's/main/old_main/' file.c > header.h
# BAD - Appends every time (file grows on each run)
sed 's/main/old_main/' file.c >> header.h
# GOOD - Only append if content not already present
if ! grep -q 'old_main' header.h 2>/dev/null; then
sed 's/main/old_main/' file.c >> header.h
fi
When $SRC changes between build.sh and test.sh, CMake/Ninja will fail with "manifest dirty" errors if build directory is in $WORK.
# BAD - $WORK is shared, CMake source path mismatch causes ninja errors
BUILD_DIR="$WORK/build"
cd "$BUILD_DIR"
cmake $SRC/project # Source path recorded as /built-src/project
# On test.sh: ninja fails because $SRC is now /test-src/project
# GOOD - Build directory relative to $SRC, each environment independent
BUILD_DIR="$SRC/project_build"
mkdir -p "$BUILD_DIR"
cd "$BUILD_DIR"
if [ ! -f build.ninja ]; then
cmake -GNinja $SRC/project
fi
ninja
Bazel has its own caching mechanism. ccache interferes with Bazel's compiler wrappers.
# BAD - ccache causes "invalid option" errors with Bazel
# Error: /usr/local/bin/ccache: invalid option -- 'U'
bazel build //...
# GOOD - Remove ccache from PATH before Bazel builds
export PATH=$(echo "$PATH" | sed 's|/ccache/bin:||g; s|:/ccache/bin||g')
unset CC CXX
export CC=clang
export CXX=clang++
bazel build //...
IMPORTANT: Execution Environment
$SRC is already set (no need for : "${SRC:=/src}")$SRC/{project} (no need for cd $SRC/{project})#!/bin/bash
set -ex
# Build (only configure on first run)
if [ ! -f Makefile ]; then
autoreconf -fi # or ./bootstrap, or skip if not autotools
./configure --options
fi
make -j$(nproc)
# Run tests (use -k to continue on failures, || true to not fail script)
make -k check || true
echo "Tests completed"
#!/bin/bash
set -ex
if [ ! -f Makefile ]; then
autoreconf -fi
./configure --enable-static
fi
make -j$(nproc)
make -k check || true
#!/bin/bash
set -ex
if [ ! -f Makefile ]; then
cmake . -DCMAKE_INSTALL_PREFIX=$WORK -DBUILD_SHARED_LIBS=off
fi
make -j$(nproc)
make test
#!/bin/bash
set -ex
# Build zlib (only on first run)
if [ ! -f "$WORK/lib/libz.a" ]; then
pushd "$SRC/zlib"
./configure --static --prefix="$WORK"
make -j$(nproc)
make install
popd
fi
# Build main project
if [ ! -f Makefile ]; then
cmake . -DCMAKE_INSTALL_PREFIX=$WORK
fi
make -j$(nproc)
make test
#!/bin/bash
set -ex
# Copy submodule if not present (conditional, not delete-and-copy)
if [ ! -d modules/oniguruma ]; then
mkdir -p modules
cp -r $SRC/oniguruma modules/
fi
# Remove failing tests from Makefile.am BEFORE configure
sed -i 's| tests/shtest||g' Makefile.am
if [ ! -f Makefile ]; then
autoreconf -fi
./configure --with-oniguruma=builtin
fi
make -j$(nproc)
# Run tests (some may fail in fuzzing environment)
make -k check || true
| Error | Cause | Fix |
|---|---|---|
undefined reference to __asan_* | $WORK shared with ASAN artifacts from build.sh | Use separate prefix like $SRC/test_deps in test.sh |
Makefile:xxx: No rule to make target | Partial build state | Use if [ ! -f Makefile ] guard around configure |
No rule to make target 'tests/shtest' | Test removed but still in Makefile.am | Use `sed -i 's |
source directory already configured | Previous configure run | Check for Makefile before configure |
mv: cannot stat: No such file | File moved in previous run | Use cp with guard |
failed to create tests/*.trs | TESTS= propagates to submodules | Remove failing test files directly |
No rule to make target 'jbig.h' | Original build.sh used mv to move files | Rewrite to use cp instead |
tiff.dict: No such file | Dict/corpus file doesn't exist | Use conditional copy: [ -f file ] && cp file dest || true |
No rule to make target 'all' in submodule | rm -rf && rsync deleted submodule's Makefile | Use conditional copy: if [ ! -d dir ]; then cp; fi |
%destructor redeclaration / duplicate content | sed -i insertion runs every time | Guard with pattern check: if grep -q 'pattern' && ! grep -q 'new_content' |
| File grows on each build | >> append runs every time | Guard append: if ! grep -q 'content' file; then ... >> file; fi |
ninja: manifest 'build.ninja' still dirty | CMake source path mismatch ($SRC changed) | Use $SRC-relative build dir instead of $WORK |
ccache: invalid option -- 'U' | ccache interferes with Bazel | Remove ccache from PATH: export PATH=$(echo "$PATH" | sed 's|/ccache/bin:||g') |
CRITICAL: Use the test-inc-build subagent via Task tool to prevent context limit errors.
The subagent runs tests, analyzes logs internally, and returns only essential summary information.
Task tool:
subagent_type: "test-inc-build"
description: "Test incremental build"
prompt: "Run incremental build test for {project_name} with oss-fuzz path ../oss-fuzz"
IMPORTANT: For AIXCC projects, use the aixcc/c/ or aixcc/jvm/ prefix in the project name.
Examples:
aixcc/c/afc-sqlite3-delta-01aixcc/c/atlanta-libjpeg-full-01aixcc/jvm/afc-jenkins-delta-01Use Task tool with run_in_background: true in a single message:
Task tool (run_in_background: true):
subagent_type: "test-inc-build"
prompt: "Run incremental build test for aixcc/c/afc-libexif-delta-01 with oss-fuzz path ../oss-fuzz"
Task tool (run_in_background: true):
subagent_type: "test-inc-build"
prompt: "Run incremental build test for aixcc/c/afc-libexif-delta-02 with oss-fuzz path ../oss-fuzz"
Then use TaskOutput to retrieve results from each agent.
On Success:
## Result: SUCCESS
**Project:** {project_name}
**Build Time Reduction:** {percentage}%
**Summary:** Incremental build working correctly.
On Failure:
## Result: FAILED
**Project:** {project_name}
**Error Type:** {category}
**Error Message:** {exact error, max 10 lines}
**Suggested Fix:** {brief fix}
Success criteria:
$SRC variable, NOT hardcoded paths like /src or /built-srcif [ ! -f Makefile ] guard around configure/autoreconfcp instead of mv where applicableif [ ! -d ]), not delete-and-copy$SRC subdirectories instead of $WORK for build dirs and install prefixes$SRC/test_deps) if dependencies needed[ -f file ] && cp ... || truemake -k check || true if some may failmv or non-idempotent operationssed -i insertions guarded with pattern + content check>>) guarded with content existence check$SRC-relative paths (not $WORK)xiaohongshu
technical spec
product ux expert
database patterns
Conduct multi-agent task orchestration and workflow coordination.
Initialize project with Conductor artifacts (product definition,
Expert in web animations, transitions, and motion design using Framer Motion and CSS
Creates Mermaid and ASCII diagrams for flowcharts, architecture, ERDs, state machines, mindmaps, and more. Use when user mentions diagram, flowchart, mermaid, ASCII diagram, text diagram, terminal diagram, visualize, C4, mindmap, architecture diagram, sequence diagram, ERD, or needs visual docume...
PostgreSQL bindings for H3 hexagonal grid system. Use when working with H3 cells in Postgres, including spatial indexing, geometry/geography integration, and raster analysis.
Context-Driven Development skill for projects using Conductor. Use this skill when you detect a `conductor/` directory in the project, when working on tasks defined in a `plan.md` file, or when the user asks about tracks, specs, or plans. Automatically applies TDD workflow, tracks task completion...
Display project status, active tracks, and next actions
Official Stakpak application containerization standard operating procedure, a step-by-step guidline to properly dockerize applications. This is a rule book curated by the Stakpak Team.
Generate, edit, and beat-sync AI video with leading models in one workspace.
The world's fastest calendar for remote work
Transform Your Design with AI Designer by ImgCreator.ai
Revolutionizing Video Production with AI-Powered Creativity
Extend an image past the frame and let AI fill the new aspect ratio.
Discover your celebrity doppelgänger with StarByFace!
ChainClarity explains 700+ crypto whitepapers in plain English, with layered summaries, comparisons, research tools, alerts, and a $4.99 Pro plan.
Opus.ai: Revolutionize Your Web Experience