diff --git a/src/cmd/go/build.go b/src/cmd/go/build.go index bdc350161a..c8a37b64d1 100644 --- a/src/cmd/go/build.go +++ b/src/cmd/go/build.go @@ -75,6 +75,8 @@ and test commands: -x print the commands. + -buildmode mode + build mode to use. See 'go help buildmodes' for more. -compiler name name of compiler to use, as in runtime.Compiler (gccgo or gc). -gccgoflags 'arg list' @@ -85,7 +87,8 @@ and test commands: a suffix to use in the name of the package installation directory, in order to keep output separate from default builds. If using the -race flag, the install suffix is automatically set to race - or, if set explicitly, has _race appended to it. + or, if set explicitly, has _race appended to it. Using a -buildmode + option that requires non-default compile flags has a similar effect. -ldflags 'flag list' arguments to pass on each 5l, 6l, 8l, or 9l linker invocation. -asmflags 'flag list' @@ -145,6 +148,7 @@ var buildLdflags []string // -ldflags flag var buildGccgoflags []string // -gccgoflags flag var buildRace bool // -race flag var buildToolExec []string // -toolexec flag +var buildBuildmode string // -buildmode flag var buildContext = build.Default var buildToolchain toolchain = noToolchain{} @@ -199,6 +203,7 @@ func addBuildFlags(cmd *Command) { cmd.Flag.Var(buildCompiler{}, "compiler", "") cmd.Flag.BoolVar(&buildRace, "race", false, "") cmd.Flag.Var((*stringsFlag)(&buildToolExec), "toolexec", "") + cmd.Flag.StringVar(&buildBuildmode, "buildmode", "default", "") } func addBuildFlagsNX(cmd *Command) { @@ -273,8 +278,51 @@ func (v *stringsFlag) String() string { return "" } +var pkgFilter = func(p *Package) bool { return true } + +func buildModeInit() { + var codegenArg, ldBuildmode string + switch buildBuildmode { + case "archive": + pkgFilter = func(p *Package) bool { return p.Name != "main" } + case "c-shared": + pkgFilter = func(p *Package) bool { return p.Name == "main" } + platform := goos + "/" + goarch + switch platform { + case "linux/amd64": + case "android/arm": + default: + fmt.Fprintf(os.Stderr, "go %s: -buildmode=c-shared not supported on %s\n", platform) + os.Exit(2) + } + if goarch == "amd64" { + codegenArg = "-shared" + } + ldBuildmode = "c-shared" + case "default": + ldBuildmode = "exe" + case "exe": + pkgFilter = func(p *Package) bool { return p.Name == "main" } + ldBuildmode = "exe" + default: + fatalf("buildmode=%s not supported", buildBuildmode) + } + if ldBuildmode != "" { + buildLdflags = append(buildLdflags, "-buildmode="+ldBuildmode) + } + if codegenArg != "" { + buildAsmflags = append(buildAsmflags, codegenArg) + buildGcflags = append(buildGcflags, codegenArg) + if buildContext.InstallSuffix != "" { + buildContext.InstallSuffix += "_" + } + buildContext.InstallSuffix += codegenArg[1:] + } +} + func runBuild(cmd *Command, args []string) { raceInit() + buildModeInit() var b builder b.init() @@ -321,7 +369,9 @@ func runBuild(cmd *Command, args []string) { a := &action{} for _, p := range packages(args) { - a.deps = append(a.deps, b.action(modeBuild, depMode, p)) + if pkgFilter(p) { + a.deps = append(a.deps, b.action(modeBuild, depMode, p)) + } } b.do(a) } @@ -362,6 +412,9 @@ func runInstall(cmd *Command, args []string) { a := &action{} var tools []*action for _, p := range pkgs { + if !pkgFilter(p) { + continue + } // If p is a tool, delay the installation until the end of the build. // This avoids installing assemblers/compilers that are being executed // by other steps in the build. diff --git a/src/cmd/go/doc.go b/src/cmd/go/doc.go index 58905d913f..95b8094a67 100644 --- a/src/cmd/go/doc.go +++ b/src/cmd/go/doc.go @@ -34,6 +34,7 @@ Use "go help [command]" for more information about a command. Additional help topics: c calling between Go and C + buildmode description of build modes filetype file types gopath GOPATH environment variable importpath import path syntax @@ -94,6 +95,8 @@ and test commands: -x print the commands. + -buildmode mode + build mode to use. See 'go help buildmodes' for more. -compiler name name of compiler to use, as in runtime.Compiler (gccgo or gc). -gccgoflags 'arg list' @@ -104,7 +107,8 @@ and test commands: a suffix to use in the name of the package installation directory, in order to keep output separate from default builds. If using the -race flag, the install suffix is automatically set to race - or, if set explicitly, has _race appended to it. + or, if set explicitly, has _race appended to it. Using a -buildmode + option that requires non-default compile flags has a similar effect. -ldflags 'flag list' arguments to pass on each 5l, 6l, 8l, or 9l linker invocation. -asmflags 'flag list' @@ -640,6 +644,32 @@ compiler. The CC or CXX environment variables may be set to determine the C or C++ compiler, respectively, to use. +Description of build modes + +The 'go build' and 'go install' commands take a -buildmode argument which +indicates which kind of object file is to be built. Currently supported values +are: + + -buildmode=archive + Build the listed non-main packages into .a files. Packages named + main are ignored. + + -buildmode=c-shared + Build the listed main packages, plus all packages that they + import, into C shared libraries. The only callable symbols will + be those functions marked as exported. Non-main packages are + ignored. + + -buildmode=default + Listed main packages are built into executables and listed + non-main packages are built into .a files (the default + behavior). + + -buildmode=exe + Build the listed main packages and everything they import into + executables. Packages not named main are ignored. + + File types The go command examines the contents of a restricted set of files diff --git a/src/cmd/go/help.go b/src/cmd/go/help.go index 2ab0353589..dafebd0141 100644 --- a/src/cmd/go/help.go +++ b/src/cmd/go/help.go @@ -363,3 +363,32 @@ at the first item in the file that is not a blank line or //-style line comment. `, } + +var helpBuildmode = &Command{ + UsageLine: "buildmode", + Short: "description of build modes", + Long: ` +The 'go build' and 'go install' commands take a -buildmode argument which +indicates which kind of object file is to be built. Currently supported values +are: + + -buildmode=archive + Build the listed non-main packages into .a files. Packages named + main are ignored. + + -buildmode=c-shared + Build the listed main packages, plus all packages that they + import, into C shared libraries. The only callable symbols will + be those functions marked as exported. Non-main packages are + ignored. + + -buildmode=default + Listed main packages are built into executables and listed + non-main packages are built into .a files (the default + behavior). + + -buildmode=exe + Build the listed main packages and everything they import into + executables. Packages not named main are ignored. +`, +} diff --git a/src/cmd/go/main.go b/src/cmd/go/main.go index 5e0ab79df3..df57575946 100644 --- a/src/cmd/go/main.go +++ b/src/cmd/go/main.go @@ -91,6 +91,7 @@ var commands = []*Command{ cmdVet, helpC, + helpBuildmode, helpFileType, helpGopath, helpImportPath,