feat: support compiler-rt

This commit is contained in:
Haolan
2025-08-29 11:30:25 +08:00
parent f3ecce86ee
commit 4639ee13e7
11 changed files with 497 additions and 119 deletions

View File

@@ -907,7 +907,7 @@ define weak void @_start() {
if !needStart(ctx.buildConf) && isWasmTarget(ctx.buildConf.Goos) {
mainDefine = "define hidden noundef i32 @__main_argc_argv(i32 noundef %0, ptr nocapture noundef readnone %1) local_unnamed_addr"
}
if !needStart(ctx.buildConf) {
if true {
startDefine = ""
}
mainCode := fmt.Sprintf(`; ModuleID = 'main'

View File

@@ -0,0 +1,99 @@
package compile
import (
"fmt"
"os"
"os/exec"
"path/filepath"
"slices"
"strings"
"github.com/goplus/llgo/internal/clang"
)
type CompileGroup struct {
OutputFileName string
Files []string // List of source files to compile
CFlags []string // C compiler flags
CCFlags []string
LDFlags []string // Linker flags
}
func (g CompileGroup) IsCompiled(outputDir string) bool {
archive := filepath.Join(outputDir, g.OutputFileName)
_, err := os.Stat(archive)
return !os.IsNotExist(err)
}
func (g CompileGroup) Compile(outputDir, cc, linkerName string, extraCCFlags, extraLDFlags []string) (err error) {
if g.IsCompiled(outputDir) {
return
}
tmpCompileDir, err := os.MkdirTemp("", "compile-group*")
if err != nil {
return
}
defer os.RemoveAll(tmpCompileDir)
compileLDFlags := append(slices.Clone(extraLDFlags), g.LDFlags...)
compileCCFlags := append(slices.Clone(extraCCFlags), g.CCFlags...)
cfg := clang.NewConfig(cc, compileCCFlags, g.CFlags, compileLDFlags, linkerName)
var objFiles []string
compiler := clang.NewCompiler(cfg)
compiler.Verbose = true
archive := filepath.Join(outputDir, g.OutputFileName)
fmt.Fprintf(os.Stderr, "Start to compile group %s to %s...\n", g.OutputFileName, archive)
for _, file := range g.Files {
var tempObjFile *os.File
tempObjFile, err = os.CreateTemp(tmpCompileDir, fmt.Sprintf("%s*.o", strings.ReplaceAll(file, string(os.PathSeparator), "-")))
if err != nil {
return
}
fmt.Fprintf(os.Stderr, "Compile file %s to %s...\n", file, tempObjFile.Name())
lang := "c"
if filepath.Ext(file) == ".S" {
lang = "assembler-with-cpp"
}
err = compiler.Compile("-o", tempObjFile.Name(), "-x", lang, "-c", file)
if err != nil {
return
}
objFiles = append(objFiles, tempObjFile.Name())
}
args := []string{"rcs", archive}
args = append(args, objFiles...)
ccDir := filepath.Dir(cc)
llvmAr := filepath.Join(ccDir, "llvm-ar")
cmd := exec.Command(llvmAr, args...)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
err = cmd.Run()
return
}
// CompileConfig represents compilation configuration
type CompileConfig struct {
Url string
Name string // compile name (e.g., "picolibc", "musl", "glibc")
Groups []CompileGroup
ArchiveSrcDir string
}
func (c CompileConfig) IsCompiled(outputDir string) bool {
for _, group := range c.Groups {
if !group.IsCompiled(outputDir) {
return false
}
}
return true
}

View File

@@ -1,20 +1,22 @@
package crosscompile
package libc
import (
"path/filepath"
"github.com/goplus/llgo/internal/crosscompile/compile"
)
// getNewlibESP32Config returns configuration for newlib esp32
func getNewlibESP32Config(baseDir, arch string) *compileLibcConfig {
func GetNewlibESP32Config(baseDir, arch string) *compile.CompileConfig {
libcDir := filepath.Join(baseDir, "newlib", "libc")
// headerFile, _ := os.Create(filepath.Join(baseDir, "picolibc.h"))
// headerFile.Close()
return &compileLibcConfig{
return &compile.CompileConfig{
Url: "https://github.com/MeteorsLiu/newlib-esp32/archive/refs/heads/esp-4.3.0.zip",
Name: "newlib-esp32",
Groups: []compileGroup{
Groups: []compile.CompileGroup{
{
OutputFileName: "libcrt0.a",
Files: []string{
@@ -23,7 +25,6 @@ func getNewlibESP32Config(baseDir, arch string) *compileLibcConfig {
filepath.Join(baseDir, "libgloss", "xtensa", "boards", "esp32", "board.c"),
filepath.Join(baseDir, "libgloss", "xtensa", "crt1-boards.S"),
filepath.Join(baseDir, "libgloss", "xtensa", "sleep.S"),
filepath.Join(baseDir, "libgloss", "xtensa", "window-vectors.S"),
},
CFlags: []string{
"-DHAVE_CONFIG_H",
@@ -974,7 +975,7 @@ func getNewlibESP32Config(baseDir, arch string) *compileLibcConfig {
"-I" + filepath.Join(libcDir, "posix"),
"-I" + filepath.Join(libcDir, "stdlib"),
},
LDFlags: []string{"-nostdlib", "-L" + baseDir, "-lgloss"},
LDFlags: []string{"-nostdlib"},
CCFlags: []string{
"-Oz",
"-fno-builtin",

View File

@@ -1,12 +1,14 @@
package crosscompile
package libc
import (
"os"
"path/filepath"
"github.com/goplus/llgo/internal/crosscompile/compile"
)
// getPicolibcConfig returns configuration for picolibc
func getPicolibcConfig(baseDir string) *compileLibcConfig {
func GetPicolibcConfig(baseDir string) *compile.CompileConfig {
libcIncludeDir := filepath.Join(baseDir, "libc", "include")
libmIncludeDir := filepath.Join(baseDir, "libm", "common")
localeIncludeDir := filepath.Join(baseDir, "libc", "locale")
@@ -16,10 +18,10 @@ func getPicolibcConfig(baseDir string) *compileLibcConfig {
headerFile, _ := os.Create(filepath.Join(baseDir, "picolibc.h"))
headerFile.Close()
return &compileLibcConfig{
return &compile.CompileConfig{
Url: "https://github.com/picolibc/picolibc/releases/download/1.8.10/picolibc-1.8.10.tar.xz",
Name: "picolibc",
Groups: []compileGroup{
Groups: []compile.CompileGroup{
{
OutputFileName: "libc.a",
Files: []string{

View File

@@ -0,0 +1,195 @@
package rtlib
import (
"path/filepath"
"github.com/goplus/llgo/internal/crosscompile/compile"
)
func GetCompilerRTConfig(baseDir, arch string) *compile.CompileConfig {
return &compile.CompileConfig{
Url: "https://github.com/MeteorsLiu/llvm-project/archive/refs/heads/compiler-rt.zip",
ArchiveSrcDir: "llvm-project-compiler-rt",
Groups: []compile.CompileGroup{
{
OutputFileName: "libclang_builtins.a",
Files: []string{
filepath.Join(baseDir, "lib", "builtins", "xtensa/ieee754_sqrtf.S"),
filepath.Join(baseDir, "lib", "builtins", "absvdi2.c"),
filepath.Join(baseDir, "lib", "builtins", "absvsi2.c"),
filepath.Join(baseDir, "lib", "builtins", "absvti2.c"),
filepath.Join(baseDir, "lib", "builtins", "adddf3.c"),
filepath.Join(baseDir, "lib", "builtins", "addsf3.c"),
filepath.Join(baseDir, "lib", "builtins", "addvdi3.c"),
filepath.Join(baseDir, "lib", "builtins", "addvsi3.c"),
filepath.Join(baseDir, "lib", "builtins", "addvti3.c"),
filepath.Join(baseDir, "lib", "builtins", "apple_versioning.c"),
filepath.Join(baseDir, "lib", "builtins", "ashldi3.c"),
filepath.Join(baseDir, "lib", "builtins", "ashlti3.c"),
filepath.Join(baseDir, "lib", "builtins", "ashrdi3.c"),
filepath.Join(baseDir, "lib", "builtins", "ashrti3.c"),
filepath.Join(baseDir, "lib", "builtins", "bswapdi2.c"),
filepath.Join(baseDir, "lib", "builtins", "bswapsi2.c"),
filepath.Join(baseDir, "lib", "builtins", "clzdi2.c"),
filepath.Join(baseDir, "lib", "builtins", "clzsi2.c"),
filepath.Join(baseDir, "lib", "builtins", "clzti2.c"),
filepath.Join(baseDir, "lib", "builtins", "cmpdi2.c"),
filepath.Join(baseDir, "lib", "builtins", "cmpti2.c"),
filepath.Join(baseDir, "lib", "builtins", "comparedf2.c"),
filepath.Join(baseDir, "lib", "builtins", "comparesf2.c"),
filepath.Join(baseDir, "lib", "builtins", "ctzdi2.c"),
filepath.Join(baseDir, "lib", "builtins", "ctzsi2.c"),
filepath.Join(baseDir, "lib", "builtins", "ctzti2.c"),
filepath.Join(baseDir, "lib", "builtins", "divdc3.c"),
filepath.Join(baseDir, "lib", "builtins", "divdf3.c"),
filepath.Join(baseDir, "lib", "builtins", "divdi3.c"),
filepath.Join(baseDir, "lib", "builtins", "divmoddi4.c"),
filepath.Join(baseDir, "lib", "builtins", "divmodsi4.c"),
filepath.Join(baseDir, "lib", "builtins", "divmodti4.c"),
filepath.Join(baseDir, "lib", "builtins", "divsc3.c"),
filepath.Join(baseDir, "lib", "builtins", "divsf3.c"),
filepath.Join(baseDir, "lib", "builtins", "divsi3.c"),
filepath.Join(baseDir, "lib", "builtins", "divti3.c"),
filepath.Join(baseDir, "lib", "builtins", "extendsfdf2.c"),
filepath.Join(baseDir, "lib", "builtins", "extendhfsf2.c"),
filepath.Join(baseDir, "lib", "builtins", "ffsdi2.c"),
filepath.Join(baseDir, "lib", "builtins", "ffssi2.c"),
filepath.Join(baseDir, "lib", "builtins", "ffsti2.c"),
filepath.Join(baseDir, "lib", "builtins", "fixdfdi.c"),
filepath.Join(baseDir, "lib", "builtins", "fixdfsi.c"),
filepath.Join(baseDir, "lib", "builtins", "fixdfti.c"),
filepath.Join(baseDir, "lib", "builtins", "fixsfdi.c"),
filepath.Join(baseDir, "lib", "builtins", "fixsfsi.c"),
filepath.Join(baseDir, "lib", "builtins", "fixsfti.c"),
filepath.Join(baseDir, "lib", "builtins", "fixunsdfdi.c"),
filepath.Join(baseDir, "lib", "builtins", "fixunsdfsi.c"),
filepath.Join(baseDir, "lib", "builtins", "fixunsdfti.c"),
filepath.Join(baseDir, "lib", "builtins", "fixunssfdi.c"),
filepath.Join(baseDir, "lib", "builtins", "fixunssfsi.c"),
filepath.Join(baseDir, "lib", "builtins", "fixunssfti.c"),
filepath.Join(baseDir, "lib", "builtins", "floatdidf.c"),
filepath.Join(baseDir, "lib", "builtins", "floatdisf.c"),
filepath.Join(baseDir, "lib", "builtins", "floatsidf.c"),
filepath.Join(baseDir, "lib", "builtins", "floatsisf.c"),
filepath.Join(baseDir, "lib", "builtins", "floattidf.c"),
filepath.Join(baseDir, "lib", "builtins", "floattisf.c"),
filepath.Join(baseDir, "lib", "builtins", "floatundidf.c"),
filepath.Join(baseDir, "lib", "builtins", "floatundisf.c"),
filepath.Join(baseDir, "lib", "builtins", "floatunsidf.c"),
filepath.Join(baseDir, "lib", "builtins", "floatunsisf.c"),
filepath.Join(baseDir, "lib", "builtins", "floatuntidf.c"),
filepath.Join(baseDir, "lib", "builtins", "floatuntisf.c"),
filepath.Join(baseDir, "lib", "builtins", "fp_mode.c"),
filepath.Join(baseDir, "lib", "builtins", "int_util.c"),
filepath.Join(baseDir, "lib", "builtins", "lshrdi3.c"),
filepath.Join(baseDir, "lib", "builtins", "lshrti3.c"),
filepath.Join(baseDir, "lib", "builtins", "moddi3.c"),
filepath.Join(baseDir, "lib", "builtins", "modsi3.c"),
filepath.Join(baseDir, "lib", "builtins", "modti3.c"),
filepath.Join(baseDir, "lib", "builtins", "muldc3.c"),
filepath.Join(baseDir, "lib", "builtins", "muldf3.c"),
filepath.Join(baseDir, "lib", "builtins", "muldi3.c"),
filepath.Join(baseDir, "lib", "builtins", "mulodi4.c"),
filepath.Join(baseDir, "lib", "builtins", "mulosi4.c"),
filepath.Join(baseDir, "lib", "builtins", "muloti4.c"),
filepath.Join(baseDir, "lib", "builtins", "mulsc3.c"),
filepath.Join(baseDir, "lib", "builtins", "mulsf3.c"),
filepath.Join(baseDir, "lib", "builtins", "multi3.c"),
filepath.Join(baseDir, "lib", "builtins", "mulvdi3.c"),
filepath.Join(baseDir, "lib", "builtins", "mulvsi3.c"),
filepath.Join(baseDir, "lib", "builtins", "mulvti3.c"),
filepath.Join(baseDir, "lib", "builtins", "negdf2.c"),
filepath.Join(baseDir, "lib", "builtins", "negdi2.c"),
filepath.Join(baseDir, "lib", "builtins", "negsf2.c"),
filepath.Join(baseDir, "lib", "builtins", "negti2.c"),
filepath.Join(baseDir, "lib", "builtins", "negvdi2.c"),
filepath.Join(baseDir, "lib", "builtins", "negvsi2.c"),
filepath.Join(baseDir, "lib", "builtins", "negvti2.c"),
filepath.Join(baseDir, "lib", "builtins", "os_version_check.c"),
filepath.Join(baseDir, "lib", "builtins", "paritydi2.c"),
filepath.Join(baseDir, "lib", "builtins", "paritysi2.c"),
filepath.Join(baseDir, "lib", "builtins", "parityti2.c"),
filepath.Join(baseDir, "lib", "builtins", "popcountdi2.c"),
filepath.Join(baseDir, "lib", "builtins", "popcountsi2.c"),
filepath.Join(baseDir, "lib", "builtins", "popcountti2.c"),
filepath.Join(baseDir, "lib", "builtins", "powidf2.c"),
filepath.Join(baseDir, "lib", "builtins", "powisf2.c"),
filepath.Join(baseDir, "lib", "builtins", "subdf3.c"),
filepath.Join(baseDir, "lib", "builtins", "subsf3.c"),
filepath.Join(baseDir, "lib", "builtins", "subvdi3.c"),
filepath.Join(baseDir, "lib", "builtins", "subvsi3.c"),
filepath.Join(baseDir, "lib", "builtins", "subvti3.c"),
filepath.Join(baseDir, "lib", "builtins", "trampoline_setup.c"),
filepath.Join(baseDir, "lib", "builtins", "truncdfhf2.c"),
filepath.Join(baseDir, "lib", "builtins", "truncdfsf2.c"),
filepath.Join(baseDir, "lib", "builtins", "truncsfhf2.c"),
filepath.Join(baseDir, "lib", "builtins", "ucmpdi2.c"),
filepath.Join(baseDir, "lib", "builtins", "ucmpti2.c"),
filepath.Join(baseDir, "lib", "builtins", "udivdi3.c"),
filepath.Join(baseDir, "lib", "builtins", "udivmoddi4.c"),
filepath.Join(baseDir, "lib", "builtins", "udivmodsi4.c"),
filepath.Join(baseDir, "lib", "builtins", "udivmodti4.c"),
filepath.Join(baseDir, "lib", "builtins", "udivsi3.c"),
filepath.Join(baseDir, "lib", "builtins", "udivti3.c"),
filepath.Join(baseDir, "lib", "builtins", "umoddi3.c"),
filepath.Join(baseDir, "lib", "builtins", "umodsi3.c"),
filepath.Join(baseDir, "lib", "builtins", "umodti3.c"),
filepath.Join(baseDir, "lib", "builtins", "gcc_personality_v0.c"),
filepath.Join(baseDir, "lib", "builtins", "clear_cache.c"),
filepath.Join(baseDir, "lib", "builtins", "addtf3.c"),
filepath.Join(baseDir, "lib", "builtins", "comparetf2.c"),
filepath.Join(baseDir, "lib", "builtins", "divtc3.c"),
filepath.Join(baseDir, "lib", "builtins", "divtf3.c"),
filepath.Join(baseDir, "lib", "builtins", "extenddftf2.c"),
filepath.Join(baseDir, "lib", "builtins", "extendhftf2.c"),
filepath.Join(baseDir, "lib", "builtins", "extendsftf2.c"),
filepath.Join(baseDir, "lib", "builtins", "fixtfdi.c"),
filepath.Join(baseDir, "lib", "builtins", "fixtfsi.c"),
filepath.Join(baseDir, "lib", "builtins", "fixtfti.c"),
filepath.Join(baseDir, "lib", "builtins", "fixunstfdi.c"),
filepath.Join(baseDir, "lib", "builtins", "fixunstfsi.c"),
filepath.Join(baseDir, "lib", "builtins", "fixunstfti.c"),
filepath.Join(baseDir, "lib", "builtins", "floatditf.c"),
filepath.Join(baseDir, "lib", "builtins", "floatsitf.c"),
filepath.Join(baseDir, "lib", "builtins", "floattitf.c"),
filepath.Join(baseDir, "lib", "builtins", "floatunditf.c"),
filepath.Join(baseDir, "lib", "builtins", "floatunsitf.c"),
filepath.Join(baseDir, "lib", "builtins", "floatuntitf.c"),
filepath.Join(baseDir, "lib", "builtins", "multc3.c"),
filepath.Join(baseDir, "lib", "builtins", "multf3.c"),
filepath.Join(baseDir, "lib", "builtins", "powitf2.c"),
filepath.Join(baseDir, "lib", "builtins", "subtf3.c"),
filepath.Join(baseDir, "lib", "builtins", "trunctfdf2.c"),
filepath.Join(baseDir, "lib", "builtins", "trunctfhf2.c"),
filepath.Join(baseDir, "lib", "builtins", "trunctfsf2.c"),
},
CFlags: []string{
"-DNDEBUG",
"-DVISIBILITY_HIDDEN",
},
CCFlags: []string{
"-Oz",
"-fno-ident",
"-Wno-unused-parameter",
"-fno-lto",
"-Werror=array-bounds",
"-Werror=uninitialized",
"-Werror=shadow",
"-Werror=empty-body",
"-Werror=sizeof-pointer-memaccess",
"-Werror=sizeof-array-argument",
"-Werror=suspicious-memaccess",
"-Werror=builtin-memcpy-chk-size",
"-Werror=array-bounds-pointer-arithmetic",
"-Werror=return-stack-address",
"-Werror=sizeof-array-decay",
"-Werror=format-insufficient-args",
"-Wformat -std=c11",
"-fno-builtin",
"-fvisibility=hidden",
"-fomit-frame-pointer",
},
},
},
}
}

View File

@@ -10,6 +10,7 @@ import (
"runtime"
"strings"
"github.com/goplus/llgo/internal/crosscompile/compile"
"github.com/goplus/llgo/internal/env"
"github.com/goplus/llgo/internal/targets"
"github.com/goplus/llgo/internal/xtool/llvm"
@@ -219,15 +220,8 @@ func ldFlagsFromFileName(fileName string) string {
return strings.TrimPrefix(strings.TrimSuffix(fileName, ".a"), "lib")
}
func getOrCompileLibc(cc, linkerName, libcName string, exportCCFlags, exportLDFlags []string) (ldflags []string, err error) {
baseDir := filepath.Join(cacheRoot(), "crosscompile")
outputDir := filepath.Join(baseDir, libcName)
compileConfig, err := getCompileLibcConfigByName(baseDir, libcName)
if err != nil {
return
}
if err = checkDownloadAndExtractLibc(compileConfig, compileConfig.Url, outputDir, compileConfig.ArchiveSrcDir); err != nil {
func getOrCompileWithConfig(compileConfig *compile.CompileConfig, outputDir, cc, linkerName, libName string, exportCCFlags, exportLDFlags []string) (ldflags []string, err error) {
if err = checkDownloadAndExtractLib(compileConfig, compileConfig.Url, outputDir, compileConfig.ArchiveSrcDir); err != nil {
return
}
ldflags = append(ldflags, "-nostdlib", "-L"+outputDir)
@@ -606,13 +600,38 @@ func useTarget(targetName string) (export Export, err error) {
if config.Libc != "" {
var libcLDFlags []string
libcLDFlags, err = getOrCompileLibc(export.CC, export.Linker, config.Libc, ccflags, ldflags)
var compileConfig *compile.CompileConfig
baseDir := filepath.Join(cacheRoot(), "crosscompile")
outputDir := filepath.Join(baseDir, config.Libc)
compileConfig, err = getLibcCompileConfigByName(baseDir, config.Libc)
if err != nil {
return
}
libcLDFlags, err = getOrCompileWithConfig(compileConfig, outputDir, export.CC, export.Linker, config.Libc, ccflags, ldflags)
if err != nil {
return
}
ldflags = append(ldflags, libcLDFlags...)
}
if config.RTLib != "" {
var rtLibLDFlags []string
var compileConfig *compile.CompileConfig
baseDir := filepath.Join(cacheRoot(), "crosscompile")
outputDir := filepath.Join(baseDir, config.RTLib)
compileConfig, err = getRTCompileConfigByName(baseDir, config.RTLib)
if err != nil {
return
}
rtLibLDFlags, err = getOrCompileWithConfig(compileConfig, outputDir, export.CC, export.Linker, config.RTLib, ccflags, ldflags)
if err != nil {
return
}
ldflags = append(ldflags, rtLibLDFlags...)
}
// Combine with config flags and expand template variables
export.CFLAGS = cflags
export.CCFLAGS = ccflags

View File

@@ -13,6 +13,8 @@ import (
"path/filepath"
"strings"
"syscall"
"github.com/goplus/llgo/internal/crosscompile/compile"
)
// checkDownloadAndExtractWasiSDK downloads and extracts WASI SDK
@@ -80,7 +82,7 @@ func checkDownloadAndExtractESPClang(platformSuffix, dir string) error {
return nil
}
func checkDownloadAndExtractLibc(cfg *compileLibcConfig, url, dstDir, internalArchiveSrcDir string) error {
func checkDownloadAndExtractLib(cfg *compile.CompileConfig, url, dstDir, internalArchiveSrcDir string) error {
// Check if already exists
if cfg.IsCompiled(dstDir) {
return nil
@@ -107,7 +109,7 @@ func checkDownloadAndExtractLibc(cfg *compileLibcConfig, url, dstDir, internalAr
if err := downloadAndExtractArchive(url, tempExtractDir, description); err != nil {
return err
}
// defer os.RemoveAll(tempExtractDir)
defer os.RemoveAll(tempExtractDir)
srcDir := tempExtractDir
@@ -115,6 +117,7 @@ func checkDownloadAndExtractLibc(cfg *compileLibcConfig, url, dstDir, internalAr
srcDir = filepath.Join(tempExtractDir, internalArchiveSrcDir)
}
os.RemoveAll(dstDir)
if err := os.Rename(srcDir, dstDir); err != nil {
return fmt.Errorf("failed to rename libc directory: %w", err)
}

View File

@@ -2,105 +2,16 @@ package crosscompile
import (
"fmt"
"os"
"os/exec"
"path/filepath"
"slices"
"strings"
"github.com/goplus/llgo/internal/clang"
"github.com/goplus/llgo/internal/crosscompile/compile"
"github.com/goplus/llgo/internal/crosscompile/compile/libc"
"github.com/goplus/llgo/internal/crosscompile/compile/rtlib"
)
type compileGroup struct {
OutputFileName string
Files []string // List of source files to compile
CFlags []string // C compiler flags specific to this libc
CCFlags []string
LDFlags []string // Linker flags
}
func (g compileGroup) IsCompiled(outputDir string) bool {
libcArchive := filepath.Join(outputDir, g.OutputFileName)
_, err := os.Stat(libcArchive)
return !os.IsNotExist(err)
}
func (g compileGroup) Compile(outputDir, cc, linkerName string, extraCCFlags, extraLDFlags []string) (err error) {
if g.IsCompiled(outputDir) {
return
}
tmpCompileDir, err := os.MkdirTemp("", "compile-libc-group*")
if err != nil {
return
}
defer os.RemoveAll(tmpCompileDir)
compileLDFlags := append(slices.Clone(extraLDFlags), g.LDFlags...)
compileCCFlags := append(slices.Clone(extraCCFlags), g.CCFlags...)
cfg := clang.NewConfig(cc, compileCCFlags, g.CFlags, compileLDFlags, linkerName)
var objFiles []string
compiler := clang.NewCompiler(cfg)
compiler.Verbose = true
libcArchive := filepath.Join(outputDir, g.OutputFileName)
fmt.Fprintf(os.Stderr, "Start to compile libc group %s to %s...\n", g.OutputFileName, libcArchive)
for _, file := range g.Files {
var tempObjFile *os.File
tempObjFile, err = os.CreateTemp(tmpCompileDir, fmt.Sprintf("%s*.o", strings.ReplaceAll(file, string(os.PathSeparator), "-")))
if err != nil {
return
}
fmt.Fprintf(os.Stderr, "Compile libc file %s to %s...\n", file, tempObjFile.Name())
lang := "c"
if filepath.Ext(file) == ".S" {
lang = "assembler-with-cpp"
}
err = compiler.Compile("-o", tempObjFile.Name(), "-x", lang, "-c", file)
if err != nil {
return
}
objFiles = append(objFiles, tempObjFile.Name())
}
args := []string{"rcs", libcArchive}
args = append(args, objFiles...)
ccDir := filepath.Dir(cc)
llvmAr := filepath.Join(ccDir, "llvm-ar")
cmd := exec.Command(llvmAr, args...)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
cmd.Run()
return
}
// CompileLibcConfig represents libc compilation configuration
type compileLibcConfig struct {
Url string
Name string // Libc name (e.g., "picolibc", "musl", "glibc")
Groups []compileGroup
ArchiveSrcDir string
}
func (c compileLibcConfig) IsCompiled(outputDir string) bool {
for _, group := range c.Groups {
if !group.IsCompiled(outputDir) {
return false
}
}
return true
}
// GetCompileLibcConfigByName retrieves libc compilation configuration by name
// GetCompileConfigByName retrieves libc compilation configuration by name
// Returns compilation file lists and corresponding cflags
func getCompileLibcConfigByName(baseDir, libcName string) (*compileLibcConfig, error) {
func getLibcCompileConfigByName(baseDir, libcName string) (*compile.CompileConfig, error) {
if libcName == "" {
return nil, fmt.Errorf("libc name cannot be empty")
}
@@ -108,10 +19,24 @@ func getCompileLibcConfigByName(baseDir, libcName string) (*compileLibcConfig, e
switch libcName {
case "picolibc":
return getPicolibcConfig(libcDir), nil
return libc.GetPicolibcConfig(libcDir), nil
case "newlib-esp32":
return getNewlibESP32Config(libcDir, "xtensa"), nil
return libc.GetNewlibESP32Config(libcDir, "xtensa"), nil
default:
return nil, fmt.Errorf("unsupported libc: %s", libcName)
}
}
func getRTCompileConfigByName(baseDir, rtName string) (*compile.CompileConfig, error) {
if rtName == "" {
return nil, fmt.Errorf("rt name cannot be empty")
}
rtDir := filepath.Join(baseDir, rtName)
switch rtName {
case "compiler-rt":
return rtlib.GetCompilerRTConfig(rtDir, "xtensa"), nil
default:
return nil, fmt.Errorf("unsupported rt: %s", rtName)
}
}

View File

@@ -17,6 +17,7 @@ type Config struct {
// Compiler and linker configuration
Libc string `json:"libc"`
RTLib string `json:"rtlib"`
Linker string `json:"linker"`
LinkerScript string `json:"linkerscript"`
CFlags []string `json:"cflags"`

View File

@@ -137,6 +137,9 @@ func (l *Loader) mergeConfig(dst, src *Config) {
if src.Libc != "" {
dst.Libc = src.Libc
}
if src.RTLib != "" {
dst.RTLib = src.RTLib
}
if src.Linker != "" {
dst.Linker = src.Linker
}

View File

@@ -0,0 +1,130 @@
/* These are the newlib functions present in ESP32 ROM.
They should not be used when compiling with PSRAM cache workaround enabled.
See also esp32.rom.newlib-data.ld for the list of .data/.bss symbols
used by these functions, and esp32.rom.newlib-nano.ld for "nano" versions
of printf/scanf family of functions.
Unlike other ROM functions which are exported using PROVIDE, which declares
weak symbols, newlib related functions are exported using assignment,
which declares strong symbols. This is done so that ROM functions are always
used instead of the ones provided by libc.a.
Time functions were moved to the esp32.rom.newlib-time.ld file.
*/
abs = 0x40056340;
__ascii_wctomb = 0x40058ef0;
atoi = 0x400566c4;
_atoi_r = 0x400566d4;
atol = 0x400566ec;
_atol_r = 0x400566fc;
bzero = 0x4000c1f4;
_cleanup = 0x40001df8;
_cleanup_r = 0x40001d48;
creat = 0x40000e8c;
div = 0x40056348;
__dummy_lock = 0x4000c728;
__dummy_lock_try = 0x4000c730;
__env_lock = 0x40001fd4;
__env_unlock = 0x40001fe0;
fclose = 0x400020ac;
_fclose_r = 0x40001fec;
fflush = 0x40059394;
_fflush_r = 0x40059320;
_findenv_r = 0x40001f44;
__fp_lock_all = 0x40001f1c;
__fp_unlock_all = 0x40001f30;
__fputwc = 0x40058da0;
fputwc = 0x40058ea8;
_fputwc_r = 0x40058e4c;
_fwalk = 0x4000c738;
_fwalk_reent = 0x4000c770;
_getenv_r = 0x40001fbc;
isalnum = 0x40000f04;
isalpha = 0x40000f18;
isascii = 0x4000c20c;
isblank = 0x40000f2c;
iscntrl = 0x40000f50;
isdigit = 0x40000f64;
isgraph = 0x40000f94;
islower = 0x40000f78;
isprint = 0x40000fa8;
ispunct = 0x40000fc0;
isspace = 0x40000fd4;
isupper = 0x40000fe8;
__itoa = 0x40056678;
itoa = 0x400566b4;
labs = 0x40056370;
ldiv = 0x40056378;
longjmp = 0x400562cc;
memccpy = 0x4000c220;
memchr = 0x4000c244;
memcmp = 0x4000c260;
memcpy = 0x4000c2c8;
memmove = 0x4000c3c0;
memrchr = 0x4000c400;
memset = 0x4000c44c;
qsort = 0x40056424;
rand = 0x40001058;
rand_r = 0x400010d4;
__sccl = 0x4000c498;
__sclose = 0x400011b8;
__seofread = 0x40001148;
setjmp = 0x40056268;
__sflush_r = 0x400591e0;
__sfmoreglue = 0x40001dc8;
__sfp = 0x40001e90;
__sfp_lock_acquire = 0x40001e08;
__sfp_lock_release = 0x40001e14;
__sinit = 0x40001e38;
__sinit_lock_acquire = 0x40001e20;
__sinit_lock_release = 0x40001e2c;
srand = 0x40001004;
__sread = 0x40001118;
__sseek = 0x40001184;
strcasecmp = 0x400011cc;
strcasestr = 0x40001210;
strcat = 0x4000c518;
strchr = 0x4000c53c;
strcmp = 0x40001274;
strcoll = 0x40001398;
strcpy = 0x400013ac;
strcspn = 0x4000c558;
strdup = 0x4000143c;
_strdup_r = 0x40001450;
strlcat = 0x40001470;
strlcpy = 0x4000c584;
strlen = 0x400014c0;
strlwr = 0x40001524;
strncasecmp = 0x40001550;
strncat = 0x4000c5c4;
strncmp = 0x4000c5f4;
strncpy = 0x400015d4;
strndup = 0x400016b0;
_strndup_r = 0x400016c4;
strnlen = 0x4000c628;
strrchr = 0x40001708;
strsep = 0x40001734;
strspn = 0x4000c648;
strstr = 0x4000c674;
__strtok_r = 0x4000c6a8;
strtok_r = 0x4000c70c;
strtol = 0x4005681c;
_strtol_r = 0x40056714;
strtoul = 0x4005692c;
_strtoul_r = 0x40056834;
strupr = 0x4000174c;
__submore = 0x40058f3c;
__swbuf = 0x40058cb4;
__swbuf_r = 0x40058bec;
__swrite = 0x40001150;
toascii = 0x4000c720;
tolower = 0x40001868;
toupper = 0x40001884;
ungetc = 0x400590f4;
_ungetc_r = 0x40058fa0;
__utoa = 0x400561f0;
utoa = 0x40056258;
wcrtomb = 0x40058920;
_wcrtomb_r = 0x400588d8;
_wctomb_r = 0x40058f14;