Skip to content

Instantly share code, notes, and snippets.

@ProfAvery
Created October 3, 2025 22:49
Show Gist options
  • Save ProfAvery/5439b62a20d0a6f04da91cb3c4d3d444 to your computer and use it in GitHub Desktop.
Save ProfAvery/5439b62a20d0a6f04da91cb3c4d3d444 to your computer and use it in GitHub Desktop.
Multi-arch MinGW build wrapper
#!/bin/sh
# compile.sh - multi-arch MinGW build wrapper
# Examples:
# ./compile.sh test.c
# ./compile.sh --64 test.c
# ./compile.sh --64 --dll mydll.c
# ./compile.sh --32 --windows test.c
# ./compile.sh --32 --windows --unicode test.c -- -D_DEBUG
set -eu
usage() {
cat <<EOF
Usage: $0 [--32|--64] [--windows] [--unicode] [--dll] <file.c|.cc|.cpp> [-- extra flags]
Defaults: --32 if neither --32 nor --64 supplied.
--windows GUI subsystem (-mwindows) for executables only.
--unicode Adds -DUNICODE -D_UNICODE. For executables with --windows, also adds -municode.
--dll Build a DLL (.dll) and import lib (.a). Ignores --windows.
EOF
exit 1
}
# defaults
ARCH=32
WINDOWS=0
UNICODE=0
DLL=0
EXTRA_FLAGS=""
SRC=""
# parse args
while [ "$#" -gt 0 ]; do
case "$1" in
--32) ARCH=32; shift ;;
--64) ARCH=64; shift ;;
--windows) WINDOWS=1; shift ;;
--unicode) UNICODE=1; shift ;;
--dll) DLL=1; shift ;;
--help|-h) usage ;;
--)
shift
[ "$#" -gt 0 ] && EXTRA_FLAGS="$*"
break
;;
-*)
EXTRA_FLAGS="$EXTRA_FLAGS $1"
shift
;;
*)
if [ -z "$SRC" ]; then
SRC="$1"; shift
else
EXTRA_FLAGS="$EXTRA_FLAGS $1"
shift
fi
;;
esac
done
[ -n "$SRC" ] || usage
case "$SRC" in
*.c|*.cc|*.cpp) ;;
*) echo "Source should be .c, .cc, or .cpp" >&2; exit 1 ;;
esac
# toolchain
if [ "$ARCH" -eq 64 ]; then
CC="x86_64-w64-mingw32-g++"
else
CC="i686-w64-mingw32-g++"
fi
command -v "$CC" >/dev/null 2>&1 || { echo "Missing $CC in PATH"; exit 1; }
# names
BASE_NAME="$(basename "$SRC")"
BASE_NOEXT="${BASE_NAME%.*}"
if [ "$DLL" -eq 1 ]; then
OUT="${BASE_NOEXT}.dll"
IMPLIB="${BASE_NOEXT}.a"
else
OUT="${BASE_NOEXT}.exe"
fi
COMMON_FLAGS="
-O2
-ffunction-sections
-fdata-sections
-Wno-write-strings
-fno-exceptions
-fmerge-all-constants
-static-libstdc++
-static-libgcc
-fpermissive
-s
-Wl,--gc-sections
-DSECURITY_WIN32
"
LINK_LIBS="
-lws2_32
-ladvapi32
-lcrypt32
-liphlpapi
-lsecur32
-lole32
-loleaut32
-lshell32
-lpathcch
-lshlwapi
"
CMD="$CC \"$SRC\" -o \"$OUT\" $COMMON_FLAGS $LINK_LIBS"
# DLLs ignore subsystem flags
if [ "$DLL" -eq 0 ] && [ "$WINDOWS" -eq 1 ]; then
CMD="$CMD -mwindows"
fi
# unicode macros always OK; -municode only for GUI executables
if [ "$UNICODE" -eq 1 ]; then
CMD="$CMD -DUNICODE -D_UNICODE"
if [ "$DLL" -eq 0 ] && [ "$WINDOWS" -eq 1 ]; then
CMD="$CMD -municode"
fi
fi
# dll specifics
if [ "$DLL" -eq 1 ] ; then
CMD="$CMD -shared -Wl,--out-implib,\"$IMPLIB\""
if [ "$ARCH" -eq 32 ]; then
CMD="$CMD -Wl,--add-stdcall-alias"
fi
fi
# append user extras
[ -n "$EXTRA_FLAGS" ] && CMD="$CMD $EXTRA_FLAGS"
printf '%s\n' "Running: $CMD"
# shellcheck disable=SC2086
eval $CMD
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment