Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8321caa1 authored by Ramy Medhat's avatar Ramy Medhat Committed by Android (Google) Code Review
Browse files

Merge changes from topic "metalava_sandbox" into rvc-dev

* changes:
  Turn on metalava sandbox warning in all droiddoc metalava invocations.
  Add support for Metalava implicit dependencies for remote execution.
  Add sourcepath to inputs of remoteable metalava action.
  Add support for the remote execution of metalava actions.
parents 26d6b783 7f2006c0
Loading
Loading
Loading
Loading
+71 −4
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@ import (

	"android/soong/android"
	"android/soong/java/config"
	"android/soong/remoteexec"
)

func init() {
@@ -375,6 +376,7 @@ type Javadoc struct {
	srcFiles    android.Paths
	sourcepaths android.Paths
	argFiles    android.Paths
	implicits   android.Paths

	args string

@@ -574,6 +576,7 @@ func (j *Javadoc) collectDeps(ctx android.ModuleContext) deps {
	// do not pass exclude_srcs directly when expanding srcFiles since exclude_srcs
	// may contain filegroup or genrule.
	srcFiles := android.PathsForModuleSrcExcludes(ctx, j.properties.Srcs, j.properties.Exclude_srcs)
	j.implicits = append(j.implicits, srcFiles...)

	filterByPackage := func(srcs []android.Path, filterPackages []string) []android.Path {
		if filterPackages == nil {
@@ -599,6 +602,24 @@ func (j *Javadoc) collectDeps(ctx android.ModuleContext) deps {
	}
	srcFiles = filterByPackage(srcFiles, j.properties.Filter_packages)

	// While metalava needs package html files, it does not need them to be explicit on the command
	// line. More importantly, the metalava rsp file is also used by the subsequent jdiff action if
	// jdiff_enabled=true. javadoc complains if it receives html files on the command line. The filter
	// below excludes html files from the rsp file for both metalava and jdiff. Note that the html
	// files are still included as implicit inputs for successful remote execution and correct
	// incremental builds.
	filterHtml := func(srcs []android.Path) []android.Path {
		filtered := []android.Path{}
		for _, src := range srcs {
			if src.Ext() == ".html" {
				continue
			}
			filtered = append(filtered, src)
		}
		return filtered
	}
	srcFiles = filterHtml(srcFiles)

	flags := j.collectAidlFlags(ctx, deps)
	srcFiles = j.genSources(ctx, srcFiles, flags)

@@ -1398,15 +1419,61 @@ func (d *Droidstubs) apiToXmlFlags(ctx android.ModuleContext, cmd *android.RuleB
}

func metalavaCmd(ctx android.ModuleContext, rule *android.RuleBuilder, javaVersion javaVersion, srcs android.Paths,
	srcJarList android.Path, bootclasspath, classpath classpath, sourcepaths android.Paths) *android.RuleBuilderCommand {
	srcJarList android.Path, bootclasspath, classpath classpath, sourcepaths android.Paths, implicits android.Paths) *android.RuleBuilderCommand {
	// Metalava uses lots of memory, restrict the number of metalava jobs that can run in parallel.
	rule.HighMem()
	cmd := rule.Command().BuiltTool(ctx, "metalava").
	cmd := rule.Command()

	var implicitsRsp android.WritablePath
	if len(implicits) > 0 {
		implicitsRsp = android.PathForModuleOut(ctx, ctx.ModuleName()+"-"+"implicits.rsp")
		impRule := android.NewRuleBuilder()
		impCmd := impRule.Command()
		// A dummy action that copies the ninja generated rsp file to a new location. This allows us to
		// add a large number of inputs to a file without exceeding bash command length limits (which
		// would happen if we use the WriteFile rule). The cp is needed because RuleBuilder sets the
		// rsp file to be ${output}.rsp.
		impCmd.Text("cp").FlagWithRspFileInputList("", implicits).Output(implicitsRsp)
		impRule.Build(pctx, ctx, "implicitsGen", "implicits generation")
		cmd.Implicits(implicits)
		cmd.Implicit(implicitsRsp)
	}
	if ctx.Config().IsEnvTrue("RBE_METALAVA") {
		rule.Remoteable(android.RemoteRuleSupports{RBE: true})
		execStrategy := remoteexec.LocalExecStrategy
		if v := ctx.Config().Getenv("RBE_METALAVA_EXEC_STRATEGY"); v != "" {
			execStrategy = v
		}
		pool := "metalava"
		if v := ctx.Config().Getenv("RBE_METALAVA_POOL"); v != "" {
			pool = v
		}
		inputs := []string{android.PathForOutput(ctx, "host", ctx.Config().PrebuiltOS(), "framework", "metalava.jar").String()}
		inputs = append(inputs, sourcepaths.Strings()...)
		if v := ctx.Config().Getenv("RBE_METALAVA_INPUTS"); v != "" {
			inputs = append(inputs, strings.Split(v, ",")...)
		}
		cmd.Text((&remoteexec.REParams{
			Labels:          map[string]string{"type": "compile", "lang": "java", "compiler": "metalava", "shallow": "true"},
			ExecStrategy:    execStrategy,
			Inputs:          inputs,
			RSPFile:         implicitsRsp.String(),
			ToolchainInputs: []string{config.JavaCmd(ctx).String()},
			Platform:        map[string]string{remoteexec.PoolKey: pool},
		}).NoVarTemplate(ctx.Config()))
	}

	cmd.BuiltTool(ctx, "metalava").
		Flag(config.JavacVmFlags).
		FlagWithArg("-encoding ", "UTF-8").
		FlagWithArg("-source ", javaVersion.String()).
		FlagWithRspFileInputList("@", srcs).
		FlagWithInput("@", srcJarList)
		FlagWithInput("@", srcJarList).
		FlagWithOutput("--strict-input-files:warn ", android.PathForModuleOut(ctx, ctx.ModuleName()+"-"+"violations.txt"))

	if implicitsRsp.String() != "" {
		cmd.FlagWithArg("--strict-input-files-exempt ", "@"+implicitsRsp.String())
	}

	if len(bootclasspath) > 0 {
		cmd.FlagWithInputList("-bootclasspath ", bootclasspath.Paths(), ":")
@@ -1453,7 +1520,7 @@ func (d *Droidstubs) GenerateAndroidBuildActions(ctx android.ModuleContext) {
	srcJarList := zipSyncCmd(ctx, rule, srcJarDir, d.Javadoc.srcJars)

	cmd := metalavaCmd(ctx, rule, javaVersion, d.Javadoc.srcFiles, srcJarList,
		deps.bootClasspath, deps.classpath, d.Javadoc.sourcepaths)
		deps.bootClasspath, deps.classpath, d.Javadoc.sourcepaths, d.Javadoc.implicits)

	d.stubsFlags(ctx, cmd, stubsDir)

+1 −1
Original line number Diff line number Diff line
@@ -1038,7 +1038,7 @@ func checkSystemModulesUseByDroidstubs(t *testing.T, ctx *android.TestContext, m
	for _, i := range metalavaRule.Implicits {
		systemJars = append(systemJars, i.Base())
	}
	if len(systemJars) != 1 || systemJars[0] != systemJar {
	if len(systemJars) < 1 || systemJars[0] != systemJar {
		t.Errorf("inputs of %q must be []string{%q}, but was %#v.", moduleName, systemJar, systemJars)
	}
}
+31 −17
Original line number Diff line number Diff line
@@ -75,8 +75,8 @@ type REParams struct {
	// OutputFiles is a list of output file paths or ninja variables as placeholders for rule
	// outputs.
	OutputFiles []string
	// OutputDirectories is a list of output directory paths or ninja variables as placeholders
	// for rule outputs.
	// OutputDirectories is a list of output directories or ninja variables as placeholders for
	// rule output directories.
	OutputDirectories []string
	// ToolchainInputs is a list of paths or ninja variables pointing to the location of
	// toolchain binaries used by the rule.
@@ -85,17 +85,31 @@ type REParams struct {

func init() {
	pctx.VariableFunc("Wrapper", func(ctx android.PackageVarContext) string {
		if override := ctx.Config().Getenv("RBE_WRAPPER"); override != "" {
		return wrapper(ctx.Config())
	})
}

func wrapper(cfg android.Config) string {
	if override := cfg.Getenv("RBE_WRAPPER"); override != "" {
		return override
	}
	return DefaultWrapperPath
	})
}

// Generate the remote execution wrapper template to be added as a prefix to the rule's command.
// Template generates the remote execution wrapper template to be added as a prefix to the rule's
// command.
func (r *REParams) Template() string {
	template := "${remoteexec.Wrapper}"
	return "${remoteexec.Wrapper}" + r.wrapperArgs()
}

// NoVarTemplate generates the remote execution wrapper template without variables, to be used in
// RuleBuilder.
func (r *REParams) NoVarTemplate(cfg android.Config) string {
	return wrapper(cfg) + r.wrapperArgs()
}

func (r *REParams) wrapperArgs() string {
	args := ""
	var kvs []string
	labels := r.Labels
	if len(labels) == 0 {
@@ -105,7 +119,7 @@ func (r *REParams) Template() string {
		kvs = append(kvs, k+"="+v)
	}
	sort.Strings(kvs)
	template += " --labels=" + strings.Join(kvs, ",")
	args += " --labels=" + strings.Join(kvs, ",")

	var platform []string
	for k, v := range r.Platform {
@@ -119,36 +133,36 @@ func (r *REParams) Template() string {
	}
	if platform != nil {
		sort.Strings(platform)
		template += " --platform=\"" + strings.Join(platform, ",") + "\""
		args += " --platform=\"" + strings.Join(platform, ",") + "\""
	}

	strategy := r.ExecStrategy
	if strategy == "" {
		strategy = defaultExecStrategy
	}
	template += " --exec_strategy=" + strategy
	args += " --exec_strategy=" + strategy

	if len(r.Inputs) > 0 {
		template += " --inputs=" + strings.Join(r.Inputs, ",")
		args += " --inputs=" + strings.Join(r.Inputs, ",")
	}

	if r.RSPFile != "" {
		template += " --input_list_paths=" + r.RSPFile
		args += " --input_list_paths=" + r.RSPFile
	}

	if len(r.OutputFiles) > 0 {
		template += " --output_files=" + strings.Join(r.OutputFiles, ",")
		args += " --output_files=" + strings.Join(r.OutputFiles, ",")
	}

	if len(r.OutputDirectories) > 0 {
		template += " --output_directories=" + strings.Join(r.OutputDirectories, ",")
		args += " --output_directories=" + strings.Join(r.OutputDirectories, ",")
	}

	if len(r.ToolchainInputs) > 0 {
		template += " --toolchain_inputs=" + strings.Join(r.ToolchainInputs, ",")
		args += " --toolchain_inputs=" + strings.Join(r.ToolchainInputs, ",")
	}

	return template + " -- "
	return args + " -- "
}

// StaticRules returns a pair of rules based on the given RuleParams, where the first rule is a
+18 −0
Original line number Diff line number Diff line
@@ -17,6 +17,8 @@ package remoteexec
import (
	"fmt"
	"testing"

	"android/soong/android"
)

func TestTemplate(t *testing.T) {
@@ -64,6 +66,22 @@ func TestTemplate(t *testing.T) {
	}
}

func TestNoVarTemplate(t *testing.T) {
	params := &REParams{
		Labels:      map[string]string{"type": "compile", "lang": "cpp", "compiler": "clang"},
		Inputs:      []string{"$in"},
		OutputFiles: []string{"$out"},
		Platform: map[string]string{
			ContainerImageKey: DefaultImage,
			PoolKey:           "default",
		},
	}
	want := fmt.Sprintf("prebuilts/remoteexecution-client/live/rewrapper --labels=compiler=clang,lang=cpp,type=compile --platform=\"Pool=default,container-image=%s\" --exec_strategy=local --inputs=$in --output_files=$out -- ", DefaultImage)
	if got := params.NoVarTemplate(android.NullConfig("")); got != want {
		t.Errorf("NoVarTemplate() returned\n%s\nwant\n%s", got, want)
	}
}

func TestTemplateDeterminism(t *testing.T) {
	r := &REParams{
		Labels:      map[string]string{"type": "compile", "lang": "cpp", "compiler": "clang"},