diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 79075b24..7977d18e 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -13,36 +13,28 @@ concurrency: cancel-in-progress: ${{ github.event_name == 'pull_request' }} jobs: - get_all_targets: + get-targets: name: Get all targets runs-on: ubuntu-latest outputs: - TARGETS: ${{ steps.get_all_targets.outputs.TARGETS }} + targets: ${{ steps.get-targets.outputs.targets }} steps: - name: Checkout uses: actions/checkout@v4 - - name: Get all targets - id: get_all_targets - run: | - declare -a arr=() - OIFS="$IFS" - IFS=$'\n,' - for line in $(BUILD_CONFIG=script/build.config.sh bash script/build.sh --show-all-platforms); do - arr+=("$line") - done - IFS="$OIFS" - printf -v json '"%s",' "${arr[@]}" - json="[${json%,}]" - echo "TARGETS=$json" >> $GITHUB_OUTPUT + - name: Get targets + id: get-targets + uses: zijiren233/go-build-action@v1 + with: + show-all-targets: true - build: + build-targets: name: Build runs-on: ubuntu-latest - needs: get_all_targets + needs: get-targets strategy: matrix: - target: ${{ fromJson(needs.get_all_targets.outputs.TARGETS) }} + target: ${{ fromJson(needs.get-targets.outputs.targets) }} steps: - name: Free Disk Space (Ubuntu) uses: jlumbroso/free-disk-space@main @@ -63,14 +55,12 @@ jobs: with: go-version: "1.23" - - name: Build - run: | - BUILD_CONFIG=script/build.config.sh bash \ - script/build.sh \ - --enable-micro \ - --skip-init-web \ - --platforms="${{ matrix.target }}" \ - --more-go-cmd-args='-a -v' + - name: Build targets + uses: zijiren233/go-build-action@v1 + with: + targets: ${{ matrix.target }} + enable-micro: true + config-args: --skip-init-web - name: Get artifact name id: get_artifact_name diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 268725ea..76409ad8 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -6,36 +6,28 @@ on: - "v*" jobs: - get_all_targets: + get-targets: name: Get all targets runs-on: ubuntu-latest outputs: - TARGETS: ${{ steps.get_all_targets.outputs.TARGETS }} + targets: ${{ steps.get-targets.outputs.targets }} steps: - name: Checkout uses: actions/checkout@v4 - - name: Get all targets - id: get_all_targets - run: | - declare -a arr=() - OIFS="$IFS" - IFS=$'\n,' - for line in $(BUILD_CONFIG=script/build.config.sh bash script/build.sh --show-all-platforms); do - arr+=("$line") - done - IFS="$OIFS" - printf -v json '"%s",' "${arr[@]}" - json="[${json%,}]" - echo "TARGETS=$json" >> $GITHUB_OUTPUT + - name: Get targets + id: get-targets + uses: zijiren233/go-build-action@v1 + with: + show-all-targets: true release: name: Release - needs: get_all_targets + needs: get-targets runs-on: ubuntu-latest strategy: matrix: - target: ${{ fromJson(needs.get_all_targets.outputs.TARGETS) }} + target: ${{ fromJson(needs.get-targets.outputs.targets) }} steps: - name: Free Disk Space (Ubuntu) uses: jlumbroso/free-disk-space@main @@ -60,14 +52,12 @@ jobs: id: get_version run: echo "VERSION=${GITHUB_REF/refs\/tags\/v/}" >> $GITHUB_OUTPUT - - name: Build - run: | - BUILD_CONFIG=script/build.config.sh bash \ - script/build.sh \ - --enable-micro \ - --version="v${{ steps.get_version.outputs.VERSION }}" \ - --platforms="${{ matrix.target }}" \ - --more-go-cmd-args='-a -v' + - name: Build targets + uses: zijiren233/go-build-action@v1 + with: + targets: ${{ matrix.target }} + enable-micro: true + config-args: --version="v${{ steps.get_version.outputs.VERSION }}" - name: Release uses: softprops/action-gh-release@v2 diff --git a/.github/workflows/release_dev.yml b/.github/workflows/release_dev.yml index dce7979c..7f856861 100644 --- a/.github/workflows/release_dev.yml +++ b/.github/workflows/release_dev.yml @@ -4,36 +4,28 @@ on: workflow_dispatch: jobs: - get_all_targets: + get-targets: name: Get all targets runs-on: ubuntu-latest outputs: - TARGETS: ${{ steps.get_all_targets.outputs.TARGETS }} + targets: ${{ steps.get-targets.outputs.targets }} steps: - name: Checkout uses: actions/checkout@v4 - - name: Get all targets - id: get_all_targets - run: | - declare -a arr=() - OIFS="$IFS" - IFS=$'\n,' - for line in $(BUILD_CONFIG=script/build.config.sh bash script/build.sh --show-all-platforms); do - arr+=("$line") - done - IFS="$OIFS" - printf -v json '"%s",' "${arr[@]}" - json="[${json%,}]" - echo "TARGETS=$json" >> $GITHUB_OUTPUT + - name: Get targets + id: get-targets + uses: zijiren233/go-build-action@v1 + with: + show-all-targets: true release_dev: name: Release dev runs-on: ubuntu-latest - needs: get_all_targets + needs: get-targets strategy: matrix: - target: ${{ fromJson(needs.get_all_targets.outputs.TARGETS) }} + target: ${{ fromJson(needs.get-targets.outputs.targets) }} steps: - name: Free Disk Space (Ubuntu) uses: jlumbroso/free-disk-space@main @@ -54,14 +46,11 @@ jobs: with: go-version: "1.23" - - name: Build - run: | - BUILD_CONFIG=script/build.config.sh bash \ - script/build.sh \ - --enable-micro \ - --version=dev \ - --platforms="${{ matrix.target }}" \ - --more-go-cmd-args='-a -v' + - name: Build targets + uses: zijiren233/go-build-action@v1 + with: + targets: ${{ matrix.target }} + enable-micro: true - name: Release uses: softprops/action-gh-release@v2 diff --git a/Dockerfile b/Dockerfile index b5216886..9ecf38cd 100644 --- a/Dockerfile +++ b/Dockerfile @@ -6,19 +6,19 @@ ARG SKIP_INIT_WEB ENV SKIP_INIT_WEB=${SKIP_INIT_WEB} -ENV BUILD_CONFIG=script/build.config.sh - WORKDIR /synctv COPY ./ ./ RUN apk add --no-cache bash curl git g++ -RUN bash script/build.sh --version=${VERSION} \ +RUN curl -sL \ + https://raw.githubusercontent.com/zijiren233/go-build-action/refs/tags/v1/build.sh | \ + bash -s -- \ + --version=${VERSION} \ --bin-name-no-suffix \ - --force-gcc='gcc -static' \ - --force-g++='g++ -static' \ - --more-go-cmd-args='-a -v' + --force-gcc='gcc -static --static' \ + --force-g++='g++ -static --static' FROM alpine:latest diff --git a/script/build.sh b/script/build.sh deleted file mode 100755 index fc2674d4..00000000 --- a/script/build.sh +++ /dev/null @@ -1,1261 +0,0 @@ -#!/bin/bash -set -e - -# Light Color definitions -readonly COLOR_LIGHT_RED='\033[1;31m' -readonly COLOR_LIGHT_GREEN='\033[1;32m' -readonly COLOR_LIGHT_YELLOW='\033[1;33m' -readonly COLOR_LIGHT_BLUE='\033[1;34m' -readonly COLOR_LIGHT_MAGENTA='\033[1;35m' -readonly COLOR_LIGHT_CYAN='\033[1;36m' -readonly COLOR_LIGHT_GRAY='\033[0;37m' -readonly COLOR_DARK_GRAY='\033[1;30m' -readonly COLOR_WHITE='\033[1;37m' -readonly COLOR_LIGHT_ORANGE='\033[1;91m' -readonly COLOR_RESET='\033[0m' - -# Default values -readonly DEFAULT_SOURCE_DIR="$(pwd)" -readonly DEFAULT_RESULT_DIR="${DEFAULT_SOURCE_DIR}/build" -readonly DEFAULT_BUILD_CONFIG="${DEFAULT_SOURCE_DIR}/build.config.sh" -readonly DEFAULT_BUILD_MODE="default" -readonly DEFAULT_CGO_ENABLED="1" -readonly DEFAULT_FORCE_CGO="0" -readonly DEFAULT_CC="gcc" -readonly DEFAULT_CXX="g++" -readonly DEFAULT_CROSS_COMPILER_DIR="$(dirname $(mktemp -u))/cross" -readonly DEFAULT_CGO_FLAGS="-O2 -g0 -pipe" -readonly DEFAULT_CGO_LDFLAGS="-s" -readonly DEFAULT_LDFLAGS="-s -w -linkmode auto" -readonly DEFAULT_EXT_LDFLAGS="" -readonly DEFAULT_CGO_DEPS_VERSION="v0.5.2" -readonly DEFAULT_TTY_WIDTH="40" -readonly DEFAULT_NDK_VERSION="r27" - -# Go environment variables -readonly GOHOSTOS="$(go env GOHOSTOS)" -readonly GOHOSTARCH="$(go env GOHOSTARCH)" -readonly GOHOSTPLATFORM="${GOHOSTOS}/${GOHOSTARCH}" -readonly GOVERSION="$(go env GOVERSION)" # e.g go1.23.1 - -# --- Function Declarations --- - -# Prints help information about build configuration. -function printBuildConfigHelp() { - echo -e "${COLOR_LIGHT_ORANGE}You can customize the build configuration using the following functions (defined in ${DEFAULT_BUILD_CONFIG}):${COLOR_RESET}" - echo -e " ${COLOR_LIGHT_GREEN}initDep${COLOR_RESET} - Initialize dependencies" - echo -e " ${COLOR_LIGHT_GREEN}initDepPlatforms${COLOR_RESET} - Initialize dependency platforms" - echo -e " ${COLOR_LIGHT_GREEN}parseDepArgs${COLOR_RESET} - Parse dependency arguments" - echo -e " ${COLOR_LIGHT_GREEN}printDepEnvHelp${COLOR_RESET} - Print dependency environment variable help" - echo -e " ${COLOR_LIGHT_GREEN}printDepHelp${COLOR_RESET} - Print dependency help information" -} - -# Prints help information about environment variables. -function printEnvHelp() { - echo -e "${COLOR_LIGHT_YELLOW}Environment Variables:${COLOR_RESET}" - echo -e " ${COLOR_LIGHT_CYAN}BIN_NAME${COLOR_RESET} - Set the binary name (default: source directory basename)" - echo -e " ${COLOR_LIGHT_CYAN}BIN_NAME_NO_SUFFIX${COLOR_RESET} - Do not append the architecture suffix to the binary name" - echo -e " ${COLOR_LIGHT_CYAN}BUILD_CONFIG${COLOR_RESET} - Set the build configuration file (default: ${DEFAULT_BUILD_CONFIG})" - echo -e " ${COLOR_LIGHT_CYAN}BUILD_MODE${COLOR_RESET} - Set the build mode (default: ${DEFAULT_BUILD_MODE})" - echo -e " ${COLOR_LIGHT_CYAN}CGO_ENABLED${COLOR_RESET} - Enable or disable CGO (default: ${DEFAULT_CGO_ENABLED})" - echo -e " ${COLOR_LIGHT_CYAN}CGO_FLAGS${COLOR_RESET} - Set CGO flags (default: ${DEFAULT_CGO_FLAGS})" - echo -e " ${COLOR_LIGHT_CYAN}CGO_LDFLAGS${COLOR_RESET} - Set CGO linker flags (default: ${DEFAULT_CGO_LDFLAGS})" - echo -e " ${COLOR_LIGHT_CYAN}CROSS_COMPILER_DIR${COLOR_RESET} - Set the cross compiler directory (default: ${DEFAULT_CROSS_COMPILER_DIR})" - echo -e " ${COLOR_LIGHT_CYAN}ENABLE_MICRO${COLOR_RESET} - Enable building micro variants" - echo -e " ${COLOR_LIGHT_CYAN}FORCE_CC${COLOR_RESET} - Force the use of a specific C compiler" - echo -e " ${COLOR_LIGHT_CYAN}FORCE_CGO${COLOR_RESET} - Force the use of CGO (default: ${DEFAULT_FORCE_CGO})" - echo -e " ${COLOR_LIGHT_CYAN}FORCE_CXX${COLOR_RESET} - Force the use of a specific C++ compiler" - echo -e " ${COLOR_LIGHT_CYAN}GH_PROXY${COLOR_RESET} - Set the GitHub proxy mirror (e.g., https://mirror.ghproxy.com/)" - echo -e " ${COLOR_LIGHT_CYAN}HOST_CC${COLOR_RESET} - Set the host C compiler (default: ${DEFAULT_CC})" - echo -e " ${COLOR_LIGHT_CYAN}HOST_CXX${COLOR_RESET} - Set the host C++ compiler (default: ${DEFAULT_CXX})" - echo -e " ${COLOR_LIGHT_CYAN}NDK_VERSION${COLOR_RESET} - Set the Android NDK version (default: ${DEFAULT_NDK_VERSION})" - echo -e " ${COLOR_LIGHT_CYAN}PLATFORM${COLOR_RESET} - Set the target platform(s) (default: host platform, supports: all, linux, linux/arm*, ...)" - echo -e " ${COLOR_LIGHT_CYAN}RESULT_DIR${COLOR_RESET} - Set the build result directory (default: ${DEFAULT_RESULT_DIR})" - echo -e " ${COLOR_LIGHT_CYAN}SOURCE_DIR${COLOR_RESET} - Set the source directory (default: ${DEFAULT_SOURCE_DIR})" - - if declare -f printDepEnvHelp >/dev/null; then - echo -e "${COLOR_LIGHT_GRAY}$(printSeparator)${COLOR_RESET}" - echo -e "${COLOR_LIGHT_ORANGE}Dependency Environment Variables:${COLOR_RESET}" - printDepEnvHelp - fi -} - -# Prints help information about command-line arguments. -function printHelp() { - echo -e "${COLOR_LIGHT_GREEN}Usage:${COLOR_RESET}" - echo -e " $(basename "$0") [options]" - echo -e "" - echo -e "${COLOR_LIGHT_RED}Options:${COLOR_RESET}" - echo -e " ${COLOR_LIGHT_BLUE}--bin-name=${COLOR_RESET} - Specify the binary name (default: source directory basename)" - echo -e " ${COLOR_LIGHT_BLUE}--bin-name-no-suffix${COLOR_RESET} - Do not append the architecture suffix to the binary name" - echo -e " ${COLOR_LIGHT_BLUE}--build-mode=${COLOR_RESET} - Set the build mode (default: ${DEFAULT_BUILD_MODE})" - echo -e " ${COLOR_LIGHT_BLUE}--cross-compiler-dir=${COLOR_RESET} - Specify the cross compiler directory (default: ${DEFAULT_CROSS_COMPILER_DIR})" - echo -e " ${COLOR_LIGHT_BLUE}--disable-cgo${COLOR_RESET} - Disable CGO support" - echo -e " ${COLOR_LIGHT_BLUE}-eh, --env-help${COLOR_RESET} - Display help information about environment variables" - echo -e " ${COLOR_LIGHT_BLUE}--enable-micro${COLOR_RESET} - Enable building micro architecture variants" - echo -e " ${COLOR_LIGHT_BLUE}--ext-ldflags=''${COLOR_RESET} - Set external linker flags (default: \"${DEFAULT_EXT_LDFLAGS}\")" - echo -e " ${COLOR_LIGHT_BLUE}--force-cgo${COLOR_RESET} - Force the use of CGO" - echo -e " ${COLOR_LIGHT_BLUE}--force-gcc=${COLOR_RESET} - Force the use of a specific C compiler" - echo -e " ${COLOR_LIGHT_BLUE}--force-g++=${COLOR_RESET} - Force the use of a specific C++ compiler" - echo -e " ${COLOR_LIGHT_BLUE}--github-proxy-mirror=${COLOR_RESET} - Use a GitHub proxy mirror (e.g., https://mirror.ghproxy.com/)" - echo -e " ${COLOR_LIGHT_BLUE}-h, --help${COLOR_RESET} - Display this help message" - echo -e " ${COLOR_LIGHT_BLUE}--host-gcc=${COLOR_RESET} - Specify the host C compiler (default: ${DEFAULT_CC})" - echo -e " ${COLOR_LIGHT_BLUE}--host-g++=${COLOR_RESET} - Specify the host C++ compiler (default: ${DEFAULT_CXX})" - echo -e " ${COLOR_LIGHT_BLUE}--ldflags=''${COLOR_RESET} - Set linker flags (default: \"${DEFAULT_LDFLAGS}\")" - echo -e " ${COLOR_LIGHT_BLUE}--more-go-cmd-args=''${COLOR_RESET} - Pass additional arguments to the 'go build' command" - echo -e " ${COLOR_LIGHT_BLUE}--ndk-version=${COLOR_RESET} - Specify the Android NDK version (default: ${DEFAULT_NDK_VERSION})" - echo -e " ${COLOR_LIGHT_BLUE}-p=, --platforms=${COLOR_RESET} - Specify target platform(s) (default: host platform, supports: all, linux, linux/arm*, ...)" - echo -e " ${COLOR_LIGHT_BLUE}--result-dir=${COLOR_RESET} - Specify the build result directory (default: ${DEFAULT_RESULT_DIR})" - echo -e " ${COLOR_LIGHT_BLUE}--show-all-platforms${COLOR_RESET} - Display all supported target platforms" - echo -e " ${COLOR_LIGHT_BLUE}--source-dir=${COLOR_RESET} - Specify the source directory (default: ${DEFAULT_SOURCE_DIR})" - echo -e " ${COLOR_LIGHT_BLUE}--tags=''${COLOR_RESET} - Set build tags" - - if declare -f printDepHelp >/dev/null; then - echo -e "${COLOR_LIGHT_MAGENTA}$(printSeparator)${COLOR_RESET}" - echo -e "${COLOR_LIGHT_MAGENTA}Dependency Options:${COLOR_RESET}" - printDepHelp - fi - - echo -e "${COLOR_DARK_GRAY}$(printSeparator)${COLOR_RESET}" - printBuildConfigHelp -} - -# Sets a variable to a default value if it's not already set. -# Arguments: -# $1: Variable name. -# $2: Default value. -function setDefault() { - local var_name="$1" - local default_value="$2" - [[ -z "${!var_name}" ]] && eval "${var_name}=\"${default_value}\"" || true -} - -# Appends tags to the TAGS variable. -# Arguments: -# $1: Tags to append. -function addTags() { - TAGS="$(echo "$TAGS $@" | sed 's/ //g' | sed 's/"//g' | sed 's/\n//g')" -} - -# Appends linker flags to the LDFLAGS variable. -# Arguments: -# $1: Linker flags to append. -function addLDFLAGS() { - [[ -n "${1}" ]] && LDFLAGS="${LDFLAGS} ${1}" || true -} - -function addExtLDFLAGS() { - [[ -n "${1}" ]] && EXT_LDFLAGS="${EXT_LDFLAGS} ${1}" || true -} - -# Appends build arguments to the BUILD_ARGS variable. -# Arguments: -# $1: Build arguments to append. -function addBuildArgs() { - [[ -n "${1}" ]] && BUILD_ARGS="${BUILD_ARGS} ${1}" || true -} - -# Fixes and validates command-line arguments and sets default values. -function fixArgs() { - setDefault "SOURCE_DIR" "${DEFAULT_SOURCE_DIR}" - source_dir="$(cd "${SOURCE_DIR}" && pwd)" - setDefault "BIN_NAME" "$(basename "${SOURCE_DIR}")" - setDefault "BIN_NAME_NO_SUFFIX" "" - setDefault "RESULT_DIR" "${DEFAULT_RESULT_DIR}" - mkdir -p "${RESULT_DIR}" - RESULT_DIR="$(cd "${RESULT_DIR}" && pwd)" - echo -e "${COLOR_LIGHT_BLUE}Source directory: ${COLOR_LIGHT_GREEN}${source_dir}${COLOR_RESET}" - echo -e "${COLOR_LIGHT_BLUE}Build result directory: ${COLOR_LIGHT_GREEN}${RESULT_DIR}${COLOR_RESET}" - - setDefault "CROSS_COMPILER_DIR" "$DEFAULT_CROSS_COMPILER_DIR" - setDefault "PLATFORMS" "${GOHOSTPLATFORM}" - setDefault "BUILD_MODE" "${DEFAULT_BUILD_MODE}" - setDefault "ENABLE_MICRO" "" - setDefault "FORCE_CGO" "${DEFAULT_FORCE_CGO}" - setDefault "HOST_CC" "${DEFAULT_CC}" - setDefault "HOST_CXX" "${DEFAULT_CXX}" - setDefault "FORCE_CC" "" - setDefault "FORCE_CXX" "" - setDefault "GH_PROXY" "" - setDefault "TAGS" "" - setDefault "LDFLAGS" "${DEFAULT_LDFLAGS}" - setDefault "EXT_LDFLAGS" "${DEFAULT_EXT_LDFLAGS}" - setDefault "BUILD_ARGS" "" - setDefault "CGO_DEPS_VERSION" "${DEFAULT_CGO_DEPS_VERSION}" - setDefault "CGO_FLAGS" "${DEFAULT_CGO_FLAGS}" - setDefault "CGO_LDFLAGS" "${DEFAULT_CGO_LDFLAGS}" - setDefault "NDK_VERSION" "${DEFAULT_NDK_VERSION}" -} - -# Checks if CGO is enabled. -# Returns: -# 0: CGO is enabled. -# 1: CGO is disabled. -function isCGOEnabled() { - [[ "${CGO_ENABLED}" == "1" ]] -} - -# Downloads a file from a URL and extracts it. -# Arguments: -# $1: URL of the file to download. -# $2: Directory to extract the file to. -# $3: Optional. File type (e.g., "tgz", "zip"). If not provided, it's extracted from the URL. -function downloadAndUnzip() { - local url="$1" - local file="$2" - local type="${3:-$(echo "${url}" | sed 's/.*\.//g')}" - - mkdir -p "${file}" || return $? - file="$(cd "${file}" && pwd)" || return $? - if [ "$(ls -A "${file}")" ]; then - rm -rf "${file}"/* || return $? - fi - echo -e "${COLOR_LIGHT_BLUE}Downloading ${COLOR_LIGHT_CYAN}\"${url}\"${COLOR_LIGHT_BLUE} to ${COLOR_LIGHT_CYAN}\"${file}\"${COLOR_RESET}" - - local start_time=$(date +%s) - - case "${type}" in - "tgz" | "gz") - curl -sL "${url}" | tar -xf - -C "${file}" --strip-components 1 -z || return $? - ;; - "bz2") - curl -sL "${url}" | tar -xf - -C "${file}" --strip-components 1 -j || return $? - ;; - "xz") - curl -sL "${url}" | tar -xf - -C "${file}" --strip-components 1 -J || return $? - ;; - "lzma") - curl -sL "${url}" | tar -xf - -C "${file}" --strip-components 1 --lzma || return $? - ;; - "zip") - curl -sL "${url}" -o "${file}/tmp.zip" || return $? - unzip -q -o "${file}/tmp.zip" -d "${file}" || return $? - rm -f "${file}/tmp.zip" || return $? - ;; - *) - echo -e "${COLOR_LIGHT_RED}Unsupported compression type: ${type}${COLOR_RESET}" - return 2 - ;; - esac - - local end_time=$(date +%s) - echo -e "${COLOR_LIGHT_GREEN}Download and extraction successful (took $((end_time - start_time))s)${COLOR_RESET}" -} - -# --- Platform Management --- - -# Removes duplicate platforms from a comma-separated list. -# Arguments: -# $1: Comma-separated list of platforms. -# Returns: -# Comma-separated list of platforms with duplicates removed. -function removeDuplicatePlatforms() { - local all_platforms="$1" - all_platforms="$(echo "${all_platforms}" | tr ',' '\n' | sort | uniq | paste -s -d ',' -)" - all_platforms="${all_platforms#,}" - all_platforms="${all_platforms%,}" - echo "${all_platforms}" -} - -# Adds platforms to the allowed platforms list. -# Arguments: -# $1: Comma-separated list of platforms to add. -function addAllowedPlatforms() { - [[ -z "$ALLOWED_PLATFORMS" ]] && ALLOWED_PLATFORMS="$1" || ALLOWED_PLATFORMS=$(removeDuplicatePlatforms "$ALLOWED_PLATFORMS,$1") -} - -# Removes platforms from the allowed platforms list. -# Arguments: -# $1: Comma-separated list of platforms to remove. -function deleteAllowedPlatforms() { - ALLOWED_PLATFORMS=$(echo "${ALLOWED_PLATFORMS}" | sed "s|${1}$||g" | sed "s|${1},||g") -} - -# Clears the allowed platforms list. -function clearAllowedPlatforms() { - ALLOWED_PLATFORMS="" -} - -# Initializes the platforms based on environment variables and allowed platforms. -# go tool dist list -function initPlatforms() { - setDefault "CGO_ENABLED" "${DEFAULT_CGO_ENABLED}" - - local distList="$(go tool dist list)" - addAllowedPlatforms "$(echo "$distList" | grep windows | grep -v arm)" - addAllowedPlatforms "$(echo "$distList" | grep linux)" - addAllowedPlatforms "$(echo "$distList" | grep android)" - addAllowedPlatforms "$(echo "$distList" | grep darwin)" - addAllowedPlatforms "$(echo "$distList" | grep ios) $(echo "$distList" | grep ios | sed 's/$/-sim/')" - - addAllowedPlatforms "${GOHOSTOS}/${GOHOSTARCH}" - - if declare -f initDepPlatforms >/dev/null; then - initDepPlatforms - fi -} - -# Checks if a platform is allowed. -# Arguments: -# $1: Target platform to check. -# $2: Optional. List of allowed platforms. If not provided, ALLOWED_PLATFORMS is used. -# Returns: -# 0: Platform is allowed. -# 1: Platform is not allowed. -function checkPlatform() { - local target_platform="$1" - - if [[ "${ALLOWED_PLATFORMS}" =~ (^|,)${target_platform}($|,) ]]; then - return 0 - else - return 1 - fi -} - -# Checks if a list of platforms are allowed. -# Arguments: -# $1: Comma-separated list of platforms to check. -# Returns: -# 0: All platforms are allowed. -# 1: At least one platform is not allowed. -# 3: Error checking platforms. -function checkPlatforms() { - for platform in ${1//,/ }; do - case $( - checkPlatform "${platform}" - echo $? - ) in - 0) - continue - ;; - 1) - echo -e "${COLOR_LIGHT_RED}Platform not supported: ${platform}${COLOR_RESET}" - return 1 - ;; - *) - echo -e "${COLOR_LIGHT_RED}Error checking platform: ${platform}${COLOR_RESET}" - return 3 - ;; - esac - done - return 0 -} - -# --- CGO Dependencies --- - -function resetCGO() { - CC="" - CXX="" - MORE_CGO_CFLAGS="" - MORE_CGO_CXXFLAGS="" - MORE_CGO_LDFLAGS="" - - EXTRA_PATH="" -} - -# Initializes CGO dependencies based on the target operating system and architecture. -# Arguments: -# $1: Target operating system (GOOS). -# $2: Target architecture (GOARCH). -# $3: Optional. Micro architecture variant. -# Returns: -# 0: CGO dependencies initialized successfully. -# 1: CGO disabled. -# 2: Error initializing CGO dependencies. -function initCGODeps() { - resetCGO - local goos="$1" - local goarch="$2" - local micro="$3" - - if [[ -n "${FORCE_CC}" ]] && [[ -n "${FORCE_CXX}" ]]; then - CC="${FORCE_CC}" - CXX="${FORCE_CXX}" - return 0 - elif [[ -n "${FORCE_CC}" ]] || [[ -n "${FORCE_CXX}" ]]; then - echo -e "${COLOR_LIGHT_RED}Both FORCE_CC and FORCE_CXX must be set at the same time.${COLOR_RESET}" - return 2 - fi - - initDefaultCGODeps "$@" || return $? - - PATH=${EXTRA_PATH:+$EXTRA_PATH:}$PATH absCCCXX || return $? - - return 0 -} - -function absCCCXX() { - local cc_command cc_options - read -r cc_command cc_options <<<"${CC}" - CC="$(command -v "${cc_command}")" || return 2 - [[ -n "${cc_options}" ]] && CC="${CC} ${cc_options}" - - local cxx_command cxx_options - read -r cxx_command cxx_options <<<"${CXX}" - CXX="$(command -v "${cxx_command}")" || return 2 - [[ -n "${cxx_options}" ]] && CXX="${CXX} ${cxx_options}" - - return 0 -} - -# Initializes CGO dependencies for the host platform. -function initHostCGODeps() { - CC="${HOST_CC}" - CXX="${HOST_CXX}" -} - -# Initializes default CGO dependencies based on the target operating system, architecture, and micro architecture. -# Arguments: -# $1: Target operating system (GOOS). -# $2: Target architecture (GOARCH). -# $3: Optional. Micro architecture variant. -function initDefaultCGODeps() { - local goos="$1" - local goarch="$2" - local micro="$3" - local unamespacer="${GOHOSTOS}-${GOHOSTARCH}" - [[ "${GOHOSTARCH}" == "arm" ]] && unamespacer="${GOHOSTOS}-arm32v7" - - case "${goos}" in - "linux") - case "${GOHOSTOS}" in - "linux" | "darwin") ;; - *) - if [[ "${goos}" == "${GOHOSTOS}" ]] && [[ "${goarch}" == "${GOHOSTARCH}" ]]; then - initHostCGODeps "$@" - return 0 - else - echo -e "${COLOR_LIGHT_YELLOW}CGO is disabled for ${goos}/${goarch}${micro:+"/$micro"}.${COLOR_RESET}" - return 1 - fi - ;; - esac - - case "${GOHOSTARCH}" in - "amd64" | "arm64" | "arm" | "ppc64le" | "riscv64" | "s390x") ;; - *) - if [[ "${goos}" == "${GOHOSTOS}" ]] && [[ "${goarch}" == "${GOHOSTARCH}" ]]; then - initHostCGODeps "$@" - return 0 - else - echo -e "${COLOR_LIGHT_YELLOW}CGO is disabled for ${goos}/${goarch}${micro:+"/$micro"}.${COLOR_RESET}" - return 1 - fi - ;; - esac - - case "${micro}" in - "hardfloat") - micro="hf" - ;; - "softfloat") - micro="sf" - ;; - esac - case "${goarch}" in - "386") - initLinuxCGO "i686" "" || return $? - ;; - "amd64") - initLinuxCGO "x86_64" "" || return $? - ;; - "arm") - if [[ "${micro}" == "5" ]]; then - initLinuxCGO "armv5" "eabi" || return $? - else - initLinuxCGO "armv${micro}" "eabihf" || return $? - fi - ;; - "arm64") - initLinuxCGO "aarch64" "" || return $? - ;; - "mips") - [[ "${micro}" == "hf" ]] && micro="" || micro="sf" - initLinuxCGO "mips" "" "${micro}" || return $? - ;; - "mipsle") - [[ "${micro}" == "hf" ]] && micro="" || micro="sf" - initLinuxCGO "mipsel" "" "${micro}" || return $? - ;; - "mips64") - [[ "${micro}" == "hf" ]] && micro="" || micro="sf" - initLinuxCGO "mips64" "" "${micro}" || return $? - ;; - "mips64le") - [[ "${micro}" == "hf" ]] && micro="" || micro="sf" - initLinuxCGO "mips64el" "" "${micro}" || return $? - ;; - "ppc64") - # initLinuxCGO "powerpc64" "" - echo -e "${COLOR_LIGHT_YELLOW}CGO is disabled for ${goos}/${goarch}${micro:+"/$micro"}.${COLOR_RESET}" - return 1 - ;; - "ppc64le") - initLinuxCGO "powerpc64le" "" || return $? - ;; - "riscv64") - initLinuxCGO "riscv64" "" || return $? - ;; - "s390x") - initLinuxCGO "s390x" "" || return $? - ;; - "loong64") - initLinuxCGO "loongarch64" "" || return $? - ;; - *) - if [[ "${goos}" == "${GOHOSTOS}" ]] && [[ "${goarch}" == "${GOHOSTARCH}" ]]; then - initHostCGODeps "$@" || return $? - else - echo -e "${COLOR_LIGHT_YELLOW}CGO is disabled for ${goos}/${goarch}${micro:+"/$micro"}.${COLOR_RESET}" - return 1 - fi - ;; - esac - ;; - "windows") - case "${GOHOSTOS}" in - "linux" | "darwin") ;; - *) - if [[ "${goos}" == "${GOHOSTOS}" ]] && [[ "${goarch}" == "${GOHOSTARCH}" ]]; then - initHostCGODeps "$@" || return $? - return 0 - else - echo -e "${COLOR_LIGHT_YELLOW}CGO is disabled for ${goos}/${goarch}${micro:+"/$micro"}.${COLOR_RESET}" - return 1 - fi - ;; - esac - - case "${GOHOSTARCH}" in - "amd64" | "arm64" | "arm" | "ppc64le" | "riscv64" | "s390x") ;; - *) - if [[ "${goos}" == "${GOHOSTOS}" ]] && [[ "${goarch}" == "${GOHOSTARCH}" ]]; then - initHostCGODeps "$@" || return $? - return 0 - else - echo -e "${COLOR_LIGHT_YELLOW}CGO is disabled for ${goos}/${goarch}${micro:+"/$micro"}.${COLOR_RESET}" - return 1 - fi - ;; - esac - - case "${goarch}" in - "386") - initWindowsCGO "i686" || return $? - ;; - "amd64") - initWindowsCGO "x86_64" || return $? - ;; - *) - if [[ "${goos}" == "${GOHOSTOS}" ]] && [[ "${goarch}" == "${GOHOSTARCH}" ]]; then - initHostCGODeps "$@" || return $? - else - echo -e "${COLOR_LIGHT_YELLOW}CGO is disabled for ${goos}/${goarch}${micro:+"/$micro"}.${COLOR_RESET}" - return 1 - fi - ;; - esac - ;; - "android") - case "${GOHOSTOS}" in - "windows" | "linux") - [[ "${GOHOSTARCH}" != "amd64" ]] && echo -e "${COLOR_LIGHT_RED}CGO is disabled for android/${goarch}${micro:+"/$micro"}.${COLOR_RESET}" && return 1 - ;; - "darwin") ;; - *) - echo -e "${COLOR_LIGHT_RED}CGO is disabled for android/${goarch}${micro:+"/$micro"}.${COLOR_RESET}" && return 1 - ;; - esac - initAndroidNDK "${goarch}" "${micro}" || return $? - ;; - "darwin") - initOsxCGO "${goarch}" "${micro}" || return $? - ;; - "ios") - initIosCGO "${goarch}" "${micro}" || return $? - ;; - *) - if [[ "${goos}" == "${GOHOSTOS}" ]] && [[ "${goarch}" == "${GOHOSTARCH}" ]]; then - initHostCGODeps "$@" || return $? - else - echo -e "${COLOR_LIGHT_YELLOW}CGO is disabled for ${goos}/${goarch}${micro:+"/$micro"}.${COLOR_RESET}" - return 1 - fi - ;; - esac -} - -function initIosCGO() { - local goarch="$1" - case "${GOHOSTOS}" in - "darwin") - case "${goarch}" in - "amd64" | "amd64-sim"*) - local sdk_path - sdk_path=$(xcrun -sdk iphonesimulator --show-sdk-path) - [ $? -ne 0 ] && echo -e "${COLOR_LIGHT_RED}Failed to get iOS simulator SDK path.${COLOR_RESET}" && return 1 - CC="clang -arch x86_64 -miphonesimulator-version-min=4.2 -isysroot ${sdk_path}" - CXX="clang++ -arch x86_64 -miphonesimulator-version-min=4.2 -isysroot ${sdk_path}" - ;; - "arm64-sim"*) - local sdk_path - sdk_path=$(xcrun -sdk iphonesimulator --show-sdk-path) - [ $? -ne 0 ] && echo -e "${COLOR_LIGHT_RED}Failed to get iOS simulator SDK path.${COLOR_RESET}" && return 1 - CC="clang -arch arm64 -miphonesimulator-version-min=4.2 -isysroot ${sdk_path}" - CXX="clang++ -arch arm64 -miphonesimulator-version-min=4.2 -isysroot ${sdk_path}" - ;; - "arm64") - local sdk_path - sdk_path=$(xcrun -sdk iphoneos --show-sdk-path) - [ $? -ne 0 ] && echo -e "${COLOR_LIGHT_RED}Failed to get iOS SDK path.${COLOR_RESET}" && return 1 - CC="clang -arch arm64 -miphoneos-version-min=4.2 -isysroot ${sdk_path}" - CXX="clang++ -arch arm64 -miphoneos-version-min=4.2 -isysroot ${sdk_path}" - ;; - *) - echo -e "${COLOR_LIGHT_YELLOW}Unknown ios architecture: ${goarch}${COLOR_RESET}" - return 2 - ;; - esac - ;; - "linux") - # FIXME: use ios sdk - case "${GOHOSTARCH}" in - "amd64") - local cc_var=$(echo "CC_OSX_${goarch}" | awk '{print tolower($0)}') - local cxx_var=$(echo "CXX_OSX_${goarch}" | awk '{print tolower($0)}') - local cc=${!cc_var} - local cxx=${!cxx_var} - if [[ -z "${cc}" ]] && [[ -z "${cxx}" ]]; then - if command -v oa64-clang >/dev/null 2>&1 && command -v oa64-clang++ >/dev/null 2>&1; then - cc="oa64-clang" - cxx="oa64-clang++" - elif [[ -x "${CROSS_COMPILER_DIR}/osxcross/bin/oa64-clang" ]] && [[ -x "${CROSS_COMPILER_DIR}/osxcross/bin/oa64-clang++" ]]; then - cc="${CROSS_COMPILER_DIR}/osxcross/bin/oa64-clang" - cxx="${CROSS_COMPILER_DIR}/osxcross/bin/oa64-clang++" - EXTRA_PATH="${CROSS_COMPILER_DIR}/osxcross/bin" - patchelf --set-rpath "${CROSS_COMPILER_DIR}/osxcross/lib" \ - ${CROSS_COMPILER_DIR}/osxcross/bin/x86_64-apple-darwin*-ld || return 2 - else - local ubuntu_version=$(lsb_release -rs 2>/dev/null || echo "18.04") - if [[ "$ubuntu_version" != *"."* ]]; then - ubuntu_version="18.04" - fi - downloadAndUnzip "${GH_PROXY}https://github.com/zijiren233/osxcross/releases/download/v0.1.1/osxcross-14-5-linux-amd64-gnu-ubuntu-${ubuntu_version}.tar.gz" \ - "${CROSS_COMPILER_DIR}/osxcross" || return 2 - cc="${CROSS_COMPILER_DIR}/osxcross/bin/oa64-clang" - cxx="${CROSS_COMPILER_DIR}/osxcross/bin/oa64-clang++" - EXTRA_PATH="${CROSS_COMPILER_DIR}/osxcross/bin" - patchelf --set-rpath "${CROSS_COMPILER_DIR}/osxcross/lib" \ - ${CROSS_COMPILER_DIR}/osxcross/bin/x86_64-apple-darwin*-ld || return 2 - fi - elif [[ -z "${cc}" ]] || [[ -z "${cxx}" ]]; then - echo -e "${COLOR_LIGHT_RED}Both ${cc_var} and ${cxx_var} must be set.${COLOR_RESET}" - return 2 - fi - CC="${cc}" - CXX="${cxx}" - ;; - *) - echo -e "${COLOR_LIGHT_YELLOW}Cross compiler not supported for ${GOHOSTOS}/${GOHOSTARCH}.${COLOR_RESET}" - return 2 - ;; - esac - ;; - *) - echo -e "${COLOR_LIGHT_YELLOW}Cross compiler not supported for ${GOHOSTOS}/${GOHOSTARCH}.${COLOR_RESET}" - return 2 - ;; - esac -} - -function initOsxCGO() { - local goarch="$1" - case "${GOHOSTOS}" in - "darwin") - case "${goarch}" in - "amd64") - local sdk_path - sdk_path=$(xcrun -sdk macosx --show-sdk-path) - [ $? -ne 0 ] && echo -e "${COLOR_LIGHT_RED}Failed to get macOS SDK path.${COLOR_RESET}" && return 1 - CC="clang -arch x86_64 -mmacosx-version-min=10.11 -isysroot ${sdk_path}" - CXX="clang++ -arch x86_64 -mmacosx-version-min=10.11 -isysroot ${sdk_path}" - ;; - "arm64") - local sdk_path - sdk_path=$(xcrun -sdk macosx --show-sdk-path) - [ $? -ne 0 ] && echo -e "${COLOR_LIGHT_RED}Failed to get macOS SDK path.${COLOR_RESET}" && return 1 - CC="clang -arch arm64 -mmacosx-version-min=10.11 -isysroot ${sdk_path}" - CXX="clang++ -arch arm64 -mmacosx-version-min=10.11 -isysroot ${sdk_path}" - ;; - *) - echo -e "${COLOR_LIGHT_YELLOW}Unknown darwin architecture: ${goarch}${COLOR_RESET}" - return 2 - ;; - esac - ;; - "linux") - case "${GOHOSTARCH}" in - "amd64") - local cc_var=$(echo "CC_OSX_${goarch}" | awk '{print tolower($0)}') - local cxx_var=$(echo "CXX_OSX_${goarch}" | awk '{print tolower($0)}') - local cc=${!cc_var} - local cxx=${!cxx_var} - if [[ -z "${cc}" ]] && [[ -z "${cxx}" ]]; then - if command -v oa64-clang >/dev/null 2>&1 && command -v oa64-clang++ >/dev/null 2>&1; then - cc="oa64-clang" - cxx="oa64-clang++" - elif [[ -x "${CROSS_COMPILER_DIR}/osxcross/bin/oa64-clang" ]] && [[ -x "${CROSS_COMPILER_DIR}/osxcross/bin/oa64-clang++" ]]; then - cc="${CROSS_COMPILER_DIR}/osxcross/bin/oa64-clang" - cxx="${CROSS_COMPILER_DIR}/osxcross/bin/oa64-clang++" - EXTRA_PATH="${CROSS_COMPILER_DIR}/osxcross/bin" - patchelf --set-rpath "${CROSS_COMPILER_DIR}/osxcross/lib" \ - ${CROSS_COMPILER_DIR}/osxcross/bin/x86_64-apple-darwin*-ld || return 2 - else - local ubuntu_version=$(lsb_release -rs 2>/dev/null || echo "18.04") - if [[ "$ubuntu_version" != *"."* ]]; then - ubuntu_version="18.04" - fi - downloadAndUnzip "${GH_PROXY}https://github.com/zijiren233/osxcross/releases/download/v0.1.1/osxcross-14-5-linux-amd64-gnu-ubuntu-${ubuntu_version}.tar.gz" \ - "${CROSS_COMPILER_DIR}/osxcross" || return 2 - cc="${CROSS_COMPILER_DIR}/osxcross/bin/oa64-clang" - cxx="${CROSS_COMPILER_DIR}/osxcross/bin/oa64-clang++" - EXTRA_PATH="${CROSS_COMPILER_DIR}/osxcross/bin" - patchelf --set-rpath "${CROSS_COMPILER_DIR}/osxcross/lib" \ - ${CROSS_COMPILER_DIR}/osxcross/bin/x86_64-apple-darwin*-ld || return 2 - fi - elif [[ -z "${cc}" ]] || [[ -z "${cxx}" ]]; then - echo -e "${COLOR_LIGHT_RED}Both ${cc_var} and ${cxx_var} must be set.${COLOR_RESET}" - return 2 - fi - CC="${cc}" - CXX="${cxx}" - ;; - *) - echo -e "${COLOR_LIGHT_YELLOW}Cross compiler not supported for ${GOHOSTOS}/${GOHOSTARCH}.${COLOR_RESET}" - return 2 - ;; - esac - ;; - *) - echo -e "${COLOR_LIGHT_YELLOW}Cross compiler not supported for ${GOHOSTOS}/${GOHOSTARCH}.${COLOR_RESET}" - return 2 - ;; - esac -} - -# Initializes CGO dependencies for Linux. -# Arguments: -# $1: Architecture prefix (e.g., "i686", "x86_64"). -# $2: Optional. ABI (e.g., "eabi", "eabihf"). -# $3: Optional. Micro architecture variant. -function initLinuxCGO() { - local arch_prefix="$1" - local abi="$2" - local micro="$3" - local cc_var=$(echo "CC_LINUX_${arch_prefix}${abi}${micro}" | awk '{print tolower($0)}') - local cxx_var=$(echo "CXX_LINUX_${arch_prefix}${abi}${micro}" | awk '{print tolower($0)}') - local cc=${!cc_var} - local cxx=${!cxx_var} - - if [[ -z "${cc}" ]] && [[ -z "${cxx}" ]]; then - local cross_compiler_name="${arch_prefix}-linux-musl${abi}${micro}-cross" - if command -v "${arch_prefix}-linux-musl${abi}${micro}-gcc" >/dev/null 2>&1 && - command -v "${arch_prefix}-linux-musl${abi}${micro}-g++" >/dev/null 2>&1; then - cc="${arch_prefix}-linux-musl${abi}${micro}-gcc" - cxx="${arch_prefix}-linux-musl${abi}${micro}-g++" - elif [[ -x "${CROSS_COMPILER_DIR}/${cross_compiler_name}/bin/${arch_prefix}-linux-musl${abi}${micro}-gcc" ]] && - [[ -x "${CROSS_COMPILER_DIR}/${cross_compiler_name}/bin/${arch_prefix}-linux-musl${abi}${micro}-g++" ]]; then - cc="${CROSS_COMPILER_DIR}/${cross_compiler_name}/bin/${arch_prefix}-linux-musl${abi}${micro}-gcc" - cxx="${CROSS_COMPILER_DIR}/${cross_compiler_name}/bin/${arch_prefix}-linux-musl${abi}${micro}-g++" - else - downloadAndUnzip "${GH_PROXY}https://github.com/zijiren233/musl-cross-make/releases/download/${CGO_DEPS_VERSION}/${cross_compiler_name}-${unamespacer}.tgz" \ - "${CROSS_COMPILER_DIR}/${cross_compiler_name}" || return 2 - cc="${CROSS_COMPILER_DIR}/${cross_compiler_name}/bin/${arch_prefix}-linux-musl${abi}${micro}-gcc" - cxx="${CROSS_COMPILER_DIR}/${cross_compiler_name}/bin/${arch_prefix}-linux-musl${abi}${micro}-g++" - fi - elif [[ -z "${cc}" ]] || [[ -z "${cxx}" ]]; then - echo -e "${COLOR_LIGHT_RED}Both ${cc_var} and ${cxx_var} must be set.${COLOR_RESET}" - return 2 - fi - - CC="${cc} -static --static" - CXX="${cxx} -static --static" -} - -# Initializes CGO dependencies for Windows. -# Arguments: -# $1: Architecture prefix (e.g., "i686", "x86_64"). -function initWindowsCGO() { - local arch_prefix="$1" - local cc_var=$(echo "CC_WINDOWS_${arch_prefix}" | awk '{print tolower($0)}') - local cxx_var=$(echo "CXX_WINDOWS_${arch_prefix}" | awk '{print tolower($0)}') - local cc=${!cc_var} - local cxx=${!cxx_var} - - if [[ -z "${cc}" ]] && [[ -z "${cxx}" ]]; then - local cross_compiler_name="${arch_prefix}-w64-mingw32-cross" - if command -v "${arch_prefix}-w64-mingw32-gcc" >/dev/null 2>&1 && - command -v "${arch_prefix}-w64-mingw32-g++" >/dev/null 2>&1; then - cc="${arch_prefix}-w64-mingw32-gcc" - cxx="${arch_prefix}-w64-mingw32-g++" - elif [[ -x "${CROSS_COMPILER_DIR}/${cross_compiler_name}/bin/${arch_prefix}-w64-mingw32-gcc" ]] && - [[ -x "${CROSS_COMPILER_DIR}/${cross_compiler_name}/bin/${arch_prefix}-w64-mingw32-g++" ]]; then - cc="${CROSS_COMPILER_DIR}/${cross_compiler_name}/bin/${arch_prefix}-w64-mingw32-gcc" - cxx="${CROSS_COMPILER_DIR}/${cross_compiler_name}/bin/${arch_prefix}-w64-mingw32-g++" - else - downloadAndUnzip "${GH_PROXY}https://github.com/zijiren233/musl-cross-make/releases/download/${CGO_DEPS_VERSION}/${cross_compiler_name}-${unamespacer}.tgz" \ - "${CROSS_COMPILER_DIR}/${cross_compiler_name}" || return 2 - cc="${CROSS_COMPILER_DIR}/${cross_compiler_name}/bin/${arch_prefix}-w64-mingw32-gcc" - cxx="${CROSS_COMPILER_DIR}/${cross_compiler_name}/bin/${arch_prefix}-w64-mingw32-g++" - fi - elif [[ -z "${cc}" ]] || [[ -z "${cxx}" ]]; then - echo -e "${COLOR_LIGHT_RED}Both ${cc_var} and ${cxx_var} must be set.${COLOR_RESET}" - return 2 - fi - - CC="${cc} -static --static" - CXX="${cxx} -static --static" -} - -# Initializes CGO dependencies for Android NDK. -# Arguments: -# $1: Target architecture (GOARCH). -function initAndroidNDK() { - local goarch="$1" - - local ndk_dir="${CROSS_COMPILER_DIR}/android-ndk-${GOHOSTOS}-${NDK_VERSION}" - local clang_base_dir="${ndk_dir}/toolchains/llvm/prebuilt/${GOHOSTOS}-x86_64/bin" - local clang_prefix="$(getAndroidClang "${goarch}")" - local cc="${clang_base_dir}/${clang_prefix}-clang" - local cxx="${clang_base_dir}/${clang_prefix}-clang++" - - if [[ ! -d "${ndk_dir}" ]]; then - local ndk_url="https://dl.google.com/android/repository/android-ndk-${NDK_VERSION}-${GOHOSTOS}.zip" - downloadAndUnzip "${ndk_url}" "${ndk_dir}" "zip" || return 2 - mv "$ndk_dir/android-ndk-${NDK_VERSION}/"* "$ndk_dir" - rmdir "$ndk_dir/android-ndk-${NDK_VERSION}" || return 2 - fi - - if [[ ! -x "${cc}" ]] || [[ ! -x "${cxx}" ]]; then - echo -e "${COLOR_LIGHT_RED}Android NDK not found or invalid. Please check the NDK_VERSION environment variable.${COLOR_RESET}" - return 2 - fi - - CC="${cc}" - CXX="${cxx}" -} - -# Gets the Clang host prefix for Android NDK. -# Arguments: -# $1: Target architecture (GOARCH). -# Returns: -# The Clang host prefix. -function getAndroidClang() { - local API="${API:-24}" - case ${1} in - arm) - echo "armv7a-linux-androideabi${API}" - ;; - arm64) - echo "aarch64-linux-android${API}" - ;; - 386) - echo "i686-linux-android${API}" - ;; - amd64) - echo "x86_64-linux-android${API}" - ;; - esac -} - -# --- Utility Functions --- - -# Gets a separator line based on the terminal width. -# Returns: -# A string of "-" characters with the length of the terminal width. -function printSeparator() { - local width=$(tput cols 2>/dev/null || echo $DEFAULT_TTY_WIDTH) - printf '%*s\n' "$width" '' | tr ' ' - -} - -# --- Build Functions --- - -# Builds a target for a specific platform and micro architecture variant. -# Arguments: -# $1: Target platform (e.g., "linux/amd64"). -# $2: Target name (e.g., binary name). -# Ref: -# https://go.dev/wiki/MinimumRequirements#microarchitecture-support -# https://go.dev/doc/install/source#environment -function buildTarget() { - local platform="$1" - local goos="${platform%/*}" - local goarch="${platform#*/}" - - echo -e "${COLOR_LIGHT_GRAY}$(printSeparator)${COLOR_RESET}" - - buildTargetWithMicro "${goos}" "${goarch}" "" - - if [ -z "${ENABLE_MICRO}" ]; then - return 0 - fi - - # Build micro architecture variants based on the target architecture. - case "${goarch}" in - "386") - echo - buildTargetWithMicro "${goos}" "${goarch}" "sse2" - echo - buildTargetWithMicro "${goos}" "${goarch}" "softfloat" - ;; - "arm") - for v in {5..7}; do - echo - buildTargetWithMicro "${goos}" "${goarch}" "$v" - done - ;; - "arm64") - if [[ ! "${GOVERSION#go}" > "1.23" ]]; then - return 0 - fi - for major in 8 9; do - for minor in $(seq 0 $((major == 8 ? 9 : 5))); do - echo - buildTargetWithMicro "${goos}" "${goarch}" "v${major}.${minor}" - echo - buildTargetWithMicro "${goos}" "${goarch}" "v${major}.${minor},lse" - echo - buildTargetWithMicro "${goos}" "${goarch}" "v${major}.${minor},crypto" - done - done - ;; - "amd64") - if [[ ! "${GOVERSION#go}" > "1.18" ]]; then - return 0 - fi - for v in {1..4}; do - echo - buildTargetWithMicro "${goos}" "${goarch}" "v$v" - done - ;; - "mips" | "mipsle" | "mips64" | "mips64le") - echo - buildTargetWithMicro "${goos}" "${goarch}" "hardfloat" - echo - buildTargetWithMicro "${goos}" "${goarch}" "softfloat" - ;; - "ppc64" | "ppc64le") - for version in 8 9 10; do - echo - buildTargetWithMicro "${goos}" "${goarch}" "power${version}" - done - ;; - "wasm") - echo - buildTargetWithMicro "${goos}" "${goarch}" "satconv" - echo - buildTargetWithMicro "${goos}" "${goarch}" "signext" - ;; - esac -} - -# Gets the extension based on the build mode and operating system. -# Arguments: -# $1: Operating system (e.g., "linux", "windows", "darwin", "ios"). -# $2: Build mode (e.g., "archive", "shared", "default"). -# Returns: -# The extension string. -function extension() { - local goos="$1" - local buildmode="$2" - if [ "$buildmode" == "archive" ] || [ "$buildmode" == "c-archive" ]; then - if [ "$goos" == "windows" ]; then - echo ".lib" - else - echo ".a" - fi - elif [ "$buildmode" == "shared" ] || [ "$buildmode" == "c-shared" ]; then - if [ "$goos" == "windows" ]; then - echo ".dll" - elif [ "$goos" == "darwin" ] || [ "$goos" == "ios" ]; then - echo ".dylib" - else - echo ".so" - fi - else - if [ "$goos" == "windows" ]; then - echo ".exe" - fi - fi -} - -# Builds a target for a specific platform, micro architecture variant, and build environment. -# Arguments: -# $1: GOOS -# $2: GOARCH -# $3: Micro architecture variant (e.g., "sse2", "softfloat"). Ref: https://go.dev/wiki/MinimumRequirements#microarchitecture-support -function buildTargetWithMicro() { - local goos="$1" - local _goarch="$2" - local goarch="${_goarch%%-*}" - local micro="$3" - local build_env=( - "GOOS=${goos}" - "GOARCH=${goarch}" - ) - local buildmode=$BUILD_MODE - local ext=$(extension "${goos}" "${buildmode}") - local target_file="${RESULT_DIR}/${BIN_NAME}" - [ -z "$BIN_NAME_NO_SUFFIX" ] && target_file="${target_file}-${goos}-${_goarch}${micro:+"-${micro//[.,]/-}"}" || true - target_file="${target_file}${ext}" - - # Set micro architecture specific environment variables. - case "${goarch}" in - "386") - build_env+=("GO386=${micro}") - [ -z "$micro" ] && micro="sse2" - ;; - "arm") - build_env+=("GOARM=${micro}") - [ -z "$micro" ] && micro="6" - ;; - "arm64") - build_env+=("GOARM64=${micro}") - [ -z "$micro" ] && micro="v8.0" - ;; - "amd64") - build_env+=("GOAMD64=${micro}") - ;; - "mips" | "mipsle") - build_env+=("GOMIPS=${micro}") - [ -z "$micro" ] && micro="hardfloat" - ;; - "mips64" | "mips64le") - build_env+=("GOMIPS64=${micro}") - [ -z "$micro" ] && micro="hardfloat" - ;; - "ppc64" | "ppc64le") - build_env+=("GOPPC64=${micro}") - ;; - "wasm") - build_env+=("GOWASM=${micro}") - ;; - esac - - echo -e "${COLOR_LIGHT_MAGENTA}Building ${goos}/${goarch}${micro:+/${micro}}...${COLOR_RESET}" - - if isCGOEnabled; then - if initCGODeps "${goos}" "${_goarch}" "${micro}"; then - code=0 - else - code=$? - fi - - build_env+=("PATH=${EXTRA_PATH:+$EXTRA_PATH:}$PATH") - - case "$code" in - 0) - build_env+=("CGO_ENABLED=1") - build_env+=("CC=${CC}") - build_env+=("CXX=${CXX}") - build_env+=("CGO_CFLAGS=${CGO_FLAGS}${MORE_CGO_CFLAGS:+ ${MORE_CGO_CFLAGS}}") - build_env+=("CGO_CXXFLAGS=${CGO_FLAGS}${MORE_CGO_CXXFLAGS:+ ${MORE_CGO_CXXFLAGS}}") - build_env+=("CGO_LDFLAGS=${CGO_LDFLAGS}${MORE_CGO_LDFLAGS:+ ${MORE_CGO_LDFLAGS}}") - ;; - 1) - if [[ "${FORCE_CGO}" == "1" ]]; then - echo -e "${COLOR_LIGHT_RED}Error initializing CGO dependencies.${COLOR_RESET}" - return 1 - fi - build_env+=("CGO_ENABLED=0") - ;; - *) - echo -e "${COLOR_LIGHT_RED}Error initializing CGO dependencies.${COLOR_RESET}" - return 1 - ;; - esac - else - if [[ "${FORCE_CGO}" == "1" ]]; then - echo -e "${COLOR_LIGHT_RED}Error initializing CGO dependencies.${COLOR_RESET}" - return 1 - fi - build_env+=("CGO_ENABLED=0") - fi - - echo -e "${COLOR_LIGHT_BLUE}Run command:${COLOR_RESET}\n$(for var in "${build_env[@]}"; do - key=$(echo "${var}" | cut -d= -f1) - value=$(echo "${var}" | cut -d= -f2-) - echo -e "${COLOR_LIGHT_GREEN}export${COLOR_RESET} ${COLOR_WHITE}${key}='${value}'${COLOR_RESET}" - done)\n${COLOR_LIGHT_CYAN}go build -buildmode=$buildmode -trimpath ${BUILD_ARGS} -tags \"${TAGS}\" -ldflags \"${LDFLAGS}${EXT_LDFLAGS:+ -extldflags '$EXT_LDFLAGS'}\" -o \"${target_file}\" \"${source_dir}\"${COLOR_RESET}" - local start_time=$(date +%s) - env "${build_env[@]}" go build -buildmode=$buildmode -trimpath ${BUILD_ARGS} -tags "${TAGS}" -ldflags "${LDFLAGS}${EXT_LDFLAGS:+ -extldflags '$EXT_LDFLAGS'}" -o "${target_file}" "${source_dir}" - local end_time=$(date +%s) - echo -e "${COLOR_LIGHT_GREEN}Build successful: ${goos}/${goarch}${micro:+ ${micro}} (took $((end_time - start_time))s)${COLOR_RESET}" -} - -# Expands platform patterns (e.g., "linux/*") to a list of supported platforms. -# Arguments: -# $1: Comma-separated list of platforms, potentially containing patterns. -# Returns: -# Comma-separated list of expanded platforms. -function expandPlatforms() { - local platforms="$1" - local expanded_platforms="" - for platform in ${platforms//,/ }; do - if [[ "${platform}" == "all" ]]; then - echo "${ALLOWED_PLATFORMS}" - return 0 - elif [[ "${platform}" == *\** ]]; then - for tmp_var in ${ALLOWED_PLATFORMS//,/ }; do - [[ "${tmp_var}" == ${platform} ]] && expanded_platforms="${expanded_platforms},${tmp_var}" - done - elif [[ "${platform}" != */* ]]; then - expanded_platforms="${expanded_platforms},$(expandPlatforms "${platform}/*")" - else - expanded_platforms="${expanded_platforms},${platform}" - fi - done - removeDuplicatePlatforms "${expanded_platforms}" -} - -# Performs the automatic build process for the specified platforms. -# Arguments: -# $1: Comma-separated list of platforms to build for. -function autoBuild() { - local platforms=$(expandPlatforms "$1") - checkPlatforms "${platforms}" || return 1 - [ -z "${platforms}" ] && - echo -e "${COLOR_LIGHT_RED}No platforms specified.${COLOR_RESET}" && - echo -e "${COLOR_LIGHT_RED}Supported platforms:${COLOR_RESET} ${COLOR_LIGHT_CYAN}${ALLOWED_PLATFORMS}${COLOR_RESET}" && - return 1 - local start_time=$(date +%s) - if declare -f initDep >/dev/null; then - initDep - fi - local build_num=0 - for platform in ${platforms//,/ }; do - buildTarget "${platform}" - build_num=$((build_num + 1)) - done - local end_time=$(date +%s) - if [[ "${build_num}" -gt 1 ]]; then - echo -e "${COLOR_LIGHT_YELLOW}Total took $((end_time - start_time))s${COLOR_RESET}" - fi -} - -# Checks if the build configuration file has been loaded. -# Returns: -# 0: Build configuration file has been loaded. -# 1: Build configuration file has not been loaded. -function loadedBuildConfig() { - if [[ -n "${load_build_config}" ]]; then - return 0 - fi - return 1 -} - -# Loads the build configuration file if it exists. -function loadBuildConfig() { - if [[ -f "${BUILD_CONFIG:=$DEFAULT_BUILD_CONFIG}" ]]; then - source $BUILD_CONFIG - load_build_config="true" - fi -} - -# --- Main Script --- - -loadBuildConfig - -# Parse command-line arguments. -while [[ $# -gt 0 ]]; do - case "${1}" in - -h | --help) - printHelp - exit 0 - ;; - -eh | --env-help) - printEnvHelp - exit 0 - ;; - --build-mode=*) - BUILD_MODE="${1#*=}" - ;; - --disable-cgo) - CGO_ENABLED="0" - ;; - --source-dir=*) - SOURCE_DIR="${1#*=}" - ;; - --bin-name=*) - BIN_NAME="${1#*=}" - ;; - --bin-name-no-suffix) - BIN_NAME_NO_SUFFIX="true" - ;; - --more-go-cmd-args=*) - addBuildArgs "${1#*=}" - ;; - --enable-micro) - ENABLE_MICRO="true" - ;; - --ldflags=*) - addLDFLAGS "${1#*=}" - ;; - --ext-ldflags=*) - addExtLDFLAGS "${1#*=}" - ;; - -p=* | --platforms=*) - PLATFORMS="${1#*=}" - ;; - --result-dir=*) - RESULT_DIR="${1#*=}" - ;; - --tags=*) - addTags "${1#*=}" - ;; - --show-all-platforms) - initPlatforms - echo "${ALLOWED_PLATFORMS}" - exit 0 - ;; - --show-all-platforms=*) - initPlatforms - echo "$(expandPlatforms "${1#*=}")" - exit 0 - ;; - --github-proxy-mirror=*) - GH_PROXY="${1#*=}" - ;; - --cross-compiler-dir=*) - CROSS_COMPILER_DIR="${1#*=}" - ;; - --force-gcc=*) - FORCE_CC="${1#*=}" - ;; - --force-g++=*) - FORCE_CXX="${1#*=}" - ;; - --host-gcc=*) - HOST_CC="${1#*=}" - ;; - --host-g++=*) - HOST_CXX="${1#*=}" - ;; - --ndk-version=*) - NDK_VERSION="${1#*=}" - ;; - *) - if declare -f parseDepArgs >/dev/null && parseDepArgs "$1"; then - shift - continue - fi - echo -e "${COLOR_LIGHT_RED}Invalid option: $1${COLOR_RESET}" - exit 1 - ;; - esac - shift -done - -fixArgs -initPlatforms -autoBuild "${PLATFORMS}"