mirror of
https://github.com/goplus/llgo.git
synced 2025-09-27 03:56:05 +08:00
410 lines
12 KiB
Go
410 lines
12 KiB
Go
//go:build !llgo
|
|
|
|
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) {
|
|
baseDir := "/test/base"
|
|
target := "armv7"
|
|
mcpu := "cortex-m4"
|
|
|
|
needSkipDownload = true
|
|
t.Run("EmptyName", func(t *testing.T) {
|
|
_, _, 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)
|
|
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)
|
|
if err != nil {
|
|
t.Fatalf("Unexpected error: %v", err)
|
|
}
|
|
|
|
if len(cfg.Groups) != 1 {
|
|
t.Fatalf("Expected 1 group, got %d", len(cfg.Groups))
|
|
}
|
|
group := cfg.Groups[0]
|
|
|
|
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", 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)
|
|
if err != nil {
|
|
t.Fatalf("Unexpected error: %v", err)
|
|
}
|
|
|
|
if len(cfg.Groups) != 3 {
|
|
t.Fatalf("Expected 3 group, got %d", len(cfg.Groups))
|
|
}
|
|
group := cfg.Groups[0]
|
|
|
|
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, libc.GetNewlibESP32Config().String(), "libgloss")
|
|
if !slices.Contains(group.CFlags, expectedFlags) {
|
|
t.Errorf("Expected flags %v, got: %v", expectedFlags, group.CFlags)
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestGetRTCompileConfigByName(t *testing.T) {
|
|
baseDir := "/test/base"
|
|
target := "wasm32"
|
|
needSkipDownload = true
|
|
|
|
t.Run("EmptyName", func(t *testing.T) {
|
|
_, _, 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)
|
|
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)
|
|
if err != nil {
|
|
t.Fatalf("Unexpected error: %v", err)
|
|
}
|
|
|
|
if len(cfg.Groups) != 1 {
|
|
t.Fatalf("Expected 1 group, got %d", len(cfg.Groups))
|
|
}
|
|
group := cfg.Groups[0]
|
|
|
|
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)
|
|
}
|
|
}
|
|
}
|