tg.run("build", "-i", "-pkgdir=.", "runtime")
}
-func TestGcflagsPatterns(t *testing.T) {
- skipIfGccgo(t, "gccgo has no standard packages")
- tg := testgo(t)
- defer tg.cleanup()
- tg.setenv("GOPATH", "")
- tg.setenv("GOCACHE", "off")
-
- tg.run("build", "-n", "-v", "-gcflags= \t\r\n -e", "fmt")
- tg.grepStderr("^# fmt", "did not rebuild fmt")
- tg.grepStderrNot("^# reflect", "incorrectly rebuilt reflect")
-
- tg.run("build", "-n", "-v", "-gcflags=-e", "fmt", "reflect")
- tg.grepStderr("^# fmt", "did not rebuild fmt")
- tg.grepStderr("^# reflect", "did not rebuild reflect")
- tg.grepStderrNot("^# runtime", "incorrectly rebuilt runtime")
-
- tg.run("build", "-n", "-x", "-v", "-gcflags= \t\r\n reflect \t\r\n = \t\r\n -N", "fmt")
- tg.grepStderr("^# fmt", "did not rebuild fmt")
- tg.grepStderr("^# reflect", "did not rebuild reflect")
- tg.grepStderr("compile.* -N .*-p reflect", "did not build reflect with -N flag")
- tg.grepStderrNot("compile.* -N .*-p fmt", "incorrectly built fmt with -N flag")
-
- tg.run("test", "-c", "-n", "-gcflags=-N", "-ldflags=-X=x.y=z", "strings")
- tg.grepStderr("compile.* -N .*compare_test.go", "did not compile strings_test package with -N flag")
- tg.grepStderr("link.* -X=x.y=z", "did not link strings.test binary with -X flag")
-
- tg.run("test", "-c", "-n", "-gcflags=strings=-N", "-ldflags=strings=-X=x.y=z", "strings")
- tg.grepStderr("compile.* -N .*compare_test.go", "did not compile strings_test package with -N flag")
- tg.grepStderr("link.* -X=x.y=z", "did not link strings.test binary with -X flag")
-}
-
func TestGoTestMinusN(t *testing.T) {
// Intent here is to verify that 'go test -n' works without crashing.
// This reuses flag_test.go, but really any test would do.
}
load1 := func(path string, mode int) *load.Package {
if parent == nil {
- return load.LoadPackage(path, stk)
+ return load.LoadPackageNoFlags(path, stk)
}
return load.LoadImport(path, parent.Dir, parent, stk, nil, mode|load.ResolveModule)
}
base.Run(cfg.BuildToolexec, str.StringList(base.Tool("fix"), files))
// The imports might have changed, so reload again.
- p = load.ReloadPackage(arg, stk)
+ p = load.ReloadPackageNoFlags(arg, stk)
if p.Error != nil {
base.Errorf("%s", p.Error)
return
import (
"cmd/go/internal/base"
- "cmd/go/internal/search"
"cmd/go/internal/str"
"fmt"
"strings"
}
return flags
}
-
-var (
- cmdlineMatchers []func(*Package) bool
- cmdlineMatcherLiterals []func(*Package) bool
-)
-
-// SetCmdlinePatterns records the set of patterns given on the command line,
-// for use by the PerPackageFlags.
-func SetCmdlinePatterns(args []string) {
- setCmdlinePatterns(args, base.Cwd)
-}
-
-func setCmdlinePatterns(args []string, cwd string) {
- if len(args) == 0 {
- args = []string{"."}
- }
- cmdlineMatchers = nil // allow reset for testing
- cmdlineMatcherLiterals = nil
- for _, arg := range args {
- cmdlineMatchers = append(cmdlineMatchers, MatchPackage(arg, cwd))
- }
- for _, arg := range args {
- if !strings.Contains(arg, "...") && !search.IsMetaPackage(arg) {
- cmdlineMatcherLiterals = append(cmdlineMatcherLiterals, MatchPackage(arg, cwd))
- }
- }
-}
-
-// isCmdlinePkg reports whether p is a package listed on the command line.
-func isCmdlinePkg(p *Package) bool {
- for _, m := range cmdlineMatchers {
- if m(p) {
- return true
- }
- }
- return false
-}
-
-// isCmdlinePkgLiteral reports whether p is a package listed as
-// a literal package argument on the command line
-// (as opposed to being the result of expanding a wildcard).
-func isCmdlinePkgLiteral(p *Package) bool {
- for _, m := range cmdlineMatcherLiterals {
- if m(p) {
- return true
- }
- }
- return false
-}
}
}
-// reloadPackage is like loadPackage but makes sure
+// ReloadPackageNoFlags is like LoadPackageNoFlags but makes sure
// not to use the package cache.
-func ReloadPackage(arg string, stk *ImportStack) *Package {
+// It is only for use by GOPATH-based "go get".
+// TODO(rsc): When GOPATH-based "go get" is removed, delete this function.
+func ReloadPackageNoFlags(arg string, stk *ImportStack) *Package {
p := packageCache[arg]
if p != nil {
delete(packageCache, p.Dir)
delete(packageCache, p.ImportPath)
}
- return LoadPackage(arg, stk)
+ return LoadPackageNoFlags(arg, stk)
}
// dirToImportPath returns the pseudo-import path we use for a package
// but possibly a local import path (an absolute file system path or one beginning
// with ./ or ../). A local relative path is interpreted relative to srcDir.
// It returns a *Package describing the package found in that directory.
+// LoadImport does not set tool flags and should only be used by
+// this package, as part of a bigger load operation, and by GOPATH-based "go get".
+// TODO(rsc): When GOPATH-based "go get" is removed, unexport this function.
func LoadImport(path, srcDir string, parent *Package, stk *ImportStack, importPos []token.Position, mode int) *Package {
stk.Push(path)
defer stk.Pop()
func (p *Package) load(stk *ImportStack, bp *build.Package, err error) {
p.copyBuild(bp)
- // Decide whether p was listed on the command line.
- // Given that load is called while processing the command line,
- // you might think we could simply pass a flag down into load
- // saying whether we are loading something named on the command
- // line or something to satisfy an import. But the first load of a
- // package named on the command line may be as a dependency
- // of an earlier package named on the command line, not when we
- // get to that package during command line processing.
- // For example "go test fmt reflect" will load reflect as a dependency
- // of fmt before it attempts to load as a command-line argument.
- // Because loads are cached, the later load will be a no-op,
- // so it is important that the first load can fill in CmdlinePkg correctly.
- // Hence the call to a separate matching check here.
- p.Internal.CmdlinePkg = isCmdlinePkg(p)
- p.Internal.CmdlinePkgLiteral = isCmdlinePkgLiteral(p)
-
- p.Internal.Asmflags = BuildAsmflags.For(p)
- p.Internal.Gcflags = BuildGcflags.For(p)
- p.Internal.Ldflags = BuildLdflags.For(p)
- p.Internal.Gccgoflags = BuildGccgoflags.For(p)
-
// The localPrefix is the path we interpret ./ imports relative to.
// Synthesized main packages sometimes override this.
if p.Internal.Local {
}
}
+// LoadPackage loads the package named by arg.
+func LoadPackage(arg string, stk *ImportStack) *Package {
+ p := loadPackage(arg, stk)
+ setToolFlags(p)
+ return p
+}
+
+// LoadPackageNoFlags is like LoadPackage
+// but does not guarantee that the build tool flags are set in the result.
+// It is only for use by GOPATH-based "go get"
+// and is only appropriate for preliminary loading of packages.
+// A real load using LoadPackage or (more likely)
+// Packages, PackageAndErrors, or PackagesForBuild
+// must be done before passing the package to any build
+// steps, so that the tool flags can be set properly.
+// TODO(rsc): When GOPATH-based "go get" is removed, delete this function.
+func LoadPackageNoFlags(arg string, stk *ImportStack) *Package {
+ return loadPackage(arg, stk)
+}
+
// loadPackage is like loadImport but is used for command-line arguments,
// not for paths found in import statements. In addition to ordinary import paths,
// loadPackage accepts pseudo-paths beginning with cmd/ to denote commands
// in the Go command directory, as well as paths to those directories.
-func LoadPackage(arg string, stk *ImportStack) *Package {
+func loadPackage(arg string, stk *ImportStack) *Package {
if build.IsLocalImport(arg) {
dir := arg
if !filepath.IsAbs(dir) {
for _, m := range matches {
for _, pkg := range m.Pkgs {
- p := LoadPackage(pkg, &stk)
+ p := loadPackage(pkg, &stk)
+ p.Internal.CmdlinePkg = true
+ if m.Literal {
+ // Note: do not set = m.Literal unconditionally
+ // because maybe we'll see p matching both
+ // a literal and also a non-literal pattern.
+ p.Internal.CmdlinePkgLiteral = true
+ }
if seenPkg[p] {
continue
}
}
}
+ // Now that CmdlinePkg is set correctly,
+ // compute the effective flags for all loaded packages
+ // (not just the ones matching the patterns but also
+ // their dependencies).
+ setToolFlags(pkgs...)
+
return pkgs
}
+func setToolFlags(pkgs ...*Package) {
+ for _, p := range PackageList(pkgs) {
+ p.Internal.Asmflags = BuildAsmflags.For(p)
+ p.Internal.Gcflags = BuildGcflags.For(p)
+ p.Internal.Ldflags = BuildLdflags.For(p)
+ p.Internal.Gccgoflags = BuildGccgoflags.For(p)
+ }
+}
+
func ImportPaths(args []string) []*search.Match {
if ModInit(); cfg.ModulesEnabled {
return ModImportPaths(args)
}
}
+ setToolFlags(pkg)
+
return pkg
}
import (
"path/filepath"
- "runtime"
"strings"
"cmd/go/internal/search"
}
dir = filepath.Join(cwd, dir)
if pattern == "" {
- return func(p *Package) bool {
- // TODO(rsc): This is wrong. See golang.org/issue/25878.
- if runtime.GOOS != "windows" {
- return p.Dir == dir
- }
- return strings.EqualFold(p.Dir, dir)
- }
+ return func(p *Package) bool { return p.Dir == dir }
}
matchPath := search.MatchPattern(pattern)
return func(p *Package) bool {
--- /dev/null
+[!gc] skip 'using -gcflags and -ldflags'
+
+# -gcflags=-e applies to named packages, not dependencies
+go build -n -v -gcflags=-e z1 z2
+stderr 'compile.* -e .*-p z1'
+stderr 'compile.* -e .*-p z2'
+stderr 'compile.* -p y'
+! stderr 'compile.* -e .*-p [^z]'
+
+# -gcflags can specify package=flags, and can be repeated; last match wins
+go build -n -v -gcflags=-e -gcflags=z1=-N z1 z2
+stderr 'compile.* -N .*-p z1'
+! stderr 'compile.* -e .*-p z1'
+! stderr 'compile.* -N .*-p z2'
+stderr 'compile.* -e .*-p z2'
+stderr 'compile.* -p y'
+! stderr 'compile.* -e .*-p [^z]'
+! stderr 'compile.* -N .*-p [^z]'
+
+# -gcflags can have arbitrary spaces around the flags
+go build -n -v -gcflags=' z1 = -e ' z1
+stderr 'compile.* -e .*-p z1'
+
+# -ldflags for implicit test package applies to test binary
+go test -c -n -gcflags=-N -ldflags=-X=x.y=z z1
+stderr 'compile.* -N .*z_test.go'
+stderr 'link.* -X=x.y=z'
+
+# -ldflags for explicit test package applies to test binary
+go test -c -n -gcflags=z1=-N -ldflags=z1=-X=x.y=z z1
+stderr 'compile.* -N .*z_test.go'
+stderr 'link.* -X=x.y=z'
+
+# -ldflags applies to link of command
+go build -n -ldflags=-X=math.pi=3 my/cmd/prog
+stderr 'link.* -X=math.pi=3'
+
+# -ldflags applies to link of command even with strange directory name
+go build -n -ldflags=-X=math.pi=3 my/cmd/prog/
+stderr 'link.* -X=math.pi=3'
+
+# -ldflags applies to current directory
+cd my/cmd/prog
+go build -n -ldflags=-X=math.pi=3
+stderr 'link.* -X=math.pi=3'
+
+# -ldflags applies to current directory even if GOPATH is funny
+[windows] cd $WORK/GoPath/src/my/cmd/prog
+[darwin] cd $WORK/GoPath/src/my/cmd/prog
+go build -n -ldflags=-X=math.pi=3
+stderr 'link.* -X=math.pi=3'
+
+-- z1/z.go --
+package z1
+import _ "y"
+import _ "z2"
+
+-- z1/z_test.go --
+package z1_test
+import "testing"
+func Test(t *testing.T) {}
+
+-- z2/z.go --
+package z2
+
+-- y/y.go --
+package y
+
+-- my/cmd/prog/prog.go --
+package main
+func main() {}