libgo: update to Go 1.11
[official-gcc.git] / libgo / go / cmd / go / internal / load / flag.go
blob7534e65f54c75309ee5fc3bcbe4fa3222481f9d0
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.
5 package load
7 import (
8 "cmd/go/internal/base"
9 "cmd/go/internal/str"
10 "fmt"
11 "strings"
14 var (
15 BuildAsmflags PerPackageFlag // -asmflags
16 BuildGcflags PerPackageFlag // -gcflags
17 BuildLdflags PerPackageFlag // -ldflags
18 BuildGccgoflags PerPackageFlag // -gccgoflags
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
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
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)
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
52 if !strings.HasPrefix(v, "-") {
53 i := strings.Index(v, "=")
54 if i < 0 {
55 return fmt.Errorf("missing =<value> in <pattern>=<value>")
57 if i == 0 {
58 return fmt.Errorf("missing <pattern> in <pattern>=<value>")
60 pattern := strings.TrimSpace(v[:i])
61 match = MatchPackage(pattern, cwd)
62 v = v[i+1:]
64 flags, err := str.SplitQuotedFields(v)
65 if err != nil {
66 return err
68 if flags == nil {
69 flags = []string{}
71 f.values = append(f.values, ppfValue{match, flags})
72 return nil
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>" }
79 // Present reports whether the flag appeared on the command line.
80 func (f *PerPackageFlag) Present() bool {
81 return f.present
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
92 return flags