github.com/zxy12/go_duplicate_112_new@v0.0.0-20200807091221-747231827200/src/cmd/go/internal/modload/build.go (about) 1 // Copyright 2018 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 modload 6 7 import ( 8 "bytes" 9 "cmd/go/internal/base" 10 "cmd/go/internal/cfg" 11 "cmd/go/internal/modfetch" 12 "cmd/go/internal/modinfo" 13 "cmd/go/internal/module" 14 "cmd/go/internal/search" 15 "encoding/hex" 16 "fmt" 17 "internal/goroot" 18 "os" 19 "path/filepath" 20 "runtime/debug" 21 "strings" 22 ) 23 24 var ( 25 infoStart, _ = hex.DecodeString("3077af0c9274080241e1c107e6d618e6") 26 infoEnd, _ = hex.DecodeString("f932433186182072008242104116d8f2") 27 ) 28 29 func isStandardImportPath(path string) bool { 30 return findStandardImportPath(path) != "" 31 } 32 33 func findStandardImportPath(path string) string { 34 if path == "" { 35 panic("findStandardImportPath called with empty path") 36 } 37 if search.IsStandardImportPath(path) { 38 if goroot.IsStandardPackage(cfg.GOROOT, cfg.BuildContext.Compiler, path) { 39 return filepath.Join(cfg.GOROOT, "src", path) 40 } 41 if goroot.IsStandardPackage(cfg.GOROOT, cfg.BuildContext.Compiler, "vendor/"+path) { 42 return filepath.Join(cfg.GOROOT, "src/vendor", path) 43 } 44 } 45 return "" 46 } 47 48 func PackageModuleInfo(pkgpath string) *modinfo.ModulePublic { 49 if isStandardImportPath(pkgpath) || !Enabled() { 50 return nil 51 } 52 return moduleInfo(findModule(pkgpath, pkgpath), true) 53 } 54 55 func ModuleInfo(path string) *modinfo.ModulePublic { 56 if !Enabled() { 57 return nil 58 } 59 60 if i := strings.Index(path, "@"); i >= 0 { 61 return moduleInfo(module.Version{Path: path[:i], Version: path[i+1:]}, false) 62 } 63 64 for _, m := range BuildList() { 65 if m.Path == path { 66 return moduleInfo(m, true) 67 } 68 } 69 70 return &modinfo.ModulePublic{ 71 Path: path, 72 Error: &modinfo.ModuleError{ 73 Err: "module not in current build", 74 }, 75 } 76 } 77 78 // addUpdate fills in m.Update if an updated version is available. 79 func addUpdate(m *modinfo.ModulePublic) { 80 if m.Version != "" { 81 if info, err := Query(m.Path, "latest", Allowed); err == nil && info.Version != m.Version { 82 m.Update = &modinfo.ModulePublic{ 83 Path: m.Path, 84 Version: info.Version, 85 Time: &info.Time, 86 } 87 } 88 } 89 } 90 91 // addVersions fills in m.Versions with the list of known versions. 92 func addVersions(m *modinfo.ModulePublic) { 93 m.Versions, _ = versions(m.Path) 94 } 95 96 func moduleInfo(m module.Version, fromBuildList bool) *modinfo.ModulePublic { 97 if m == Target { 98 info := &modinfo.ModulePublic{ 99 Path: m.Path, 100 Version: m.Version, 101 Main: true, 102 } 103 if HasModRoot() { 104 info.Dir = ModRoot() 105 info.GoMod = filepath.Join(info.Dir, "go.mod") 106 if modFile.Go != nil { 107 info.GoVersion = modFile.Go.Version 108 } 109 } 110 return info 111 } 112 113 info := &modinfo.ModulePublic{ 114 Path: m.Path, 115 Version: m.Version, 116 Indirect: fromBuildList && loaded != nil && !loaded.direct[m.Path], 117 } 118 if loaded != nil { 119 info.GoVersion = loaded.goVersion[m.Path] 120 } 121 122 if cfg.BuildMod == "vendor" { 123 info.Dir = filepath.Join(ModRoot(), "vendor", m.Path) 124 return info 125 } 126 127 // complete fills in the extra fields in m. 128 complete := func(m *modinfo.ModulePublic) { 129 if m.Version != "" { 130 if q, err := Query(m.Path, m.Version, nil); err != nil { 131 m.Error = &modinfo.ModuleError{Err: err.Error()} 132 } else { 133 m.Version = q.Version 134 m.Time = &q.Time 135 } 136 137 mod := module.Version{Path: m.Path, Version: m.Version} 138 gomod, err := modfetch.CachePath(mod, "mod") 139 if err == nil { 140 if info, err := os.Stat(gomod); err == nil && info.Mode().IsRegular() { 141 m.GoMod = gomod 142 } 143 } 144 dir, err := modfetch.DownloadDir(mod) 145 if err == nil { 146 if info, err := os.Stat(dir); err == nil && info.IsDir() { 147 m.Dir = dir 148 } 149 } 150 } 151 } 152 153 if !fromBuildList { 154 complete(info) 155 return info 156 } 157 158 r := Replacement(m) 159 if r.Path == "" { 160 complete(info) 161 return info 162 } 163 164 // Don't hit the network to fill in extra data for replaced modules. 165 // The original resolved Version and Time don't matter enough to be 166 // worth the cost, and we're going to overwrite the GoMod and Dir from the 167 // replacement anyway. See https://golang.org/issue/27859. 168 info.Replace = &modinfo.ModulePublic{ 169 Path: r.Path, 170 Version: r.Version, 171 GoVersion: info.GoVersion, 172 } 173 if r.Version == "" { 174 if filepath.IsAbs(r.Path) { 175 info.Replace.Dir = r.Path 176 } else { 177 info.Replace.Dir = filepath.Join(ModRoot(), r.Path) 178 } 179 } 180 complete(info.Replace) 181 info.Dir = info.Replace.Dir 182 info.GoMod = filepath.Join(info.Dir, "go.mod") 183 return info 184 } 185 186 func PackageBuildInfo(path string, deps []string) string { 187 if isStandardImportPath(path) || !Enabled() { 188 return "" 189 } 190 191 target := findModule(path, path) 192 mdeps := make(map[module.Version]bool) 193 for _, dep := range deps { 194 if !isStandardImportPath(dep) { 195 mdeps[findModule(path, dep)] = true 196 } 197 } 198 var mods []module.Version 199 delete(mdeps, target) 200 for mod := range mdeps { 201 mods = append(mods, mod) 202 } 203 module.Sort(mods) 204 205 var buf bytes.Buffer 206 fmt.Fprintf(&buf, "path\t%s\n", path) 207 tv := target.Version 208 if tv == "" { 209 tv = "(devel)" 210 } 211 fmt.Fprintf(&buf, "mod\t%s\t%s\t%s\n", target.Path, tv, modfetch.Sum(target)) 212 for _, mod := range mods { 213 mv := mod.Version 214 if mv == "" { 215 mv = "(devel)" 216 } 217 r := Replacement(mod) 218 h := "" 219 if r.Path == "" { 220 h = "\t" + modfetch.Sum(mod) 221 } 222 fmt.Fprintf(&buf, "dep\t%s\t%s%s\n", mod.Path, mod.Version, h) 223 if r.Path != "" { 224 fmt.Fprintf(&buf, "=>\t%s\t%s\t%s\n", r.Path, r.Version, modfetch.Sum(r)) 225 } 226 } 227 return buf.String() 228 } 229 230 // findModule returns the module containing the package at path, 231 // needed to build the package at target. 232 func findModule(target, path string) module.Version { 233 pkg, ok := loaded.pkgCache.Get(path).(*loadPkg) 234 if ok { 235 if pkg.err != nil { 236 base.Fatalf("build %v: cannot load %v: %v", target, path, pkg.err) 237 } 238 return pkg.mod 239 } 240 241 if path == "command-line-arguments" { 242 return Target 243 } 244 245 if printStackInDie { 246 debug.PrintStack() 247 } 248 base.Fatalf("build %v: cannot find module for path %v", target, path) 249 panic("unreachable") 250 } 251 252 func ModInfoProg(info string) []byte { 253 // Inject a variable with the debug information as runtime/debug.modinfo, 254 // but compile it in package main so that it is specific to the binary. 255 // 256 // The variable must be a literal so that it will have the correct value 257 // before the initializer for package main runs. 258 // 259 // We also want the value to be present even if runtime/debug.modinfo is 260 // otherwise unused in the rest of the program. Reading it in an init function 261 // suffices for now. 262 263 return []byte(fmt.Sprintf(`package main 264 import _ "unsafe" 265 //go:linkname __debug_modinfo__ runtime/debug.modinfo 266 var __debug_modinfo__ = %q 267 var keepalive_modinfo = __debug_modinfo__ 268 func init() { keepalive_modinfo = __debug_modinfo__ } 269 `, string(infoStart)+info+string(infoEnd))) 270 }