Skip to content

Instantly share code, notes, and snippets.

@lcrilly
Last active February 7, 2024 19:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lcrilly/670642988f417e091a31a021c6c9977c to your computer and use it in GitHub Desktop.
Save lcrilly/670642988f417e091a31a021c6c9977c to your computer and use it in GitHub Desktop.
build_unit.sh - builds NGINX Unit from source based on installed version
#!/bin/bash
NJS_VER=""
RBT=0
UNIT_VER=""
SUFFIX=()
PATCH_FILES=()
CONFIGURE_OPTIONS=""
STARTDIR=$PWD
WORKDIR=/tmp/build_unit.$$
UNITD_FILENAME=""
while [ $# -gt 0 ]; do
case $1 in
"-h" | "--help")
echo "${0##*/} - builds NGINX Unit from source"
echo ""
echo "USAGE: ${0##*/} [OPTIONS] [patch …]"
echo ""
echo "Options:"
echo " -d | --debug # Build with debugging symbols and logging"
echo " -j | --njs <version|off> # JavaScript support (default: latest) "
echo " -o | --output <filename> # Produces a unitd binary with the specified filename"
echo " -v | --version <version|latest> # Override version (default: already-installed version)"
echo ""
echo " Patches are applied in command-line order from these locations:"
echo " - filename"
echo " - URL to GitHub PR URL (requires curl)"
echo " - URL to plaintext diff/patch (requires curl)"
echo " - Review Board patch number (requires rbt)"
echo ""
exit 0
;;
"-d" | "--debug")
CONFIGURE_OPTIONS="--debug"
shift
;;
"-j" | "--njs")
NJS_VER=$2
shift; shift
;;
"-o" | "--output")
UNITD_FILENAME=$2
shift; shift
;;
"-v" | "--version")
UNIT_VER=$2
shift; shift
;;
*)
if [ -f $1 ] && [ -r $1 ]; then
FILENAME=${1##*/}
echo "${0##*/}: INFO: Using patch file $FILENAME"
mkdir -p $WORKDIR/patches
cp $1 $WORKDIR/patches/${FILENAME%.*}
PATCHES+=(${FILENAME%.*})
elif [ -n "$1" ] && [ "$1" -eq "$1" ] 2> /dev/null; then
echo "${0##*/}: INFO: Using Review Board patch $1"
RBT=1
MISSING=$(hash hg rbt 2>&1 | cut -f4 -d: | tr -d '\n')
if [ $? -ne 0 ]; then
echo "${0##*/}: ERROR: You must install and configure$MISSING to apply this patch"
exit 3
fi
PATCHES+=($1)
elif [ "${1:0:35}" = "https://github.com/nginx/unit/pull/" ]; then
echo "${0##*/}: INFO: Using GitHub PR ${1##*/}"
hash curl 2> /dev/null
if [ $? -ne 0 ]; then
echo "${0##*/}: ERROR: curl(1) is required to obtain patches from GitHub"
exit 3
fi
PATCHES+=($1.diff)
elif [ "${1:0:4}" = "http" ]; then
echo "${0##*/}: INFO: Using remote patch $1"
hash curl 2> /dev/null
if [ $? -ne 0 ]; then
echo "${0##*/}: ERROR: curl(1) is required to obtain remote patches"
exit 3
fi
PATCHES+=($1)
else
echo "${0##*/}: ERROR: Unrecognized option, $1"
exit 2
fi
shift
;;
esac
done
if [ "$UNIT_VER" = "" ]; then
hash unitd 2> /dev/null
if [ $? -eq 0 ]; then
UNIT_VER=$(unitd --version 2>&1 | head -1 | cut -f3 -d' ')
else
echo "${0##*/}: WARNING: Unit not installed and no version specified, using the head/tip"
fi
fi
# Prefer Mercurial but fallback to Git
#
hash hg 2> /dev/null
if [ $? -eq 0 ]; then
CLONE_PREFIX="hg clone http://hg.nginx.org"
CLONE_BRANCH="-u"
else
CLONE_PREFIX="git clone https://github.com/nginx"
CLONE_BRANCH="--branch"
fi
# Obtain and patch Unit
#
echo "${0##*/}: INFO: Cloning Unit $UNIT_VER"
SUFFIX=$UNIT_VER
if [ "$UNIT_VER" = "latest" ]; then
UNIT_VER=""
fi
mkdir -p $WORKDIR
cd $WORKDIR
if [ "$UNIT_VER" = "" ]; then
$CLONE_PREFIX/unit > /dev/null
else
$CLONE_PREFIX/unit $CLONE_BRANCH $UNIT_VER > /dev/null
fi
cd unit
if [ ${#PATCHES[@]} -eq 0 ]; then
echo "${0##*/}: INFO: No patches"
else
echo "${0##*/}: INFO: Patching Unit"
if [ $RBT -eq 1 ]; then
hg qnew ${0##*/}
fi
for PATCH in "${PATCHES[@]}"; do
if [ -f ../patches/$PATCH ]; then
SUFFIX="${SUFFIX}+${PATCH##*/}"
patch -p1 < ../patches/$PATCH > $WORKDIR/patch.out
elif [ -n "$PATCH" ] && [ "$PATCH" -eq "$PATCH" ] 2> /dev/null; then
SUFFIX="${SUFFIX}+$PATCH"
hg qref
rbt patch $PATCH > $WORKDIR/patch.out
else
SUFFIX="${SUFFIX}+$(echo ${PATCH##*/} | cut -f1 -d. | cut -f2 -d= | tr -d '?&_+%=')"
curl -fsL $PATCH | patch -p1 > $WORKDIR/patch.out
fi
if [ $? -ne 0 ]; then
if [ $(grep -c 'changes.xml' $WORKDIR/patch.out) -gt 0 ]; then
echo "${0##*/}: WARNING: Could not patch changes.xml, continuing"
else
echo "${0##*/}: ERROR: Patch failed"
cat $WORKDIR/patch.out
exit 1
fi
fi
cat $WORKDIR/patch.out
done
fi
# Build njs (as late as possible, to avoid wasting time if the patch failed)
#
if [ "$NJS_VER" != "off" ]; then
echo "${0##*/}: INFO: Cloning NGINX JavaScript $NJS_VER"
if [ "$NJS_VER" = "" ]; then
$CLONE_PREFIX/njs > /dev/null
else
$CLONE_PREFIX/njs $CLONE_BRANCH $NJS_VER > /dev/null
fi
cd njs
echo "${0##*/}: INFO: Configuring NGINX JavaScript"
./configure --no-libxml2 --no-zlib 2>&1 > configure.out
if [ $? -gt 0 ]; then
echo "${0##*/}: ERROR: Failed to configure njs"
cat configure.out
exit 1
fi
echo "${0##*/}: INFO: Compiling NGINX JavaScript"
make 2>&1 > make.out
if [ $? -gt 0 ]; then
echo "${0##*/}: ERROR: Failed to build njs"
tail make.out
exit 1
fi
cd ..
fi
# Build Unit (keeping only the include paths from installed version)
#
echo "${0##*/}: INFO: Configuring Unit"
#if [ "$UNIT_VER" != "" ]; then
CC_OPT=$(unitd --version 2>&1 | grep ^configured | sed -e 's/ \-\-/\n--/g' | grep ^--cc-opt | cut -f2- -d= | tr " '" "\n" | grep ^-I)
LD_OPT=$(unitd --version 2>&1 | grep ^configured | sed -e 's/ \-\-/\n--/g' | grep ^--ld-opt | cut -f2- -d= | tr " '" "\n" | grep ^-L)
#fi
if [ "$NJS_VER" != "off" ]; then
CONFIGURE_OPTIONS="$CONFIGURE_OPTIONS --njs"
CC_OPT="$CC_OPT -Injs/src -Injs/build"
LD_OPT="$LD_OPT -Lnjs/build"
fi
cd $WORKDIR/unit
CPPFLAGS=$CC_OPT ./configure $CONFIGURE_OPTIONS \
$(unitd --version 2>&1 | grep ^configured | sed -e 's/ \-\-/\n--/g' | grep ^-- | grep -ve ^--njs -e ^--..-opt=) \
--cc-opt="$CC_OPT" --ld-opt="$LD_OPT" 2>&1 > configure.out
if [ $? -ne 0 ]; then
echo "${0##*/}: ERROR: Failed to configure Unit"
cat configure.out
exit 1
fi
echo "${0##*/}: INFO: Compiling Unit"
make 2>&1 > make.out
if [ $? -ne 0 ]; then
echo "${0##*/}: ERROR: Failed to build Unit"
tail make.out
exit 1
fi
echo "${0##*/}: INFO: Done"
if [ "$UNITD_FILENAME" = "" ]; then
UNITD_FILENAME=$STARTDIR/unitd-$SUFFIX
fi
if [ -f build/unitd ]; then
cp build/unitd $UNITD_FILENAME
else
cp build/sbin/unitd $UNITD_FILENAME
fi
cd .. && rm -fr $WORKDIR
ls -l $UNITD_FILENAME
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment