From daf0d7e56e990b83b6be77113c44d47137373e80 Mon Sep 17 00:00:00 2001 From: Li Jie Date: Tue, 29 Jul 2025 15:12:25 +0800 Subject: [PATCH] feat(cmd): enable -target parameter for build, run, and test commands MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 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 --- cmd/internal/build/build.go | 3 ++- cmd/internal/run/run.go | 7 ++--- cmd/internal/test/test.go | 3 ++- internal/build/build.go | 53 ++++++++++++++++++++++++++----------- 4 files changed, 45 insertions(+), 21 deletions(-) diff --git a/cmd/internal/build/build.go b/cmd/internal/build/build.go index d88f1666..39ab5db8 100644 --- a/cmd/internal/build/build.go +++ b/cmd/internal/build/build.go @@ -29,7 +29,7 @@ import ( // llgo build var Cmd = &base.Command{ - UsageLine: "llgo build [-o output] [build flags] [packages]", + UsageLine: "llgo build [-o output] [-target platform] [build flags] [packages]", Short: "Compile packages and dependencies", } @@ -50,6 +50,7 @@ func runCmd(cmd *base.Command, args []string) { conf.Tags = flags.Tags conf.Verbose = flags.Verbose conf.OutFile = flags.OutputFile + conf.Target = flags.Target args = cmd.Flag.Args() diff --git a/cmd/internal/run/run.go b/cmd/internal/run/run.go index 3df0c199..93b7bb41 100644 --- a/cmd/internal/run/run.go +++ b/cmd/internal/run/run.go @@ -34,7 +34,7 @@ var ( // llgo run var Cmd = &base.Command{ - UsageLine: "llgo run [build flags] package [arguments...]", + UsageLine: "llgo run [-target platform] [build flags] package [arguments...]", Short: "Compile and run Go program", } @@ -54,11 +54,11 @@ func init() { } func runCmd(cmd *base.Command, args []string) { - runCmdEx(cmd, args, build.ModeRun) + runCmdEx(cmd, args, build.ModeRun) // support target } func runCmpTest(cmd *base.Command, args []string) { - runCmdEx(cmd, args, build.ModeCmpTest) + runCmdEx(cmd, args, build.ModeCmpTest) // no target support } func runCmdEx(cmd *base.Command, args []string, mode build.Mode) { @@ -71,6 +71,7 @@ func runCmdEx(cmd *base.Command, args []string, mode build.Mode) { conf.Tags = flags.Tags conf.Verbose = flags.Verbose conf.GenExpect = flags.Gen + conf.Target = flags.Target args = cmd.Flag.Args() args, runArgs, err := parseRunArgs(args) diff --git a/cmd/internal/test/test.go b/cmd/internal/test/test.go index 64e49927..34516381 100644 --- a/cmd/internal/test/test.go +++ b/cmd/internal/test/test.go @@ -11,7 +11,7 @@ import ( // llgo test var Cmd = &base.Command{ - UsageLine: "llgo test [build flags] package [arguments...]", + UsageLine: "llgo test [-target platform] [build flags] package [arguments...]", Short: "Compile and run Go test", } @@ -29,6 +29,7 @@ func runCmd(cmd *base.Command, args []string) { conf := build.NewDefaultConf(build.ModeTest) conf.Tags = flags.Tags conf.Verbose = flags.Verbose + conf.Target = flags.Target args = cmd.Flag.Args() _, err := build.Do(args, conf) diff --git a/internal/build/build.go b/internal/build/build.go index 46a2da6d..abfc4a3d 100644 --- a/internal/build/build.go +++ b/internal/build/build.go @@ -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) }