Make OutputFileForModule work for AllowMissingDependencies
Report missing output files as missing dependencies when AllowMissingDependencies is enabled. This will fix AllowMissingDependencies builds where a dependency module is present but missing support for a specific architecture. Bug: 250918230 Test: lunch aosp_riscv64-userdebug && m ALLOW_MISSING_DEPENDENCIES=true nothing Test: TestOutputFileForModule Change-Id: I95e96e3e7cb3df7bf678ed628b45baf659addbad
This commit is contained in:
@@ -15,10 +15,32 @@
|
|||||||
package android
|
package android
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestMain(m *testing.M) {
|
var buildDir string
|
||||||
os.Exit(m.Run())
|
|
||||||
|
func setUp() {
|
||||||
|
var err error
|
||||||
|
buildDir, err = ioutil.TempDir("", "android_test")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func tearDown() {
|
||||||
|
os.RemoveAll(buildDir)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMain(m *testing.M) {
|
||||||
|
run := func() int {
|
||||||
|
setUp()
|
||||||
|
defer tearDown()
|
||||||
|
|
||||||
|
return m.Run()
|
||||||
|
}
|
||||||
|
|
||||||
|
os.Exit(run())
|
||||||
}
|
}
|
||||||
|
@@ -3546,10 +3546,29 @@ func OutputFileForModule(ctx PathContext, module blueprint.Module, tag string) P
|
|||||||
reportPathError(ctx, err)
|
reportPathError(ctx, err)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
if len(paths) == 0 {
|
||||||
|
type addMissingDependenciesIntf interface {
|
||||||
|
AddMissingDependencies([]string)
|
||||||
|
OtherModuleName(blueprint.Module) string
|
||||||
|
}
|
||||||
|
if mctx, ok := ctx.(addMissingDependenciesIntf); ok && ctx.Config().AllowMissingDependencies() {
|
||||||
|
mctx.AddMissingDependencies([]string{mctx.OtherModuleName(module)})
|
||||||
|
} else {
|
||||||
|
ReportPathErrorf(ctx, "failed to get output files from module %q", pathContextName(ctx, module))
|
||||||
|
}
|
||||||
|
// Return a fake output file to avoid nil dereferences of Path objects later.
|
||||||
|
// This should never get used for an actual build as the error or missing
|
||||||
|
// dependency has already been reported.
|
||||||
|
p, err := pathForSource(ctx, filepath.Join("missing_output_file", pathContextName(ctx, module)))
|
||||||
|
if err != nil {
|
||||||
|
reportPathError(ctx, err)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return p
|
||||||
|
}
|
||||||
if len(paths) > 1 {
|
if len(paths) > 1 {
|
||||||
ReportPathErrorf(ctx, "got multiple output files from module %q, expected exactly one",
|
ReportPathErrorf(ctx, "got multiple output files from module %q, expected exactly one",
|
||||||
pathContextName(ctx, module))
|
pathContextName(ctx, module))
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
return paths[0]
|
return paths[0]
|
||||||
}
|
}
|
||||||
@@ -3561,18 +3580,12 @@ func outputFilesForModule(ctx PathContext, module blueprint.Module, tag string)
|
|||||||
return nil, fmt.Errorf("failed to get output file from module %q: %s",
|
return nil, fmt.Errorf("failed to get output file from module %q: %s",
|
||||||
pathContextName(ctx, module), err.Error())
|
pathContextName(ctx, module), err.Error())
|
||||||
}
|
}
|
||||||
if len(paths) == 0 {
|
|
||||||
return nil, fmt.Errorf("failed to get output files from module %q", pathContextName(ctx, module))
|
|
||||||
}
|
|
||||||
return paths, nil
|
return paths, nil
|
||||||
} else if sourceFileProducer, ok := module.(SourceFileProducer); ok {
|
} else if sourceFileProducer, ok := module.(SourceFileProducer); ok {
|
||||||
if tag != "" {
|
if tag != "" {
|
||||||
return nil, fmt.Errorf("module %q is a SourceFileProducer, not an OutputFileProducer, and so does not support tag %q", pathContextName(ctx, module), tag)
|
return nil, fmt.Errorf("module %q is a SourceFileProducer, not an OutputFileProducer, and so does not support tag %q", pathContextName(ctx, module), tag)
|
||||||
}
|
}
|
||||||
paths := sourceFileProducer.Srcs()
|
paths := sourceFileProducer.Srcs()
|
||||||
if len(paths) == 0 {
|
|
||||||
return nil, fmt.Errorf("failed to get output files from module %q", pathContextName(ctx, module))
|
|
||||||
}
|
|
||||||
return paths, nil
|
return paths, nil
|
||||||
} else {
|
} else {
|
||||||
return nil, fmt.Errorf("module %q is not an OutputFileProducer", pathContextName(ctx, module))
|
return nil, fmt.Errorf("module %q is not an OutputFileProducer", pathContextName(ctx, module))
|
||||||
|
@@ -15,6 +15,7 @@
|
|||||||
package android
|
package android
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/google/blueprint"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
"testing"
|
"testing"
|
||||||
@@ -978,3 +979,88 @@ func TestSetAndroidMkEntriesWithTestOptions(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type fakeBlueprintModule struct{}
|
||||||
|
|
||||||
|
func (fakeBlueprintModule) Name() string { return "foo" }
|
||||||
|
|
||||||
|
func (fakeBlueprintModule) GenerateBuildActions(blueprint.ModuleContext) {}
|
||||||
|
|
||||||
|
type sourceProducerTestModule struct {
|
||||||
|
fakeBlueprintModule
|
||||||
|
source Path
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s sourceProducerTestModule) Srcs() Paths { return Paths{s.source} }
|
||||||
|
|
||||||
|
type outputFileProducerTestModule struct {
|
||||||
|
fakeBlueprintModule
|
||||||
|
output map[string]Path
|
||||||
|
error map[string]error
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o outputFileProducerTestModule) OutputFiles(tag string) (Paths, error) {
|
||||||
|
return PathsIfNonNil(o.output[tag]), o.error[tag]
|
||||||
|
}
|
||||||
|
|
||||||
|
type pathContextAddMissingDependenciesWrapper struct {
|
||||||
|
PathContext
|
||||||
|
missingDeps []string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *pathContextAddMissingDependenciesWrapper) AddMissingDependencies(deps []string) {
|
||||||
|
p.missingDeps = append(p.missingDeps, deps...)
|
||||||
|
}
|
||||||
|
func (p *pathContextAddMissingDependenciesWrapper) OtherModuleName(module blueprint.Module) string {
|
||||||
|
return module.Name()
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestOutputFileForModule(t *testing.T) {
|
||||||
|
testcases := []struct {
|
||||||
|
name string
|
||||||
|
module blueprint.Module
|
||||||
|
tag string
|
||||||
|
env map[string]string
|
||||||
|
config func(*config)
|
||||||
|
expected string
|
||||||
|
missingDeps []string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "SourceFileProducer",
|
||||||
|
module: &sourceProducerTestModule{source: PathForTesting("foo.txt")},
|
||||||
|
expected: "foo.txt",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "OutputFileProducer",
|
||||||
|
module: &outputFileProducerTestModule{output: map[string]Path{"": PathForTesting("foo.txt")}},
|
||||||
|
expected: "foo.txt",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "OutputFileProducer_tag",
|
||||||
|
module: &outputFileProducerTestModule{output: map[string]Path{"foo": PathForTesting("foo.txt")}},
|
||||||
|
tag: "foo",
|
||||||
|
expected: "foo.txt",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "OutputFileProducer_AllowMissingDependencies",
|
||||||
|
config: func(config *config) {
|
||||||
|
config.TestProductVariables.Allow_missing_dependencies = boolPtr(true)
|
||||||
|
},
|
||||||
|
module: &outputFileProducerTestModule{},
|
||||||
|
missingDeps: []string{"foo"},
|
||||||
|
expected: "missing_output_file/foo",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range testcases {
|
||||||
|
config := TestConfig(buildDir, tt.env, "", nil)
|
||||||
|
if tt.config != nil {
|
||||||
|
tt.config(config.config)
|
||||||
|
}
|
||||||
|
ctx := &pathContextAddMissingDependenciesWrapper{
|
||||||
|
PathContext: PathContextForTesting(config),
|
||||||
|
}
|
||||||
|
got := OutputFileForModule(ctx, tt.module, tt.tag)
|
||||||
|
AssertPathRelativeToTopEquals(t, "expected source path", tt.expected, got)
|
||||||
|
AssertArrayString(t, "expected missing deps", tt.missingDeps, ctx.missingDeps)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user