feat(cmd): enable -target parameter for build, run, and test commands

- Update build command: llgo build -target platform
- Update run command: llgo run -target platform
- Update test command: llgo test -target platform
- Wire target flag to build configuration
- Update usage documentation for new parameter

Examples:
- llgo build -target rp2040 ./firmware
- llgo run -target wasi ./main.go
- llgo test -target cortex-m ./tests

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Li Jie
2025-07-29 15:12:25 +08:00
parent 0136344282
commit daf0d7e56e
4 changed files with 45 additions and 21 deletions

View File

@@ -70,7 +70,7 @@ const (
type Config struct {
Goos string
Goarch string
Target string // target name (e.g., "rp2040", "wasi") - takes precedence over Goos/Goarch
Target string // target name (e.g., "rp2040", "wasi") - takes precedence over Goos/Goarch
BinPath string
AppExt string // ".exe" on Windows, empty on Unix
OutFile string // only valid for ModeBuild when len(pkgs) == 1
@@ -150,6 +150,20 @@ func Do(args []string, conf *Config) ([]Package, error) {
if conf.Goarch == "" {
conf.Goarch = runtime.GOARCH
}
// Handle crosscompile configuration first to set correct GOOS/GOARCH
export, err := crosscompile.UseWithTarget(conf.Goos, conf.Goarch, IsWasiThreadsEnabled(), conf.Target)
if err != nil {
return nil, fmt.Errorf("failed to setup crosscompile: %w", err)
}
// Update GOOS/GOARCH from export if target was used
if conf.Target != "" && export.GOOS != "" {
conf.Goos = export.GOOS
}
if conf.Target != "" && export.GOARCH != "" {
conf.Goarch = export.GOARCH
}
verbose := conf.Verbose
patterns := args
tags := "llgo"
@@ -161,6 +175,7 @@ func Do(args []string, conf *Config) ([]Package, error) {
BuildFlags: []string{"-tags=" + tags},
Fset: token.NewFileSet(),
Tests: conf.Mode == ModeTest,
Env: append(slices.Clone(os.Environ()), "GOOS="+conf.Goos, "GOARCH="+conf.Goarch),
}
if conf.Mode == ModeTest {
cfg.Mode |= packages.NeedForTest
@@ -252,8 +267,6 @@ func Do(args []string, conf *Config) ([]Package, error) {
os.Setenv("PATH", env.BinDir()+":"+os.Getenv("PATH")) // TODO(xsw): check windows
output := conf.OutFile != ""
export, err := crosscompile.UseWithTarget(conf.Goos, conf.Goarch, IsWasiThreadsEnabled(), conf.Target)
check(err)
ctx := &context{env: env, conf: cfg, progSSA: progSSA, prog: prog, dedup: dedup,
patches: patches, built: make(map[string]none), initial: initial, mode: mode,
output: output,
@@ -371,6 +384,15 @@ func (c *context) compiler() *clang.Cmd {
return cmd
}
func (c *context) linker() *clang.Cmd {
cmd := c.env.Clang()
if c.crossCompile.Linker != "" {
cmd = clang.New(c.crossCompile.Linker)
}
cmd.Verbose = c.buildConf.Verbose
return cmd
}
func buildAllPkgs(ctx *context, initial []*packages.Package, verbose bool) (pkgs []*aPackage, err error) {
pkgs, errPkgs := allPkgs(ctx, initial, verbose)
for _, errPkg := range errPkgs {
@@ -541,14 +563,14 @@ func linkMainPkg(ctx *context, pkg *packages.Package, pkgs []*aPackage, global l
pkgsMap[v.Package] = v
allPkgs = append(allPkgs, v.Package)
}
var llFiles []string
var objFiles []string
var linkArgs []string
packages.Visit(allPkgs, nil, func(p *packages.Package) {
aPkg := pkgsMap[p]
if p.ExportFile != "" && aPkg != nil { // skip packages that only contain declarations
linkArgs = append(linkArgs, aPkg.LinkArgs...)
llFiles = append(llFiles, aPkg.LLFiles...)
llFiles = append(llFiles, aPkg.ExportFile)
objFiles = append(objFiles, aPkg.LLFiles...)
objFiles = append(objFiles, aPkg.ExportFile)
need1, need2 := isNeedRuntimeOrPyInit(ctx, p)
if !needRuntime {
needRuntime = need1
@@ -558,18 +580,19 @@ func linkMainPkg(ctx *context, pkg *packages.Package, pkgs []*aPackage, global l
}
}
})
entryLLFile, err := genMainModuleFile(ctx, llssa.PkgRuntime, pkg, needRuntime, needPyInit)
entryObjFile, err := genMainModuleFile(ctx, llssa.PkgRuntime, pkg, needRuntime, needPyInit)
check(err)
// defer os.Remove(entryLLFile)
llFiles = append(llFiles, entryLLFile)
objFiles = append(objFiles, entryObjFile)
if global != nil {
export, err := exportObject(ctx, pkg.PkgPath+".global", pkg.ExportFile+"-global", []byte(global.String()))
check(err)
llFiles = append(llFiles, export)
objFiles = append(objFiles, export)
}
err = compileAndLinkLLFiles(ctx, app, llFiles, linkArgs, verbose)
err = linkObjFiles(ctx, app, objFiles, linkArgs, verbose)
err = linkObjFiles(ctx, app, objFiles, linkArgs, verbose)
check(err)
switch mode {
@@ -626,7 +649,7 @@ func linkMainPkg(ctx *context, pkg *packages.Package, pkgs []*aPackage, global l
}
}
func compileAndLinkLLFiles(ctx *context, app string, llFiles, linkArgs []string, verbose bool) error {
func linkObjFiles(ctx *context, app string, objFiles, linkArgs []string, verbose bool) error {
buildArgs := []string{"-o", app}
buildArgs = append(buildArgs, linkArgs...)
@@ -638,12 +661,9 @@ func compileAndLinkLLFiles(ctx *context, app string, llFiles, linkArgs []string,
buildArgs = append(buildArgs, ctx.crossCompile.CCFLAGS...)
buildArgs = append(buildArgs, ctx.crossCompile.LDFLAGS...)
buildArgs = append(buildArgs, ctx.crossCompile.EXTRAFLAGS...)
buildArgs = append(buildArgs, llFiles...)
if verbose {
buildArgs = append(buildArgs, "-v")
}
buildArgs = append(buildArgs, objFiles...)
cmd := ctx.compiler()
cmd := ctx.linker()
cmd.Verbose = verbose
return cmd.Link(buildArgs...)
}
@@ -820,6 +840,7 @@ func exportObject(ctx *context, pkgPath string, exportFile string, data []byte)
exportFile += ".o"
args := []string{"-o", exportFile, "-c", f.Name(), "-Wno-override-module"}
args = append(args, ctx.crossCompile.CCFLAGS...)
args = append(args, ctx.crossCompile.CFLAGS...)
if ctx.buildConf.Verbose {
fmt.Fprintln(os.Stderr, "clang", args)
}