gopherjs/gopherjs — pull request #38 by metakeule (2014-05-23 23:21:47+00:00)
Title: Code changes to let gopherjs be used as library

Regard issue gopherjs/gopherjs/#36 here is the code that makes gopherjs usable as a library.

There had to be some code movement, so I tried to do it in small steps.

# Goals have been:

- touch only tools.go file
- reuse existing code in tools.go
- don't change existing behavior
- smallest possible changes in existing code
- nice API for library usage

For the code changes in tools.go, there had been just made the following changes:

- extract code in functions / methods
- change parameters to be more explicit
- both only where needed to support the new API

Then two sub packages had been created:

jslib => contains the code that needs to be imported when using gopherjs as library
build => contains the shared code used by tools.go and jslib

# Usage

## Build from a single file

```go
package main

import (
"bytes"
"fmt"
"github.com/gopherjs/gopherjs/jslib"
"os"
"strings"
)

func main() {
var out bytes.Buffer

file := strings.NewReader(`
package main

import (
"github.com/gopherjs/gopherjs/js"
)

func main() {
println(js.Global.Get("window"))
}

`)

// since file and Target are io.Writers they may also be files or whatever
err := jslib.BuildFile(file, &jslib.Options{Target: &out})

if err != nil {
fmt.Fprintf(os.Stderr, "compile error: %s\n", err.Error())
os.Exit(1)
}

fmt.Println(out.String())
}
```

## Build from a directory

```go
package main

import (
"bytes"
"fmt"
"github.com/gopherjs/gopherjs/jslib"
"os"
)

func main() {
var out bytes.Buffer

// pass an existing package path here
err := jslib.BuildDir("github.com/gopherjs/gopherjs/example/pkg",
&jslib.Options{Target: &out},
)

if err != nil {
fmt.Fprintf(os.Stderr, "compile error: %s\n", err.Error())
os.Exit(1)
}
fmt.Println(out.String())
}
```

## Build from multiple files

```go
package main

import (
"bytes"
"fmt"
"github.com/gopherjs/gopherjs/jslib"
"os"
"strings"
)

func main() {
var out bytes.Buffer
builder, err := jslib.NewBuilder(&jslib.Options{Target: &out})
if err != nil {
fmt.Fprintf(os.Stderr, "can't create builder: %s\n", err.Error())
os.Exit(1)
}
file1 := strings.NewReader(`
package main

import (
"github.com/gopherjs/gopherjs/js"
)

func a() {
println(js.Global.Get("window"))
}

`)

err = builder.AddFile("a.go", file1)
if err != nil {
fmt.Fprintf(os.Stderr, "can't add a.go: %s\n", err.Error())
os.Exit(1)
}

file2 := strings.NewReader(`
package main

import (
"github.com/gopherjs/gopherjs/js"
)

func main() {
a()
println(js.Global.Get("document"))
}

`)
err = builder.AddFile("b.go", file2)
if err != nil {
fmt.Fprintf(os.Stderr, "can't add b.go: %s\n", err.Error())
os.Exit(1)
}

err = builder.Build()
if err != nil {
fmt.Fprintf(os.Stderr, "can't build: %s\n", err.Error())
os.Exit(1)
}

fmt.Println(out.String())
}
```

# Tests

only tested by hand at the moment. No sure how you want unit tests to be written in this case.
We may test if it compiles without and error but that doesn't mean much.