Compare commits
13 commits
67b7f16add
...
b7e4d26faf
Author | SHA1 | Date | |
---|---|---|---|
|
b7e4d26faf | ||
|
6d13ab0b7f | ||
|
ece5b2fba8 | ||
|
28c638257d | ||
|
ad07561c07 | ||
|
27a62c91fd | ||
|
a3684d5d61 | ||
|
63acbad058 | ||
|
96cb91fe28 | ||
|
019fec2c06 | ||
|
e370708d90 | ||
|
2d4c300b08 | ||
|
6dd9fcc314 |
6 changed files with 75 additions and 161 deletions
|
@ -102,7 +102,6 @@ func RunBlueprint(args Args, stopBefore StopBefore, ctx *blueprint.Context, conf
|
||||||
ctx.RegisterBottomUpMutator("bootstrap_plugin_deps", pluginDeps)
|
ctx.RegisterBottomUpMutator("bootstrap_plugin_deps", pluginDeps)
|
||||||
ctx.RegisterSingletonType("bootstrap", newSingletonFactory(), false)
|
ctx.RegisterSingletonType("bootstrap", newSingletonFactory(), false)
|
||||||
RegisterGoModuleTypes(ctx)
|
RegisterGoModuleTypes(ctx)
|
||||||
blueprint.RegisterPackageIncludesModuleType(ctx)
|
|
||||||
|
|
||||||
ctx.BeginEvent("parse_bp")
|
ctx.BeginEvent("parse_bp")
|
||||||
if blueprintFiles, errs := ctx.ParseFileList(".", filesToParse, config); len(errs) > 0 {
|
if blueprintFiles, errs := ctx.ParseFileList(".", filesToParse, config); len(errs) > 0 {
|
||||||
|
|
79
context.go
79
context.go
|
@ -812,43 +812,10 @@ type shouldVisitFileInfo struct {
|
||||||
// This should be processed before adding any modules to the build graph
|
// This should be processed before adding any modules to the build graph
|
||||||
func shouldVisitFile(c *Context, file *parser.File) shouldVisitFileInfo {
|
func shouldVisitFile(c *Context, file *parser.File) shouldVisitFileInfo {
|
||||||
skippedModules := []string{}
|
skippedModules := []string{}
|
||||||
var blueprintPackageIncludes *PackageIncludes
|
|
||||||
for _, def := range file.Defs {
|
for _, def := range file.Defs {
|
||||||
switch def := def.(type) {
|
switch def := def.(type) {
|
||||||
case *parser.Module:
|
case *parser.Module:
|
||||||
skippedModules = append(skippedModules, def.Name())
|
skippedModules = append(skippedModules, def.Name())
|
||||||
if def.Type != "blueprint_package_includes" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
module, errs := processModuleDef(def, file.Name, c.moduleFactories, nil, c.ignoreUnknownModuleTypes)
|
|
||||||
if len(errs) > 0 {
|
|
||||||
// This file contains errors in blueprint_package_includes
|
|
||||||
// Visit anyways so that we can report errors on other modules in the file
|
|
||||||
return shouldVisitFileInfo{
|
|
||||||
shouldVisitFile: true,
|
|
||||||
errs: errs,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
logicModule, _ := c.cloneLogicModule(module)
|
|
||||||
blueprintPackageIncludes = logicModule.(*PackageIncludes)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if blueprintPackageIncludes != nil {
|
|
||||||
packageMatches, err := blueprintPackageIncludes.matchesIncludeTags(c)
|
|
||||||
if err != nil {
|
|
||||||
return shouldVisitFileInfo{
|
|
||||||
errs: []error{err},
|
|
||||||
}
|
|
||||||
} else if !packageMatches {
|
|
||||||
return shouldVisitFileInfo{
|
|
||||||
shouldVisitFile: false,
|
|
||||||
skippedModules: skippedModules,
|
|
||||||
reasonForSkip: fmt.Sprintf(
|
|
||||||
"module is defined in %q which contains a blueprint_package_includes module with unsatisfied tags",
|
|
||||||
file.Name,
|
|
||||||
),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5214,52 +5181,6 @@ Singleton: {{.name}}
|
||||||
Factory: {{.goFactory}}
|
Factory: {{.goFactory}}
|
||||||
`
|
`
|
||||||
|
|
||||||
// Blueprint module type that can be used to gate blueprint files beneath this directory
|
|
||||||
type PackageIncludes struct {
|
|
||||||
properties struct {
|
|
||||||
// Package will be included if all include tags in this list are set
|
|
||||||
Match_all []string
|
|
||||||
}
|
|
||||||
name *string `blueprint:"mutated"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (pi *PackageIncludes) Name() string {
|
|
||||||
return proptools.String(pi.name)
|
|
||||||
}
|
|
||||||
|
|
||||||
// This module type does not have any build actions
|
|
||||||
func (pi *PackageIncludes) GenerateBuildActions(ctx ModuleContext) {
|
|
||||||
}
|
|
||||||
|
|
||||||
func newPackageIncludesFactory() (Module, []interface{}) {
|
|
||||||
module := &PackageIncludes{}
|
|
||||||
AddLoadHook(module, func(ctx LoadHookContext) {
|
|
||||||
module.name = proptools.StringPtr(ctx.ModuleDir() + "_includes") // Generate a synthetic name
|
|
||||||
})
|
|
||||||
return module, []interface{}{&module.properties}
|
|
||||||
}
|
|
||||||
|
|
||||||
func RegisterPackageIncludesModuleType(ctx *Context) {
|
|
||||||
ctx.RegisterModuleType("blueprint_package_includes", newPackageIncludesFactory)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (pi *PackageIncludes) MatchAll() []string {
|
|
||||||
return pi.properties.Match_all
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns true if all requested include tags are set in the Context object
|
|
||||||
func (pi *PackageIncludes) matchesIncludeTags(ctx *Context) (bool, error) {
|
|
||||||
if len(pi.MatchAll()) == 0 {
|
|
||||||
return false, ctx.ModuleErrorf(pi, "Match_all must be a non-empty list")
|
|
||||||
}
|
|
||||||
for _, includeTag := range pi.MatchAll() {
|
|
||||||
if !ctx.ContainsIncludeTag(includeTag) {
|
|
||||||
return false, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func JoinPath(base, path string) string {
|
func JoinPath(base, path string) string {
|
||||||
if filepath.IsAbs(path) {
|
if filepath.IsAbs(path) {
|
||||||
return path
|
return path
|
||||||
|
|
|
@ -19,7 +19,6 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"hash/fnv"
|
"hash/fnv"
|
||||||
"path/filepath"
|
|
||||||
"reflect"
|
"reflect"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -1089,78 +1088,6 @@ func Test_parallelVisit(t *testing.T) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPackageIncludes(t *testing.T) {
|
|
||||||
dir1_foo_bp := `
|
|
||||||
blueprint_package_includes {
|
|
||||||
match_all: ["use_dir1"],
|
|
||||||
}
|
|
||||||
foo_module {
|
|
||||||
name: "foo",
|
|
||||||
}
|
|
||||||
`
|
|
||||||
dir2_foo_bp := `
|
|
||||||
blueprint_package_includes {
|
|
||||||
match_all: ["use_dir2"],
|
|
||||||
}
|
|
||||||
foo_module {
|
|
||||||
name: "foo",
|
|
||||||
}
|
|
||||||
`
|
|
||||||
mockFs := map[string][]byte{
|
|
||||||
"dir1/Android.bp": []byte(dir1_foo_bp),
|
|
||||||
"dir2/Android.bp": []byte(dir2_foo_bp),
|
|
||||||
}
|
|
||||||
testCases := []struct {
|
|
||||||
desc string
|
|
||||||
includeTags []string
|
|
||||||
expectedDir string
|
|
||||||
expectedErr string
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
desc: "use_dir1 is set, use dir1 foo",
|
|
||||||
includeTags: []string{"use_dir1"},
|
|
||||||
expectedDir: "dir1",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
desc: "use_dir2 is set, use dir2 foo",
|
|
||||||
includeTags: []string{"use_dir2"},
|
|
||||||
expectedDir: "dir2",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
desc: "duplicate module error if both use_dir1 and use_dir2 are set",
|
|
||||||
includeTags: []string{"use_dir1", "use_dir2"},
|
|
||||||
expectedDir: "",
|
|
||||||
expectedErr: `module "foo" already defined`,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
for _, tc := range testCases {
|
|
||||||
t.Run(tc.desc, func(t *testing.T) {
|
|
||||||
ctx := NewContext()
|
|
||||||
// Register mock FS
|
|
||||||
ctx.MockFileSystem(mockFs)
|
|
||||||
// Register module types
|
|
||||||
ctx.RegisterModuleType("foo_module", newFooModule)
|
|
||||||
RegisterPackageIncludesModuleType(ctx)
|
|
||||||
// Add include tags for test case
|
|
||||||
ctx.AddIncludeTags(tc.includeTags...)
|
|
||||||
// Run test
|
|
||||||
_, actualErrs := ctx.ParseFileList(".", []string{"dir1/Android.bp", "dir2/Android.bp"}, nil)
|
|
||||||
// Evaluate
|
|
||||||
if !strings.Contains(fmt.Sprintf("%s", actualErrs), fmt.Sprintf("%s", tc.expectedErr)) {
|
|
||||||
t.Errorf("Expected errors: %s, got errors: %s\n", tc.expectedErr, actualErrs)
|
|
||||||
}
|
|
||||||
if tc.expectedErr != "" {
|
|
||||||
return // expectedDir check not necessary
|
|
||||||
}
|
|
||||||
actualBpFile := ctx.moduleGroupFromName("foo", nil).modules.firstModule().relBlueprintsFile
|
|
||||||
if tc.expectedDir != filepath.Dir(actualBpFile) {
|
|
||||||
t.Errorf("Expected foo from %s, got %s\n", tc.expectedDir, filepath.Dir(actualBpFile))
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestDeduplicateOrderOnlyDeps(t *testing.T) {
|
func TestDeduplicateOrderOnlyDeps(t *testing.T) {
|
||||||
b := func(output string, inputs []string, orderOnlyDeps []string) *buildDef {
|
b := func(output string, inputs []string, orderOnlyDeps []string) *buildDef {
|
||||||
return &buildDef{
|
return &buildDef{
|
||||||
|
@ -1532,7 +1459,6 @@ func TestSourceRootDirs(t *testing.T) {
|
||||||
ctx.RegisterModuleType("foo_module", newFooModule)
|
ctx.RegisterModuleType("foo_module", newFooModule)
|
||||||
ctx.RegisterBottomUpMutator("deps", depsMutator)
|
ctx.RegisterBottomUpMutator("deps", depsMutator)
|
||||||
ctx.AddSourceRootDirs(tc.sourceRootDirs...)
|
ctx.AddSourceRootDirs(tc.sourceRootDirs...)
|
||||||
RegisterPackageIncludesModuleType(ctx)
|
|
||||||
ctx.ParseFileList(".", fileList, nil)
|
ctx.ParseFileList(".", fileList, nil)
|
||||||
_, actualErrs := ctx.ResolveDependencies(nil)
|
_, actualErrs := ctx.ResolveDependencies(nil)
|
||||||
|
|
||||||
|
|
|
@ -227,7 +227,7 @@ func (p *printer) printSelect(s *Select) {
|
||||||
} else {
|
} else {
|
||||||
p.printExpression(c.Value)
|
p.printExpression(c.Value)
|
||||||
}
|
}
|
||||||
p.printToken(",", c.Value.Pos())
|
p.printToken(",", c.Value.End())
|
||||||
}
|
}
|
||||||
p.requestNewline()
|
p.requestNewline()
|
||||||
p.unindent(s.RBracePos)
|
p.unindent(s.RBracePos)
|
||||||
|
|
|
@ -696,6 +696,43 @@ foo {
|
||||||
(default, default): "b",
|
(default, default): "b",
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
|
`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Select with multiline inner expression",
|
||||||
|
input: `
|
||||||
|
foo {
|
||||||
|
cflags: [
|
||||||
|
"-DPRODUCT_COMPATIBLE_PROPERTY",
|
||||||
|
"-DRIL_SHLIB",
|
||||||
|
"-Wall",
|
||||||
|
"-Wextra",
|
||||||
|
"-Werror",
|
||||||
|
] + select(soong_config_variable("sim", "sim_count"), {
|
||||||
|
"2": [
|
||||||
|
"-DANDROID_MULTI_SIM",
|
||||||
|
"-DANDROID_SIM_COUNT_2",
|
||||||
|
],
|
||||||
|
default: [],
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
output: `
|
||||||
|
foo {
|
||||||
|
cflags: [
|
||||||
|
"-DPRODUCT_COMPATIBLE_PROPERTY",
|
||||||
|
"-DRIL_SHLIB",
|
||||||
|
"-Wall",
|
||||||
|
"-Werror",
|
||||||
|
"-Wextra",
|
||||||
|
] + select(soong_config_variable("sim", "sim_count"), {
|
||||||
|
"2": [
|
||||||
|
"-DANDROID_MULTI_SIM",
|
||||||
|
"-DANDROID_SIM_COUNT_2",
|
||||||
|
],
|
||||||
|
default: [],
|
||||||
|
}),
|
||||||
|
}
|
||||||
`,
|
`,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -296,7 +296,7 @@ func NewConfigurableCase[T ConfigurableElements](patterns []ConfigurablePattern,
|
||||||
patterns = slices.Clone(patterns)
|
patterns = slices.Clone(patterns)
|
||||||
return ConfigurableCase[T]{
|
return ConfigurableCase[T]{
|
||||||
patterns: patterns,
|
patterns: patterns,
|
||||||
value: copyConfiguredValue(value),
|
value: copyConfiguredValuePtr(value),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -408,6 +408,22 @@ func NewConfigurable[T ConfigurableElements](conditions []ConfigurableCondition,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Configurable[T]) AppendSimpleValue(value T) {
|
||||||
|
value = copyConfiguredValue(value)
|
||||||
|
// This may be a property that was never initialized from a bp file
|
||||||
|
if c.inner == nil {
|
||||||
|
c.inner = &configurableInner[T]{
|
||||||
|
single: singleConfigurable[T]{
|
||||||
|
cases: []ConfigurableCase[T]{{
|
||||||
|
value: &value,
|
||||||
|
}},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
c.inner.appendSimpleValue(value)
|
||||||
|
}
|
||||||
|
|
||||||
// Get returns the final value for the configurable property.
|
// Get returns the final value for the configurable property.
|
||||||
// A configurable property may be unset, in which case Get will return nil.
|
// A configurable property may be unset, in which case Get will return nil.
|
||||||
func (c *Configurable[T]) Get(evaluator ConfigurableEvaluator) ConfigurableOptional[T] {
|
func (c *Configurable[T]) Get(evaluator ConfigurableEvaluator) ConfigurableOptional[T] {
|
||||||
|
@ -420,7 +436,7 @@ func (c *Configurable[T]) GetOrDefault(evaluator ConfigurableEvaluator, defaultV
|
||||||
result := c.inner.evaluate(c.propertyName, evaluator)
|
result := c.inner.evaluate(c.propertyName, evaluator)
|
||||||
if result != nil {
|
if result != nil {
|
||||||
// Copy the result so that it can't be changed from soong
|
// Copy the result so that it can't be changed from soong
|
||||||
return copyAndDereferenceConfiguredValue(result)
|
return copyConfiguredValue(*result)
|
||||||
}
|
}
|
||||||
return defaultValue
|
return defaultValue
|
||||||
}
|
}
|
||||||
|
@ -628,6 +644,21 @@ func (c *configurableInner[T]) setAppend(append *configurableInner[T], replace b
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *configurableInner[T]) appendSimpleValue(value T) {
|
||||||
|
if c.next == nil {
|
||||||
|
c.replace = false
|
||||||
|
c.next = &configurableInner[T]{
|
||||||
|
single: singleConfigurable[T]{
|
||||||
|
cases: []ConfigurableCase[T]{{
|
||||||
|
value: &value,
|
||||||
|
}},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
c.next.appendSimpleValue(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (c Configurable[T]) printfInto(value string) error {
|
func (c Configurable[T]) printfInto(value string) error {
|
||||||
return c.inner.printfInto(value)
|
return c.inner.printfInto(value)
|
||||||
}
|
}
|
||||||
|
@ -754,7 +785,7 @@ func (c Configurable[T]) configuredType() reflect.Type {
|
||||||
return reflect.TypeOf((*T)(nil)).Elem()
|
return reflect.TypeOf((*T)(nil)).Elem()
|
||||||
}
|
}
|
||||||
|
|
||||||
func copyConfiguredValue[T ConfigurableElements](t *T) *T {
|
func copyConfiguredValuePtr[T ConfigurableElements](t *T) *T {
|
||||||
if t == nil {
|
if t == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -781,12 +812,12 @@ func configuredValuePtrToOptional[T ConfigurableElements](t *T) ConfigurableOpti
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func copyAndDereferenceConfiguredValue[T ConfigurableElements](t *T) T {
|
func copyConfiguredValue[T ConfigurableElements](t T) T {
|
||||||
switch t2 := any(*t).(type) {
|
switch t2 := any(t).(type) {
|
||||||
case []string:
|
case []string:
|
||||||
return any(slices.Clone(t2)).(T)
|
return any(slices.Clone(t2)).(T)
|
||||||
default:
|
default:
|
||||||
return *t
|
return t
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue