diff --git a/.github/workflows/export_test_normal.sh b/.github/workflows/export_test_normal.sh new file mode 100644 index 00000000..7304a553 --- /dev/null +++ b/.github/workflows/export_test_normal.sh @@ -0,0 +1,101 @@ +#!/bin/bash + +# Test script for //export on normal (non-baremetal) targets +# This ensures that //export with different symbol names does NOT work on normal targets + +set -e # Exit on any error + +# Use current working directory (workflow already cd's to the test directory) +WORK_DIR="$(pwd)" + +# Colors for output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +NC='\033[0m' # No Color + +# Function to print colored output +print_status() { + echo -e "${GREEN}[INFO]${NC} $1" +} + +print_error() { + echo -e "${RED}[ERROR]${NC} $1" +} + +# Check if llgo command is available +if ! command -v llgo &> /dev/null; then + print_error "llgo command not found, please install llgo first" + exit 1 +fi + +# Check if LLGO_ROOT is set +if [[ -z "$LLGO_ROOT" ]]; then + print_error "LLGO_ROOT environment variable is not set" + exit 1 +fi + +print_status "Starting export symbol name test for normal targets..." +print_status "Working directory: $WORK_DIR" +print_status "LLGO_ROOT: $LLGO_ROOT" + +echo "" + +# Build the test program +print_status "=== Building test program ===" +if llgo build -o test_export main.go; then + print_status "Build succeeded" +else + print_error "Build failed" + exit 1 +fi + +# Check for expected symbols using nm +print_status "=== Checking exported symbols with nm ===" +if ! command -v nm &> /dev/null; then + print_error "nm command not found, skipping symbol verification" + exit 1 +fi + +NM_OUTPUT=$(nm test_export) + +# For normal targets, //export SymbolName should export the FUNCTION NAME, not the symbol name +# So we expect LPSPI2_IRQHandler, SysTick_Handler, Add (the function names) + +# Verify LPSPI2_IRQHandler symbol exists (function name) +if echo "$NM_OUTPUT" | grep -q "LPSPI2_IRQHandler"; then + print_status "✓ Symbol LPSPI2_IRQHandler found (function name)" +else + print_error "✗ Symbol LPSPI2_IRQHandler not found" + echo "Available symbols:" + echo "$NM_OUTPUT" + exit 1 +fi + +# Verify SysTick_Handler symbol exists (function name) +if echo "$NM_OUTPUT" | grep -q "SysTick_Handler"; then + print_status "✓ Symbol SysTick_Handler found (function name)" +else + print_error "✗ Symbol SysTick_Handler not found" + echo "Available symbols:" + echo "$NM_OUTPUT" + exit 1 +fi + +# Verify Add symbol exists (same name) +if echo "$NM_OUTPUT" | grep -q "Add"; then + print_status "✓ Symbol Add found" +else + print_error "✗ Symbol Add not found" + echo "Available symbols:" + echo "$NM_OUTPUT" + exit 1 +fi + +echo "" +print_status "=== All symbol name tests passed for normal targets! ===" + +# Cleanup +rm -f test_export + +print_status "Export symbol name test for normal targets completed successfully!" diff --git a/.github/workflows/llgo.yml b/.github/workflows/llgo.yml index 22795758..3856b7d0 100644 --- a/.github/workflows/llgo.yml +++ b/.github/workflows/llgo.yml @@ -140,6 +140,13 @@ jobs: cd _demo/embed/export bash ../../../.github/workflows/export_test.sh + - name: Test export symbol names for normal targets + run: | + echo "Testing //export behavior for normal (non-embedded) targets..." + chmod +x .github/workflows/export_test_normal.sh + cd _demo/normal/export + bash ../../../.github/workflows/export_test_normal.sh + - name: _xtool build tests run: | cd _xtool diff --git a/_demo/normal/export/main.go b/_demo/normal/export/main.go new file mode 100644 index 00000000..9b498947 --- /dev/null +++ b/_demo/normal/export/main.go @@ -0,0 +1,22 @@ +package main + +//export LPSPI2_IRQHandler +func LPSPI2_IRQHandler() { + println("LPSPI2 interrupt handled") +} + +//export SysTick_Handler +func SysTick_Handler() { + println("System tick") +} + +//export Add +func Add(a, b int) int { + return a + b +} + +func main() { + LPSPI2_IRQHandler() + SysTick_Handler() + println("Add(2, 3) =", Add(2, 3)) +} diff --git a/cl/import.go b/cl/import.go index 9cae2f68..c03479cc 100644 --- a/cl/import.go +++ b/cl/import.go @@ -317,14 +317,20 @@ func (p *context) initLinkname(line string, f func(inPkgName string) (fullName s // format: //export ExportName or //export FuncName ExportName exportName := strings.TrimSpace(line[len(export):]) var inPkgName string + isBaremetal := os.Getenv("LLGO_TARGET_BAREMETAL") == "1" if idx := strings.IndexByte(exportName, ' '); idx > 0 { // format: //export FuncName ExportName (go-style) inPkgName = exportName[:idx] exportName = strings.TrimLeft(exportName[idx+1:], " ") } else { - // format: //export ExportName (tinygo-style) - // use empty string to match any function - inPkgName = "" + // format: //export ExportName (tinygo-style, only for baremetal targets) + if !isBaremetal { + // For non-baremetal targets, treat as function name (standard Go behavior) + inPkgName = exportName + } else { + // For baremetal targets, use empty string to match any function + inPkgName = "" + } } if fullName, _, ok := f(inPkgName); ok { p.prog.SetLinkname(fullName, exportName) diff --git a/internal/build/build.go b/internal/build/build.go index 1147d495..1e493cc2 100644 --- a/internal/build/build.go +++ b/internal/build/build.go @@ -222,6 +222,13 @@ func Do(args []string, conf *Config) ([]Package, error) { } if len(export.BuildTags) > 0 { tags += "," + strings.Join(export.BuildTags, ",") + // Set environment variable if building for baremetal target + for _, tag := range export.BuildTags { + if tag == "baremetal" { + os.Setenv("LLGO_TARGET_BAREMETAL", "1") + break + } + } } cfg := &packages.Config{ Mode: loadSyntax | packages.NeedDeps | packages.NeedModule | packages.NeedExportFile,