Skip to content

Commit 34c2546

Browse files
committed
Comments and README for multibuild
1 parent cd4e6fe commit 34c2546

File tree

3 files changed

+55
-25
lines changed

3 files changed

+55
-25
lines changed

README.md

+9-5
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,24 @@
11
# pluggo
22
Golang compile-time, in-process plugin framework
33

4+
[![GoDoc](https://godoc.org/github.com/CAFxX/pluggo?status.svg)](https://godoc.org/github.com/CAFxX/pluggo)
5+
46
## Purpose
57
Pluggo allows you to define interface-based extension points in your code, so
68
that users of your code can plug in their modifications at compile time while
79
keeping the application code and plugin code in completely separated packages
8-
and repositories. Compared to RPC/IPC approaches, plugins using this framework
9-
run in the same process as the application, with no IPC/RPC overhead.
10+
and repositories.
11+
12+
Compared to RPC/IPC approaches, plugins using this framework run in the same
13+
process as the application with no IPC/RPC overhead.
1014

1115
## How it works
1216
Similarly as how `database/sql` drivers registers themselves: there's a
1317
"extension point registry" (just a `map[string]func() interface{}`) where
1418
plugins `Register` their factories for the appropriate extension points.
1519
Application code at each extension point requests to the registry instances of
1620
the plugin using `Get`. Application and plugins are then compiled and linked
17-
together in the same executable with the `multibuild` tool.
21+
together in the same executable with the `[multibuild](cmd/multibuild)` tool.
1822

1923
## Examples
2024

@@ -73,8 +77,8 @@ packages (the plugins).
7377
$ multibuild appMainPkg pluginPkg1 pluginPkg2 ...
7478
```
7579

76-
You can have a look at the [sample](sample/README.md) directory for a
77-
ready-to-run example.
80+
You can have a look at the [sample](sample) directory for a ready-to-run
81+
example.
7882

7983
### Factory pattern
8084

cmd/multibuild/README.md

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# multibuild
2+
A small tool to build and link together multiple go packages
3+
4+
## Purpose
5+
This tool was designed to work with [pluggo](../..), to perform linking of
6+
plugins with the application/library they're intended for.
7+
8+
It can also be used in other cases, where you're importing a package only for
9+
its side-effects, e.g.:
10+
11+
- To link additional `database/sql` drivers
12+
- To link `pprof` at compile-time
13+
- ...

cmd/multibuild/multibuild.go

+33-20
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import (
55
"fmt"
66
"go/build"
77
"io/ioutil"
8-
"log"
98
"os"
109
"os/exec"
1110

@@ -22,42 +21,56 @@ func usage() {
2221
fmt.Println("The resulting build will have the package name of <mainPkg>")
2322
}
2423

25-
func main() {
26-
flag.Usage = usage
27-
flag.Parse()
28-
29-
if len(flag.Args()) == 0 {
30-
fmt.Println("missing arguments")
31-
usage()
32-
os.Exit(-1)
33-
}
34-
35-
pkgs := gotool.ImportPaths(flag.Args())
24+
func multibuild(packages []string) (error, int) {
25+
// parse the names of the paths/packages provided on the command-line
26+
pkgs := gotool.ImportPaths(packages)
3627

28+
// parse the main package: we need the package name and the path
3729
mainpkg, err := build.Import(pkgs[0], ".", 0)
3830
if err != nil {
39-
log.Printf("unable to import main package %s: %s", pkgs[0], err)
40-
os.Exit(-2)
31+
return fmt.Errorf("unable to import main package %s: %s", pkgs[0], err), -2
4132
}
4233

34+
// create the linker file in the main package directory, so that it will be
35+
// compiled and linked with the main package when we `go build` is invoked
36+
// the linker file is a go file in the same package of the main package that
37+
// imports all additional packages (normally for their side-effects)
4338
tmpFile, err := ioutil.TempFile(mainpkg.Dir, "pluggo")
4439
if err != nil {
45-
log.Printf("unable to create temporary file: %s", err)
46-
os.Exit(-3)
40+
return fmt.Errorf("unable to create temporary file: %s", err), -3
4741
}
4842

4943
fmt.Fprintf(tmpFile, "package %s\n", mainpkg.Name)
50-
for _, pkgname := range os.Args[2:] {
44+
for _, pkgname := range pkgs[1:] {
5145
fmt.Fprintf(tmpFile, "import _ \"%s\"\n", pkgname)
5246
}
5347

5448
tmpFile.Close()
5549
os.Rename(tmpFile.Name(), tmpFile.Name()+".go")
5650
defer os.Remove(tmpFile.Name() + ".go")
5751

58-
output, err := exec.Command("go", "build", flag.Args()[0]).CombinedOutput()
52+
// run go build on the main package
53+
output, err := exec.Command("go", "build", packages[0]).CombinedOutput()
54+
if err != nil {
55+
return fmt.Errorf("error executing go build: %s\ngo build output:\n%s", err, string(output)), -4
56+
}
57+
58+
return nil, 0
59+
}
60+
61+
func main() {
62+
flag.Usage = usage
63+
flag.Parse()
64+
65+
if len(flag.Args()) == 0 {
66+
fmt.Println("missing arguments")
67+
usage()
68+
os.Exit(-1)
69+
}
70+
71+
err, rv := multibuild(flag.Args())
5972
if err != nil {
60-
fmt.Print(string(output))
61-
os.Exit(-4)
73+
fmt.Println(err)
74+
os.Exit(rv)
6275
}
6376
}

0 commit comments

Comments
 (0)