fix cross compilation

This commit is contained in:
Li Jie
2025-08-21 14:13:42 +08:00
parent 50a2650e67
commit 7e8df050a1
3 changed files with 42 additions and 120 deletions

View File

@@ -96,46 +96,46 @@ func (c *Cmd) Link(args ...string) error {
// mergeCompilerFlags merges environment CCFLAGS/CFLAGS with crossCompile flags.
func (c *Cmd) mergeCompilerFlags() []string {
var flags []string
// Add environment CCFLAGS
if envCCFlags := os.Getenv("CCFLAGS"); envCCFlags != "" {
flags = append(flags, safesplit.SplitPkgConfigFlags(envCCFlags)...)
}
// Add environment CFLAGS
if envCFlags := os.Getenv("CFLAGS"); envCFlags != "" {
flags = append(flags, safesplit.SplitPkgConfigFlags(envCFlags)...)
}
// Add crossCompile CCFLAGS
flags = append(flags, c.crossCompile.CCFLAGS...)
// Add crossCompile CFLAGS
flags = append(flags, c.crossCompile.CFLAGS...)
return flags
}
// mergeLinkerFlags merges environment CCFLAGS/LDFLAGS with crossCompile flags.
func (c *Cmd) mergeLinkerFlags() []string {
var flags []string
// Add environment CCFLAGS (for linker)
if envCCFlags := os.Getenv("CCFLAGS"); envCCFlags != "" {
flags = append(flags, safesplit.SplitPkgConfigFlags(envCCFlags)...)
}
// Add environment LDFLAGS
if envLDFlags := os.Getenv("LDFLAGS"); envLDFlags != "" {
flags = append(flags, safesplit.SplitPkgConfigFlags(envLDFlags)...)
}
// Add crossCompile CCFLAGS (for linker)
flags = append(flags, c.crossCompile.CCFLAGS...)
// Add crossCompile LDFLAGS
flags = append(flags, c.crossCompile.LDFLAGS...)
return flags
}
@@ -183,4 +183,4 @@ func (c *Cmd) CheckLinkArgs(cmdArgs []string, wasm bool) error {
// Execute the command with linker flags
return c.Link(args...)
}
}

View File

@@ -339,11 +339,21 @@ func useTarget(targetName string) (export Export, err error) {
target = llvm.GetTargetTriple(config.GOOS, config.GOARCH)
}
ccflags = append(ccflags, "-Wno-override-module", "--target="+config.LLVMTarget)
cflags := []string{"-Wno-override-module"}
if config.LLVMTarget != "" {
cflags = append(cflags, "--target="+config.LLVMTarget)
ccflags = append(ccflags, "--target="+config.LLVMTarget)
}
cflags = append(cflags, config.CFlags...)
// Inspired by tinygo
cpu := config.CPU
if cpu != "" {
if config.Linker == "ld.lld" {
ldflags = append(ldflags, "-mllvm", "-mcpu="+cpu)
}
// Always add CPU to CCFLAGS for proper compilation
if strings.HasPrefix(target, "i386") || strings.HasPrefix(target, "x86_64") {
ccflags = append(ccflags, "-march="+cpu)
} else if strings.HasPrefix(target, "avr") {
@@ -351,10 +361,6 @@ func useTarget(targetName string) (export Export, err error) {
} else {
ccflags = append(ccflags, "-mcpu="+cpu)
}
// Only add -mllvm flags for non-WebAssembly linkers
if config.Linker == "ld.lld" {
ldflags = append(ldflags, "-mllvm", "-mcpu="+cpu)
}
}
// Handle Features
@@ -375,7 +381,7 @@ func useTarget(targetName string) (export Export, err error) {
ldflags = append(ldflags, "-L", env.LLGoROOT()) // search targets/*.ld
// Combine with config flags
export.CFLAGS = config.CFlags
export.CFLAGS = cflags
export.CCFLAGS = ccflags
export.LDFLAGS = append(ldflags, config.LDFlags...)
@@ -390,44 +396,3 @@ func Use(goos, goarch string, wasiThreads bool, targetName string) (export Expor
}
return use(goos, goarch, wasiThreads)
}
// filterCompatibleLDFlags filters out linker flags that are incompatible with clang/lld
func filterCompatibleLDFlags(ldflags []string) []string {
if len(ldflags) == 0 {
return ldflags
}
var filtered []string
incompatiblePrefixes := []string{
"--defsym=", // Use -Wl,--defsym= instead
"-T", // Linker script, needs special handling
}
i := 0
for i < len(ldflags) {
flag := ldflags[i]
// Check incompatible prefixes
skip := false
for _, prefix := range incompatiblePrefixes {
if strings.HasPrefix(flag, prefix) {
skip = true
break
}
}
if skip {
// Skip -T and its argument if separate
if flag == "-T" && i+1 < len(ldflags) {
i += 2 // Skip both -T and the script path
} else {
i++
}
continue
}
filtered = append(filtered, flag)
i++
}
return filtered
}

View File

@@ -230,20 +230,33 @@ func TestUseTarget(t *testing.T) {
}
}
// Check if CPU is in CCFLAGS
// Check if CPU is in LDFLAGS (for ld.lld linker) or CCFLAGS (for other cases)
if tc.expectCPU != "" {
found := false
expectedFlags := []string{"-mmcu=" + tc.expectCPU, "-mcpu=" + tc.expectCPU}
for _, flag := range export.CCFLAGS {
for _, expectedFlag := range expectedFlags {
if flag == expectedFlag {
// First check LDFLAGS for -mllvm -mcpu= pattern
for i, flag := range export.LDFLAGS {
if flag == "-mllvm" && i+1 < len(export.LDFLAGS) {
nextFlag := export.LDFLAGS[i+1]
if nextFlag == "-mcpu="+tc.expectCPU {
found = true
break
}
}
}
// If not found in LDFLAGS, check CCFLAGS for direct CPU flags
if !found {
t.Errorf("Expected CPU %s in CCFLAGS, got %v", tc.expectCPU, export.CCFLAGS)
expectedFlags := []string{"-mmcu=" + tc.expectCPU, "-mcpu=" + tc.expectCPU}
for _, flag := range export.CCFLAGS {
for _, expectedFlag := range expectedFlags {
if flag == expectedFlag {
found = true
break
}
}
}
}
if !found {
t.Errorf("Expected CPU %s in LDFLAGS or CCFLAGS, got LDFLAGS=%v, CCFLAGS=%v", tc.expectCPU, export.LDFLAGS, export.CCFLAGS)
}
}
@@ -277,59 +290,3 @@ func TestUseWithTarget(t *testing.T) {
t.Error("Expected LDFLAGS to be set for native build")
}
}
func TestFilterCompatibleLDFlags(t *testing.T) {
testCases := []struct {
name string
input []string
expected []string
}{
{
name: "Empty flags",
input: []string{},
expected: []string{},
},
{
name: "Compatible flags only",
input: []string{"-lm", "-lpthread"},
expected: []string{"-lm", "-lpthread"},
},
{
name: "Incompatible flags filtered",
input: []string{"--gc-sections", "-lm", "--emit-relocs", "-lpthread"},
expected: []string{"--gc-sections", "-lm", "--emit-relocs", "-lpthread"},
},
{
name: "Defsym flags filtered",
input: []string{"--defsym=_stack_size=512", "-lm", "--defsym=_bootloader_size=512"},
expected: []string{"-lm"},
},
{
name: "Linker script flags filtered",
input: []string{"-T", "script.ld", "-lm"},
expected: []string{"-lm"},
},
{
name: "Mixed compatible and incompatible",
input: []string{"-lm", "--gc-sections", "--defsym=test=1", "-lpthread", "--no-demangle"},
expected: []string{"-lm", "--gc-sections", "-lpthread", "--no-demangle"},
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
result := filterCompatibleLDFlags(tc.input)
if len(result) != len(tc.expected) {
t.Errorf("Expected %d flags, got %d: %v", len(tc.expected), len(result), result)
return
}
for i, expected := range tc.expected {
if result[i] != expected {
t.Errorf("Expected flag[%d] = %s, got %s", i, expected, result[i])
}
}
})
}
}