...

Source file src/pkg/cmd/go/internal/load/flag.go

     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		"cmd/go/internal/base"
     9		"cmd/go/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	}
    94	

View as plain text