func main() {
	args := os.Args[1:]

	switch {
	case len(args) < 1, args[0] == "-h", args[0] == "-help":
		fs.Usage()
		os.Exit(1)
	case args[0] == "help":
		help(args[1:])
		return
	case projectroot == "":
		log.Fatalf("don't run this binary directly, it is meant to be run as 'gb vendor ...'")
	default:
	}

	root, err := cmd.FindProjectroot(projectroot)
	if err != nil {
		log.Fatalf("could not locate project root: %v", err)
	}
	project := gb.NewProject(root,
		gb.SourceDir(filepath.Join(root, "src")),
		gb.SourceDir(filepath.Join(root, "vendor", "src")))
	log.Debugf("project root %q", project.Projectdir())

	for _, command := range commands {
		if command.Name == args[0] && command.Runnable() {

			// add extra flags if necessary
			if command.AddFlags != nil {
				command.AddFlags(fs)
			}

			if command.FlagParse != nil {
				err = command.FlagParse(fs, args)
			} else {
				err = fs.Parse(args[1:])
			}
			if err != nil {
				log.Fatalf("could not parse flags: %v", err)
			}
			args = fs.Args() // reset args to the leftovers from fs.Parse
			log.Debugf("args: %v", args)

			ctx, err := project.NewContext(
				gb.GcToolchain(),
			)
			if err != nil {
				log.Fatalf("unable to construct context: %v", err)
			}
			defer ctx.Destroy()

			if err := command.Run(ctx, args); err != nil {
				log.Fatalf("command %q failed: %v", command.Name, err)
			}
			return
		}
	}
	log.Fatalf("unknown command %q ", args[0])
}
Beispiel #2
0
Datei: gc.go Projekt: srid/hock
func (t *gcToolchain) Gc(pkg *Package, searchpaths []string, importpath, srcdir, outfile string, files []string) error {
	log.Debugf("gc:gc %v %v %v %v", importpath, srcdir, outfile, files)
	args := append(pkg.gcflags, "-p", importpath, "-pack")
	args = append(args, "-o", outfile)
	for _, d := range searchpaths {
		args = append(args, "-I", d)
	}
	if pkg.Standard && pkg.ImportPath == "runtime" {
		// runtime compiles with a special gc flag to emit
		// additional reflect type data.
		args = append(args, "-+")
	}

	if pkg.Complete() {
		args = append(args, "-complete")
	} else if gc15 {
		asmhdr := filepath.Join(filepath.Dir(outfile), pkg.Name, "go_asm.h")
		args = append(args, "-asmhdr", asmhdr)
	}

	args = append(args, files...)
	if err := mkdir(filepath.Join(filepath.Dir(outfile), pkg.Name)); err != nil {
		return fmt.Errorf("gc:gc: %v", err)
	}
	return runOut(os.Stdout, srcdir, nil, t.gc, args...)
}
func runOut(output io.Writer, dir string, env []string, command string, args ...string) error {
	cmd := exec.Command(command, args...)
	cmd.Dir = dir
	cmd.Stdout = output
	cmd.Stderr = os.Stderr
	cmd.Env = mergeEnvLists(env, envForDir(cmd.Dir))
	log.Debugf("cd %s; %s", cmd.Dir, cmd.Args)
	err := cmd.Run()
	return err
}
// BuildPackages produces a tree of *Actions that can be executed to build
// a *Package.
// BuildPackages walks the tree of *Packages and returns a corresponding
// tree of *Actions representing the steps required to build *Package
// and any of its dependencies
func BuildPackages(pkgs ...*Package) (*Action, error) {
	if len(pkgs) < 1 {
		return nil, fmt.Errorf("no packages supplied")
	}

	targets := make(map[string]*Action) // maps package importpath to build action

	names := func(pkgs []*Package) []string {
		var names []string
		for _, pkg := range pkgs {
			names = append(names, pkg.ImportPath)
		}
		return names
	}

	// create top level build action to unify all packages
	t0 := time.Now()
	build := Action{
		Name: fmt.Sprintf("build: %s", strings.Join(names(pkgs), ",")),
		Task: TaskFn(func() error {
			log.Debugf("build duration: %v %v", time.Since(t0), pkgs[0].Statistics.String())
			return nil
		}),
	}

	for _, pkg := range pkgs {
		if len(pkg.GoFiles)+len(pkg.CgoFiles) == 0 {
			log.Debugf("skipping %v: no go files", pkg.ImportPath)
			continue
		}
		a, err := BuildPackage(targets, pkg)
		if err != nil {
			return nil, err
		}
		if a == nil {
			// nothing to do
			continue
		}
		build.Deps = append(build.Deps, a)
	}
	return &build, nil
}
// ResolvePackagesWithTests is similar to ResolvePackages however
// it also loads the test and external test packages of args into
// the context.
func ResolvePackagesWithTests(r Resolver, paths ...string) ([]*gb.Package, error) {
	var pkgs []*gb.Package
	for _, path := range paths {
		path = relImportPath(r.Srcdirs()[0], path)
		pkg, err := r.ResolvePackageWithTests(path)
		if err != nil {
			if _, ok := err.(*build.NoGoError); ok {
				log.Debugf("skipping %q", path)
				continue
			}
			return pkgs, fmt.Errorf("failed to resolve package %q: %v", path, err)
		}
		pkgs = append(pkgs, pkg)
	}
	return pkgs, nil
}
// loadTestFuncs returns the testFuncs describing the tests that will be run.
func loadTestFuncs(ptest *build.Package) (*testFuncs, error) {
	t := &testFuncs{
		Package: ptest,
	}
	log.Debugf("loadTestFuncs: %v, %v", ptest.TestGoFiles, ptest.XTestGoFiles)
	for _, file := range ptest.TestGoFiles {
		if err := t.load(filepath.Join(ptest.Dir, file), "_test", &t.ImportTest, &t.NeedTest); err != nil {
			return nil, err
		}
	}
	for _, file := range ptest.XTestGoFiles {
		if err := t.load(filepath.Join(ptest.Dir, file), "_xtest", &t.ImportXtest, &t.NeedXtest); err != nil {
			return nil, err
		}
	}
	return t, nil
}
func matchPackages(c *Context, pattern string) []string {
	log.Debugf("matchPackages: %v %v", c.srcdirs[0].Root, pattern)
	match := func(string) bool { return true }
	treeCanMatch := func(string) bool { return true }
	if pattern != "all" && pattern != "std" {
		match = matchPattern(pattern)
		treeCanMatch = treeCanMatchPattern(pattern)
	}

	var pkgs []string

	for _, dir := range c.srcdirs[:1] {
		src := filepath.Clean(dir.Root) + string(filepath.Separator)
		filepath.Walk(src, func(path string, fi os.FileInfo, err error) error {
			if err != nil || !fi.IsDir() || path == src {
				return nil
			}

			// Avoid .foo, _foo, and testdata directory trees.
			_, elem := filepath.Split(path)
			if strings.HasPrefix(elem, ".") || strings.HasPrefix(elem, "_") || elem == "testdata" {
				return filepath.SkipDir
			}

			name := filepath.ToSlash(path[len(src):])
			if pattern == "std" && strings.Contains(name, ".") {
				return filepath.SkipDir
			}
			if !treeCanMatch(name) {
				return filepath.SkipDir
			}
			if !match(name) {
				return nil
			}
			_, err = c.Context.Import(".", path, 0)
			if err != nil {
				if _, noGo := err.(*build.NoGoError); noGo {
					return nil
				}
			}
			pkgs = append(pkgs, name)
			return nil
		})
	}
	return pkgs
}
Beispiel #8
0
// NewContext creates a gb.Context for the project root.
func NewContext(projectroot string, options ...func(*gb.Context) error) (*gb.Context, error) {
	if projectroot == "" {
		return nil, fmt.Errorf("project root is blank")
	}

	root, err := FindProjectroot(projectroot)
	if err != nil {
		return nil, fmt.Errorf("could not locate project root: %v", err)
	}
	project := gb.NewProject(root,
		gb.SourceDir(filepath.Join(root, "src")),
		gb.SourceDir(filepath.Join(root, "vendor", "src")),
	)

	log.Debugf("project root %q", project.Projectdir())
	return project.NewContext(options...)
}
Beispiel #9
0
func copyfile(dst, src string) error {
	err := mkdir(filepath.Dir(dst))
	if err != nil {
		return fmt.Errorf("copyfile: mkdirall: %v", err)
	}
	r, err := os.Open(src)
	if err != nil {
		return fmt.Errorf("copyfile: open(%q): %v", src, err)
	}
	defer r.Close()
	w, err := os.Create(dst)
	if err != nil {
		return fmt.Errorf("copyfile: create(%q): %v", dst, err)
	}
	defer w.Close()
	log.Debugf("copyfile(dst: %v, src: %v)", dst, src)
	_, err = io.Copy(w, r)
	return err
}
Beispiel #10
0
// RunCommand detects the project root, parses flags and runs the Command.
func RunCommand(fs *flag.FlagSet, cmd *Command, projectroot, goroot string, args []string) error {
	if cmd.AddFlags != nil {
		cmd.AddFlags(fs)
	}
	if err := fs.Parse(args); err != nil {
		fs.Usage()
		os.Exit(1)
	}
	args = fs.Args() // reset to the remaining arguments

	ctx, err := NewContext(projectroot, gb.GcToolchain())
	if err != nil {
		return fmt.Errorf("unable to construct context: %v", err)
	}
	defer ctx.Destroy()

	log.Debugf("args: %v", args)
	return cmd.Run(ctx, args)
}
Beispiel #11
0
// TestPackages produces a graph of Actions that when executed build
// and test the supplied packages.
func TestPackages(flags []string, pkgs ...*gb.Package) (*gb.Action, error) {
	if len(pkgs) < 1 {
		return nil, fmt.Errorf("no test packages provided")
	}
	targets := make(map[string]*gb.Action) // maps package import paths to their test run action

	names := func(pkgs []*gb.Package) []string {
		var names []string
		for _, pkg := range pkgs {
			names = append(names, pkg.ImportPath)
		}
		return names
	}

	// create top level test action to root all test actions
	t0 := time.Now()
	test := gb.Action{
		Name: fmt.Sprintf("test: %s", strings.Join(names(pkgs), ",")),
		Task: gb.TaskFn(func() error {
			log.Debugf("test duration: %v %v", time.Since(t0), pkgs[0].Statistics.String())
			return nil
		}),
	}

	for _, pkg := range pkgs {
		a, err := TestPackage(targets, pkg, flags)
		if err != nil {
			return nil, err
		}
		if a == nil {
			// nothing to do ?? not even a test action ?
			continue
		}
		test.Deps = append(test.Deps, a)
	}
	return &test, nil
}
Beispiel #12
0
// TestPackage returns an Action representing the steps required to build
// and test this Package.
func TestPackage(targets map[string]*gb.Action, pkg *gb.Package, flags []string) (*gb.Action, error) {
	var gofiles []string
	gofiles = append(gofiles, pkg.GoFiles...)
	gofiles = append(gofiles, pkg.TestGoFiles...)

	var cgofiles []string
	cgofiles = append(cgofiles, pkg.CgoFiles...)

	var imports []string
	imports = append(imports, pkg.Package.Imports...)
	imports = append(imports, pkg.Package.TestImports...)

	name := pkg.Name
	if name == "main" {
		// rename the main package to its package name for testing.
		name = filepath.Base(filepath.FromSlash(pkg.ImportPath))
	}

	// internal tests
	testpkg := gb.NewPackage(pkg.Context, &build.Package{
		Name:       name,
		ImportPath: pkg.ImportPath,
		Dir:        pkg.Dir,
		SrcRoot:    pkg.SrcRoot,

		GoFiles:      gofiles,
		CFiles:       pkg.CFiles,
		CgoFiles:     cgofiles,
		TestGoFiles:  pkg.TestGoFiles,  // passed directly to buildTestMain
		XTestGoFiles: pkg.XTestGoFiles, // passed directly to buildTestMain

		CgoCFLAGS:    pkg.CgoCFLAGS,
		CgoCPPFLAGS:  pkg.CgoCPPFLAGS,
		CgoCXXFLAGS:  pkg.CgoCXXFLAGS,
		CgoLDFLAGS:   pkg.CgoLDFLAGS,
		CgoPkgConfig: pkg.CgoPkgConfig,

		Imports: imports,
	})
	testpkg.Scope = "test"
	testpkg.Stale = true

	// build dependencies
	deps, err := gb.BuildDependencies(targets, testpkg)
	if err != nil {
		return nil, err
	}

	// only build the internal test if there is Go source or
	// internal test files.
	var testobj *gb.Action
	if len(testpkg.GoFiles)+len(testpkg.CgoFiles)+len(testpkg.TestGoFiles) > 0 {
		var err error
		testobj, err = gb.Compile(testpkg, deps...)
		if err != nil {
			return nil, err
		}
	}

	// external tests
	if len(pkg.XTestGoFiles) > 0 {
		xtestpkg := gb.NewPackage(pkg.Context, &build.Package{
			Name:       name,
			ImportPath: pkg.ImportPath + "_test",
			Dir:        pkg.Dir,
			GoFiles:    pkg.XTestGoFiles,
			Imports:    pkg.XTestImports,
		})
		// build external test dependencies
		deps, err := gb.BuildDependencies(targets, xtestpkg)
		if err != nil {
			return nil, err
		}
		xtestpkg.Scope = "test"
		xtestpkg.Stale = true
		xtestpkg.ExtraIncludes = filepath.Join(pkg.Workdir(), filepath.FromSlash(pkg.ImportPath), "_test")

		// if there is an internal test object, add it as a dependency.
		if testobj != nil {
			deps = append(deps, testobj)
		}
		testobj, err = gb.Compile(xtestpkg, deps...)
		if err != nil {
			return nil, err
		}
	}

	testmainpkg, err := buildTestMain(testpkg)
	if err != nil {
		return nil, err
	}
	testmain, err := gb.Compile(testmainpkg, testobj)
	if err != nil {
		return nil, err
	}

	cmd := exec.Command(testmainpkg.Binfile()+".test", flags...)
	cmd.Dir = pkg.Dir // tests run in the original source directory
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr

	log.Debugf("scheduling run of %v", cmd.Args)
	return &gb.Action{
		Name: fmt.Sprintf("run: %s", cmd.Args),
		Deps: []*gb.Action{testmain},
		Task: gb.TaskFn(func() error {
			return cmd.Run()
		}),
	}, nil
}
Beispiel #13
0
Datei: main.go Projekt: tianon/gb
func main() {
	args := os.Args
	if len(args) < 2 || args[1] == "-h" {
		fs.Usage()
		os.Exit(1)
	}
	name := args[1]
	if name == "help" {
		help(args[2:])
		return
	}

	command, ok := commands[name]
	if (command != nil && !command.Runnable()) || !ok {
		plugin, err := lookupPlugin(name)
		if err != nil {
			fmt.Fprintf(os.Stderr, "FATAL: unknown command %q\n", name)
			fs.Usage()
			os.Exit(1)
		}
		command = &cmd.Command{
			Run: func(ctx *gb.Context, args []string) error {
				if len(args) < 1 {
					return fmt.Errorf("plugin: no command supplied")
				}
				args = append([]string{plugin}, args...)

				env := cmd.MergeEnv(os.Environ(), map[string]string{
					"GB_PROJECT_DIR": ctx.Projectdir(),
				})

				cmd := exec.Cmd{
					Path: plugin,
					Args: args,
					Env:  env,

					Stdin:  os.Stdin,
					Stdout: os.Stdout,
					Stderr: os.Stderr,
				}

				return cmd.Run()
			},
			// plugin should not interpret arguments
			ParseArgs: func(_ *gb.Context, _ string, args []string) []string { return args },
		}
	}

	// add extra flags if necessary
	if command.AddFlags != nil {
		command.AddFlags(fs)
	}

	var err error
	if command.FlagParse != nil {
		err = command.FlagParse(fs, args)
	} else {
		err = fs.Parse(args[2:])
	}
	if err != nil {
		log.Fatalf("could not parse flags: %v", err)
	}

	args = fs.Args() // reset args to the leftovers from fs.Parse
	if command == commands["plugin"] {
		args = append([]string{name}, args...)
	}
	cwd, err := filepath.Abs(cwd) // if cwd was passed in via -R, make sure it is absolute
	if err != nil {
		log.Fatalf("could not make project root absolute: %v", err)
	}

	ctx, err := cmd.NewContext(
		cwd, // project root
		gb.GcToolchain(),
		gb.Gcflags(gcflags),
		gb.Ldflags(ldflags),
	)
	if err != nil {
		log.Fatalf("unable to construct context: %v", err)
	}

	if !noDestroyContext {
		defer ctx.Destroy()
	}

	if command.ParseArgs != nil {
		args = command.ParseArgs(ctx, ctx.Projectdir(), args)
	} else {
		args = cmd.ImportPaths(ctx, cwd, args)
	}

	log.Debugf("args: %v", args)
	if err := command.Run(ctx, args); err != nil {
		if !noDestroyContext {
			ctx.Destroy()
		}
		log.Fatalf("command %q failed: %v", name, err)
	}
}
// Destroy removes the temporary working files of this context.
func (c *Context) Destroy() error {
	log.Debugf("removing work directory: %v", c.workdir)
	return os.RemoveAll(c.workdir)
}