#!/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 < Go version to download, default: ${GO_VERSION} --output Build output path, default: ${OUTPUT_PATH} --tools-dir Toolchain directory, default: ${TOOLS_DIR} --cache-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 <