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
5package work
6
7import (
8	"errors"
9	"fmt"
10	"go/build"
11	"os"
12	"os/exec"
13	"path"
14	"path/filepath"
15	"runtime"
16	"strings"
17
18	"cmd/go/internal/base"
19	"cmd/go/internal/cfg"
20	"cmd/go/internal/load"
21)
22
23var CmdBuild = &base.Command{
24	UsageLine: "build [-o output] [-i] [build flags] [packages]",
25	Short:     "compile packages and dependencies",
26	Long: `
27Build compiles the packages named by the import paths,
28along with their dependencies, but it does not install the results.
29
30If the arguments to build are a list of .go files, build treats
31them as a list of source files specifying a single package.
32
33When compiling a single main package, build writes
34the resulting executable to an output file named after
35the first source file ('go build ed.go rx.go' writes 'ed' or 'ed.exe')
36or the source code directory ('go build unix/sam' writes 'sam' or 'sam.exe').
37The '.exe' suffix is added when writing a Windows executable.
38
39When compiling multiple packages or a single non-main package,
40build compiles the packages but discards the resulting object,
41serving only as a check that the packages can be built.
42
43When compiling packages, build ignores files that end in '_test.go'.
44
45The -o flag, only allowed when compiling a single package,
46forces build to write the resulting executable or object
47to the named output file, instead of the default behavior described
48in the last two paragraphs.
49
50The -i flag installs the packages that are dependencies of the target.
51
52The build flags are shared by the build, clean, get, install, list, run,
53and test commands:
54
55	-a
56		force rebuilding of packages that are already up-to-date.
57	-n
58		print the commands but do not run them.
59	-p n
60		the number of programs, such as build commands or
61		test binaries, that can be run in parallel.
62		The default is the number of CPUs available.
63	-race
64		enable data race detection.
65		Supported only on linux/amd64, freebsd/amd64, darwin/amd64 and windows/amd64.
66	-msan
67		enable interoperation with memory sanitizer.
68		Supported only on linux/amd64,
69		and only with Clang/LLVM as the host C compiler.
70	-v
71		print the names of packages as they are compiled.
72	-work
73		print the name of the temporary work directory and
74		do not delete it when exiting.
75	-x
76		print the commands.
77
78	-asmflags '[pattern=]arg list'
79		arguments to pass on each go tool asm invocation.
80	-buildmode mode
81		build mode to use. See 'go help buildmode' for more.
82	-compiler name
83		name of compiler to use, as in runtime.Compiler (gccgo or gc).
84	-gccgoflags '[pattern=]arg list'
85		arguments to pass on each gccgo compiler/linker invocation.
86	-gcflags '[pattern=]arg list'
87		arguments to pass on each go tool compile invocation.
88	-installsuffix suffix
89		a suffix to use in the name of the package installation directory,
90		in order to keep output separate from default builds.
91		If using the -race flag, the install suffix is automatically set to race
92		or, if set explicitly, has _race appended to it. Likewise for the -msan
93		flag. Using a -buildmode option that requires non-default compile flags
94		has a similar effect.
95	-ldflags '[pattern=]arg list'
96		arguments to pass on each go tool link invocation.
97	-linkshared
98		link against shared libraries previously created with
99		-buildmode=shared.
100	-pkgdir dir
101		install and load all packages from dir instead of the usual locations.
102		For example, when building with a non-standard configuration,
103		use -pkgdir to keep generated packages in a separate location.
104	-tags 'tag list'
105		a space-separated list of build tags to consider satisfied during the
106		build. For more information about build tags, see the description of
107		build constraints in the documentation for the go/build package.
108	-toolexec 'cmd args'
109		a program to use to invoke toolchain programs like vet and asm.
110		For example, instead of running asm, the go command will run
111		'cmd args /path/to/asm <arguments for asm>'.
112
113The -asmflags, -gccgoflags, -gcflags, and -ldflags flags accept a
114space-separated list of arguments to pass to an underlying tool
115during the build. To embed spaces in an element in the list, surround
116it with either single or double quotes. The argument list may be
117preceded by a package pattern and an equal sign, which restricts
118the use of that argument list to the building of packages matching
119that pattern (see 'go help packages' for a description of package
120patterns). Without a pattern, the argument list applies only to the
121packages named on the command line. The flags may be repeated
122with different patterns in order to specify different arguments for
123different sets of packages. If a package matches patterns given in
124multiple flags, the latest match on the command line wins.
125For example, 'go build -gcflags=-S fmt' prints the disassembly
126only for package fmt, while 'go build -gcflags=all=-S fmt'
127prints the disassembly for fmt and all its dependencies.
128
129For more about specifying packages, see 'go help packages'.
130For more about where packages and binaries are installed,
131run 'go help gopath'.
132For more about calling between Go and C/C++, run 'go help c'.
133
134Note: Build adheres to certain conventions such as those described
135by 'go help gopath'. Not all projects can follow these conventions,
136however. Installations that have their own conventions or that use
137a separate software build system may choose to use lower-level
138invocations such as 'go tool compile' and 'go tool link' to avoid
139some of the overheads and design decisions of the build tool.
140
141See also: go install, go get, go clean.
142	`,
143}
144
145const concurrentGCBackendCompilationEnabledByDefault = true
146
147func init() {
148	// break init cycle
149	CmdBuild.Run = runBuild
150	CmdInstall.Run = runInstall
151
152	CmdBuild.Flag.BoolVar(&cfg.BuildI, "i", false, "")
153	CmdBuild.Flag.StringVar(&cfg.BuildO, "o", "", "output file")
154
155	CmdInstall.Flag.BoolVar(&cfg.BuildI, "i", false, "")
156
157	AddBuildFlags(CmdBuild)
158	AddBuildFlags(CmdInstall)
159}
160
161// Note that flags consulted by other parts of the code
162// (for example, buildV) are in cmd/go/internal/cfg.
163
164var (
165	forcedAsmflags   []string // internally-forced flags for cmd/asm
166	forcedGcflags    []string // internally-forced flags for cmd/compile
167	forcedLdflags    []string // internally-forced flags for cmd/link
168	forcedGccgoflags []string // internally-forced flags for gccgo
169)
170
171var BuildToolchain toolchain = noToolchain{}
172var ldBuildmode string
173
174// buildCompiler implements flag.Var.
175// It implements Set by updating both
176// BuildToolchain and buildContext.Compiler.
177type buildCompiler struct{}
178
179func (c buildCompiler) Set(value string) error {
180	switch value {
181	case "gc":
182		BuildToolchain = gcToolchain{}
183	case "gccgo":
184		BuildToolchain = gccgoToolchain{}
185	default:
186		return fmt.Errorf("unknown compiler %q", value)
187	}
188	cfg.BuildToolchainName = value
189	cfg.BuildToolchainCompiler = BuildToolchain.compiler
190	cfg.BuildToolchainLinker = BuildToolchain.linker
191	cfg.BuildContext.Compiler = value
192	return nil
193}
194
195func (c buildCompiler) String() string {
196	return cfg.BuildContext.Compiler
197}
198
199func init() {
200	switch build.Default.Compiler {
201	case "gc", "gccgo":
202		buildCompiler{}.Set(build.Default.Compiler)
203	}
204}
205
206// addBuildFlags adds the flags common to the build, clean, get,
207// install, list, run, and test commands.
208func AddBuildFlags(cmd *base.Command) {
209	cmd.Flag.BoolVar(&cfg.BuildA, "a", false, "")
210	cmd.Flag.BoolVar(&cfg.BuildN, "n", false, "")
211	cmd.Flag.IntVar(&cfg.BuildP, "p", cfg.BuildP, "")
212	cmd.Flag.BoolVar(&cfg.BuildV, "v", false, "")
213	cmd.Flag.BoolVar(&cfg.BuildX, "x", false, "")
214
215	cmd.Flag.Var(&load.BuildAsmflags, "asmflags", "")
216	cmd.Flag.Var(buildCompiler{}, "compiler", "")
217	cmd.Flag.StringVar(&cfg.BuildBuildmode, "buildmode", "default", "")
218	cmd.Flag.Var(&load.BuildGcflags, "gcflags", "")
219	cmd.Flag.Var(&load.BuildGccgoflags, "gccgoflags", "")
220	cmd.Flag.StringVar(&cfg.BuildContext.InstallSuffix, "installsuffix", "", "")
221	cmd.Flag.Var(&load.BuildLdflags, "ldflags", "")
222	cmd.Flag.BoolVar(&cfg.BuildLinkshared, "linkshared", false, "")
223	cmd.Flag.StringVar(&cfg.BuildPkgdir, "pkgdir", "", "")
224	cmd.Flag.BoolVar(&cfg.BuildRace, "race", false, "")
225	cmd.Flag.BoolVar(&cfg.BuildMSan, "msan", false, "")
226	cmd.Flag.Var((*base.StringsFlag)(&cfg.BuildContext.BuildTags), "tags", "")
227	cmd.Flag.Var((*base.StringsFlag)(&cfg.BuildToolexec), "toolexec", "")
228	cmd.Flag.BoolVar(&cfg.BuildWork, "work", false, "")
229
230	// Undocumented, unstable debugging flags.
231	cmd.Flag.StringVar(&cfg.DebugActiongraph, "debug-actiongraph", "", "")
232}
233
234// fileExtSplit expects a filename and returns the name
235// and ext (without the dot). If the file has no
236// extension, ext will be empty.
237func fileExtSplit(file string) (name, ext string) {
238	dotExt := filepath.Ext(file)
239	name = file[:len(file)-len(dotExt)]
240	if dotExt != "" {
241		ext = dotExt[1:]
242	}
243	return
244}
245
246func pkgsMain(pkgs []*load.Package) (res []*load.Package) {
247	for _, p := range pkgs {
248		if p.Name == "main" {
249			res = append(res, p)
250		}
251	}
252	return res
253}
254
255func pkgsNotMain(pkgs []*load.Package) (res []*load.Package) {
256	for _, p := range pkgs {
257		if p.Name != "main" {
258			res = append(res, p)
259		}
260	}
261	return res
262}
263
264func oneMainPkg(pkgs []*load.Package) []*load.Package {
265	if len(pkgs) != 1 || pkgs[0].Name != "main" {
266		base.Fatalf("-buildmode=%s requires exactly one main package", cfg.BuildBuildmode)
267	}
268	return pkgs
269}
270
271var pkgsFilter = func(pkgs []*load.Package) []*load.Package { return pkgs }
272
273var runtimeVersion = runtime.Version()
274
275func runBuild(cmd *base.Command, args []string) {
276	BuildInit()
277	var b Builder
278	b.Init()
279
280	pkgs := load.PackagesForBuild(args)
281
282	if len(pkgs) == 1 && pkgs[0].Name == "main" && cfg.BuildO == "" {
283		_, cfg.BuildO = path.Split(pkgs[0].ImportPath)
284		cfg.BuildO += cfg.ExeSuffix
285	}
286
287	// Special case -o /dev/null by not writing at all.
288	if cfg.BuildO == os.DevNull {
289		cfg.BuildO = ""
290	}
291
292	// sanity check some often mis-used options
293	switch cfg.BuildContext.Compiler {
294	case "gccgo":
295		if load.BuildGcflags.Present() {
296			fmt.Println("go build: when using gccgo toolchain, please pass compiler flags using -gccgoflags, not -gcflags")
297		}
298		if load.BuildLdflags.Present() {
299			fmt.Println("go build: when using gccgo toolchain, please pass linker flags using -gccgoflags, not -ldflags")
300		}
301	case "gc":
302		if load.BuildGccgoflags.Present() {
303			fmt.Println("go build: when using gc toolchain, please pass compile flags using -gcflags, and linker flags using -ldflags")
304		}
305	}
306
307	depMode := ModeBuild
308	if cfg.BuildI {
309		depMode = ModeInstall
310	}
311
312	pkgs = pkgsFilter(load.Packages(args))
313
314	if cfg.BuildO != "" {
315		if len(pkgs) > 1 {
316			base.Fatalf("go build: cannot use -o with multiple packages")
317		} else if len(pkgs) == 0 {
318			base.Fatalf("no packages to build")
319		}
320		p := pkgs[0]
321		p.Target = cfg.BuildO
322		p.Stale = true // must build - not up to date
323		p.StaleReason = "build -o flag in use"
324		a := b.AutoAction(ModeInstall, depMode, p)
325		b.Do(a)
326		return
327	}
328
329	a := &Action{Mode: "go build"}
330	for _, p := range pkgs {
331		a.Deps = append(a.Deps, b.AutoAction(ModeBuild, depMode, p))
332	}
333	if cfg.BuildBuildmode == "shared" {
334		a = b.buildmodeShared(ModeBuild, depMode, args, pkgs, a)
335	}
336	b.Do(a)
337}
338
339var CmdInstall = &base.Command{
340	UsageLine: "install [-i] [build flags] [packages]",
341	Short:     "compile and install packages and dependencies",
342	Long: `
343Install compiles and installs the packages named by the import paths.
344
345The -i flag installs the dependencies of the named packages as well.
346
347For more about the build flags, see 'go help build'.
348For more about specifying packages, see 'go help packages'.
349
350See also: go build, go get, go clean.
351	`,
352}
353
354// libname returns the filename to use for the shared library when using
355// -buildmode=shared. The rules we use are:
356// Use arguments for special 'meta' packages:
357//	std --> libstd.so
358//	std cmd --> libstd,cmd.so
359// A single non-meta argument with trailing "/..." is special cased:
360//	foo/... --> libfoo.so
361//	(A relative path like "./..."  expands the "." first)
362// Use import paths for other cases, changing '/' to '-':
363//	somelib --> libsubdir-somelib.so
364//	./ or ../ --> libsubdir-somelib.so
365//	gopkg.in/tomb.v2 -> libgopkg.in-tomb.v2.so
366//	a/... b/... ---> liba/c,b/d.so - all matching import paths
367// Name parts are joined with ','.
368func libname(args []string, pkgs []*load.Package) (string, error) {
369	var libname string
370	appendName := func(arg string) {
371		if libname == "" {
372			libname = arg
373		} else {
374			libname += "," + arg
375		}
376	}
377	var haveNonMeta bool
378	for _, arg := range args {
379		if load.IsMetaPackage(arg) {
380			appendName(arg)
381		} else {
382			haveNonMeta = true
383		}
384	}
385	if len(libname) == 0 { // non-meta packages only. use import paths
386		if len(args) == 1 && strings.HasSuffix(args[0], "/...") {
387			// Special case of "foo/..." as mentioned above.
388			arg := strings.TrimSuffix(args[0], "/...")
389			if build.IsLocalImport(arg) {
390				cwd, _ := os.Getwd()
391				bp, _ := cfg.BuildContext.ImportDir(filepath.Join(cwd, arg), build.FindOnly)
392				if bp.ImportPath != "" && bp.ImportPath != "." {
393					arg = bp.ImportPath
394				}
395			}
396			appendName(strings.Replace(arg, "/", "-", -1))
397		} else {
398			for _, pkg := range pkgs {
399				appendName(strings.Replace(pkg.ImportPath, "/", "-", -1))
400			}
401		}
402	} else if haveNonMeta { // have both meta package and a non-meta one
403		return "", errors.New("mixing of meta and non-meta packages is not allowed")
404	}
405	// TODO(mwhudson): Needs to change for platforms that use different naming
406	// conventions...
407	return "lib" + libname + ".so", nil
408}
409
410func runInstall(cmd *base.Command, args []string) {
411	BuildInit()
412	InstallPackages(args, false)
413}
414
415func InstallPackages(args []string, forGet bool) {
416	if cfg.GOBIN != "" && !filepath.IsAbs(cfg.GOBIN) {
417		base.Fatalf("cannot install, GOBIN must be an absolute path")
418	}
419
420	pkgs := pkgsFilter(load.PackagesForBuild(args))
421
422	for _, p := range pkgs {
423		if p.Target == "" && (!p.Standard || p.ImportPath != "unsafe") {
424			switch {
425			case p.Internal.GobinSubdir:
426				base.Errorf("go %s: cannot install cross-compiled binaries when GOBIN is set", cfg.CmdName)
427			case p.Internal.CmdlineFiles:
428				base.Errorf("go %s: no install location for .go files listed on command line (GOBIN not set)", cfg.CmdName)
429			case p.ConflictDir != "":
430				base.Errorf("go %s: no install location for %s: hidden by %s", cfg.CmdName, p.Dir, p.ConflictDir)
431			default:
432				base.Errorf("go %s: no install location for directory %s outside GOPATH\n"+
433					"\tFor more details see: 'go help gopath'", cfg.CmdName, p.Dir)
434			}
435		}
436	}
437	base.ExitIfErrors()
438
439	var b Builder
440	b.Init()
441	depMode := ModeBuild
442	if cfg.BuildI {
443		depMode = ModeInstall
444	}
445	a := &Action{Mode: "go install"}
446	var tools []*Action
447	for _, p := range pkgs {
448		// During 'go get', don't attempt (and fail) to install packages with only tests.
449		// TODO(rsc): It's not clear why 'go get' should be different from 'go install' here. See #20760.
450		if forGet && len(p.GoFiles)+len(p.CgoFiles) == 0 && len(p.TestGoFiles)+len(p.XTestGoFiles) > 0 {
451			continue
452		}
453		// If p is a tool, delay the installation until the end of the build.
454		// This avoids installing assemblers/compilers that are being executed
455		// by other steps in the build.
456		a1 := b.AutoAction(ModeInstall, depMode, p)
457		if load.InstallTargetDir(p) == load.ToTool {
458			a.Deps = append(a.Deps, a1.Deps...)
459			a1.Deps = append(a1.Deps, a)
460			tools = append(tools, a1)
461			continue
462		}
463		a.Deps = append(a.Deps, a1)
464	}
465	if len(tools) > 0 {
466		a = &Action{
467			Mode: "go install (tools)",
468			Deps: tools,
469		}
470	}
471
472	if cfg.BuildBuildmode == "shared" {
473		// Note: If buildmode=shared then only non-main packages
474		// are present in the pkgs list, so all the special case code about
475		// tools above did not apply, and a is just a simple Action
476		// with a list of Deps, one per package named in pkgs,
477		// the same as in runBuild.
478		a = b.buildmodeShared(ModeInstall, ModeInstall, args, pkgs, a)
479	}
480
481	b.Do(a)
482	base.ExitIfErrors()
483
484	// Success. If this command is 'go install' with no arguments
485	// and the current directory (the implicit argument) is a command,
486	// remove any leftover command binary from a previous 'go build'.
487	// The binary is installed; it's not needed here anymore.
488	// And worse it might be a stale copy, which you don't want to find
489	// instead of the installed one if $PATH contains dot.
490	// One way to view this behavior is that it is as if 'go install' first
491	// runs 'go build' and the moves the generated file to the install dir.
492	// See issue 9645.
493	if len(args) == 0 && len(pkgs) == 1 && pkgs[0].Name == "main" {
494		// Compute file 'go build' would have created.
495		// If it exists and is an executable file, remove it.
496		_, targ := filepath.Split(pkgs[0].ImportPath)
497		targ += cfg.ExeSuffix
498		if filepath.Join(pkgs[0].Dir, targ) != pkgs[0].Target { // maybe $GOBIN is the current directory
499			fi, err := os.Stat(targ)
500			if err == nil {
501				m := fi.Mode()
502				if m.IsRegular() {
503					if m&0111 != 0 || cfg.Goos == "windows" { // windows never sets executable bit
504						os.Remove(targ)
505					}
506				}
507			}
508		}
509	}
510}
511
512// ExecCmd is the command to use to run user binaries.
513// Normally it is empty, meaning run the binaries directly.
514// If cross-compiling and running on a remote system or
515// simulator, it is typically go_GOOS_GOARCH_exec, with
516// the target GOOS and GOARCH substituted.
517// The -exec flag overrides these defaults.
518var ExecCmd []string
519
520// FindExecCmd derives the value of ExecCmd to use.
521// It returns that value and leaves ExecCmd set for direct use.
522func FindExecCmd() []string {
523	if ExecCmd != nil {
524		return ExecCmd
525	}
526	ExecCmd = []string{} // avoid work the second time
527	if cfg.Goos == runtime.GOOS && cfg.Goarch == runtime.GOARCH {
528		return ExecCmd
529	}
530	path, err := exec.LookPath(fmt.Sprintf("go_%s_%s_exec", cfg.Goos, cfg.Goarch))
531	if err == nil {
532		ExecCmd = []string{path}
533	}
534	return ExecCmd
535}
536