mirror of
https://github.com/golang/go
synced 2024-11-23 19:40:08 -07:00
cmd/go: support -buildmode=shared
You can now do 'go install -buildmode=shared std' and get yourself a nice (33 meg) libstd.so (which is not useful until there is -linkshared support as well, of course). Change-Id: Ie9b7e7f72abc7d369a6e3ecc98903a9d197bd6e6 Reviewed-on: https://go-review.googlesource.com/8300 Run-TryBot: Ian Lance Taylor <iant@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Ian Lance Taylor <iant@golang.org>
This commit is contained in:
parent
6e83ef6d21
commit
725cd2ea72
@ -326,9 +326,8 @@ func buildModeInit() {
|
|||||||
switch platform {
|
switch platform {
|
||||||
case "linux/amd64":
|
case "linux/amd64":
|
||||||
codegenArg = "-shared"
|
codegenArg = "-shared"
|
||||||
buildGcflags = append(buildGcflags, codegenArg)
|
|
||||||
case "linux/arm":
|
case "linux/arm":
|
||||||
codegenArg = "-shared"
|
buildAsmflags = append(buildAsmflags, "-shared")
|
||||||
case "android/arm":
|
case "android/arm":
|
||||||
default:
|
default:
|
||||||
fatalf("-buildmode=c-shared not supported on %s\n", platform)
|
fatalf("-buildmode=c-shared not supported on %s\n", platform)
|
||||||
@ -339,6 +338,18 @@ func buildModeInit() {
|
|||||||
case "exe":
|
case "exe":
|
||||||
pkgsFilter = pkgsMain
|
pkgsFilter = pkgsMain
|
||||||
ldBuildmode = "exe"
|
ldBuildmode = "exe"
|
||||||
|
case "shared":
|
||||||
|
pkgsFilter = pkgsNotMain
|
||||||
|
switch platform {
|
||||||
|
case "linux/amd64":
|
||||||
|
default:
|
||||||
|
fatalf("-buildmode=shared not supported on %s\n", platform)
|
||||||
|
}
|
||||||
|
if *buildO != "" {
|
||||||
|
fatalf("-buildmode=shared and -o not supported together")
|
||||||
|
}
|
||||||
|
codegenArg = "-dynlink"
|
||||||
|
ldBuildmode = "shared"
|
||||||
default:
|
default:
|
||||||
fatalf("buildmode=%s not supported", buildBuildmode)
|
fatalf("buildmode=%s not supported", buildBuildmode)
|
||||||
}
|
}
|
||||||
@ -348,7 +359,6 @@ func buildModeInit() {
|
|||||||
os.Exit(2)
|
os.Exit(2)
|
||||||
}
|
}
|
||||||
codegenArg = "-dynlink"
|
codegenArg = "-dynlink"
|
||||||
buildGcflags = append(buildGcflags, codegenArg)
|
|
||||||
// TODO(mwhudson): remove -w when that gets fixed in linker.
|
// TODO(mwhudson): remove -w when that gets fixed in linker.
|
||||||
buildLdflags = append(buildLdflags, "-linkshared", "-w")
|
buildLdflags = append(buildLdflags, "-linkshared", "-w")
|
||||||
}
|
}
|
||||||
@ -357,6 +367,7 @@ func buildModeInit() {
|
|||||||
}
|
}
|
||||||
if codegenArg != "" {
|
if codegenArg != "" {
|
||||||
buildAsmflags = append(buildAsmflags, codegenArg)
|
buildAsmflags = append(buildAsmflags, codegenArg)
|
||||||
|
buildGcflags = append(buildGcflags, codegenArg)
|
||||||
if buildContext.InstallSuffix != "" {
|
if buildContext.InstallSuffix != "" {
|
||||||
buildContext.InstallSuffix += "_"
|
buildContext.InstallSuffix += "_"
|
||||||
}
|
}
|
||||||
@ -393,6 +404,7 @@ func runBuild(cmd *Command, args []string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
depMode := modeBuild
|
depMode := modeBuild
|
||||||
|
mode := modeBuild
|
||||||
if buildI {
|
if buildI {
|
||||||
depMode = modeInstall
|
depMode = modeInstall
|
||||||
}
|
}
|
||||||
@ -411,9 +423,15 @@ func runBuild(cmd *Command, args []string) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
a := &action{}
|
var a *action
|
||||||
|
if buildBuildmode == "shared" {
|
||||||
|
a = b.libaction(libname(args))
|
||||||
|
mode = depMode
|
||||||
|
} else {
|
||||||
|
a = &action{}
|
||||||
|
}
|
||||||
for _, p := range pkgsFilter(packages(args)) {
|
for _, p := range pkgsFilter(packages(args)) {
|
||||||
a.deps = append(a.deps, b.action(modeBuild, depMode, p))
|
a.deps = append(a.deps, b.action(mode, depMode, p))
|
||||||
}
|
}
|
||||||
b.do(a)
|
b.do(a)
|
||||||
}
|
}
|
||||||
@ -432,8 +450,33 @@ See also: go build, go get, go clean.
|
|||||||
`,
|
`,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// libname returns the filename to use for the shared library when using
|
||||||
|
// -buildmode=shared. The rules we use are:
|
||||||
|
// 1) Drop any trailing "/..."s if present
|
||||||
|
// 2) Change / to -
|
||||||
|
// 3) Join arguments with ,
|
||||||
|
// So std -> libstd.so
|
||||||
|
// a b/... -> liba,b.so
|
||||||
|
// gopkg.in/tomb.v2 -> libgopkg.in-tomb.v2.so
|
||||||
|
func libname(args []string) string {
|
||||||
|
var libname string
|
||||||
|
for _, arg := range args {
|
||||||
|
arg = strings.TrimSuffix(arg, "/...")
|
||||||
|
arg = strings.Replace(arg, "/", "-", -1)
|
||||||
|
if libname == "" {
|
||||||
|
libname = arg
|
||||||
|
} else {
|
||||||
|
libname += "," + arg
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// TODO(mwhudson): Needs to change for platforms that use different naming
|
||||||
|
// conventions...
|
||||||
|
return "lib" + libname + ".so"
|
||||||
|
}
|
||||||
|
|
||||||
func runInstall(cmd *Command, args []string) {
|
func runInstall(cmd *Command, args []string) {
|
||||||
raceInit()
|
raceInit()
|
||||||
|
buildModeInit()
|
||||||
pkgs := pkgsFilter(packagesForBuild(args))
|
pkgs := pkgsFilter(packagesForBuild(args))
|
||||||
|
|
||||||
for _, p := range pkgs {
|
for _, p := range pkgs {
|
||||||
@ -452,25 +495,54 @@ func runInstall(cmd *Command, args []string) {
|
|||||||
var b builder
|
var b builder
|
||||||
b.init()
|
b.init()
|
||||||
a := &action{}
|
a := &action{}
|
||||||
var tools []*action
|
if buildBuildmode == "shared" {
|
||||||
for _, p := range pkgs {
|
var libdir string
|
||||||
// If p is a tool, delay the installation until the end of the build.
|
for _, p := range pkgs {
|
||||||
// This avoids installing assemblers/compilers that are being executed
|
plibdir := p.build.PkgTargetRoot
|
||||||
// by other steps in the build.
|
if libdir == "" {
|
||||||
// cmd/cgo is handled specially in b.action, so that we can
|
libdir = plibdir
|
||||||
// both build and use it in the same 'go install'.
|
} else if libdir != plibdir {
|
||||||
action := b.action(modeInstall, modeInstall, p)
|
fatalf("multiple roots %s & %s", libdir, plibdir)
|
||||||
if goTools[p.ImportPath] == toTool && p.ImportPath != "cmd/cgo" {
|
}
|
||||||
a.deps = append(a.deps, action.deps...)
|
|
||||||
action.deps = append(action.deps, a)
|
|
||||||
tools = append(tools, action)
|
|
||||||
continue
|
|
||||||
}
|
}
|
||||||
a.deps = append(a.deps, action)
|
|
||||||
}
|
a.f = (*builder).install
|
||||||
if len(tools) > 0 {
|
libfilename := libname(args)
|
||||||
a = &action{
|
linkSharedAction := b.libaction(libfilename)
|
||||||
deps: tools,
|
a.target = filepath.Join(libdir, libfilename)
|
||||||
|
a.deps = append(a.deps, linkSharedAction)
|
||||||
|
for _, p := range pkgs {
|
||||||
|
if p.target == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
shlibnameaction := &action{}
|
||||||
|
shlibnameaction.f = (*builder).installShlibname
|
||||||
|
shlibnameaction.target = p.target[:len(p.target)-2] + ".shlibname"
|
||||||
|
a.deps = append(a.deps, shlibnameaction)
|
||||||
|
shlibnameaction.deps = append(shlibnameaction.deps, linkSharedAction)
|
||||||
|
linkSharedAction.deps = append(linkSharedAction.deps, b.action(modeInstall, modeInstall, p))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
var tools []*action
|
||||||
|
for _, p := range pkgs {
|
||||||
|
// 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.
|
||||||
|
// cmd/cgo is handled specially in b.action, so that we can
|
||||||
|
// both build and use it in the same 'go install'.
|
||||||
|
action := b.action(modeInstall, modeInstall, p)
|
||||||
|
if goTools[p.ImportPath] == toTool && p.ImportPath != "cmd/cgo" {
|
||||||
|
a.deps = append(a.deps, action.deps...)
|
||||||
|
action.deps = append(action.deps, a)
|
||||||
|
tools = append(tools, action)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
a.deps = append(a.deps, action)
|
||||||
|
}
|
||||||
|
if len(tools) > 0 {
|
||||||
|
a = &action{
|
||||||
|
deps: tools,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
b.do(a)
|
b.do(a)
|
||||||
@ -769,6 +841,13 @@ func (b *builder) action(mode buildMode, depMode buildMode, p *Package) *action
|
|||||||
return a
|
return a
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (b *builder) libaction(libname string) *action {
|
||||||
|
a := &action{}
|
||||||
|
a.f = (*builder).linkShared
|
||||||
|
a.target = filepath.Join(b.work, libname)
|
||||||
|
return a
|
||||||
|
}
|
||||||
|
|
||||||
// actionList returns the list of actions in the dag rooted at root
|
// actionList returns the list of actions in the dag rooted at root
|
||||||
// as visited in a depth-first post-order traversal.
|
// as visited in a depth-first post-order traversal.
|
||||||
func actionList(root *action) []*action {
|
func actionList(root *action) []*action {
|
||||||
@ -1188,6 +1267,34 @@ func (b *builder) getPkgConfigFlags(p *Package) (cflags, ldflags []string, err e
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (b *builder) installShlibname(a *action) error {
|
||||||
|
a1 := a.deps[0]
|
||||||
|
err := ioutil.WriteFile(a.target, []byte(filepath.Base(a1.target)+"\n"), 0644)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if buildX {
|
||||||
|
b.showcmd("", "echo '%s' > %s # internal", filepath.Base(a1.target), a.target)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *builder) linkShared(a *action) (err error) {
|
||||||
|
// TODO(mwhudson): obvious copy pasting from gcToolchain.ld, should make a few
|
||||||
|
// changes to that function and then call it. And support gccgo.
|
||||||
|
allactions := actionList(a)
|
||||||
|
importArgs := b.includeArgs("-L", allactions[:len(allactions)-1])
|
||||||
|
// TODO(mwhudson): this does not check for cxx-ness, extldflags etc
|
||||||
|
ldflags := []string{"-installsuffix", buildContext.InstallSuffix}
|
||||||
|
ldflags = append(ldflags, buildLdflags...)
|
||||||
|
for _, d := range a.deps {
|
||||||
|
if d.target != "" { // omit unsafe etc
|
||||||
|
ldflags = append(ldflags, d.p.ImportPath+"="+d.target)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return b.run(".", a.target, nil, buildToolExec, tool(archChar()+"l"), "-o", a.target, importArgs, ldflags)
|
||||||
|
}
|
||||||
|
|
||||||
// install is the action for installing a single package or executable.
|
// install is the action for installing a single package or executable.
|
||||||
func (b *builder) install(a *action) (err error) {
|
func (b *builder) install(a *action) (err error) {
|
||||||
defer func() {
|
defer func() {
|
||||||
|
@ -674,6 +674,11 @@ are:
|
|||||||
non-main packages are built into .a files (the default
|
non-main packages are built into .a files (the default
|
||||||
behavior).
|
behavior).
|
||||||
|
|
||||||
|
-buildmode=shared
|
||||||
|
Combine all the listed non-main packages into a single shared
|
||||||
|
library that will be used when building with the -linkshared
|
||||||
|
option. Packages named main are ignored.
|
||||||
|
|
||||||
-buildmode=exe
|
-buildmode=exe
|
||||||
Build the listed main packages and everything they import into
|
Build the listed main packages and everything they import into
|
||||||
executables. Packages not named main are ignored.
|
executables. Packages not named main are ignored.
|
||||||
|
@ -393,6 +393,11 @@ are:
|
|||||||
non-main packages are built into .a files (the default
|
non-main packages are built into .a files (the default
|
||||||
behavior).
|
behavior).
|
||||||
|
|
||||||
|
-buildmode=shared
|
||||||
|
Combine all the listed non-main packages into a single shared
|
||||||
|
library that will be used when building with the -linkshared
|
||||||
|
option. Packages named main are ignored.
|
||||||
|
|
||||||
-buildmode=exe
|
-buildmode=exe
|
||||||
Build the listed main packages and everything they import into
|
Build the listed main packages and everything they import into
|
||||||
executables. Packages not named main are ignored.
|
executables. Packages not named main are ignored.
|
||||||
|
Loading…
Reference in New Issue
Block a user