feat: support compiler-rt
This commit is contained in:
@@ -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'
|
||||
|
||||
99
internal/crosscompile/compile/compile.go
Normal file
99
internal/crosscompile/compile/compile.go
Normal 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
|
||||
}
|
||||
@@ -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",
|
||||
@@ -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{
|
||||
195
internal/crosscompile/compile/rtlib/compiler_rt.go
Normal file
195
internal/crosscompile/compile/rtlib/compiler_rt.go
Normal 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",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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"`
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
130
targets/esp32.rom.newlib-funcs.ld
Normal file
130
targets/esp32.rom.newlib-funcs.ld
Normal 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;
|
||||
Reference in New Issue
Block a user