Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 28 additions & 8 deletions .github/actions/setup-deps/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ inputs:
description: "LLVM version to install"
required: true
default: "19"
install-llvm:
description: "Whether to install LLVM"
required: false
default: "true"

runs:
using: "composite"
Expand All @@ -14,9 +18,17 @@ runs:
shell: bash
run: |
brew update
brew install llvm@${{inputs.llvm-version}} lld@${{inputs.llvm-version}} bdw-gc openssl libffi libuv
brew link --overwrite llvm@${{inputs.llvm-version}} lld@${{inputs.llvm-version}} libffi
echo "$(brew --prefix llvm@${{inputs.llvm-version}})/bin" >> $GITHUB_PATH

# Install LLVM if requested
if [[ "${{ inputs.install-llvm }}" == "true" ]]; then
brew install llvm@${{inputs.llvm-version}} lld@${{inputs.llvm-version}}
brew link --overwrite llvm@${{inputs.llvm-version}} lld@${{inputs.llvm-version}}
echo "$(brew --prefix llvm@${{inputs.llvm-version}})/bin" >> $GITHUB_PATH
fi

# Install common dependencies
brew install bdw-gc openssl libffi libuv
brew link --overwrite libffi

# Install optional deps for demos.
#
Expand All @@ -31,11 +43,19 @@ runs:
if: runner.os == 'Linux'
shell: bash
run: |
echo "deb http://apt.llvm.org/$(lsb_release -cs)/ llvm-toolchain-$(lsb_release -cs)-${{inputs.llvm-version}} main" | sudo tee /etc/apt/sources.list.d/llvm.list
wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add -
sudo apt-get update
sudo apt-get install -y llvm-${{inputs.llvm-version}}-dev clang-${{inputs.llvm-version}} libclang-${{inputs.llvm-version}}-dev lld-${{inputs.llvm-version}} libunwind-${{inputs.llvm-version}}-dev libc++-${{inputs.llvm-version}}-dev pkg-config libgc-dev libssl-dev zlib1g-dev libffi-dev libcjson-dev libuv1-dev
echo "PATH=/usr/lib/llvm-${{inputs.llvm-version}}/bin:$PATH" >> $GITHUB_ENV
# Install LLVM if requested
if [[ "${{ inputs.install-llvm }}" == "true" ]]; then
echo "deb http://apt.llvm.org/$(lsb_release -cs)/ llvm-toolchain-$(lsb_release -cs)-${{inputs.llvm-version}} main" | sudo tee /etc/apt/sources.list.d/llvm.list
wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add -
sudo apt-get update
sudo apt-get install -y llvm-${{inputs.llvm-version}}-dev clang-${{inputs.llvm-version}} libclang-${{inputs.llvm-version}}-dev lld-${{inputs.llvm-version}} libunwind-${{inputs.llvm-version}}-dev libc++-${{inputs.llvm-version}}-dev
echo "PATH=/usr/lib/llvm-${{inputs.llvm-version}}/bin:$PATH" >> $GITHUB_ENV
else
sudo apt-get update
fi

# Install common dependencies
sudo apt-get install -y pkg-config libgc-dev libssl-dev zlib1g-dev libffi-dev libcjson-dev libuv1-dev

# Install optional deps for demos.
#
Expand Down
3 changes: 3 additions & 0 deletions .github/actions/setup-goreleaser/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,6 @@ runs:
- name: Check file
run: tree .sysroot
shell: bash
- name: Get Esp clang
run: bash .github/workflows/download_esp_clang.sh
shell: bash
14 changes: 12 additions & 2 deletions .github/actions/test-helloworld/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ runs:
Hello, LLGo!
Hello, LLGo!
Hello LLGo by cpp/std.Str"
OUTPUT=$(llgo run . 2>&1)
OUTPUT=$(llgo run . 2>&1 | tee /dev/stderr)
if echo "$OUTPUT" | grep -qF "$EXPECTED"; then
echo "Basic test passed"
else
Expand All @@ -50,4 +50,14 @@ runs:
exit 1
fi

#TODO(zzy): Test embed targets, need dispatch target dir
cd ../..
mkdir -p _test/emb && cd _test/emb
cat > main.go << 'EOL'
package main

func main() {
}
EOL
llgo build -v -target esp32-coreboard-v2 -o demo.out .
test -f demo.out.elf && echo "ESP32 cross-compilation test passed: demo.out.elf generated"
exit $?
67 changes: 67 additions & 0 deletions .github/workflows/download_esp_clang.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
#!/bin/bash
set -e

ESP_CLANG_VERSION="19.1.2_20250905-3"
BASE_URL="https://github.com/goplus/espressif-llvm-project-prebuilt/releases/download/${ESP_CLANG_VERSION}"

get_esp_clang_platform() {
local platform="$1"
local os="${platform%-*}"
local arch="${platform##*-}"

case "${os}" in
"darwin")
case "${arch}" in
"amd64") echo "x86_64-apple-darwin" ;;
"arm64") echo "aarch64-apple-darwin" ;;
*) echo "Error: Unsupported darwin architecture: ${arch}" >&2; exit 1 ;;
esac
;;
"linux")
case "${arch}" in
"amd64") echo "x86_64-linux-gnu" ;;
"arm64") echo "aarch64-linux-gnu" ;;
*) echo "Error: Unsupported linux architecture: ${arch}" >&2; exit 1 ;;
esac
;;
*)
echo "Error: Unsupported OS: ${os}" >&2
exit 1
;;
esac
}

get_filename() {
local platform="$1"
local platform_suffix=$(get_esp_clang_platform "${platform}")
echo "clang-esp-${ESP_CLANG_VERSION}-${platform_suffix}.tar.xz"
}

download_and_extract() {
local platform="$1"
local os="${platform%-*}"
local arch="${platform##*-}"
local filename=$(get_filename "${platform}")
local download_url="${BASE_URL}/${filename}"

echo "Downloading ESP Clang for ${platform}..."
echo " URL: ${download_url}"

mkdir -p ".sysroot/${os}/${arch}/crosscompile/clang"
curl -fsSL "${download_url}" | tar -xJ -C ".sysroot/${os}/${arch}/crosscompile/clang" --strip-components=1

if [[ ! -f ".sysroot/${os}/${arch}/crosscompile/clang/bin/clang++" ]]; then
echo "Error: clang++ not found in ${platform} toolchain"
exit 1
fi

echo "${platform} ESP Clang ready in .sysroot/${os}/${arch}/crosscompile/clang"
}

echo "Downloading ESP Clang toolchain version ${ESP_CLANG_VERSION}..."

for platform in "darwin-amd64" "darwin-arm64" "linux-amd64" "linux-arm64"; do
download_and_extract "${platform}"
done

echo "ESP Clang toolchain completed successfully!"
10 changes: 6 additions & 4 deletions .github/workflows/release-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ jobs:
LINUX_KEY="linux-sysroot-${{ hashFiles('.github/workflows/populate_linux_sysroot.sh', '.github/workflows/release-build.yml') }}-v1.0.0"
echo "darwin-key=$DARWIN_KEY" >> $GITHUB_OUTPUT
echo "linux-key=$LINUX_KEY" >> $GITHUB_OUTPUT

populate-darwin-sysroot:
runs-on: macos-latest
timeout-minutes: 30
Expand Down Expand Up @@ -107,7 +106,7 @@ jobs:
-v $(pwd):/go/src/llgo \
-w /go/src/llgo \
ghcr.io/goreleaser/goreleaser-cross:v1.22 \
release --skip=publish,nfpm,snapcraft --snapshot --clean
release --verbose --skip=publish,nfpm,snapcraft --snapshot --clean

- name: Upload Darwin AMD64 Artifacts
uses: actions/upload-artifact@v4
Expand Down Expand Up @@ -179,6 +178,8 @@ jobs:
- uses: actions/checkout@v5
- name: Install dependencies
uses: ./.github/actions/setup-deps
with:
install-llvm: false
- name: Set up Go
uses: actions/setup-go@v5
with:
Expand All @@ -205,7 +206,8 @@ jobs:
mod-version: ${{ matrix.go-mod-version }}

release:
needs: [setup, build, test-artifacts]
needs:
[setup, test-artifacts, populate-darwin-sysroot, populate-linux-sysroot]
runs-on: ubuntu-latest
if: startsWith(github.ref, 'refs/tags/')
steps:
Expand All @@ -231,4 +233,4 @@ jobs:
-v $(pwd):/go/src/llgo \
-w /go/src/llgo \
ghcr.io/goreleaser/goreleaser-cross:v1.22 \
release --clean --skip nfpm,snapcraft
release --clean --verbose --skip nfpm,snapcraft
30 changes: 17 additions & 13 deletions .goreleaser.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,11 @@ builds:
ldflags:
- -X github.com/goplus/llgo/internal/env.buildVersion=v{{.Version}}
- -X github.com/goplus/llgo/internal/env.buildTime={{.Date}}
- -X github.com/goplus/llgo/xtool/env/llvm.ldLLVMConfigBin=/usr/local/opt/llvm@19/bin/llvm-config
env:
- CC=o64-clang
- CXX=o64-clang++
- CGO_CPPFLAGS=-I{{.Env.SYSROOT_DARWIN_AMD64}}/usr/local/opt/llvm@19/include -mmacosx-version-min=10.13 -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS
- CGO_LDFLAGS=-L{{.Env.SYSROOT_DARWIN_AMD64}}/usr/local/opt/llvm@19/lib -mmacosx-version-min=10.13 -Wl,-search_paths_first -Wl,-headerpad_max_install_names -lLLVM-19 -lz -lm
- CGO_CPPFLAGS=-I{{.Env.SYSROOT_DARWIN_AMD64}}/crosscompile/clang/include -mmacosx-version-min=10.13 -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS
- CGO_LDFLAGS=-L{{.Env.SYSROOT_DARWIN_AMD64}}/crosscompile/clang/lib -mmacosx-version-min=10.13 -Wl,-search_paths_first -Wl,-headerpad_max_install_names -lLLVM-19 -lz -lm -Wl,-rpath,@executable_path/../crosscompile/clang/lib
targets:
- darwin_amd64
mod_timestamp: "{{.CommitTimestamp}}"
Expand All @@ -40,12 +39,11 @@ builds:
ldflags:
- -X github.com/goplus/llgo/internal/env.buildVersion=v{{.Version}}
- -X github.com/goplus/llgo/internal/env.buildTime={{.Date}}
- -X github.com/goplus/llgo/xtool/env/llvm.ldLLVMConfigBin=/opt/homebrew/opt/llvm@19/bin/llvm-config
env:
- CC=oa64-clang
- CXX=oa64-clang++
- CGO_CPPFLAGS=-I{{.Env.SYSROOT_DARWIN_ARM64}}/opt/homebrew/opt/llvm@19/include -mmacosx-version-min=10.13 -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS
- CGO_LDFLAGS=-L{{.Env.SYSROOT_DARWIN_ARM64}}/opt/homebrew/opt/llvm@19/lib -mmacosx-version-min=10.13 -Wl,-search_paths_first -Wl,-headerpad_max_install_names -lLLVM-19 -lz -lm
- CGO_CPPFLAGS=-I{{.Env.SYSROOT_DARWIN_ARM64}}/crosscompile/clang/include -mmacosx-version-min=10.13 -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS
- CGO_LDFLAGS=-L{{.Env.SYSROOT_DARWIN_ARM64}}/crosscompile/clang/lib -mmacosx-version-min=10.13 -Wl,-search_paths_first -Wl,-headerpad_max_install_names -lLLVM-19 -lz -lm -Wl,-rpath,@executable_path/../crosscompile/clang/lib
targets:
- darwin_arm64
mod_timestamp: "{{.CommitTimestamp}}"
Expand All @@ -57,12 +55,13 @@ builds:
ldflags:
- -X github.com/goplus/llgo/internal/env.buildVersion=v{{.Version}}
- -X github.com/goplus/llgo/internal/env.buildTime={{.Date}}
- -X github.com/goplus/llgo/xtool/env/llvm.ldLLVMConfigBin=/usr/lib/llvm-19/bin/llvm-config
- '-extldflags=-Wl,-rpath,$ORIGIN/../crosscompile/clang/lib'
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-19 -I{{.Env.SYSROOT_LINUX_AMD64}}/usr/include/llvm-c-19 -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-19/lib -lLLVM-19
- CGO_CPPFLAGS=--sysroot={{.Env.SYSROOT_LINUX_AMD64}} -I{{.Env.SYSROOT_LINUX_AMD64}}/crosscompile/clang/include -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}}/crosscompile/clang/lib -lLLVM-19
- CGO_LDFLAGS_ALLOW=--sysroot.*
targets:
- linux_amd64
mod_timestamp: "{{.CommitTimestamp}}"
Expand All @@ -74,12 +73,13 @@ builds:
ldflags:
- -X github.com/goplus/llgo/internal/env.buildVersion=v{{.Version}}
- -X github.com/goplus/llgo/internal/env.buildTime={{.Date}}
- -X github.com/goplus/llgo/xtool/env/llvm.ldLLVMConfigBin=/usr/lib/llvm-19/bin/llvm-config
- '-extldflags=-Wl,-rpath,$ORIGIN/../crosscompile/clang/lib'
Copy link
Member Author

@luoliwoshang luoliwoshang Sep 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NOTE:To avoid $ORIGIN being unexpectedly escaped in yml, it needs to be added in -extldflags

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-19 -I{{.Env.SYSROOT_LINUX_ARM64}}/usr/include/llvm-c-19 -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-19/lib -lLLVM-19
- CGO_CPPFLAGS=--sysroot={{.Env.SYSROOT_LINUX_ARM64}} -I{{.Env.SYSROOT_LINUX_ARM64}}/crosscompile/clang/include -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}}/crosscompile/clang/lib -lLLVM-19
- CGO_LDFLAGS_ALLOW=--sysroot.*
targets:
- linux_arm64
mod_timestamp: "{{.CommitTimestamp}}"
Expand All @@ -93,7 +93,11 @@ archives:
- LICENSE
- README.md
- runtime

- targets
- src: ".sysroot/{{.Os}}/{{.Arch}}/crosscompile/clang"
dst: crosscompile/clang
info:
mode: 0755
checksum:
name_template: "{{.ProjectName}}{{.Version}}.checksums.txt"

Expand Down
7 changes: 4 additions & 3 deletions internal/crosscompile/crosscompile.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
"github.com/goplus/llgo/internal/flash"
"github.com/goplus/llgo/internal/targets"
"github.com/goplus/llgo/internal/xtool/llvm"
envllvm "github.com/goplus/llgo/xtool/env/llvm"
)

type Export struct {
Expand Down Expand Up @@ -48,8 +49,8 @@ var (
)

var (
espClangBaseUrl = "https://github.com/goplus/espressif-llvm-project-prebuilt/releases/download/19.1.2_20250820"
espClangVersion = "19.1.2_20250820"
espClangBaseUrl = "https://github.com/goplus/espressif-llvm-project-prebuilt/releases/download/19.1.2_20250905-3"
espClangVersion = "19.1.2_20250905-3"
)

// cacheRoot can be overridden for testing
Expand Down Expand Up @@ -108,7 +109,7 @@ func getESPClangRoot(forceEspClang bool) (clangRoot string, err error) {
llgoRoot := env.LLGoROOT()

// First check if clang exists in LLGoROOT
espClangRoot := filepath.Join(llgoRoot, "crosscompile", "clang")
espClangRoot := filepath.Join(llgoRoot, envllvm.CrosscompileClangPath)
if _, err = os.Stat(espClangRoot); err == nil {
clangRoot = espClangRoot
return
Expand Down
2 changes: 1 addition & 1 deletion internal/crosscompile/fetch_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -605,7 +605,7 @@ func TestESPClangDownloadWhenNotExists(t *testing.T) {
}

server := createTestServer(t, map[string]string{
"clang-esp-19.1.2_20250820-linux.tar.xz": string(archiveContent),
fmt.Sprintf("clang-esp-%s-linux.tar.xz", espClangVersion): string(archiveContent),
})
defer server.Close()

Expand Down
15 changes: 15 additions & 0 deletions xtool/env/llvm/llvm.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
"path/filepath"
"strings"

"github.com/goplus/llgo/internal/env"
"github.com/goplus/llgo/xtool/clang"
"github.com/goplus/llgo/xtool/llvm/install_name_tool"
"github.com/goplus/llgo/xtool/llvm/llvmlink"
Expand All @@ -30,6 +31,13 @@ import (

// -----------------------------------------------------------------------------

const (
// CrosscompileClangPath is the relative path from LLGO_ROOT to the clang installation
CrosscompileClangPath = "crosscompile/clang"
)

// -----------------------------------------------------------------------------

// defaultLLVMConfigBin returns the default path to the llvm-config binary. It
// checks the LLVM_CONFIG environment variable first, then searches in PATH. If
// not found, it returns [ldLLVMConfigBin] as a last resort.
Expand All @@ -42,6 +50,13 @@ func defaultLLVMConfigBin() string {
if bin != "" {
return bin
}

llgoRoot := env.LLGoROOT()
// Check LLGO_ROOT/crosscompile/clang for llvm-config
crossLLVMConfigBin := filepath.Join(llgoRoot, CrosscompileClangPath, "bin", "llvm-config")
if _, err := os.Stat(crossLLVMConfigBin); err == nil {
return crossLLVMConfigBin
}
return ldLLVMConfigBin
}

Expand Down
Loading