extract common cmd flags

This commit is contained in:
Li Jie
2025-04-18 12:54:04 +08:00
parent a257b7bdfa
commit 489a0069aa
9 changed files with 113 additions and 135 deletions

View File

@@ -22,6 +22,7 @@ import (
"os" "os"
"github.com/goplus/llgo/cmd/internal/base" "github.com/goplus/llgo/cmd/internal/base"
"github.com/goplus/llgo/cmd/internal/flags"
"github.com/goplus/llgo/internal/build" "github.com/goplus/llgo/internal/build"
"github.com/goplus/llgo/internal/mockable" "github.com/goplus/llgo/internal/mockable"
) )
@@ -34,14 +35,22 @@ var Cmd = &base.Command{
func init() { func init() {
Cmd.Run = runCmd Cmd.Run = runCmd
flags.AddBuildFlags(&Cmd.Flag)
flags.AddOutputFlags(&Cmd.Flag)
} }
func runCmd(cmd *base.Command, args []string) { func runCmd(cmd *base.Command, args []string) {
conf := build.NewDefaultConf(build.ModeBuild) if err := cmd.Flag.Parse(args); err != nil {
if len(args) >= 2 && args[0] == "-o" { panic(err)
conf.OutFile = args[1]
args = args[2:]
} }
conf := build.NewDefaultConf(build.ModeBuild)
conf.Tags = flags.Tags
conf.Verbose = flags.Verbose
conf.OutFile = flags.OutputFile
args = cmd.Flag.Args()
_, err := build.Do(args, conf) _, err := build.Do(args, conf)
if err != nil { if err != nil {
fmt.Fprintln(os.Stderr, err) fmt.Fprintln(os.Stderr, err)

View File

@@ -19,6 +19,7 @@ package clean
import ( import (
"github.com/goplus/llgo/cmd/internal/base" "github.com/goplus/llgo/cmd/internal/base"
"github.com/goplus/llgo/cmd/internal/flags"
"github.com/goplus/llgo/internal/build" "github.com/goplus/llgo/internal/build"
) )
@@ -30,9 +31,18 @@ var Cmd = &base.Command{
func init() { func init() {
Cmd.Run = runCmd Cmd.Run = runCmd
flags.AddBuildFlags(&Cmd.Flag)
} }
func runCmd(cmd *base.Command, args []string) { func runCmd(cmd *base.Command, args []string) {
if err := cmd.Flag.Parse(args); err != nil {
panic(err)
}
conf := build.NewDefaultConf(0) conf := build.NewDefaultConf(0)
conf.Tags = flags.Tags
conf.Verbose = flags.Verbose
args = cmd.Flag.Args()
build.Clean(args, conf) build.Clean(args, conf)
} }

View File

@@ -0,0 +1,27 @@
package flags
import (
"flag"
)
var OutputFile string
func AddOutputFlags(fs *flag.FlagSet) {
fs.StringVar(&OutputFile, "o", "", "Output file")
}
var Verbose bool
var BuildEnv string
var Tags string
func AddBuildFlags(fs *flag.FlagSet) {
fs.BoolVar(&Verbose, "v", false, "Verbose mode")
fs.StringVar(&Tags, "tags", "", "Build tags")
fs.StringVar(&BuildEnv, "buildenv", "", "Build environment")
}
var Gen bool
func AddCmpTestFlags(fs *flag.FlagSet) {
fs.BoolVar(&Gen, "gen", false, "Generate llgo.expect file")
}

View File

@@ -22,6 +22,7 @@ import (
"os" "os"
"github.com/goplus/llgo/cmd/internal/base" "github.com/goplus/llgo/cmd/internal/base"
"github.com/goplus/llgo/cmd/internal/flags"
"github.com/goplus/llgo/internal/build" "github.com/goplus/llgo/internal/build"
"github.com/goplus/llgo/internal/mockable" "github.com/goplus/llgo/internal/mockable"
) )
@@ -34,10 +35,19 @@ var Cmd = &base.Command{
func init() { func init() {
Cmd.Run = runCmd Cmd.Run = runCmd
flags.AddBuildFlags(&Cmd.Flag)
} }
func runCmd(cmd *base.Command, args []string) { func runCmd(cmd *base.Command, args []string) {
if err := cmd.Flag.Parse(args); err != nil {
panic(err)
}
conf := build.NewDefaultConf(build.ModeInstall) conf := build.NewDefaultConf(build.ModeInstall)
conf.Tags = flags.Tags
conf.Verbose = flags.Verbose
args = cmd.Flag.Args()
_, err := build.Do(args, conf) _, err := build.Do(args, conf)
if err != nil { if err != nil {
fmt.Fprintln(os.Stderr, err) fmt.Fprintln(os.Stderr, err)

View File

@@ -21,9 +21,9 @@ import (
"errors" "errors"
"fmt" "fmt"
"os" "os"
"path/filepath"
"github.com/goplus/llgo/cmd/internal/base" "github.com/goplus/llgo/cmd/internal/base"
"github.com/goplus/llgo/cmd/internal/flags"
"github.com/goplus/llgo/internal/build" "github.com/goplus/llgo/internal/build"
"github.com/goplus/llgo/internal/mockable" "github.com/goplus/llgo/internal/mockable"
) )
@@ -47,6 +47,9 @@ var CmpTestCmd = &base.Command{
func init() { func init() {
Cmd.Run = runCmd Cmd.Run = runCmd
CmpTestCmd.Run = runCmpTest CmpTestCmd.Run = runCmpTest
flags.AddBuildFlags(&Cmd.Flag)
flags.AddBuildFlags(&CmpTestCmd.Flag)
flags.AddCmpTestFlags(&CmpTestCmd.Flag)
} }
func runCmd(cmd *base.Command, args []string) { func runCmd(cmd *base.Command, args []string) {
@@ -57,12 +60,17 @@ func runCmpTest(cmd *base.Command, args []string) {
runCmdEx(cmd, args, build.ModeCmpTest) runCmdEx(cmd, args, build.ModeCmpTest)
} }
func runCmdEx(_ *base.Command, args []string, mode build.Mode) { func runCmdEx(cmd *base.Command, args []string, mode build.Mode) {
conf := build.NewDefaultConf(mode) if err := cmd.Flag.Parse(args); err != nil {
if mode == build.ModeCmpTest && len(args) > 0 && args[0] == "-gen" { panic(err)
conf.GenExpect = true
args = args[1:]
} }
conf := build.NewDefaultConf(mode)
conf.Tags = flags.Tags
conf.Verbose = flags.Verbose
conf.GenExpect = flags.Gen
args = cmd.Flag.Args()
args, runArgs, err := parseRunArgs(args) args, runArgs, err := parseRunArgs(args)
check(err) check(err)
conf.RunArgs = runArgs conf.RunArgs = runArgs
@@ -74,24 +82,11 @@ func runCmdEx(_ *base.Command, args []string, mode build.Mode) {
} }
func parseRunArgs(args []string) ([]string, []string, error) { func parseRunArgs(args []string) ([]string, []string, error) {
n := build.SkipFlagArgs(args) if len(args) == 0 {
if n < 0 {
return nil, nil, errNoProj return nil, nil, errNoProj
} }
arg := args[n] return args[:1], args[1:], nil
if isGoFile(arg) {
n++
for n < len(args) && isGoFile(args[n]) {
n++
}
return args[:n], args[n:], nil
}
return args[:n+1], args[n+1:], nil
}
func isGoFile(fname string) bool {
return filepath.Ext(fname) == ".go"
} }
func check(err error) { func check(err error) {

View File

@@ -5,6 +5,7 @@ import (
"os" "os"
"github.com/goplus/llgo/cmd/internal/base" "github.com/goplus/llgo/cmd/internal/base"
"github.com/goplus/llgo/cmd/internal/flags"
"github.com/goplus/llgo/internal/build" "github.com/goplus/llgo/internal/build"
) )
@@ -16,15 +17,19 @@ var Cmd = &base.Command{
func init() { func init() {
Cmd.Run = runCmd Cmd.Run = runCmd
flags.AddBuildFlags(&Cmd.Flag)
} }
func runCmd(cmd *base.Command, args []string) { func runCmd(cmd *base.Command, args []string) {
runCmdEx(cmd, args, build.ModeRun) if err := cmd.Flag.Parse(args); err != nil {
} panic(err)
}
func runCmdEx(_ *base.Command, args []string, mode build.Mode) { conf := build.NewDefaultConf(build.ModeTest)
conf := build.NewDefaultConf(mode) conf.Tags = flags.Tags
conf.Mode = build.ModeTest conf.Verbose = flags.Verbose
args = cmd.Flag.Args()
_, err := build.Do(args, conf) _, err := build.Do(args, conf)
if err != nil { if err != nil {
fmt.Fprintln(os.Stderr, err) fmt.Fprintln(os.Stderr, err)

View File

@@ -75,6 +75,8 @@ type Config struct {
RunArgs []string // only valid for ModeRun RunArgs []string // only valid for ModeRun
Mode Mode Mode Mode
GenExpect bool // only valid for ModeCmpTest GenExpect bool // only valid for ModeCmpTest
Verbose bool
Tags string
} }
func NewDefaultConf(mode Mode) *Config { func NewDefaultConf(mode Mode) *Config {
@@ -136,56 +138,6 @@ const (
loadSyntax = loadTypes | packages.NeedSyntax | packages.NeedTypesInfo loadSyntax = loadTypes | packages.NeedSyntax | packages.NeedTypesInfo
) )
func mergeFlags(flags, extraFlags []string) (newFlags []string, tags []string) {
// Combine all flags
allFlags := append([]string{}, flags...)
allFlags = append(allFlags, extraFlags...)
// Find all -tags flags and extract their values
tagValues := []string{}
for i := 0; i < len(allFlags); i++ {
flag := allFlags[i]
// Handle -tags=value format
if strings.HasPrefix(flag, "-tags=") {
value := strings.TrimPrefix(flag, "-tags=")
if value != "" {
tagValues = append(tagValues, strings.Split(value, ",")...)
}
continue
}
// Handle -tags value format
if flag == "-tags" && i+1 < len(allFlags) {
i++
value := allFlags[i]
if value != "" {
tagValues = append(tagValues, strings.Split(value, ",")...)
}
continue
}
// Keep other flags
newFlags = append(newFlags, flag)
}
// Add combined -tags flag if we found any tag values
if len(tagValues) > 0 {
// Remove duplicates
uniqueTags := make([]string, 0, len(tagValues))
seen := make(map[string]bool)
for _, tag := range tagValues {
tag = strings.TrimSpace(tag)
if tag != "" && !seen[tag] {
seen[tag] = true
uniqueTags = append(uniqueTags, tag)
}
}
if len(uniqueTags) > 0 {
newFlags = append(newFlags, "-tags", strings.Join(uniqueTags, ","))
tags = []string{"-tags", strings.Join(uniqueTags, ",")}
}
}
return newFlags, tags
}
func Do(args []string, conf *Config) ([]Package, error) { func Do(args []string, conf *Config) ([]Package, error) {
if conf.Goos == "" { if conf.Goos == "" {
conf.Goos = runtime.GOOS conf.Goos = runtime.GOOS
@@ -193,11 +145,15 @@ func Do(args []string, conf *Config) ([]Package, error) {
if conf.Goarch == "" { if conf.Goarch == "" {
conf.Goarch = runtime.GOARCH conf.Goarch = runtime.GOARCH
} }
flags, patterns, verbose := ParseArgs(args, buildFlags) verbose := conf.Verbose
flags, _ = mergeFlags(flags, []string{"-tags", "llgo"}) patterns := args
tags := "llgo"
if conf.Tags != "" {
tags += "," + conf.Tags
}
cfg := &packages.Config{ cfg := &packages.Config{
Mode: loadSyntax | packages.NeedDeps | packages.NeedModule | packages.NeedExportFile, Mode: loadSyntax | packages.NeedDeps | packages.NeedModule | packages.NeedExportFile,
BuildFlags: flags, BuildFlags: []string{"-tags=" + tags},
Fset: token.NewFileSet(), Fset: token.NewFileSet(),
Tests: conf.Mode == ModeTest, Tests: conf.Mode == ModeTest,
} }
@@ -1048,50 +1004,6 @@ func WasmRuntime() string {
return defaultEnv(llgoWasmRuntime, defaultWasmRuntime) return defaultEnv(llgoWasmRuntime, defaultWasmRuntime)
} }
func ParseArgs(args []string, swflags map[string]bool) (flags, patterns []string, verbose bool) {
n := len(args)
for i := 0; i < n; i++ {
arg := args[i]
if strings.HasPrefix(arg, "-") {
checkFlag(arg, &i, &verbose, swflags)
} else {
patterns = append([]string{}, args[i:]...)
flags = append([]string{}, args[:i]...)
return
}
}
return
}
func SkipFlagArgs(args []string) int {
n := len(args)
for i := 0; i < n; i++ {
arg := args[i]
if strings.HasPrefix(arg, "-") {
checkFlag(arg, &i, nil, buildFlags)
} else {
return i
}
}
return -1
}
func checkFlag(arg string, i *int, verbose *bool, swflags map[string]bool) {
if pos := strings.IndexByte(arg, '='); pos > 0 {
if verbose != nil && arg == "-v=true" {
*verbose = true
}
} else if hasarg, ok := swflags[arg]; ok {
if hasarg {
*i++
} else if verbose != nil && arg == "-v" {
*verbose = true
}
} else {
panic("unknown flag: " + arg)
}
}
func concatPkgLinkFiles(ctx *context, pkg *packages.Package, verbose bool) (parts []string) { func concatPkgLinkFiles(ctx *context, pkg *packages.Package, verbose bool) (parts []string) {
llgoPkgLinkFiles(ctx, pkg, func(linkFile string) { llgoPkgLinkFiles(ctx, pkg, func(linkFile string) {
parts = append(parts, linkFile) parts = append(parts, linkFile)

View File

@@ -54,13 +54,13 @@ func mockRun(args []string, cfg *Config) {
} }
func TestRun(t *testing.T) { func TestRun(t *testing.T) {
mockRun([]string{"-v", "../../cl/_testgo/print"}, &Config{Mode: ModeRun}) mockRun([]string{"../../cl/_testgo/print"}, &Config{Mode: ModeRun})
} }
func TestTest(t *testing.T) { func TestTest(t *testing.T) {
mockRun([]string{"-v", "../../cl/_testgo/runtest"}, &Config{Mode: ModeTest}) mockRun([]string{"../../cl/_testgo/runtest"}, &Config{Mode: ModeTest})
} }
func TestCmpTest(t *testing.T) { func TestCmpTest(t *testing.T) {
mockRun([]string{"-v", "../../cl/_testgo/runtest"}, &Config{Mode: ModeCmpTest}) mockRun([]string{"../../cl/_testgo/runtest"}, &Config{Mode: ModeCmpTest})
} }

View File

@@ -21,6 +21,7 @@ import (
"os" "os"
"path" "path"
"path/filepath" "path/filepath"
"runtime"
"github.com/goplus/llgo/internal/packages" "github.com/goplus/llgo/internal/packages"
) )
@@ -32,11 +33,20 @@ var (
} }
) )
func Clean(args []string, conf *Config) { func Clean(patterns []string, conf *Config) {
flags, patterns, verbose := ParseArgs(args, cleanFlags) if conf.Goos == "" {
conf.Goos = runtime.GOOS
}
if conf.Goarch == "" {
conf.Goarch = runtime.GOARCH
}
tags := "llgo"
if conf.Tags != "" {
tags += "," + conf.Tags
}
cfg := &packages.Config{ cfg := &packages.Config{
Mode: loadSyntax | packages.NeedExportFile, Mode: loadSyntax | packages.NeedExportFile,
BuildFlags: flags, BuildFlags: []string{"-tags=" + tags},
} }
if patterns == nil { if patterns == nil {
@@ -45,11 +55,11 @@ func Clean(args []string, conf *Config) {
initial, err := packages.LoadEx(nil, nil, cfg, patterns...) initial, err := packages.LoadEx(nil, nil, cfg, patterns...)
check(err) check(err)
cleanPkgs(initial, verbose) cleanPkgs(initial, conf.Verbose)
for _, pkg := range initial { for _, pkg := range initial {
if pkg.Name == "main" { if pkg.Name == "main" {
cleanMainPkg(pkg, conf, verbose) cleanMainPkg(pkg, conf, conf.Verbose)
} }
} }
} }