Beispiel #1
0
// extractToolArgs extracts the build tool arguments from args.
func extractToolArgs(args []string) toolArgs {
	if len(args) == 3 && args[0] == "/bin/bash" && args[1] == "-c" {
		actual, ok := shell.Split(args[2])
		if !ok {
			log.Fatalf("Invalid shell-quoted argument %#q", args[2])
		}
		args = actual
	}

	// Find the Go tool invocation, and return only that portion.
	var result toolArgs
	var wantArg *string
	inTool := false
	for _, arg := range args {
		// Discard arguments until the tool binary is found.
		if !inTool {
			if root := strings.TrimPrefix(arg, "GOROOT="); root != arg {
				result.goRoot = os.ExpandEnv(root)
				continue
			} else if ok, dir := isGoTool(arg); ok {
				inTool = true
				result.toolRoot = dir
			} else {
				continue
			}
		}
		result.fullArgs = append(result.fullArgs, arg)

		// Scan for important flags.
		if wantArg != nil { // capture argument for a previous flag
			*wantArg = arg
			wantArg = nil
			continue
		}
		if arg == "-p" {
			wantArg = &result.importPath
		} else if arg == "-o" {
			wantArg = &result.outputPath
		} else if arg == "-I" {
			wantArg = &result.includePath
		} else if !strings.HasPrefix(arg, "-") && strings.HasSuffix(arg, ".go") {
			result.sources = append(result.sources, arg)
		}
	}
	return result
}
Beispiel #2
0
// parseBazelArgs extracts the compiler command line from the raw argument list
// passed in by Bazel. The official Go rules currently pass in a response file
// containing a shell script that we have to parse.
func (c *Config) parseBazelArgs(ctx context.Context, args []string) (*bazelArgs, error) {
	if len(args) != 1 || filepath.Ext(args[0]) != ".params" {
		// This is some unusual case; assume the arguments are already parsed.
		return &bazelArgs{compile: args}, nil
	}

	// This is the expected case, a response file.
	result := &bazelArgs{paramsFile: args[0]}
	f, err := c.openFile(ctx, result.paramsFile)
	if err != nil {
		return nil, err
	}
	data, err := ioutil.ReadAll(f)
	f.Close()
	if err != nil {
		return nil, err
	}

	// Split up the response into lines, and split each line into commands
	// assuming a pipeline of the form "cmd1 && cmd2 && ...".
	// Bazel exports GOROOT and changes the working directory, both of which we
	// want for processing the compiler's argument list.
	var last []string
	for _, line := range strings.Split(string(data), "\n") {
		for _, cmd := range strings.Split(line, "&&") {
			trimmed := strings.TrimSpace(cmd)
			last, _ = shell.Split(trimmed)
			if m := rootVar.FindStringSubmatch(trimmed); m != nil {
				result.goRoot = m[1]
			} else if m := cdCommand.FindStringSubmatch(trimmed); m != nil {
				result.workDir = m[1]
			}
		}
	}
	result.compile = last
	return result, nil
}