From 66bf801fd648a0dd7193d24272f7ea05242a7809 Mon Sep 17 00:00:00 2001 From: luoliwoshang <2643523683@qq.com> Date: Mon, 8 Sep 2025 09:40:43 +0800 Subject: [PATCH 01/29] internal/crosscompile:update clang with older glibc & more same size --- internal/crosscompile/crosscompile.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/crosscompile/crosscompile.go b/internal/crosscompile/crosscompile.go index c128d8f1..09264cf0 100644 --- a/internal/crosscompile/crosscompile.go +++ b/internal/crosscompile/crosscompile.go @@ -43,8 +43,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 From d2a021ceae3624c992d643c562cf9a374601638e Mon Sep 17 00:00:00 2001 From: luoliwoshang <2643523683@qq.com> Date: Mon, 8 Sep 2025 10:02:27 +0800 Subject: [PATCH 02/29] test:with esp-clang version --- internal/crosscompile/fetch_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/crosscompile/fetch_test.go b/internal/crosscompile/fetch_test.go index d5e4bc57..9be771dd 100644 --- a/internal/crosscompile/fetch_test.go +++ b/internal/crosscompile/fetch_test.go @@ -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() From bb89ef5c5de5b6276d9634f587a7993dcad3c22f Mon Sep 17 00:00:00 2001 From: luoliwoshang <2643523683@qq.com> Date: Mon, 8 Sep 2025 17:44:46 +0800 Subject: [PATCH 03/29] ci:refresh ci .sysroot cache key --- .github/workflows/release-build.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/release-build.yml b/.github/workflows/release-build.yml index 49399c70..4c14fc00 100644 --- a/.github/workflows/release-build.yml +++ b/.github/workflows/release-build.yml @@ -23,8 +23,8 @@ jobs: - name: Calculate cache keys id: cache-keys run: | - DARWIN_KEY="darwin-sysroot-${{ hashFiles('.github/workflows/populate_darwin_sysroot.sh', '.github/workflows/release-build.yml') }}" - LINUX_KEY="linux-sysroot-${{ hashFiles('.github/workflows/populate_linux_sysroot.sh', '.github/workflows/release-build.yml') }}" + DARWIN_KEY="darwin-sysroot-${{ hashFiles('.github/workflows/populate_darwin_sysroot.sh', '.github/workflows/release-build.yml') }}-v1.0.0" + 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 From 9cea3226db9f5a1a1192c19b73ff0e8125a7d008 Mon Sep 17 00:00:00 2001 From: luoliwoshang <2643523683@qq.com> Date: Mon, 8 Sep 2025 19:07:12 +0800 Subject: [PATCH 04/29] ci:fail when docker start error --- .github/workflows/populate_linux_sysroot.sh | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/populate_linux_sysroot.sh b/.github/workflows/populate_linux_sysroot.sh index 7c976c33..b41d3252 100755 --- a/.github/workflows/populate_linux_sysroot.sh +++ b/.github/workflows/populate_linux_sysroot.sh @@ -139,7 +139,10 @@ populate_linux_sysroot() { /populate_linux_sysroot.sh } populate_linux_sysroot amd64 "${LINUX_AMD64_PREFIX}" & +PID1=$! populate_linux_sysroot arm64 "${LINUX_ARM64_PREFIX}" & +PID2=$! # Wait for both background processes to complete -wait +wait $PID1 || exit $? +wait $PID2 || exit $? From a19011897c61eac0e9614c2819981efb33827bbc Mon Sep 17 00:00:00 2001 From: luoliwoshang <2643523683@qq.com> Date: Mon, 8 Sep 2025 22:43:24 +0800 Subject: [PATCH 05/29] install with esp-clang & new cache key --- .github/actions/setup-goreleaser/action.yml | 3 + .github/workflows/download_esp_clang.sh | 67 +++++++++++++++++++++ .github/workflows/release-build.yml | 7 +-- .goreleaser.yaml | 41 +++++++++---- internal/crosscompile/crosscompile.go | 4 +- internal/crosscompile/fetch_test.go | 2 +- 6 files changed, 105 insertions(+), 19 deletions(-) create mode 100755 .github/workflows/download_esp_clang.sh diff --git a/.github/actions/setup-goreleaser/action.yml b/.github/actions/setup-goreleaser/action.yml index d4ef8665..644388db 100644 --- a/.github/actions/setup-goreleaser/action.yml +++ b/.github/actions/setup-goreleaser/action.yml @@ -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 diff --git a/.github/workflows/download_esp_clang.sh b/.github/workflows/download_esp_clang.sh new file mode 100755 index 00000000..5ea6a764 --- /dev/null +++ b/.github/workflows/download_esp_clang.sh @@ -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!" diff --git a/.github/workflows/release-build.yml b/.github/workflows/release-build.yml index 4c14fc00..56c6e0e7 100644 --- a/.github/workflows/release-build.yml +++ b/.github/workflows/release-build.yml @@ -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 @@ -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 --parallelism=1 --skip=publish,nfpm,snapcraft --snapshot --clean - name: Upload Darwin AMD64 Artifacts uses: actions/upload-artifact@v4 @@ -205,7 +204,7 @@ jobs: mod-version: ${{ matrix.go-mod-version }} release: - needs: [setup, build, test-artifacts] + needs: [setup, test-artifacts] runs-on: ubuntu-latest if: startsWith(github.ref, 'refs/tags/') steps: @@ -231,4 +230,4 @@ jobs: -v $(pwd):/go/src/llgo \ -w /go/src/llgo \ ghcr.io/goreleaser/goreleaser-cross:v1.22 \ - release --clean --skip nfpm,snapcraft + release --parallelism=1 --clean --verbose --skip nfpm,snapcraft diff --git a/.goreleaser.yaml b/.goreleaser.yaml index 4a42dbe3..7bf527e1 100644 --- a/.goreleaser.yaml +++ b/.goreleaser.yaml @@ -18,68 +18,84 @@ builds: - id: llgo-darwin-amd64 main: ./cmd/llgo binary: bin/llgo + hooks: + pre: + - rm -rf crosscompile + - cp -r .sysroot/darwin/amd64/crosscompile . flags: - -tags=darwin,amd64,byollvm 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 + - -X github.com/goplus/llgo/xtool/env/llvm.ldLLVMConfigBin=../crosscompile/clang/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.PWD}}/crosscompile/clang/include -mmacosx-version-min=10.13 -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS + - CGO_LDFLAGS=-L{{.Env.PWD}}/crosscompile/clang/lib -mmacosx-version-min=10.13 -Wl,-search_paths_first -Wl,-headerpad_max_install_names -lLLVM-19 -lz -lm targets: - darwin_amd64 mod_timestamp: "{{.CommitTimestamp}}" - id: llgo-darwin-arm64 main: ./cmd/llgo binary: bin/llgo + hooks: + pre: + - rm -rf crosscompile + - cp -r .sysroot/darwin/arm64/crosscompile . flags: - -tags=darwin,arm64,byollvm 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 + - -X github.com/goplus/llgo/xtool/env/llvm.ldLLVMConfigBin=../crosscompile/clang/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.PWD}}/crosscompile/clang/include -mmacosx-version-min=10.13 -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS + - CGO_LDFLAGS=-L{{.Env.PWD}}/crosscompile/clang/lib -mmacosx-version-min=10.13 -Wl,-search_paths_first -Wl,-headerpad_max_install_names -lLLVM-19 -lz -lm targets: - darwin_arm64 mod_timestamp: "{{.CommitTimestamp}}" - id: llgo-linux-amd64 main: ./cmd/llgo binary: bin/llgo + hooks: + pre: + - rm -rf crosscompile + - cp -r .sysroot/linux/amd64/crosscompile . flags: - -tags=linux,amd64,byollvm 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 + - -X github.com/goplus/llgo/xtool/env/llvm.ldLLVMConfigBin=../crosscompile/clang/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-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=-I{{.Env.PWD}}/crosscompile/clang/include -D_GNU_SOURCE -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS + - CGO_LDFLAGS=-L{{.Env.PWD}}/crosscompile/clang/lib -lLLVM-19 targets: - linux_amd64 mod_timestamp: "{{.CommitTimestamp}}" - id: llgo-linux-arm64 main: ./cmd/llgo binary: bin/llgo + hooks: + pre: + - rm -rf crosscompile + - cp -r .sysroot/linux/arm64/crosscompile . flags: - -tags=linux,arm64,byollvm 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 + - -X github.com/goplus/llgo/xtool/env/llvm.ldLLVMConfigBin=../crosscompile/clang/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-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=-I{{.Env.PWD}}/crosscompile/clang/include -D_GNU_SOURCE -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS + - CGO_LDFLAGS=-L{{.Env.PWD}}/crosscompile/clang/lib -lLLVM-19 targets: - linux_arm64 mod_timestamp: "{{.CommitTimestamp}}" @@ -93,6 +109,7 @@ archives: - LICENSE - README.md - runtime + - crosscompile checksum: name_template: "{{.ProjectName}}{{.Version}}.checksums.txt" diff --git a/internal/crosscompile/crosscompile.go b/internal/crosscompile/crosscompile.go index fbd8962a..8c0bf788 100644 --- a/internal/crosscompile/crosscompile.go +++ b/internal/crosscompile/crosscompile.go @@ -48,8 +48,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 diff --git a/internal/crosscompile/fetch_test.go b/internal/crosscompile/fetch_test.go index d5e4bc57..9be771dd 100644 --- a/internal/crosscompile/fetch_test.go +++ b/internal/crosscompile/fetch_test.go @@ -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() From 848432ea6865748cda7904c3fa5b440c9c0c1ce9 Mon Sep 17 00:00:00 2001 From: luoliwoshang <2643523683@qq.com> Date: Mon, 8 Sep 2025 22:53:39 +0800 Subject: [PATCH 06/29] ci:sysroot for linux --- .goreleaser.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.goreleaser.yaml b/.goreleaser.yaml index 7bf527e1..365d68ba 100644 --- a/.goreleaser.yaml +++ b/.goreleaser.yaml @@ -73,8 +73,8 @@ builds: env: - CC=x86_64-linux-gnu-gcc - CXX=x86_64-linux-gnu-g++ - - CGO_CPPFLAGS=-I{{.Env.PWD}}/crosscompile/clang/include -D_GNU_SOURCE -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS - - CGO_LDFLAGS=-L{{.Env.PWD}}/crosscompile/clang/lib -lLLVM-19 + - CGO_CPPFLAGS=--sysroot={{.Env.SYSROOT_LINUX_AMD64}} -I{{.Env.PWD}}/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.PWD}}/crosscompile/clang/lib -lLLVM-19 targets: - linux_amd64 mod_timestamp: "{{.CommitTimestamp}}" @@ -94,8 +94,8 @@ builds: env: - CC=aarch64-linux-gnu-gcc - CXX=aarch64-linux-gnu-g++ - - CGO_CPPFLAGS=-I{{.Env.PWD}}/crosscompile/clang/include -D_GNU_SOURCE -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS - - CGO_LDFLAGS=-L{{.Env.PWD}}/crosscompile/clang/lib -lLLVM-19 + - CGO_CPPFLAGS=--sysroot={{.Env.SYSROOT_LINUX_ARM64}} -I{{.Env.PWD}}/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.PWD}}/crosscompile/clang/lib -lLLVM-19 targets: - linux_arm64 mod_timestamp: "{{.CommitTimestamp}}" From 2a022be5108169776063de0d997065a47dfc8b03 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 9 Sep 2025 00:44:54 +0000 Subject: [PATCH 07/29] build(deps): bump actions/setup-go from 5 to 6 Bumps [actions/setup-go](https://github.com/actions/setup-go) from 5 to 6. - [Release notes](https://github.com/actions/setup-go/releases) - [Commits](https://github.com/actions/setup-go/compare/v5...v6) --- updated-dependencies: - dependency-name: actions/setup-go dependency-version: '6' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/release-build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release-build.yml b/.github/workflows/release-build.yml index 49399c70..1df5917a 100644 --- a/.github/workflows/release-build.yml +++ b/.github/workflows/release-build.yml @@ -180,7 +180,7 @@ jobs: - name: Install dependencies uses: ./.github/actions/setup-deps - name: Set up Go - uses: actions/setup-go@v5 + uses: actions/setup-go@v6 with: go-version: ${{ matrix.go-version }} - name: Download Platform Artifact From 13b5f39125f6ebdd91757ba209f97da829483d4e Mon Sep 17 00:00:00 2001 From: luoliwoshang <2643523683@qq.com> Date: Mon, 8 Sep 2025 19:07:12 +0800 Subject: [PATCH 08/29] ci:fail when docker start error --- .github/workflows/populate_linux_sysroot.sh | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/populate_linux_sysroot.sh b/.github/workflows/populate_linux_sysroot.sh index 7c976c33..b41d3252 100755 --- a/.github/workflows/populate_linux_sysroot.sh +++ b/.github/workflows/populate_linux_sysroot.sh @@ -139,7 +139,10 @@ populate_linux_sysroot() { /populate_linux_sysroot.sh } populate_linux_sysroot amd64 "${LINUX_AMD64_PREFIX}" & +PID1=$! populate_linux_sysroot arm64 "${LINUX_ARM64_PREFIX}" & +PID2=$! # Wait for both background processes to complete -wait +wait $PID1 || exit $? +wait $PID2 || exit $? From 68623f0b2746e53ffae58a10fa2f9f42eba7c198 Mon Sep 17 00:00:00 2001 From: luoliwoshang <2643523683@qq.com> Date: Tue, 9 Sep 2025 10:16:39 +0800 Subject: [PATCH 09/29] env:find crosscompile llvm --- .goreleaser.yaml | 4 ---- internal/crosscompile/crosscompile.go | 3 ++- xtool/env/llvm/llvm.go | 18 +++++++++++++++--- 3 files changed, 17 insertions(+), 8 deletions(-) diff --git a/.goreleaser.yaml b/.goreleaser.yaml index 365d68ba..10fbc007 100644 --- a/.goreleaser.yaml +++ b/.goreleaser.yaml @@ -27,7 +27,6 @@ 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=../crosscompile/clang/bin/llvm-config env: - CC=o64-clang - CXX=o64-clang++ @@ -48,7 +47,6 @@ 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=../crosscompile/clang/bin/llvm-config env: - CC=oa64-clang - CXX=oa64-clang++ @@ -69,7 +67,6 @@ 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=../crosscompile/clang/bin/llvm-config env: - CC=x86_64-linux-gnu-gcc - CXX=x86_64-linux-gnu-g++ @@ -90,7 +87,6 @@ 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=../crosscompile/clang/bin/llvm-config env: - CC=aarch64-linux-gnu-gcc - CXX=aarch64-linux-gnu-g++ diff --git a/internal/crosscompile/crosscompile.go b/internal/crosscompile/crosscompile.go index 8c0bf788..5b31aea8 100644 --- a/internal/crosscompile/crosscompile.go +++ b/internal/crosscompile/crosscompile.go @@ -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 { @@ -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 diff --git a/xtool/env/llvm/llvm.go b/xtool/env/llvm/llvm.go index a34757c9..6bea3099 100644 --- a/xtool/env/llvm/llvm.go +++ b/xtool/env/llvm/llvm.go @@ -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" @@ -30,9 +31,13 @@ import ( // ----------------------------------------------------------------------------- -// 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. +const ( + // CrosscompileClangPath is the relative path from LLGO_ROOT to the clang installation + CrosscompileClangPath = "crosscompile/clang" +) + +// ----------------------------------------------------------------------------- + func defaultLLVMConfigBin() string { bin := os.Getenv("LLVM_CONFIG") if bin != "" { @@ -42,6 +47,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 } From 0340ef2a75b20ead4352c57a3a45c6b68c29946e Mon Sep 17 00:00:00 2001 From: luoliwoshang <2643523683@qq.com> Date: Tue, 9 Sep 2025 11:06:17 +0800 Subject: [PATCH 10/29] goreleaser:move clang to result --- .github/workflows/release-build.yml | 4 +-- .goreleaser.yaml | 39 ++++++++++------------------- 2 files changed, 15 insertions(+), 28 deletions(-) diff --git a/.github/workflows/release-build.yml b/.github/workflows/release-build.yml index 56c6e0e7..99f990d0 100644 --- a/.github/workflows/release-build.yml +++ b/.github/workflows/release-build.yml @@ -106,7 +106,7 @@ jobs: -v $(pwd):/go/src/llgo \ -w /go/src/llgo \ ghcr.io/goreleaser/goreleaser-cross:v1.22 \ - release --verbose --parallelism=1 --skip=publish,nfpm,snapcraft --snapshot --clean + release --verbose --skip=publish,nfpm,snapcraft --snapshot --clean - name: Upload Darwin AMD64 Artifacts uses: actions/upload-artifact@v4 @@ -230,4 +230,4 @@ jobs: -v $(pwd):/go/src/llgo \ -w /go/src/llgo \ ghcr.io/goreleaser/goreleaser-cross:v1.22 \ - release --parallelism=1 --clean --verbose --skip nfpm,snapcraft + release --clean --verbose --skip nfpm,snapcraft diff --git a/.goreleaser.yaml b/.goreleaser.yaml index 10fbc007..97840e52 100644 --- a/.goreleaser.yaml +++ b/.goreleaser.yaml @@ -18,10 +18,6 @@ builds: - id: llgo-darwin-amd64 main: ./cmd/llgo binary: bin/llgo - hooks: - pre: - - rm -rf crosscompile - - cp -r .sysroot/darwin/amd64/crosscompile . flags: - -tags=darwin,amd64,byollvm ldflags: @@ -30,18 +26,14 @@ builds: env: - CC=o64-clang - CXX=o64-clang++ - - CGO_CPPFLAGS=-I{{.Env.PWD}}/crosscompile/clang/include -mmacosx-version-min=10.13 -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS - - CGO_LDFLAGS=-L{{.Env.PWD}}/crosscompile/clang/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 targets: - darwin_amd64 mod_timestamp: "{{.CommitTimestamp}}" - id: llgo-darwin-arm64 main: ./cmd/llgo binary: bin/llgo - hooks: - pre: - - rm -rf crosscompile - - cp -r .sysroot/darwin/arm64/crosscompile . flags: - -tags=darwin,arm64,byollvm ldflags: @@ -50,18 +42,14 @@ builds: env: - CC=oa64-clang - CXX=oa64-clang++ - - CGO_CPPFLAGS=-I{{.Env.PWD}}/crosscompile/clang/include -mmacosx-version-min=10.13 -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS - - CGO_LDFLAGS=-L{{.Env.PWD}}/crosscompile/clang/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 targets: - darwin_arm64 mod_timestamp: "{{.CommitTimestamp}}" - id: llgo-linux-amd64 main: ./cmd/llgo binary: bin/llgo - hooks: - pre: - - rm -rf crosscompile - - cp -r .sysroot/linux/amd64/crosscompile . flags: - -tags=linux,amd64,byollvm ldflags: @@ -70,18 +58,14 @@ builds: env: - CC=x86_64-linux-gnu-gcc - CXX=x86_64-linux-gnu-g++ - - CGO_CPPFLAGS=--sysroot={{.Env.SYSROOT_LINUX_AMD64}} -I{{.Env.PWD}}/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.PWD}}/crosscompile/clang/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 targets: - linux_amd64 mod_timestamp: "{{.CommitTimestamp}}" - id: llgo-linux-arm64 main: ./cmd/llgo binary: bin/llgo - hooks: - pre: - - rm -rf crosscompile - - cp -r .sysroot/linux/arm64/crosscompile . flags: - -tags=linux,arm64,byollvm ldflags: @@ -90,8 +74,8 @@ builds: env: - CC=aarch64-linux-gnu-gcc - CXX=aarch64-linux-gnu-g++ - - CGO_CPPFLAGS=--sysroot={{.Env.SYSROOT_LINUX_ARM64}} -I{{.Env.PWD}}/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.PWD}}/crosscompile/clang/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 targets: - linux_arm64 mod_timestamp: "{{.CommitTimestamp}}" @@ -105,8 +89,11 @@ archives: - LICENSE - README.md - runtime - - crosscompile - + - src: ".sysroot/{{.Os}}/{{.Arch}}/crosscompile/clang/**/*" + dst: crosscompile/clang + strip_parent: true + info: + mode: 0755 checksum: name_template: "{{.ProjectName}}{{.Version}}.checksums.txt" From 6ce28e4d4e9d60e1d936abc7e891f46d2e3dd9c9 Mon Sep 17 00:00:00 2001 From: luoliwoshang <2643523683@qq.com> Date: Tue, 9 Sep 2025 11:27:39 +0800 Subject: [PATCH 11/29] goreleaser:keep file level --- .goreleaser.yaml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.goreleaser.yaml b/.goreleaser.yaml index 97840e52..52e30391 100644 --- a/.goreleaser.yaml +++ b/.goreleaser.yaml @@ -89,9 +89,8 @@ archives: - LICENSE - README.md - runtime - - src: ".sysroot/{{.Os}}/{{.Arch}}/crosscompile/clang/**/*" + - src: ".sysroot/{{.Os}}/{{.Arch}}/crosscompile/clang" dst: crosscompile/clang - strip_parent: true info: mode: 0755 checksum: From 92beb562bf3dc8e3ae774cad5aeb5840eefc29a2 Mon Sep 17 00:00:00 2001 From: luoliwoshang <2643523683@qq.com> Date: Tue, 9 Sep 2025 11:57:38 +0800 Subject: [PATCH 12/29] goreleaser:relative rpath --- .goreleaser.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.goreleaser.yaml b/.goreleaser.yaml index 52e30391..6a2a3d14 100644 --- a/.goreleaser.yaml +++ b/.goreleaser.yaml @@ -27,7 +27,7 @@ builds: - CC=o64-clang - CXX=o64-clang++ - 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 + - CGO_LDFLAGS=-L{{.Env.SYSROOT_DARWIN_AMD64}}/crosscompile/clang/lib -Wl,-rpath,@executable_path/../crosscompile/clang/lib -mmacosx-version-min=10.13 -Wl,-search_paths_first -Wl,-headerpad_max_install_names -lLLVM-19 -lz -lm targets: - darwin_amd64 mod_timestamp: "{{.CommitTimestamp}}" @@ -43,7 +43,7 @@ builds: - CC=oa64-clang - CXX=oa64-clang++ - 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 + - CGO_LDFLAGS=-L{{.Env.SYSROOT_DARWIN_ARM64}}/crosscompile/clang/lib -Wl,-rpath,@executable_path/../crosscompile/clang/lib -mmacosx-version-min=10.13 -Wl,-search_paths_first -Wl,-headerpad_max_install_names -lLLVM-19 -lz -lm targets: - darwin_arm64 mod_timestamp: "{{.CommitTimestamp}}" @@ -59,7 +59,7 @@ builds: - CC=x86_64-linux-gnu-gcc - CXX=x86_64-linux-gnu-g++ - 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=--sysroot={{.Env.SYSROOT_LINUX_AMD64}} -L{{.Env.SYSROOT_LINUX_AMD64}}/crosscompile/clang/lib -Wl,-rpath,\$ORIGIN/../crosscompile/clang/lib -lLLVM-19 targets: - linux_amd64 mod_timestamp: "{{.CommitTimestamp}}" @@ -75,7 +75,7 @@ builds: - CC=aarch64-linux-gnu-gcc - CXX=aarch64-linux-gnu-g++ - 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=--sysroot={{.Env.SYSROOT_LINUX_ARM64}} -L{{.Env.SYSROOT_LINUX_ARM64}}/crosscompile/clang/lib -Wl,-rpath,\$ORIGIN/../crosscompile/clang/lib -lLLVM-19 targets: - linux_arm64 mod_timestamp: "{{.CommitTimestamp}}" From d0cf57fa95fae0a61f40558394d21f05628e532e Mon Sep 17 00:00:00 2001 From: luoliwoshang <2643523683@qq.com> Date: Tue, 9 Sep 2025 12:03:35 +0800 Subject: [PATCH 13/29] ci:test release without llvm dependency --- .github/actions/setup-deps/action.yml | 36 +++++++++++++++++----- .github/actions/test-helloworld/action.yml | 2 +- .github/workflows/release-build.yml | 2 ++ 3 files changed, 31 insertions(+), 9 deletions(-) diff --git a/.github/actions/setup-deps/action.yml b/.github/actions/setup-deps/action.yml index 7a0669c8..b0bdb4bc 100644 --- a/.github/actions/setup-deps/action.yml +++ b/.github/actions/setup-deps/action.yml @@ -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" @@ -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. # @@ -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. # diff --git a/.github/actions/test-helloworld/action.yml b/.github/actions/test-helloworld/action.yml index 9ce49ef9..f13bb257 100644 --- a/.github/actions/test-helloworld/action.yml +++ b/.github/actions/test-helloworld/action.yml @@ -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 diff --git a/.github/workflows/release-build.yml b/.github/workflows/release-build.yml index 99f990d0..811310d2 100644 --- a/.github/workflows/release-build.yml +++ b/.github/workflows/release-build.yml @@ -178,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: From e05f890b94cb8a45abab0064f3acf45a21110b3e Mon Sep 17 00:00:00 2001 From: luoliwoshang <2643523683@qq.com> Date: Tue, 9 Sep 2025 12:25:39 +0800 Subject: [PATCH 14/29] temp remove origin rpath set --- .goreleaser.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.goreleaser.yaml b/.goreleaser.yaml index 6a2a3d14..2b821608 100644 --- a/.goreleaser.yaml +++ b/.goreleaser.yaml @@ -43,7 +43,7 @@ builds: - CC=oa64-clang - CXX=oa64-clang++ - 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 -Wl,-rpath,@executable_path/../crosscompile/clang/lib -mmacosx-version-min=10.13 -Wl,-search_paths_first -Wl,-headerpad_max_install_names -lLLVM-19 -lz -lm + - 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 targets: - darwin_arm64 mod_timestamp: "{{.CommitTimestamp}}" @@ -75,7 +75,7 @@ builds: - CC=aarch64-linux-gnu-gcc - CXX=aarch64-linux-gnu-g++ - 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 -Wl,-rpath,\$ORIGIN/../crosscompile/clang/lib -lLLVM-19 + - CGO_LDFLAGS=--sysroot={{.Env.SYSROOT_LINUX_ARM64}} -L{{.Env.SYSROOT_LINUX_ARM64}}/crosscompile/clang/lib -lLLVM-19 targets: - linux_arm64 mod_timestamp: "{{.CommitTimestamp}}" From 9f4875320359cf5ac2968adafbdfdbaffd3c7b93 Mon Sep 17 00:00:00 2001 From: luoliwoshang <2643523683@qq.com> Date: Tue, 9 Sep 2025 12:34:36 +0800 Subject: [PATCH 15/29] allow sysroot --- .goreleaser.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.goreleaser.yaml b/.goreleaser.yaml index 2b821608..36808e08 100644 --- a/.goreleaser.yaml +++ b/.goreleaser.yaml @@ -60,6 +60,7 @@ builds: - CXX=x86_64-linux-gnu-g++ - 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 -Wl,-rpath,\$ORIGIN/../crosscompile/clang/lib -lLLVM-19 + - CGO_LDFLAGS_ALLOW=--sysroot.* targets: - linux_amd64 mod_timestamp: "{{.CommitTimestamp}}" @@ -76,6 +77,7 @@ builds: - CXX=aarch64-linux-gnu-g++ - 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}}" From f66bbb7fc348c4ca372e0399b44ae2e4478dbc1a Mon Sep 17 00:00:00 2001 From: luoliwoshang <2643523683@qq.com> Date: Tue, 9 Sep 2025 12:51:34 +0800 Subject: [PATCH 16/29] execute rpath search --- .github/actions/test-helloworld/action.yml | 2 +- .goreleaser.yaml | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/actions/test-helloworld/action.yml b/.github/actions/test-helloworld/action.yml index f13bb257..6ef57444 100644 --- a/.github/actions/test-helloworld/action.yml +++ b/.github/actions/test-helloworld/action.yml @@ -38,7 +38,7 @@ runs: Hello, LLGo! Hello, LLGo! Hello LLGo by cpp/std.Str" - OUTPUT=$(llgo run . 2>&1 | tee /dev/stderr) + OUTPUT=$(llgo run -v . 2>&1 | tee /dev/stderr) if echo "$OUTPUT" | grep -qF "$EXPECTED"; then echo "Basic test passed" else diff --git a/.goreleaser.yaml b/.goreleaser.yaml index 36808e08..681e422b 100644 --- a/.goreleaser.yaml +++ b/.goreleaser.yaml @@ -27,7 +27,7 @@ builds: - CC=o64-clang - CXX=o64-clang++ - 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 -Wl,-rpath,@executable_path/../crosscompile/clang/lib -mmacosx-version-min=10.13 -Wl,-search_paths_first -Wl,-headerpad_max_install_names -lLLVM-19 -lz -lm + - 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}}" @@ -43,7 +43,7 @@ builds: - CC=oa64-clang - CXX=oa64-clang++ - 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 + - 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}}" @@ -59,7 +59,7 @@ builds: - CC=x86_64-linux-gnu-gcc - CXX=x86_64-linux-gnu-g++ - 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 -Wl,-rpath,\$ORIGIN/../crosscompile/clang/lib -lLLVM-19 + - CGO_LDFLAGS=--sysroot={{.Env.SYSROOT_LINUX_AMD64}} -L{{.Env.SYSROOT_LINUX_AMD64}}/crosscompile/clang/lib -lLLVM-19 -Wl,-rpath,\$ORIGIN/../crosscompile/clang/lib - CGO_LDFLAGS_ALLOW=--sysroot.* targets: - linux_amd64 @@ -76,7 +76,7 @@ builds: - CC=aarch64-linux-gnu-gcc - CXX=aarch64-linux-gnu-g++ - 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=--sysroot={{.Env.SYSROOT_LINUX_ARM64}} -L{{.Env.SYSROOT_LINUX_ARM64}}/crosscompile/clang/lib -lLLVM-19 -Wl,-rpath,\$ORIGIN/../crosscompile/clang/lib - CGO_LDFLAGS_ALLOW=--sysroot.* targets: - linux_arm64 From 3be12dce44a9ff79962200d935607e68db080e30 Mon Sep 17 00:00:00 2001 From: luoliwoshang <2643523683@qq.com> Date: Tue, 9 Sep 2025 13:44:11 +0800 Subject: [PATCH 17/29] ci:test helloword with embed target --- .github/actions/test-helloworld/action.yml | 14 ++++++++++++-- .goreleaser.yaml | 1 + 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/.github/actions/test-helloworld/action.yml b/.github/actions/test-helloworld/action.yml index 6ef57444..9020e788 100644 --- a/.github/actions/test-helloworld/action.yml +++ b/.github/actions/test-helloworld/action.yml @@ -38,7 +38,7 @@ runs: Hello, LLGo! Hello, LLGo! Hello LLGo by cpp/std.Str" - OUTPUT=$(llgo run -v . 2>&1 | tee /dev/stderr) + OUTPUT=$(llgo run . 2>&1 | tee /dev/stderr) if echo "$OUTPUT" | grep -qF "$EXPECTED"; then echo "Basic test passed" else @@ -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 $? diff --git a/.goreleaser.yaml b/.goreleaser.yaml index 681e422b..2169ef1d 100644 --- a/.goreleaser.yaml +++ b/.goreleaser.yaml @@ -91,6 +91,7 @@ archives: - LICENSE - README.md - runtime + - targets - src: ".sysroot/{{.Os}}/{{.Arch}}/crosscompile/clang" dst: crosscompile/clang info: From e63ebb8151de00ce9306b4c4dd31109f37f31b26 Mon Sep 17 00:00:00 2001 From: luoliwoshang <2643523683@qq.com> Date: Tue, 9 Sep 2025 15:05:52 +0800 Subject: [PATCH 18/29] goreleaser:avoid fail --- .goreleaser.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.goreleaser.yaml b/.goreleaser.yaml index 2169ef1d..fc8a949f 100644 --- a/.goreleaser.yaml +++ b/.goreleaser.yaml @@ -59,7 +59,7 @@ builds: - CC=x86_64-linux-gnu-gcc - CXX=x86_64-linux-gnu-g++ - 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 -Wl,-rpath,\$ORIGIN/../crosscompile/clang/lib + - CGO_LDFLAGS=--sysroot={{.Env.SYSROOT_LINUX_AMD64}} -L{{.Env.SYSROOT_LINUX_AMD64}}/crosscompile/clang/lib -lLLVM-19 -Wl,-rpath,$ORIGIN/../crosscompile/clang/lib - CGO_LDFLAGS_ALLOW=--sysroot.* targets: - linux_amd64 @@ -76,7 +76,7 @@ builds: - CC=aarch64-linux-gnu-gcc - CXX=aarch64-linux-gnu-g++ - 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 -Wl,-rpath,\$ORIGIN/../crosscompile/clang/lib + - CGO_LDFLAGS=--sysroot={{.Env.SYSROOT_LINUX_ARM64}} -L{{.Env.SYSROOT_LINUX_ARM64}}/crosscompile/clang/lib -lLLVM-19 -Wl,-rpath,$ORIGIN/../crosscompile/clang/lib - CGO_LDFLAGS_ALLOW=--sysroot.* targets: - linux_arm64 From 89af430329189ed379603e5747bd0a4d53dca708 Mon Sep 17 00:00:00 2001 From: visualfc Date: Tue, 9 Sep 2025 11:22:53 +0800 Subject: [PATCH 19/29] cl: embed struct support __llgo_va_list --- cl/_testrt/vamethod/in.go | 32 +++++++++++++++ cl/_testrt/vamethod/out.ll | 79 ++++++++++++++++++++++++++++++++++++++ cl/compile.go | 2 + 3 files changed, 113 insertions(+) create mode 100644 cl/_testrt/vamethod/in.go create mode 100644 cl/_testrt/vamethod/out.ll diff --git a/cl/_testrt/vamethod/in.go b/cl/_testrt/vamethod/in.go new file mode 100644 index 00000000..c2dbea83 --- /dev/null +++ b/cl/_testrt/vamethod/in.go @@ -0,0 +1,32 @@ +package main + +import ( + "unsafe" + _ "unsafe" + + "github.com/goplus/lib/c" +) + +type T c.Char + +//go:linkname Printf C.printf +func Printf(format *c.Char, __llgo_va_list ...any) c.Int + +//llgo:link (*T).Printf C.printf +func (*T) Printf(__llgo_va_list ...any) c.Int { return 0 } + +type CFmt struct { + *T +} + +func (f *CFmt) SetFormat(fmt string) { + f.T = (*T)(unsafe.Pointer(c.AllocaCStr(fmt))) +} + +func main() { + cfmt := &CFmt{} + cfmt.SetFormat("%s (%d)\n") + cfmt.Printf(c.Str("hello"), 100) + cfmt.SetFormat("(%d) %s\n") + cfmt.Printf(200, c.Str("world")) +} diff --git a/cl/_testrt/vamethod/out.ll b/cl/_testrt/vamethod/out.ll new file mode 100644 index 00000000..02eeeffa --- /dev/null +++ b/cl/_testrt/vamethod/out.ll @@ -0,0 +1,79 @@ +; ModuleID = 'github.com/goplus/llgo/cl/_testrt/vamethod' +source_filename = "github.com/goplus/llgo/cl/_testrt/vamethod" + +%"github.com/goplus/llgo/cl/_testrt/vamethod.CFmt" = type { ptr } +%"github.com/goplus/llgo/runtime/internal/runtime.String" = type { ptr, i64 } + +@"github.com/goplus/llgo/cl/_testrt/vamethod.init$guard" = global i1 false, align 1 +@0 = private unnamed_addr constant [8 x i8] c"%s (%d)\0A", align 1 +@1 = private unnamed_addr constant [6 x i8] c"hello\00", align 1 +@2 = private unnamed_addr constant [8 x i8] c"(%d) %s\0A", align 1 +@3 = private unnamed_addr constant [6 x i8] c"world\00", align 1 + +define i32 @"github.com/goplus/llgo/cl/_testrt/vamethod.CFmt.Printf"(%"github.com/goplus/llgo/cl/_testrt/vamethod.CFmt" %0, ...) { +_llgo_0: + %1 = alloca %"github.com/goplus/llgo/cl/_testrt/vamethod.CFmt", align 8 + call void @llvm.memset(ptr %1, i8 0, i64 8, i1 false) + store %"github.com/goplus/llgo/cl/_testrt/vamethod.CFmt" %0, ptr %1, align 8 + %2 = getelementptr inbounds %"github.com/goplus/llgo/cl/_testrt/vamethod.CFmt", ptr %1, i32 0, i32 0 + %3 = load ptr, ptr %2, align 8 + %4 = call i32 (ptr, ...) @printf(ptr %3) + ret i32 %4 +} + +define i32 @"github.com/goplus/llgo/cl/_testrt/vamethod.(*CFmt).Printf"(ptr %0, ...) { +_llgo_0: + %1 = getelementptr inbounds %"github.com/goplus/llgo/cl/_testrt/vamethod.CFmt", ptr %0, i32 0, i32 0 + %2 = load ptr, ptr %1, align 8 + %3 = call i32 (ptr, ...) @printf(ptr %2) + ret i32 %3 +} + +define void @"github.com/goplus/llgo/cl/_testrt/vamethod.(*CFmt).SetFormat"(ptr %0, %"github.com/goplus/llgo/runtime/internal/runtime.String" %1) { +_llgo_0: + %2 = extractvalue %"github.com/goplus/llgo/runtime/internal/runtime.String" %1, 1 + %3 = add i64 %2, 1 + %4 = alloca i8, i64 %3, align 1 + %5 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.CStrCopy"(ptr %4, %"github.com/goplus/llgo/runtime/internal/runtime.String" %1) + %6 = getelementptr inbounds %"github.com/goplus/llgo/cl/_testrt/vamethod.CFmt", ptr %0, i32 0, i32 0 + store ptr %5, ptr %6, align 8 + ret void +} + +define void @"github.com/goplus/llgo/cl/_testrt/vamethod.init"() { +_llgo_0: + %0 = load i1, ptr @"github.com/goplus/llgo/cl/_testrt/vamethod.init$guard", align 1 + br i1 %0, label %_llgo_2, label %_llgo_1 + +_llgo_1: ; preds = %_llgo_0 + store i1 true, ptr @"github.com/goplus/llgo/cl/_testrt/vamethod.init$guard", align 1 + br label %_llgo_2 + +_llgo_2: ; preds = %_llgo_1, %_llgo_0 + ret void +} + +define void @"github.com/goplus/llgo/cl/_testrt/vamethod.main"() { +_llgo_0: + %0 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.AllocZ"(i64 8) + call void @"github.com/goplus/llgo/cl/_testrt/vamethod.(*CFmt).SetFormat"(ptr %0, %"github.com/goplus/llgo/runtime/internal/runtime.String" { ptr @0, i64 8 }) + %1 = getelementptr inbounds %"github.com/goplus/llgo/cl/_testrt/vamethod.CFmt", ptr %0, i32 0, i32 0 + %2 = load ptr, ptr %1, align 8 + %3 = call i32 (ptr, ...) @printf(ptr %2, ptr @1, i64 100) + call void @"github.com/goplus/llgo/cl/_testrt/vamethod.(*CFmt).SetFormat"(ptr %0, %"github.com/goplus/llgo/runtime/internal/runtime.String" { ptr @2, i64 8 }) + %4 = getelementptr inbounds %"github.com/goplus/llgo/cl/_testrt/vamethod.CFmt", ptr %0, i32 0, i32 0 + %5 = load ptr, ptr %4, align 8 + %6 = call i32 (ptr, ...) @printf(ptr %5, i64 200, ptr @3) + ret void +} + +; Function Attrs: nocallback nofree nounwind willreturn memory(argmem: write) +declare void @llvm.memset(ptr nocapture writeonly, i8, i64, i1 immarg) #0 + +declare i32 @printf(ptr, ...) + +declare ptr @"github.com/goplus/llgo/runtime/internal/runtime.CStrCopy"(ptr, %"github.com/goplus/llgo/runtime/internal/runtime.String") + +declare ptr @"github.com/goplus/llgo/runtime/internal/runtime.AllocZ"(i64) + +attributes #0 = { nocallback nofree nounwind willreturn memory(argmem: write) } diff --git a/cl/compile.go b/cl/compile.go index c8ff8d08..5bb20025 100644 --- a/cl/compile.go +++ b/cl/compile.go @@ -935,6 +935,8 @@ func (p *context) compileVArg(ret []llssa.Expr, b llssa.Builder, v ssa.Value) [] if v.Value == nil { return ret } + case *ssa.Parameter: + return ret } panic(fmt.Sprintf("compileVArg: unknown value - %T\n", v)) } From fd17a43adeef3b5fd747f6aabc408dc1f928e18c Mon Sep 17 00:00:00 2001 From: visualfc Date: Tue, 9 Sep 2025 13:20:01 +0800 Subject: [PATCH 20/29] cl: interface support __llgo_va_list --- cl/_testrt/vamethod/in.go | 21 +- cl/_testrt/vamethod/out.ll | 433 +++++++++++++++++++++++++++++++++++-- cl/compile.go | 7 +- cl/instr.go | 6 +- ssa/decl.go | 4 +- ssa/type.go | 2 +- 6 files changed, 451 insertions(+), 22 deletions(-) diff --git a/cl/_testrt/vamethod/in.go b/cl/_testrt/vamethod/in.go index c2dbea83..42382967 100644 --- a/cl/_testrt/vamethod/in.go +++ b/cl/_testrt/vamethod/in.go @@ -19,14 +19,27 @@ type CFmt struct { *T } -func (f *CFmt) SetFormat(fmt string) { - f.T = (*T)(unsafe.Pointer(c.AllocaCStr(fmt))) +func (f *CFmt) SetFormat(fmt *c.Char) { + f.T = (*T)(unsafe.Pointer(fmt)) +} + +type IFmt interface { + SetFormat(fmt *c.Char) + Printf(__llgo_va_list ...any) c.Int } func main() { cfmt := &CFmt{} - cfmt.SetFormat("%s (%d)\n") + cfmt.SetFormat(c.Str("%s (%d)\n")) cfmt.Printf(c.Str("hello"), 100) - cfmt.SetFormat("(%d) %s\n") + cfmt.SetFormat(c.Str("(%d) %s\n")) cfmt.Printf(200, c.Str("world")) + + var i any = &CFmt{} + ifmt, ok := i.(IFmt) + if !ok { + panic("error") + } + ifmt.SetFormat(c.Str("%s (%d,%d)\n")) + ifmt.Printf(c.Str("ifmt"), 100, 200) } diff --git a/cl/_testrt/vamethod/out.ll b/cl/_testrt/vamethod/out.ll index 02eeeffa..1df84695 100644 --- a/cl/_testrt/vamethod/out.ll +++ b/cl/_testrt/vamethod/out.ll @@ -2,13 +2,43 @@ source_filename = "github.com/goplus/llgo/cl/_testrt/vamethod" %"github.com/goplus/llgo/cl/_testrt/vamethod.CFmt" = type { ptr } +%"github.com/goplus/llgo/runtime/internal/runtime.eface" = type { ptr, ptr } %"github.com/goplus/llgo/runtime/internal/runtime.String" = type { ptr, i64 } +%"github.com/goplus/llgo/runtime/internal/runtime.iface" = type { ptr, ptr } +%"github.com/goplus/llgo/runtime/internal/runtime.Slice" = type { ptr, i64, i64 } +%"github.com/goplus/llgo/runtime/abi.Method" = type { %"github.com/goplus/llgo/runtime/internal/runtime.String", ptr, ptr, ptr } +%"github.com/goplus/llgo/runtime/abi.StructField" = type { %"github.com/goplus/llgo/runtime/internal/runtime.String", ptr, i64, %"github.com/goplus/llgo/runtime/internal/runtime.String", i1 } +%"github.com/goplus/llgo/runtime/abi.Imethod" = type { %"github.com/goplus/llgo/runtime/internal/runtime.String", ptr } @"github.com/goplus/llgo/cl/_testrt/vamethod.init$guard" = global i1 false, align 1 -@0 = private unnamed_addr constant [8 x i8] c"%s (%d)\0A", align 1 +@0 = private unnamed_addr constant [9 x i8] c"%s (%d)\0A\00", align 1 @1 = private unnamed_addr constant [6 x i8] c"hello\00", align 1 -@2 = private unnamed_addr constant [8 x i8] c"(%d) %s\0A", align 1 +@2 = private unnamed_addr constant [9 x i8] c"(%d) %s\0A\00", align 1 @3 = private unnamed_addr constant [6 x i8] c"world\00", align 1 +@"_llgo_github.com/goplus/llgo/cl/_testrt/vamethod.CFmt" = linkonce global ptr null, align 8 +@4 = private unnamed_addr constant [42 x i8] c"github.com/goplus/llgo/cl/_testrt/vamethod", align 1 +@5 = private unnamed_addr constant [4 x i8] c"CFmt", align 1 +@"_llgo_github.com/goplus/llgo/cl/_testrt/vamethod.T" = linkonce global ptr null, align 8 +@6 = private unnamed_addr constant [1 x i8] c"T", align 1 +@_llgo_int8 = linkonce global ptr null, align 8 +@7 = private unnamed_addr constant [6 x i8] c"Printf", align 1 +@_llgo_any = linkonce global ptr null, align 8 +@"[]_llgo_any" = linkonce global ptr null, align 8 +@_llgo_int32 = linkonce global ptr null, align 8 +@"_llgo_func$sSO5Bw-E3E7TeJqIJF_OmmojTYyqWBhYrUwNYJNw7Bs" = linkonce global ptr null, align 8 +@"*_llgo_github.com/goplus/llgo/cl/_testrt/vamethod.T" = linkonce global ptr null, align 8 +@"_llgo_struct$quUppefyumGvUA5WNkqjeO0PomZGx9OI8NFZ2pfWLXw" = linkonce global ptr null, align 8 +@8 = private unnamed_addr constant [9 x i8] c"SetFormat", align 1 +@"*_llgo_int8" = linkonce global ptr null, align 8 +@"_llgo_func$vAfTC3ZLX0_lZI-ZNliu0_DkE266FSmKXxj_cqKPPkA" = linkonce global ptr null, align 8 +@"*_llgo_github.com/goplus/llgo/cl/_testrt/vamethod.CFmt" = linkonce global ptr null, align 8 +@"_llgo_github.com/goplus/llgo/cl/_testrt/vamethod.IFmt" = linkonce global ptr null, align 8 +@9 = private unnamed_addr constant [4 x i8] c"IFmt", align 1 +@"_llgo_iface$a85zs5wWQQoPIERm_en8plssh4spdIeeXZPC-E0TDh0" = linkonce global ptr null, align 8 +@10 = private unnamed_addr constant [12 x i8] c"%s (%d,%d)\0A\00", align 1 +@11 = private unnamed_addr constant [5 x i8] c"ifmt\00", align 1 +@12 = private unnamed_addr constant [5 x i8] c"error", align 1 +@_llgo_string = linkonce global ptr null, align 8 define i32 @"github.com/goplus/llgo/cl/_testrt/vamethod.CFmt.Printf"(%"github.com/goplus/llgo/cl/_testrt/vamethod.CFmt" %0, ...) { _llgo_0: @@ -29,14 +59,10 @@ _llgo_0: ret i32 %3 } -define void @"github.com/goplus/llgo/cl/_testrt/vamethod.(*CFmt).SetFormat"(ptr %0, %"github.com/goplus/llgo/runtime/internal/runtime.String" %1) { +define void @"github.com/goplus/llgo/cl/_testrt/vamethod.(*CFmt).SetFormat"(ptr %0, ptr %1) { _llgo_0: - %2 = extractvalue %"github.com/goplus/llgo/runtime/internal/runtime.String" %1, 1 - %3 = add i64 %2, 1 - %4 = alloca i8, i64 %3, align 1 - %5 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.CStrCopy"(ptr %4, %"github.com/goplus/llgo/runtime/internal/runtime.String" %1) - %6 = getelementptr inbounds %"github.com/goplus/llgo/cl/_testrt/vamethod.CFmt", ptr %0, i32 0, i32 0 - store ptr %5, ptr %6, align 8 + %2 = getelementptr inbounds %"github.com/goplus/llgo/cl/_testrt/vamethod.CFmt", ptr %0, i32 0, i32 0 + store ptr %1, ptr %2, align 8 ret void } @@ -47,6 +73,7 @@ _llgo_0: _llgo_1: ; preds = %_llgo_0 store i1 true, ptr @"github.com/goplus/llgo/cl/_testrt/vamethod.init$guard", align 1 + call void @"github.com/goplus/llgo/cl/_testrt/vamethod.init$after"() br label %_llgo_2 _llgo_2: ; preds = %_llgo_1, %_llgo_0 @@ -56,15 +83,72 @@ _llgo_2: ; preds = %_llgo_1, %_llgo_0 define void @"github.com/goplus/llgo/cl/_testrt/vamethod.main"() { _llgo_0: %0 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.AllocZ"(i64 8) - call void @"github.com/goplus/llgo/cl/_testrt/vamethod.(*CFmt).SetFormat"(ptr %0, %"github.com/goplus/llgo/runtime/internal/runtime.String" { ptr @0, i64 8 }) + call void @"github.com/goplus/llgo/cl/_testrt/vamethod.(*CFmt).SetFormat"(ptr %0, ptr @0) %1 = getelementptr inbounds %"github.com/goplus/llgo/cl/_testrt/vamethod.CFmt", ptr %0, i32 0, i32 0 %2 = load ptr, ptr %1, align 8 %3 = call i32 (ptr, ...) @printf(ptr %2, ptr @1, i64 100) - call void @"github.com/goplus/llgo/cl/_testrt/vamethod.(*CFmt).SetFormat"(ptr %0, %"github.com/goplus/llgo/runtime/internal/runtime.String" { ptr @2, i64 8 }) + call void @"github.com/goplus/llgo/cl/_testrt/vamethod.(*CFmt).SetFormat"(ptr %0, ptr @2) %4 = getelementptr inbounds %"github.com/goplus/llgo/cl/_testrt/vamethod.CFmt", ptr %0, i32 0, i32 0 %5 = load ptr, ptr %4, align 8 %6 = call i32 (ptr, ...) @printf(ptr %5, i64 200, ptr @3) + %7 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.AllocZ"(i64 8) + %8 = load ptr, ptr @"_llgo_github.com/goplus/llgo/cl/_testrt/vamethod.CFmt", align 8 + %9 = load ptr, ptr @"*_llgo_github.com/goplus/llgo/cl/_testrt/vamethod.CFmt", align 8 + %10 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.eface" undef, ptr %9, 0 + %11 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.eface" %10, ptr %7, 1 + %12 = extractvalue %"github.com/goplus/llgo/runtime/internal/runtime.eface" %11, 0 + %13 = load ptr, ptr @"_llgo_github.com/goplus/llgo/cl/_testrt/vamethod.IFmt", align 8 + %14 = call i1 @"github.com/goplus/llgo/runtime/internal/runtime.Implements"(ptr %13, ptr %12) + br i1 %14, label %_llgo_3, label %_llgo_4 + +_llgo_1: ; preds = %_llgo_5 + %15 = load ptr, ptr @_llgo_string, align 8 + %16 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.AllocU"(i64 16) + store %"github.com/goplus/llgo/runtime/internal/runtime.String" { ptr @12, i64 5 }, ptr %16, align 8 + %17 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.eface" undef, ptr %15, 0 + %18 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.eface" %17, ptr %16, 1 + call void @"github.com/goplus/llgo/runtime/internal/runtime.Panic"(%"github.com/goplus/llgo/runtime/internal/runtime.eface" %18) + unreachable + +_llgo_2: ; preds = %_llgo_5 + %19 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.IfacePtrData"(%"github.com/goplus/llgo/runtime/internal/runtime.iface" %44) + %20 = extractvalue %"github.com/goplus/llgo/runtime/internal/runtime.iface" %44, 0 + %21 = getelementptr ptr, ptr %20, i64 4 + %22 = load ptr, ptr %21, align 8 + %23 = insertvalue { ptr, ptr } undef, ptr %22, 0 + %24 = insertvalue { ptr, ptr } %23, ptr %19, 1 + %25 = extractvalue { ptr, ptr } %24, 1 + %26 = extractvalue { ptr, ptr } %24, 0 + call void %26(ptr %25, ptr @10) + %27 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.IfacePtrData"(%"github.com/goplus/llgo/runtime/internal/runtime.iface" %44) + %28 = extractvalue %"github.com/goplus/llgo/runtime/internal/runtime.iface" %44, 0 + %29 = getelementptr ptr, ptr %28, i64 3 + %30 = load ptr, ptr %29, align 8 + %31 = insertvalue { ptr, ptr } undef, ptr %30, 0 + %32 = insertvalue { ptr, ptr } %31, ptr %27, 1 + %33 = extractvalue { ptr, ptr } %32, 1 + %34 = extractvalue { ptr, ptr } %32, 0 + %35 = call i32 (ptr, ...) %34(ptr %33, ptr @11, i64 100, i64 200) ret void + +_llgo_3: ; preds = %_llgo_0 + %36 = extractvalue %"github.com/goplus/llgo/runtime/internal/runtime.eface" %11, 1 + %37 = load ptr, ptr @"_llgo_iface$a85zs5wWQQoPIERm_en8plssh4spdIeeXZPC-E0TDh0", align 8 + %38 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.NewItab"(ptr %37, ptr %12) + %39 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.iface" undef, ptr %38, 0 + %40 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.iface" %39, ptr %36, 1 + %41 = insertvalue { %"github.com/goplus/llgo/runtime/internal/runtime.iface", i1 } undef, %"github.com/goplus/llgo/runtime/internal/runtime.iface" %40, 0 + %42 = insertvalue { %"github.com/goplus/llgo/runtime/internal/runtime.iface", i1 } %41, i1 true, 1 + br label %_llgo_5 + +_llgo_4: ; preds = %_llgo_0 + br label %_llgo_5 + +_llgo_5: ; preds = %_llgo_4, %_llgo_3 + %43 = phi { %"github.com/goplus/llgo/runtime/internal/runtime.iface", i1 } [ %42, %_llgo_3 ], [ zeroinitializer, %_llgo_4 ] + %44 = extractvalue { %"github.com/goplus/llgo/runtime/internal/runtime.iface", i1 } %43, 0 + %45 = extractvalue { %"github.com/goplus/llgo/runtime/internal/runtime.iface", i1 } %43, 1 + br i1 %45, label %_llgo_2, label %_llgo_1 } ; Function Attrs: nocallback nofree nounwind willreturn memory(argmem: write) @@ -72,8 +156,331 @@ declare void @llvm.memset(ptr nocapture writeonly, i8, i64, i1 immarg) #0 declare i32 @printf(ptr, ...) -declare ptr @"github.com/goplus/llgo/runtime/internal/runtime.CStrCopy"(ptr, %"github.com/goplus/llgo/runtime/internal/runtime.String") - declare ptr @"github.com/goplus/llgo/runtime/internal/runtime.AllocZ"(i64) +define void @"github.com/goplus/llgo/cl/_testrt/vamethod.init$after"() { +_llgo_0: + %0 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.NewNamed"(%"github.com/goplus/llgo/runtime/internal/runtime.String" { ptr @4, i64 42 }, %"github.com/goplus/llgo/runtime/internal/runtime.String" { ptr @5, i64 4 }, i64 25, i64 8, i64 1, i64 2) + %1 = load ptr, ptr @"_llgo_github.com/goplus/llgo/cl/_testrt/vamethod.CFmt", align 8 + %2 = icmp eq ptr %1, null + br i1 %2, label %_llgo_1, label %_llgo_2 + +_llgo_1: ; preds = %_llgo_0 + call void @"github.com/goplus/llgo/runtime/internal/runtime.SetDirectIface"(ptr %0) + store ptr %0, ptr @"_llgo_github.com/goplus/llgo/cl/_testrt/vamethod.CFmt", align 8 + br label %_llgo_2 + +_llgo_2: ; preds = %_llgo_1, %_llgo_0 + %3 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.NewNamed"(%"github.com/goplus/llgo/runtime/internal/runtime.String" { ptr @4, i64 42 }, %"github.com/goplus/llgo/runtime/internal/runtime.String" { ptr @6, i64 1 }, i64 3, i64 1, i64 0, i64 1) + %4 = load ptr, ptr @"_llgo_github.com/goplus/llgo/cl/_testrt/vamethod.T", align 8 + %5 = icmp eq ptr %4, null + br i1 %5, label %_llgo_3, label %_llgo_4 + +_llgo_3: ; preds = %_llgo_2 + store ptr %3, ptr @"_llgo_github.com/goplus/llgo/cl/_testrt/vamethod.T", align 8 + br label %_llgo_4 + +_llgo_4: ; preds = %_llgo_3, %_llgo_2 + %6 = load ptr, ptr @_llgo_int8, align 8 + %7 = icmp eq ptr %6, null + br i1 %7, label %_llgo_5, label %_llgo_6 + +_llgo_5: ; preds = %_llgo_4 + %8 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.Basic"(i64 35) + store ptr %8, ptr @_llgo_int8, align 8 + br label %_llgo_6 + +_llgo_6: ; preds = %_llgo_5, %_llgo_4 + %9 = load ptr, ptr @_llgo_int8, align 8 + br i1 %5, label %_llgo_7, label %_llgo_8 + +_llgo_7: ; preds = %_llgo_6 + %10 = load ptr, ptr @_llgo_any, align 8 + %11 = icmp eq ptr %10, null + br i1 %11, label %_llgo_9, label %_llgo_10 + +_llgo_8: ; preds = %_llgo_16, %_llgo_6 + %12 = load ptr, ptr @"_llgo_github.com/goplus/llgo/cl/_testrt/vamethod.T", align 8 + %13 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.NewNamed"(%"github.com/goplus/llgo/runtime/internal/runtime.String" { ptr @4, i64 42 }, %"github.com/goplus/llgo/runtime/internal/runtime.String" { ptr @6, i64 1 }, i64 3, i64 1, i64 0, i64 1) + %14 = load ptr, ptr @"*_llgo_github.com/goplus/llgo/cl/_testrt/vamethod.T", align 8 + %15 = icmp eq ptr %14, null + br i1 %15, label %_llgo_17, label %_llgo_18 + +_llgo_9: ; preds = %_llgo_7 + %16 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.AllocU"(i64 0) + %17 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.Slice" undef, ptr %16, 0 + %18 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.Slice" %17, i64 0, 1 + %19 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.Slice" %18, i64 0, 2 + %20 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.Interface"(%"github.com/goplus/llgo/runtime/internal/runtime.String" { ptr @4, i64 42 }, %"github.com/goplus/llgo/runtime/internal/runtime.Slice" %19) + store ptr %20, ptr @_llgo_any, align 8 + br label %_llgo_10 + +_llgo_10: ; preds = %_llgo_9, %_llgo_7 + %21 = load ptr, ptr @_llgo_any, align 8 + %22 = load ptr, ptr @"[]_llgo_any", align 8 + %23 = icmp eq ptr %22, null + br i1 %23, label %_llgo_11, label %_llgo_12 + +_llgo_11: ; preds = %_llgo_10 + %24 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.AllocU"(i64 0) + %25 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.Slice" undef, ptr %24, 0 + %26 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.Slice" %25, i64 0, 1 + %27 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.Slice" %26, i64 0, 2 + %28 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.Interface"(%"github.com/goplus/llgo/runtime/internal/runtime.String" { ptr @4, i64 42 }, %"github.com/goplus/llgo/runtime/internal/runtime.Slice" %27) + %29 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.SliceOf"(ptr %28) + store ptr %29, ptr @"[]_llgo_any", align 8 + br label %_llgo_12 + +_llgo_12: ; preds = %_llgo_11, %_llgo_10 + %30 = load ptr, ptr @"[]_llgo_any", align 8 + %31 = load ptr, ptr @_llgo_int32, align 8 + %32 = icmp eq ptr %31, null + br i1 %32, label %_llgo_13, label %_llgo_14 + +_llgo_13: ; preds = %_llgo_12 + %33 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.Basic"(i64 37) + store ptr %33, ptr @_llgo_int32, align 8 + br label %_llgo_14 + +_llgo_14: ; preds = %_llgo_13, %_llgo_12 + %34 = load ptr, ptr @_llgo_int32, align 8 + %35 = load ptr, ptr @"[]_llgo_any", align 8 + %36 = load ptr, ptr @_llgo_int32, align 8 + %37 = load ptr, ptr @"_llgo_func$sSO5Bw-E3E7TeJqIJF_OmmojTYyqWBhYrUwNYJNw7Bs", align 8 + %38 = icmp eq ptr %37, null + br i1 %38, label %_llgo_15, label %_llgo_16 + +_llgo_15: ; preds = %_llgo_14 + %39 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.AllocU"(i64 8) + %40 = getelementptr ptr, ptr %39, i64 0 + store ptr %35, ptr %40, align 8 + %41 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.Slice" undef, ptr %39, 0 + %42 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.Slice" %41, i64 1, 1 + %43 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.Slice" %42, i64 1, 2 + %44 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.AllocU"(i64 8) + %45 = getelementptr ptr, ptr %44, i64 0 + store ptr %36, ptr %45, align 8 + %46 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.Slice" undef, ptr %44, 0 + %47 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.Slice" %46, i64 1, 1 + %48 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.Slice" %47, i64 1, 2 + %49 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.Func"(%"github.com/goplus/llgo/runtime/internal/runtime.Slice" %43, %"github.com/goplus/llgo/runtime/internal/runtime.Slice" %48, i1 true) + call void @"github.com/goplus/llgo/runtime/internal/runtime.SetDirectIface"(ptr %49) + store ptr %49, ptr @"_llgo_func$sSO5Bw-E3E7TeJqIJF_OmmojTYyqWBhYrUwNYJNw7Bs", align 8 + br label %_llgo_16 + +_llgo_16: ; preds = %_llgo_15, %_llgo_14 + %50 = load ptr, ptr @"_llgo_func$sSO5Bw-E3E7TeJqIJF_OmmojTYyqWBhYrUwNYJNw7Bs", align 8 + %51 = insertvalue %"github.com/goplus/llgo/runtime/abi.Method" { %"github.com/goplus/llgo/runtime/internal/runtime.String" { ptr @7, i64 6 }, ptr undef, ptr undef, ptr undef }, ptr %50, 1 + %52 = insertvalue %"github.com/goplus/llgo/runtime/abi.Method" %51, ptr @printf, 2 + %53 = insertvalue %"github.com/goplus/llgo/runtime/abi.Method" %52, ptr @printf, 3 + %54 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.AllocU"(i64 40) + %55 = getelementptr %"github.com/goplus/llgo/runtime/abi.Method", ptr %54, i64 0 + store %"github.com/goplus/llgo/runtime/abi.Method" %53, ptr %55, align 8 + %56 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.Slice" undef, ptr %54, 0 + %57 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.Slice" %56, i64 1, 1 + %58 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.Slice" %57, i64 1, 2 + call void @"github.com/goplus/llgo/runtime/internal/runtime.InitNamed"(ptr %3, ptr %9, { ptr, i64, i64 } zeroinitializer, %"github.com/goplus/llgo/runtime/internal/runtime.Slice" %58) + br label %_llgo_8 + +_llgo_17: ; preds = %_llgo_8 + %59 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.PointerTo"(ptr %13) + call void @"github.com/goplus/llgo/runtime/internal/runtime.SetDirectIface"(ptr %59) + store ptr %59, ptr @"*_llgo_github.com/goplus/llgo/cl/_testrt/vamethod.T", align 8 + br label %_llgo_18 + +_llgo_18: ; preds = %_llgo_17, %_llgo_8 + %60 = load ptr, ptr @"*_llgo_github.com/goplus/llgo/cl/_testrt/vamethod.T", align 8 + %61 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.NewNamed"(%"github.com/goplus/llgo/runtime/internal/runtime.String" { ptr @4, i64 42 }, %"github.com/goplus/llgo/runtime/internal/runtime.String" { ptr @6, i64 1 }, i64 3, i64 1, i64 0, i64 1) + %62 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.PointerTo"(ptr %61) + %63 = call %"github.com/goplus/llgo/runtime/abi.StructField" @"github.com/goplus/llgo/runtime/internal/runtime.StructField"(%"github.com/goplus/llgo/runtime/internal/runtime.String" { ptr @6, i64 1 }, ptr %62, i64 0, %"github.com/goplus/llgo/runtime/internal/runtime.String" zeroinitializer, i1 true) + %64 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.AllocU"(i64 56) + %65 = getelementptr %"github.com/goplus/llgo/runtime/abi.StructField", ptr %64, i64 0 + store %"github.com/goplus/llgo/runtime/abi.StructField" %63, ptr %65, align 8 + %66 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.Slice" undef, ptr %64, 0 + %67 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.Slice" %66, i64 1, 1 + %68 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.Slice" %67, i64 1, 2 + %69 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.Struct"(%"github.com/goplus/llgo/runtime/internal/runtime.String" { ptr @4, i64 42 }, i64 8, %"github.com/goplus/llgo/runtime/internal/runtime.Slice" %68) + call void @"github.com/goplus/llgo/runtime/internal/runtime.SetDirectIface"(ptr %69) + store ptr %69, ptr @"_llgo_struct$quUppefyumGvUA5WNkqjeO0PomZGx9OI8NFZ2pfWLXw", align 8 + %70 = load ptr, ptr @"_llgo_struct$quUppefyumGvUA5WNkqjeO0PomZGx9OI8NFZ2pfWLXw", align 8 + br i1 %2, label %_llgo_19, label %_llgo_20 + +_llgo_19: ; preds = %_llgo_18 + %71 = load ptr, ptr @"_llgo_func$sSO5Bw-E3E7TeJqIJF_OmmojTYyqWBhYrUwNYJNw7Bs", align 8 + %72 = insertvalue %"github.com/goplus/llgo/runtime/abi.Method" { %"github.com/goplus/llgo/runtime/internal/runtime.String" { ptr @7, i64 6 }, ptr undef, ptr undef, ptr undef }, ptr %71, 1 + %73 = insertvalue %"github.com/goplus/llgo/runtime/abi.Method" %72, ptr @"github.com/goplus/llgo/cl/_testrt/vamethod.(*CFmt).Printf", 2 + %74 = insertvalue %"github.com/goplus/llgo/runtime/abi.Method" %73, ptr @"github.com/goplus/llgo/cl/_testrt/vamethod.(*CFmt).Printf", 3 + %75 = insertvalue %"github.com/goplus/llgo/runtime/abi.Method" { %"github.com/goplus/llgo/runtime/internal/runtime.String" { ptr @7, i64 6 }, ptr undef, ptr undef, ptr undef }, ptr %71, 1 + %76 = insertvalue %"github.com/goplus/llgo/runtime/abi.Method" %75, ptr @"github.com/goplus/llgo/cl/_testrt/vamethod.(*CFmt).Printf", 2 + %77 = insertvalue %"github.com/goplus/llgo/runtime/abi.Method" %76, ptr @"github.com/goplus/llgo/cl/_testrt/vamethod.CFmt.Printf", 3 + %78 = load ptr, ptr @_llgo_int8, align 8 + %79 = load ptr, ptr @"*_llgo_int8", align 8 + %80 = icmp eq ptr %79, null + br i1 %80, label %_llgo_21, label %_llgo_22 + +_llgo_20: ; preds = %_llgo_24, %_llgo_18 + %81 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.NewNamed"(%"github.com/goplus/llgo/runtime/internal/runtime.String" { ptr @4, i64 42 }, %"github.com/goplus/llgo/runtime/internal/runtime.String" { ptr @5, i64 4 }, i64 25, i64 8, i64 1, i64 2) + %82 = load ptr, ptr @"*_llgo_github.com/goplus/llgo/cl/_testrt/vamethod.CFmt", align 8 + %83 = icmp eq ptr %82, null + br i1 %83, label %_llgo_25, label %_llgo_26 + +_llgo_21: ; preds = %_llgo_19 + %84 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.Basic"(i64 35) + %85 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.PointerTo"(ptr %84) + call void @"github.com/goplus/llgo/runtime/internal/runtime.SetDirectIface"(ptr %85) + store ptr %85, ptr @"*_llgo_int8", align 8 + br label %_llgo_22 + +_llgo_22: ; preds = %_llgo_21, %_llgo_19 + %86 = load ptr, ptr @"*_llgo_int8", align 8 + %87 = load ptr, ptr @"*_llgo_int8", align 8 + %88 = load ptr, ptr @"_llgo_func$vAfTC3ZLX0_lZI-ZNliu0_DkE266FSmKXxj_cqKPPkA", align 8 + %89 = icmp eq ptr %88, null + br i1 %89, label %_llgo_23, label %_llgo_24 + +_llgo_23: ; preds = %_llgo_22 + %90 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.AllocU"(i64 8) + %91 = getelementptr ptr, ptr %90, i64 0 + store ptr %87, ptr %91, align 8 + %92 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.Slice" undef, ptr %90, 0 + %93 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.Slice" %92, i64 1, 1 + %94 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.Slice" %93, i64 1, 2 + %95 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.AllocU"(i64 0) + %96 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.Slice" undef, ptr %95, 0 + %97 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.Slice" %96, i64 0, 1 + %98 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.Slice" %97, i64 0, 2 + %99 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.Func"(%"github.com/goplus/llgo/runtime/internal/runtime.Slice" %94, %"github.com/goplus/llgo/runtime/internal/runtime.Slice" %98, i1 false) + call void @"github.com/goplus/llgo/runtime/internal/runtime.SetDirectIface"(ptr %99) + store ptr %99, ptr @"_llgo_func$vAfTC3ZLX0_lZI-ZNliu0_DkE266FSmKXxj_cqKPPkA", align 8 + br label %_llgo_24 + +_llgo_24: ; preds = %_llgo_23, %_llgo_22 + %100 = load ptr, ptr @"_llgo_func$vAfTC3ZLX0_lZI-ZNliu0_DkE266FSmKXxj_cqKPPkA", align 8 + %101 = insertvalue %"github.com/goplus/llgo/runtime/abi.Method" { %"github.com/goplus/llgo/runtime/internal/runtime.String" { ptr @8, i64 9 }, ptr undef, ptr undef, ptr undef }, ptr %100, 1 + %102 = insertvalue %"github.com/goplus/llgo/runtime/abi.Method" %101, ptr @"github.com/goplus/llgo/cl/_testrt/vamethod.(*CFmt).SetFormat", 2 + %103 = insertvalue %"github.com/goplus/llgo/runtime/abi.Method" %102, ptr @"github.com/goplus/llgo/cl/_testrt/vamethod.(*CFmt).SetFormat", 3 + %104 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.AllocU"(i64 40) + %105 = getelementptr %"github.com/goplus/llgo/runtime/abi.Method", ptr %104, i64 0 + store %"github.com/goplus/llgo/runtime/abi.Method" %77, ptr %105, align 8 + %106 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.Slice" undef, ptr %104, 0 + %107 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.Slice" %106, i64 1, 1 + %108 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.Slice" %107, i64 1, 2 + %109 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.AllocU"(i64 80) + %110 = getelementptr %"github.com/goplus/llgo/runtime/abi.Method", ptr %109, i64 0 + store %"github.com/goplus/llgo/runtime/abi.Method" %74, ptr %110, align 8 + %111 = getelementptr %"github.com/goplus/llgo/runtime/abi.Method", ptr %109, i64 1 + store %"github.com/goplus/llgo/runtime/abi.Method" %103, ptr %111, align 8 + %112 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.Slice" undef, ptr %109, 0 + %113 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.Slice" %112, i64 2, 1 + %114 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.Slice" %113, i64 2, 2 + call void @"github.com/goplus/llgo/runtime/internal/runtime.InitNamed"(ptr %0, ptr %70, %"github.com/goplus/llgo/runtime/internal/runtime.Slice" %108, %"github.com/goplus/llgo/runtime/internal/runtime.Slice" %114) + br label %_llgo_20 + +_llgo_25: ; preds = %_llgo_20 + %115 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.PointerTo"(ptr %81) + call void @"github.com/goplus/llgo/runtime/internal/runtime.SetDirectIface"(ptr %115) + store ptr %115, ptr @"*_llgo_github.com/goplus/llgo/cl/_testrt/vamethod.CFmt", align 8 + br label %_llgo_26 + +_llgo_26: ; preds = %_llgo_25, %_llgo_20 + %116 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.NewNamedInterface"(%"github.com/goplus/llgo/runtime/internal/runtime.String" { ptr @4, i64 42 }, %"github.com/goplus/llgo/runtime/internal/runtime.String" { ptr @9, i64 4 }) + %117 = load ptr, ptr @"_llgo_github.com/goplus/llgo/cl/_testrt/vamethod.IFmt", align 8 + %118 = icmp eq ptr %117, null + br i1 %118, label %_llgo_27, label %_llgo_28 + +_llgo_27: ; preds = %_llgo_26 + store ptr %116, ptr @"_llgo_github.com/goplus/llgo/cl/_testrt/vamethod.IFmt", align 8 + br label %_llgo_28 + +_llgo_28: ; preds = %_llgo_27, %_llgo_26 + %119 = load ptr, ptr @"[]_llgo_any", align 8 + %120 = load ptr, ptr @"_llgo_func$sSO5Bw-E3E7TeJqIJF_OmmojTYyqWBhYrUwNYJNw7Bs", align 8 + %121 = load ptr, ptr @"*_llgo_int8", align 8 + %122 = load ptr, ptr @"_llgo_func$vAfTC3ZLX0_lZI-ZNliu0_DkE266FSmKXxj_cqKPPkA", align 8 + br i1 %118, label %_llgo_29, label %_llgo_30 + +_llgo_29: ; preds = %_llgo_28 + %123 = insertvalue %"github.com/goplus/llgo/runtime/abi.Imethod" { %"github.com/goplus/llgo/runtime/internal/runtime.String" { ptr @7, i64 6 }, ptr undef }, ptr %120, 1 + %124 = insertvalue %"github.com/goplus/llgo/runtime/abi.Imethod" { %"github.com/goplus/llgo/runtime/internal/runtime.String" { ptr @8, i64 9 }, ptr undef }, ptr %122, 1 + %125 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.AllocU"(i64 48) + %126 = getelementptr %"github.com/goplus/llgo/runtime/abi.Imethod", ptr %125, i64 0 + store %"github.com/goplus/llgo/runtime/abi.Imethod" %123, ptr %126, align 8 + %127 = getelementptr %"github.com/goplus/llgo/runtime/abi.Imethod", ptr %125, i64 1 + store %"github.com/goplus/llgo/runtime/abi.Imethod" %124, ptr %127, align 8 + %128 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.Slice" undef, ptr %125, 0 + %129 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.Slice" %128, i64 2, 1 + %130 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.Slice" %129, i64 2, 2 + call void @"github.com/goplus/llgo/runtime/internal/runtime.InitNamedInterface"(ptr %116, %"github.com/goplus/llgo/runtime/internal/runtime.Slice" %130) + br label %_llgo_30 + +_llgo_30: ; preds = %_llgo_29, %_llgo_28 + %131 = load ptr, ptr @"_llgo_func$sSO5Bw-E3E7TeJqIJF_OmmojTYyqWBhYrUwNYJNw7Bs", align 8 + %132 = load ptr, ptr @"_llgo_func$vAfTC3ZLX0_lZI-ZNliu0_DkE266FSmKXxj_cqKPPkA", align 8 + %133 = load ptr, ptr @"_llgo_iface$a85zs5wWQQoPIERm_en8plssh4spdIeeXZPC-E0TDh0", align 8 + %134 = icmp eq ptr %133, null + br i1 %134, label %_llgo_31, label %_llgo_32 + +_llgo_31: ; preds = %_llgo_30 + %135 = insertvalue %"github.com/goplus/llgo/runtime/abi.Imethod" { %"github.com/goplus/llgo/runtime/internal/runtime.String" { ptr @7, i64 6 }, ptr undef }, ptr %131, 1 + %136 = insertvalue %"github.com/goplus/llgo/runtime/abi.Imethod" { %"github.com/goplus/llgo/runtime/internal/runtime.String" { ptr @8, i64 9 }, ptr undef }, ptr %132, 1 + %137 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.AllocU"(i64 48) + %138 = getelementptr %"github.com/goplus/llgo/runtime/abi.Imethod", ptr %137, i64 0 + store %"github.com/goplus/llgo/runtime/abi.Imethod" %135, ptr %138, align 8 + %139 = getelementptr %"github.com/goplus/llgo/runtime/abi.Imethod", ptr %137, i64 1 + store %"github.com/goplus/llgo/runtime/abi.Imethod" %136, ptr %139, align 8 + %140 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.Slice" undef, ptr %137, 0 + %141 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.Slice" %140, i64 2, 1 + %142 = insertvalue %"github.com/goplus/llgo/runtime/internal/runtime.Slice" %141, i64 2, 2 + %143 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.Interface"(%"github.com/goplus/llgo/runtime/internal/runtime.String" { ptr @4, i64 42 }, %"github.com/goplus/llgo/runtime/internal/runtime.Slice" %142) + store ptr %143, ptr @"_llgo_iface$a85zs5wWQQoPIERm_en8plssh4spdIeeXZPC-E0TDh0", align 8 + br label %_llgo_32 + +_llgo_32: ; preds = %_llgo_31, %_llgo_30 + %144 = load ptr, ptr @_llgo_string, align 8 + %145 = icmp eq ptr %144, null + br i1 %145, label %_llgo_33, label %_llgo_34 + +_llgo_33: ; preds = %_llgo_32 + %146 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.Basic"(i64 24) + store ptr %146, ptr @_llgo_string, align 8 + br label %_llgo_34 + +_llgo_34: ; preds = %_llgo_33, %_llgo_32 + ret void +} + +declare ptr @"github.com/goplus/llgo/runtime/internal/runtime.NewNamed"(%"github.com/goplus/llgo/runtime/internal/runtime.String", %"github.com/goplus/llgo/runtime/internal/runtime.String", i64, i64, i64, i64) + +declare void @"github.com/goplus/llgo/runtime/internal/runtime.SetDirectIface"(ptr) + +declare ptr @"github.com/goplus/llgo/runtime/internal/runtime.Basic"(i64) + +declare void @"github.com/goplus/llgo/runtime/internal/runtime.InitNamed"(ptr, ptr, %"github.com/goplus/llgo/runtime/internal/runtime.Slice", %"github.com/goplus/llgo/runtime/internal/runtime.Slice") + +declare ptr @"github.com/goplus/llgo/runtime/internal/runtime.Interface"(%"github.com/goplus/llgo/runtime/internal/runtime.String", %"github.com/goplus/llgo/runtime/internal/runtime.Slice") + +declare ptr @"github.com/goplus/llgo/runtime/internal/runtime.AllocU"(i64) + +declare ptr @"github.com/goplus/llgo/runtime/internal/runtime.SliceOf"(ptr) + +declare ptr @"github.com/goplus/llgo/runtime/internal/runtime.Func"(%"github.com/goplus/llgo/runtime/internal/runtime.Slice", %"github.com/goplus/llgo/runtime/internal/runtime.Slice", i1) + +declare ptr @"github.com/goplus/llgo/runtime/internal/runtime.PointerTo"(ptr) + +declare ptr @"github.com/goplus/llgo/runtime/internal/runtime.Struct"(%"github.com/goplus/llgo/runtime/internal/runtime.String", i64, %"github.com/goplus/llgo/runtime/internal/runtime.Slice") + +declare %"github.com/goplus/llgo/runtime/abi.StructField" @"github.com/goplus/llgo/runtime/internal/runtime.StructField"(%"github.com/goplus/llgo/runtime/internal/runtime.String", ptr, i64, %"github.com/goplus/llgo/runtime/internal/runtime.String", i1) + +declare ptr @"github.com/goplus/llgo/runtime/internal/runtime.NewNamedInterface"(%"github.com/goplus/llgo/runtime/internal/runtime.String", %"github.com/goplus/llgo/runtime/internal/runtime.String") + +declare void @"github.com/goplus/llgo/runtime/internal/runtime.InitNamedInterface"(ptr, %"github.com/goplus/llgo/runtime/internal/runtime.Slice") + +declare i1 @"github.com/goplus/llgo/runtime/internal/runtime.Implements"(ptr, ptr) + +declare ptr @"github.com/goplus/llgo/runtime/internal/runtime.NewItab"(ptr, ptr) + +declare ptr @"github.com/goplus/llgo/runtime/internal/runtime.IfacePtrData"(%"github.com/goplus/llgo/runtime/internal/runtime.iface") + +declare void @"github.com/goplus/llgo/runtime/internal/runtime.Panic"(%"github.com/goplus/llgo/runtime/internal/runtime.eface") + attributes #0 = { nocallback nofree nounwind willreturn memory(argmem: write) } diff --git a/cl/compile.go b/cl/compile.go index 5bb20025..fc24b9c2 100644 --- a/cl/compile.go +++ b/cl/compile.go @@ -537,6 +537,9 @@ func isAllocVargs(ctx *context, v *ssa.Alloc) bool { default: return false } + if call.IsInvoke() { + return llssa.HasNameValist(call.Signature()) + } return ctx.funcKind(call.Value) == fnHasVArg } } @@ -936,7 +939,9 @@ func (p *context) compileVArg(ret []llssa.Expr, b llssa.Builder, v ssa.Value) [] return ret } case *ssa.Parameter: - return ret + if llssa.HasNameValist(v.Parent().Signature) { + return ret + } } panic(fmt.Sprintf("compileVArg: unknown value - %T\n", v)) } diff --git a/cl/instr.go b/cl/instr.go index 5dabd5f8..e007d826 100644 --- a/cl/instr.go +++ b/cl/instr.go @@ -506,7 +506,11 @@ func (p *context) call(b llssa.Builder, act llssa.DoAction, call *ssa.CallCommon if mthd := call.Method; mthd != nil { o := p.compileValue(b, cv) fn := b.Imethod(o, mthd) - args := p.compileValues(b, call.Args, fnNormal) + hasVArg := fnNormal + if llssa.HasNameValist(call.Signature()) { + hasVArg = fnHasVArg + } + args := p.compileValues(b, call.Args, hasVArg) ret = b.Do(act, fn, args...) return } diff --git a/ssa/decl.go b/ssa/decl.go index d139c7cb..b877addb 100644 --- a/ssa/decl.go +++ b/ssa/decl.go @@ -34,7 +34,7 @@ func VArg() *types.Var { return types.NewParam(0, nil, NameValist, types.NewSlice(tyAny)) } -func hasNameValist(sig *types.Signature) bool { +func HasNameValist(sig *types.Signature) bool { if sig.Variadic() { if params := sig.Params(); params.At(params.Len()-1).Name() == NameValist { return true @@ -241,7 +241,7 @@ func newParams(fn Type, prog Program) (params []Type, hasVArg bool) { sig := fn.raw.Type.(*types.Signature) in := sig.Params() if n := in.Len(); n > 0 { - if hasVArg = hasNameValist(sig); hasVArg { + if hasVArg = HasNameValist(sig); hasVArg { n-- } params = make([]Type, n) diff --git a/ssa/type.go b/ssa/type.go index 0cd72042..374df514 100644 --- a/ssa/type.go +++ b/ssa/type.go @@ -458,7 +458,7 @@ func (p Program) toLLVMTypes(t *types.Tuple, n int) (ret []llvm.Type) { func (p Program) toLLVMFunc(sig *types.Signature) llvm.Type { tParams := sig.Params() n := tParams.Len() - hasVArg := hasNameValist(sig) + hasVArg := HasNameValist(sig) if hasVArg { n-- } From 5dbf1a75611a5d2c8bc4b12807464f66f3c6bd1d Mon Sep 17 00:00:00 2001 From: visualfc Date: Tue, 9 Sep 2025 17:24:17 +0800 Subject: [PATCH 21/29] cl/_testrt/vamethod: optimize code --- cl/_testrt/vamethod/in.go | 1 - 1 file changed, 1 deletion(-) diff --git a/cl/_testrt/vamethod/in.go b/cl/_testrt/vamethod/in.go index 42382967..db763f56 100644 --- a/cl/_testrt/vamethod/in.go +++ b/cl/_testrt/vamethod/in.go @@ -2,7 +2,6 @@ package main import ( "unsafe" - _ "unsafe" "github.com/goplus/lib/c" ) From 95bd495d7be9f3bceb8592ea1e11c65d2f5b4de1 Mon Sep 17 00:00:00 2001 From: Haolan Date: Thu, 4 Sep 2025 19:08:48 +0800 Subject: [PATCH 22/29] feat: support libc version --- internal/crosscompile/compile/compile.go | 12 +- internal/crosscompile/compile/compile_test.go | 57 +++ .../crosscompile/compile/libc/libc_test.go | 79 ++--- .../crosscompile/compile/libc/newlibesp.go | 34 +- .../crosscompile/compile/libc/picolibc.go | 21 +- .../crosscompile/compile/rtlib/compiler_rt.go | 14 +- .../crosscompile/compile/rtlib/rt_test.go | 11 +- internal/crosscompile/crosscompile.go | 30 +- internal/crosscompile/libc.go | 56 ++- internal/crosscompile/libc_test.go | 324 +++++++++++++++++- 10 files changed, 503 insertions(+), 135 deletions(-) diff --git a/internal/crosscompile/compile/compile.go b/internal/crosscompile/compile/compile.go index 0fc7d79a..01136d8e 100644 --- a/internal/crosscompile/compile/compile.go +++ b/internal/crosscompile/compile/compile.go @@ -95,9 +95,17 @@ func (g CompileGroup) Compile( // CompileConfig represents compilation configuration type CompileConfig struct { + Groups []CompileGroup + ExportCFlags []string +} + +type LibConfig struct { Url string Name string // compile name (e.g., "picolibc", "musl", "glibc") - Groups []CompileGroup + Version string ArchiveSrcDir string - LibcCFlags []string +} + +func (cfg LibConfig) String() string { + return fmt.Sprintf("%s-%s", cfg.Name, cfg.Version) } diff --git a/internal/crosscompile/compile/compile_test.go b/internal/crosscompile/compile/compile_test.go index d2125e5a..f5f5ba7d 100644 --- a/internal/crosscompile/compile/compile_test.go +++ b/internal/crosscompile/compile/compile_test.go @@ -207,3 +207,60 @@ func TestCompile(t *testing.T) { } }) } + +func TestLibConfig_String(t *testing.T) { + tests := []struct { + name string + config LibConfig + expected string + }{ + { + name: "Normal name and version", + config: LibConfig{ + Name: "picolibc", + Version: "1.0", + }, + expected: "picolibc-1.0", + }, + { + name: "Empty name", + config: LibConfig{ + Name: "", + Version: "2.5", + }, + expected: "-2.5", + }, + { + name: "Empty version", + config: LibConfig{ + Name: "musl", + Version: "", + }, + expected: "musl-", + }, + { + name: "Both empty", + config: LibConfig{ + Name: "", + Version: "", + }, + expected: "-", + }, + { + name: "Special characters", + config: LibConfig{ + Name: "glibc++", + Version: "v3.2.1", + }, + expected: "glibc++-v3.2.1", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := tt.config.String(); got != tt.expected { + t.Errorf("String() = %v, want %v", got, tt.expected) + } + }) + } +} diff --git a/internal/crosscompile/compile/libc/libc_test.go b/internal/crosscompile/compile/libc/libc_test.go index 20022229..3689d9fa 100644 --- a/internal/crosscompile/compile/libc/libc_test.go +++ b/internal/crosscompile/compile/libc/libc_test.go @@ -9,27 +9,20 @@ func TestGetPicolibcConfig(t *testing.T) { baseDir := "/test/base" target := "test-target" - config := GetPicolibcConfig(baseDir, target) - - if config.Name != "picolibc" { - t.Errorf("Expected Name 'picolibc', got '%s'", config.Name) - } - if config.ArchiveSrcDir != "picolibc-main" { - t.Errorf("Expected ArchiveSrcDir 'picolibc-main', got '%s'", config.ArchiveSrcDir) - } + config := GetPicolibcCompileConfig(baseDir, target) // Test LibcCFlags - if len(config.LibcCFlags) != 2 { - t.Errorf("Expected 2 LibcCFlags, got %d", len(config.LibcCFlags)) + if len(config.ExportCFlags) != 2 { + t.Errorf("Expected 2 LibcCFlags, got %d", len(config.ExportCFlags)) } else { expected := "-I" + baseDir - if config.LibcCFlags[0] != expected { - t.Errorf("Expected LibcCFlags[0] to be '%s', got '%s'", expected, config.LibcCFlags[0]) + if config.ExportCFlags[0] != expected { + t.Errorf("Expected LibcCFlags[0] to be '%s', got '%s'", expected, config.ExportCFlags[0]) } expected = "-isystem" + filepath.Join(baseDir, "newlib", "libc", "include") - if config.LibcCFlags[1] != expected { - t.Errorf("Expected LibcCFlags[1] to be '%s', got '%s'", expected, config.LibcCFlags[1]) + if config.ExportCFlags[1] != expected { + t.Errorf("Expected LibcCFlags[1] to be '%s', got '%s'", expected, config.ExportCFlags[1]) } } @@ -113,22 +106,22 @@ func TestGetPicolibcConfig(t *testing.T) { func TestGetPicolibcConfig_EdgeCases(t *testing.T) { t.Run("EmptyBaseDir", func(t *testing.T) { - config := GetPicolibcConfig("", "test-target") + config := GetPicolibcCompileConfig("", "test-target") // Check that paths are constructed correctly even with empty baseDir expected := "-I" - if config.LibcCFlags[0] != expected { - t.Errorf("Expected LibcCFlags[0] to be '%s', got '%s'", expected, config.LibcCFlags[0]) + if config.ExportCFlags[0] != expected { + t.Errorf("Expected LibcCFlags[0] to be '%s', got '%s'", expected, config.ExportCFlags[0]) } expected = "-isystem" + filepath.Join("", "newlib", "libc", "include") - if config.LibcCFlags[1] != expected { - t.Errorf("Expected LibcCFlags[1] to be '%s', got '%s'", expected, config.LibcCFlags[1]) + if config.ExportCFlags[1] != expected { + t.Errorf("Expected LibcCFlags[1] to be '%s', got '%s'", expected, config.ExportCFlags[1]) } }) t.Run("EmptyTarget", func(t *testing.T) { - config := GetPicolibcConfig("/test/base", "") + config := GetPicolibcCompileConfig("/test/base", "") // Check output file name formatting expectedOutput := "libc-.a" @@ -144,17 +137,6 @@ func TestGetNewlibESP32ConfigRISCV(t *testing.T) { config := getNewlibESP32ConfigRISCV(baseDir, target) - // Test basic configuration - if config.Url != _newlibUrl { - t.Errorf("Expected URL '%s', got '%s'", _newlibUrl, config.Url) - } - if config.Name != "newlib-esp32" { - t.Errorf("Expected Name 'newlib-esp32', got '%s'", config.Name) - } - if config.ArchiveSrcDir != _archiveInternalSrcDir { - t.Errorf("Expected ArchiveSrcDir '%s', got '%s'", _archiveInternalSrcDir, config.ArchiveSrcDir) - } - // Test LibcCFlags libcDir := filepath.Join(baseDir, "newlib", "libc") expectedCFlags := []string{ @@ -162,12 +144,12 @@ func TestGetNewlibESP32ConfigRISCV(t *testing.T) { "-I" + filepath.Join(baseDir, "newlib"), "-I" + libcDir, } - if len(config.LibcCFlags) != len(expectedCFlags) { - t.Errorf("Expected %d LibcCFlags, got %d", len(expectedCFlags), len(config.LibcCFlags)) + if len(config.ExportCFlags) != len(expectedCFlags) { + t.Errorf("Expected %d LibcCFlags, got %d", len(expectedCFlags), len(config.ExportCFlags)) } else { for i, expected := range expectedCFlags { - if config.LibcCFlags[i] != expected { - t.Errorf("LibcCFlags[%d] mismatch. Expected '%s', got '%s'", i, expected, config.LibcCFlags[i]) + if config.ExportCFlags[i] != expected { + t.Errorf("LibcCFlags[%d] mismatch. Expected '%s', got '%s'", i, expected, config.ExportCFlags[i]) } } } @@ -288,17 +270,6 @@ func TestGetNewlibESP32ConfigXtensa(t *testing.T) { config := getNewlibESP32ConfigXtensa(baseDir, target) - // Test basic configuration - if config.Url != _newlibUrl { - t.Errorf("Expected URL '%s', got '%s'", _newlibUrl, config.Url) - } - if config.Name != "newlib-esp32" { - t.Errorf("Expected Name 'newlib-esp32', got '%s'", config.Name) - } - if config.ArchiveSrcDir != _archiveInternalSrcDir { - t.Errorf("Expected ArchiveSrcDir '%s', got '%s'", _archiveInternalSrcDir, config.ArchiveSrcDir) - } - // Test LibcCFlags libcDir := filepath.Join(baseDir, "newlib", "libc") expectedCFlags := []string{ @@ -306,12 +277,12 @@ func TestGetNewlibESP32ConfigXtensa(t *testing.T) { "-I" + filepath.Join(baseDir, "newlib"), "-I" + libcDir, } - if len(config.LibcCFlags) != len(expectedCFlags) { - t.Errorf("Expected %d LibcCFlags, got %d", len(expectedCFlags), len(config.LibcCFlags)) + if len(config.ExportCFlags) != len(expectedCFlags) { + t.Errorf("Expected %d LibcCFlags, got %d", len(expectedCFlags), len(config.ExportCFlags)) } else { for i, expected := range expectedCFlags { - if config.LibcCFlags[i] != expected { - t.Errorf("LibcCFlags[%d] mismatch. Expected '%s', got '%s'", i, expected, config.LibcCFlags[i]) + if config.ExportCFlags[i] != expected { + t.Errorf("LibcCFlags[%d] mismatch. Expected '%s', got '%s'", i, expected, config.ExportCFlags[i]) } } } @@ -407,8 +378,8 @@ func TestEdgeCases(t *testing.T) { // Check that paths are constructed correctly expected := "-isystem" + filepath.Join(libcDir, "include") - if config.LibcCFlags[0] != expected { - t.Errorf("Expected LibcCFlags[0] to be '%s', got '%s'", expected, config.LibcCFlags[0]) + if config.ExportCFlags[0] != expected { + t.Errorf("Expected LibcCFlags[0] to be '%s', got '%s'", expected, config.ExportCFlags[0]) } }) @@ -428,8 +399,8 @@ func TestEdgeCases(t *testing.T) { // Check that paths are constructed correctly expected := "-I" + filepath.Join(libcDir, "include") - if config.LibcCFlags[0] != expected { - t.Errorf("Expected LibcCFlags[0] to be '%s', got '%s'", expected, config.LibcCFlags[0]) + if config.ExportCFlags[0] != expected { + t.Errorf("Expected LibcCFlags[0] to be '%s', got '%s'", expected, config.ExportCFlags[0]) } }) diff --git a/internal/crosscompile/compile/libc/newlibesp.go b/internal/crosscompile/compile/libc/newlibesp.go index 23d7930d..dd6c57fb 100644 --- a/internal/crosscompile/compile/libc/newlibesp.go +++ b/internal/crosscompile/compile/libc/newlibesp.go @@ -21,16 +21,20 @@ var _libcCCFlags = []string{ "-ffreestanding", } -const ( - _newlibUrl = "https://github.com/goplus/newlib/archive/refs/tags/v0.2.0.tar.gz" - _archiveInternalSrcDir = "newlib-0.2.0" -) - func withDefaultCCFlags(ccflags []string) []string { return append(ccflags, _libcCCFlags...) } -func getNewlibESP32ConfigRISCV(baseDir, target string) *compile.CompileConfig { +func GetNewlibESP32Config() compile.LibConfig { + return compile.LibConfig{ + Url: "https://github.com/goplus/newlib/archive/refs/tags/v0.3.0.tar.gz", + Name: "newlib-esp32", + Version: "v0.3.0", + ArchiveSrcDir: "newlib-0.3.0", + } +} + +func getNewlibESP32ConfigRISCV(baseDir, target string) compile.CompileConfig { libcDir := filepath.Join(baseDir, "newlib", "libc") libcIncludeDir := []string{ @@ -39,11 +43,8 @@ func getNewlibESP32ConfigRISCV(baseDir, target string) *compile.CompileConfig { "-I" + libcDir, } - return &compile.CompileConfig{ - Url: _newlibUrl, - Name: "newlib-esp32", - LibcCFlags: libcIncludeDir, - ArchiveSrcDir: _archiveInternalSrcDir, + return compile.CompileConfig{ + ExportCFlags: libcIncludeDir, Groups: []compile.CompileGroup{ { OutputFileName: fmt.Sprintf("libcrt0-%s.a", target), @@ -1092,7 +1093,7 @@ func getNewlibESP32ConfigRISCV(baseDir, target string) *compile.CompileConfig { } } -func getNewlibESP32ConfigXtensa(baseDir, target string) *compile.CompileConfig { +func getNewlibESP32ConfigXtensa(baseDir, target string) compile.CompileConfig { libcDir := filepath.Join(baseDir, "newlib", "libc") libcIncludeDir := []string{ @@ -1101,11 +1102,8 @@ func getNewlibESP32ConfigXtensa(baseDir, target string) *compile.CompileConfig { "-I" + libcDir, } - return &compile.CompileConfig{ - Url: _newlibUrl, - Name: "newlib-esp32", - ArchiveSrcDir: _archiveInternalSrcDir, - LibcCFlags: libcIncludeDir, + return compile.CompileConfig{ + ExportCFlags: libcIncludeDir, Groups: []compile.CompileGroup{ { OutputFileName: fmt.Sprintf("libcrt0-%s.a", target), @@ -2075,7 +2073,7 @@ func getNewlibESP32ConfigXtensa(baseDir, target string) *compile.CompileConfig { } // getNewlibESP32Config returns configuration for newlib esp32 -func GetNewlibESP32Config(baseDir, target, mcpu string) *compile.CompileConfig { +func GetNewlibESP32CompileConfig(baseDir, target, mcpu string) compile.CompileConfig { if strings.Contains(target, "riscv32") { return getNewlibESP32ConfigRISCV(baseDir, target) } diff --git a/internal/crosscompile/compile/libc/picolibc.go b/internal/crosscompile/compile/libc/picolibc.go index 7736ccf7..7a6d4b3f 100644 --- a/internal/crosscompile/compile/libc/picolibc.go +++ b/internal/crosscompile/compile/libc/picolibc.go @@ -7,16 +7,22 @@ import ( "github.com/goplus/llgo/internal/crosscompile/compile" ) -// getPicolibcConfig returns configuration for picolibc -func GetPicolibcConfig(baseDir, target string) *compile.CompileConfig { - return &compile.CompileConfig{ - Url: "https://github.com/goplus/picolibc/archive/refs/heads/main.zip", - Name: "picolibc", - LibcCFlags: []string{ +func GetPicolibcConfig() compile.LibConfig { + return compile.LibConfig{ + Name: "picolibc", + Version: "v0.1.0", + Url: "https://github.com/goplus/picolibc/archive/refs/heads/main.zip", + ArchiveSrcDir: "picolibc-main", + } +} + +// GetPicolibcCompileConfig returns configuration for picolibc +func GetPicolibcCompileConfig(baseDir, target string) compile.CompileConfig { + return compile.CompileConfig{ + ExportCFlags: []string{ "-I" + baseDir, "-isystem" + filepath.Join(baseDir, "newlib", "libc", "include"), }, - Groups: []compile.CompileGroup{ { OutputFileName: fmt.Sprintf("libc-%s.a", target), @@ -158,6 +164,5 @@ func GetPicolibcConfig(baseDir, target string) *compile.CompileConfig { CCFlags: _libcCCFlags, }, }, - ArchiveSrcDir: "picolibc-main", } } diff --git a/internal/crosscompile/compile/rtlib/compiler_rt.go b/internal/crosscompile/compile/rtlib/compiler_rt.go index d307132c..1a7f4590 100644 --- a/internal/crosscompile/compile/rtlib/compiler_rt.go +++ b/internal/crosscompile/compile/rtlib/compiler_rt.go @@ -100,10 +100,17 @@ func withPlatformSpecifiedFiles(baseDir, target string, files []string) []string return append(files, platformSpecifiedFiles(builtinsDir, target)...) } -func GetCompilerRTConfig(baseDir, target string) *compile.CompileConfig { - return &compile.CompileConfig{ +func GetCompilerRTConfig() compile.LibConfig { + return compile.LibConfig{ + Name: "compiler-rt", Url: "https://github.com/goplus/compiler-rt/archive/refs/tags/v0.1.0.tar.gz", + Version: "v0.1.0", ArchiveSrcDir: "compiler-rt-0.1.0", + } +} + +func GetCompilerRTCompileConfig(baseDir, target string) compile.CompileConfig { + return compile.CompileConfig{ Groups: []compile.CompileGroup{ { OutputFileName: fmt.Sprintf("libclang_builtins-%s.a", target), @@ -277,7 +284,8 @@ func GetCompilerRTConfig(baseDir, target string) *compile.CompileConfig { "-Werror=return-stack-address", "-Werror=sizeof-array-decay", "-Werror=format-insufficient-args", - "-Wformat -std=c11", + "-Wformat", + "-std=c11", "-fno-builtin", "-fvisibility=hidden", "-fomit-frame-pointer", diff --git a/internal/crosscompile/compile/rtlib/rt_test.go b/internal/crosscompile/compile/rtlib/rt_test.go index 58aeb05e..ca18e1b5 100644 --- a/internal/crosscompile/compile/rtlib/rt_test.go +++ b/internal/crosscompile/compile/rtlib/rt_test.go @@ -60,7 +60,7 @@ func TestGetCompilerRTConfig(t *testing.T) { baseDir := "/test/base" target := "riscv32-unknown-elf" - config := GetCompilerRTConfig(baseDir, target) + config := GetCompilerRTCompileConfig(baseDir, target) // Test groups configuration if len(config.Groups) != 1 { @@ -101,15 +101,8 @@ func TestGetCompilerRTConfig_DifferentTargets(t *testing.T) { baseDir := "/test/base" for _, target := range targets { t.Run(target, func(t *testing.T) { - config := GetCompilerRTConfig(baseDir, target) + config := GetCompilerRTCompileConfig(baseDir, target) - // Basic validation - if config.Url == "" { - t.Error("URL should not be empty") - } - if config.ArchiveSrcDir == "" { - t.Error("ArchiveSrcDir should not be empty") - } if len(config.Groups) == 0 { t.Error("Should have at least one group") } diff --git a/internal/crosscompile/crosscompile.go b/internal/crosscompile/crosscompile.go index fbd8962a..7c2d1dd4 100644 --- a/internal/crosscompile/crosscompile.go +++ b/internal/crosscompile/crosscompile.go @@ -171,16 +171,10 @@ func ldFlagsFromFileName(fileName string) string { return strings.TrimPrefix(strings.TrimSuffix(fileName, ".a"), "lib") } -func getOrCompileWithConfig( - compileConfig *compile.CompileConfig, +func compileWithConfig( + compileConfig compile.CompileConfig, outputDir string, options compile.CompileOptions, ) (ldflags []string, err error) { - if err = checkDownloadAndExtractLib( - compileConfig.Url, outputDir, - compileConfig.ArchiveSrcDir, - ); err != nil { - return - } ldflags = append(ldflags, "-nostdlib", "-L"+outputDir) for _, group := range compileConfig.Groups { @@ -586,16 +580,16 @@ func UseTarget(targetName string) (export Export, err error) { var libcIncludeDir []string if config.Libc != "" { + var outputDir string var libcLDFlags []string - var compileConfig *compile.CompileConfig + var compileConfig compile.CompileConfig baseDir := filepath.Join(cacheRoot(), "crosscompile") - outputDir := filepath.Join(baseDir, config.Libc) - compileConfig, err = getLibcCompileConfigByName(baseDir, config.Libc, config.LLVMTarget, config.CPU) + outputDir, compileConfig, err = getLibcCompileConfigByName(baseDir, config.Libc, config.LLVMTarget, config.CPU) if err != nil { return } - libcLDFlags, err = getOrCompileWithConfig(compileConfig, outputDir, compile.CompileOptions{ + libcLDFlags, err = compileWithConfig(compileConfig, outputDir, compile.CompileOptions{ CC: export.CC, Linker: export.Linker, CCFLAGS: ccflags, @@ -604,24 +598,24 @@ func UseTarget(targetName string) (export Export, err error) { if err != nil { return } - cflags = append(cflags, compileConfig.LibcCFlags...) + cflags = append(cflags, compileConfig.ExportCFlags...) ldflags = append(ldflags, libcLDFlags...) - libcIncludeDir = compileConfig.LibcCFlags + libcIncludeDir = compileConfig.ExportCFlags export.Libc = config.Libc } if config.RTLib != "" { + var outputDir string var rtLibLDFlags []string - var compileConfig *compile.CompileConfig + var compileConfig compile.CompileConfig baseDir := filepath.Join(cacheRoot(), "crosscompile") - outputDir := filepath.Join(baseDir, config.RTLib) - compileConfig, err = getRTCompileConfigByName(baseDir, config.RTLib, config.LLVMTarget) + outputDir, compileConfig, err = getRTCompileConfigByName(baseDir, config.RTLib, config.LLVMTarget) if err != nil { return } - rtLibLDFlags, err = getOrCompileWithConfig(compileConfig, outputDir, compile.CompileOptions{ + rtLibLDFlags, err = compileWithConfig(compileConfig, outputDir, compile.CompileOptions{ CC: export.CC, Linker: export.Linker, CCFLAGS: ccflags, diff --git a/internal/crosscompile/libc.go b/internal/crosscompile/libc.go index fdbb7307..fb255419 100644 --- a/internal/crosscompile/libc.go +++ b/internal/crosscompile/libc.go @@ -9,34 +9,68 @@ import ( "github.com/goplus/llgo/internal/crosscompile/compile/rtlib" ) +// for testing, in testing env, we use fake path, it will cause downloading failure +var needSkipDownload = false + // GetCompileConfigByName retrieves libc compilation configuration by name // Returns compilation file lists and corresponding cflags -func getLibcCompileConfigByName(baseDir, libcName, target, mcpu string) (*compile.CompileConfig, error) { +func getLibcCompileConfigByName(baseDir, libcName, target, mcpu string) (outputDir string, cfg compile.CompileConfig, err error) { if libcName == "" { - return nil, fmt.Errorf("libc name cannot be empty") + err = fmt.Errorf("libc name cannot be empty") + return } - libcDir := filepath.Join(baseDir, libcName) + var libcDir string + var config compile.LibConfig + var compileConfig compile.CompileConfig switch libcName { case "picolibc": - return libc.GetPicolibcConfig(libcDir, target), nil + config = libc.GetPicolibcConfig() + libcDir = filepath.Join(baseDir, config.String()) + compileConfig = libc.GetPicolibcCompileConfig(libcDir, target) case "newlib-esp32": - return libc.GetNewlibESP32Config(libcDir, target, mcpu), nil + config = libc.GetNewlibESP32Config() + libcDir = filepath.Join(baseDir, config.String()) + compileConfig = libc.GetNewlibESP32CompileConfig(libcDir, target, mcpu) default: - return nil, fmt.Errorf("unsupported libc: %s", libcName) + err = fmt.Errorf("unsupported libc: %s", libcName) + return } + if needSkipDownload { + return libcDir, compileConfig, err + } + + if err = checkDownloadAndExtractLib(config.Url, libcDir, config.ArchiveSrcDir); err != nil { + return + } + + return libcDir, compileConfig, nil } -func getRTCompileConfigByName(baseDir, rtName, target string) (*compile.CompileConfig, error) { +func getRTCompileConfigByName(baseDir, rtName, target string) (outputDir string, cfg compile.CompileConfig, err error) { if rtName == "" { - return nil, fmt.Errorf("rt name cannot be empty") + err = fmt.Errorf("rt name cannot be empty") + return } - rtDir := filepath.Join(baseDir, rtName) + var rtDir string + var config compile.LibConfig + var compileConfig compile.CompileConfig switch rtName { case "compiler-rt": - return rtlib.GetCompilerRTConfig(rtDir, target), nil + config = rtlib.GetCompilerRTConfig() + rtDir = filepath.Join(baseDir, config.String()) + compileConfig = rtlib.GetCompilerRTCompileConfig(rtDir, target) default: - return nil, fmt.Errorf("unsupported rt: %s", rtName) + err = fmt.Errorf("unsupported rt: %s", rtName) } + if needSkipDownload { + return rtDir, compileConfig, err + } + + if err = checkDownloadAndExtractLib(config.Url, rtDir, config.ArchiveSrcDir); err != nil { + return + } + + return rtDir, compileConfig, nil } diff --git a/internal/crosscompile/libc_test.go b/internal/crosscompile/libc_test.go index 5953d56c..f03a4646 100644 --- a/internal/crosscompile/libc_test.go +++ b/internal/crosscompile/libc_test.go @@ -3,9 +3,14 @@ package crosscompile import ( + "fmt" "path/filepath" "slices" + "strings" "testing" + + "github.com/goplus/llgo/internal/crosscompile/compile/libc" + "github.com/goplus/llgo/internal/crosscompile/compile/rtlib" ) func TestGetLibcCompileConfigByName(t *testing.T) { @@ -13,22 +18,23 @@ func TestGetLibcCompileConfigByName(t *testing.T) { target := "armv7" mcpu := "cortex-m4" + needSkipDownload = true t.Run("EmptyName", func(t *testing.T) { - _, err := getLibcCompileConfigByName(baseDir, "", target, mcpu) + _, _, err := getLibcCompileConfigByName(baseDir, "", target, mcpu) if err == nil || err.Error() != "libc name cannot be empty" { t.Errorf("Expected empty name error, got: %v", err) } }) t.Run("UnsupportedLibc", func(t *testing.T) { - _, err := getLibcCompileConfigByName(baseDir, "invalid", target, mcpu) + _, _, err := getLibcCompileConfigByName(baseDir, "invalid", target, mcpu) if err == nil || err.Error() != "unsupported libc: invalid" { t.Errorf("Expected unsupported libc error, got: %v", err) } }) t.Run("Picolibc", func(t *testing.T) { - cfg, err := getLibcCompileConfigByName(baseDir, "picolibc", target, mcpu) + _, cfg, err := getLibcCompileConfigByName(baseDir, "picolibc", target, mcpu) if err != nil { t.Fatalf("Unexpected error: %v", err) } @@ -38,19 +44,19 @@ func TestGetLibcCompileConfigByName(t *testing.T) { } group := cfg.Groups[0] - expectedFile := filepath.Join(baseDir, "picolibc", "newlib", "libc", "string", "memmem.c") + expectedFile := filepath.Join(baseDir, libc.GetPicolibcConfig().String(), "newlib", "libc", "string", "memmem.c") if !slices.Contains(group.Files, expectedFile) { t.Errorf("Expected files [%s], got: %v", expectedFile, group.Files) } - expectedFlag := "-I" + filepath.Join("/test", "base", "picolibc") + expectedFlag := "-I" + filepath.Join("/test", "base", libc.GetPicolibcConfig().String()) if !slices.Contains(group.CFlags, expectedFlag) { t.Errorf("Expected flags [%s], got: %v", expectedFlag, group.CFlags) } }) t.Run("NewlibESP32", func(t *testing.T) { - cfg, err := getLibcCompileConfigByName(baseDir, "newlib-esp32", target, mcpu) + _, cfg, err := getLibcCompileConfigByName(baseDir, "newlib-esp32", target, mcpu) if err != nil { t.Fatalf("Unexpected error: %v", err) } @@ -60,12 +66,12 @@ func TestGetLibcCompileConfigByName(t *testing.T) { } group := cfg.Groups[0] - expectedFile := filepath.Join(baseDir, "newlib-esp32", "libgloss", "xtensa", "crt1-boards.S") + expectedFile := filepath.Join(baseDir, libc.GetNewlibESP32Config().String(), "libgloss", "xtensa", "crt1-boards.S") if !slices.Contains(group.Files, expectedFile) { t.Errorf("Expected files [%s], got: %v", expectedFile, group.Files) } - expectedFlags := "-I" + filepath.Join(baseDir, "newlib-esp32", "libgloss") + expectedFlags := "-I" + filepath.Join(baseDir, libc.GetNewlibESP32Config().String(), "libgloss") if !slices.Contains(group.CFlags, expectedFlags) { t.Errorf("Expected flags %v, got: %v", expectedFlags, group.CFlags) } @@ -75,23 +81,24 @@ func TestGetLibcCompileConfigByName(t *testing.T) { func TestGetRTCompileConfigByName(t *testing.T) { baseDir := "/test/base" target := "wasm32" + needSkipDownload = true t.Run("EmptyName", func(t *testing.T) { - _, err := getRTCompileConfigByName(baseDir, "", target) + _, _, err := getRTCompileConfigByName(baseDir, "", target) if err == nil || err.Error() != "rt name cannot be empty" { t.Errorf("Expected empty name error, got: %v", err) } }) t.Run("UnsupportedRT", func(t *testing.T) { - _, err := getRTCompileConfigByName(baseDir, "invalid", target) + _, _, err := getRTCompileConfigByName(baseDir, "invalid", target) if err == nil || err.Error() != "unsupported rt: invalid" { t.Errorf("Expected unsupported rt error, got: %v", err) } }) t.Run("CompilerRT", func(t *testing.T) { - cfg, err := getRTCompileConfigByName(baseDir, "compiler-rt", target) + _, cfg, err := getRTCompileConfigByName(baseDir, "compiler-rt", target) if err != nil { t.Fatalf("Unexpected error: %v", err) } @@ -101,9 +108,302 @@ func TestGetRTCompileConfigByName(t *testing.T) { } group := cfg.Groups[0] - expectedFile := filepath.Join(baseDir, "compiler-rt", "lib", "builtins", "absvdi2.c") + expectedFile := filepath.Join(baseDir, rtlib.GetCompilerRTConfig().String(), "lib", "builtins", "absvdi2.c") if !slices.Contains(group.Files, expectedFile) { t.Errorf("Expected files [%s], got: %v", expectedFile, group.Files) } }) } + +// TestCompilerRTCompileConfigPaths tests that file paths in the CompileConfig +// are correctly based on the provided baseDir for various target platforms. +func TestCompilerRTCompileConfigPaths(t *testing.T) { + // Define test cases for different target platforms + tests := []struct { + name string // Test case name + baseDir string // Input base directory + target string // Target platform + expected string // Expected platform-specific file + }{ + { + name: "RISC-V 32", + baseDir: "/test/base/dir", + target: "riscv32-unknown-elf", + expected: "riscv/mulsi3.S", // Expected platform file for RISC-V 32 + }, + { + name: "RISC-V 64", + baseDir: "/another/dir", + target: "riscv64-unknown-elf", + expected: "addtf3.c", // Expected platform file for RISC-V 64 + }, + { + name: "ARM", + baseDir: "/arm/dir", + target: "armv7-unknown-linux-gnueabihf", + expected: "arm/aeabi_cdcmp.S", // Expected platform file for ARM + }, + { + name: "AVR", + baseDir: "/avr/dir", + target: "avr", + expected: "avr/divmodhi4.S", // Expected platform file for AVR + }, + { + name: "XTENSA", + baseDir: "/xtensa/dir", + target: "xtensa", + expected: "xtensa/ieee754_sqrtf.S", // Expected platform file for XTENSA + }, + } + needSkipDownload = true + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + // Get the compile configuration for this target + cfg := rtlib.GetCompilerRTCompileConfig(tt.baseDir, tt.target) + + // Verify there is at least one compile group + if len(cfg.Groups) == 0 { + t.Fatal("CompileConfig has no groups") + } + + group := cfg.Groups[0] + found := false + + // Check all files in the group + for _, file := range group.Files { + // Verify file path starts with baseDir + if !strings.HasPrefix(file, tt.baseDir) { + t.Errorf("File path %q should start with baseDir %q", file, tt.baseDir) + } + + // Verify file path contains the expected platform-specific file + if strings.Contains(file, tt.expected) { + found = true + + // Construct the expected full path + expectedPath := filepath.Join(tt.baseDir, "lib", "builtins", tt.expected) + + // Verify the actual path matches the expected path + if file != expectedPath { + t.Errorf("Expected file path %q, got %q", expectedPath, file) + } + } + } + + // Verify the platform-specific file was found + if !found { + t.Errorf("Expected platform-specific file %q not found in file list", tt.expected) + } + + // Verify the output file name format + expectedOutput := fmt.Sprintf("libclang_builtins-%s.a", tt.target) + if !strings.HasSuffix(group.OutputFileName, expectedOutput) { + t.Errorf("OutputFileName should end with %q, got %q", expectedOutput, group.OutputFileName) + } + }) + } +} + +// TestCompilerRTCompileConfigPathRelations tests the general path relationships +// in the CompileConfig for a specific target. +func TestCompilerRTCompileConfigPathRelations(t *testing.T) { + baseDir := "/test/base/dir" + target := "riscv64-unknown-elf" + + // Get the compile configuration + cfg := rtlib.GetCompilerRTCompileConfig(baseDir, target) + + // Verify there is at least one compile group + if len(cfg.Groups) == 0 { + t.Fatal("CompileConfig has no groups") + } + needSkipDownload = true + + group := cfg.Groups[0] + + // Check all files in the group + for _, file := range group.Files { + // Verify file path starts with baseDir + if !strings.HasPrefix(file, baseDir) { + t.Errorf("File path %q should start with baseDir %q", file, baseDir) + } + + // Verify file path contains the expected subdirectory structure + expectedSubdir := filepath.Join(baseDir, "lib", "builtins") + if !strings.Contains(file, expectedSubdir) { + t.Errorf("File path %q should contain %q", file, expectedSubdir) + } + } + + // Verify the output file name format + expectedOutput := fmt.Sprintf("libclang_builtins-%s.a", target) + if !strings.HasSuffix(group.OutputFileName, expectedOutput) { + t.Errorf("OutputFileName should end with %q, got %q", expectedOutput, group.OutputFileName) + } +} + +// TestGetPicolibcCompileConfigPaths tests that all paths in the CompileConfig +// are correctly based on the provided baseDir. +func TestGetPicolibcCompileConfigPaths(t *testing.T) { + // Define test cases with different base directories + tests := []struct { + name string + baseDir string + target string + }{ + { + name: "Unix-like path", + baseDir: "/test/base/dir", + target: "riscv64-unknown-elf", + }, + { + name: "Windows-like path", + baseDir: "C:\\test\\base\\dir", + target: "x86_64-pc-windows-msvc", + }, + { + name: "Relative path", + baseDir: "test/base/dir", + target: "armv7-unknown-linux-gnueabihf", + }, + } + needSkipDownload = true + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + // Get the compile configuration + cfg := libc.GetPicolibcCompileConfig(tt.baseDir, tt.target) + + // Verify ExportCFlags paths + for _, flag := range cfg.ExportCFlags { + if strings.HasPrefix(flag, "-I") || strings.HasPrefix(flag, "-isystem") { + path := strings.TrimPrefix(flag, "-I") + path = strings.TrimPrefix(path, "-isystem") + path = strings.TrimSpace(path) + + if !strings.HasPrefix(path, tt.baseDir) { + t.Errorf("ExportCFlags path %q should start with baseDir %q", path, tt.baseDir) + } + } + } + + // Verify there is at least one compile group + if len(cfg.Groups) == 0 { + t.Fatal("CompileConfig has no groups") + } + + group := cfg.Groups[0] + + // Verify output file name format + expectedOutput := fmt.Sprintf("libc-%s.a", tt.target) + if group.OutputFileName != expectedOutput { + t.Errorf("Expected OutputFileName %q, got %q", expectedOutput, group.OutputFileName) + } + + // Verify all file paths start with baseDir + for _, file := range group.Files { + if !strings.HasPrefix(file, tt.baseDir) { + t.Errorf("File path %q should start with baseDir %q", file, tt.baseDir) + } + + // Verify file path contains expected subdirectories + if !strings.Contains(file, filepath.Join(tt.baseDir, "newlib")) { + t.Errorf("File path %q should contain 'newlib' subdirectory", file) + } + } + + // Verify CFlags paths + for _, flag := range group.CFlags { + if strings.HasPrefix(flag, "-I") { + path := strings.TrimPrefix(flag, "-I") + path = strings.TrimSpace(path) + + if !strings.HasPrefix(path, tt.baseDir) { + t.Errorf("CFlags path %q should start with baseDir %q", path, tt.baseDir) + } + } + } + }) + } +} + +// TestGetPicolibcCompileConfigSpecificPaths tests specific path constructions +// in the CompileConfig for a given baseDir and target. +func TestGetPicolibcCompileConfigSpecificPaths(t *testing.T) { + baseDir := "/test/base/dir" + target := "riscv64-unknown-elf" + needSkipDownload = true + + // Get the compile configuration + cfg := libc.GetPicolibcCompileConfig(baseDir, target) + + // Verify ExportCFlags + expectedInclude := filepath.Join(baseDir, "newlib", "libc", "include") + foundInclude := false + for _, flag := range cfg.ExportCFlags { + if flag == "-I"+baseDir || flag == "-isystem"+expectedInclude { + foundInclude = true + } + } + if !foundInclude { + t.Errorf("Expected ExportCFlags to contain -I%s and -isystem%s", baseDir, expectedInclude) + } + + // Verify there is at least one compile group + if len(cfg.Groups) == 0 { + t.Fatal("CompileConfig has no groups") + } + + group := cfg.Groups[0] + + // Verify output file name + expectedOutput := fmt.Sprintf("libc-%s.a", target) + if group.OutputFileName != expectedOutput { + t.Errorf("Expected OutputFileName %q, got %q", expectedOutput, group.OutputFileName) + } + + // Verify specific file paths + expectedFiles := []string{ + filepath.Join(baseDir, "newlib", "libc", "string", "memcpy.c"), + filepath.Join(baseDir, "newlib", "libc", "string", "strlen.c"), + filepath.Join(baseDir, "newlib", "libc", "stdlib", "nano-malloc.c"), + filepath.Join(baseDir, "newlib", "libc", "tinystdio", "printf.c"), + } + + for _, expected := range expectedFiles { + found := false + for _, file := range group.Files { + if file == expected { + found = true + break + } + } + if !found { + t.Errorf("Expected file %q not found in file list", expected) + } + } + + // Verify CFlags paths + expectedCFlags := []string{ + "-I" + baseDir, + "-isystem" + filepath.Join(baseDir, "newlib", "libc", "include"), + "-I" + filepath.Join(baseDir, "newlib", "libm", "common"), + "-I" + filepath.Join(baseDir, "newlib", "libc", "locale"), + "-I" + filepath.Join(baseDir, "newlib", "libc", "tinystdio"), + } + + for _, expected := range expectedCFlags { + found := false + for _, flag := range group.CFlags { + if flag == expected { + found = true + break + } + } + if !found { + t.Errorf("Expected CFlag %q not found", expected) + } + } +} From f573ebe40bb0a05f01bf67b9176a61adb0112235 Mon Sep 17 00:00:00 2001 From: Haolan Date: Thu, 4 Sep 2025 19:13:58 +0800 Subject: [PATCH 23/29] fix: xtensa stdio --- targets/esp32.app.elf.ld | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/targets/esp32.app.elf.ld b/targets/esp32.app.elf.ld index 88e6cf26..beab0485 100755 --- a/targets/esp32.app.elf.ld +++ b/targets/esp32.app.elf.ld @@ -5,23 +5,6 @@ ENTRY(_start) SECTIONS { . = SEGMENT_START("iram_seg", 0); - .vectors : - { - _vector_table = ABSOLUTE(.); - KEEP(*(.WindowVectors.text)); - KEEP(*(.Level2InterruptVector.text)); - KEEP(*(.Level3InterruptVector.text)); - KEEP(*(.Level4InterruptVector.text)); - KEEP(*(.Level5InterruptVector.text)); - KEEP(*(.DebugExceptionVector.text)); - KEEP(*(.NMIExceptionVector.text)); - KEEP(*(.KernelExceptionVector.text)); - KEEP(*(.UserExceptionVector.text)); - KEEP(*(.DoubleExceptionVector.text)); - KEEP(*(.ResetVector.text)); - *(.*Vector.literal) - . = ALIGN (16); - } > iram_seg text : { From b239494a9f1695b875e36336c591260ba932077e Mon Sep 17 00:00:00 2001 From: Haolan Date: Fri, 5 Sep 2025 15:38:14 +0800 Subject: [PATCH 24/29] test: add test for getting config --- .../crosscompile/compile/libc/libc_test.go | 178 +++++++++++++++++- .../crosscompile/compile/libc/newlibesp.go | 6 +- .../crosscompile/compile/rtlib/compiler_rt.go | 6 +- .../crosscompile/compile/rtlib/rt_test.go | 31 +++ 4 files changed, 214 insertions(+), 7 deletions(-) diff --git a/internal/crosscompile/compile/libc/libc_test.go b/internal/crosscompile/compile/libc/libc_test.go index 3689d9fa..383c116a 100644 --- a/internal/crosscompile/compile/libc/libc_test.go +++ b/internal/crosscompile/compile/libc/libc_test.go @@ -2,10 +2,73 @@ package libc import ( "path/filepath" + "strings" "testing" ) -func TestGetPicolibcConfig(t *testing.T) { +func TestGetNewlibESP32Config_LibConfig(t *testing.T) { + config := GetNewlibESP32Config() + + // Test basic configuration fields + expectedName := "newlib-esp32" + if config.Name != expectedName { + t.Errorf("Expected Name '%s', got '%s'", expectedName, config.Name) + } + + expectedVersion := "esp-4.3.0_20250211-patch2" + if config.Version != expectedVersion { + t.Errorf("Expected Version '%s', got '%s'", expectedVersion, config.Version) + } + + expectedUrl := "https://github.com/goplus/newlib/archive/refs/tags/esp-4.3.0_20250211-patch2.tar.gz" + if config.Url != expectedUrl { + t.Errorf("Expected Url '%s', got '%s'", expectedUrl, config.Url) + } + + expectedArchiveSrcDir := "newlib-esp-4.3.0_20250211-patch2" + if config.ArchiveSrcDir != expectedArchiveSrcDir { + t.Errorf("Expected ArchiveSrcDir '%s', got '%s'", expectedArchiveSrcDir, config.ArchiveSrcDir) + } + + // Test String() method + expectedString := "newlib-esp32-esp-4.3.0_20250211-patch2" + if config.String() != expectedString { + t.Errorf("Expected String() '%s', got '%s'", expectedString, config.String()) + } +} + +func TestGetPicolibcConfig_LibConfig(t *testing.T) { + config := GetPicolibcConfig() + + // Test basic configuration fields + expectedName := "picolibc" + if config.Name != expectedName { + t.Errorf("Expected Name '%s', got '%s'", expectedName, config.Name) + } + + expectedVersion := "v0.1.0" + if config.Version != expectedVersion { + t.Errorf("Expected Version '%s', got '%s'", expectedVersion, config.Version) + } + + expectedUrl := "https://github.com/goplus/picolibc/archive/refs/heads/main.zip" + if config.Url != expectedUrl { + t.Errorf("Expected Url '%s', got '%s'", expectedUrl, config.Url) + } + + expectedArchiveSrcDir := "picolibc-main" + if config.ArchiveSrcDir != expectedArchiveSrcDir { + t.Errorf("Expected ArchiveSrcDir '%s', got '%s'", expectedArchiveSrcDir, config.ArchiveSrcDir) + } + + // Test String() method + expectedString := "picolibc-v0.1.0" + if config.String() != expectedString { + t.Errorf("Expected String() '%s', got '%s'", expectedString, config.String()) + } +} + +func TestGetPicolibcCompileConfig(t *testing.T) { baseDir := "/test/base" target := "test-target" @@ -131,6 +194,119 @@ func TestGetPicolibcConfig_EdgeCases(t *testing.T) { }) } +func TestPicolibcFileStructure(t *testing.T) { + baseDir := "/test/base" + target := "test-target" + + config := GetPicolibcCompileConfig(baseDir, target) + group := config.Groups[0] + + // Test that all files have .c extension (no assembly files in picolibc config) + for _, file := range group.Files { + if !strings.HasSuffix(file, ".c") { + t.Errorf("File '%s' does not have .c extension", file) + } + } + + // Test that files are from expected directories + stringFiles := 0 + stdlibFiles := 0 + tinystdioFiles := 0 + + for _, file := range group.Files { + if strings.Contains(file, "/string/") { + stringFiles++ + } else if strings.Contains(file, "/stdlib/") { + stdlibFiles++ + } else if strings.Contains(file, "/tinystdio/") { + tinystdioFiles++ + } + } + + if stringFiles < 50 { + t.Errorf("Expected at least 50 string files, got %d", stringFiles) + } + if stdlibFiles < 5 { + t.Errorf("Expected at least 5 stdlib files, got %d", stdlibFiles) + } + if tinystdioFiles < 3 { + t.Errorf("Expected at least 3 tinystdio files, got %d", tinystdioFiles) + } + + // Test that all files have correct base directory + for _, file := range group.Files { + if !strings.HasPrefix(file, baseDir) { + t.Errorf("File '%s' does not have expected base directory '%s'", file, baseDir) + } + } +} + +func TestPicolibcCompilerFlags(t *testing.T) { + baseDir := "/test/base" + target := "test-target" + + config := GetPicolibcCompileConfig(baseDir, target) + group := config.Groups[0] + + // Test that required preprocessor definitions are present + requiredDefines := []string{ + "-D_COMPILING_NEWLIB", + "-D_HAVE_ALIAS_ATTRIBUTE", + "-DTINY_STDIO", + "-DPOSIX_IO", + "-DFORMAT_DEFAULT_INTEGER", + "-D_IEEE_LIBM", + "-D_WANT_IO_C99_FORMATS", + } + + for _, define := range requiredDefines { + found := false + for _, flag := range group.CFlags { + if flag == define { + found = true + break + } + } + if !found { + t.Errorf("Required define '%s' not found in CFlags", define) + } + } + + // Test that required include paths are present + requiredIncludes := []string{ + "-I" + baseDir, + "-isystem" + filepath.Join(baseDir, "newlib", "libc", "include"), + "-I" + filepath.Join(baseDir, "newlib", "libm", "common"), + "-I" + filepath.Join(baseDir, "newlib", "libc", "locale"), + "-I" + filepath.Join(baseDir, "newlib", "libc", "tinystdio"), + } + + for _, include := range requiredIncludes { + found := false + for _, flag := range group.CFlags { + if flag == include { + found = true + break + } + } + if !found { + t.Errorf("Required include '%s' not found in CFlags", include) + } + } + + // Test that nostdlib is present + found := false + for _, flag := range group.CFlags { + if flag == "-nostdlib" { + found = true + break + } + } + if !found { + t.Error("Required flag '-nostdlib' not found in CFlags") + } +} + func TestGetNewlibESP32ConfigRISCV(t *testing.T) { baseDir := "/test/base" target := "riscv32-unknown-elf" diff --git a/internal/crosscompile/compile/libc/newlibesp.go b/internal/crosscompile/compile/libc/newlibesp.go index dd6c57fb..95f30622 100644 --- a/internal/crosscompile/compile/libc/newlibesp.go +++ b/internal/crosscompile/compile/libc/newlibesp.go @@ -27,10 +27,10 @@ func withDefaultCCFlags(ccflags []string) []string { func GetNewlibESP32Config() compile.LibConfig { return compile.LibConfig{ - Url: "https://github.com/goplus/newlib/archive/refs/tags/v0.3.0.tar.gz", + Url: "https://github.com/goplus/newlib/archive/refs/tags/esp-4.3.0_20250211-patch2.tar.gz", Name: "newlib-esp32", - Version: "v0.3.0", - ArchiveSrcDir: "newlib-0.3.0", + Version: "esp-4.3.0_20250211-patch2", + ArchiveSrcDir: "newlib-esp-4.3.0_20250211-patch2", } } diff --git a/internal/crosscompile/compile/rtlib/compiler_rt.go b/internal/crosscompile/compile/rtlib/compiler_rt.go index 1a7f4590..d526251c 100644 --- a/internal/crosscompile/compile/rtlib/compiler_rt.go +++ b/internal/crosscompile/compile/rtlib/compiler_rt.go @@ -103,9 +103,9 @@ func withPlatformSpecifiedFiles(baseDir, target string, files []string) []string func GetCompilerRTConfig() compile.LibConfig { return compile.LibConfig{ Name: "compiler-rt", - Url: "https://github.com/goplus/compiler-rt/archive/refs/tags/v0.1.0.tar.gz", - Version: "v0.1.0", - ArchiveSrcDir: "compiler-rt-0.1.0", + Url: "https://github.com/goplus/compiler-rt/archive/refs/tags/xtensa_release_19.1.2.tar.gz", + Version: "xtensa_release_19.1.2", + ArchiveSrcDir: "compiler-rt-xtensa_release_19.1.2", } } diff --git a/internal/crosscompile/compile/rtlib/rt_test.go b/internal/crosscompile/compile/rtlib/rt_test.go index ca18e1b5..427ecd5b 100644 --- a/internal/crosscompile/compile/rtlib/rt_test.go +++ b/internal/crosscompile/compile/rtlib/rt_test.go @@ -5,6 +5,37 @@ import ( "testing" ) +func TestGetNewlibESP32Config_LibConfig(t *testing.T) { + config := GetCompilerRTConfig() + + // Test basic configuration fields + expectedName := "compiler-rt" + if config.Name != expectedName { + t.Errorf("Expected Name '%s', got '%s'", expectedName, config.Name) + } + + expectedVersion := "xtensa_release_19.1.2" + if config.Version != expectedVersion { + t.Errorf("Expected Version '%s', got '%s'", expectedVersion, config.Version) + } + + expectedUrl := "https://github.com/goplus/compiler-rt/archive/refs/tags/xtensa_release_19.1.2.tar.gz" + if config.Url != expectedUrl { + t.Errorf("Expected Url '%s', got '%s'", expectedUrl, config.Url) + } + + expectedArchiveSrcDir := "compiler-rt-xtensa_release_19.1.2" + if config.ArchiveSrcDir != expectedArchiveSrcDir { + t.Errorf("Expected ArchiveSrcDir '%s', got '%s'", expectedArchiveSrcDir, config.ArchiveSrcDir) + } + + // Test String() method + expectedString := "compiler-rt-xtensa_release_19.1.2" + if config.String() != expectedString { + t.Errorf("Expected String() '%s', got '%s'", expectedString, config.String()) + } +} + func TestPlatformSpecifiedFiles(t *testing.T) { tests := []struct { target string From 6aa63121ffe4de9a584c7e7f44c25c831507f805 Mon Sep 17 00:00:00 2001 From: Haolan Date: Mon, 8 Sep 2025 15:21:55 +0800 Subject: [PATCH 25/29] chore: upgrade newlib --- internal/crosscompile/compile/libc/libc_test.go | 8 ++++---- internal/crosscompile/compile/libc/newlibesp.go | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/internal/crosscompile/compile/libc/libc_test.go b/internal/crosscompile/compile/libc/libc_test.go index 383c116a..7b79675b 100644 --- a/internal/crosscompile/compile/libc/libc_test.go +++ b/internal/crosscompile/compile/libc/libc_test.go @@ -15,23 +15,23 @@ func TestGetNewlibESP32Config_LibConfig(t *testing.T) { t.Errorf("Expected Name '%s', got '%s'", expectedName, config.Name) } - expectedVersion := "esp-4.3.0_20250211-patch2" + expectedVersion := "esp-4.3.0_20250211-patch3" if config.Version != expectedVersion { t.Errorf("Expected Version '%s', got '%s'", expectedVersion, config.Version) } - expectedUrl := "https://github.com/goplus/newlib/archive/refs/tags/esp-4.3.0_20250211-patch2.tar.gz" + expectedUrl := "https://github.com/goplus/newlib/archive/refs/tags/esp-4.3.0_20250211-patch3.tar.gz" if config.Url != expectedUrl { t.Errorf("Expected Url '%s', got '%s'", expectedUrl, config.Url) } - expectedArchiveSrcDir := "newlib-esp-4.3.0_20250211-patch2" + expectedArchiveSrcDir := "newlib-esp-4.3.0_20250211-patch3" if config.ArchiveSrcDir != expectedArchiveSrcDir { t.Errorf("Expected ArchiveSrcDir '%s', got '%s'", expectedArchiveSrcDir, config.ArchiveSrcDir) } // Test String() method - expectedString := "newlib-esp32-esp-4.3.0_20250211-patch2" + expectedString := "newlib-esp32-esp-4.3.0_20250211-patch3" if config.String() != expectedString { t.Errorf("Expected String() '%s', got '%s'", expectedString, config.String()) } diff --git a/internal/crosscompile/compile/libc/newlibesp.go b/internal/crosscompile/compile/libc/newlibesp.go index 95f30622..a2e32149 100644 --- a/internal/crosscompile/compile/libc/newlibesp.go +++ b/internal/crosscompile/compile/libc/newlibesp.go @@ -27,10 +27,10 @@ func withDefaultCCFlags(ccflags []string) []string { func GetNewlibESP32Config() compile.LibConfig { return compile.LibConfig{ - Url: "https://github.com/goplus/newlib/archive/refs/tags/esp-4.3.0_20250211-patch2.tar.gz", + Url: "https://github.com/goplus/newlib/archive/refs/tags/esp-4.3.0_20250211-patch3.tar.gz", Name: "newlib-esp32", - Version: "esp-4.3.0_20250211-patch2", - ArchiveSrcDir: "newlib-esp-4.3.0_20250211-patch2", + Version: "esp-4.3.0_20250211-patch3", + ArchiveSrcDir: "newlib-esp-4.3.0_20250211-patch3", } } From d4474be921b654699ceafb6fb28297c4090c0c76 Mon Sep 17 00:00:00 2001 From: Haolan Date: Tue, 9 Sep 2025 17:45:02 +0800 Subject: [PATCH 26/29] chore: fix some wrong commets --- internal/crosscompile/compile/compile.go | 8 +++++++- internal/crosscompile/compile/compile_test.go | 6 +++--- internal/crosscompile/compile/libc/newlibesp.go | 2 ++ internal/crosscompile/compile/libc/picolibc.go | 1 + internal/crosscompile/crosscompile.go | 4 ++++ internal/crosscompile/crosscompile_test.go | 8 ++++---- internal/crosscompile/libc.go | 4 +++- 7 files changed, 24 insertions(+), 9 deletions(-) diff --git a/internal/crosscompile/compile/compile.go b/internal/crosscompile/compile/compile.go index 01136d8e..acfec5b3 100644 --- a/internal/crosscompile/compile/compile.go +++ b/internal/crosscompile/compile/compile.go @@ -27,12 +27,16 @@ type CompileGroup struct { LDFlags []string // Linker flags } +// IsCompiled checks if the compile group has already been compiled by verifying +// if the output archive file exists in the specified directory func (g CompileGroup) IsCompiled(outputDir string) bool { archive := filepath.Join(outputDir, filepath.Base(g.OutputFileName)) _, err := os.Stat(archive) return err == nil } +// Compile compiles all source files in the group into a static library archive +// If the archive already exists, compilation is skipped func (g CompileGroup) Compile( outputDir string, options CompileOptions, ) (err error) { @@ -101,11 +105,13 @@ type CompileConfig struct { type LibConfig struct { Url string - Name string // compile name (e.g., "picolibc", "musl", "glibc") + Name string // Library name (e.g., "picolibc", "musl", "glibc") Version string ArchiveSrcDir string } +// String returns a string representation of the library configuration +// in the format "name-version" func (cfg LibConfig) String() string { return fmt.Sprintf("%s-%s", cfg.Name, cfg.Version) } diff --git a/internal/crosscompile/compile/compile_test.go b/internal/crosscompile/compile/compile_test.go index f5f5ba7d..eb37254f 100644 --- a/internal/crosscompile/compile/compile_test.go +++ b/internal/crosscompile/compile/compile_test.go @@ -11,8 +11,8 @@ import ( "github.com/goplus/llgo/xtool/nm" ) -func TestIsCompile(t *testing.T) { - t.Run("IsCompile Not Exists", func(t *testing.T) { +func TestIsCompiled(t *testing.T) { + t.Run("IsCompiled Not Exists", func(t *testing.T) { cfg := CompileConfig{ Groups: []CompileGroup{ { @@ -25,7 +25,7 @@ func TestIsCompile(t *testing.T) { t.Errorf("unexpected result: should false") } }) - t.Run("IsCompile Exists", func(t *testing.T) { + t.Run("IsCompiled Exists", func(t *testing.T) { tmpFile, err := os.CreateTemp("", "test*.a") if err != nil { t.Error(err) diff --git a/internal/crosscompile/compile/libc/newlibesp.go b/internal/crosscompile/compile/libc/newlibesp.go index a2e32149..cb55f495 100644 --- a/internal/crosscompile/compile/libc/newlibesp.go +++ b/internal/crosscompile/compile/libc/newlibesp.go @@ -21,10 +21,12 @@ var _libcCCFlags = []string{ "-ffreestanding", } +// withDefaultCCFlags appends default C compiler flags to the provided flags func withDefaultCCFlags(ccflags []string) []string { return append(ccflags, _libcCCFlags...) } +// GetNewlibESP32Config returns the configuration for downloading and building newlib for ESP32 func GetNewlibESP32Config() compile.LibConfig { return compile.LibConfig{ Url: "https://github.com/goplus/newlib/archive/refs/tags/esp-4.3.0_20250211-patch3.tar.gz", diff --git a/internal/crosscompile/compile/libc/picolibc.go b/internal/crosscompile/compile/libc/picolibc.go index 7a6d4b3f..680c1ed7 100644 --- a/internal/crosscompile/compile/libc/picolibc.go +++ b/internal/crosscompile/compile/libc/picolibc.go @@ -7,6 +7,7 @@ import ( "github.com/goplus/llgo/internal/crosscompile/compile" ) +// GetPicolibcConfig returns the configuration for downloading and building picolibc func GetPicolibcConfig() compile.LibConfig { return compile.LibConfig{ Name: "picolibc", diff --git a/internal/crosscompile/crosscompile.go b/internal/crosscompile/crosscompile.go index 7c2d1dd4..025f6293 100644 --- a/internal/crosscompile/crosscompile.go +++ b/internal/crosscompile/crosscompile.go @@ -167,10 +167,14 @@ func getESPClangPlatform(goos, goarch string) string { return "" } +// ldFlagsFromFileName extracts the library name from a filename for use in linker flags +// For example, "libmath.a" becomes "math" for use with "-lmath" func ldFlagsFromFileName(fileName string) string { return strings.TrimPrefix(strings.TrimSuffix(fileName, ".a"), "lib") } +// compileWithConfig compiles libraries according to the provided configuration +// and returns the necessary linker flags for linking against the compiled libraries func compileWithConfig( compileConfig compile.CompileConfig, outputDir string, options compile.CompileOptions, diff --git a/internal/crosscompile/crosscompile_test.go b/internal/crosscompile/crosscompile_test.go index 9856133c..6bf0fcf3 100644 --- a/internal/crosscompile/crosscompile_test.go +++ b/internal/crosscompile/crosscompile_test.go @@ -37,10 +37,10 @@ func TestUseCrossCompileSDK(t *testing.T) { name: "Same Platform", goos: runtime.GOOS, goarch: runtime.GOARCH, - expectSDK: true, // Changed: now we expect flags even for same platform - expectCCFlags: true, // Changed: CCFLAGS will contain sysroot - expectCFlags: false, // Changed: CFLAGS will not contain include paths - expectLDFlags: false, // Changed: LDFLAGS will not contain library paths + expectSDK: true, // We expect flags even for same platform + expectCCFlags: true, // CCFLAGS will contain sysroot + expectCFlags: false, // CFLAGS will not contain include paths + expectLDFlags: false, // LDFLAGS will not contain library paths }, { name: "WASM Target", diff --git a/internal/crosscompile/libc.go b/internal/crosscompile/libc.go index fb255419..b7feefc3 100644 --- a/internal/crosscompile/libc.go +++ b/internal/crosscompile/libc.go @@ -12,7 +12,7 @@ import ( // for testing, in testing env, we use fake path, it will cause downloading failure var needSkipDownload = false -// GetCompileConfigByName retrieves libc compilation configuration by name +// getLibcCompileConfigByName retrieves libc compilation configuration by name // Returns compilation file lists and corresponding cflags func getLibcCompileConfigByName(baseDir, libcName, target, mcpu string) (outputDir string, cfg compile.CompileConfig, err error) { if libcName == "" { @@ -47,6 +47,8 @@ func getLibcCompileConfigByName(baseDir, libcName, target, mcpu string) (outputD return libcDir, compileConfig, nil } +// getRTCompileConfigByName retrieves runtime library compilation configuration by name +// Returns compilation file lists and corresponding flags for the specified runtime library func getRTCompileConfigByName(baseDir, rtName, target string) (outputDir string, cfg compile.CompileConfig, err error) { if rtName == "" { err = fmt.Errorf("rt name cannot be empty") From 8ce6c3b9abc09568567a24e35ab04b8e526efa31 Mon Sep 17 00:00:00 2001 From: Haolan Date: Tue, 9 Sep 2025 17:48:54 +0800 Subject: [PATCH 27/29] chore: fix commets and format Update internal/crosscompile/compile/rtlib/rt_test.go Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> Update internal/crosscompile/compile/libc/libc_test.go Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> Update internal/crosscompile/compile/libc/libc_test.go Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> chore: format contents --- internal/crosscompile/compile/libc/libc_test.go | 4 ++-- internal/crosscompile/compile/rtlib/rt_test.go | 2 +- internal/crosscompile/libc.go | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/internal/crosscompile/compile/libc/libc_test.go b/internal/crosscompile/compile/libc/libc_test.go index 7b79675b..9a994ef3 100644 --- a/internal/crosscompile/compile/libc/libc_test.go +++ b/internal/crosscompile/compile/libc/libc_test.go @@ -325,7 +325,7 @@ func TestGetNewlibESP32ConfigRISCV(t *testing.T) { } else { for i, expected := range expectedCFlags { if config.ExportCFlags[i] != expected { - t.Errorf("LibcCFlags[%d] mismatch. Expected '%s', got '%s'", i, expected, config.ExportCFlags[i]) + t.Errorf("ExportCFlags[%d] mismatch. Expected '%s', got '%s'", i, expected, config.ExportCFlags[i]) } } } @@ -458,7 +458,7 @@ func TestGetNewlibESP32ConfigXtensa(t *testing.T) { } else { for i, expected := range expectedCFlags { if config.ExportCFlags[i] != expected { - t.Errorf("LibcCFlags[%d] mismatch. Expected '%s', got '%s'", i, expected, config.ExportCFlags[i]) + t.Errorf("ExportCFlags[%d] mismatch. Expected '%s', got '%s'", i, expected, config.ExportCFlags[i]) } } } diff --git a/internal/crosscompile/compile/rtlib/rt_test.go b/internal/crosscompile/compile/rtlib/rt_test.go index 427ecd5b..6e7d1541 100644 --- a/internal/crosscompile/compile/rtlib/rt_test.go +++ b/internal/crosscompile/compile/rtlib/rt_test.go @@ -5,7 +5,7 @@ import ( "testing" ) -func TestGetNewlibESP32Config_LibConfig(t *testing.T) { +func TestGetCompilerRTConfig_LibConfig(t *testing.T) { config := GetCompilerRTConfig() // Test basic configuration fields diff --git a/internal/crosscompile/libc.go b/internal/crosscompile/libc.go index b7feefc3..c19eeab9 100644 --- a/internal/crosscompile/libc.go +++ b/internal/crosscompile/libc.go @@ -13,7 +13,7 @@ import ( var needSkipDownload = false // getLibcCompileConfigByName retrieves libc compilation configuration by name -// Returns compilation file lists and corresponding cflags +// Returns the actual libc output dir, compilation config and err func getLibcCompileConfigByName(baseDir, libcName, target, mcpu string) (outputDir string, cfg compile.CompileConfig, err error) { if libcName == "" { err = fmt.Errorf("libc name cannot be empty") @@ -48,7 +48,7 @@ func getLibcCompileConfigByName(baseDir, libcName, target, mcpu string) (outputD } // getRTCompileConfigByName retrieves runtime library compilation configuration by name -// Returns compilation file lists and corresponding flags for the specified runtime library +// Returns the actual libc output dir, compilation config and err func getRTCompileConfigByName(baseDir, rtName, target string) (outputDir string, cfg compile.CompileConfig, err error) { if rtName == "" { err = fmt.Errorf("rt name cannot be empty") From a17f1f0bb0db1d159b4dfd9226ba01adebf96ef8 Mon Sep 17 00:00:00 2001 From: luoliwoshang <2643523683@qq.com> Date: Tue, 9 Sep 2025 16:08:40 +0800 Subject: [PATCH 28/29] set origin test avoid transform --- .github/workflows/release-build.yml | 3 ++- .goreleaser.yaml | 6 ++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/.github/workflows/release-build.yml b/.github/workflows/release-build.yml index 811310d2..bb8a4423 100644 --- a/.github/workflows/release-build.yml +++ b/.github/workflows/release-build.yml @@ -206,7 +206,8 @@ jobs: mod-version: ${{ matrix.go-mod-version }} release: - needs: [setup, test-artifacts] + needs: + [setup, test-artifacts, populate-darwin-sysroot, populate-linux-sysroot] runs-on: ubuntu-latest if: startsWith(github.ref, 'refs/tags/') steps: diff --git a/.goreleaser.yaml b/.goreleaser.yaml index fc8a949f..bbd0104c 100644 --- a/.goreleaser.yaml +++ b/.goreleaser.yaml @@ -55,11 +55,12 @@ builds: ldflags: - -X github.com/goplus/llgo/internal/env.buildVersion=v{{.Version}} - -X github.com/goplus/llgo/internal/env.buildTime={{.Date}} + - '-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}}/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 -Wl,-rpath,$ORIGIN/../crosscompile/clang/lib + - CGO_LDFLAGS=--sysroot={{.Env.SYSROOT_LINUX_AMD64}} -L{{.Env.SYSROOT_LINUX_AMD64}}/crosscompile/clang/lib -lLLVM-19 - CGO_LDFLAGS_ALLOW=--sysroot.* targets: - linux_amd64 @@ -72,11 +73,12 @@ builds: ldflags: - -X github.com/goplus/llgo/internal/env.buildVersion=v{{.Version}} - -X github.com/goplus/llgo/internal/env.buildTime={{.Date}} + - '-extldflags=-Wl,-rpath,$ORIGIN/../crosscompile/clang/lib' env: - CC=aarch64-linux-gnu-gcc - CXX=aarch64-linux-gnu-g++ - 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 -Wl,-rpath,$ORIGIN/../crosscompile/clang/lib + - CGO_LDFLAGS=--sysroot={{.Env.SYSROOT_LINUX_ARM64}} -L{{.Env.SYSROOT_LINUX_ARM64}}/crosscompile/clang/lib -lLLVM-19 - CGO_LDFLAGS_ALLOW=--sysroot.* targets: - linux_arm64 From 073e79d03b53d6e9617e402826d49e4384611c81 Mon Sep 17 00:00:00 2001 From: Haolan Date: Wed, 10 Sep 2025 11:47:02 +0800 Subject: [PATCH 29/29] chore: rename ArchiveSrcDir --- internal/crosscompile/compile/compile.go | 8 ++++---- internal/crosscompile/compile/libc/libc_test.go | 8 ++++---- internal/crosscompile/compile/libc/newlibesp.go | 8 ++++---- internal/crosscompile/compile/libc/picolibc.go | 8 ++++---- internal/crosscompile/compile/rtlib/compiler_rt.go | 8 ++++---- internal/crosscompile/compile/rtlib/rt_test.go | 4 ++-- internal/crosscompile/libc.go | 4 ++-- 7 files changed, 24 insertions(+), 24 deletions(-) diff --git a/internal/crosscompile/compile/compile.go b/internal/crosscompile/compile/compile.go index acfec5b3..ded11530 100644 --- a/internal/crosscompile/compile/compile.go +++ b/internal/crosscompile/compile/compile.go @@ -104,10 +104,10 @@ type CompileConfig struct { } type LibConfig struct { - Url string - Name string // Library name (e.g., "picolibc", "musl", "glibc") - Version string - ArchiveSrcDir string + Url string + Name string // Library name (e.g., "picolibc", "musl", "glibc") + Version string + ResourceSubDir string } // String returns a string representation of the library configuration diff --git a/internal/crosscompile/compile/libc/libc_test.go b/internal/crosscompile/compile/libc/libc_test.go index 9a994ef3..b866f1dd 100644 --- a/internal/crosscompile/compile/libc/libc_test.go +++ b/internal/crosscompile/compile/libc/libc_test.go @@ -26,8 +26,8 @@ func TestGetNewlibESP32Config_LibConfig(t *testing.T) { } expectedArchiveSrcDir := "newlib-esp-4.3.0_20250211-patch3" - if config.ArchiveSrcDir != expectedArchiveSrcDir { - t.Errorf("Expected ArchiveSrcDir '%s', got '%s'", expectedArchiveSrcDir, config.ArchiveSrcDir) + if config.ResourceSubDir != expectedArchiveSrcDir { + t.Errorf("Expected ResourceSubDir '%s', got '%s'", expectedArchiveSrcDir, config.ResourceSubDir) } // Test String() method @@ -57,8 +57,8 @@ func TestGetPicolibcConfig_LibConfig(t *testing.T) { } expectedArchiveSrcDir := "picolibc-main" - if config.ArchiveSrcDir != expectedArchiveSrcDir { - t.Errorf("Expected ArchiveSrcDir '%s', got '%s'", expectedArchiveSrcDir, config.ArchiveSrcDir) + if config.ResourceSubDir != expectedArchiveSrcDir { + t.Errorf("Expected ResourceSubDir '%s', got '%s'", expectedArchiveSrcDir, config.ResourceSubDir) } // Test String() method diff --git a/internal/crosscompile/compile/libc/newlibesp.go b/internal/crosscompile/compile/libc/newlibesp.go index cb55f495..eb3917cc 100644 --- a/internal/crosscompile/compile/libc/newlibesp.go +++ b/internal/crosscompile/compile/libc/newlibesp.go @@ -29,10 +29,10 @@ func withDefaultCCFlags(ccflags []string) []string { // GetNewlibESP32Config returns the configuration for downloading and building newlib for ESP32 func GetNewlibESP32Config() compile.LibConfig { return compile.LibConfig{ - Url: "https://github.com/goplus/newlib/archive/refs/tags/esp-4.3.0_20250211-patch3.tar.gz", - Name: "newlib-esp32", - Version: "esp-4.3.0_20250211-patch3", - ArchiveSrcDir: "newlib-esp-4.3.0_20250211-patch3", + Url: "https://github.com/goplus/newlib/archive/refs/tags/esp-4.3.0_20250211-patch3.tar.gz", + Name: "newlib-esp32", + Version: "esp-4.3.0_20250211-patch3", + ResourceSubDir: "newlib-esp-4.3.0_20250211-patch3", } } diff --git a/internal/crosscompile/compile/libc/picolibc.go b/internal/crosscompile/compile/libc/picolibc.go index 680c1ed7..45344762 100644 --- a/internal/crosscompile/compile/libc/picolibc.go +++ b/internal/crosscompile/compile/libc/picolibc.go @@ -10,10 +10,10 @@ import ( // GetPicolibcConfig returns the configuration for downloading and building picolibc func GetPicolibcConfig() compile.LibConfig { return compile.LibConfig{ - Name: "picolibc", - Version: "v0.1.0", - Url: "https://github.com/goplus/picolibc/archive/refs/heads/main.zip", - ArchiveSrcDir: "picolibc-main", + Name: "picolibc", + Version: "v0.1.0", + Url: "https://github.com/goplus/picolibc/archive/refs/heads/main.zip", + ResourceSubDir: "picolibc-main", } } diff --git a/internal/crosscompile/compile/rtlib/compiler_rt.go b/internal/crosscompile/compile/rtlib/compiler_rt.go index d526251c..0be8cf64 100644 --- a/internal/crosscompile/compile/rtlib/compiler_rt.go +++ b/internal/crosscompile/compile/rtlib/compiler_rt.go @@ -102,10 +102,10 @@ func withPlatformSpecifiedFiles(baseDir, target string, files []string) []string func GetCompilerRTConfig() compile.LibConfig { return compile.LibConfig{ - Name: "compiler-rt", - Url: "https://github.com/goplus/compiler-rt/archive/refs/tags/xtensa_release_19.1.2.tar.gz", - Version: "xtensa_release_19.1.2", - ArchiveSrcDir: "compiler-rt-xtensa_release_19.1.2", + Name: "compiler-rt", + Url: "https://github.com/goplus/compiler-rt/archive/refs/tags/xtensa_release_19.1.2.tar.gz", + Version: "xtensa_release_19.1.2", + ResourceSubDir: "compiler-rt-xtensa_release_19.1.2", } } diff --git a/internal/crosscompile/compile/rtlib/rt_test.go b/internal/crosscompile/compile/rtlib/rt_test.go index 6e7d1541..5f5f2548 100644 --- a/internal/crosscompile/compile/rtlib/rt_test.go +++ b/internal/crosscompile/compile/rtlib/rt_test.go @@ -25,8 +25,8 @@ func TestGetCompilerRTConfig_LibConfig(t *testing.T) { } expectedArchiveSrcDir := "compiler-rt-xtensa_release_19.1.2" - if config.ArchiveSrcDir != expectedArchiveSrcDir { - t.Errorf("Expected ArchiveSrcDir '%s', got '%s'", expectedArchiveSrcDir, config.ArchiveSrcDir) + if config.ResourceSubDir != expectedArchiveSrcDir { + t.Errorf("Expected ResourceSubDir '%s', got '%s'", expectedArchiveSrcDir, config.ResourceSubDir) } // Test String() method diff --git a/internal/crosscompile/libc.go b/internal/crosscompile/libc.go index c19eeab9..225a4a56 100644 --- a/internal/crosscompile/libc.go +++ b/internal/crosscompile/libc.go @@ -40,7 +40,7 @@ func getLibcCompileConfigByName(baseDir, libcName, target, mcpu string) (outputD return libcDir, compileConfig, err } - if err = checkDownloadAndExtractLib(config.Url, libcDir, config.ArchiveSrcDir); err != nil { + if err = checkDownloadAndExtractLib(config.Url, libcDir, config.ResourceSubDir); err != nil { return } @@ -70,7 +70,7 @@ func getRTCompileConfigByName(baseDir, rtName, target string) (outputDir string, return rtDir, compileConfig, err } - if err = checkDownloadAndExtractLib(config.Url, rtDir, config.ArchiveSrcDir); err != nil { + if err = checkDownloadAndExtractLib(config.Url, rtDir, config.ResourceSubDir); err != nil { return }