Browse Source

Allow build to accept multiple entries in a .json; provide example usage at top level.

This is a first step to replacing BUILD. You can do this:
buil [-s regexp] build.json
e.g.

build -w k.* build.json

and it will build all k.* targets

Note that it's pretty stupid. It will do the same thing a few times, even though I think it should
not. Oops. Well, somebody fix it.

Change-Id: Icc7a790bcc5855b431d30334026ba4ff305a8bcb
Signed-off-by: Ronald G. Minnich <rminnich@gmail.com>
Ronald G. Minnich 8 years ago
parent
commit
0016425954
2 changed files with 131 additions and 56 deletions
  1. 16 0
      build.json
  2. 115 56
      util/src/harvey/cmd/build/build.go

+ 16 - 0
build.json

@@ -0,0 +1,16 @@
+{
+	"Name": "k8cpu",
+	"Projects": ["/sys/src/9/k10/k8cpu.json"]
+}
+{
+	"Name": "regress",
+	"Projects": ["/sys/src/regress/regress.json"]
+}
+{
+	"Name": "kregress",
+	"Projects": ["/sys/src/9/k10/k8cpu.json", "/sys/src/regress/regress.json"]
+}
+{
+	"Name": "kernels",
+	"Projects": ["/sys/src/9/k10/k8cpu.json"]
+}

+ 115 - 56
util/src/harvey/cmd/build/build.go

@@ -19,6 +19,7 @@ import (
 	"bytes"
 	"debug/elf"
 	"encoding/json"
+	"flag"
 	"fmt"
 	"io/ioutil"
 	"log"
@@ -26,6 +27,7 @@ import (
 	"os/exec"
 	"path"
 	"path/filepath"
+	"regexp"
 	"strings"
 	"text/template"
 )
@@ -87,6 +89,7 @@ var (
 	arch = map[string]bool{
 		"amd64": true,
 	}
+	which = flag.String("w", ".*", "Regexp defining which top level JSONs to process")
 )
 
 func fail(err error) {
@@ -108,60 +111,113 @@ func adjust(s []string) (r []string) {
 	}
 	return
 }
-func process(f string, b *build) {
+
+// send cmd to a shell
+func sh(cmd *exec.Cmd) {
+	shell := exec.Command(tools["sh"])
+	shell.Env = cmd.Env
+
+	commandString := strings.Join(cmd.Args, " ")
+	if shStdin, e := shell.StdinPipe(); e == nil {
+		go func() {
+			defer shStdin.Close()
+			io.WriteString(shStdin, commandString)
+		}()
+	} else {
+		log.Fatalf("cannot pipe [%v] to %s: %v", commandString, tools["sh"], e)
+	}
+	shell.Stderr = os.Stderr
+	shell.Stdout = os.Stdout
+
+	log.Printf("[%v]", commandString)
+	err := shell.Run()
+	failOn(err)
+}
+
+// run cmd preserving $LD_PRELOAD tricks
+func withPreloadTricks(cmd *exec.Cmd) {
+	if os.Getenv("LD_PRELOAD") != "" {
+		// we need a shell to enable $LD_PRELOAD tricks,
+		// see https://github.com/Harvey-OS/harvey/issues/8#issuecomment-131235178
+		sh(cmd)
+	} else {
+		cmd.Stdin = os.Stdin
+		cmd.Stderr = os.Stderr
+		cmd.Stdout = os.Stdout
+		log.Printf("%v", cmd.Args)
+		err := cmd.Run()
+		failOn(err)
+	}
+}
+
+func process(f, which string, b *build) {
+	r := regexp.MustCompile(which)
 	if b.jsons[f] {
 		return
 	}
 	log.Printf("Processing %v", f)
 	d, err := ioutil.ReadFile(f)
-	fail(err)
-	var build build
-	err = json.Unmarshal(d, &build)
-	fail(err)
-	b.jsons[f] = true
-
-	if len(b.jsons) == 1 {
-		cwd, err := os.Getwd()
-		if err != nil {
-			log.Fatalf("%v", err)
+	dec := json.NewDecoder(strings.NewReader(string(d)))
+	failOn(err)
+	var builds []build
+	for {
+		var b build
+		err := dec.Decode(&b)
+		if err == io.EOF {
+			break
 		}
-		b.path = path.Join(cwd, f)
-		b.Name = build.Name
-		b.Kernel = build.Kernel
-	}
-
-	b.SourceFiles = append(b.SourceFiles, build.SourceFiles...)
-	b.Cflags = append(b.Cflags, build.Cflags...)
-	b.Oflags = append(b.Oflags, build.Oflags...)
-	b.Pre = append(b.Pre, build.Pre...)
-	b.Post = append(b.Post, build.Post...)
-	b.Libs = append(b.Libs, adjust(build.Libs)...)
-	b.Projects = append(b.Projects, adjust(build.Projects)...)
-	b.Env = append(b.Env, build.Env...)
-	b.SourceFilesCmd = append(b.SourceFilesCmd, build.SourceFilesCmd...)
-	b.Program += build.Program
-	b.Library += build.Library
-	b.Install += build.Install
-
-	// For each source file, assume we create an object file with the last char replaced
-	// with 'o'. We can get smarter later.
-
-	for _, v := range build.SourceFiles {
-		f := path.Base(v)
-		o := f[:len(f)-1] + "o"
-		b.ObjectFiles = append(b.ObjectFiles, o)
+		failOn(err)
+		builds = append(builds, b)
 	}
+	for _, build := range builds {
+		log.Printf("Do %v", b.Name)
+		if !r.MatchString(build.Name) {
+			continue
+		}
+		b.jsons[f] = true
+
+		if len(b.jsons) == 1 {
+			cwd, err := os.Getwd()
+			failOn(err)
+
+			b.path = path.Join(cwd, f)
+			b.Name = build.Name
+			b.Kernel = build.Kernel
+		}
 
-	b.ObjectFiles = append(b.ObjectFiles, adjust(build.ObjectFiles)...)
+		b.SourceFiles = append(b.SourceFiles, build.SourceFiles...)
+		b.Cflags = append(b.Cflags, build.Cflags...)
+		b.Oflags = append(b.Oflags, build.Oflags...)
+		b.Pre = append(b.Pre, build.Pre...)
+		b.Post = append(b.Post, build.Post...)
+		b.Libs = append(b.Libs, adjust(build.Libs)...)
+		b.Projects = append(b.Projects, adjust(build.Projects)...)
+		b.Env = append(b.Env, build.Env...)
+		b.SourceFilesCmd = append(b.SourceFilesCmd, build.SourceFilesCmd...)
+		b.Program += build.Program
+		b.Library += build.Library
+		b.Install += build.Install
+		b.ObjectFiles = append(b.ObjectFiles, adjust(build.ObjectFiles)...)
+
+		includes := adjust(build.Include)
+		for _, v := range includes {
+			if !path.IsAbs(v) {
+				wd := path.Dir(f)
+				v = path.Join(wd, v)
+			}
+			process(v, ".*", b)
+		}
 
-	includes := adjust(build.Include)
-	for _, v := range includes {
-		if !path.IsAbs(v) {
-			wd := path.Dir(f)
-			v = path.Join(wd, v)
+		// For each source file, assume we create an object file with the last char replaced
+		// with 'o'. We can get smarter later.
+
+		for _, v := range build.SourceFiles {
+			f := path.Base(v)
+			o := f[:len(f)-1] + "o"
+			b.ObjectFiles = append(b.ObjectFiles, o)
 		}
-		process(v, b)
 	}
+
 }
 
 func compile(b *build) {
@@ -358,7 +414,7 @@ func projects(b *build) {
 		cwd, err := os.Getwd()
 		fail(err)
 		os.Chdir(wd)
-		project(f)
+		project(f, ".*")
 		os.Chdir(cwd)
 	}
 }
@@ -395,9 +451,10 @@ func data2c(name string, path string) (string, error) {
 	} else {
 		var file *os.File
 		var err error
-		if file, err = os.Open(path); err != nil {
-			log.Fatalf("%v", err)
-		}
+
+		file, err = os.Open(path)
+		failOn(err)
+
 		in, err = ioutil.ReadAll(file)
 		if err != nil {
 			log.Fatalf("%v\n", err)
@@ -561,10 +618,10 @@ func buildkernel(b *build) {
 }
 
 // assumes we are in the wd of the project.
-func project(root string) {
+func project(root, which string) {
 	b := &build{}
 	b.jsons = map[string]bool{}
-	process(root, b)
+	process(root, which, b)
 	projects(b)
 	run(b, b.Pre)
 	buildkernel(b)
@@ -592,12 +649,14 @@ func project(root string) {
 func main() {
 	var badsetup bool
 	var err error
+	flag.Parse()
 	cwd, err = os.Getwd()
 	fail(err)
 	harvey = os.Getenv("HARVEY")
-	if err := findTools(os.Getenv("TOOLPREFIX")); err != nil {
-		fail(err)
-	}
+
+	err = findTools(os.Getenv("TOOLPREFIX"))
+	failOn(err)
+
 	if harvey == "" {
 		log.Printf("You need to set the HARVEY environment variable")
 		badsetup = true
@@ -614,11 +673,11 @@ func main() {
 	if badsetup {
 		os.Exit(1)
 	}
-	dir := path.Dir(os.Args[1])
-	file := path.Base(os.Args[1])
+	dir := path.Dir(flag.Arg(0))
+	file := path.Base(flag.Arg(0))
 	err = os.Chdir(dir)
-	fail(err)
-	project(file)
+	failOn(err)
+	project(file, *which)
 }
 
 func findTools(toolprefix string) (err error) {