// Copyright 2017 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Build initialization (after flag parsing). package work import ( "cmd/go/internal/base" "cmd/go/internal/cfg" "cmd/go/internal/load" "cmd/internal/sys" "flag" "fmt" "os" "path/filepath" "strings" ) func BuildInit() { load.ModInit() instrumentInit() buildModeInit() // Make sure -pkgdir is absolute, because we run commands // in different directories. if cfg.BuildPkgdir != "" && !filepath.IsAbs(cfg.BuildPkgdir) { p, err := filepath.Abs(cfg.BuildPkgdir) if err != nil { fmt.Fprintf(os.Stderr, "go %s: evaluating -pkgdir: %v\n", flag.Args()[0], err) base.SetExitStatus(2) base.Exit() } cfg.BuildPkgdir = p } } func instrumentInit() { if !cfg.BuildRace && !cfg.BuildMSan { return } if cfg.BuildRace && cfg.BuildMSan { fmt.Fprintf(os.Stderr, "go %s: may not use -race and -msan simultaneously\n", flag.Args()[0]) base.SetExitStatus(2) base.Exit() } if cfg.BuildMSan && !sys.MSanSupported(cfg.Goos, cfg.Goarch) { fmt.Fprintf(os.Stderr, "-msan is not supported on %s/%s\n", cfg.Goos, cfg.Goarch) base.SetExitStatus(2) base.Exit() } if cfg.BuildRace { if !sys.RaceDetectorSupported(cfg.Goos, cfg.Goarch) { fmt.Fprintf(os.Stderr, "go %s: -race is only supported on linux/amd64, linux/ppc64le, linux/arm64, freebsd/amd64, netbsd/amd64, darwin/amd64 and windows/amd64\n", flag.Args()[0]) base.SetExitStatus(2) base.Exit() } } mode := "race" if cfg.BuildMSan { mode = "msan" } modeFlag := "-" + mode if !cfg.BuildContext.CgoEnabled { fmt.Fprintf(os.Stderr, "go %s: %s requires cgo; enable cgo by setting CGO_ENABLED=1\n", flag.Args()[0], modeFlag) base.SetExitStatus(2) base.Exit() } forcedGcflags = append(forcedGcflags, modeFlag) forcedLdflags = append(forcedLdflags, modeFlag) if cfg.BuildContext.InstallSuffix != "" { cfg.BuildContext.InstallSuffix += "_" } cfg.BuildContext.InstallSuffix += mode cfg.BuildContext.BuildTags = append(cfg.BuildContext.BuildTags, mode) } func buildModeInit() { gccgo := cfg.BuildToolchainName == "gccgo" var codegenArg string platform := cfg.Goos + "/" + cfg.Goarch switch cfg.BuildBuildmode { case "archive": pkgsFilter = pkgsNotMain case "c-archive": pkgsFilter = oneMainPkg if gccgo { codegenArg = "-fPIC" } else { switch platform { case "darwin/arm", "darwin/arm64": codegenArg = "-shared" default: switch cfg.Goos { case "dragonfly", "freebsd", "illumos", "linux", "netbsd", "openbsd", "solaris": if platform == "linux/ppc64" { base.Fatalf("-buildmode=c-archive not supported on %s\n", platform) } // Use -shared so that the result is // suitable for inclusion in a PIE or // shared library. codegenArg = "-shared" } } } cfg.ExeSuffix = ".a" ldBuildmode = "c-archive" case "c-shared": pkgsFilter = oneMainPkg if gccgo { codegenArg = "-fPIC" } else { switch platform { case "linux/amd64", "linux/arm", "linux/arm64", "linux/386", "linux/ppc64le", "linux/s390x", "android/amd64", "android/arm", "android/arm64", "android/386", "freebsd/amd64": codegenArg = "-shared" case "darwin/amd64", "darwin/386": case "windows/amd64", "windows/386": // Do not add usual .exe suffix to the .dll file. cfg.ExeSuffix = "" default: base.Fatalf("-buildmode=c-shared not supported on %s\n", platform) } } ldBuildmode = "c-shared" case "default": switch platform { case "android/arm", "android/arm64", "android/amd64", "android/386": codegenArg = "-shared" ldBuildmode = "pie" case "darwin/arm", "darwin/arm64": codegenArg = "-shared" fallthrough default: ldBuildmode = "exe" } if gccgo { codegenArg = "" } case "exe": pkgsFilter = pkgsMain ldBuildmode = "exe" // Set the pkgsFilter to oneMainPkg if the user passed a specific binary output // and is using buildmode=exe for a better error message. // See issue #20017. if cfg.BuildO != "" { pkgsFilter = oneMainPkg } case "pie": if cfg.BuildRace { base.Fatalf("-buildmode=pie not supported when -race is enabled") } if gccgo { codegenArg = "-fPIE" } else { switch platform { case "linux/386", "linux/amd64", "linux/arm", "linux/arm64", "linux/ppc64le", "linux/s390x", "android/amd64", "android/arm", "android/arm64", "android/386", "freebsd/amd64": codegenArg = "-shared" case "darwin/amd64": codegenArg = "-shared" case "aix/ppc64": default: base.Fatalf("-buildmode=pie not supported on %s\n", platform) } } ldBuildmode = "pie" case "shared": pkgsFilter = pkgsNotMain if gccgo { codegenArg = "-fPIC" } else { switch platform { case "linux/386", "linux/amd64", "linux/arm", "linux/arm64", "linux/ppc64le", "linux/s390x": default: base.Fatalf("-buildmode=shared not supported on %s\n", platform) } codegenArg = "-dynlink" } if cfg.BuildO != "" { base.Fatalf("-buildmode=shared and -o not supported together") } ldBuildmode = "shared" case "plugin": pkgsFilter = oneMainPkg if gccgo { codegenArg = "-fPIC" } else { switch platform { case "linux/amd64", "linux/arm", "linux/arm64", "linux/386", "linux/s390x", "linux/ppc64le", "android/amd64", "android/arm", "android/arm64", "android/386": case "darwin/amd64": // Skip DWARF generation due to #21647 forcedLdflags = append(forcedLdflags, "-w") default: base.Fatalf("-buildmode=plugin not supported on %s\n", platform) } codegenArg = "-dynlink" } cfg.ExeSuffix = ".so" ldBuildmode = "plugin" default: base.Fatalf("buildmode=%s not supported", cfg.BuildBuildmode) } if cfg.BuildLinkshared { if gccgo { codegenArg = "-fPIC" } else { switch platform { case "linux/386", "linux/amd64", "linux/arm", "linux/arm64", "linux/ppc64le", "linux/s390x": forcedAsmflags = append(forcedAsmflags, "-D=GOBUILDMODE_shared=1") default: base.Fatalf("-linkshared not supported on %s\n", platform) } codegenArg = "-dynlink" // TODO(mwhudson): remove -w when that gets fixed in linker. forcedLdflags = append(forcedLdflags, "-linkshared", "-w") } } if codegenArg != "" { if gccgo { forcedGccgoflags = append([]string{codegenArg}, forcedGccgoflags...) } else { forcedAsmflags = append([]string{codegenArg}, forcedAsmflags...) forcedGcflags = append([]string{codegenArg}, forcedGcflags...) } // Don't alter InstallSuffix when modifying default codegen args. if cfg.BuildBuildmode != "default" || cfg.BuildLinkshared { if cfg.BuildContext.InstallSuffix != "" { cfg.BuildContext.InstallSuffix += "_" } cfg.BuildContext.InstallSuffix += codegenArg[1:] } } switch cfg.BuildMod { case "": // ok case "readonly", "vendor": if load.ModLookup == nil && !inGOFLAGS("-mod") { base.Fatalf("build flag -mod=%s only valid when using modules", cfg.BuildMod) } default: base.Fatalf("-mod=%s not supported (can be '', 'readonly', or 'vendor')", cfg.BuildMod) } } func inGOFLAGS(flag string) bool { for _, goflag := range base.GOFLAGS() { name := goflag if strings.HasPrefix(name, "--") { name = name[1:] } if i := strings.Index(name, "="); i >= 0 { name = name[:i] } if name == flag { return true } } return false }