From 489a0069aa9b0b789a757fd37b8070d9cda9021e Mon Sep 17 00:00:00 2001 From: Li Jie Date: Fri, 18 Apr 2025 12:54:04 +0800 Subject: [PATCH] extract common cmd flags --- cmd/internal/build/build.go | 17 +++-- cmd/internal/clean/clean.go | 10 +++ cmd/internal/flags/flags.go | 27 ++++++++ cmd/internal/install/install.go | 10 +++ cmd/internal/run/run.go | 37 +++++------ cmd/internal/test/test.go | 15 +++-- internal/build/build.go | 106 +++----------------------------- internal/build/build_test.go | 6 +- internal/build/clean.go | 20 ++++-- 9 files changed, 113 insertions(+), 135 deletions(-) create mode 100644 cmd/internal/flags/flags.go diff --git a/cmd/internal/build/build.go b/cmd/internal/build/build.go index 3bbde7c7..c5d3ef6e 100644 --- a/cmd/internal/build/build.go +++ b/cmd/internal/build/build.go @@ -22,6 +22,7 @@ import ( "os" "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/mockable" ) @@ -34,14 +35,22 @@ var Cmd = &base.Command{ func init() { Cmd.Run = runCmd + flags.AddBuildFlags(&Cmd.Flag) + flags.AddOutputFlags(&Cmd.Flag) } func runCmd(cmd *base.Command, args []string) { - conf := build.NewDefaultConf(build.ModeBuild) - if len(args) >= 2 && args[0] == "-o" { - conf.OutFile = args[1] - args = args[2:] + if err := cmd.Flag.Parse(args); err != nil { + panic(err) } + + 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) if err != nil { fmt.Fprintln(os.Stderr, err) diff --git a/cmd/internal/clean/clean.go b/cmd/internal/clean/clean.go index f0b12fe2..370da1de 100644 --- a/cmd/internal/clean/clean.go +++ b/cmd/internal/clean/clean.go @@ -19,6 +19,7 @@ package clean import ( "github.com/goplus/llgo/cmd/internal/base" + "github.com/goplus/llgo/cmd/internal/flags" "github.com/goplus/llgo/internal/build" ) @@ -30,9 +31,18 @@ var Cmd = &base.Command{ func init() { Cmd.Run = runCmd + flags.AddBuildFlags(&Cmd.Flag) } func runCmd(cmd *base.Command, args []string) { + if err := cmd.Flag.Parse(args); err != nil { + panic(err) + } + conf := build.NewDefaultConf(0) + conf.Tags = flags.Tags + conf.Verbose = flags.Verbose + + args = cmd.Flag.Args() build.Clean(args, conf) } diff --git a/cmd/internal/flags/flags.go b/cmd/internal/flags/flags.go new file mode 100644 index 00000000..56aa39d7 --- /dev/null +++ b/cmd/internal/flags/flags.go @@ -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") +} diff --git a/cmd/internal/install/install.go b/cmd/internal/install/install.go index 7626f416..4430eb42 100644 --- a/cmd/internal/install/install.go +++ b/cmd/internal/install/install.go @@ -22,6 +22,7 @@ import ( "os" "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/mockable" ) @@ -34,10 +35,19 @@ var Cmd = &base.Command{ func init() { Cmd.Run = runCmd + flags.AddBuildFlags(&Cmd.Flag) } func runCmd(cmd *base.Command, args []string) { + if err := cmd.Flag.Parse(args); err != nil { + panic(err) + } + conf := build.NewDefaultConf(build.ModeInstall) + conf.Tags = flags.Tags + conf.Verbose = flags.Verbose + + args = cmd.Flag.Args() _, err := build.Do(args, conf) if err != nil { fmt.Fprintln(os.Stderr, err) diff --git a/cmd/internal/run/run.go b/cmd/internal/run/run.go index af1859f1..470a4e75 100644 --- a/cmd/internal/run/run.go +++ b/cmd/internal/run/run.go @@ -21,9 +21,9 @@ import ( "errors" "fmt" "os" - "path/filepath" "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/mockable" ) @@ -47,6 +47,9 @@ var CmpTestCmd = &base.Command{ func init() { Cmd.Run = runCmd CmpTestCmd.Run = runCmpTest + flags.AddBuildFlags(&Cmd.Flag) + flags.AddBuildFlags(&CmpTestCmd.Flag) + flags.AddCmpTestFlags(&CmpTestCmd.Flag) } func runCmd(cmd *base.Command, args []string) { @@ -57,12 +60,17 @@ func runCmpTest(cmd *base.Command, args []string) { runCmdEx(cmd, args, build.ModeCmpTest) } -func runCmdEx(_ *base.Command, args []string, mode build.Mode) { - conf := build.NewDefaultConf(mode) - if mode == build.ModeCmpTest && len(args) > 0 && args[0] == "-gen" { - conf.GenExpect = true - args = args[1:] +func runCmdEx(cmd *base.Command, args []string, mode build.Mode) { + if err := cmd.Flag.Parse(args); err != nil { + panic(err) } + + 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) check(err) conf.RunArgs = runArgs @@ -74,24 +82,11 @@ func runCmdEx(_ *base.Command, args []string, mode build.Mode) { } func parseRunArgs(args []string) ([]string, []string, error) { - n := build.SkipFlagArgs(args) - if n < 0 { + if len(args) == 0 { return nil, nil, errNoProj } - arg := args[n] - 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" + return args[:1], args[1:], nil } func check(err error) { diff --git a/cmd/internal/test/test.go b/cmd/internal/test/test.go index bd04adba..e51c7418 100644 --- a/cmd/internal/test/test.go +++ b/cmd/internal/test/test.go @@ -5,6 +5,7 @@ import ( "os" "github.com/goplus/llgo/cmd/internal/base" + "github.com/goplus/llgo/cmd/internal/flags" "github.com/goplus/llgo/internal/build" ) @@ -16,15 +17,19 @@ var Cmd = &base.Command{ func init() { Cmd.Run = runCmd + flags.AddBuildFlags(&Cmd.Flag) } 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(mode) - conf.Mode = build.ModeTest + conf := build.NewDefaultConf(build.ModeTest) + conf.Tags = flags.Tags + conf.Verbose = flags.Verbose + + args = cmd.Flag.Args() _, err := build.Do(args, conf) if err != nil { fmt.Fprintln(os.Stderr, err) diff --git a/internal/build/build.go b/internal/build/build.go index 312c5c4f..cf5cc2e8 100644 --- a/internal/build/build.go +++ b/internal/build/build.go @@ -75,6 +75,8 @@ type Config struct { RunArgs []string // only valid for ModeRun Mode Mode GenExpect bool // only valid for ModeCmpTest + Verbose bool + Tags string } func NewDefaultConf(mode Mode) *Config { @@ -136,56 +138,6 @@ const ( 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) { if conf.Goos == "" { conf.Goos = runtime.GOOS @@ -193,11 +145,15 @@ func Do(args []string, conf *Config) ([]Package, error) { if conf.Goarch == "" { conf.Goarch = runtime.GOARCH } - flags, patterns, verbose := ParseArgs(args, buildFlags) - flags, _ = mergeFlags(flags, []string{"-tags", "llgo"}) + verbose := conf.Verbose + patterns := args + tags := "llgo" + if conf.Tags != "" { + tags += "," + conf.Tags + } cfg := &packages.Config{ Mode: loadSyntax | packages.NeedDeps | packages.NeedModule | packages.NeedExportFile, - BuildFlags: flags, + BuildFlags: []string{"-tags=" + tags}, Fset: token.NewFileSet(), Tests: conf.Mode == ModeTest, } @@ -1048,50 +1004,6 @@ func WasmRuntime() string { 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) { llgoPkgLinkFiles(ctx, pkg, func(linkFile string) { parts = append(parts, linkFile) diff --git a/internal/build/build_test.go b/internal/build/build_test.go index d9e5a8cf..e7e599fd 100644 --- a/internal/build/build_test.go +++ b/internal/build/build_test.go @@ -54,13 +54,13 @@ func mockRun(args []string, cfg *Config) { } 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) { - mockRun([]string{"-v", "../../cl/_testgo/runtest"}, &Config{Mode: ModeTest}) + mockRun([]string{"../../cl/_testgo/runtest"}, &Config{Mode: ModeTest}) } func TestCmpTest(t *testing.T) { - mockRun([]string{"-v", "../../cl/_testgo/runtest"}, &Config{Mode: ModeCmpTest}) + mockRun([]string{"../../cl/_testgo/runtest"}, &Config{Mode: ModeCmpTest}) } diff --git a/internal/build/clean.go b/internal/build/clean.go index 60ec5f46..71ca1a1f 100644 --- a/internal/build/clean.go +++ b/internal/build/clean.go @@ -21,6 +21,7 @@ import ( "os" "path" "path/filepath" + "runtime" "github.com/goplus/llgo/internal/packages" ) @@ -32,11 +33,20 @@ var ( } ) -func Clean(args []string, conf *Config) { - flags, patterns, verbose := ParseArgs(args, cleanFlags) +func Clean(patterns []string, conf *Config) { + 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{ Mode: loadSyntax | packages.NeedExportFile, - BuildFlags: flags, + BuildFlags: []string{"-tags=" + tags}, } if patterns == nil { @@ -45,11 +55,11 @@ func Clean(args []string, conf *Config) { initial, err := packages.LoadEx(nil, nil, cfg, patterns...) check(err) - cleanPkgs(initial, verbose) + cleanPkgs(initial, conf.Verbose) for _, pkg := range initial { if pkg.Name == "main" { - cleanMainPkg(pkg, conf, verbose) + cleanMainPkg(pkg, conf, conf.Verbose) } } }