Merge pull request #1264 from MeteorsLiu/libc-version
Fix xtensa newlib `stdio` stuck and support libc version
This commit is contained in:
@@ -27,12 +27,16 @@ type CompileGroup struct {
|
|||||||
LDFlags []string // Linker flags
|
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 {
|
func (g CompileGroup) IsCompiled(outputDir string) bool {
|
||||||
archive := filepath.Join(outputDir, filepath.Base(g.OutputFileName))
|
archive := filepath.Join(outputDir, filepath.Base(g.OutputFileName))
|
||||||
_, err := os.Stat(archive)
|
_, err := os.Stat(archive)
|
||||||
return err == nil
|
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(
|
func (g CompileGroup) Compile(
|
||||||
outputDir string, options CompileOptions,
|
outputDir string, options CompileOptions,
|
||||||
) (err error) {
|
) (err error) {
|
||||||
@@ -95,9 +99,19 @@ func (g CompileGroup) Compile(
|
|||||||
|
|
||||||
// CompileConfig represents compilation configuration
|
// CompileConfig represents compilation configuration
|
||||||
type CompileConfig struct {
|
type CompileConfig struct {
|
||||||
Url string
|
|
||||||
Name string // compile name (e.g., "picolibc", "musl", "glibc")
|
|
||||||
Groups []CompileGroup
|
Groups []CompileGroup
|
||||||
ArchiveSrcDir string
|
ExportCFlags []string
|
||||||
LibcCFlags []string
|
}
|
||||||
|
|
||||||
|
type LibConfig struct {
|
||||||
|
Url string
|
||||||
|
Name string // Library name (e.g., "picolibc", "musl", "glibc")
|
||||||
|
Version string
|
||||||
|
ResourceSubDir 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)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,8 +11,8 @@ import (
|
|||||||
"github.com/goplus/llgo/xtool/nm"
|
"github.com/goplus/llgo/xtool/nm"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestIsCompile(t *testing.T) {
|
func TestIsCompiled(t *testing.T) {
|
||||||
t.Run("IsCompile Not Exists", func(t *testing.T) {
|
t.Run("IsCompiled Not Exists", func(t *testing.T) {
|
||||||
cfg := CompileConfig{
|
cfg := CompileConfig{
|
||||||
Groups: []CompileGroup{
|
Groups: []CompileGroup{
|
||||||
{
|
{
|
||||||
@@ -25,7 +25,7 @@ func TestIsCompile(t *testing.T) {
|
|||||||
t.Errorf("unexpected result: should false")
|
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")
|
tmpFile, err := os.CreateTemp("", "test*.a")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
@@ -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)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -2,34 +2,90 @@ package libc
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
"testing"
|
"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-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-patch3.tar.gz"
|
||||||
|
if config.Url != expectedUrl {
|
||||||
|
t.Errorf("Expected Url '%s', got '%s'", expectedUrl, config.Url)
|
||||||
|
}
|
||||||
|
|
||||||
|
expectedArchiveSrcDir := "newlib-esp-4.3.0_20250211-patch3"
|
||||||
|
if config.ResourceSubDir != expectedArchiveSrcDir {
|
||||||
|
t.Errorf("Expected ResourceSubDir '%s', got '%s'", expectedArchiveSrcDir, config.ResourceSubDir)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test String() method
|
||||||
|
expectedString := "newlib-esp32-esp-4.3.0_20250211-patch3"
|
||||||
|
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.ResourceSubDir != expectedArchiveSrcDir {
|
||||||
|
t.Errorf("Expected ResourceSubDir '%s', got '%s'", expectedArchiveSrcDir, config.ResourceSubDir)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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"
|
baseDir := "/test/base"
|
||||||
target := "test-target"
|
target := "test-target"
|
||||||
|
|
||||||
config := GetPicolibcConfig(baseDir, target)
|
config := GetPicolibcCompileConfig(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)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test LibcCFlags
|
// Test LibcCFlags
|
||||||
if len(config.LibcCFlags) != 2 {
|
if len(config.ExportCFlags) != 2 {
|
||||||
t.Errorf("Expected 2 LibcCFlags, got %d", len(config.LibcCFlags))
|
t.Errorf("Expected 2 LibcCFlags, got %d", len(config.ExportCFlags))
|
||||||
} else {
|
} else {
|
||||||
expected := "-I" + baseDir
|
expected := "-I" + baseDir
|
||||||
if config.LibcCFlags[0] != expected {
|
if config.ExportCFlags[0] != expected {
|
||||||
t.Errorf("Expected LibcCFlags[0] to be '%s', got '%s'", expected, config.LibcCFlags[0])
|
t.Errorf("Expected LibcCFlags[0] to be '%s', got '%s'", expected, config.ExportCFlags[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
expected = "-isystem" + filepath.Join(baseDir, "newlib", "libc", "include")
|
expected = "-isystem" + filepath.Join(baseDir, "newlib", "libc", "include")
|
||||||
if config.LibcCFlags[1] != expected {
|
if config.ExportCFlags[1] != expected {
|
||||||
t.Errorf("Expected LibcCFlags[1] to be '%s', got '%s'", expected, config.LibcCFlags[1])
|
t.Errorf("Expected LibcCFlags[1] to be '%s', got '%s'", expected, config.ExportCFlags[1])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -113,22 +169,22 @@ func TestGetPicolibcConfig(t *testing.T) {
|
|||||||
|
|
||||||
func TestGetPicolibcConfig_EdgeCases(t *testing.T) {
|
func TestGetPicolibcConfig_EdgeCases(t *testing.T) {
|
||||||
t.Run("EmptyBaseDir", func(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
|
// Check that paths are constructed correctly even with empty baseDir
|
||||||
expected := "-I"
|
expected := "-I"
|
||||||
if config.LibcCFlags[0] != expected {
|
if config.ExportCFlags[0] != expected {
|
||||||
t.Errorf("Expected LibcCFlags[0] to be '%s', got '%s'", expected, config.LibcCFlags[0])
|
t.Errorf("Expected LibcCFlags[0] to be '%s', got '%s'", expected, config.ExportCFlags[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
expected = "-isystem" + filepath.Join("", "newlib", "libc", "include")
|
expected = "-isystem" + filepath.Join("", "newlib", "libc", "include")
|
||||||
if config.LibcCFlags[1] != expected {
|
if config.ExportCFlags[1] != expected {
|
||||||
t.Errorf("Expected LibcCFlags[1] to be '%s', got '%s'", expected, config.LibcCFlags[1])
|
t.Errorf("Expected LibcCFlags[1] to be '%s', got '%s'", expected, config.ExportCFlags[1])
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("EmptyTarget", func(t *testing.T) {
|
t.Run("EmptyTarget", func(t *testing.T) {
|
||||||
config := GetPicolibcConfig("/test/base", "")
|
config := GetPicolibcCompileConfig("/test/base", "")
|
||||||
|
|
||||||
// Check output file name formatting
|
// Check output file name formatting
|
||||||
expectedOutput := "libc-.a"
|
expectedOutput := "libc-.a"
|
||||||
@@ -138,23 +194,125 @@ 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) {
|
func TestGetNewlibESP32ConfigRISCV(t *testing.T) {
|
||||||
baseDir := "/test/base"
|
baseDir := "/test/base"
|
||||||
target := "riscv32-unknown-elf"
|
target := "riscv32-unknown-elf"
|
||||||
|
|
||||||
config := getNewlibESP32ConfigRISCV(baseDir, target)
|
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
|
// Test LibcCFlags
|
||||||
libcDir := filepath.Join(baseDir, "newlib", "libc")
|
libcDir := filepath.Join(baseDir, "newlib", "libc")
|
||||||
expectedCFlags := []string{
|
expectedCFlags := []string{
|
||||||
@@ -162,12 +320,12 @@ func TestGetNewlibESP32ConfigRISCV(t *testing.T) {
|
|||||||
"-I" + filepath.Join(baseDir, "newlib"),
|
"-I" + filepath.Join(baseDir, "newlib"),
|
||||||
"-I" + libcDir,
|
"-I" + libcDir,
|
||||||
}
|
}
|
||||||
if len(config.LibcCFlags) != len(expectedCFlags) {
|
if len(config.ExportCFlags) != len(expectedCFlags) {
|
||||||
t.Errorf("Expected %d LibcCFlags, got %d", len(expectedCFlags), len(config.LibcCFlags))
|
t.Errorf("Expected %d LibcCFlags, got %d", len(expectedCFlags), len(config.ExportCFlags))
|
||||||
} else {
|
} else {
|
||||||
for i, expected := range expectedCFlags {
|
for i, expected := range expectedCFlags {
|
||||||
if config.LibcCFlags[i] != expected {
|
if config.ExportCFlags[i] != expected {
|
||||||
t.Errorf("LibcCFlags[%d] mismatch. Expected '%s', got '%s'", i, expected, config.LibcCFlags[i])
|
t.Errorf("ExportCFlags[%d] mismatch. Expected '%s', got '%s'", i, expected, config.ExportCFlags[i])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -288,17 +446,6 @@ func TestGetNewlibESP32ConfigXtensa(t *testing.T) {
|
|||||||
|
|
||||||
config := getNewlibESP32ConfigXtensa(baseDir, target)
|
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
|
// Test LibcCFlags
|
||||||
libcDir := filepath.Join(baseDir, "newlib", "libc")
|
libcDir := filepath.Join(baseDir, "newlib", "libc")
|
||||||
expectedCFlags := []string{
|
expectedCFlags := []string{
|
||||||
@@ -306,12 +453,12 @@ func TestGetNewlibESP32ConfigXtensa(t *testing.T) {
|
|||||||
"-I" + filepath.Join(baseDir, "newlib"),
|
"-I" + filepath.Join(baseDir, "newlib"),
|
||||||
"-I" + libcDir,
|
"-I" + libcDir,
|
||||||
}
|
}
|
||||||
if len(config.LibcCFlags) != len(expectedCFlags) {
|
if len(config.ExportCFlags) != len(expectedCFlags) {
|
||||||
t.Errorf("Expected %d LibcCFlags, got %d", len(expectedCFlags), len(config.LibcCFlags))
|
t.Errorf("Expected %d LibcCFlags, got %d", len(expectedCFlags), len(config.ExportCFlags))
|
||||||
} else {
|
} else {
|
||||||
for i, expected := range expectedCFlags {
|
for i, expected := range expectedCFlags {
|
||||||
if config.LibcCFlags[i] != expected {
|
if config.ExportCFlags[i] != expected {
|
||||||
t.Errorf("LibcCFlags[%d] mismatch. Expected '%s', got '%s'", i, expected, config.LibcCFlags[i])
|
t.Errorf("ExportCFlags[%d] mismatch. Expected '%s', got '%s'", i, expected, config.ExportCFlags[i])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -407,8 +554,8 @@ func TestEdgeCases(t *testing.T) {
|
|||||||
|
|
||||||
// Check that paths are constructed correctly
|
// Check that paths are constructed correctly
|
||||||
expected := "-isystem" + filepath.Join(libcDir, "include")
|
expected := "-isystem" + filepath.Join(libcDir, "include")
|
||||||
if config.LibcCFlags[0] != expected {
|
if config.ExportCFlags[0] != expected {
|
||||||
t.Errorf("Expected LibcCFlags[0] to be '%s', got '%s'", expected, config.LibcCFlags[0])
|
t.Errorf("Expected LibcCFlags[0] to be '%s', got '%s'", expected, config.ExportCFlags[0])
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -428,8 +575,8 @@ func TestEdgeCases(t *testing.T) {
|
|||||||
|
|
||||||
// Check that paths are constructed correctly
|
// Check that paths are constructed correctly
|
||||||
expected := "-I" + filepath.Join(libcDir, "include")
|
expected := "-I" + filepath.Join(libcDir, "include")
|
||||||
if config.LibcCFlags[0] != expected {
|
if config.ExportCFlags[0] != expected {
|
||||||
t.Errorf("Expected LibcCFlags[0] to be '%s', got '%s'", expected, config.LibcCFlags[0])
|
t.Errorf("Expected LibcCFlags[0] to be '%s', got '%s'", expected, config.ExportCFlags[0])
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -21,16 +21,22 @@ var _libcCCFlags = []string{
|
|||||||
"-ffreestanding",
|
"-ffreestanding",
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
// withDefaultCCFlags appends default C compiler flags to the provided flags
|
||||||
_newlibUrl = "https://github.com/goplus/newlib/archive/refs/tags/v0.2.0.tar.gz"
|
|
||||||
_archiveInternalSrcDir = "newlib-0.2.0"
|
|
||||||
)
|
|
||||||
|
|
||||||
func withDefaultCCFlags(ccflags []string) []string {
|
func withDefaultCCFlags(ccflags []string) []string {
|
||||||
return append(ccflags, _libcCCFlags...)
|
return append(ccflags, _libcCCFlags...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func getNewlibESP32ConfigRISCV(baseDir, target string) *compile.CompileConfig {
|
// 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",
|
||||||
|
ResourceSubDir: "newlib-esp-4.3.0_20250211-patch3",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func getNewlibESP32ConfigRISCV(baseDir, target string) compile.CompileConfig {
|
||||||
libcDir := filepath.Join(baseDir, "newlib", "libc")
|
libcDir := filepath.Join(baseDir, "newlib", "libc")
|
||||||
|
|
||||||
libcIncludeDir := []string{
|
libcIncludeDir := []string{
|
||||||
@@ -39,11 +45,8 @@ func getNewlibESP32ConfigRISCV(baseDir, target string) *compile.CompileConfig {
|
|||||||
"-I" + libcDir,
|
"-I" + libcDir,
|
||||||
}
|
}
|
||||||
|
|
||||||
return &compile.CompileConfig{
|
return compile.CompileConfig{
|
||||||
Url: _newlibUrl,
|
ExportCFlags: libcIncludeDir,
|
||||||
Name: "newlib-esp32",
|
|
||||||
LibcCFlags: libcIncludeDir,
|
|
||||||
ArchiveSrcDir: _archiveInternalSrcDir,
|
|
||||||
Groups: []compile.CompileGroup{
|
Groups: []compile.CompileGroup{
|
||||||
{
|
{
|
||||||
OutputFileName: fmt.Sprintf("libcrt0-%s.a", target),
|
OutputFileName: fmt.Sprintf("libcrt0-%s.a", target),
|
||||||
@@ -1092,7 +1095,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")
|
libcDir := filepath.Join(baseDir, "newlib", "libc")
|
||||||
|
|
||||||
libcIncludeDir := []string{
|
libcIncludeDir := []string{
|
||||||
@@ -1101,11 +1104,8 @@ func getNewlibESP32ConfigXtensa(baseDir, target string) *compile.CompileConfig {
|
|||||||
"-I" + libcDir,
|
"-I" + libcDir,
|
||||||
}
|
}
|
||||||
|
|
||||||
return &compile.CompileConfig{
|
return compile.CompileConfig{
|
||||||
Url: _newlibUrl,
|
ExportCFlags: libcIncludeDir,
|
||||||
Name: "newlib-esp32",
|
|
||||||
ArchiveSrcDir: _archiveInternalSrcDir,
|
|
||||||
LibcCFlags: libcIncludeDir,
|
|
||||||
Groups: []compile.CompileGroup{
|
Groups: []compile.CompileGroup{
|
||||||
{
|
{
|
||||||
OutputFileName: fmt.Sprintf("libcrt0-%s.a", target),
|
OutputFileName: fmt.Sprintf("libcrt0-%s.a", target),
|
||||||
@@ -2075,7 +2075,7 @@ func getNewlibESP32ConfigXtensa(baseDir, target string) *compile.CompileConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// getNewlibESP32Config returns configuration for newlib esp32
|
// 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") {
|
if strings.Contains(target, "riscv32") {
|
||||||
return getNewlibESP32ConfigRISCV(baseDir, target)
|
return getNewlibESP32ConfigRISCV(baseDir, target)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,16 +7,23 @@ import (
|
|||||||
"github.com/goplus/llgo/internal/crosscompile/compile"
|
"github.com/goplus/llgo/internal/crosscompile/compile"
|
||||||
)
|
)
|
||||||
|
|
||||||
// getPicolibcConfig returns configuration for picolibc
|
// GetPicolibcConfig returns the configuration for downloading and building picolibc
|
||||||
func GetPicolibcConfig(baseDir, target string) *compile.CompileConfig {
|
func GetPicolibcConfig() compile.LibConfig {
|
||||||
return &compile.CompileConfig{
|
return compile.LibConfig{
|
||||||
Url: "https://github.com/goplus/picolibc/archive/refs/heads/main.zip",
|
|
||||||
Name: "picolibc",
|
Name: "picolibc",
|
||||||
LibcCFlags: []string{
|
Version: "v0.1.0",
|
||||||
|
Url: "https://github.com/goplus/picolibc/archive/refs/heads/main.zip",
|
||||||
|
ResourceSubDir: "picolibc-main",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetPicolibcCompileConfig returns configuration for picolibc
|
||||||
|
func GetPicolibcCompileConfig(baseDir, target string) compile.CompileConfig {
|
||||||
|
return compile.CompileConfig{
|
||||||
|
ExportCFlags: []string{
|
||||||
"-I" + baseDir,
|
"-I" + baseDir,
|
||||||
"-isystem" + filepath.Join(baseDir, "newlib", "libc", "include"),
|
"-isystem" + filepath.Join(baseDir, "newlib", "libc", "include"),
|
||||||
},
|
},
|
||||||
|
|
||||||
Groups: []compile.CompileGroup{
|
Groups: []compile.CompileGroup{
|
||||||
{
|
{
|
||||||
OutputFileName: fmt.Sprintf("libc-%s.a", target),
|
OutputFileName: fmt.Sprintf("libc-%s.a", target),
|
||||||
@@ -158,6 +165,5 @@ func GetPicolibcConfig(baseDir, target string) *compile.CompileConfig {
|
|||||||
CCFlags: _libcCCFlags,
|
CCFlags: _libcCCFlags,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
ArchiveSrcDir: "picolibc-main",
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -100,10 +100,17 @@ func withPlatformSpecifiedFiles(baseDir, target string, files []string) []string
|
|||||||
return append(files, platformSpecifiedFiles(builtinsDir, target)...)
|
return append(files, platformSpecifiedFiles(builtinsDir, target)...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetCompilerRTConfig(baseDir, target string) *compile.CompileConfig {
|
func GetCompilerRTConfig() compile.LibConfig {
|
||||||
return &compile.CompileConfig{
|
return compile.LibConfig{
|
||||||
Url: "https://github.com/goplus/compiler-rt/archive/refs/tags/v0.1.0.tar.gz",
|
Name: "compiler-rt",
|
||||||
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",
|
||||||
|
ResourceSubDir: "compiler-rt-xtensa_release_19.1.2",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetCompilerRTCompileConfig(baseDir, target string) compile.CompileConfig {
|
||||||
|
return compile.CompileConfig{
|
||||||
Groups: []compile.CompileGroup{
|
Groups: []compile.CompileGroup{
|
||||||
{
|
{
|
||||||
OutputFileName: fmt.Sprintf("libclang_builtins-%s.a", target),
|
OutputFileName: fmt.Sprintf("libclang_builtins-%s.a", target),
|
||||||
@@ -277,7 +284,8 @@ func GetCompilerRTConfig(baseDir, target string) *compile.CompileConfig {
|
|||||||
"-Werror=return-stack-address",
|
"-Werror=return-stack-address",
|
||||||
"-Werror=sizeof-array-decay",
|
"-Werror=sizeof-array-decay",
|
||||||
"-Werror=format-insufficient-args",
|
"-Werror=format-insufficient-args",
|
||||||
"-Wformat -std=c11",
|
"-Wformat",
|
||||||
|
"-std=c11",
|
||||||
"-fno-builtin",
|
"-fno-builtin",
|
||||||
"-fvisibility=hidden",
|
"-fvisibility=hidden",
|
||||||
"-fomit-frame-pointer",
|
"-fomit-frame-pointer",
|
||||||
|
|||||||
@@ -5,6 +5,37 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func TestGetCompilerRTConfig_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.ResourceSubDir != expectedArchiveSrcDir {
|
||||||
|
t.Errorf("Expected ResourceSubDir '%s', got '%s'", expectedArchiveSrcDir, config.ResourceSubDir)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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) {
|
func TestPlatformSpecifiedFiles(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
target string
|
target string
|
||||||
@@ -60,7 +91,7 @@ func TestGetCompilerRTConfig(t *testing.T) {
|
|||||||
baseDir := "/test/base"
|
baseDir := "/test/base"
|
||||||
target := "riscv32-unknown-elf"
|
target := "riscv32-unknown-elf"
|
||||||
|
|
||||||
config := GetCompilerRTConfig(baseDir, target)
|
config := GetCompilerRTCompileConfig(baseDir, target)
|
||||||
|
|
||||||
// Test groups configuration
|
// Test groups configuration
|
||||||
if len(config.Groups) != 1 {
|
if len(config.Groups) != 1 {
|
||||||
@@ -101,15 +132,8 @@ func TestGetCompilerRTConfig_DifferentTargets(t *testing.T) {
|
|||||||
baseDir := "/test/base"
|
baseDir := "/test/base"
|
||||||
for _, target := range targets {
|
for _, target := range targets {
|
||||||
t.Run(target, func(t *testing.T) {
|
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 {
|
if len(config.Groups) == 0 {
|
||||||
t.Error("Should have at least one group")
|
t.Error("Should have at least one group")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -168,20 +168,18 @@ func getESPClangPlatform(goos, goarch string) string {
|
|||||||
return ""
|
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 {
|
func ldFlagsFromFileName(fileName string) string {
|
||||||
return strings.TrimPrefix(strings.TrimSuffix(fileName, ".a"), "lib")
|
return strings.TrimPrefix(strings.TrimSuffix(fileName, ".a"), "lib")
|
||||||
}
|
}
|
||||||
|
|
||||||
func getOrCompileWithConfig(
|
// compileWithConfig compiles libraries according to the provided configuration
|
||||||
compileConfig *compile.CompileConfig,
|
// and returns the necessary linker flags for linking against the compiled libraries
|
||||||
|
func compileWithConfig(
|
||||||
|
compileConfig compile.CompileConfig,
|
||||||
outputDir string, options compile.CompileOptions,
|
outputDir string, options compile.CompileOptions,
|
||||||
) (ldflags []string, err error) {
|
) (ldflags []string, err error) {
|
||||||
if err = checkDownloadAndExtractLib(
|
|
||||||
compileConfig.Url, outputDir,
|
|
||||||
compileConfig.ArchiveSrcDir,
|
|
||||||
); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
ldflags = append(ldflags, "-nostdlib", "-L"+outputDir)
|
ldflags = append(ldflags, "-nostdlib", "-L"+outputDir)
|
||||||
|
|
||||||
for _, group := range compileConfig.Groups {
|
for _, group := range compileConfig.Groups {
|
||||||
@@ -587,16 +585,16 @@ func UseTarget(targetName string) (export Export, err error) {
|
|||||||
var libcIncludeDir []string
|
var libcIncludeDir []string
|
||||||
|
|
||||||
if config.Libc != "" {
|
if config.Libc != "" {
|
||||||
|
var outputDir string
|
||||||
var libcLDFlags []string
|
var libcLDFlags []string
|
||||||
var compileConfig *compile.CompileConfig
|
var compileConfig compile.CompileConfig
|
||||||
baseDir := filepath.Join(cacheRoot(), "crosscompile")
|
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 {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
libcLDFlags, err = getOrCompileWithConfig(compileConfig, outputDir, compile.CompileOptions{
|
libcLDFlags, err = compileWithConfig(compileConfig, outputDir, compile.CompileOptions{
|
||||||
CC: export.CC,
|
CC: export.CC,
|
||||||
Linker: export.Linker,
|
Linker: export.Linker,
|
||||||
CCFLAGS: ccflags,
|
CCFLAGS: ccflags,
|
||||||
@@ -605,24 +603,24 @@ func UseTarget(targetName string) (export Export, err error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
cflags = append(cflags, compileConfig.LibcCFlags...)
|
cflags = append(cflags, compileConfig.ExportCFlags...)
|
||||||
ldflags = append(ldflags, libcLDFlags...)
|
ldflags = append(ldflags, libcLDFlags...)
|
||||||
|
|
||||||
libcIncludeDir = compileConfig.LibcCFlags
|
libcIncludeDir = compileConfig.ExportCFlags
|
||||||
export.Libc = config.Libc
|
export.Libc = config.Libc
|
||||||
}
|
}
|
||||||
|
|
||||||
if config.RTLib != "" {
|
if config.RTLib != "" {
|
||||||
|
var outputDir string
|
||||||
var rtLibLDFlags []string
|
var rtLibLDFlags []string
|
||||||
var compileConfig *compile.CompileConfig
|
var compileConfig compile.CompileConfig
|
||||||
baseDir := filepath.Join(cacheRoot(), "crosscompile")
|
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 {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
rtLibLDFlags, err = getOrCompileWithConfig(compileConfig, outputDir, compile.CompileOptions{
|
rtLibLDFlags, err = compileWithConfig(compileConfig, outputDir, compile.CompileOptions{
|
||||||
CC: export.CC,
|
CC: export.CC,
|
||||||
Linker: export.Linker,
|
Linker: export.Linker,
|
||||||
CCFLAGS: ccflags,
|
CCFLAGS: ccflags,
|
||||||
|
|||||||
@@ -37,10 +37,10 @@ func TestUseCrossCompileSDK(t *testing.T) {
|
|||||||
name: "Same Platform",
|
name: "Same Platform",
|
||||||
goos: runtime.GOOS,
|
goos: runtime.GOOS,
|
||||||
goarch: runtime.GOARCH,
|
goarch: runtime.GOARCH,
|
||||||
expectSDK: true, // Changed: now we expect flags even for same platform
|
expectSDK: true, // We expect flags even for same platform
|
||||||
expectCCFlags: true, // Changed: CCFLAGS will contain sysroot
|
expectCCFlags: true, // CCFLAGS will contain sysroot
|
||||||
expectCFlags: false, // Changed: CFLAGS will not contain include paths
|
expectCFlags: false, // CFLAGS will not contain include paths
|
||||||
expectLDFlags: false, // Changed: LDFLAGS will not contain library paths
|
expectLDFlags: false, // LDFLAGS will not contain library paths
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "WASM Target",
|
name: "WASM Target",
|
||||||
|
|||||||
@@ -9,34 +9,70 @@ import (
|
|||||||
"github.com/goplus/llgo/internal/crosscompile/compile/rtlib"
|
"github.com/goplus/llgo/internal/crosscompile/compile/rtlib"
|
||||||
)
|
)
|
||||||
|
|
||||||
// GetCompileConfigByName retrieves libc compilation configuration by name
|
// for testing, in testing env, we use fake path, it will cause downloading failure
|
||||||
// Returns compilation file lists and corresponding cflags
|
var needSkipDownload = false
|
||||||
func getLibcCompileConfigByName(baseDir, libcName, target, mcpu string) (*compile.CompileConfig, error) {
|
|
||||||
|
// getLibcCompileConfigByName retrieves libc compilation configuration by name
|
||||||
|
// 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 == "" {
|
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 {
|
switch libcName {
|
||||||
case "picolibc":
|
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":
|
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:
|
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.ResourceSubDir); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
return libcDir, compileConfig, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getRTCompileConfigByName(baseDir, rtName, target string) (*compile.CompileConfig, error) {
|
// getRTCompileConfigByName retrieves runtime library compilation configuration by name
|
||||||
|
// 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 == "" {
|
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 {
|
switch rtName {
|
||||||
case "compiler-rt":
|
case "compiler-rt":
|
||||||
return rtlib.GetCompilerRTConfig(rtDir, target), nil
|
config = rtlib.GetCompilerRTConfig()
|
||||||
|
rtDir = filepath.Join(baseDir, config.String())
|
||||||
|
compileConfig = rtlib.GetCompilerRTCompileConfig(rtDir, target)
|
||||||
default:
|
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.ResourceSubDir); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
return rtDir, compileConfig, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,9 +3,14 @@
|
|||||||
package crosscompile
|
package crosscompile
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"slices"
|
"slices"
|
||||||
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/goplus/llgo/internal/crosscompile/compile/libc"
|
||||||
|
"github.com/goplus/llgo/internal/crosscompile/compile/rtlib"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestGetLibcCompileConfigByName(t *testing.T) {
|
func TestGetLibcCompileConfigByName(t *testing.T) {
|
||||||
@@ -13,22 +18,23 @@ func TestGetLibcCompileConfigByName(t *testing.T) {
|
|||||||
target := "armv7"
|
target := "armv7"
|
||||||
mcpu := "cortex-m4"
|
mcpu := "cortex-m4"
|
||||||
|
|
||||||
|
needSkipDownload = true
|
||||||
t.Run("EmptyName", func(t *testing.T) {
|
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" {
|
if err == nil || err.Error() != "libc name cannot be empty" {
|
||||||
t.Errorf("Expected empty name error, got: %v", err)
|
t.Errorf("Expected empty name error, got: %v", err)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("UnsupportedLibc", func(t *testing.T) {
|
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" {
|
if err == nil || err.Error() != "unsupported libc: invalid" {
|
||||||
t.Errorf("Expected unsupported libc error, got: %v", err)
|
t.Errorf("Expected unsupported libc error, got: %v", err)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Picolibc", func(t *testing.T) {
|
t.Run("Picolibc", func(t *testing.T) {
|
||||||
cfg, err := getLibcCompileConfigByName(baseDir, "picolibc", target, mcpu)
|
_, cfg, err := getLibcCompileConfigByName(baseDir, "picolibc", target, mcpu)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Unexpected error: %v", err)
|
t.Fatalf("Unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
@@ -38,19 +44,19 @@ func TestGetLibcCompileConfigByName(t *testing.T) {
|
|||||||
}
|
}
|
||||||
group := cfg.Groups[0]
|
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) {
|
if !slices.Contains(group.Files, expectedFile) {
|
||||||
t.Errorf("Expected files [%s], got: %v", expectedFile, group.Files)
|
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) {
|
if !slices.Contains(group.CFlags, expectedFlag) {
|
||||||
t.Errorf("Expected flags [%s], got: %v", expectedFlag, group.CFlags)
|
t.Errorf("Expected flags [%s], got: %v", expectedFlag, group.CFlags)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("NewlibESP32", func(t *testing.T) {
|
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 {
|
if err != nil {
|
||||||
t.Fatalf("Unexpected error: %v", err)
|
t.Fatalf("Unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
@@ -60,12 +66,12 @@ func TestGetLibcCompileConfigByName(t *testing.T) {
|
|||||||
}
|
}
|
||||||
group := cfg.Groups[0]
|
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) {
|
if !slices.Contains(group.Files, expectedFile) {
|
||||||
t.Errorf("Expected files [%s], got: %v", expectedFile, group.Files)
|
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) {
|
if !slices.Contains(group.CFlags, expectedFlags) {
|
||||||
t.Errorf("Expected flags %v, got: %v", expectedFlags, group.CFlags)
|
t.Errorf("Expected flags %v, got: %v", expectedFlags, group.CFlags)
|
||||||
}
|
}
|
||||||
@@ -75,23 +81,24 @@ func TestGetLibcCompileConfigByName(t *testing.T) {
|
|||||||
func TestGetRTCompileConfigByName(t *testing.T) {
|
func TestGetRTCompileConfigByName(t *testing.T) {
|
||||||
baseDir := "/test/base"
|
baseDir := "/test/base"
|
||||||
target := "wasm32"
|
target := "wasm32"
|
||||||
|
needSkipDownload = true
|
||||||
|
|
||||||
t.Run("EmptyName", func(t *testing.T) {
|
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" {
|
if err == nil || err.Error() != "rt name cannot be empty" {
|
||||||
t.Errorf("Expected empty name error, got: %v", err)
|
t.Errorf("Expected empty name error, got: %v", err)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("UnsupportedRT", func(t *testing.T) {
|
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" {
|
if err == nil || err.Error() != "unsupported rt: invalid" {
|
||||||
t.Errorf("Expected unsupported rt error, got: %v", err)
|
t.Errorf("Expected unsupported rt error, got: %v", err)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("CompilerRT", func(t *testing.T) {
|
t.Run("CompilerRT", func(t *testing.T) {
|
||||||
cfg, err := getRTCompileConfigByName(baseDir, "compiler-rt", target)
|
_, cfg, err := getRTCompileConfigByName(baseDir, "compiler-rt", target)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Unexpected error: %v", err)
|
t.Fatalf("Unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
@@ -101,9 +108,302 @@ func TestGetRTCompileConfigByName(t *testing.T) {
|
|||||||
}
|
}
|
||||||
group := cfg.Groups[0]
|
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) {
|
if !slices.Contains(group.Files, expectedFile) {
|
||||||
t.Errorf("Expected files [%s], got: %v", expectedFile, group.Files)
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -5,23 +5,6 @@ ENTRY(_start)
|
|||||||
SECTIONS
|
SECTIONS
|
||||||
{
|
{
|
||||||
. = SEGMENT_START("iram_seg", 0);
|
. = 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 :
|
text :
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user