github.com/go-asm/go@v1.21.1-0.20240213172139-40c5ead50c48/cmd/go/load/flag.go (about) 1 // Copyright 2017 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package load 6 7 import ( 8 "fmt" 9 "strings" 10 11 "github.com/go-asm/go/cmd/go/base" 12 "github.com/go-asm/go/cmd/quoted" 13 ) 14 15 var ( 16 BuildAsmflags PerPackageFlag // -asmflags 17 BuildGcflags PerPackageFlag // -gcflags 18 BuildLdflags PerPackageFlag // -ldflags 19 BuildGccgoflags PerPackageFlag // -gccgoflags 20 ) 21 22 // A PerPackageFlag is a command-line flag implementation (a flag.Value) 23 // that allows specifying different effective flags for different packages. 24 // See 'go help build' for more details about per-package flags. 25 type PerPackageFlag struct { 26 raw string 27 present bool 28 values []ppfValue 29 } 30 31 // A ppfValue is a single <pattern>=<flags> per-package flag value. 32 type ppfValue struct { 33 match func(*Package) bool // compiled pattern 34 flags []string 35 } 36 37 // Set is called each time the flag is encountered on the command line. 38 func (f *PerPackageFlag) Set(v string) error { 39 return f.set(v, base.Cwd()) 40 } 41 42 // set is the implementation of Set, taking a cwd (current working directory) for easier testing. 43 func (f *PerPackageFlag) set(v, cwd string) error { 44 f.raw = v 45 f.present = true 46 match := func(p *Package) bool { return p.Internal.CmdlinePkg || p.Internal.CmdlineFiles } // default predicate with no pattern 47 // For backwards compatibility with earlier flag splitting, ignore spaces around flags. 48 v = strings.TrimSpace(v) 49 if v == "" { 50 // Special case: -gcflags="" means no flags for command-line arguments 51 // (overrides previous -gcflags="-whatever"). 52 f.values = append(f.values, ppfValue{match, []string{}}) 53 return nil 54 } 55 if !strings.HasPrefix(v, "-") { 56 i := strings.Index(v, "=") 57 if i < 0 { 58 return fmt.Errorf("missing =<value> in <pattern>=<value>") 59 } 60 if i == 0 { 61 return fmt.Errorf("missing <pattern> in <pattern>=<value>") 62 } 63 if v[0] == '\'' || v[0] == '"' { 64 return fmt.Errorf("parameter may not start with quote character %c", v[0]) 65 } 66 pattern := strings.TrimSpace(v[:i]) 67 match = MatchPackage(pattern, cwd) 68 v = v[i+1:] 69 } 70 flags, err := quoted.Split(v) 71 if err != nil { 72 return err 73 } 74 if flags == nil { 75 flags = []string{} 76 } 77 f.values = append(f.values, ppfValue{match, flags}) 78 return nil 79 } 80 81 func (f *PerPackageFlag) String() string { return f.raw } 82 83 // Present reports whether the flag appeared on the command line. 84 func (f *PerPackageFlag) Present() bool { 85 return f.present 86 } 87 88 // For returns the flags to use for the given package. 89 func (f *PerPackageFlag) For(p *Package) []string { 90 flags := []string{} 91 for _, v := range f.values { 92 if v.match(p) { 93 flags = v.flags 94 } 95 } 96 return flags 97 }