179 lines
4.0 KiB
Bash
179 lines
4.0 KiB
Bash
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
GO_MOD_FILE="${ROOT_DIR}/go.mod"
|
|
DEFAULT_GO_VERSION="$(awk '/^go / { print $2; exit }' "${GO_MOD_FILE}")"
|
|
|
|
GO_VERSION="${DEFAULT_GO_VERSION}"
|
|
OUTPUT_PATH="${ROOT_DIR}/api"
|
|
TOOLS_DIR="${ROOT_DIR}/.build-tools"
|
|
CACHE_DIR="${ROOT_DIR}/.build-cache"
|
|
CLEAN_GO="false"
|
|
|
|
usage() {
|
|
cat <<EOF
|
|
Usage: scripts/build_install.sh [options]
|
|
|
|
Options:
|
|
--go-version <version> Go version to download, default: ${GO_VERSION}
|
|
--output <path> Build output path, default: ${OUTPUT_PATH}
|
|
--tools-dir <dir> Toolchain directory, default: ${TOOLS_DIR}
|
|
--cache-dir <dir> Go cache directory, default: ${CACHE_DIR}
|
|
--clean-go Re-download the Go toolchain even if it exists
|
|
-h, --help Show this help
|
|
|
|
Examples:
|
|
bash scripts/build_install.sh
|
|
bash scripts/build_install.sh --output ./package/api
|
|
EOF
|
|
}
|
|
|
|
parse_args() {
|
|
while [[ $# -gt 0 ]]; do
|
|
case "$1" in
|
|
--go-version)
|
|
GO_VERSION="$2"
|
|
shift 2
|
|
;;
|
|
--output)
|
|
OUTPUT_PATH="$2"
|
|
shift 2
|
|
;;
|
|
--tools-dir)
|
|
TOOLS_DIR="$2"
|
|
shift 2
|
|
;;
|
|
--cache-dir)
|
|
CACHE_DIR="$2"
|
|
shift 2
|
|
;;
|
|
--clean-go)
|
|
CLEAN_GO="true"
|
|
shift
|
|
;;
|
|
-h|--help)
|
|
usage
|
|
exit 0
|
|
;;
|
|
*)
|
|
echo "error: unknown option: $1" >&2
|
|
usage
|
|
exit 1
|
|
;;
|
|
esac
|
|
done
|
|
}
|
|
|
|
require_cmd() {
|
|
if ! command -v "$1" >/dev/null 2>&1; then
|
|
echo "error: required command not found: $1" >&2
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
detect_platform() {
|
|
local uname_os uname_arch
|
|
uname_os="$(uname -s)"
|
|
uname_arch="$(uname -m)"
|
|
|
|
case "${uname_os}" in
|
|
Linux) GO_OS="linux" ;;
|
|
Darwin) GO_OS="darwin" ;;
|
|
*)
|
|
echo "error: unsupported operating system: ${uname_os}" >&2
|
|
exit 1
|
|
;;
|
|
esac
|
|
|
|
case "${uname_arch}" in
|
|
x86_64|amd64) GO_ARCH="amd64" ;;
|
|
aarch64|arm64) GO_ARCH="arm64" ;;
|
|
*)
|
|
echo "error: unsupported architecture: ${uname_arch}" >&2
|
|
exit 1
|
|
;;
|
|
esac
|
|
}
|
|
|
|
download_go() {
|
|
local archive_name archive_path download_url current_version
|
|
|
|
mkdir -p "${TOOLS_DIR}"
|
|
archive_name="go${GO_VERSION}.${GO_OS}-${GO_ARCH}.tar.gz"
|
|
archive_path="${TOOLS_DIR}/${archive_name}"
|
|
GO_ROOT="${TOOLS_DIR}/go"
|
|
|
|
if [[ -x "${GO_ROOT}/bin/go" ]]; then
|
|
current_version="$("${GO_ROOT}/bin/go" version | awk '{print $3}' | sed 's/^go//')"
|
|
if [[ "${current_version}" != "${GO_VERSION}" ]]; then
|
|
rm -rf "${GO_ROOT}"
|
|
fi
|
|
fi
|
|
|
|
if [[ "${CLEAN_GO}" == "true" ]]; then
|
|
rm -rf "${GO_ROOT}"
|
|
rm -f "${archive_path}"
|
|
fi
|
|
|
|
if [[ ! -x "${GO_ROOT}/bin/go" ]]; then
|
|
download_url="https://go.dev/dl/${archive_name}"
|
|
echo "downloading Go ${GO_VERSION} for ${GO_OS}/${GO_ARCH}..."
|
|
if [[ ! -f "${archive_path}" ]]; then
|
|
if command -v curl >/dev/null 2>&1; then
|
|
curl -fsSL "${download_url}" -o "${archive_path}"
|
|
elif command -v wget >/dev/null 2>&1; then
|
|
wget -O "${archive_path}" "${download_url}"
|
|
else
|
|
echo "error: curl or wget is required to download Go" >&2
|
|
exit 1
|
|
fi
|
|
fi
|
|
|
|
rm -rf "${GO_ROOT}"
|
|
tar -C "${TOOLS_DIR}" -xzf "${archive_path}"
|
|
fi
|
|
}
|
|
|
|
build_binary() {
|
|
local output_dir
|
|
|
|
mkdir -p "${CACHE_DIR}/gocache" "${CACHE_DIR}/gomodcache"
|
|
output_dir="$(dirname "${OUTPUT_PATH}")"
|
|
mkdir -p "${output_dir}"
|
|
|
|
echo "building ${OUTPUT_PATH}..."
|
|
(
|
|
cd "${ROOT_DIR}"
|
|
export GOROOT="${GO_ROOT}"
|
|
export PATH="${GO_ROOT}/bin:${PATH}"
|
|
export GOCACHE="${CACHE_DIR}/gocache"
|
|
export GOMODCACHE="${CACHE_DIR}/gomodcache"
|
|
"${GO_ROOT}/bin/go" build -trimpath -o "${OUTPUT_PATH}" ./cmd/api
|
|
)
|
|
chmod +x "${OUTPUT_PATH}" || true
|
|
}
|
|
|
|
print_summary() {
|
|
cat <<EOF
|
|
|
|
Build complete.
|
|
|
|
Go version: ${GO_VERSION}
|
|
Toolchain: ${GO_ROOT}
|
|
Output: ${OUTPUT_PATH}
|
|
Cache dir: ${CACHE_DIR}
|
|
EOF
|
|
}
|
|
|
|
main() {
|
|
parse_args "$@"
|
|
require_cmd tar
|
|
detect_platform
|
|
download_go
|
|
build_binary
|
|
print_summary
|
|
}
|
|
|
|
main "$@"
|