Created
February 19, 2026 14:28
-
-
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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/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