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:
@@ -29,7 +29,7 @@ import (
|
|||||||
|
|
||||||
// llgo build
|
// llgo build
|
||||||
var Cmd = &base.Command{
|
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",
|
Short: "Compile packages and dependencies",
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -50,6 +50,7 @@ func runCmd(cmd *base.Command, args []string) {
|
|||||||
conf.Tags = flags.Tags
|
conf.Tags = flags.Tags
|
||||||
conf.Verbose = flags.Verbose
|
conf.Verbose = flags.Verbose
|
||||||
conf.OutFile = flags.OutputFile
|
conf.OutFile = flags.OutputFile
|
||||||
|
conf.Target = flags.Target
|
||||||
|
|
||||||
args = cmd.Flag.Args()
|
args = cmd.Flag.Args()
|
||||||
|
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ var (
|
|||||||
|
|
||||||
// llgo run
|
// llgo run
|
||||||
var Cmd = &base.Command{
|
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",
|
Short: "Compile and run Go program",
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -54,11 +54,11 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func runCmd(cmd *base.Command, args []string) {
|
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) {
|
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) {
|
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.Tags = flags.Tags
|
||||||
conf.Verbose = flags.Verbose
|
conf.Verbose = flags.Verbose
|
||||||
conf.GenExpect = flags.Gen
|
conf.GenExpect = flags.Gen
|
||||||
|
conf.Target = flags.Target
|
||||||
|
|
||||||
args = cmd.Flag.Args()
|
args = cmd.Flag.Args()
|
||||||
args, runArgs, err := parseRunArgs(args)
|
args, runArgs, err := parseRunArgs(args)
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import (
|
|||||||
|
|
||||||
// llgo test
|
// llgo test
|
||||||
var Cmd = &base.Command{
|
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",
|
Short: "Compile and run Go test",
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -29,6 +29,7 @@ func runCmd(cmd *base.Command, args []string) {
|
|||||||
conf := build.NewDefaultConf(build.ModeTest)
|
conf := build.NewDefaultConf(build.ModeTest)
|
||||||
conf.Tags = flags.Tags
|
conf.Tags = flags.Tags
|
||||||
conf.Verbose = flags.Verbose
|
conf.Verbose = flags.Verbose
|
||||||
|
conf.Target = flags.Target
|
||||||
|
|
||||||
args = cmd.Flag.Args()
|
args = cmd.Flag.Args()
|
||||||
_, err := build.Do(args, conf)
|
_, err := build.Do(args, conf)
|
||||||
|
|||||||
@@ -150,6 +150,20 @@ func Do(args []string, conf *Config) ([]Package, error) {
|
|||||||
if conf.Goarch == "" {
|
if conf.Goarch == "" {
|
||||||
conf.Goarch = runtime.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
|
verbose := conf.Verbose
|
||||||
patterns := args
|
patterns := args
|
||||||
tags := "llgo"
|
tags := "llgo"
|
||||||
@@ -161,6 +175,7 @@ func Do(args []string, conf *Config) ([]Package, error) {
|
|||||||
BuildFlags: []string{"-tags=" + tags},
|
BuildFlags: []string{"-tags=" + tags},
|
||||||
Fset: token.NewFileSet(),
|
Fset: token.NewFileSet(),
|
||||||
Tests: conf.Mode == ModeTest,
|
Tests: conf.Mode == ModeTest,
|
||||||
|
Env: append(slices.Clone(os.Environ()), "GOOS="+conf.Goos, "GOARCH="+conf.Goarch),
|
||||||
}
|
}
|
||||||
if conf.Mode == ModeTest {
|
if conf.Mode == ModeTest {
|
||||||
cfg.Mode |= packages.NeedForTest
|
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
|
os.Setenv("PATH", env.BinDir()+":"+os.Getenv("PATH")) // TODO(xsw): check windows
|
||||||
|
|
||||||
output := conf.OutFile != ""
|
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,
|
ctx := &context{env: env, conf: cfg, progSSA: progSSA, prog: prog, dedup: dedup,
|
||||||
patches: patches, built: make(map[string]none), initial: initial, mode: mode,
|
patches: patches, built: make(map[string]none), initial: initial, mode: mode,
|
||||||
output: output,
|
output: output,
|
||||||
@@ -371,6 +384,15 @@ func (c *context) compiler() *clang.Cmd {
|
|||||||
return 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) {
|
func buildAllPkgs(ctx *context, initial []*packages.Package, verbose bool) (pkgs []*aPackage, err error) {
|
||||||
pkgs, errPkgs := allPkgs(ctx, initial, verbose)
|
pkgs, errPkgs := allPkgs(ctx, initial, verbose)
|
||||||
for _, errPkg := range errPkgs {
|
for _, errPkg := range errPkgs {
|
||||||
@@ -541,14 +563,14 @@ func linkMainPkg(ctx *context, pkg *packages.Package, pkgs []*aPackage, global l
|
|||||||
pkgsMap[v.Package] = v
|
pkgsMap[v.Package] = v
|
||||||
allPkgs = append(allPkgs, v.Package)
|
allPkgs = append(allPkgs, v.Package)
|
||||||
}
|
}
|
||||||
var llFiles []string
|
var objFiles []string
|
||||||
var linkArgs []string
|
var linkArgs []string
|
||||||
packages.Visit(allPkgs, nil, func(p *packages.Package) {
|
packages.Visit(allPkgs, nil, func(p *packages.Package) {
|
||||||
aPkg := pkgsMap[p]
|
aPkg := pkgsMap[p]
|
||||||
if p.ExportFile != "" && aPkg != nil { // skip packages that only contain declarations
|
if p.ExportFile != "" && aPkg != nil { // skip packages that only contain declarations
|
||||||
linkArgs = append(linkArgs, aPkg.LinkArgs...)
|
linkArgs = append(linkArgs, aPkg.LinkArgs...)
|
||||||
llFiles = append(llFiles, aPkg.LLFiles...)
|
objFiles = append(objFiles, aPkg.LLFiles...)
|
||||||
llFiles = append(llFiles, aPkg.ExportFile)
|
objFiles = append(objFiles, aPkg.ExportFile)
|
||||||
need1, need2 := isNeedRuntimeOrPyInit(ctx, p)
|
need1, need2 := isNeedRuntimeOrPyInit(ctx, p)
|
||||||
if !needRuntime {
|
if !needRuntime {
|
||||||
needRuntime = need1
|
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)
|
check(err)
|
||||||
// defer os.Remove(entryLLFile)
|
// defer os.Remove(entryLLFile)
|
||||||
llFiles = append(llFiles, entryLLFile)
|
objFiles = append(objFiles, entryObjFile)
|
||||||
|
|
||||||
if global != nil {
|
if global != nil {
|
||||||
export, err := exportObject(ctx, pkg.PkgPath+".global", pkg.ExportFile+"-global", []byte(global.String()))
|
export, err := exportObject(ctx, pkg.PkgPath+".global", pkg.ExportFile+"-global", []byte(global.String()))
|
||||||
check(err)
|
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)
|
check(err)
|
||||||
|
|
||||||
switch mode {
|
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 := []string{"-o", app}
|
||||||
buildArgs = append(buildArgs, linkArgs...)
|
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.CCFLAGS...)
|
||||||
buildArgs = append(buildArgs, ctx.crossCompile.LDFLAGS...)
|
buildArgs = append(buildArgs, ctx.crossCompile.LDFLAGS...)
|
||||||
buildArgs = append(buildArgs, ctx.crossCompile.EXTRAFLAGS...)
|
buildArgs = append(buildArgs, ctx.crossCompile.EXTRAFLAGS...)
|
||||||
buildArgs = append(buildArgs, llFiles...)
|
buildArgs = append(buildArgs, objFiles...)
|
||||||
if verbose {
|
|
||||||
buildArgs = append(buildArgs, "-v")
|
|
||||||
}
|
|
||||||
|
|
||||||
cmd := ctx.compiler()
|
cmd := ctx.linker()
|
||||||
cmd.Verbose = verbose
|
cmd.Verbose = verbose
|
||||||
return cmd.Link(buildArgs...)
|
return cmd.Link(buildArgs...)
|
||||||
}
|
}
|
||||||
@@ -820,6 +840,7 @@ func exportObject(ctx *context, pkgPath string, exportFile string, data []byte)
|
|||||||
exportFile += ".o"
|
exportFile += ".o"
|
||||||
args := []string{"-o", exportFile, "-c", f.Name(), "-Wno-override-module"}
|
args := []string{"-o", exportFile, "-c", f.Name(), "-Wno-override-module"}
|
||||||
args = append(args, ctx.crossCompile.CCFLAGS...)
|
args = append(args, ctx.crossCompile.CCFLAGS...)
|
||||||
|
args = append(args, ctx.crossCompile.CFLAGS...)
|
||||||
if ctx.buildConf.Verbose {
|
if ctx.buildConf.Verbose {
|
||||||
fmt.Fprintln(os.Stderr, "clang", args)
|
fmt.Fprintln(os.Stderr, "clang", args)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user