Merge changes from topic "sbox_tools"

* changes:
  Sandbox genrule tools
  Call ctx.InstallFile for uninstallable cc modules
  Don't copy uninstallable variants of NDK libraries to sysroot
This commit is contained in:
Colin Cross
2020-12-17 22:01:06 +00:00
committed by Gerrit Code Review
19 changed files with 292 additions and 79 deletions

View File

@@ -820,7 +820,7 @@ func shouldSkipAndroidMkProcessing(module *ModuleBase) bool {
}
return !module.Enabled() ||
module.commonProperties.SkipInstall ||
module.commonProperties.HideFromMake ||
// Make does not understand LinuxBionic
module.Os() == LinuxBionic
}

View File

@@ -452,8 +452,8 @@ type Module interface {
InstallInRoot() bool
InstallBypassMake() bool
InstallForceOS() (*OsType, *ArchType)
SkipInstall()
IsSkipInstall() bool
HideFromMake()
IsHideFromMake() bool
MakeUninstallable()
ReplacedByPrebuilt()
IsReplacedByPrebuilt() bool
@@ -751,6 +751,13 @@ type commonProperties struct {
// Set by osMutator.
CommonOSVariant bool `blueprint:"mutated"`
// When HideFromMake is set to true, no entry for this variant will be emitted in the
// generated Android.mk file.
HideFromMake bool `blueprint:"mutated"`
// When SkipInstall is set to true, calls to ctx.InstallFile, ctx.InstallExecutable,
// ctx.InstallSymlink and ctx.InstallAbsoluteSymlink act like calls to ctx.PackageFile
// and don't create a rule to install the file.
SkipInstall bool `blueprint:"mutated"`
// Whether the module has been replaced by a prebuilt
@@ -1355,26 +1362,33 @@ func (m *ModuleBase) Disable() {
m.commonProperties.ForcedDisabled = true
}
// HideFromMake marks this variant so that it is not emitted in the generated Android.mk file.
func (m *ModuleBase) HideFromMake() {
m.commonProperties.HideFromMake = true
}
// IsHideFromMake returns true if HideFromMake was previously called.
func (m *ModuleBase) IsHideFromMake() bool {
return m.commonProperties.HideFromMake == true
}
// SkipInstall marks this variant to not create install rules when ctx.Install* are called.
func (m *ModuleBase) SkipInstall() {
m.commonProperties.SkipInstall = true
}
func (m *ModuleBase) IsSkipInstall() bool {
return m.commonProperties.SkipInstall == true
}
// Similar to SkipInstall, but if the AndroidMk entry would set
// Similar to HideFromMake, but if the AndroidMk entry would set
// LOCAL_UNINSTALLABLE_MODULE then this variant may still output that entry
// rather than leaving it out altogether. That happens in cases where it would
// have other side effects, in particular when it adds a NOTICE file target,
// which other install targets might depend on.
func (m *ModuleBase) MakeUninstallable() {
m.SkipInstall()
m.HideFromMake()
}
func (m *ModuleBase) ReplacedByPrebuilt() {
m.commonProperties.ReplacedByPrebuilt = true
m.SkipInstall()
m.HideFromMake()
}
func (m *ModuleBase) IsReplacedByPrebuilt() bool {
@@ -2440,11 +2454,15 @@ func (m *moduleContext) InstallForceOS() (*OsType, *ArchType) {
return m.module.InstallForceOS()
}
func (m *moduleContext) skipInstall(fullInstallPath InstallPath) bool {
func (m *moduleContext) skipInstall() bool {
if m.module.base().commonProperties.SkipInstall {
return true
}
if m.module.base().commonProperties.HideFromMake {
return true
}
// We'll need a solution for choosing which of modules with the same name in different
// namespaces to install. For now, reuse the list of namespaces exported to Make as the
// list of namespaces to install in a Soong-only build.
@@ -2492,7 +2510,7 @@ func (m *moduleContext) installFile(installPath InstallPath, name string, srcPat
fullInstallPath := installPath.Join(m, name)
m.module.base().hooks.runInstallHooks(m, srcPath, fullInstallPath, false)
if !m.skipInstall(fullInstallPath) {
if !m.skipInstall() {
deps = append(deps, m.module.base().installFilesDepSet.ToList().Paths()...)
var implicitDeps, orderOnlyDeps Paths
@@ -2526,6 +2544,7 @@ func (m *moduleContext) installFile(installPath InstallPath, name string, srcPat
m.packageFile(fullInstallPath, srcPath, executable)
m.checkbuildFiles = append(m.checkbuildFiles, srcPath)
return fullInstallPath
}
@@ -2537,7 +2556,7 @@ func (m *moduleContext) InstallSymlink(installPath InstallPath, name string, src
if err != nil {
panic(fmt.Sprintf("Unable to generate symlink between %q and %q: %s", fullInstallPath.Base(), srcPath.Base(), err))
}
if !m.skipInstall(fullInstallPath) {
if !m.skipInstall() {
m.Build(pctx, BuildParams{
Rule: Symlink,
@@ -2570,7 +2589,7 @@ func (m *moduleContext) InstallAbsoluteSymlink(installPath InstallPath, name str
fullInstallPath := installPath.Join(m, name)
m.module.base().hooks.runInstallHooks(m, nil, fullInstallPath, true)
if !m.skipInstall(fullInstallPath) {
if !m.skipInstall() {
m.Build(pctx, BuildParams{
Rule: Symlink,
Description: "install symlink " + fullInstallPath.Base() + " -> " + absPath,
@@ -2738,6 +2757,7 @@ func outputFilesForModule(ctx PathContext, module blueprint.Module, tag string)
// Modules can implement HostToolProvider and return a valid OptionalPath from HostToolPath() to
// specify that they can be used as a tool by a genrule module.
type HostToolProvider interface {
Module
// HostToolPath returns the path to the host tool for the module if it is one, or an invalid
// OptionalPath.
HostToolPath() OptionalPath

View File

@@ -235,7 +235,7 @@ func overrideModuleDepsMutator(ctx BottomUpMutatorContext) {
return
}
// See if there's a prebuilt module that overrides this override module with prefer flag,
// in which case we call SkipInstall on the corresponding variant later.
// in which case we call HideFromMake on the corresponding variant later.
ctx.VisitDirectDepsWithTag(PrebuiltDepTag, func(dep Module) {
prebuilt, ok := dep.(PrebuiltInterface)
if !ok {
@@ -284,7 +284,7 @@ func performOverrideMutator(ctx BottomUpMutatorContext) {
mods[i+1].(OverridableModule).override(ctx, o)
if o.getOverriddenByPrebuilt() {
// The overriding module itself, too, is overridden by a prebuilt. Skip its installation.
mods[i+1].SkipInstall()
mods[i+1].HideFromMake()
}
}
} else if o, ok := ctx.Module().(OverrideModule); ok {

View File

@@ -289,7 +289,7 @@ func PrebuiltPostDepsMutator(ctx BottomUpMutatorContext) {
})
}
} else {
m.SkipInstall()
m.HideFromMake()
}
}
}

View File

@@ -32,6 +32,7 @@ import (
const sboxSandboxBaseDir = "__SBOX_SANDBOX_DIR__"
const sboxOutSubDir = "out"
const sboxToolsSubDir = "tools"
const sboxOutDir = sboxSandboxBaseDir + "/" + sboxOutSubDir
// RuleBuilder provides an alternative to ModuleContext.Rule and ModuleContext.Build to add a command line to the build
@@ -48,6 +49,7 @@ type RuleBuilder struct {
highmem bool
remoteable RemoteRuleSupports
outDir WritablePath
sboxTools bool
sboxManifestPath WritablePath
missingDeps []string
}
@@ -140,6 +142,19 @@ func (r *RuleBuilder) Sbox(outputDir WritablePath, manifestPath WritablePath) *R
return r
}
// SandboxTools enables tool sandboxing for the rule by copying any referenced tools into the
// sandbox.
func (r *RuleBuilder) SandboxTools() *RuleBuilder {
if !r.sbox {
panic("SandboxTools() must be called after Sbox()")
}
if len(r.commands) > 0 {
panic("SandboxTools() may not be called after Command()")
}
r.sboxTools = true
return r
}
// Install associates an output of the rule with an install location, which can be retrieved later using
// RuleBuilder.Installs.
func (r *RuleBuilder) Install(from Path, to string) {
@@ -468,8 +483,29 @@ func (r *RuleBuilder) Build(name string, desc string) {
manifest.OutputDepfile = proto.String(depFile.String())
}
// If sandboxing tools is enabled, add copy rules to the manifest to copy each tool
// into the sbox directory.
if r.sboxTools {
for _, tool := range tools {
command.CopyBefore = append(command.CopyBefore, &sbox_proto.Copy{
From: proto.String(tool.String()),
To: proto.String(sboxPathForToolRel(r.ctx, tool)),
})
}
for _, c := range r.commands {
for _, tool := range c.packagedTools {
command.CopyBefore = append(command.CopyBefore, &sbox_proto.Copy{
From: proto.String(tool.srcPath.String()),
To: proto.String(sboxPathForPackagedToolRel(tool)),
Executable: proto.Bool(tool.executable),
})
tools = append(tools, tool.srcPath)
}
}
}
// Add copy rules to the manifest to copy each output file from the sbox directory.
// to the output directory.
// to the output directory after running the commands.
sboxOutputs := make([]string, len(outputs))
for i, output := range outputs {
rel := Rel(r.ctx, r.outDir.String(), output.String())
@@ -582,6 +618,7 @@ type RuleBuilderCommand struct {
symlinkOutputs WritablePaths
depFiles WritablePaths
tools Paths
packagedTools []PackagingSpec
rspFileInputs Paths
// spans [start,end) of the command that should not be ninja escaped
@@ -625,6 +662,79 @@ func (c *RuleBuilderCommand) PathForOutput(path WritablePath) string {
return path.String()
}
// SboxPathForTool takes a path to a tool, which may be an output file or a source file, and returns
// the corresponding path for the tool in the sbox sandbox. It assumes that sandboxing and tool
// sandboxing are enabled.
func SboxPathForTool(ctx BuilderContext, path Path) string {
return filepath.Join(sboxSandboxBaseDir, sboxPathForToolRel(ctx, path))
}
func sboxPathForToolRel(ctx BuilderContext, path Path) string {
// Errors will be handled in RuleBuilder.Build where we have a context to report them
relOut, isRelOut, _ := maybeRelErr(PathForOutput(ctx, "host", ctx.Config().PrebuiltOS()).String(), path.String())
if isRelOut {
// The tool is in the output directory, it will be copied to __SBOX_OUT_DIR__/tools/out
return filepath.Join(sboxToolsSubDir, "out", relOut)
}
// The tool is in the source directory, it will be copied to __SBOX_OUT_DIR__/tools/src
return filepath.Join(sboxToolsSubDir, "src", path.String())
}
// SboxPathForPackagedTool takes a PackageSpec for a tool and returns the corresponding path for the
// tool after copying it into the sandbox. This can be used on the RuleBuilder command line to
// reference the tool.
func SboxPathForPackagedTool(spec PackagingSpec) string {
return filepath.Join(sboxSandboxBaseDir, sboxPathForPackagedToolRel(spec))
}
func sboxPathForPackagedToolRel(spec PackagingSpec) string {
return filepath.Join(sboxToolsSubDir, "out", spec.relPathInPackage)
}
// PathForTool takes a path to a tool, which may be an output file or a source file, and returns
// the corresponding path for the tool in the sbox sandbox if sbox is enabled, or the original path
// if it is not. This can be used on the RuleBuilder command line to reference the tool.
func (c *RuleBuilderCommand) PathForTool(path Path) string {
if c.rule.sbox && c.rule.sboxTools {
return filepath.Join(sboxSandboxBaseDir, sboxPathForToolRel(c.rule.ctx, path))
}
return path.String()
}
// PackagedTool adds the specified tool path to the command line. It can only be used with tool
// sandboxing enabled by SandboxTools(), and will copy the tool into the sandbox.
func (c *RuleBuilderCommand) PackagedTool(spec PackagingSpec) *RuleBuilderCommand {
if !c.rule.sboxTools {
panic("PackagedTool() requires SandboxTools()")
}
c.packagedTools = append(c.packagedTools, spec)
c.Text(sboxPathForPackagedToolRel(spec))
return c
}
// ImplicitPackagedTool copies the specified tool into the sandbox without modifying the command
// line. It can only be used with tool sandboxing enabled by SandboxTools().
func (c *RuleBuilderCommand) ImplicitPackagedTool(spec PackagingSpec) *RuleBuilderCommand {
if !c.rule.sboxTools {
panic("ImplicitPackagedTool() requires SandboxTools()")
}
c.packagedTools = append(c.packagedTools, spec)
return c
}
// ImplicitPackagedTools copies the specified tools into the sandbox without modifying the command
// line. It can only be used with tool sandboxing enabled by SandboxTools().
func (c *RuleBuilderCommand) ImplicitPackagedTools(specs []PackagingSpec) *RuleBuilderCommand {
if !c.rule.sboxTools {
panic("ImplicitPackagedTools() requires SandboxTools()")
}
c.packagedTools = append(c.packagedTools, specs...)
return c
}
// Text adds the specified raw text to the command line. The text should not contain input or output paths or the
// rule will not have them listed in its dependencies or outputs.
func (c *RuleBuilderCommand) Text(text string) *RuleBuilderCommand {
@@ -693,7 +803,19 @@ func (c *RuleBuilderCommand) FlagWithList(flag string, list []string, sep string
// RuleBuilder.Tools.
func (c *RuleBuilderCommand) Tool(path Path) *RuleBuilderCommand {
c.tools = append(c.tools, path)
return c.Text(path.String())
return c.Text(c.PathForTool(path))
}
// Tool adds the specified tool path to the dependencies returned by RuleBuilder.Tools.
func (c *RuleBuilderCommand) ImplicitTool(path Path) *RuleBuilderCommand {
c.tools = append(c.tools, path)
return c
}
// Tool adds the specified tool path to the dependencies returned by RuleBuilder.Tools.
func (c *RuleBuilderCommand) ImplicitTools(paths Paths) *RuleBuilderCommand {
c.tools = append(c.tools, paths...)
return c
}
// BuiltTool adds the specified tool path that was built using a host Soong module to the command line. The path will

View File

@@ -436,6 +436,44 @@ func TestRuleBuilder(t *testing.T) {
t.Errorf("\nwant rule.depFileMergerCmd() = %#v\n got %#v", w, g)
}
})
t.Run("sbox tools", func(t *testing.T) {
rule := NewRuleBuilder(pctx, ctx).Sbox(PathForOutput(ctx, ""),
PathForOutput(ctx, "sbox.textproto")).SandboxTools()
addCommands(rule)
wantCommands := []string{
"__SBOX_SANDBOX_DIR__/out/DepFile Flag FlagWithArg=arg FlagWithDepFile=__SBOX_SANDBOX_DIR__/out/depfile FlagWithInput=input FlagWithOutput=__SBOX_SANDBOX_DIR__/out/output Input __SBOX_SANDBOX_DIR__/out/Output __SBOX_SANDBOX_DIR__/out/SymlinkOutput Text __SBOX_SANDBOX_DIR__/tools/src/Tool after command2 old cmd",
"command2 __SBOX_SANDBOX_DIR__/out/depfile2 input2 __SBOX_SANDBOX_DIR__/out/output2 __SBOX_SANDBOX_DIR__/tools/src/tool2",
"command3 input3 __SBOX_SANDBOX_DIR__/out/output2 __SBOX_SANDBOX_DIR__/out/output3",
}
wantDepMergerCommand := "__SBOX_SANDBOX_DIR__/tools/out/bin/dep_fixer __SBOX_SANDBOX_DIR__/out/DepFile __SBOX_SANDBOX_DIR__/out/depfile __SBOX_SANDBOX_DIR__/out/ImplicitDepFile __SBOX_SANDBOX_DIR__/out/depfile2"
if g, w := rule.Commands(), wantCommands; !reflect.DeepEqual(g, w) {
t.Errorf("\nwant rule.Commands() = %#v\n got %#v", w, g)
}
if g, w := rule.Inputs(), wantInputs; !reflect.DeepEqual(w, g) {
t.Errorf("\nwant rule.Inputs() = %#v\n got %#v", w, g)
}
if g, w := rule.Outputs(), wantOutputs; !reflect.DeepEqual(w, g) {
t.Errorf("\nwant rule.Outputs() = %#v\n got %#v", w, g)
}
if g, w := rule.DepFiles(), wantDepFiles; !reflect.DeepEqual(w, g) {
t.Errorf("\nwant rule.DepFiles() = %#v\n got %#v", w, g)
}
if g, w := rule.Tools(), wantTools; !reflect.DeepEqual(w, g) {
t.Errorf("\nwant rule.Tools() = %#v\n got %#v", w, g)
}
if g, w := rule.OrderOnlys(), wantOrderOnlys; !reflect.DeepEqual(w, g) {
t.Errorf("\nwant rule.OrderOnlys() = %#v\n got %#v", w, g)
}
if g, w := rule.depFileMergerCmd(rule.DepFiles()).String(), wantDepMergerCommand; g != w {
t.Errorf("\nwant rule.depFileMergerCmd() = %#v\n got %#v", w, g)
}
})
}
func testRuleBuilderFactory() Module {