Skip to content

Instantly share code, notes, and snippets.

@garettbass
Created May 5, 2020 01:10
Show Gist options
  • Save garettbass/292013912430b99f126f6cd34188f8bb to your computer and use it in GitHub Desktop.
Save garettbass/292013912430b99f126f6cd34188f8bb to your computer and use it in GitHub Desktop.
This is the bash script I run to build C/C++ projects on Windows & macOS.
#!/usr/bin/env
CMDLINE="$0 $@"
#-------------------------------------------------------------------------------
function usage {
echo "Usage:"
echo ""
echo " sh $0 [options] <sources> [-- ...]"
echo ""
echo "Options:"
echo ""
echo " -std=<...> Set C/C++ standard, e.g "
echo " -D<...>[=...] Define preprocessor macro, e.g.: -DNDEBUG=1"
echo " -O<...> Set optimization level, e.g.: -O0, -O1, -O2, -O3, -Ofast, -Os"
echo " -g Generate debug symbols."
echo " -o <dir> Set output directory."
echo " -v Enable verbose output."
echo " -x <ext> Specify source language, e.g.: -x c, -x c++"
echo " --clean Delete build artifacts."
echo " --clear Clear the terminal before building."
echo " -- Run the compiled app, passing along remaining arguments."
echo ""
}
#-------------------------------------------------------------------------------
function realpath {
local path="${1//\\//}"
if [ "$path" == "." ]; then
echo "$(pwd)"
elif [ "$path" == ".." ]; then
echo "$(dirname "$(pwd)")"
else
echo "$(cd "$(dirname "$path")"; pwd)/$(basename "$path")"
fi
}
#-------------------------------------------------------------------------------
CFLAGS="$CFLAGS -Wall -Werror -Wfatal-errors -Wno-comment -Wno-unused-variable"
SOURCES=()
while [ $# -gt 0 ]; do
case $1 in
-h|--help)
usage
exit 1
;;
-g)
CFLAGS="$CFLAGS $1"
shift
;;
-D*|-f*|-I*|-O*|-std=*|-W*)
CFLAGS="$CFLAGS $1"
shift
;;
-x)
CFLAGS="$CFLAGS $1 $2"
shift
shift
;;
-o)
APP_BUILD_ROOT="$2"
shift
shift
;;
-t|--time)
TIME=YES
shift
;;
-v|--verbose)
VERBOSE=YES
shift
;;
--clean)
CLEAN=YES
shift
;;
--clear)
CLEAR=YES
shift
;;
--)
RUN=YES
shift
break
;;
-*)
echo "unrecognized option: $1"
echo ""
usage
exit 1
;;
*)
SOURCE="$(realpath $1)"
SOURCES+=("$SOURCE")
shift
;;
esac
done
if [ ! $SOURCES ]; then
usage
exit 1
fi
#-------------------------------------------------------------------------------
if [ $CLEAR ]; then
clear
fi
#-------------------------------------------------------------------------------
bold=$(tput bold)
normal=$(tput sgr0)
function hline {
printf '%*s' "${COLUMNS:-$(tput cols)}" '' | tr ' ' _
}
#-------------------------------------------------------------------------------
function verbose {
if [ $VERBOSE ]; then
echo "$@" | \
sed 's/ -/ \\\n -/g' | \
sed 's/ \// \\\n \//g'
fi
}
#-------------------------------------------------------------------------------
verbose "$CMDLINE"
#-------------------------------------------------------------------------------
APP_MAIN="${SOURCES[0]}"
APP_NAME="$(basename ${APP_MAIN%.*})"
APP_BUILD_ROOT="${APP_BUILD_ROOT:=$(dirname $APP_MAIN)/build}"
APP_SCRIPTS_DIR="$(realpath $(dirname $0))"
APP_TEMPLATES_DIR="$(dirname $APP_SCRIPTS_DIR)/templates"
case $(uname | tr '[:upper:]' '[:lower:]') in
darwin*)
APP_BUILD_OS=macos
APP_BUILD_DIR="$APP_BUILD_ROOT/macos/$APP_NAME.app"
APP_BIN="$APP_BUILD_DIR/Contents/MacOS/$APP_NAME"
;;
linux*)
APP_BUILD_OS=linux
echo "unsupported operating system"
exit 1
;;
msys*|mingw*)
APP_BUILD_OS=windows
APP_BUILD_DIR="$APP_BUILD_ROOT/windows/$APP_NAME"
APP_BIN="$APP_BUILD_DIR/$APP_NAME.exe"
CFLAGS="${CFLAGS} -D_CRT_SECURE_NO_WARNINGS"
CLANG_CFLAGS="${CLANG_CFLAGS} -fuse-ld=lld"
;;
*)
echo "unsupported operating system"
exit 1
;;
esac
#-------------------------------------------------------------------------------
function execute {
verbose "$@"
if [ $TIME ]; then
time --format="${bold}took %Es${normal}\n" "$@" || exit $?
else
"$@" || exit $?
fi
if [ $VERBOSE ]; then
printf "${bold}\e[32m\xE2\x9C\x93 OK\e[39m${normal}\n"
fi
}
#-------------------------------------------------------------------------------
# ensure $APP_BUILD_DIR exists
[ -d "$APP_BUILD_DIR" ] || execute mkdir -p "$APP_BUILD_DIR"
#-------------------------------------------------------------------------------
# copy template content into build dir
APP_TEMPLATE_DIR="$APP_TEMPLATES_DIR/$APP_BUILD_OS/."
[ -d "$APP_TEMPLATE_DIR" ] && execute cp -rf "$APP_TEMPLATE_DIR" "$APP_BUILD_DIR/"
#-------------------------------------------------------------------------------
# CC="${CC:=$(command -v cc || command -v gcc || command -v clang)}"
CC="${CC:=$(command -v clang)}"
# echo CC:"$CC"
case $CC in
*clang*)
CFLAGS="$CFLAGS $CLANG_CFLAGS"
;;
esac
case $($CC --version | tr '[:upper:]' '[:lower:]') in
*msys*)
CFLAGS="$CFLAGS -Wl,--subsystem,windows"
;;
esac
#-------------------------------------------------------------------------------
for SOURCE in "${SOURCES[@]}"; do
CFLAGS="$CFLAGS $SOURCE"
done
execute "$CC" $CFLAGS -o"$APP_BIN"
# hline
#-------------------------------------------------------------------------------
if [ $RUN ]; then
echo $''
execute "$APP_BIN" "$@"
# echo "$APP_BIN" returned "$?"
fi
#-------------------------------------------------------------------------------
if [ $CLEAN ]; then
execute rm -rf "$APP_BUILD_ROOT"
fi
#-------------------------------------------------------------------------------
exit
#-------------------------------------------------------------------------------
@garettbass
Copy link
Author

hello.cpp

///usr/bin/env sh scripts/build.sh \
    -Iinclude \
    -fno-rtti \
    -std=c++2a $0 "$@" \
    ;exit $?

#include <stdio.h>

int main() {
    puts("hello world");
    return 0;
}

terminal

> sh hello.cpp --

hello world

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment