github.com/gagliardetto/golang-go@v0.0.0-20201020153340-53909ea70814/cmd/go/not-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/gagliardetto/golang-go/cmd/go/not-internal/base" 9 "github.com/gagliardetto/golang-go/cmd/go/not-internal/str" 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 present bool 26 values []ppfValue 27 } 28 29 // A ppfValue is a single <pattern>=<flags> per-package flag value. 30 type ppfValue struct { 31 match func(*Package) bool // compiled pattern 32 flags []string 33 } 34 35 // Set is called each time the flag is encountered on the command line. 36 func (f *PerPackageFlag) Set(v string) error { 37 return f.set(v, base.Cwd) 38 } 39 40 // set is the implementation of Set, taking a cwd (current working directory) for easier testing. 41 func (f *PerPackageFlag) set(v, cwd string) error { 42 f.present = true 43 match := func(p *Package) bool { return p.Internal.CmdlinePkg || p.Internal.CmdlineFiles } // default predicate with no pattern 44 // For backwards compatibility with earlier flag splitting, ignore spaces around flags. 45 v = strings.TrimSpace(v) 46 if v == "" { 47 // Special case: -gcflags="" means no flags for command-line arguments 48 // (overrides previous -gcflags="-whatever"). 49 f.values = append(f.values, ppfValue{match, []string{}}) 50 return nil 51 } 52 if !strings.HasPrefix(v, "-") { 53 i := strings.Index(v, "=") 54 if i < 0 { 55 return fmt.Errorf("missing =<value> in <pattern>=<value>") 56 } 57 if i == 0 { 58 return fmt.Errorf("missing <pattern> in <pattern>=<value>") 59 } 60 pattern := strings.TrimSpace(v[:i]) 61 match = MatchPackage(pattern, cwd) 62 v = v[i+1:] 63 } 64 flags, err := str.SplitQuotedFields(v) 65 if err != nil { 66 return err 67 } 68 if flags == nil { 69 flags = []string{} 70 } 71 f.values = append(f.values, ppfValue{match, flags}) 72 return nil 73 } 74 75 // String is required to implement flag.Value. 76 // It is not used, because cmd/go never calls flag.PrintDefaults. 77 func (f *PerPackageFlag) String() string { return "<PerPackageFlag>" } 78 79 // Present reports whether the flag appeared on the command line. 80 func (f *PerPackageFlag) Present() bool { 81 return f.present 82 } 83 84 // For returns the flags to use for the given package. 85 func (f *PerPackageFlag) For(p *Package) []string { 86 flags := []string{} 87 for _, v := range f.values { 88 if v.match(p) { 89 flags = v.flags 90 } 91 } 92 return flags 93 }