Skip to content

Instantly share code, notes, and snippets.

@CodeAsm
Created February 19, 2026 14:28
Show Gist options
  • Select an option

  • Save CodeAsm/610e2e1deb630a5ada0c76cfc206e39a to your computer and use it in GitHub Desktop.

Select an option

Save CodeAsm/610e2e1deb630a5ada0c76cfc206e39a to your computer and use it in GitHub Desktop.
A Bmake fork, called crappie. It will build fine with just a musl native compiler and now you have a working Make program.
#!/usr/bin/env sh
set -eu
SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd)
OUT_DIR=${OUT_DIR:-"$SCRIPT_DIR/out"}
BIN_DIR="$OUT_DIR/bin"
OBJ_DIR="$OUT_DIR/obj"
SYSMK_DIR=${SYSMK_DIR:-"$OUT_DIR/share/mk"}
SRC_DIR=${SRC_DIR:-"$SCRIPT_DIR/make"}
SRC_URL=${SRC_URL:-"http://www.crufty.net/ftp/pub/sjg/bmake-20251111.tar.gz"}
SRC_SUBDIR=${SRC_SUBDIR:-"bmake"}
MACHINE=${MACHINE:-"$(uname -m)"}
MACHINE_ARCH=${MACHINE_ARCH:-"$MACHINE"}
MAKE_SYMLINK=${MAKE_SYMLINK:-"yes"}
PREFIX=${PREFIX:-""}
INSTALL_MODE=${INSTALL_MODE:-"no"}
CC=${CC:-""}
CFLAGS=${CFLAGS:-"-Os"}
CPPFLAGS=${CPPFLAGS:-""}
LDFLAGS=${LDFLAGS:-"-static"}
# Check for -install flag
if [ "${1:-}" = "-install" ]; then
INSTALL_MODE="yes"
elif [ "${1:-}" = "--help" ]; then
# Continue to help below
:
fi
if [ "${1:-}" = "--help" ]; then
cat <<'EOF'
Usage: build-crappie.sh [OPTIONS]
Options:
-install Build and install to PREFIX directory
--help Show this help message
Env vars:
SRC_DIR Path to make sources (default: ./make)
SRC_URL Download URL if sources not found (default: crufty.net tarball)
SRC_SUBDIR Subdir inside tarball that contains sources (default: bmake)
OUT_DIR Output directory (default: ./out)
CC Compiler (default: musl-gcc if found, else cc)
CFLAGS C compiler flags (default: -Os)
CPPFLAGS Preprocessor flags (extra)
LDFLAGS Linker flags (default: -static)
SYSMK_DIR System mk directory (default: OUT_DIR/share/mk)
MACHINE Target machine name (default: uname -m)
MACHINE_ARCH Target machine arch (default: MACHINE)
MAKE_SYMLINK Create a make symlink (yes/no, default: yes)
PREFIX Installation prefix for -install (default: /)
Examples:
# Build to ./out (no installation)
CC=gcc sh ./build-crappie.sh
# Build and install to /usr/local
CC=gcc sh ./build-crappie.sh -install
# Build and install to custom prefix
PREFIX=/opt/crappie CC=gcc sh ./build-crappie.sh -install
Note: Tarball is cached in .cache/ for re-extraction if needed.
EOF
exit 0
fi
# Download and extract from URL only if sources don't exist locally
if [ ! -d "$SRC_DIR" ] || [ ! -f "$SRC_DIR/make.h" ]; then
echo "Source directory not complete. Downloading from: $SRC_URL" >&2
CACHE_DIR="$SCRIPT_DIR/.cache"
mkdir -p "$CACHE_DIR"
ARCHIVE_NAME=$(basename "$SRC_URL")
ARCHIVE_PATH="$CACHE_DIR/$ARCHIVE_NAME"
# Download if not cached
if [ ! -f "$ARCHIVE_PATH" ]; then
echo "Downloading: $SRC_URL" >&2
wget -O "$ARCHIVE_PATH" "$SRC_URL" || {
echo "Download failed!" >&2
exit 1
}
else
echo "Using cached: $ARCHIVE_PATH" >&2
fi
# Extract to source directory
echo "Extracting to: $SRC_DIR" >&2
mkdir -p "$(dirname "$SRC_DIR")"
tar -xzf "$ARCHIVE_PATH" -C "$(dirname "$SRC_DIR")" || {
echo "Extraction failed!" >&2
exit 1
}
# Handle extraction directory structure
if [ -d "$(dirname "$SRC_DIR")/$SRC_SUBDIR/usr.bin/make" ]; then
# bmake tarball has usr.bin/make subdirectory
mv "$(dirname "$SRC_DIR")/$SRC_SUBDIR/usr.bin/make" "$SRC_DIR" 2>/dev/null || true
elif [ -d "$(dirname "$SRC_DIR")/$SRC_SUBDIR" ] && [ "$SRC_DIR" != "$(dirname "$SRC_DIR")/$SRC_SUBDIR" ]; then
# Just rename the extracted subdir to our target
mv "$(dirname "$SRC_DIR")/$SRC_SUBDIR" "$SRC_DIR" 2>/dev/null || true
fi
echo "Source ready at: $SRC_DIR" >&2
fi
if [ ! -d "$SRC_DIR" ]; then
echo "Source directory not found: $SRC_DIR" >&2
exit 1
fi
if [ -z "$CC" ]; then
if command -v musl-gcc >/dev/null 2>&1; then
CC=musl-gcc
else
CC=cc
fi
fi
# Set default sys.mk path based on install mode
if [ "$INSTALL_MODE" = "yes" ]; then
DEFAULT_SYSMK_PATH="$PREFIX/share/mk"
else
DEFAULT_SYSMK_PATH="$SYSMK_DIR"
fi
DEFINES="-DHAVE_SETENV -DHAVE_SETPGID -DHAVE_SETRLIMIT -DHAVE_STRERROR -DHAVE_STRSEP -DHAVE_VSNPRINTF -DHAVE_POLL_H -DHAVE_GETCWD -DHAVE_SIGACTION -DHAVE_STDINT_H -DHAVE_INTTYPES_H -DHAVE_LIMITS_H"
DEFINES="$DEFINES -DTARGET_MACHINE=\"$MACHINE\" -DTARGET_MACHINE_ARCH=\"$MACHINE_ARCH\" -DMAKE_MACHINE=\"$MACHINE\""
DEFINES="$DEFINES -D_PATH_DEFSYSPATH=\"$DEFAULT_SYSMK_PATH\""
SRCS="arch.c buf.c compat.c cond.c dir.c for.c hash.c job.c lst.c main.c make.c make_malloc.c metachar.c parse.c str.c suff.c targ.c trace.c var.c util.c"
mkdir -p "$BIN_DIR" "$OBJ_DIR" "$SYSMK_DIR"
# Create compat directory with system headers
COMPAT_DIR="$OUT_DIR/compat"
mkdir -p "$COMPAT_DIR/sys"
cat > "$COMPAT_DIR/sys/cdefs.h" <<'EOF'
#ifndef CRAPPIE_SYS_CDEFS_H
#define CRAPPIE_SYS_CDEFS_H
/* Minimal sys/cdefs.h for non-BSD systems */
#include <string.h>
#define __RCSID(x)
#define __COPYRIGHT(x)
#ifdef __cplusplus
#define __BEGIN_DECLS extern "C" {
#define __END_DECLS }
#else
#define __BEGIN_DECLS
#define __END_DECLS
#endif
#endif
EOF
cat > "$COMPAT_DIR/string.h" <<'EOF'
#ifndef CRAPPIE_STRING_H
#define CRAPPIE_STRING_H
/* Ensure standard string.h is available */
#include_next <string.h>
#endif
EOF
# Create sys.mk file
cat > "$SYSMK_DIR/sys.mk" <<'EOF'
# Minimal sys.mk for crappie.
# Keep this tiny to support very small embedded systems.
.SUFFIXES:
EOF
for src in $SRCS; do
obj="$OBJ_DIR/${src%.c}.o"
"$CC" -I"$COMPAT_DIR" $CPPFLAGS $CFLAGS $DEFINES -I"$SRC_DIR" -Wno-implicit-function-declaration -Wno-int-conversion -c "$SRC_DIR/$src" -o "$obj"
done
"$CC" $CFLAGS "$OBJ_DIR"/*.o -o "$BIN_DIR/crappie" $LDFLAGS -Wl,--allow-multiple-definition
if [ "$MAKE_SYMLINK" = "yes" ]; then
ln -sf crappie "$BIN_DIR/make"
fi
echo "Built: $BIN_DIR/crappie"
if [ "$MAKE_SYMLINK" = "yes" ]; then
echo "Symlink: $BIN_DIR/make -> crappie"
fi
# Install if requested
if [ "$INSTALL_MODE" = "yes" ]; then
echo "Installing to $PREFIX..." >&2
mkdir -p "$PREFIX/bin" "$PREFIX/share/mk"
cp "$BIN_DIR/crappie" "$PREFIX/bin/crappie"
chmod 755 "$PREFIX/bin/crappie"
echo "Installed: $PREFIX/bin/crappie"
if [ "$MAKE_SYMLINK" = "yes" ]; then
rm -f "$PREFIX/bin/make"
ln -s crappie "$PREFIX/bin/make"
echo "Symlink: $PREFIX/bin/make -> crappie"
fi
cp "$SYSMK_DIR/sys.mk" "$PREFIX/share/mk/sys.mk"
chmod 644 "$PREFIX/share/mk/sys.mk"
echo "Installed: $PREFIX/share/mk/sys.mk"
# Update dpkg status if available
if [ -f "/var/lib/dpkg/status" ]; then
DPKG_STATUS="/var/lib/dpkg/status"
# Remove old crappie entry if it exists
if grep -q "^Package: crappie$" "$DPKG_STATUS"; then
# Remove the entire crappie entry (up to the next blank line)
sed -i '/^Package: crappie$/,/^$/d' "$DPKG_STATUS"
fi
# Add new entry
cat << EOF >> "$DPKG_STATUS"
Package: crappie (bmake)
Status: install ok installed
Priority: optional
Section: dev
Version: 20251111
EOF
echo "Updated: $DPKG_STATUS"
fi
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment