Merge changes from topic "gcov-prefix-permissions-fix"
* changes:
Wrap getenv when linking a coverage-enabled binary
Refactor libprofile-extras to be added as a whole static library
diff --git a/README.md b/README.md
index ebbe8bc..531ef4c 100644
--- a/README.md
+++ b/README.md
@@ -337,6 +337,19 @@
This will bind mount the Soong source directories into the directory in the layout expected by
the IDE.
+### Running Soong in a debugger
+
+To run the soong_build process in a debugger, install `dlv` and then start the build with
+`SOONG_DELVE=<listen addr>` in the environment.
+For examle:
+```bash
+SOONG_DELVE=:1234 m nothing
+```
+and then in another terminal:
+```
+dlv connect :1234
+```
+
## Contact
Email android-building@googlegroups.com (external) for any questions, or see
diff --git a/android/androidmk.go b/android/androidmk.go
index 7d0aa3b..9bc2692 100644
--- a/android/androidmk.go
+++ b/android/androidmk.go
@@ -216,7 +216,10 @@
}
a.SetBoolIfTrue("LOCAL_ODM_MODULE", Bool(amod.commonProperties.Device_specific))
a.SetBoolIfTrue("LOCAL_PRODUCT_MODULE", Bool(amod.commonProperties.Product_specific))
- a.SetBoolIfTrue("LOCAL_PRODUCT_SERVICES_MODULE", Bool(amod.commonProperties.Product_services_specific))
+ // TODO(b/135957588) product_services_specific is matched to LOCAL_PRODUCT_MODULE
+ // as a workaround. Remove this after clearing all Android.bp
+ a.SetBoolIfTrue("LOCAL_PRODUCT_MODULE", Bool(amod.commonProperties.Product_services_specific))
+ a.SetBoolIfTrue("LOCAL_SYSTEM_EXT_MODULE", Bool(amod.commonProperties.System_ext_specific))
if amod.commonProperties.Owner != nil {
a.SetString("LOCAL_MODULE_OWNER", *amod.commonProperties.Owner)
}
diff --git a/android/config.go b/android/config.go
index e4012fa..c0ed50f 100644
--- a/android/config.go
+++ b/android/config.go
@@ -901,11 +901,11 @@
return "product"
}
-func (c *deviceConfig) ProductServicesPath() string {
- if c.config.productVariables.ProductServicesPath != nil {
- return *c.config.productVariables.ProductServicesPath
+func (c *deviceConfig) SystemExtPath() string {
+ if c.config.productVariables.SystemExtPath != nil {
+ return *c.config.productVariables.SystemExtPath
}
- return "product_services"
+ return "system_ext"
}
func (c *deviceConfig) BtConfigIncludeDir() string {
diff --git a/android/defaults.go b/android/defaults.go
index 844b4d4..ae2c820 100644
--- a/android/defaults.go
+++ b/android/defaults.go
@@ -63,9 +63,28 @@
type DefaultsModuleBase struct {
DefaultableModuleBase
- defaultProperties []interface{}
}
+// The common pattern for defaults modules is to register separate instances of
+// the xxxProperties structs in the AddProperties calls, rather than reusing the
+// ones inherited from Module.
+//
+// The effect is that e.g. myDefaultsModuleInstance.base().xxxProperties won't
+// contain the values that have been set for the defaults module. Rather, to
+// retrieve the values it is necessary to iterate over properties(). E.g. to get
+// the commonProperties instance that have the real values:
+//
+// d := myModule.(Defaults)
+// for _, props := range d.properties() {
+// if cp, ok := props.(*commonProperties); ok {
+// ... access property values in cp ...
+// }
+// }
+//
+// The rationale is that the properties on a defaults module apply to the
+// defaultable modules using it, not to the defaults module itself. E.g. setting
+// the "enabled" property false makes inheriting modules disabled by default,
+// rather than disabling the defaults module itself.
type Defaults interface {
Defaultable
isDefaults() bool
diff --git a/android/env.go b/android/env.go
index 469dfff..d9f2db2 100644
--- a/android/env.go
+++ b/android/env.go
@@ -16,6 +16,7 @@
import (
"os"
+ "os/exec"
"strings"
"android/soong/env"
@@ -29,8 +30,16 @@
// a manifest regeneration.
var originalEnv map[string]string
+var SoongDelveListen string
+var SoongDelvePath string
func init() {
+ // Delve support needs to read this environment variable very early, before NewConfig has created a way to
+ // access originalEnv with dependencies. Store the value where soong_build can find it, it will manually
+ // ensure the dependencies are created.
+ SoongDelveListen = os.Getenv("SOONG_DELVE")
+ SoongDelvePath, _ = exec.LookPath("dlv")
+
originalEnv = make(map[string]string)
for _, env := range os.Environ() {
idx := strings.IndexRune(env, '=')
@@ -38,6 +47,8 @@
originalEnv[env[:idx]] = env[idx+1:]
}
}
+ // Clear the environment to prevent use of os.Getenv(), which would not provide dependencies on environment
+ // variable values. The environment is available through ctx.Config().Getenv, ctx.Config().IsEnvTrue, etc.
os.Clearenv()
}
diff --git a/android/hooks.go b/android/hooks.go
index 2d2f797..5810996 100644
--- a/android/hooks.go
+++ b/android/hooks.go
@@ -129,6 +129,8 @@
func LoadHookMutator(ctx TopDownMutatorContext) {
if m, ok := ctx.Module().(Module); ok {
+ m.base().commonProperties.DebugName = ctx.ModuleName()
+
// Cast through *topDownMutatorContext because AppendProperties is implemented
// on *topDownMutatorContext but not exposed through TopDownMutatorContext
var loadHookCtx LoadHookContext = ctx.(*topDownMutatorContext)
diff --git a/android/module.go b/android/module.go
index 43b8763..adb9454 100644
--- a/android/module.go
+++ b/android/module.go
@@ -126,7 +126,7 @@
DeviceSpecific() bool
SocSpecific() bool
ProductSpecific() bool
- ProductServicesSpecific() bool
+ SystemExtSpecific() bool
AConfig() Config
DeviceConfig() DeviceConfig
}
@@ -203,6 +203,9 @@
RuleParamsForTests() map[blueprint.Rule]blueprint.RuleParams
VariablesForTests() map[string]string
+ // String returns a string that includes the module name and variants for printing during debugging.
+ String() string
+
// Get the qualified module id for this module.
qualifiedModuleId(ctx BaseModuleContext) qualifiedModuleName
@@ -347,11 +350,15 @@
// /system/product if product partition does not exist).
Product_specific *bool
- // whether this module provides services owned by the OS provider to the core platform. When set
- // to true, it is installed into /product_services (or /system/product_services if
- // product_services partition does not exist).
+ // TODO(b/135957588) Product_services_specific will be removed once we clear all Android.bp
+ // files that have 'product_services_specific: true'. This will be converted to
+ // Product_speicific as a workaround.
Product_services_specific *bool
+ // whether this module extends system. When set to true, it is installed into /system_ext
+ // (or /system/system_ext if system_ext partition does not exist).
+ System_ext_specific *bool
+
// Whether this module is installed to recovery partition
Recovery *bool
@@ -408,6 +415,11 @@
NamespaceExportedToMake bool `blueprint:"mutated"`
MissingDeps []string `blueprint:"mutated"`
+
+ // Name and variant strings stored by mutators to enable Module.String()
+ DebugName string `blueprint:"mutated"`
+ DebugMutators []string `blueprint:"mutated"`
+ DebugVariations []string `blueprint:"mutated"`
}
type hostAndDeviceProperties struct {
@@ -461,7 +473,7 @@
deviceSpecificModule
socSpecificModule
productSpecificModule
- productServicesSpecificModule
+ systemExtSpecificModule
)
func (k moduleKind) String() string {
@@ -474,8 +486,8 @@
return "soc-specific"
case productSpecificModule:
return "product-specific"
- case productServicesSpecificModule:
- return "productservices-specific"
+ case systemExtSpecificModule:
+ return "systemext-specific"
default:
panic(fmt.Errorf("unknown module kind %d", k))
}
@@ -625,6 +637,23 @@
return String(m.nameProperties.Name)
}
+// String returns a string that includes the module name and variants for printing during debugging.
+func (m *ModuleBase) String() string {
+ sb := strings.Builder{}
+ sb.WriteString(m.commonProperties.DebugName)
+ sb.WriteString("{")
+ for i := range m.commonProperties.DebugMutators {
+ if i != 0 {
+ sb.WriteString(",")
+ }
+ sb.WriteString(m.commonProperties.DebugMutators[i])
+ sb.WriteString(":")
+ sb.WriteString(m.commonProperties.DebugVariations[i])
+ }
+ sb.WriteString("}")
+ return sb.String()
+}
+
// BaseModuleName returns the name of the module as specified in the blueprints file.
func (m *ModuleBase) BaseModuleName() string {
return String(m.nameProperties.Name)
@@ -713,7 +742,7 @@
}
func (m *ModuleBase) Platform() bool {
- return !m.DeviceSpecific() && !m.SocSpecific() && !m.ProductSpecific() && !m.ProductServicesSpecific()
+ return !m.DeviceSpecific() && !m.SocSpecific() && !m.ProductSpecific() && !m.SystemExtSpecific()
}
func (m *ModuleBase) DeviceSpecific() bool {
@@ -728,8 +757,8 @@
return Bool(m.commonProperties.Product_specific)
}
-func (m *ModuleBase) ProductServicesSpecific() bool {
- return Bool(m.commonProperties.Product_services_specific)
+func (m *ModuleBase) SystemExtSpecific() bool {
+ return Bool(m.commonProperties.System_ext_specific)
}
func (m *ModuleBase) Enabled() bool {
@@ -850,7 +879,7 @@
var socSpecific = Bool(m.commonProperties.Vendor) || Bool(m.commonProperties.Proprietary) || Bool(m.commonProperties.Soc_specific)
var deviceSpecific = Bool(m.commonProperties.Device_specific)
var productSpecific = Bool(m.commonProperties.Product_specific)
- var productServicesSpecific = Bool(m.commonProperties.Product_services_specific)
+ var systemExtSpecific = Bool(m.commonProperties.System_ext_specific)
msg := "conflicting value set here"
if socSpecific && deviceSpecific {
@@ -866,16 +895,16 @@
}
}
- if productSpecific && productServicesSpecific {
- ctx.PropertyErrorf("product_specific", "a module cannot be specific to product and product_services at the same time.")
- ctx.PropertyErrorf("product_services_specific", msg)
+ if productSpecific && systemExtSpecific {
+ ctx.PropertyErrorf("product_specific", "a module cannot be specific to product and system_ext at the same time.")
+ ctx.PropertyErrorf("system_ext_specific", msg)
}
- if (socSpecific || deviceSpecific) && (productSpecific || productServicesSpecific) {
+ if (socSpecific || deviceSpecific) && (productSpecific || systemExtSpecific) {
if productSpecific {
ctx.PropertyErrorf("product_specific", "a module cannot be specific to SoC or device and product at the same time.")
} else {
- ctx.PropertyErrorf("product_services_specific", "a module cannot be specific to SoC or device and product_services at the same time.")
+ ctx.PropertyErrorf("system_ext_specific", "a module cannot be specific to SoC or device and system_ext at the same time.")
}
if deviceSpecific {
ctx.PropertyErrorf("device_specific", msg)
@@ -894,8 +923,8 @@
if productSpecific {
return productSpecificModule
- } else if productServicesSpecific {
- return productServicesSpecificModule
+ } else if systemExtSpecific {
+ return systemExtSpecificModule
} else if deviceSpecific {
return deviceSpecificModule
} else if socSpecific {
@@ -1408,18 +1437,18 @@
return b.kind == productSpecificModule
}
-func (b *baseModuleContext) ProductServicesSpecific() bool {
- return b.kind == productServicesSpecificModule
+func (b *baseModuleContext) SystemExtSpecific() bool {
+ return b.kind == systemExtSpecificModule
}
// Makes this module a platform module, i.e. not specific to soc, device,
-// product, or product_services.
+// product, or system_ext.
func (m *ModuleBase) MakeAsPlatform() {
m.commonProperties.Vendor = boolPtr(false)
m.commonProperties.Proprietary = boolPtr(false)
m.commonProperties.Soc_specific = boolPtr(false)
m.commonProperties.Product_specific = boolPtr(false)
- m.commonProperties.Product_services_specific = boolPtr(false)
+ m.commonProperties.System_ext_specific = boolPtr(false)
}
func (m *ModuleBase) EnableNativeBridgeSupportByDefault() {
diff --git a/android/mutator.go b/android/mutator.go
index 070b420..b799432 100644
--- a/android/mutator.go
+++ b/android/mutator.go
@@ -117,6 +117,8 @@
type TopDownMutatorContext interface {
BaseModuleContext
+ MutatorName() string
+
Rename(name string)
CreateModule(blueprint.ModuleFactory, ...interface{})
@@ -132,6 +134,8 @@
type BottomUpMutatorContext interface {
BaseModuleContext
+ MutatorName() string
+
Rename(name string)
AddDependency(module blueprint.Module, tag blueprint.DependencyTag, name ...string)
@@ -229,16 +233,26 @@
// non-overridden method has to be forwarded. There are fewer non-overridden methods, so use the latter. The following
// methods forward to the identical blueprint versions for topDownMutatorContext and bottomUpMutatorContext.
+func (t *topDownMutatorContext) MutatorName() string {
+ return t.bp.MutatorName()
+}
+
func (t *topDownMutatorContext) Rename(name string) {
t.bp.Rename(name)
+ t.Module().base().commonProperties.DebugName = name
}
func (t *topDownMutatorContext) CreateModule(factory blueprint.ModuleFactory, props ...interface{}) {
t.bp.CreateModule(factory, props...)
}
+func (b *bottomUpMutatorContext) MutatorName() string {
+ return b.bp.MutatorName()
+}
+
func (b *bottomUpMutatorContext) Rename(name string) {
b.bp.Rename(name)
+ b.Module().base().commonProperties.DebugName = name
}
func (b *bottomUpMutatorContext) AddDependency(module blueprint.Module, tag blueprint.DependencyTag, name ...string) {
@@ -250,11 +264,27 @@
}
func (b *bottomUpMutatorContext) CreateVariations(variations ...string) []blueprint.Module {
- return b.bp.CreateVariations(variations...)
+ modules := b.bp.CreateVariations(variations...)
+
+ for i := range variations {
+ base := modules[i].(Module).base()
+ base.commonProperties.DebugMutators = append(base.commonProperties.DebugMutators, b.MutatorName())
+ base.commonProperties.DebugVariations = append(base.commonProperties.DebugVariations, variations[i])
+ }
+
+ return modules
}
func (b *bottomUpMutatorContext) CreateLocalVariations(variations ...string) []blueprint.Module {
- return b.bp.CreateLocalVariations(variations...)
+ modules := b.bp.CreateLocalVariations(variations...)
+
+ for i := range variations {
+ base := modules[i].(Module).base()
+ base.commonProperties.DebugMutators = append(base.commonProperties.DebugMutators, b.MutatorName())
+ base.commonProperties.DebugVariations = append(base.commonProperties.DebugVariations, variations[i])
+ }
+
+ return modules
}
func (b *bottomUpMutatorContext) SetDependencyVariation(variation string) {
diff --git a/android/mutator_test.go b/android/mutator_test.go
index 4cef400..0b23434 100644
--- a/android/mutator_test.go
+++ b/android/mutator_test.go
@@ -15,8 +15,6 @@
package android
import (
- "io/ioutil"
- "os"
"reflect"
"testing"
@@ -26,6 +24,8 @@
type mutatorTestModule struct {
ModuleBase
props struct {
+ Deps_missing_deps []string
+ Mutator_missing_deps []string
}
missingDeps []string
@@ -48,20 +48,14 @@
}
func (m *mutatorTestModule) DepsMutator(ctx BottomUpMutatorContext) {
- ctx.AddDependency(ctx.Module(), nil, "regular_missing_dep")
+ ctx.AddDependency(ctx.Module(), nil, m.props.Deps_missing_deps...)
}
func addMissingDependenciesMutator(ctx TopDownMutatorContext) {
- ctx.AddMissingDependencies([]string{"added_missing_dep"})
+ ctx.AddMissingDependencies(ctx.Module().(*mutatorTestModule).props.Mutator_missing_deps)
}
func TestMutatorAddMissingDependencies(t *testing.T) {
- buildDir, err := ioutil.TempDir("", "soong_mutator_test")
- if err != nil {
- t.Fatal(err)
- }
- defer os.RemoveAll(buildDir)
-
config := TestConfig(buildDir, nil)
config.TestProductVariables.Allow_missing_dependencies = proptools.BoolPtr(true)
@@ -76,6 +70,8 @@
bp := `
test {
name: "foo",
+ deps_missing_deps: ["regular_missing_dep"],
+ mutator_missing_deps: ["added_missing_dep"],
}
`
@@ -97,3 +93,107 @@
t.Errorf("want foo missing deps %q, got %q", w, g)
}
}
+
+func TestModuleString(t *testing.T) {
+ ctx := NewTestContext()
+
+ var moduleStrings []string
+
+ ctx.PreArchMutators(func(ctx RegisterMutatorsContext) {
+ ctx.BottomUp("pre_arch", func(ctx BottomUpMutatorContext) {
+ moduleStrings = append(moduleStrings, ctx.Module().String())
+ ctx.CreateVariations("a", "b")
+ })
+ ctx.TopDown("rename_top_down", func(ctx TopDownMutatorContext) {
+ moduleStrings = append(moduleStrings, ctx.Module().String())
+ ctx.Rename(ctx.Module().base().Name() + "_renamed1")
+ })
+ })
+
+ ctx.PreDepsMutators(func(ctx RegisterMutatorsContext) {
+ ctx.BottomUp("pre_deps", func(ctx BottomUpMutatorContext) {
+ moduleStrings = append(moduleStrings, ctx.Module().String())
+ ctx.CreateVariations("c", "d")
+ })
+ })
+
+ ctx.PostDepsMutators(func(ctx RegisterMutatorsContext) {
+ ctx.BottomUp("post_deps", func(ctx BottomUpMutatorContext) {
+ moduleStrings = append(moduleStrings, ctx.Module().String())
+ ctx.CreateLocalVariations("e", "f")
+ })
+ ctx.BottomUp("rename_bottom_up", func(ctx BottomUpMutatorContext) {
+ moduleStrings = append(moduleStrings, ctx.Module().String())
+ ctx.Rename(ctx.Module().base().Name() + "_renamed2")
+ })
+ ctx.BottomUp("final", func(ctx BottomUpMutatorContext) {
+ moduleStrings = append(moduleStrings, ctx.Module().String())
+ })
+ })
+
+ ctx.RegisterModuleType("test", ModuleFactoryAdaptor(mutatorTestModuleFactory))
+
+ bp := `
+ test {
+ name: "foo",
+ }
+ `
+
+ mockFS := map[string][]byte{
+ "Android.bp": []byte(bp),
+ }
+
+ ctx.MockFileSystem(mockFS)
+
+ ctx.Register()
+
+ config := TestConfig(buildDir, nil)
+
+ _, errs := ctx.ParseFileList(".", []string{"Android.bp"})
+ FailIfErrored(t, errs)
+ _, errs = ctx.PrepareBuildActions(config)
+ FailIfErrored(t, errs)
+
+ want := []string{
+ // Initial name.
+ "foo{}",
+
+ // After pre_arch (reversed because rename_top_down is TopDown so it visits in reverse order).
+ "foo{pre_arch:b}",
+ "foo{pre_arch:a}",
+
+ // After rename_top_down.
+ "foo_renamed1{pre_arch:a}",
+ "foo_renamed1{pre_arch:b}",
+
+ // After pre_deps.
+ "foo_renamed1{pre_arch:a,pre_deps:c}",
+ "foo_renamed1{pre_arch:a,pre_deps:d}",
+ "foo_renamed1{pre_arch:b,pre_deps:c}",
+ "foo_renamed1{pre_arch:b,pre_deps:d}",
+
+ // After post_deps.
+ "foo_renamed1{pre_arch:a,pre_deps:c,post_deps:e}",
+ "foo_renamed1{pre_arch:a,pre_deps:c,post_deps:f}",
+ "foo_renamed1{pre_arch:a,pre_deps:d,post_deps:e}",
+ "foo_renamed1{pre_arch:a,pre_deps:d,post_deps:f}",
+ "foo_renamed1{pre_arch:b,pre_deps:c,post_deps:e}",
+ "foo_renamed1{pre_arch:b,pre_deps:c,post_deps:f}",
+ "foo_renamed1{pre_arch:b,pre_deps:d,post_deps:e}",
+ "foo_renamed1{pre_arch:b,pre_deps:d,post_deps:f}",
+
+ // After rename_bottom_up.
+ "foo_renamed2{pre_arch:a,pre_deps:c,post_deps:e}",
+ "foo_renamed2{pre_arch:a,pre_deps:c,post_deps:f}",
+ "foo_renamed2{pre_arch:a,pre_deps:d,post_deps:e}",
+ "foo_renamed2{pre_arch:a,pre_deps:d,post_deps:f}",
+ "foo_renamed2{pre_arch:b,pre_deps:c,post_deps:e}",
+ "foo_renamed2{pre_arch:b,pre_deps:c,post_deps:f}",
+ "foo_renamed2{pre_arch:b,pre_deps:d,post_deps:e}",
+ "foo_renamed2{pre_arch:b,pre_deps:d,post_deps:f}",
+ }
+
+ if !reflect.DeepEqual(moduleStrings, want) {
+ t.Errorf("want module String() values:\n%q\ngot:\n%q", want, moduleStrings)
+ }
+}
diff --git a/android/notices.go b/android/notices.go
index dbb88fc..8503593 100644
--- a/android/notices.go
+++ b/android/notices.go
@@ -27,6 +27,13 @@
pctx.HostBinToolVariable("minigzip", "minigzip")
}
+type NoticeOutputs struct {
+ Merged OptionalPath
+ TxtOutput OptionalPath
+ HtmlOutput OptionalPath
+ HtmlGzOutput OptionalPath
+}
+
var (
mergeNoticesRule = pctx.AndroidStaticRule("mergeNoticesRule", blueprint.RuleParams{
Command: `${merge_notices} --output $out $in`,
@@ -35,13 +42,13 @@
})
generateNoticeRule = pctx.AndroidStaticRule("generateNoticeRule", blueprint.RuleParams{
- Command: `rm -rf $tmpDir $$(dirname $out) && ` +
- `mkdir -p $tmpDir $$(dirname $out) && ` +
- `${generate_notice} --text-output $tmpDir/NOTICE.txt --html-output $tmpDir/NOTICE.html -t "$title" -s $inputDir && ` +
- `${minigzip} -c $tmpDir/NOTICE.html > $out`,
+ Command: `rm -rf $$(dirname $txtOut) $$(dirname htmlOut) $$(dirname $out) && ` +
+ `mkdir -p $$(dirname $txtOut) $$(dirname htmlOut) $$(dirname $out) && ` +
+ `${generate_notice} --text-output $txtOut --html-output $htmlOut -t "$title" -s $inputDir && ` +
+ `${minigzip} -c $htmlOut > $out`,
CommandDeps: []string{"${generate_notice}", "${minigzip}"},
Description: "produce notice file $out",
- }, "tmpDir", "title", "inputDir")
+ }, "txtOut", "htmlOut", "title", "inputDir")
)
func MergeNotices(ctx ModuleContext, mergedNotice WritablePath, noticePaths []Path) {
@@ -54,7 +61,7 @@
}
func BuildNoticeOutput(ctx ModuleContext, installPath OutputPath, installFilename string,
- noticePaths []Path) ModuleOutPath {
+ noticePaths []Path) NoticeOutputs {
// Merge all NOTICE files into one.
// TODO(jungjw): We should just produce a well-formatted NOTICE.html file in a single pass.
//
@@ -68,20 +75,28 @@
MergeNotices(ctx, mergedNotice, noticePaths)
// Transform the merged NOTICE file into a gzipped HTML file.
- noticeOutput := PathForModuleOut(ctx, "NOTICE", "NOTICE.html.gz")
- tmpDir := PathForModuleOut(ctx, "NOTICE_tmp")
+ txtOuptut := PathForModuleOut(ctx, "NOTICE_txt", "NOTICE.txt")
+ htmlOutput := PathForModuleOut(ctx, "NOTICE_html", "NOTICE.html")
+ htmlGzOutput := PathForModuleOut(ctx, "NOTICE", "NOTICE.html.gz")
title := "Notices for " + ctx.ModuleName()
ctx.Build(pctx, BuildParams{
- Rule: generateNoticeRule,
- Description: "generate notice output",
- Input: mergedNotice,
- Output: noticeOutput,
+ Rule: generateNoticeRule,
+ Description: "generate notice output",
+ Input: mergedNotice,
+ Output: htmlGzOutput,
+ ImplicitOutputs: WritablePaths{txtOuptut, htmlOutput},
Args: map[string]string{
- "tmpDir": tmpDir.String(),
+ "txtOut": txtOuptut.String(),
+ "htmlOut": htmlOutput.String(),
"title": title,
"inputDir": PathForModuleOut(ctx, "NOTICE_FILES/src").String(),
},
})
- return noticeOutput
+ return NoticeOutputs{
+ Merged: OptionalPathForPath(mergedNotice),
+ TxtOutput: OptionalPathForPath(txtOuptut),
+ HtmlOutput: OptionalPathForPath(htmlOutput),
+ HtmlGzOutput: OptionalPathForPath(htmlGzOutput),
+ }
}
diff --git a/android/package_test.go b/android/package_test.go
index f1f47ac..e5b0556 100644
--- a/android/package_test.go
+++ b/android/package_test.go
@@ -1,8 +1,6 @@
package android
import (
- "io/ioutil"
- "os"
"testing"
)
@@ -58,15 +56,9 @@
}
func TestPackage(t *testing.T) {
- buildDir, err := ioutil.TempDir("", "soong_package_test")
- if err != nil {
- t.Fatal(err)
- }
- defer os.RemoveAll(buildDir)
-
for _, test := range packageTests {
t.Run(test.name, func(t *testing.T) {
- _, errs := testPackage(buildDir, test.fs)
+ _, errs := testPackage(test.fs)
expectedErrors := test.expectedErrors
if expectedErrors == nil {
@@ -89,7 +81,7 @@
}
}
-func testPackage(buildDir string, fs map[string][]byte) (*TestContext, []error) {
+func testPackage(fs map[string][]byte) (*TestContext, []error) {
// Create a new config per test as visibility information is stored in the config.
config := TestArchConfig(buildDir, nil)
diff --git a/android/path_properties_test.go b/android/path_properties_test.go
index fa187fa..e98c136 100644
--- a/android/path_properties_test.go
+++ b/android/path_properties_test.go
@@ -15,8 +15,6 @@
package android
import (
- "io/ioutil"
- "os"
"reflect"
"testing"
)
@@ -85,12 +83,6 @@
},
}
- buildDir, err := ioutil.TempDir("", "soong_path_properties_test")
- if err != nil {
- t.Fatal(err)
- }
- defer os.RemoveAll(buildDir)
-
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
config := TestArchConfig(buildDir, nil)
diff --git a/android/paths.go b/android/paths.go
index 20b8b82..0ea4447 100644
--- a/android/paths.go
+++ b/android/paths.go
@@ -1145,8 +1145,8 @@
partition = ctx.DeviceConfig().OdmPath()
} else if ctx.ProductSpecific() {
partition = ctx.DeviceConfig().ProductPath()
- } else if ctx.ProductServicesSpecific() {
- partition = ctx.DeviceConfig().ProductServicesPath()
+ } else if ctx.SystemExtSpecific() {
+ partition = ctx.DeviceConfig().SystemExtPath()
} else {
partition = "system"
}
diff --git a/android/paths_test.go b/android/paths_test.go
index 7bcfe41..8286e9a 100644
--- a/android/paths_test.go
+++ b/android/paths_test.go
@@ -294,15 +294,15 @@
out: "target/product/test_device/product/bin/my_test",
},
{
- name: "product_services binary",
+ name: "system_ext binary",
ctx: &moduleInstallPathContextImpl{
baseModuleContext: baseModuleContext{
target: deviceTarget,
- kind: productServicesSpecificModule,
+ kind: systemExtSpecificModule,
},
},
in: []string{"bin", "my_test"},
- out: "target/product/test_device/product_services/bin/my_test",
+ out: "target/product/test_device/system_ext/bin/my_test",
},
{
@@ -354,11 +354,11 @@
},
{
- name: "product_services native test binary",
+ name: "system_ext native test binary",
ctx: &moduleInstallPathContextImpl{
baseModuleContext: baseModuleContext{
target: deviceTarget,
- kind: productServicesSpecificModule,
+ kind: systemExtSpecificModule,
},
inData: true,
},
@@ -415,16 +415,16 @@
},
{
- name: "sanitized product_services binary",
+ name: "sanitized system_ext binary",
ctx: &moduleInstallPathContextImpl{
baseModuleContext: baseModuleContext{
target: deviceTarget,
- kind: productServicesSpecificModule,
+ kind: systemExtSpecificModule,
},
inSanitizerDir: true,
},
in: []string{"bin", "my_test"},
- out: "target/product/test_device/data/asan/product_services/bin/my_test",
+ out: "target/product/test_device/data/asan/system_ext/bin/my_test",
},
{
@@ -479,11 +479,11 @@
out: "target/product/test_device/data/asan/data/nativetest/my_test",
},
{
- name: "sanitized product_services native test binary",
+ name: "sanitized system_ext native test binary",
ctx: &moduleInstallPathContextImpl{
baseModuleContext: baseModuleContext{
target: deviceTarget,
- kind: productServicesSpecificModule,
+ kind: systemExtSpecificModule,
},
inData: true,
inSanitizerDir: true,
diff --git a/android/rule_builder.go b/android/rule_builder.go
index 8d7e74b..e53eb0d 100644
--- a/android/rule_builder.go
+++ b/android/rule_builder.go
@@ -267,7 +267,7 @@
func (r *RuleBuilder) Commands() []string {
var commands []string
for _, c := range r.commands {
- commands = append(commands, string(c.buf))
+ commands = append(commands, c.buf.String())
}
return commands
}
@@ -358,7 +358,7 @@
Flag("--output-root").Text(r.sboxOutDir.String()).
Flags(sboxOutputs)
- commandString = string(sboxCmd.buf)
+ commandString = sboxCmd.buf.String()
tools = append(tools, sboxCmd.tools...)
}
@@ -388,7 +388,7 @@
// RuleBuilderCommand, so they can be used chained or unchained. All methods that add text implicitly add a single
// space as a separator from the previous method.
type RuleBuilderCommand struct {
- buf []byte
+ buf strings.Builder
inputs Paths
outputs WritablePaths
depFiles WritablePaths
@@ -420,10 +420,10 @@
// 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 {
- if len(c.buf) > 0 {
- c.buf = append(c.buf, ' ')
+ if c.buf.Len() > 0 {
+ c.buf.WriteByte(' ')
}
- c.buf = append(c.buf, text...)
+ c.buf.WriteString(text)
return c
}
@@ -608,7 +608,7 @@
// String returns the command line.
func (c *RuleBuilderCommand) String() string {
- return string(c.buf)
+ return c.buf.String()
}
func ninjaNameEscape(s string) string {
diff --git a/android/variable.go b/android/variable.go
index b4f31c6..fcd92d4 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -232,10 +232,10 @@
EnableXOM *bool `json:",omitempty"`
XOMExcludePaths []string `json:",omitempty"`
- VendorPath *string `json:",omitempty"`
- OdmPath *string `json:",omitempty"`
- ProductPath *string `json:",omitempty"`
- ProductServicesPath *string `json:",omitempty"`
+ VendorPath *string `json:",omitempty"`
+ OdmPath *string `json:",omitempty"`
+ ProductPath *string `json:",omitempty"`
+ SystemExtPath *string `json:",omitempty"`
ClangTidy *bool `json:",omitempty"`
TidyChecks *string `json:",omitempty"`
diff --git a/androidmk/cmd/androidmk/android.go b/androidmk/cmd/androidmk/android.go
index af81e43..2def179 100644
--- a/androidmk/cmd/androidmk/android.go
+++ b/androidmk/cmd/androidmk/android.go
@@ -192,7 +192,7 @@
"LOCAL_VENDOR_MODULE": "vendor",
"LOCAL_ODM_MODULE": "device_specific",
"LOCAL_PRODUCT_MODULE": "product_specific",
- "LOCAL_PRODUCT_SERVICES_MODULE": "product_services_specific",
+ "LOCAL_SYSTEM_EXT_MODULE": "system_ext_specific",
"LOCAL_EXPORT_PACKAGE_RESOURCES": "export_package_resources",
"LOCAL_PRIVILEGED_MODULE": "privileged",
"LOCAL_AAPT_INCLUDE_ALL_RESOURCES": "aapt_include_all_resources",
@@ -602,8 +602,8 @@
return fmt.Errorf("Cannot handle appending to LOCAL_MODULE_PATH")
}
// Analyze value in order to set the correct values for the 'device_specific',
- // 'product_specific', 'product_services_specific' 'vendor'/'soc_specific',
- // 'product_services_specific' attribute. Two cases are allowed:
+ // 'product_specific', 'system_ext_specific' 'vendor'/'soc_specific',
+ // 'system_ext_specific' attribute. Two cases are allowed:
// $(VAR)/<literal-value>
// $(PRODUCT_OUT)/$(TARGET_COPY_OUT_VENDOR)/<literal-value>
// The last case is equivalent to $(TARGET_OUT_VENDOR)/<literal-value>
diff --git a/androidmk/cmd/androidmk/androidmk_test.go b/androidmk/cmd/androidmk/androidmk_test.go
index 4d5180e..dbb7fde 100644
--- a/androidmk/cmd/androidmk/androidmk_test.go
+++ b/androidmk/cmd/androidmk/androidmk_test.go
@@ -957,37 +957,37 @@
`,
},
{
- desc: "prebuilt_etc_TARGET_OUT_PRODUCT_SERVICES/etc",
+ desc: "prebuilt_etc_TARGET_OUT_SYSTEM_EXT/etc",
in: `
include $(CLEAR_VARS)
LOCAL_MODULE := etc.test1
LOCAL_MODULE_CLASS := ETC
-LOCAL_MODULE_PATH := $(TARGET_OUT_PRODUCT_SERVICES)/etc/foo/bar
+LOCAL_MODULE_PATH := $(TARGET_OUT_SYSTEM_EXT)/etc/foo/bar
include $(BUILD_PREBUILT)
`,
expected: `
prebuilt_etc {
name: "etc.test1",
sub_dir: "foo/bar",
- product_services_specific: true,
+ system_ext_specific: true,
}
`,
},
{
- desc: "prebuilt_etc_TARGET_OUT_PRODUCT_SERVICES_ETC",
+ desc: "prebuilt_etc_TARGET_OUT_SYSTEM_EXT_ETC",
in: `
include $(CLEAR_VARS)
LOCAL_MODULE := etc.test1
LOCAL_MODULE_CLASS := ETC
-LOCAL_MODULE_PATH := $(TARGET_OUT_PRODUCT_SERVICES_ETC)/foo/bar
+LOCAL_MODULE_PATH := $(TARGET_OUT_SYSTEM_EXT_ETC)/foo/bar
include $(BUILD_PREBUILT)
`,
expected: `
prebuilt_etc {
name: "etc.test1",
sub_dir: "foo/bar",
- product_services_specific: true,
+ system_ext_specific: true,
}
diff --git a/apex/apex.go b/apex/apex.go
index a77e295..f683f96 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -108,6 +108,7 @@
executableTag = dependencyTag{name: "executable"}
javaLibTag = dependencyTag{name: "javaLib"}
prebuiltTag = dependencyTag{name: "prebuilt"}
+ testTag = dependencyTag{name: "test"}
keyTag = dependencyTag{name: "key"}
certificateTag = dependencyTag{name: "certificate"}
)
@@ -192,6 +193,8 @@
Native_shared_libs []string
// List of native executables
Binaries []string
+ // List of native tests
+ Tests []string
}
type apexMultilibProperties struct {
// Native dependencies whose compile_multilib is "first"
@@ -232,7 +235,7 @@
// List of native shared libs that are embedded inside this APEX bundle
Native_shared_libs []string
- // List of native executables that are embedded inside this APEX bundle
+ // List of executables that are embedded inside this APEX bundle
Binaries []string
// List of java libraries that are embedded inside this APEX bundle
@@ -241,6 +244,9 @@
// List of prebuilt files that are embedded inside this APEX bundle
Prebuilts []string
+ // List of tests that are embedded inside this APEX bundle
+ Tests []string
+
// Name of the apex_key module that provides the private key to sign APEX
Key *string
@@ -299,6 +305,7 @@
pyBinary
goBinary
javaSharedLib
+ nativeTest
)
type apexPackaging int
@@ -361,6 +368,8 @@
return "EXECUTABLES"
case javaSharedLib:
return "JAVA_LIBRARIES"
+ case nativeTest:
+ return "NATIVE_TESTS"
default:
panic(fmt.Errorf("unkonwn class %d", class))
}
@@ -406,7 +415,8 @@
}
func addDependenciesForNativeModules(ctx android.BottomUpMutatorContext,
- native_shared_libs []string, binaries []string, arch string, imageVariation string) {
+ native_shared_libs []string, binaries []string, tests []string,
+ arch string, imageVariation string) {
// Use *FarVariation* to be able to depend on modules having
// conflicting variations with this module. This is required since
// arch variant of an APEX bundle is 'common' but it is 'arm' or 'arm64'
@@ -422,6 +432,11 @@
{Mutator: "arch", Variation: arch},
{Mutator: "image", Variation: imageVariation},
}, executableTag, binaries...)
+
+ ctx.AddFarVariationDependencies([]blueprint.Variation{
+ {Mutator: "arch", Variation: arch},
+ {Mutator: "image", Variation: imageVariation},
+ }, testTag, tests...)
}
func (a *apexBundle) combineProperties(ctx android.BottomUpMutatorContext) {
@@ -459,10 +474,19 @@
{Mutator: "link", Variation: "shared"},
}, sharedLibTag, a.properties.Native_shared_libs...)
+ // When multilib.* is omitted for tests, it implies
+ // multilib.both.
+ ctx.AddFarVariationDependencies([]blueprint.Variation{
+ {Mutator: "arch", Variation: target.String()},
+ {Mutator: "image", Variation: a.getImageVariation(config)},
+ }, testTag, a.properties.Tests...)
+
// Add native modules targetting both ABIs
addDependenciesForNativeModules(ctx,
a.properties.Multilib.Both.Native_shared_libs,
- a.properties.Multilib.Both.Binaries, target.String(),
+ a.properties.Multilib.Both.Binaries,
+ a.properties.Multilib.Both.Tests,
+ target.String(),
a.getImageVariation(config))
isPrimaryAbi := i == 0
@@ -477,7 +501,9 @@
// Add native modules targetting the first ABI
addDependenciesForNativeModules(ctx,
a.properties.Multilib.First.Native_shared_libs,
- a.properties.Multilib.First.Binaries, target.String(),
+ a.properties.Multilib.First.Binaries,
+ a.properties.Multilib.First.Tests,
+ target.String(),
a.getImageVariation(config))
// When multilib.* is omitted for prebuilts, it implies multilib.first.
@@ -491,24 +517,32 @@
// Add native modules targetting 32-bit ABI
addDependenciesForNativeModules(ctx,
a.properties.Multilib.Lib32.Native_shared_libs,
- a.properties.Multilib.Lib32.Binaries, target.String(),
+ a.properties.Multilib.Lib32.Binaries,
+ a.properties.Multilib.Lib32.Tests,
+ target.String(),
a.getImageVariation(config))
addDependenciesForNativeModules(ctx,
a.properties.Multilib.Prefer32.Native_shared_libs,
- a.properties.Multilib.Prefer32.Binaries, target.String(),
+ a.properties.Multilib.Prefer32.Binaries,
+ a.properties.Multilib.Prefer32.Tests,
+ target.String(),
a.getImageVariation(config))
case "lib64":
// Add native modules targetting 64-bit ABI
addDependenciesForNativeModules(ctx,
a.properties.Multilib.Lib64.Native_shared_libs,
- a.properties.Multilib.Lib64.Binaries, target.String(),
+ a.properties.Multilib.Lib64.Binaries,
+ a.properties.Multilib.Lib64.Tests,
+ target.String(),
a.getImageVariation(config))
if !has32BitTarget {
addDependenciesForNativeModules(ctx,
a.properties.Multilib.Prefer32.Native_shared_libs,
- a.properties.Multilib.Prefer32.Binaries, target.String(),
+ a.properties.Multilib.Prefer32.Binaries,
+ a.properties.Multilib.Prefer32.Tests,
+ target.String(),
a.getImageVariation(config))
}
@@ -517,7 +551,7 @@
if sanitizer == "hwaddress" {
addDependenciesForNativeModules(ctx,
[]string{"libclang_rt.hwasan-aarch64-android"},
- nil, target.String(), a.getImageVariation(config))
+ nil, nil, target.String(), a.getImageVariation(config))
break
}
}
@@ -686,6 +720,11 @@
return
}
+ if len(a.properties.Tests) > 0 && !a.testApex {
+ ctx.PropertyErrorf("tests", "property not allowed in apex module type")
+ return
+ }
+
handleSpecialLibs := !android.Bool(a.properties.Ignore_system_library_special_case)
ctx.WalkDepsBlueprint(func(child, parent blueprint.Module) bool {
@@ -747,6 +786,14 @@
} else {
ctx.PropertyErrorf("prebuilts", "%q is not a prebuilt_etc module", depName)
}
+ case testTag:
+ if cc, ok := child.(*cc.Module); ok {
+ fileToCopy, dirInApex := getCopyManifestForExecutable(cc)
+ filesInfo = append(filesInfo, apexFile{fileToCopy, depName, dirInApex, nativeTest, cc, nil})
+ return true
+ } else {
+ ctx.PropertyErrorf("tests", "%q is not a cc module", depName)
+ }
case keyTag:
if key, ok := child.(*apexKey); ok {
a.private_key_file = key.private_key_file
@@ -858,8 +905,7 @@
return android.OptionalPath{}
}
- return android.OptionalPathForPath(
- android.BuildNoticeOutput(ctx, a.installDir, apexFileName, android.FirstUniquePaths(noticeFiles)))
+ return android.BuildNoticeOutput(ctx, a.installDir, apexFileName, android.FirstUniquePaths(noticeFiles)).HtmlGzOutput
}
func (a *apexBundle) buildUnflattenedApex(ctx android.ModuleContext, apexType apexPackaging) {
@@ -916,7 +962,7 @@
var executablePaths []string // this also includes dirs
for _, f := range a.filesInfo {
pathInApex := filepath.Join(f.installDir, f.builtFile.Base())
- if f.installDir == "bin" {
+ if f.installDir == "bin" || strings.HasPrefix(f.installDir, "bin/") {
executablePaths = append(executablePaths, pathInApex)
for _, s := range f.symlinks {
executablePaths = append(executablePaths, filepath.Join("bin", s))
@@ -1253,11 +1299,11 @@
}
func testApexBundleFactory() android.Module {
- return ApexBundleFactory( /*testApex*/ true)
+ return ApexBundleFactory(true /*testApex*/)
}
func apexBundleFactory() android.Module {
- return ApexBundleFactory( /*testApex*/ false)
+ return ApexBundleFactory(false /*testApex*/)
}
func ApexBundleFactory(testApex bool) android.Module {
diff --git a/apex/apex_test.go b/apex/apex_test.go
index 2e44db7..b410425 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -57,6 +57,7 @@
ctx.RegisterModuleType("cc_library_headers", android.ModuleFactoryAdaptor(cc.LibraryHeaderFactory))
ctx.RegisterModuleType("cc_binary", android.ModuleFactoryAdaptor(cc.BinaryFactory))
ctx.RegisterModuleType("cc_object", android.ModuleFactoryAdaptor(cc.ObjectFactory))
+ ctx.RegisterModuleType("cc_test", android.ModuleFactoryAdaptor(cc.TestFactory))
ctx.RegisterModuleType("llndk_library", android.ModuleFactoryAdaptor(cc.LlndkLibraryFactory))
ctx.RegisterModuleType("toolchain_library", android.ModuleFactoryAdaptor(cc.ToolchainLibraryFactory))
ctx.RegisterModuleType("prebuilt_etc", android.ModuleFactoryAdaptor(android.PrebuiltEtcFactory))
@@ -168,6 +169,7 @@
"system/sepolicy/apex/myapex_keytest-file_contexts": nil,
"system/sepolicy/apex/otherapex-file_contexts": nil,
"mylib.cpp": nil,
+ "mytest.cpp": nil,
"myprebuilt": nil,
"my_include": nil,
"vendor/foo/devkeys/test.x509.pem": nil,
@@ -1285,6 +1287,40 @@
}
}
+func TestApexWithTests(t *testing.T) {
+ ctx := testApex(t, `
+ apex_test {
+ name: "myapex",
+ key: "myapex.key",
+ tests: [
+ "mytest",
+ ],
+ }
+
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+
+ cc_test {
+ name: "mytest",
+ gtest: false,
+ srcs: ["mytest.cpp"],
+ relative_install_path: "test",
+ system_shared_libs: [],
+ static_executable: true,
+ stl: "none",
+ }
+ `)
+
+ apexRule := ctx.ModuleForTests("myapex", "android_common_myapex").Rule("apexRule")
+ copyCmds := apexRule.Args["copy_commands"]
+
+ // Ensure that test dep is copied into apex.
+ ensureContains(t, copyCmds, "image.apex/bin/test/mytest")
+}
+
func TestMain(m *testing.M) {
run := func() int {
setUp()
diff --git a/bpfix/bpfix/bpfix.go b/bpfix/bpfix/bpfix.go
index cac4d9a..5f1cce8 100644
--- a/bpfix/bpfix/bpfix.go
+++ b/bpfix/bpfix/bpfix.go
@@ -508,15 +508,15 @@
"TARGET_OUT": {{prefix: "/usr/share", modType: "prebuilt_usr_share"}, {prefix: "/fonts", modType: "prebuilt_font"},
{prefix: "/etc/firmware", modType: "prebuilt_firmware"}, {prefix: "/vendor/firmware", modType: "prebuilt_firmware", flags: []string{"proprietary"}},
{prefix: "/etc"}},
- "TARGET_OUT_ETC": {{prefix: "/firmware", modType: "prebuilt_firmware"}, {prefix: ""}},
- "TARGET_OUT_PRODUCT": {{prefix: "/etc", flags: []string{"product_specific"}}, {prefix: "/fonts", modType: "prebuilt_font", flags: []string{"product_specific"}}},
- "TARGET_OUT_PRODUCT_ETC": {{prefix: "", flags: []string{"product_specific"}}},
- "TARGET_OUT_ODM": {{prefix: "/etc", flags: []string{"device_specific"}}},
- "TARGET_OUT_PRODUCT_SERVICES": {{prefix: "/etc", flags: []string{"product_services_specific"}}},
- "TARGET_OUT_PRODUCT_SERVICES_ETC": {{prefix: "", flags: []string{"product_services_specific"}}},
- "TARGET_OUT_VENDOR": {{prefix: "/etc", flags: []string{"proprietary"}}, {prefix: "/firmware", modType: "prebuilt_firmware", flags: []string{"proprietary"}}},
- "TARGET_OUT_VENDOR_ETC": {{prefix: "", flags: []string{"proprietary"}}},
- "TARGET_RECOVERY_ROOT_OUT": {{prefix: "/system/etc", flags: []string{"recovery"}}},
+ "TARGET_OUT_ETC": {{prefix: "/firmware", modType: "prebuilt_firmware"}, {prefix: ""}},
+ "TARGET_OUT_PRODUCT": {{prefix: "/etc", flags: []string{"product_specific"}}, {prefix: "/fonts", modType: "prebuilt_font", flags: []string{"product_specific"}}},
+ "TARGET_OUT_PRODUCT_ETC": {{prefix: "", flags: []string{"product_specific"}}},
+ "TARGET_OUT_ODM": {{prefix: "/etc", flags: []string{"device_specific"}}},
+ "TARGET_OUT_SYSTEM_EXT": {{prefix: "/etc", flags: []string{"system_ext_specific"}}},
+ "TARGET_OUT_SYSTEM_EXT_ETC": {{prefix: "", flags: []string{"system_ext_specific"}}},
+ "TARGET_OUT_VENDOR": {{prefix: "/etc", flags: []string{"proprietary"}}, {prefix: "/firmware", modType: "prebuilt_firmware", flags: []string{"proprietary"}}},
+ "TARGET_OUT_VENDOR_ETC": {{prefix: "", flags: []string{"proprietary"}}},
+ "TARGET_RECOVERY_ROOT_OUT": {{prefix: "/system/etc", flags: []string{"recovery"}}},
}
// rewriteAndroidPrebuiltEtc fixes prebuilt_etc rule
diff --git a/cc/library.go b/cc/library.go
index 5fbb36e..6ac0c39 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -113,8 +113,6 @@
}
type LibraryMutatedProperties struct {
- VariantName string `blueprint:"mutated"`
-
// Build a static variant
BuildStatic bool `blueprint:"mutated"`
// Build a shared variant
@@ -528,7 +526,7 @@
}
}
- return name + library.MutatedProperties.VariantName
+ return name
}
var versioningMacroNamesListMutex sync.Mutex
@@ -633,7 +631,7 @@
library.objects = deps.WholeStaticLibObjs.Copy()
library.objects = library.objects.Append(objs)
- fileName := ctx.ModuleName() + library.MutatedProperties.VariantName + staticLibraryExtension
+ fileName := ctx.ModuleName() + staticLibraryExtension
outputFile := android.PathForModuleOut(ctx, fileName)
builderFlags := flagsToBuilderFlags(flags)
@@ -651,8 +649,7 @@
TransformObjToStaticLib(ctx, library.objects.objFiles, builderFlags, outputFile, objs.tidyFiles)
- library.coverageOutputFile = TransformCoverageFilesToZip(ctx, library.objects,
- ctx.ModuleName()+library.MutatedProperties.VariantName)
+ library.coverageOutputFile = TransformCoverageFilesToZip(ctx, library.objects, ctx.ModuleName())
library.wholeStaticMissingDeps = ctx.GetMissingDependencies()
diff --git a/cmd/diff_target_files/target_files.go b/cmd/diff_target_files/target_files.go
index 8705ca7..0fa04e8 100644
--- a/cmd/diff_target_files/target_files.go
+++ b/cmd/diff_target_files/target_files.go
@@ -28,7 +28,7 @@
"ODM/",
"OEM/",
"PRODUCT/",
- "PRODUCT_SERVICES/",
+ "SYSTEM_EXT/",
"ROOT/",
"SYSTEM/",
"SYSTEM_OTHER/",
diff --git a/cmd/soong_build/main.go b/cmd/soong_build/main.go
index 41c7d46..30381e0 100644
--- a/cmd/soong_build/main.go
+++ b/cmd/soong_build/main.go
@@ -18,7 +18,12 @@
"flag"
"fmt"
"os"
+ "os/exec"
"path/filepath"
+ "strconv"
+ "strings"
+ "syscall"
+ "time"
"github.com/google/blueprint/bootstrap"
@@ -50,6 +55,42 @@
}
func main() {
+ if android.SoongDelveListen != "" {
+ if android.SoongDelvePath == "" {
+ fmt.Fprintln(os.Stderr, "SOONG_DELVE is set but failed to find dlv")
+ os.Exit(1)
+ }
+ pid := strconv.Itoa(os.Getpid())
+ cmd := []string{android.SoongDelvePath,
+ "attach", pid,
+ "--headless",
+ "-l", android.SoongDelveListen,
+ "--api-version=2",
+ "--accept-multiclient",
+ "--log",
+ }
+
+ fmt.Println("Starting", strings.Join(cmd, " "))
+ dlv := exec.Command(cmd[0], cmd[1:]...)
+ dlv.Stdout = os.Stdout
+ dlv.Stderr = os.Stderr
+ dlv.Stdin = nil
+
+ // Put dlv into its own process group so we can kill it and the child process it starts.
+ dlv.SysProcAttr = &syscall.SysProcAttr{Setpgid: true}
+
+ err := dlv.Start()
+ if err != nil {
+ // Print the error starting dlv and continue.
+ fmt.Println(err)
+ } else {
+ // Kill the process group for dlv when soong_build exits.
+ defer syscall.Kill(-dlv.Process.Pid, syscall.SIGKILL)
+ // Wait to give dlv a chance to connect and pause the process.
+ time.Sleep(time.Second)
+ }
+ }
+
flag.Parse()
// The top-level Blueprints file is passed as the first argument.
@@ -72,7 +113,17 @@
ctx.SetAllowMissingDependencies(configuration.AllowMissingDependencies())
- bootstrap.Main(ctx.Context, configuration, configuration.ConfigFileName, configuration.ProductVariablesFileName)
+ extraNinjaDeps := []string{configuration.ConfigFileName, configuration.ProductVariablesFileName}
+
+ // Read the SOONG_DELVE again through configuration so that there is a dependency on the environment variable
+ // and soong_build will rerun when it is set for the first time.
+ if listen := configuration.Getenv("SOONG_DELVE"); listen != "" {
+ // Add a non-existent file to the dependencies so that soong_build will rerun when the debugger is
+ // enabled even if it completed successfully.
+ extraNinjaDeps = append(extraNinjaDeps, filepath.Join(configuration.BuildDir(), "always_rerun_for_delve"))
+ }
+
+ bootstrap.Main(ctx.Context, configuration, extraNinjaDeps...)
if docFile != "" {
if err := writeDocs(ctx, docFile); err != nil {
diff --git a/java/androidmk.go b/java/androidmk.go
index 39c2d13..90fdd0f 100644
--- a/java/androidmk.go
+++ b/java/androidmk.go
@@ -327,6 +327,18 @@
install := "$(LOCAL_MODULE_PATH)/" + strings.TrimSuffix(app.installApkName, ".apk") + split.suffix + ".apk"
fmt.Fprintln(w, "LOCAL_SOONG_BUILT_INSTALLED +=", split.path.String()+":"+install)
}
+ if app.noticeOutputs.Merged.Valid() {
+ fmt.Fprintf(w, "$(call dist-for-goals,%s,%s:%s)\n",
+ app.installApkName, app.noticeOutputs.Merged.String(), app.installApkName+"_NOTICE")
+ }
+ if app.noticeOutputs.TxtOutput.Valid() {
+ fmt.Fprintf(w, "$(call dist-for-goals,%s,%s:%s)\n",
+ app.installApkName, app.noticeOutputs.TxtOutput.String(), app.installApkName+"_NOTICE.txt")
+ }
+ if app.noticeOutputs.HtmlOutput.Valid() {
+ fmt.Fprintf(w, "$(call dist-for-goals,%s,%s:%s)\n",
+ app.installApkName, app.noticeOutputs.HtmlOutput.String(), app.installApkName+"_NOTICE.html")
+ }
},
},
}
diff --git a/java/app.go b/java/app.go
index f58b0f8..e12b56c 100644
--- a/java/app.go
+++ b/java/app.go
@@ -141,6 +141,8 @@
installApkName string
additionalAaptFlags []string
+
+ noticeOutputs android.NoticeOutputs
}
func (a *AndroidApp) ExportedProguardFlagFiles() android.Paths {
@@ -357,11 +359,7 @@
return jniJarFile
}
-func (a *AndroidApp) noticeBuildActions(ctx android.ModuleContext, installDir android.OutputPath) android.OptionalPath {
- if !Bool(a.appProperties.Embed_notices) && !ctx.Config().IsEnvTrue("ALWAYS_EMBED_NOTICES") {
- return android.OptionalPath{}
- }
-
+func (a *AndroidApp) noticeBuildActions(ctx android.ModuleContext, installDir android.OutputPath) {
// Collect NOTICE files from all dependencies.
seenModules := make(map[android.Module]bool)
noticePathSet := make(map[android.Path]bool)
@@ -391,7 +389,7 @@
}
if len(noticePathSet) == 0 {
- return android.OptionalPath{}
+ return
}
var noticePaths []android.Path
for path := range noticePathSet {
@@ -400,9 +398,8 @@
sort.Slice(noticePaths, func(i, j int) bool {
return noticePaths[i].String() < noticePaths[j].String()
})
- noticeFile := android.BuildNoticeOutput(ctx, installDir, a.installApkName+".apk", noticePaths)
- return android.OptionalPathForPath(noticeFile)
+ a.noticeOutputs = android.BuildNoticeOutput(ctx, installDir, a.installApkName+".apk", noticePaths)
}
// Reads and prepends a main cert from the default cert dir if it hasn't been set already, i.e. it
@@ -455,7 +452,10 @@
installDir = android.PathForModuleInstall(ctx, "app", a.installApkName)
}
- a.aapt.noticeFile = a.noticeBuildActions(ctx, installDir)
+ a.noticeBuildActions(ctx, installDir)
+ if Bool(a.appProperties.Embed_notices) || ctx.Config().IsEnvTrue("ALWAYS_EMBED_NOTICES") {
+ a.aapt.noticeFile = a.noticeOutputs.HtmlGzOutput
+ }
// Process all building blocks, from AAPT to certificates.
a.aaptBuildActions(ctx)
diff --git a/java/app_test.go b/java/app_test.go
index c7ea338..721dd4d 100644
--- a/java/app_test.go
+++ b/java/app_test.go
@@ -1479,16 +1479,20 @@
// bar has NOTICE files to process, but embed_notices is not set.
bar := ctx.ModuleForTests("bar", "android_common")
- mergeNotices = bar.MaybeRule("mergeNoticesRule")
- if mergeNotices.Rule != nil {
- t.Errorf("mergeNotices shouldn't have run for bar")
+ res = bar.Output("package-res.apk")
+ aapt2Flags = res.Args["flags"]
+ e = "-A " + buildDir + "/.intermediates/bar/android_common/NOTICE"
+ if strings.Contains(aapt2Flags, e) {
+ t.Errorf("bar shouldn't have the asset dir flag for NOTICE: %q", e)
}
// baz's embed_notice is true, but it doesn't have any NOTICE files.
baz := ctx.ModuleForTests("baz", "android_common")
- mergeNotices = baz.MaybeRule("mergeNoticesRule")
- if mergeNotices.Rule != nil {
- t.Errorf("mergeNotices shouldn't have run for baz")
+ res = baz.Output("package-res.apk")
+ aapt2Flags = res.Args["flags"]
+ e = "-A " + buildDir + "/.intermediates/baz/android_common/NOTICE"
+ if strings.Contains(aapt2Flags, e) {
+ t.Errorf("baz shouldn't have the asset dir flag for NOTICE: %q", e)
}
}
diff --git a/ui/build/cleanbuild.go b/ui/build/cleanbuild.go
index c47f614..8e7f96a 100644
--- a/ui/build/cleanbuild.go
+++ b/ui/build/cleanbuild.go
@@ -111,7 +111,7 @@
productOut("system_other"),
productOut("vendor"),
productOut("product"),
- productOut("product_services"),
+ productOut("system_ext"),
productOut("oem"),
productOut("obj/FAKE"),
productOut("breakpad"),
diff --git a/ui/build/config.go b/ui/build/config.go
index 4a70f06..4e19e9e 100644
--- a/ui/build/config.go
+++ b/ui/build/config.go
@@ -266,6 +266,10 @@
if err != nil {
ctx.Fatalf("Error retrieving top directory: %v", err)
}
+ dir, err = filepath.EvalSymlinks(dir)
+ if err != nil {
+ ctx.Fatalf("Unable to evaluate symlink of %s: %v", dir, err)
+ }
dir, err = filepath.Abs(dir)
if err != nil {
ctx.Fatalf("Unable to find absolute path %s: %v", dir, err)
diff --git a/ui/build/config_test.go b/ui/build/config_test.go
index 856af11..7a1ee17 100644
--- a/ui/build/config_test.go
+++ b/ui/build/config_test.go
@@ -690,6 +690,9 @@
// Build files that exists in the source tree.
buildFiles []string
+ // Create root symlink that points to topDir.
+ rootSymlink bool
+
// ********* Action *********
// Arguments passed in to soong_ui.
args []string
@@ -738,6 +741,22 @@
createDirectories(t, topDir, tt.dirsInTrees)
createBuildFiles(t, topDir, tt.buildFiles)
+ if tt.rootSymlink {
+ // Create a secondary root source tree which points to the true root source tree.
+ symlinkTopDir, err := ioutil.TempDir("", "")
+ if err != nil {
+ t.Fatalf("failed to create symlink temp dir: %v", err)
+ }
+ defer os.RemoveAll(symlinkTopDir)
+
+ symlinkTopDir = filepath.Join(symlinkTopDir, "root")
+ err = os.Symlink(topDir, symlinkTopDir)
+ if err != nil {
+ t.Fatalf("failed to create symlink: %v", err)
+ }
+ topDir = symlinkTopDir
+ }
+
r := setTop(t, topDir)
defer r()
@@ -796,7 +815,17 @@
dirsInTrees: []string{"0/1/2", "0/2", "0/3"},
buildFiles: []string{"0/1/2/Android.mk", "0/2/Android.bp"},
args: []string{},
- curDir: "1/2/3/4/5/6/7/8/9",
+ curDir: "0/2",
+ tidyOnly: "",
+ expectedArgs: []string{},
+ expectedEnvVars: []envVar{},
+ }, {
+ description: "normal execution in symlink root source tree, no args",
+ dirsInTrees: []string{"0/1/2", "0/2", "0/3"},
+ buildFiles: []string{"0/1/2/Android.mk", "0/2/Android.bp"},
+ rootSymlink: true,
+ args: []string{},
+ curDir: "0/2",
tidyOnly: "",
expectedArgs: []string{},
expectedEnvVars: []envVar{},
@@ -932,6 +961,17 @@
description: "build action executed at root directory",
dirsInTrees: []string{},
buildFiles: []string{},
+ rootSymlink: false,
+ args: []string{},
+ curDir: ".",
+ tidyOnly: "",
+ expectedArgs: []string{},
+ expectedEnvVars: []envVar{},
+ }, {
+ description: "build action executed at root directory in symlink",
+ dirsInTrees: []string{},
+ buildFiles: []string{},
+ rootSymlink: true,
args: []string{},
curDir: ".",
tidyOnly: "",
@@ -1080,6 +1120,20 @@
description: "normal execution from top dir directory",
dirsInTrees: []string{"0/1/2/3.1", "0/1/2/3.2", "0/1/3", "0/2"},
buildFiles: []string{"0/1/2/3.1/Android.bp", "0/1/2/3.2/Android.bp", "0/1/3/Android.bp", "0/2/Android.bp"},
+ rootSymlink: false,
+ args: []string{"0/1/2/3.1", "0/1/2/3.2", "0/1/3", "0/2"},
+ curDir: ".",
+ tidyOnly: "",
+ expectedArgs: []string{"MODULES-IN-0-1-2-3.1", "MODULES-IN-0-1-2-3.2", "MODULES-IN-0-1-3", "MODULES-IN-0-2"},
+ expectedEnvVars: []envVar{
+ envVar{
+ name: "ONE_SHOT_MAKEFILE",
+ value: ""}},
+ }, {
+ description: "normal execution from top dir directory in symlink",
+ dirsInTrees: []string{"0/1/2/3.1", "0/1/2/3.2", "0/1/3", "0/2"},
+ buildFiles: []string{"0/1/2/3.1/Android.bp", "0/1/2/3.2/Android.bp", "0/1/3/Android.bp", "0/2/Android.bp"},
+ rootSymlink: true,
args: []string{"0/1/2/3.1", "0/1/2/3.2", "0/1/3", "0/2"},
curDir: ".",
tidyOnly: "",
diff --git a/ui/build/exec.go b/ui/build/exec.go
index 5c312bc..e435c53 100644
--- a/ui/build/exec.go
+++ b/ui/build/exec.go
@@ -15,7 +15,10 @@
package build
import (
+ "bufio"
+ "io"
"os/exec"
+ "strings"
)
// Cmd is a wrapper of os/exec.Cmd that integrates with the build context for
@@ -139,3 +142,34 @@
st.Finish()
c.reportError(err)
}
+
+// RunAndStreamOrFatal will run the command, while running print
+// any output, then handle any errors with a call to ctx.Fatal
+func (c *Cmd) RunAndStreamOrFatal() {
+ out, err := c.StdoutPipe()
+ if err != nil {
+ c.ctx.Fatal(err)
+ }
+ c.Stderr = c.Stdout
+
+ st := c.ctx.Status.StartTool()
+
+ c.StartOrFatal()
+
+ buf := bufio.NewReaderSize(out, 2*1024*1024)
+ for {
+ // Attempt to read whole lines, but write partial lines that are too long to fit in the buffer or hit EOF
+ line, err := buf.ReadString('\n')
+ if line != "" {
+ st.Print(strings.TrimSuffix(line, "\n"))
+ } else if err == io.EOF {
+ break
+ } else if err != nil {
+ c.ctx.Fatal(err)
+ }
+ }
+
+ err = c.Wait()
+ st.Finish()
+ c.reportError(err)
+}
diff --git a/ui/build/ninja.go b/ui/build/ninja.go
index 7994f3a..b41ac20 100644
--- a/ui/build/ninja.go
+++ b/ui/build/ninja.go
@@ -103,7 +103,7 @@
}()
ctx.Status.Status("Starting ninja...")
- cmd.RunAndPrintOrFatal()
+ cmd.RunAndStreamOrFatal()
}
type statusChecker struct {
diff --git a/ui/build/paths/config.go b/ui/build/paths/config.go
index e2c5043..a4be2ac 100644
--- a/ui/build/paths/config.go
+++ b/ui/build/paths/config.go
@@ -81,6 +81,7 @@
"bzip2": Allowed,
"dd": Allowed,
"diff": Allowed,
+ "dlv": Allowed,
"egrep": Allowed,
"expr": Allowed,
"find": Allowed,
diff --git a/ui/build/sandbox_linux.go b/ui/build/sandbox_linux.go
index b94db74..11ff667 100644
--- a/ui/build/sandbox_linux.go
+++ b/ui/build/sandbox_linux.go
@@ -162,6 +162,10 @@
c.ctx.Printf("AllowBuildBrokenUsesNetwork: %v", c.Sandbox.AllowBuildBrokenUsesNetwork)
c.ctx.Printf("BuildBrokenUsesNetwork: %v", c.config.BuildBrokenUsesNetwork())
sandboxArgs = append(sandboxArgs, "-N")
+ } else if dlv, _ := c.config.Environment().Get("SOONG_DELVE"); dlv != "" {
+ // The debugger is enabled and soong_build will pause until a remote delve process connects, allow
+ // network connections.
+ sandboxArgs = append(sandboxArgs, "-N")
}
// Stop nsjail from parsing arguments
diff --git a/ui/build/soong.go b/ui/build/soong.go
index 2ce1ac9..3388417 100644
--- a/ui/build/soong.go
+++ b/ui/build/soong.go
@@ -120,7 +120,7 @@
"--frontend_file", fifo,
"-f", filepath.Join(config.SoongOutDir(), file))
cmd.Sandbox = soongSandbox
- cmd.RunAndPrintOrFatal()
+ cmd.RunAndStreamOrFatal()
}
ninja("minibootstrap", ".minibootstrap/build.ninja")