From 45404b5bcfde2dde74ab84d65336aef2fa55bf31 Mon Sep 17 00:00:00 2001 From: Aofei Sheng Date: Wed, 10 Jul 2024 19:28:42 +0800 Subject: [PATCH] ci: implement release-build.yml workflow with GoReleaser --- .github/workflows/populate_darwin_sysroot.sh | 40 +++++ .github/workflows/populate_linux_sysroot.sh | 143 ++++++++++++++++++ .github/workflows/release-build.yml | 58 ++++++++ .gitignore | 4 + .goreleaser.yaml | 145 +++++++++++++++++++ 5 files changed, 390 insertions(+) create mode 100755 .github/workflows/populate_darwin_sysroot.sh create mode 100755 .github/workflows/populate_linux_sysroot.sh create mode 100644 .github/workflows/release-build.yml create mode 100644 .goreleaser.yaml diff --git a/.github/workflows/populate_darwin_sysroot.sh b/.github/workflows/populate_darwin_sysroot.sh new file mode 100755 index 00000000..9e276847 --- /dev/null +++ b/.github/workflows/populate_darwin_sysroot.sh @@ -0,0 +1,40 @@ +#!/bin/bash + +set -e + +TMPDIR="$(mktemp -d)" +export TMPDIR +trap 'rm -rf "${TMPDIR}"' EXIT + +DARWIN_AMD64_LLVM_PREFIX=.sysroot/darwin/amd64/usr/local/opt/llvm@18 +DARWIN_ARM64_LLVM_PREFIX=.sysroot/darwin/arm64/opt/homebrew/opt/llvm@18 +mkdir -p "${DARWIN_AMD64_LLVM_PREFIX}" "${DARWIN_ARM64_LLVM_PREFIX}" + +BREW_LLVM_FORMULA_JSON="$(mktemp)" +curl -fsSL https://formulae.brew.sh/api/formula/llvm.json > "${BREW_LLVM_FORMULA_JSON}" +BREW_LLVM_AMD64_BOTTLE_URL=$(jq -r '.bottle.stable.files.sonoma.url' "${BREW_LLVM_FORMULA_JSON}") +BREW_LLVM_ARM64_BOTTLE_URL=$(jq -r '.bottle.stable.files.arm64_sonoma.url' "${BREW_LLVM_FORMULA_JSON}") +curl -fsSL -H "Authorization: Bearer QQ==" "${BREW_LLVM_AMD64_BOTTLE_URL}" | tar -xzf - --strip-components=2 -C "${DARWIN_AMD64_LLVM_PREFIX}" +curl -fsSL -H "Authorization: Bearer QQ==" "${BREW_LLVM_ARM64_BOTTLE_URL}" | tar -xzf - --strip-components=2 -C "${DARWIN_ARM64_LLVM_PREFIX}" + +patch_homebrew_lib_dir() { + local LIB_DIR="$1" + local HOMEBREW_PREFIX="$2" + for DYLIB_FILE in "${LIB_DIR}"/*.dylib; do + if [[ -f "${DYLIB_FILE}" ]]; then + ID=$(otool -D "${DYLIB_FILE}" | grep '@@HOMEBREW_PREFIX@@' | awk '{print $1}') + if [[ -n "${ID}" ]]; then + NEW_ID=${ID/'@@HOMEBREW_PREFIX@@'/${HOMEBREW_PREFIX}} + install_name_tool -id "${NEW_ID}" "${DYLIB_FILE}" + fi + + DEPS=$(otool -L "${DYLIB_FILE}" | grep '@@HOMEBREW_PREFIX@@' | awk '{print $1}') + for DEP in ${DEPS}; do + NEW_DEP=${DEP/'@@HOMEBREW_PREFIX@@'/${HOMEBREW_PREFIX}} + install_name_tool -change "${DEP}" "${NEW_DEP}" "${DYLIB_FILE}" + done + fi + done +} +patch_homebrew_lib_dir "${DARWIN_AMD64_LLVM_PREFIX}/lib" /usr/lib +patch_homebrew_lib_dir "${DARWIN_ARM64_LLVM_PREFIX}/lib" /opt/homebrew diff --git a/.github/workflows/populate_linux_sysroot.sh b/.github/workflows/populate_linux_sysroot.sh new file mode 100755 index 00000000..57e44c09 --- /dev/null +++ b/.github/workflows/populate_linux_sysroot.sh @@ -0,0 +1,143 @@ +#!/bin/bash + +set -e + +TMPDIR="$(mktemp -d)" +export TMPDIR +trap 'rm -rf "${TMPDIR}"' EXIT + +LINUX_AMD64_PREFIX=.sysroot/linux/amd64 +LINUX_ARM64_PREFIX=.sysroot/linux/arm64 +mkdir -p "${LINUX_AMD64_PREFIX}" "${LINUX_ARM64_PREFIX}" + +POPULATE_LINUX_SYSROOT_SCRIPT="$(mktemp)" +cat > "${POPULATE_LINUX_SYSROOT_SCRIPT}" << EOF +#!/bin/bash + +export DEBIAN_FRONTEND=noninteractive + +apt-get update +apt-get install -y lsb-release gnupg2 wget rsync + +echo "deb http://apt.llvm.org/\$(lsb_release -cs)/ llvm-toolchain-\$(lsb_release -cs)-18 main" | tee /etc/apt/sources.list.d/llvm.list +wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | apt-key add - +apt-get update +apt-get install -y llvm-18-dev + +error() { + echo -e "\$1" >&2 + exit 1 +} + +exclude_list=() +include_list=() + +exclude_list+=(--exclude "/bin") +exclude_list+=(--exclude "/boot") +exclude_list+=(--exclude "/boot*") +exclude_list+=(--exclude "/dev") +exclude_list+=(--exclude "/etc") +exclude_list+=(--exclude "/home") +exclude_list+=(--exclude "/lib/dhcpd") +exclude_list+=(--exclude "/lib/firmware") +exclude_list+=(--exclude "/lib/hdparm") +exclude_list+=(--exclude "/lib/ifupdown") +exclude_list+=(--exclude "/lib/modules") +exclude_list+=(--exclude "/lib/modprobe.d") +exclude_list+=(--exclude "/lib/modules-load.d") +exclude_list+=(--exclude "/lib/resolvconf") +exclude_list+=(--exclude "/lib/startpar") +exclude_list+=(--exclude "/lib/systemd") +exclude_list+=(--exclude "/lib/terminfo") +exclude_list+=(--exclude "/lib/udev") +exclude_list+=(--exclude "/lib/xtables") +exclude_list+=(--exclude "/lib/ssl/private") +exclude_list+=(--exclude "/lost+found") +exclude_list+=(--exclude "/media") +exclude_list+=(--exclude "/mnt") +exclude_list+=(--exclude "/proc") +exclude_list+=(--exclude "/root") +exclude_list+=(--exclude "/run") +exclude_list+=(--exclude "/sbin") +exclude_list+=(--exclude "/srv") +exclude_list+=(--exclude "/sys") +exclude_list+=(--exclude "/tmp") +exclude_list+=(--exclude "/usr/bin") +exclude_list+=(--exclude "/usr/games") +exclude_list+=(--exclude "/usr/sbin") +exclude_list+=(--exclude "/usr/share") +exclude_list+=(--exclude "/usr/src") +exclude_list+=(--exclude "/usr/local/bin") +exclude_list+=(--exclude "/usr/local/etc") +exclude_list+=(--exclude "/usr/local/games") +exclude_list+=(--exclude "/usr/local/man") +exclude_list+=(--exclude "/usr/local/sbin") +exclude_list+=(--exclude "/usr/local/share") +exclude_list+=(--exclude "/usr/local/src") +exclude_list+=(--exclude "/usr/lib/ssl/private") +exclude_list+=(--exclude "/var") +exclude_list+=(--exclude "/snap") +exclude_list+=(--exclude "*python*") + +include_list+=(--include "*.a") +include_list+=(--include "*.so") +include_list+=(--include "*.so.*") +include_list+=(--include "*.h") +include_list+=(--include "*.hh") +include_list+=(--include "*.hpp") +include_list+=(--include "*.hxx") +include_list+=(--include "*.pc") +include_list+=(--include "*.def") +include_list+=(--include "*.inc") +include_list+=(--include "/lib") +include_list+=(--include "/lib32") +include_list+=(--include "/lib64") +include_list+=(--include "/libx32") +include_list+=(--include "*/") + +do-sync() { + from=\$1 + to=\$2 + + args=() + args+=(-a) + args+=(-z) + args+=(-m) + args+=(-d) + args+=(-h) + args+=(--keep-dirlinks) + args+=("--info=progress2") + args+=(--delete) + args+=(--prune-empty-dirs) + args+=(--sparse) + args+=(--links) + args+=(--copy-unsafe-links) + args+=("\${exclude_list[@]}") + args+=("\${include_list[@]}") + args+=(--exclude "*") + args+=("\${from}") + args+=("\${to}") + + echo "\${args[@]}" + rsync "\${args[@]}" + + exit \$? +} + +do-sync / /sysroot/ +EOF +chmod +x "${POPULATE_LINUX_SYSROOT_SCRIPT}" + +populate_linux_sysroot() { + local ARCH="$1" + local PREFIX="$2" + docker run \ + --rm \ + --platform "linux/${ARCH}" \ + -v "$(pwd)/${PREFIX}":/sysroot \ + -v "${POPULATE_LINUX_SYSROOT_SCRIPT}":/populate_linux_sysroot.sh \ + debian:bullseye \ + /populate_linux_sysroot.sh +} +populate_linux_sysroot amd64 "${LINUX_AMD64_PREFIX}" +populate_linux_sysroot arm64 "${LINUX_ARM64_PREFIX}" diff --git a/.github/workflows/release-build.yml b/.github/workflows/release-build.yml new file mode 100644 index 00000000..869c4fbd --- /dev/null +++ b/.github/workflows/release-build.yml @@ -0,0 +1,58 @@ +name: Release Build + +on: + push: + tags: + - "*" + +jobs: + populate-darwin-sysroot: + runs-on: macos-latest + steps: + - name: Check out code + uses: actions/checkout@v4 + - name: Populate Darwin sysroot + run: bash .github/workflows/populate_darwin_sysroot.sh + - name: Create Darwin sysroot tarball + run: tar -czvf .sysroot/darwin.tar.gz -C .sysroot darwin + - name: Upload Darwin sysroot tarball + uses: actions/upload-artifact@v4 + with: + name: darwin-sysroot-tarball + path: .sysroot/darwin.tar.gz + compression-level: 0 + build: + runs-on: ubuntu-latest + needs: populate-darwin-sysroot + steps: + - name: Check out code + uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: Set up Go + uses: actions/setup-go@v5 + with: + go-version: 1.20.x + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + - name: Download Darwin sysroot tarball + uses: actions/download-artifact@v4 + with: + name: darwin-sysroot-tarball + path: .sysroot + - name: Populate Darwin sysroot + run: tar -xzvf .sysroot/darwin.tar.gz -C .sysroot + - name: Populate Linux sysroot + run: bash .github/workflows/populate_linux_sysroot.sh + - name: Run GoReleaser + env: + GITHUB_TOKEN: ${{github.token}} + run: | + docker run \ + --rm \ + -e GITHUB_TOKEN=${GITHUB_TOKEN} \ + -v /var/run/docker.sock:/var/run/docker.sock \ + -v $(pwd):/go/src/llgo \ + -w /go/src/llgo \ + ghcr.io/goreleaser/goreleaser-cross:v1.22 \ + release --clean --skip nfpm,snapcraft diff --git a/.gitignore b/.gitignore index f1ec3d90..e7faa0ec 100644 --- a/.gitignore +++ b/.gitignore @@ -35,3 +35,7 @@ build.dir/ # Go workspace file go.work* + +# GoReleaser +.dist/ +.sysroot/ diff --git a/.goreleaser.yaml b/.goreleaser.yaml new file mode 100644 index 00000000..9dc465b9 --- /dev/null +++ b/.goreleaser.yaml @@ -0,0 +1,145 @@ +version: 2 + +dist: .dist + +env: + - SYSROOT_DARWIN_AMD64={{.Env.PWD}}/.sysroot/darwin/amd64 + - SYSROOT_DARWIN_ARM64={{.Env.PWD}}/.sysroot/darwin/arm64 + - SYSROOT_LINUX_AMD64={{.Env.PWD}}/.sysroot/linux/amd64 + - SYSROOT_LINUX_ARM64={{.Env.PWD}}/.sysroot/linux/arm64 + - CGO_ENABLED=1 + - CGO_CXXFLAGS=-std=c++17 + +before: + hooks: + - go mod download + +builds: + - id: llgo-darwin-amd64 + main: ./cmd/llgo + flags: + - -tags=darwin,amd64,byollvm + ldflags: + - -X github.com/goplus/llgo/xtool/env.buildVersion=v{{.Version}} + - -X github.com/goplus/llgo/xtool/env.buildDate={{.Date}} + - -X github.com/goplus/llgo/xtool/env/llvm.ldLLVMConfigBin=/usr/local/opt/llvm@18/bin/llvm-config + env: + - CC=o64-clang + - CXX=o64-clang++ + - CGO_CPPFLAGS=-I{{.Env.SYSROOT_DARWIN_AMD64}}/usr/local/opt/llvm@18/include -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS + - CGO_LDFLAGS=-L{{.Env.SYSROOT_DARWIN_AMD64}}/usr/local/opt/llvm@18/lib -Wl,-search_paths_first -Wl,-headerpad_max_install_names -lLLVM-18 -lz -lm + targets: + - darwin_amd64 + mod_timestamp: "{{.CommitTimestamp}}" + - id: llgo-darwin-arm64 + main: ./cmd/llgo + flags: + - -tags=darwin,arm64,byollvm + ldflags: + - -X github.com/goplus/llgo/xtool/env.buildVersion=v{{.Version}} + - -X github.com/goplus/llgo/xtool/env.buildDate={{.Date}} + - -X github.com/goplus/llgo/xtool/env/llvm.ldLLVMConfigBin=/opt/homebrew/opt/llvm@18/bin/llvm-config + env: + - CC=oa64-clang + - CXX=oa64-clang++ + - CGO_CPPFLAGS=-I{{.Env.SYSROOT_DARWIN_ARM64}}/opt/homebrew/opt/llvm@18/include -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS + - CGO_LDFLAGS=-L{{.Env.SYSROOT_DARWIN_ARM64}}/opt/homebrew/opt/llvm@18/lib -Wl,-search_paths_first -Wl,-headerpad_max_install_names -lLLVM-18 -lz -lm + targets: + - darwin_arm64 + mod_timestamp: "{{.CommitTimestamp}}" + - id: llgo-linux-amd64 + main: ./cmd/llgo + flags: + - -tags=linux,amd64,byollvm + ldflags: + - -X github.com/goplus/llgo/xtool/env.buildVersion=v{{.Version}} + - -X github.com/goplus/llgo/xtool/env.buildDate={{.Date}} + - -X github.com/goplus/llgo/xtool/env/llvm.ldLLVMConfigBin=/usr/lib/llvm-18/bin/llvm-config + env: + - CC=x86_64-linux-gnu-gcc + - CXX=x86_64-linux-gnu-g++ + - CGO_CPPFLAGS=--sysroot={{.Env.SYSROOT_LINUX_AMD64}} -I{{.Env.SYSROOT_LINUX_AMD64}}/usr/include/llvm-18 -I{{.Env.SYSROOT_LINUX_AMD64}}/usr/include/llvm-c-18 -D_GNU_SOURCE -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS + - CGO_LDFLAGS=--sysroot={{.Env.SYSROOT_LINUX_AMD64}} -L{{.Env.SYSROOT_LINUX_AMD64}}/usr/lib/llvm-18/lib -lLLVM-18 + targets: + - linux_amd64 + mod_timestamp: "{{.CommitTimestamp}}" + - id: llgo-linux-arm64 + main: ./cmd/llgo + flags: + - -tags=linux,arm64,byollvm + ldflags: + - -X github.com/goplus/llgo/xtool/env.buildVersion=v{{.Version}} + - -X github.com/goplus/llgo/xtool/env.buildDate={{.Date}} + - -X github.com/goplus/llgo/xtool/env/llvm.ldLLVMConfigBin=/usr/lib/llvm-18/bin/llvm-config + env: + - CC=aarch64-linux-gnu-gcc + - CXX=aarch64-linux-gnu-g++ + - CGO_CPPFLAGS=--sysroot={{.Env.SYSROOT_LINUX_ARM64}} -I{{.Env.SYSROOT_LINUX_ARM64}}/usr/include/llvm-18 -I{{.Env.SYSROOT_LINUX_ARM64}}/usr/include/llvm-c-18 -D_GNU_SOURCE -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS + - CGO_LDFLAGS=--sysroot={{.Env.SYSROOT_LINUX_ARM64}} -L{{.Env.SYSROOT_LINUX_ARM64}}/usr/lib/llvm-18/lib -lLLVM-18 + targets: + - linux_arm64 + mod_timestamp: "{{.CommitTimestamp}}" + +archives: + - format: tar.gz + name_template: >- + {{.ProjectName}}{{.Version}}.{{.Os}}-{{.Arch}} + {{- if .Arm}}v{{.Arm}}{{end}} + files: + - LICENSE + - README.md + +checksum: + name_template: "{{.ProjectName}}{{.Version}}.checksums.txt" + +nfpms: + - package_name: llgo + vendor: goplus + homepage: https://github.com/goplus/llgo + maintainer: Aofei Sheng + description: | + LLGo is a Go compiler based on LLVM in order to better integrate Go with the C ecosystem including Python. It's a + subproject of the Go+ project. + + LLGo aims to expand the boundaries of Go/Go+, providing limitless possibilities such as: + + - Game development + - AI and data science + - WebAssembly + - Embedded development + - ... + license: Apache-2.0 + formats: + - deb + - rpm + file_name_template: >- + {{.ProjectName}}{{.Version}}.{{.Os}}-{{.Arch}} + {{- if .Arm}}v{{.Arm}}{{end}} + bindir: /usr/local/bin + +snapcrafts: + - name: llgo + title: A Go compiler based on LLVM + summary: A Go compiler based on LLVM + description: | + LLGo is a Go compiler based on LLVM in order to better integrate Go with the C ecosystem including Python. It's a + subproject of the Go+ project. + + LLGo aims to expand the boundaries of Go/Go+, providing limitless possibilities such as: + + - Game development + - AI and data science + - WebAssembly + - Embedded development + - ... + license: Apache-2.0 + confinement: classic + name_template: >- + {{.ProjectName}}{{.Version}}.{{.Os}}-{{.Arch}} + {{- if .Arm}}v{{.Arm}}{{end}} + +snapshot: + name_template: '{{trimprefix .Summary "v"}}' + +release: + prerelease: auto