Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions _embdemo/hello-esp32/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package main

import "github.com/goplus/lib/c"

func myprint(s *c.Char) {
for i := 0; i < int(c.Strlen(s)); i++ {
WriteByte(byte(c.Index(s, i)))
}
}

func main() {
for {
myprint(c.Str("hello world"))
sleep(1)
}
}
Comment on lines +1 to +16
Copy link
Member

@luoliwoshang luoliwoshang Sep 3, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#1257 the issue for how to run this demo

13 changes: 13 additions & 0 deletions _embdemo/hello-esp32/uart.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package main

import (
_ "unsafe"

"github.com/goplus/lib/c"
)

//go:linkname WriteByte C.board_uart_write_char
func WriteByte(b byte)

//go:linkname sleep sleep
func sleep(c c.Int)
31 changes: 31 additions & 0 deletions _embdemo/write-esp32/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package main

import (
_ "unsafe"

"github.com/goplus/lib/c"
)

//go:linkname write C.write
func write(c.Int, *c.Char, c.SizeT) int

func main() {
buf := c.Malloc(6)
c.Memset(buf, 0, 6)
c.Strncpy((*c.Char)(buf), c.Str("abcde"), 5)

if c.Strcmp((*c.Char)(buf), c.Str("abcde")) == 0 {
write(1, c.Str("pass strcmp"), 11)
}

if byte(c.Index((*c.Char)(buf), 0)) == 'a' {
write(1, c.Str("pass index"), 10)
}

c.Memset(buf, c.Int('A'), 5)
if c.Strcmp((*c.Char)(buf), c.Str("AAAAA")) == 0 {
write(1, c.Str("pass memeset"), 11)
}

write(1, (*c.Char)(buf), 5)
}
15 changes: 8 additions & 7 deletions internal/build/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -838,15 +838,16 @@ func isWasmTarget(goos string) bool {
return slices.Contains([]string{"wasi", "js", "wasip1"}, goos)
}

func needStart(conf *Config) bool {
if conf.Target == "" {
return !isWasmTarget(conf.Goos)
func needStart(ctx *context) bool {
if ctx.buildConf.Target == "" {
return !isWasmTarget(ctx.buildConf.Goos)
}
switch conf.Target {
switch ctx.buildConf.Target {
case "wasip2":
return false
default:
return true
// since newlib-esp32 provides _start, we don't need to provide a fake _start function
return ctx.crossCompile.Libc != "newlib-esp32"
}
}

Expand Down Expand Up @@ -903,10 +904,10 @@ define weak void @_start() {
}
`
mainDefine := "define i32 @main(i32 noundef %0, ptr nocapture noundef readnone %1) local_unnamed_addr"
if !needStart(ctx.buildConf) && isWasmTarget(ctx.buildConf.Goos) {
if !needStart(ctx) && 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 !needStart(ctx) {
startDefine = ""
}
mainCode := fmt.Sprintf(`; ModuleID = 'main'
Expand Down
103 changes: 103 additions & 0 deletions internal/crosscompile/compile/compile.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
package compile

import (
"fmt"
"os"
"os/exec"
"path/filepath"
"slices"
"strings"

"github.com/goplus/llgo/internal/clang"
)

type CompileOptions struct {
CC string // Compiler to use
Linker string
CCFLAGS []string
CFLAGS []string
LDFLAGS []string
}

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, filepath.Base(g.OutputFileName))
_, err := os.Stat(archive)
return err == nil
}

func (g CompileGroup) Compile(
outputDir string, options CompileOptions,
) (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(options.LDFLAGS), g.LDFlags...)
compileCCFlags := append(slices.Clone(options.CCFLAGS), g.CCFlags...)
compileCFFlags := append(slices.Clone(options.CFLAGS), g.CFlags...)

cfg := clang.NewConfig(options.CC, compileCCFlags, compileCFFlags, compileLDFlags, options.Linker)

var objFiles []string

compiler := clang.NewCompiler(cfg)

compiler.Verbose = true

archive := filepath.Join(outputDir, filepath.Base(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
}

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(options.CC)
llvmAr := filepath.Join(ccDir, "llvm-ar")

cmd := exec.Command(llvmAr, args...)
// TODO(MeteorsLiu): support verbose
// 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
LibcCFlags []string
}
Loading
Loading