Skip to content

Instantly share code, notes, and snippets.

@knz
Created June 8, 2016 15:42
Show Gist options
  • Save knz/3e6d072d93b21b85399d56624d1305f0 to your computer and use it in GitHub Desktop.
Save knz/3e6d072d93b21b85399d56624d1305f0 to your computer and use it in GitHub Desktop.
cgo parallel build
--- src/cmd/go/build.go.orig 2016-06-08 15:34:08.613910443 +0000
+++ src/cmd/go/build.go 2016-06-08 15:38:07.317612174 +0000
@@ -694,6 +694,8 @@
exec sync.Mutex
readySema chan bool
ready actionQueue
+
+ tasks chan func()
}
// An action represents a single action in the action graph.
@@ -1236,6 +1238,7 @@
}
b.readySema = make(chan bool, len(all))
+ b.tasks = make(chan func(), buildP)
// Initialize per-action execution state.
for _, a := range all {
@@ -1312,6 +1315,8 @@
a := b.ready.pop()
b.exec.Unlock()
handle(a)
+ case task := <-b.tasks:
+ task()
case <-interrupted:
setExitStatus(1)
return
@@ -3141,12 +3146,16 @@
staticLibs = []string{"-Wl,--start-group", "-lmingwex", "-lmingw32", "-Wl,--end-group"}
}
+ var tasks []func()
+ var results chan error
+
cflags := stringList(cgoCPPFLAGS, cgoCFLAGS)
for _, cfile := range cfiles {
+ cfile := cfile
ofile := obj + cfile[:len(cfile)-1] + "o"
- if err := b.gcc(p, ofile, cflags, obj+cfile); err != nil {
- return nil, nil, err
- }
+ tasks = append(tasks, func() {
+ results <- b.gcc(p, ofile, cflags, obj+cfile)
+ })
linkobj = append(linkobj, ofile)
if !strings.HasSuffix(ofile, "_cgo_main.o") {
outObj = append(outObj, ofile)
@@ -3154,35 +3163,65 @@
}
for _, file := range gccfiles {
+ file := file
ofile := obj + cgoRe.ReplaceAllString(file[:len(file)-1], "_") + "o"
- if err := b.gcc(p, ofile, cflags, file); err != nil {
- return nil, nil, err
- }
+ tasks = append(tasks, func() {
+ results <- b.gcc(p, ofile, cflags, file)
+ })
linkobj = append(linkobj, ofile)
outObj = append(outObj, ofile)
}
cxxflags := stringList(cgoCPPFLAGS, cgoCXXFLAGS)
for _, file := range gxxfiles {
+ file := file
// Append .o to the file, just in case the pkg has file.c and file.cpp
ofile := obj + cgoRe.ReplaceAllString(file, "_") + ".o"
- if err := b.gxx(p, ofile, cxxflags, file); err != nil {
- return nil, nil, err
- }
+ tasks = append(tasks, func() {
+ results <- b.gxx(p, ofile, cxxflags, file)
+ })
linkobj = append(linkobj, ofile)
outObj = append(outObj, ofile)
}
for _, file := range mfiles {
+ file := file
// Append .o to the file, just in case the pkg has file.c and file.m
ofile := obj + cgoRe.ReplaceAllString(file, "_") + ".o"
- if err := b.gcc(p, ofile, cflags, file); err != nil {
- return nil, nil, err
- }
+ tasks = append(tasks, func() {
+ results <- b.gcc(p, ofile, cflags, file)
+ })
linkobj = append(linkobj, ofile)
outObj = append(outObj, ofile)
}
+ // Give the results channel enough capacity so that sending the
+ // result is guaranteed not to block.
+ results = make(chan error, len(tasks))
+
+ // Feed the tasks into the b.tasks channel on a separate goroutine
+ // because the b.tasks channel's limited capacity might cause
+ // sending the task to block.
+ go func() {
+ for _, task := range tasks {
+ b.tasks <- task
+ }
+ }()
+
+ // Loop until we've received results from all of our tasks or an
+ // error occurs.
+ for count := 0; count < len(tasks); {
+ select {
+ case err := <-results:
+ if err != nil {
+ return nil, nil, err
+ }
+ count++
+ case task := <-b.tasks:
+ task()
+ }
+ }
+
linkobj = append(linkobj, p.SysoFiles...)
dynobj := obj + "_cgo_.o"
pie := (goarch == "arm" && goos == "linux") || goos == "android"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment