- Reorganized the code a bit and split each of sigtool's commands into a separate file. - Added extra tests to validate verify's new capabilities - Updated README
432 lines
9.4 KiB
Bash
Executable file
432 lines
9.4 KiB
Bash
Executable file
#! /usr/bin/env bash
|
|
|
|
# Tool to build go programs in this repo
|
|
#
|
|
# - it tacks on a version number for use by the individual tools
|
|
# - it supports git and mercurial version#
|
|
#
|
|
# NB:
|
|
# o the attempt at decoding dirty repo state for mercurial is
|
|
# borked. It doesn't know about untracked files
|
|
#
|
|
# (c) 2016 Sudhi Herle
|
|
#
|
|
# License: GPLv2
|
|
#
|
|
Progs="src:sigtool"
|
|
|
|
# Relative path to protobuf sources
|
|
# e.g. src/foo/a.proto
|
|
Protobufs="internal/pb/hdr.proto"
|
|
|
|
|
|
# -- DO NOT CHANGE ANYTHING AFTER THIS --
|
|
|
|
Z=`basename $0`
|
|
PWD=`pwd`
|
|
|
|
Static=0
|
|
Dryrun=0
|
|
Prodver=""
|
|
Verbose=0
|
|
Go=`which go`
|
|
|
|
die() {
|
|
echo "$Z: $@" 1>&2
|
|
exit 0
|
|
}
|
|
|
|
warn() {
|
|
echo "$Z: $@" 1>&2
|
|
}
|
|
|
|
case $BASH_VERSION in
|
|
4.*|5.*) ;;
|
|
|
|
*) die "I need bash 4.x to run!"
|
|
;;
|
|
esac
|
|
|
|
|
|
|
|
|
|
usage() {
|
|
|
|
cat <<EOF
|
|
$0 - A Go production build tool that adds git-repository information,
|
|
product version, build-timestamp etc. It supports cross-compilation,
|
|
static linking and generating protobuf output.
|
|
|
|
If needed, it uses the gogo-slick protobuf compiler [github.com/gogo/protobuf].
|
|
|
|
Build output is in bin/\$OS-\$CPU for a given OS, CPU combination.
|
|
|
|
Usage: $0
|
|
$0 [options] [PROGS]
|
|
|
|
Where OS-ARCH denotes one of the valid OS, ARCH combinations supported by 'go'.
|
|
And, PROGS is one or more go programs.
|
|
|
|
With no arguments, $0 builds: $Progs (source in ./src/)
|
|
|
|
The repository's latest tag is used as the default version of the software being
|
|
built.
|
|
|
|
Options:
|
|
-h, --help Show this help message and quit
|
|
-s, --static Build a statically linked binary [False]
|
|
-V N, --version=N Use 'N' as the product version string [$Prodver]
|
|
-a X, --arch=X Cross compile for OS-CPU 'X' [$hostos-$hostcpu]
|
|
-n, --dry-run Dry-run, don't actually build anything [False]
|
|
-t, --test Run "go test" on modules named on the command line [False]
|
|
-v, --verbose Build verbosely (adds "-v" to go tooling) [False]
|
|
--vet Run "go vet" on modules named on the command line [False]
|
|
--mod Run "go mod ..." [False]
|
|
--go=G Use Go in 'G' [$Go]
|
|
-x Run in debug/trace mode [False]
|
|
--print-arch Print the target architecture and exit
|
|
EOF
|
|
|
|
exit 0
|
|
}
|
|
|
|
host=`uname|tr '[A-Z]' '[a-z]'`
|
|
|
|
declare -A oses
|
|
declare -A cpus
|
|
declare -A cgo
|
|
|
|
# Supported & Verified OS/CPU combos for this script
|
|
oslist="linux android openbsd freebsd darwin dragonfly netbsd windows"
|
|
needcgo="android"
|
|
cpulist="i386 amd64 arm arm64"
|
|
cpualias_i386="i486 i586 i686"
|
|
cpualias_amd64="x86_64"
|
|
cpualias_arm64="aarch64"
|
|
|
|
# CGO Cross-Compilers for various CPU+OS combinations of Android
|
|
android_i386=i686-linux-android-gcc
|
|
android_arm64=aarch64-linux-android-gcc
|
|
android_arm=arm-linux-androideabi-gcc
|
|
|
|
# initialize the various hash tables
|
|
for o in $oslist; do oses[$o]=$o; done
|
|
for o in $needcgo; do cgo[$o]=$o; done
|
|
for c in $cpulist; do
|
|
cpus[$c]=$c
|
|
a="cpualias_$c"
|
|
a=${!a}
|
|
for x in $a; do cpus[$x]=$c; done
|
|
done
|
|
|
|
|
|
Tool=
|
|
doinit=0
|
|
args=
|
|
Printarch=0
|
|
|
|
#set -x
|
|
ac_prev=
|
|
for ac_option
|
|
do
|
|
shift
|
|
|
|
if [ -n "$ac_prev" ]; then
|
|
eval "$ac_prev=\$ac_option"
|
|
ac_prev=
|
|
continue
|
|
fi
|
|
|
|
case "$ac_option" in
|
|
-*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
|
|
*) ac_optarg= ;;
|
|
esac
|
|
|
|
|
|
case "$ac_option" in
|
|
--help|-h|--hel|--he|--h)
|
|
usage;
|
|
;;
|
|
|
|
--arch=*)
|
|
Arch=$ac_optarg
|
|
;;
|
|
|
|
-a|--arch)
|
|
ac_prev=Arch
|
|
;;
|
|
|
|
--version=*)
|
|
Prodver=$ac_optarg
|
|
;;
|
|
|
|
--test|-t)
|
|
Tool=test
|
|
;;
|
|
|
|
--vet)
|
|
Tool=vet
|
|
;;
|
|
|
|
--mod)
|
|
Tool=mod
|
|
;;
|
|
|
|
-V|--version)
|
|
ac_prev=Prodver
|
|
;;
|
|
|
|
-v|--verbose)
|
|
Verbose=1
|
|
;;
|
|
|
|
-s|--static)
|
|
Static=1
|
|
;;
|
|
|
|
--dry-run|-n)
|
|
Dryrun=1
|
|
;;
|
|
|
|
--debug|-x)
|
|
set -x
|
|
;;
|
|
|
|
--go-root=*)
|
|
GoRoot=$ac_optarg
|
|
;;
|
|
|
|
--print-arch)
|
|
Printarch=1
|
|
;;
|
|
|
|
*) # first non option terminates option processing.
|
|
# we gather all remaining args and bundle them up.
|
|
args="$args $ac_option"
|
|
for xx
|
|
do
|
|
args="$args $xx"
|
|
done
|
|
break
|
|
;;
|
|
esac
|
|
done
|
|
|
|
[ $Dryrun -gt 0 ] && e=echo
|
|
|
|
# let every error abort
|
|
set -e
|
|
|
|
# build a tool that runs on the host - if needed.
|
|
hosttool() {
|
|
local tool=$1
|
|
local bindir=$2
|
|
local src=$3
|
|
|
|
p=$bindir/$tool
|
|
if [ -x $p ]; then
|
|
return 0
|
|
fi
|
|
|
|
local tmpdir=/tmp/$tool.$$
|
|
mkdir $tmpdir || die "can't make $tmpdir"
|
|
|
|
# since go1.20 - install uses env vars to decide where to put
|
|
# build artifacts. Why are all the google tooling so bloody dev
|
|
# hostile! WTF is wrong with command line args?!
|
|
export GOBIN=$bindir
|
|
|
|
# build it and stash it in the hostdir
|
|
echo "Building tool $tool from $src .."
|
|
(
|
|
cd $tmpdir
|
|
$e $Go install $src@latest || die "can't install $tool"
|
|
)
|
|
$e rm -rf $tmpdir
|
|
|
|
return 0
|
|
}
|
|
|
|
# protobuf gen
|
|
buildproto() {
|
|
local pbgo=protoc-gen-go
|
|
local vtgo=protoc-gen-go-vtproto
|
|
local vtgo_src=github.com/planetscale/vtprotobuf/cmd/protoc-gen-go-vtproto
|
|
local pc
|
|
local args="$*"
|
|
|
|
local pgen=$(type -p protoc)
|
|
local gogen=$(type -p $pbgo)
|
|
local vt=$Hostbindir/$vtgo
|
|
|
|
[ -z $pgen ] && die "install protoc tools"
|
|
[ -z $gogen ] && die "install protoc-gen-go"
|
|
|
|
# now install the vtproto generator
|
|
hosttool $vtgo $Hostbindir $vtgo_src
|
|
|
|
for f in $args; do
|
|
local dn=$(dirname $f)
|
|
local bn=$(basename $f .proto)
|
|
|
|
|
|
$e $pgen \
|
|
--go_out=. --plugin protoc-gen-go=$gogen \
|
|
--go-vtproto_out=. --plugin protoc-gen-go-vtproto="$vt" \
|
|
--go-vtproto_opt=features=marshal+unmarshal+size \
|
|
$f || die "can't generate protobuf output for $f .."
|
|
done
|
|
|
|
return 0
|
|
}
|
|
|
|
# the rest has to execute in the context of main shell (not funcs)
|
|
|
|
hostos=$($Go env GOHOSTOS) || exit 1
|
|
hostcpu=$($Go env GOHOSTARCH) || exit 1
|
|
|
|
# This fragment can't be in a function - since it exports several vars
|
|
if [ -n "$Arch" ]; then
|
|
ox=${Arch%%-*}
|
|
cx=${Arch##*-}
|
|
[ "$ox" = "$cx" ] && cx=$hostcpu
|
|
|
|
os=${oses[$ox]}
|
|
cpu=${cpus[$cx]}
|
|
[ -z "$os" ] && die "Don't know anything about OS $ox"
|
|
[ -z "$cpu" ] && die "Don't know anything about CPU $cx"
|
|
|
|
export GOOS=$os GOARCH=$cpu
|
|
cross=$os-$cpu
|
|
|
|
else
|
|
os=$hostos
|
|
cpu=$hostcpu
|
|
cross=$os-$cpu
|
|
fi
|
|
|
|
# If we don't need CGO, then we can attempt a static link
|
|
if [ -n "${cgo[$os]}" ]; then
|
|
export CGO_ENABLED=1
|
|
|
|
# See if we have a specific cross-compiler for this CPU+OS combo
|
|
xcc="${GOOS}_${GOARCH}"
|
|
xcc=${!xcc}
|
|
if [ -n "$xcc" ]; then
|
|
p=`type -p $xcc`
|
|
[ -n "$p" ] || die "Can't find $xcc! Do you have compilers for $GOARCH available in PATH?"
|
|
export CC=$xcc
|
|
else
|
|
echo "$Z: No Cross compiler defined for $GOOS-$GOARCH. Build may fail.." 1>&2
|
|
fi
|
|
else
|
|
if [ $Static -gt 0 ]; then
|
|
export CGO_ENABLED=0
|
|
|
|
isuffix="--installsuffix cgo"
|
|
ldflags="-s"
|
|
msg="statically linked"
|
|
fi
|
|
fi
|
|
|
|
if [ $Printarch -gt 0 ]; then
|
|
echo "$hostos-$hostcpu"
|
|
exit 0
|
|
fi
|
|
|
|
|
|
# This is where build outputs go
|
|
Bindir=$PWD/bin/$cross
|
|
Hostbindir=$PWD/bin/$hostos-$hostcpu
|
|
export PATH=$Hostbindir:$PATH
|
|
|
|
[ -d $Bindir ] || mkdir -p $Bindir
|
|
[ -d $Hostbindir ] || mkdir -p $Hostbindir
|
|
|
|
# Get git/hg version info for the build
|
|
if [ -d "./.hg" ]; then
|
|
xrev=$(hg id --id) || exit 1
|
|
brev=${xrev%+}
|
|
if [ "$brev" != "$xrev" ]; then
|
|
rev="hg:${brev}-dirty"
|
|
else
|
|
rev="hg:${brev}"
|
|
fi
|
|
if [ -z "$Prodver" ]; then
|
|
Prodver=$(hg log -r "branch(stable) and tag()" -T "{tags}\n" | tail -1)
|
|
fi
|
|
elif [ -d "./.git" ]; then
|
|
xrev=$(git describe --always --dirty --long --abbrev=12) || exit 1
|
|
rev="git:$xrev"
|
|
if [ -z "$Prodver" ]; then
|
|
Prodver=$(git tag --list | tail -1)
|
|
fi
|
|
else
|
|
rev="UNKNOWN-VER"
|
|
echo "$0: Can't find version info" 1>&2
|
|
fi
|
|
|
|
|
|
# Do Protobufs if needed
|
|
if [ -n "$Protobufs" ]; then
|
|
set +e
|
|
buildproto $Protobufs
|
|
set -e
|
|
fi
|
|
|
|
repover="main.RepoVersion=$rev"
|
|
prodver="main.ProductVersion=$Prodver"
|
|
date="main.Buildtime=`date -u '+%Y-%m-%dT%H:%M.%SZ'`"
|
|
ldflags="-ldflags \"-X $repover -X $prodver -X $date $ldflags\""
|
|
vflag=""
|
|
|
|
[ $Verbose -gt 0 ] && vflag="-v"
|
|
|
|
case $Tool in
|
|
test)
|
|
set -- $args
|
|
$e $Go test $vflag "$@"
|
|
;;
|
|
|
|
vet)
|
|
set -- $args
|
|
$e $Go vet $vflag "$@"
|
|
;;
|
|
|
|
mod)
|
|
set -- $args
|
|
$e $Go mod $vflag "$@"
|
|
;;
|
|
|
|
*) # Default is to build programs
|
|
set -- $args
|
|
if [ -z "$1" ]; then
|
|
all=$Progs
|
|
else
|
|
all="$@"
|
|
fi
|
|
|
|
echo "Building $Prodver ($rev), $cross $msg .."
|
|
|
|
for p in $all; do
|
|
if echo $p | grep -q ':' ; then
|
|
out=${p##*:}
|
|
dir=${p%%:*}
|
|
else
|
|
out=$p
|
|
dir=$p
|
|
fi
|
|
|
|
# Add .exe suffix to out if needed
|
|
if [ "$GOOS" = "windows" ]; then
|
|
base=${out%%.exe}
|
|
out="${base}.exe"
|
|
fi
|
|
|
|
echo " $dir: $out .. "
|
|
$e eval $Go build $vflag -o $Bindir/$out $isuffix "$ldflags" ./$dir || exit 1
|
|
done
|
|
;;
|
|
esac
|
|
|
|
# vim: ft=sh:expandtab:ts=4:sw=4:tw=84:
|