diff options
-rw-r--r-- | builder/build.go | 2 | ||||
-rw-r--r-- | compiler/compiler_test.go | 2 | ||||
-rw-r--r-- | loader/loader.go | 4 | ||||
-rw-r--r-- | main.go | 43 | ||||
-rw-r--r-- | main_test.go | 41 | ||||
-rw-r--r-- | transform/transform_test.go | 2 |
6 files changed, 86 insertions, 8 deletions
diff --git a/builder/build.go b/builder/build.go index d0e92d7c9..cb9368572 100644 --- a/builder/build.go +++ b/builder/build.go @@ -193,7 +193,7 @@ func Build(pkgName, outpath string, config *compileopts.Config, action func(Buil defer machine.Dispose() // Load entire program AST into memory. - lprogram, err := loader.Load(config, []string{pkgName}, config.ClangHeaders, types.Config{ + lprogram, err := loader.Load(config, pkgName, config.ClangHeaders, types.Config{ Sizes: compiler.Sizes(machine), }) if err != nil { diff --git a/compiler/compiler_test.go b/compiler/compiler_test.go index 199c71200..9b0c6efff 100644 --- a/compiler/compiler_test.go +++ b/compiler/compiler_test.go @@ -109,7 +109,7 @@ func TestCompiler(t *testing.T) { defer machine.Dispose() // Load entire program AST into memory. - lprogram, err := loader.Load(config, []string{"./testdata/" + tc.file}, config.ClangHeaders, types.Config{ + lprogram, err := loader.Load(config, "./testdata/"+tc.file, config.ClangHeaders, types.Config{ Sizes: Sizes(machine), }) if err != nil { diff --git a/loader/loader.go b/loader/loader.go index f02219425..88eb15dac 100644 --- a/loader/loader.go +++ b/loader/loader.go @@ -104,7 +104,7 @@ type EmbedFile struct { // Load loads the given package with all dependencies (including the runtime // package). Call .Parse() afterwards to parse all Go files (including CGo // processing, if necessary). -func Load(config *compileopts.Config, inputPkgs []string, clangHeaders string, typeChecker types.Config) (*Program, error) { +func Load(config *compileopts.Config, inputPkg string, clangHeaders string, typeChecker types.Config) (*Program, error) { goroot, err := GetCachedGoroot(config) if err != nil { return nil, err @@ -133,7 +133,7 @@ func Load(config *compileopts.Config, inputPkgs []string, clangHeaders string, t if config.TestConfig.CompileTestBinary { extraArgs = append(extraArgs, "-test") } - cmd, err := List(config, extraArgs, inputPkgs) + cmd, err := List(config, extraArgs, []string{inputPkg}) if err != nil { return nil, err } @@ -1,6 +1,7 @@ package main import ( + "bufio" "bytes" "context" "encoding/json" @@ -1252,6 +1253,35 @@ func parseGoLinkFlag(flagsString string) (map[string]map[string]string, error) { return map[string]map[string]string(globalVarValues), nil } +// getListOfPackages returns a standard list of packages for a given list that might +// include wildards using `go list`. +// For example [./...] => ["pkg1", "pkg1/pkg12", "pkg2"] +func getListOfPackages(pkgs []string, options *compileopts.Options) ([]string, error) { + config, err := builder.NewConfig(options) + if err != nil { + return nil, err + } + cmd, err := loader.List(config, nil, pkgs) + if err != nil { + return nil, fmt.Errorf("failed to run `go list`: %w", err) + } + outputBuf := bytes.NewBuffer(nil) + cmd.Stdout = outputBuf + cmd.Stderr = os.Stderr + err = cmd.Run() + if err != nil { + return nil, err + } + + var pkgNames []string + sc := bufio.NewScanner(outputBuf) + for sc.Scan() { + pkgNames = append(pkgNames, sc.Text()) + } + + return pkgNames, nil +} + func main() { if len(os.Args) < 2 { fmt.Fprintln(os.Stderr, "No command-line arguments supplied.") @@ -1487,14 +1517,21 @@ func main() { if len(pkgNames) == 0 { pkgNames = []string{"."} } - if outpath != "" && len(pkgNames) > 1 { + + explicitPkgNames, err := getListOfPackages(pkgNames, options) + if err != nil { + fmt.Printf("cannot resolve packages: %v\n", err) + os.Exit(1) + } + + if outpath != "" && len(explicitPkgNames) > 1 { fmt.Println("cannot use -o flag with multiple packages") os.Exit(1) } fail := make(chan struct{}, 1) var wg sync.WaitGroup - bufs := make([]testOutputBuf, len(pkgNames)) + bufs := make([]testOutputBuf, len(explicitPkgNames)) for i := range bufs { bufs[i].done = make(chan struct{}) } @@ -1520,7 +1557,7 @@ func main() { // Build and run the tests concurrently. // This uses an additional semaphore to reduce the memory usage. testSema := make(chan struct{}, cap(options.Semaphore)) - for i, pkgName := range pkgNames { + for i, pkgName := range explicitPkgNames { pkgName := pkgName buf := &bufs[i] testSema <- struct{}{} diff --git a/main_test.go b/main_test.go index 3351b6c0e..080e4b95a 100644 --- a/main_test.go +++ b/main_test.go @@ -13,6 +13,7 @@ import ( "io/ioutil" "os" "os/exec" + "reflect" "regexp" "runtime" "strings" @@ -520,6 +521,46 @@ func ioLogger(t *testing.T, wg *sync.WaitGroup) io.WriteCloser { return w } +func TestGetListOfPackages(t *testing.T) { + opts := optionsFromTarget("", sema) + tests := []struct { + pkgs []string + expectedPkgs []string + expectesError bool + }{ + { + pkgs: []string{"./tests/testing/recurse/..."}, + expectedPkgs: []string{ + "github.com/tinygo-org/tinygo/tests/testing/recurse", + "github.com/tinygo-org/tinygo/tests/testing/recurse/subdir", + }, + }, + { + pkgs: []string{"./tests/testing/pass"}, + expectedPkgs: []string{ + "github.com/tinygo-org/tinygo/tests/testing/pass", + }, + }, + { + pkgs: []string{"./tests/testing"}, + expectesError: true, + }, + } + + for _, test := range tests { + actualPkgs, err := getListOfPackages(test.pkgs, &opts) + if err != nil && !test.expectesError { + t.Errorf("unexpected error: %v", err) + } else if err == nil && test.expectesError { + t.Error("expected error, but got none") + } + + if !reflect.DeepEqual(test.expectedPkgs, actualPkgs) { + t.Errorf("expected two slices to be equal, expected %v got %v", test.expectedPkgs, actualPkgs) + } + } +} + // This TestMain is necessary because TinyGo may also be invoked to run certain // LLVM tools in a separate process. Not capturing these invocations would lead // to recursive tests. diff --git a/transform/transform_test.go b/transform/transform_test.go index 9ad724346..1c6b5df39 100644 --- a/transform/transform_test.go +++ b/transform/transform_test.go @@ -146,7 +146,7 @@ func compileGoFileForTesting(t *testing.T, filename string) llvm.Module { defer machine.Dispose() // Load entire program AST into memory. - lprogram, err := loader.Load(config, []string{filename}, config.ClangHeaders, types.Config{ + lprogram, err := loader.Load(config, filename, config.ClangHeaders, types.Config{ Sizes: compiler.Sizes(machine), }) if err != nil { |