1// Copyright 2011 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 list implements the ``go list'' command. 6package list 7 8import ( 9 "bufio" 10 "bytes" 11 "encoding/json" 12 "io" 13 "os" 14 "sort" 15 "strings" 16 "text/template" 17 18 "cmd/go/internal/base" 19 "cmd/go/internal/cache" 20 "cmd/go/internal/cfg" 21 "cmd/go/internal/load" 22 "cmd/go/internal/modload" 23 "cmd/go/internal/str" 24 "cmd/go/internal/work" 25) 26 27var CmdList = &base.Command{ 28 // Note: -f -json -m are listed explicitly because they are the most common list flags. 29 // Do not send CLs removing them because they're covered by [list flags]. 30 UsageLine: "go list [-f format] [-json] [-m] [list flags] [build flags] [packages]", 31 Short: "list packages or modules", 32 Long: ` 33List lists the named packages, one per line. 34The most commonly-used flags are -f and -json, which control the form 35of the output printed for each package. Other list flags, documented below, 36control more specific details. 37 38The default output shows the package import path: 39 40 bytes 41 encoding/json 42 github.com/gorilla/mux 43 golang.org/x/net/html 44 45The -f flag specifies an alternate format for the list, using the 46syntax of package template. The default output is equivalent 47to -f '{{.ImportPath}}'. The struct being passed to the template is: 48 49 type Package struct { 50 Dir string // directory containing package sources 51 ImportPath string // import path of package in dir 52 ImportComment string // path in import comment on package statement 53 Name string // package name 54 Doc string // package documentation string 55 Target string // install path 56 Shlib string // the shared library that contains this package (only set when -linkshared) 57 Goroot bool // is this package in the Go root? 58 Standard bool // is this package part of the standard Go library? 59 Stale bool // would 'go install' do anything for this package? 60 StaleReason string // explanation for Stale==true 61 Root string // Go root or Go path dir containing this package 62 ConflictDir string // this directory shadows Dir in $GOPATH 63 BinaryOnly bool // binary-only package: cannot be recompiled from sources 64 ForTest string // package is only for use in named test 65 Export string // file containing export data (when using -export) 66 Module *Module // info about package's containing module, if any (can be nil) 67 Match []string // command-line patterns matching this package 68 DepOnly bool // package is only a dependency, not explicitly listed 69 70 // Source files 71 GoFiles []string // .go source files (excluding CgoFiles, TestGoFiles, XTestGoFiles) 72 CgoFiles []string // .go source files that import "C" 73 CompiledGoFiles []string // .go files presented to compiler (when using -compiled) 74 IgnoredGoFiles []string // .go source files ignored due to build constraints 75 CFiles []string // .c source files 76 CXXFiles []string // .cc, .cxx and .cpp source files 77 MFiles []string // .m source files 78 HFiles []string // .h, .hh, .hpp and .hxx source files 79 FFiles []string // .f, .F, .for and .f90 Fortran source files 80 SFiles []string // .s source files 81 SwigFiles []string // .swig files 82 SwigCXXFiles []string // .swigcxx files 83 SysoFiles []string // .syso object files to add to archive 84 TestGoFiles []string // _test.go files in package 85 XTestGoFiles []string // _test.go files outside package 86 87 // Cgo directives 88 CgoCFLAGS []string // cgo: flags for C compiler 89 CgoCPPFLAGS []string // cgo: flags for C preprocessor 90 CgoCXXFLAGS []string // cgo: flags for C++ compiler 91 CgoFFLAGS []string // cgo: flags for Fortran compiler 92 CgoLDFLAGS []string // cgo: flags for linker 93 CgoPkgConfig []string // cgo: pkg-config names 94 95 // Dependency information 96 Imports []string // import paths used by this package 97 ImportMap map[string]string // map from source import to ImportPath (identity entries omitted) 98 Deps []string // all (recursively) imported dependencies 99 TestImports []string // imports from TestGoFiles 100 XTestImports []string // imports from XTestGoFiles 101 102 // Error information 103 Incomplete bool // this package or a dependency has an error 104 Error *PackageError // error loading package 105 DepsErrors []*PackageError // errors loading dependencies 106 } 107 108Packages stored in vendor directories report an ImportPath that includes the 109path to the vendor directory (for example, "d/vendor/p" instead of "p"), 110so that the ImportPath uniquely identifies a given copy of a package. 111The Imports, Deps, TestImports, and XTestImports lists also contain these 112expanded import paths. See golang.org/s/go15vendor for more about vendoring. 113 114The error information, if any, is 115 116 type PackageError struct { 117 ImportStack []string // shortest path from package named on command line to this one 118 Pos string // position of error (if present, file:line:col) 119 Err string // the error itself 120 } 121 122The module information is a Module struct, defined in the discussion 123of list -m below. 124 125The template function "join" calls strings.Join. 126 127The template function "context" returns the build context, defined as: 128 129 type Context struct { 130 GOARCH string // target architecture 131 GOOS string // target operating system 132 GOROOT string // Go root 133 GOPATH string // Go path 134 CgoEnabled bool // whether cgo can be used 135 UseAllFiles bool // use files regardless of +build lines, file names 136 Compiler string // compiler to assume when computing target paths 137 BuildTags []string // build constraints to match in +build lines 138 ReleaseTags []string // releases the current release is compatible with 139 InstallSuffix string // suffix to use in the name of the install dir 140 } 141 142For more information about the meaning of these fields see the documentation 143for the go/build package's Context type. 144 145The -json flag causes the package data to be printed in JSON format 146instead of using the template format. 147 148The -compiled flag causes list to set CompiledGoFiles to the Go source 149files presented to the compiler. Typically this means that it repeats 150the files listed in GoFiles and then also adds the Go code generated 151by processing CgoFiles and SwigFiles. The Imports list contains the 152union of all imports from both GoFiles and CompiledGoFiles. 153 154The -deps flag causes list to iterate over not just the named packages 155but also all their dependencies. It visits them in a depth-first post-order 156traversal, so that a package is listed only after all its dependencies. 157Packages not explicitly listed on the command line will have the DepOnly 158field set to true. 159 160The -e flag changes the handling of erroneous packages, those that 161cannot be found or are malformed. By default, the list command 162prints an error to standard error for each erroneous package and 163omits the packages from consideration during the usual printing. 164With the -e flag, the list command never prints errors to standard 165error and instead processes the erroneous packages with the usual 166printing. Erroneous packages will have a non-empty ImportPath and 167a non-nil Error field; other information may or may not be missing 168(zeroed). 169 170The -export flag causes list to set the Export field to the name of a 171file containing up-to-date export information for the given package. 172 173The -find flag causes list to identify the named packages but not 174resolve their dependencies: the Imports and Deps lists will be empty. 175 176The -test flag causes list to report not only the named packages 177but also their test binaries (for packages with tests), to convey to 178source code analysis tools exactly how test binaries are constructed. 179The reported import path for a test binary is the import path of 180the package followed by a ".test" suffix, as in "math/rand.test". 181When building a test, it is sometimes necessary to rebuild certain 182dependencies specially for that test (most commonly the tested 183package itself). The reported import path of a package recompiled 184for a particular test binary is followed by a space and the name of 185the test binary in brackets, as in "math/rand [math/rand.test]" 186or "regexp [sort.test]". The ForTest field is also set to the name 187of the package being tested ("math/rand" or "sort" in the previous 188examples). 189 190The Dir, Target, Shlib, Root, ConflictDir, and Export file paths 191are all absolute paths. 192 193By default, the lists GoFiles, CgoFiles, and so on hold names of files in Dir 194(that is, paths relative to Dir, not absolute paths). 195The generated files added when using the -compiled and -test flags 196are absolute paths referring to cached copies of generated Go source files. 197Although they are Go source files, the paths may not end in ".go". 198 199The -m flag causes list to list modules instead of packages. 200 201When listing modules, the -f flag still specifies a format template 202applied to a Go struct, but now a Module struct: 203 204 type Module struct { 205 Path string // module path 206 Version string // module version 207 Versions []string // available module versions (with -versions) 208 Replace *Module // replaced by this module 209 Time *time.Time // time version was created 210 Update *Module // available update, if any (with -u) 211 Main bool // is this the main module? 212 Indirect bool // is this module only an indirect dependency of main module? 213 Dir string // directory holding files for this module, if any 214 GoMod string // path to go.mod file for this module, if any 215 Error *ModuleError // error loading module 216 } 217 218 type ModuleError struct { 219 Err string // the error itself 220 } 221 222The default output is to print the module path and then 223information about the version and replacement if any. 224For example, 'go list -m all' might print: 225 226 my/main/module 227 golang.org/x/text v0.3.0 => /tmp/text 228 rsc.io/pdf v0.1.1 229 230The Module struct has a String method that formats this 231line of output, so that the default format is equivalent 232to -f '{{.String}}'. 233 234Note that when a module has been replaced, its Replace field 235describes the replacement module, and its Dir field is set to 236the replacement's source code, if present. (That is, if Replace 237is non-nil, then Dir is set to Replace.Dir, with no access to 238the replaced source code.) 239 240The -u flag adds information about available upgrades. 241When the latest version of a given module is newer than 242the current one, list -u sets the Module's Update field 243to information about the newer module. 244The Module's String method indicates an available upgrade by 245formatting the newer version in brackets after the current version. 246For example, 'go list -m -u all' might print: 247 248 my/main/module 249 golang.org/x/text v0.3.0 [v0.4.0] => /tmp/text 250 rsc.io/pdf v0.1.1 [v0.1.2] 251 252(For tools, 'go list -m -u -json all' may be more convenient to parse.) 253 254The -versions flag causes list to set the Module's Versions field 255to a list of all known versions of that module, ordered according 256to semantic versioning, earliest to latest. The flag also changes 257the default output format to display the module path followed by the 258space-separated version list. 259 260The arguments to list -m are interpreted as a list of modules, not packages. 261The main module is the module containing the current directory. 262The active modules are the main module and its dependencies. 263With no arguments, list -m shows the main module. 264With arguments, list -m shows the modules specified by the arguments. 265Any of the active modules can be specified by its module path. 266The special pattern "all" specifies all the active modules, first the main 267module and then dependencies sorted by module path. 268A pattern containing "..." specifies the active modules whose 269module paths match the pattern. 270A query of the form path@version specifies the result of that query, 271which is not limited to active modules. 272See 'go help modules' for more about module queries. 273 274The template function "module" takes a single string argument 275that must be a module path or query and returns the specified 276module as a Module struct. If an error occurs, the result will 277be a Module struct with a non-nil Error field. 278 279For more about build flags, see 'go help build'. 280 281For more about specifying packages, see 'go help packages'. 282 283For more about modules, see 'go help modules'. 284 `, 285} 286 287func init() { 288 CmdList.Run = runList // break init cycle 289 work.AddBuildFlags(CmdList) 290} 291 292var ( 293 listCompiled = CmdList.Flag.Bool("compiled", false, "") 294 listDeps = CmdList.Flag.Bool("deps", false, "") 295 listE = CmdList.Flag.Bool("e", false, "") 296 listExport = CmdList.Flag.Bool("export", false, "") 297 listFmt = CmdList.Flag.String("f", "", "") 298 listFind = CmdList.Flag.Bool("find", false, "") 299 listJson = CmdList.Flag.Bool("json", false, "") 300 listM = CmdList.Flag.Bool("m", false, "") 301 listU = CmdList.Flag.Bool("u", false, "") 302 listTest = CmdList.Flag.Bool("test", false, "") 303 listVersions = CmdList.Flag.Bool("versions", false, "") 304) 305 306var nl = []byte{'\n'} 307 308func runList(cmd *base.Command, args []string) { 309 modload.LoadTests = *listTest 310 work.BuildInit() 311 out := newTrackingWriter(os.Stdout) 312 defer out.w.Flush() 313 314 if *listFmt == "" { 315 if *listM { 316 *listFmt = "{{.String}}" 317 if *listVersions { 318 *listFmt = `{{.Path}}{{range .Versions}} {{.}}{{end}}` 319 } 320 } else { 321 *listFmt = "{{.ImportPath}}" 322 } 323 } 324 325 var do func(interface{}) 326 if *listJson { 327 do = func(x interface{}) { 328 b, err := json.MarshalIndent(x, "", "\t") 329 if err != nil { 330 out.Flush() 331 base.Fatalf("%s", err) 332 } 333 out.Write(b) 334 out.Write(nl) 335 } 336 } else { 337 var cachedCtxt *Context 338 context := func() *Context { 339 if cachedCtxt == nil { 340 cachedCtxt = newContext(&cfg.BuildContext) 341 } 342 return cachedCtxt 343 } 344 fm := template.FuncMap{ 345 "join": strings.Join, 346 "context": context, 347 "module": modload.ModuleInfo, 348 } 349 tmpl, err := template.New("main").Funcs(fm).Parse(*listFmt) 350 if err != nil { 351 base.Fatalf("%s", err) 352 } 353 do = func(x interface{}) { 354 if err := tmpl.Execute(out, x); err != nil { 355 out.Flush() 356 base.Fatalf("%s", err) 357 } 358 if out.NeedNL() { 359 out.Write(nl) 360 } 361 } 362 } 363 364 if *listM { 365 // Module mode. 366 if *listCompiled { 367 base.Fatalf("go list -compiled cannot be used with -m") 368 } 369 if *listDeps { 370 // TODO(rsc): Could make this mean something with -m. 371 base.Fatalf("go list -deps cannot be used with -m") 372 } 373 if *listExport { 374 base.Fatalf("go list -export cannot be used with -m") 375 } 376 if *listFind { 377 base.Fatalf("go list -find cannot be used with -m") 378 } 379 if *listTest { 380 base.Fatalf("go list -test cannot be used with -m") 381 } 382 383 if modload.Init(); !modload.Enabled() { 384 base.Fatalf("go list -m: not using modules") 385 } 386 modload.LoadBuildList() 387 388 mods := modload.ListModules(args, *listU, *listVersions) 389 if !*listE { 390 for _, m := range mods { 391 if m.Error != nil { 392 base.Errorf("go list -m %s: %v", m.Path, m.Error.Err) 393 } 394 } 395 base.ExitIfErrors() 396 } 397 for _, m := range mods { 398 do(m) 399 } 400 return 401 } 402 403 // Package mode (not -m). 404 if *listU { 405 base.Fatalf("go list -u can only be used with -m") 406 } 407 if *listVersions { 408 base.Fatalf("go list -versions can only be used with -m") 409 } 410 411 // These pairings make no sense. 412 if *listFind && *listDeps { 413 base.Fatalf("go list -deps cannot be used with -find") 414 } 415 if *listFind && *listTest { 416 base.Fatalf("go list -test cannot be used with -find") 417 } 418 419 load.IgnoreImports = *listFind 420 var pkgs []*load.Package 421 if *listE { 422 pkgs = load.PackagesAndErrors(args) 423 } else { 424 pkgs = load.Packages(args) 425 } 426 427 if cache.Default() == nil { 428 // These flags return file names pointing into the build cache, 429 // so the build cache must exist. 430 if *listCompiled { 431 base.Fatalf("go list -compiled requires build cache") 432 } 433 if *listExport { 434 base.Fatalf("go list -export requires build cache") 435 } 436 if *listTest { 437 base.Fatalf("go list -test requires build cache") 438 } 439 } 440 441 if *listTest { 442 c := cache.Default() 443 // Add test binaries to packages to be listed. 444 for _, p := range pkgs { 445 if p.Error != nil { 446 continue 447 } 448 if len(p.TestGoFiles)+len(p.XTestGoFiles) > 0 { 449 pmain, ptest, pxtest, err := load.GetTestPackagesFor(p, nil) 450 if err != nil { 451 if *listE { 452 pkgs = append(pkgs, &load.Package{ 453 PackagePublic: load.PackagePublic{ 454 ImportPath: p.ImportPath + ".test", 455 Error: &load.PackageError{Err: err.Error()}, 456 }, 457 }) 458 continue 459 } 460 base.Errorf("can't load test package: %s", err) 461 continue 462 } 463 pkgs = append(pkgs, pmain) 464 if ptest != nil { 465 pkgs = append(pkgs, ptest) 466 } 467 if pxtest != nil { 468 pkgs = append(pkgs, pxtest) 469 } 470 471 data := *pmain.Internal.TestmainGo 472 h := cache.NewHash("testmain") 473 h.Write([]byte("testmain\n")) 474 h.Write(data) 475 out, _, err := c.Put(h.Sum(), bytes.NewReader(data)) 476 if err != nil { 477 base.Fatalf("%s", err) 478 } 479 pmain.GoFiles[0] = c.OutputFile(out) 480 } 481 } 482 } 483 484 // Remember which packages are named on the command line. 485 cmdline := make(map[*load.Package]bool) 486 for _, p := range pkgs { 487 cmdline[p] = true 488 } 489 490 if *listDeps { 491 // Note: This changes the order of the listed packages 492 // from "as written on the command line" to 493 // "a depth-first post-order traversal". 494 // (The dependency exploration order for a given node 495 // is alphabetical, same as listed in .Deps.) 496 // Note that -deps is applied after -test, 497 // so that you only get descriptions of tests for the things named 498 // explicitly on the command line, not for all dependencies. 499 pkgs = load.PackageList(pkgs) 500 } 501 502 // Do we need to run a build to gather information? 503 needStale := *listJson || strings.Contains(*listFmt, ".Stale") 504 if needStale || *listExport || *listCompiled { 505 var b work.Builder 506 b.Init() 507 b.IsCmdList = true 508 b.NeedExport = *listExport 509 b.NeedCompiledGoFiles = *listCompiled 510 a := &work.Action{} 511 // TODO: Use pkgsFilter? 512 for _, p := range pkgs { 513 if len(p.GoFiles)+len(p.CgoFiles) > 0 { 514 a.Deps = append(a.Deps, b.AutoAction(work.ModeInstall, work.ModeInstall, p)) 515 } 516 } 517 b.Do(a) 518 } 519 520 for _, p := range pkgs { 521 // Show vendor-expanded paths in listing 522 p.TestImports = p.Resolve(p.TestImports) 523 p.XTestImports = p.Resolve(p.XTestImports) 524 p.DepOnly = !cmdline[p] 525 526 if *listCompiled { 527 p.Imports = str.StringList(p.Imports, p.Internal.CompiledImports) 528 } 529 } 530 531 if *listTest { 532 all := pkgs 533 if !*listDeps { 534 all = load.PackageList(pkgs) 535 } 536 // Update import paths to distinguish the real package p 537 // from p recompiled for q.test. 538 // This must happen only once the build code is done 539 // looking at import paths, because it will get very confused 540 // if it sees these. 541 old := make(map[string]string) 542 for _, p := range all { 543 if p.ForTest != "" { 544 new := p.ImportPath + " [" + p.ForTest + ".test]" 545 old[new] = p.ImportPath 546 p.ImportPath = new 547 } 548 p.DepOnly = !cmdline[p] 549 } 550 // Update import path lists to use new strings. 551 m := make(map[string]string) 552 for _, p := range all { 553 for _, p1 := range p.Internal.Imports { 554 if p1.ForTest != "" { 555 m[old[p1.ImportPath]] = p1.ImportPath 556 } 557 } 558 for i, old := range p.Imports { 559 if new := m[old]; new != "" { 560 p.Imports[i] = new 561 } 562 } 563 for old := range m { 564 delete(m, old) 565 } 566 } 567 // Recompute deps lists using new strings, from the leaves up. 568 for _, p := range all { 569 deps := make(map[string]bool) 570 for _, p1 := range p.Internal.Imports { 571 deps[p1.ImportPath] = true 572 for _, d := range p1.Deps { 573 deps[d] = true 574 } 575 } 576 p.Deps = make([]string, 0, len(deps)) 577 for d := range deps { 578 p.Deps = append(p.Deps, d) 579 } 580 sort.Strings(p.Deps) 581 } 582 } 583 584 // Record non-identity import mappings in p.ImportMap. 585 for _, p := range pkgs { 586 for i, srcPath := range p.Internal.RawImports { 587 path := p.Imports[i] 588 if path != srcPath { 589 if p.ImportMap == nil { 590 p.ImportMap = make(map[string]string) 591 } 592 p.ImportMap[srcPath] = path 593 } 594 } 595 } 596 597 for _, p := range pkgs { 598 do(&p.PackagePublic) 599 } 600} 601 602// TrackingWriter tracks the last byte written on every write so 603// we can avoid printing a newline if one was already written or 604// if there is no output at all. 605type TrackingWriter struct { 606 w *bufio.Writer 607 last byte 608} 609 610func newTrackingWriter(w io.Writer) *TrackingWriter { 611 return &TrackingWriter{ 612 w: bufio.NewWriter(w), 613 last: '\n', 614 } 615} 616 617func (t *TrackingWriter) Write(p []byte) (n int, err error) { 618 n, err = t.w.Write(p) 619 if n > 0 { 620 t.last = p[n-1] 621 } 622 return 623} 624 625func (t *TrackingWriter) Flush() { 626 t.w.Flush() 627} 628 629func (t *TrackingWriter) NeedNL() bool { 630 return t.last != '\n' 631} 632