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