diff --git a/go.go b/go.go index ed814e7..283f897 100644 --- a/go.go +++ b/go.go @@ -19,7 +19,7 @@ type OutputTemplateData struct { } // GoCrossCompile -func GoCrossCompile(packagePath string, platform Platform, outputTpl string, ldflags string, tags string) error { +func GoCrossCompile(pkg string, packagePath string, platform Platform, outputTpl string, ldflags string, tags string, test bool) error { env := append(os.Environ(), "GOOS="+platform.OS, "GOARCH="+platform.Arch) @@ -59,18 +59,31 @@ func GoCrossCompile(packagePath string, platform Platform, outputTpl string, ldf packagePath = "" } - _, err = execGo(env, chdir, "build", - "-ldflags", ldflags, + var args []string + if test { + args = []string{"test", "-c"} + } else { + args = []string{"build"} + } + if !test { + args = append(args, "-o", outputPathReal) + } + args = append(args, "-ldflags", ldflags, "-tags", tags, - "-o", outputPathReal, packagePath) + _, err = execGo(env, chdir, args...) + if err == nil && test { + err = renameTestExecutable(pkg, platform) + } return err } -// GoMainDirs returns the file paths to the packages that are "main" -// packages, from the list of packages given. The list of packages can -// include relative paths, the special "..." Go keyword, etc. -func GoMainDirs(packages []string) ([]string, error) { +// GoMainDirs returns the packages and file paths for the packages that +// are "main" packages, from the list of packages given. The list of packages +// can include relative paths, the special "..." Go keyword, etc. +// +// If test is true, GoMainDirs returns all matching packages. +func GoMainDirs(packages []string, test bool) ([][]string, error) { args := make([]string, 0, len(packages)+3) args = append(args, "list", "-f", "{{.Name}}|{{.ImportPath}}") args = append(args, packages...) @@ -80,7 +93,7 @@ func GoMainDirs(packages []string) ([]string, error) { return nil, err } - results := make([]string, 0, len(output)) + results := make([][]string, 0, len(output)) for _, line := range strings.Split(output, "\n") { if line == "" { continue @@ -92,8 +105,8 @@ func GoMainDirs(packages []string) ([]string, error) { continue } - if parts[0] == "main" { - results = append(results, parts[1]) + if parts[0] == "main" || test { + results = append(results, parts) } } @@ -153,6 +166,16 @@ func execGo(env []string, dir string, args ...string) (string, error) { return stdout.String(), nil } +func renameTestExecutable(pkg string, platform Platform) error { + originalName := fmt.Sprintf("%s.test", pkg) + newName := fmt.Sprintf("%s_%s_%s.test", pkg, platform.OS, platform.Arch) + if platform.OS == "windows" { + originalName = fmt.Sprintf("%s.exe", originalName) + newName = fmt.Sprintf("%s.exe", newName) + } + return os.Rename(originalName, newName) +} + const versionSource = `package main import ( diff --git a/main.go b/main.go index 6428cfc..5cd2129 100644 --- a/main.go +++ b/main.go @@ -22,6 +22,7 @@ func realMain() int { var parallel int var platformFlag PlatformFlag var tags string + var test bool var verbose bool flags := flag.NewFlagSet("gox", flag.ExitOnError) flags.Usage = func() { printUsage() } @@ -33,6 +34,7 @@ func realMain() int { flags.StringVar(&outputTpl, "output", "{{.Dir}}_{{.OS}}_{{.Arch}}", "output path") flags.IntVar(¶llel, "parallel", -1, "parallelization factor") flags.BoolVar(&buildToolchain, "build-toolchain", false, "build toolchain") + flags.BoolVar(&test, "test", false, "set to true to build tests intead of main program") flags.BoolVar(&verbose, "verbose", false, "verbose") if err := flags.Parse(os.Args[1:]); err != nil { flags.Usage() @@ -45,6 +47,11 @@ func realMain() int { parallel = runtime.NumCPU() } + if parallel > 1 && test { + fmt.Println("Disabling parallel builds when building tests") + parallel = 1 + } + if buildToolchain { return mainBuildToolchain(parallel, platformFlag, verbose) } @@ -68,7 +75,7 @@ func realMain() int { } // Get the packages that are in the given paths - mainDirs, err := GoMainDirs(packages) + mainDirs, err := GoMainDirs(packages, test) if err != nil { fmt.Fprintf(os.Stderr, "Error reading packages: %s", err) return 1 @@ -90,14 +97,16 @@ func realMain() int { errors := make([]string, 0) semaphore := make(chan int, parallel) for _, platform := range platforms { - for _, path := range mainDirs { + for _, pkgAndPath := range mainDirs { + pkg := pkgAndPath[0] + path := pkgAndPath[1] // Start the goroutine that will do the actual build wg.Add(1) go func(path string, platform Platform) { defer wg.Done() semaphore <- 1 fmt.Printf("--> %15s: %s\n", platform.String(), path) - if err := GoCrossCompile(path, platform, outputTpl, ldflags, tags); err != nil { + if err := GoCrossCompile(pkg, path, platform, outputTpl, ldflags, tags, test); err != nil { errorLock.Lock() defer errorLock.Unlock() errors = append(errors,