Skip to content
This repository has been archived by the owner on Dec 14, 2023. It is now read-only.

Commit

Permalink
Merge pull request #90 from quarnster/test
Browse files Browse the repository at this point in the history
cmd/llgo-build: Add -test flag creating a test binary. For #48.
  • Loading branch information
axw committed Oct 5, 2013
2 parents de75e0c + 4ed1dbe commit 7cfde94
Show file tree
Hide file tree
Showing 4 changed files with 190 additions and 7 deletions.
23 changes: 22 additions & 1 deletion cmd/llgo-build/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,20 @@ func getPackage(pkgpath string) (pkg *build.Package, err error) {
}
pkg.GoFiles[i] = path.Join(pkgdir, filename)
}
for i, filename := range pkg.TestGoFiles {
pkgdir := pkg.Dir
if overlayentries[filename] {
pkgdir = overlaypkg.Dir
}
pkg.TestGoFiles[i] = path.Join(pkgdir, filename)
}
for i, filename := range pkg.XTestGoFiles {
pkgdir := pkg.Dir
if overlayentries[filename] {
pkgdir = overlaypkg.Dir
}
pkg.XTestGoFiles[i] = path.Join(pkgdir, filename)
}
for i, filename := range pkg.CFiles {
pkgdir := pkg.Dir
if overlayentries[filename] {
Expand Down Expand Up @@ -191,7 +205,7 @@ func buildPackages(pkgpaths []string) error {
func buildPackage(pkg *build.Package, output string) error {
args := []string{"-c", "-triple", triple}
dir, file := path.Split(pkg.ImportPath)
if pkg.IsCommand() {
if pkg.IsCommand() || test {
if output == "" {
output = file
}
Expand All @@ -211,6 +225,9 @@ func buildPackage(pkg *build.Package, output string) error {
tempfile := path.Join(workdir, file+".bc")
args = append(args, "-o", tempfile)
args = append(args, pkg.GoFiles...)
if test {
args = append(args, pkg.TestGoFiles...)
}
cmd := exec.Command("llgo", args...)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
Expand Down Expand Up @@ -271,6 +288,10 @@ func buildPackage(pkg *build.Package, output string) error {
if err != nil {
return err
}
} else if test {
if err = linktest(pkg, tempfile); err != nil {
return err
}
}
return moveFile(tempfile, output)
}
21 changes: 16 additions & 5 deletions cmd/llgo-build/link.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,16 @@ func linkdeps(pkg *build.Package, output string) error {
deps["runtime"] = true
deps["unsafe"] = true

var mkdeps func(pkg *build.Package) error
mkdeps = func(pkg *build.Package) error {
for _, path := range pkg.Imports {
var mkdeps func(pkg *build.Package, imports []string) error
mkdeps = func(pkg *build.Package, imports []string) error {
for _, path := range imports {
if !deps[path] {
deps[path] = true
pkg, err := build.Import(path, "", 0)
if err != nil {
return err
}
if err = mkdeps(pkg); err != nil {
if err = mkdeps(pkg, pkg.Imports); err != nil {
return err
}
depslist = append(depslist, path)
Expand All @@ -37,10 +37,18 @@ func linkdeps(pkg *build.Package, output string) error {
return nil
}

err := mkdeps(pkg)
err := mkdeps(pkg, pkg.Imports)
if err != nil {
return err
}
if test {
if err = mkdeps(pkg, pkg.TestImports); err != nil {
return err
}
if err = mkdeps(pkg, pkg.XTestImports); err != nil {
return err
}
}

for i := 0; i < len(depslist)/2; i++ {
j := len(depslist) - i - 1
Expand All @@ -50,6 +58,9 @@ func linkdeps(pkg *build.Package, output string) error {
llvmlink := filepath.Join(llvmbindir, "llvm-link")
args := []string{"-o", output, output}
for _, path := range depslist {
if path == pkg.ImportPath {
continue
}
bcfile := filepath.Join(pkgroot, path+".bc")
if buildDeps {
if _, err := os.Stat(bcfile); err != nil {
Expand Down
14 changes: 13 additions & 1 deletion cmd/llgo-build/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ package main

import (
"flag"
"fmt"
llgobuild "github.com/axw/llgo/build"
"go/build"
"io/ioutil"
Expand All @@ -28,6 +29,7 @@ var (
emitllvm bool
buildctx *build.Context
workdir string
test bool
buildDeps bool = true
)

Expand All @@ -37,6 +39,7 @@ func init() {
flag.StringVar(&output, "o", "", "Output file")
flag.BoolVar(&emitllvm, "emit-llvm", false, "Emit LLVM bitcode instead of a native binary")
flag.BoolVar(&printcommands, "x", false, "Print the commands")
flag.BoolVar(&test, "test", test, "When specified, the created output binary will be similar to what's output of \"go test -c\"")
flag.BoolVar(&buildDeps, "build-deps", buildDeps, "Whether to also build dependency packages or not")
}

Expand Down Expand Up @@ -71,7 +74,16 @@ func main() {
if err != nil {
log.Fatal(err)
}
err = buildPackages(flag.Args())
args := flag.Args()
if test {
if len(args) > 1 {
err = fmt.Errorf("Multiple files/packages can not be specified when building a test binary")
} else {
err = buildPackageTests(args[0])
}
} else {
err = buildPackages(args)
}
os.RemoveAll(workdir)
if err != nil {
log.Fatal(err)
Expand Down
139 changes: 139 additions & 0 deletions cmd/llgo-build/test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
package main

import (
"bytes"
"fmt"
"go/build"
"go/format"
"go/parser"
"go/token"
"io/ioutil"
"os"
"os/exec"
"path/filepath"
"strings"
)

func buildPackageTests(pkgpath string) error {
if strings.HasSuffix(pkgpath, ".go") {
return fmt.Errorf("-test needs a package path, not a .go file")
}
return buildPackages([]string{pkgpath})
}

func writeTestMain(pkg *build.Package, linkfile string) (err error) {
w := bytes.NewBuffer(nil)
tests := bytes.NewBuffer(nil)
fset := token.NewFileSet()

w.WriteString(`package main
import (
"testing"
`)

tests.WriteString("var tests = []testing.InternalTest{\n")

imports := make(map[string]bool)

addtests := func(pkgname string, gofiles []string) error {
for _, tf := range gofiles {
f, err := parser.ParseFile(fset, tf, nil, 0)
if err != nil {
return err
}
for k := range f.Scope.Objects {
if strings.HasPrefix(k, "Test") {
if !imports[pkgname] {
w.WriteString(fmt.Sprintf("\t\"%s\"\n", pkgname))
imports[pkgname] = true
}
tests.WriteString(fmt.Sprintf("\t{\"%s\", %s.%s},\n", k, pkgname, k))
}
}
}
return nil
}
if err = addtests(pkg.Name, pkg.TestGoFiles); err != nil {
return err
}
if err = addtests(pkg.Name+"_test", pkg.XTestGoFiles); err != nil {
return err
}
w.WriteString(")\n")
tests.WriteString("}\n")
w.Write(tests.Bytes())
w.WriteString(`
var benchmarks = []testing.InternalBenchmark{}
var examples = []testing.InternalExample{}
func matchString(pat, str string) (bool, error) {
return true, nil
}
func main() {
testing.Main(matchString, tests, benchmarks, examples)
}
`)
data, err := format.Source(w.Bytes())
if err != nil {
return err
}
gofile := filepath.Join(filepath.Dir(linkfile), "main.go")
if err = ioutil.WriteFile(gofile, data, 0644); err != nil {
return err
}

test_bc := ""
if len(pkg.XTestGoFiles) > 0 {
args2 := []string{"-c", "-triple", triple}
file := filepath.Base(linkfile)
file = file[:len(file)-3]
test_bc = filepath.Join(workdir, file+"_test.bc")
args2 = append(args2, "-o", test_bc)
args2 = append(args2, pkg.XTestGoFiles...)
cmd := exec.Command("llgo", args2...)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
err := runCmd(cmd)
if err != nil {
return err
}
}

mainbc := gofile[:len(gofile)-3] + ".bc"
args := []string{"-c", "-triple", triple, "-o", mainbc, gofile}
cmd := exec.Command("llgo", args...)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
err = runCmd(cmd)
if err != nil {
return err
}
llvmlink := filepath.Join(llvmbindir, "llvm-link")
args = []string{"-o", linkfile, linkfile, mainbc}
if test_bc != "" {
args = append(args, test_bc)
}

cmd = exec.Command(llvmlink, args...)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
if err = runCmd(cmd); err != nil {
return err
}

return nil
}

func linktest(pkg *build.Package, linkfile string) error {
if err := writeTestMain(pkg, linkfile); err != nil {
return err
}
if err := linkdeps(pkg, linkfile); err != nil {
return err
}
return nil
}

0 comments on commit 7cfde94

Please sign in to comment.