summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--android/Android.bp4
-rw-r--r--android/androidmk.go27
-rw-r--r--android/androidmk_test.go34
-rw-r--r--android/apex.go212
-rw-r--r--android/apex_test.go111
-rw-r--r--android/bazel_overlay.go76
-rw-r--r--android/config.go238
-rw-r--r--android/defs.go2
-rw-r--r--android/filegroup.go23
-rw-r--r--android/makefile_goal.go99
-rw-r--r--android/makevars.go121
-rw-r--r--android/module.go41
-rw-r--r--android/mutator.go5
-rw-r--r--android/neverallow.go12
-rw-r--r--android/neverallow_test.go34
-rw-r--r--android/override_module.go12
-rw-r--r--android/paths.go54
-rw-r--r--android/prebuilt_build_tool.go94
-rw-r--r--android/sdk.go31
-rw-r--r--android/test_suites.go75
-rw-r--r--android/testing.go40
-rw-r--r--android/util.go14
-rw-r--r--android/variable.go67
-rw-r--r--apex/androidmk.go25
-rw-r--r--apex/apex.go203
-rw-r--r--apex/apex_test.go340
-rw-r--r--apex/builder.go31
-rw-r--r--apex/prebuilt.go108
-rw-r--r--bpfix/bpfix/bpfix.go23
-rw-r--r--bpfix/bpfix/bpfix_test.go58
-rw-r--r--cc/Android.bp1
-rw-r--r--cc/androidmk.go68
-rw-r--r--cc/binary.go48
-rw-r--r--cc/binary_sdk_member.go7
-rw-r--r--cc/builder.go62
-rw-r--r--cc/cc.go1043
-rw-r--r--cc/cc_test.go140
-rw-r--r--cc/compiler.go25
-rw-r--r--cc/config/clang.go42
-rw-r--r--cc/config/global.go2
-rw-r--r--cc/config/integer_overflow_blocklist.txt (renamed from cc/config/integer_overflow_blacklist.txt)0
-rw-r--r--cc/coverage.go18
-rw-r--r--cc/fuzz.go2
-rw-r--r--cc/gen.go21
-rw-r--r--cc/genrule_test.go39
-rw-r--r--cc/image.go348
-rw-r--r--cc/installer.go4
-rw-r--r--cc/library.go77
-rw-r--r--cc/library_headers.go5
-rw-r--r--cc/library_sdk_member.go27
-rw-r--r--cc/linkable.go35
-rw-r--r--cc/llndk_library.go2
-rw-r--r--cc/lto.go35
-rw-r--r--cc/makevars.go2
-rw-r--r--cc/ndk_library.go60
-rw-r--r--cc/object.go8
-rw-r--r--cc/pgo.go22
-rw-r--r--cc/prebuilt.go27
-rw-r--r--cc/rs.go4
-rw-r--r--cc/sabi.go5
-rw-r--r--cc/sanitize.go273
-rw-r--r--cc/strip.go40
-rw-r--r--cc/test.go31
-rw-r--r--cc/testing.go48
-rw-r--r--cc/tidy.go3
-rw-r--r--cc/toolchain_library.go7
-rw-r--r--cc/util.go5
-rw-r--r--cc/vendor_public_library.go2
-rw-r--r--cc/vendor_snapshot.go278
-rw-r--r--cc/vndk.go10
-rw-r--r--cc/vndk_prebuilt.go7
-rw-r--r--cmd/diff_target_files/Android.bp4
-rw-r--r--cmd/diff_target_files/allow_list.go (renamed from cmd/diff_target_files/whitelist.go)56
-rw-r--r--cmd/diff_target_files/allow_list_test.go (renamed from cmd/diff_target_files/whitelist_test.go)18
-rw-r--r--cmd/diff_target_files/compare.go4
-rw-r--r--cmd/diff_target_files/diff_target_files.go10
-rw-r--r--cmd/merge_zips/merge_zips.go2
-rw-r--r--cmd/soong_build/Android.bp4
-rw-r--r--cmd/soong_build/bazel_overlay.go449
-rw-r--r--cmd/soong_build/bazel_overlay_test.go255
-rw-r--r--cmd/soong_build/main.go21
-rw-r--r--cmd/soong_ui/main.go41
-rw-r--r--dexpreopt/config.go112
-rw-r--r--dexpreopt/dexpreopt.go161
-rw-r--r--genrule/genrule.go12
-rw-r--r--go.mod2
-rw-r--r--java/Android.bp2
-rw-r--r--java/aar.go35
-rw-r--r--java/android_manifest.go9
-rw-r--r--java/androidmk.go44
-rwxr-xr-xjava/app.go67
-rw-r--r--java/app_test.go223
-rw-r--r--java/config/config.go20
-rw-r--r--java/config/makevars.go2
-rw-r--r--java/device_host_converter.go3
-rw-r--r--java/dex.go154
-rw-r--r--java/dexpreopt_bootjars.go45
-rw-r--r--java/dexpreopt_bootjars_test.go2
-rw-r--r--java/dexpreopt_config.go66
-rw-r--r--java/droiddoc.go84
-rw-r--r--java/hiddenapi.go4
-rw-r--r--java/hiddenapi_singleton.go34
-rw-r--r--java/java.go242
-rw-r--r--java/java_test.go101
-rw-r--r--java/legacy_core_platform_api_usage.go174
-rw-r--r--java/lint.go158
-rw-r--r--java/prebuilt_apis.go36
-rw-r--r--java/robolectric.go181
-rw-r--r--java/sdk.go60
-rw-r--r--java/sdk_library.go305
-rw-r--r--java/sdk_test.go64
-rw-r--r--java/testing.go23
-rw-r--r--phony/phony.go5
-rw-r--r--python/binary.go2
-rw-r--r--python/builder.go2
-rw-r--r--python/python.go21
-rw-r--r--python/python_test.go6
-rw-r--r--rust/Android.bp5
-rw-r--r--rust/androidmk.go44
-rw-r--r--rust/binary.go21
-rw-r--r--rust/binary_test.go77
-rw-r--r--rust/bindgen.go206
-rw-r--r--rust/bindgen_test.go84
-rw-r--r--rust/builder.go47
-rw-r--r--rust/builder_test.go42
-rw-r--r--rust/clippy.go16
-rw-r--r--rust/clippy_test.go68
-rw-r--r--rust/compiler.go60
-rw-r--r--rust/compiler_test.go102
-rw-r--r--rust/config/allowed_list.go4
-rw-r--r--rust/config/global.go2
-rw-r--r--rust/config/lints.go112
-rw-r--r--rust/coverage.go2
-rw-r--r--rust/coverage_test.go2
-rw-r--r--rust/library.go75
-rw-r--r--rust/library_test.go16
-rw-r--r--rust/prebuilt.go4
-rw-r--r--rust/proc_macro.go5
-rw-r--r--rust/project_json.go26
-rw-r--r--rust/project_json_test.go142
-rw-r--r--rust/rust.go281
-rw-r--r--rust/rust_test.go156
-rw-r--r--rust/source_provider.go97
-rw-r--r--rust/source_provider_test.go31
-rw-r--r--rust/test.go13
-rw-r--r--rust/testing.go26
-rwxr-xr-xscripts/build-aml-prebuilts.sh2
-rwxr-xr-xscripts/build-mainline-modules.sh12
-rw-r--r--sdk/cc_sdk_test.go569
-rw-r--r--sdk/java_sdk_test.go16
-rw-r--r--sdk/sdk.go41
-rw-r--r--sdk/testing.go5
-rw-r--r--sdk/update.go111
-rw-r--r--sh/Android.bp1
-rw-r--r--sh/sh_binary.go145
-rw-r--r--sh/sh_binary_test.go114
-rw-r--r--sysprop/sysprop_test.go2
-rw-r--r--third_party/zip/android.go9
-rw-r--r--third_party/zip/zip_test.go2
-rw-r--r--tradefed/autogen.go15
-rw-r--r--tradefed/config.go1
-rw-r--r--ui/build/config.go100
-rw-r--r--ui/build/dumpvars.go3
-rw-r--r--ui/build/kati.go6
-rw-r--r--ui/build/paths/config.go1
-rw-r--r--ui/build/rbe.go35
-rw-r--r--ui/build/rbe_test.go29
-rw-r--r--ui/build/upload.go4
-rw-r--r--ui/metrics/metrics.go8
-rw-r--r--ui/metrics/metrics_proto/metrics.pb.go199
-rw-r--r--ui/metrics/metrics_proto/metrics.proto10
-rw-r--r--ui/terminal/Android.bp2
-rw-r--r--ui/terminal/simple_status.go (renamed from ui/terminal/dumb_status.go)18
-rw-r--r--ui/terminal/status.go6
-rw-r--r--ui/terminal/status_test.go92
-rw-r--r--zip/cmd/main.go12
-rw-r--r--zip/zip.go24
-rw-r--r--zip/zip_test.go21
178 files changed, 8737 insertions, 3066 deletions
diff --git a/android/Android.bp b/android/Android.bp
index 977345b6b..a1b515940 100644
--- a/android/Android.bp
+++ b/android/Android.bp
@@ -15,6 +15,7 @@ bootstrap_go_package {
"apex.go",
"api_levels.go",
"arch.go",
+ "bazel_overlay.go",
"config.go",
"csuite_config.go",
"defaults.go",
@@ -24,6 +25,7 @@ bootstrap_go_package {
"filegroup.go",
"hooks.go",
"image.go",
+ "makefile_goal.go",
"makevars.go",
"metrics.go",
"module.go",
@@ -39,6 +41,7 @@ bootstrap_go_package {
"paths.go",
"phony.go",
"prebuilt.go",
+ "prebuilt_build_tool.go",
"proto.go",
"register.go",
"rule_builder.go",
@@ -46,6 +49,7 @@ bootstrap_go_package {
"sdk.go",
"singleton.go",
"soong_config_modules.go",
+ "test_suites.go",
"testing.go",
"util.go",
"variable.go",
diff --git a/android/androidmk.go b/android/androidmk.go
index dfc68c437..fafbfd61e 100644
--- a/android/androidmk.go
+++ b/android/androidmk.go
@@ -126,6 +126,26 @@ func (a *AndroidMkEntries) AddOptionalPath(name string, path OptionalPath) {
}
}
+func (a *AndroidMkEntries) SetPaths(name string, paths Paths) {
+ if _, ok := a.EntryMap[name]; !ok {
+ a.entryOrder = append(a.entryOrder, name)
+ }
+ a.EntryMap[name] = paths.Strings()
+}
+
+func (a *AndroidMkEntries) SetOptionalPaths(name string, paths Paths) {
+ if len(paths) > 0 {
+ a.SetPaths(name, paths)
+ }
+}
+
+func (a *AndroidMkEntries) AddPaths(name string, paths Paths) {
+ if _, ok := a.EntryMap[name]; !ok {
+ a.entryOrder = append(a.entryOrder, name)
+ }
+ a.EntryMap[name] = append(a.EntryMap[name], paths.Strings()...)
+}
+
func (a *AndroidMkEntries) SetBoolIfTrue(name string, flag bool) {
if flag {
if _, ok := a.EntryMap[name]; !ok {
@@ -163,12 +183,15 @@ func (a *AndroidMkEntries) GetDistForGoals(mod blueprint.Module) []string {
name := amod.BaseModuleName()
var ret []string
+ var availableTaggedDists TaggedDistFiles
- availableTaggedDists := TaggedDistFiles{}
- if a.DistFiles != nil && len(a.DistFiles[""]) > 0 {
+ if a.DistFiles != nil {
availableTaggedDists = a.DistFiles
} else if a.OutputFile.Valid() {
availableTaggedDists = MakeDefaultDistFiles(a.OutputFile.Path())
+ } else {
+ // Nothing dist-able for this module.
+ return nil
}
// Iterate over this module's dist structs, merged from the dist and dists properties.
diff --git a/android/androidmk_test.go b/android/androidmk_test.go
index 250f086e5..a558f453f 100644
--- a/android/androidmk_test.go
+++ b/android/androidmk_test.go
@@ -45,6 +45,8 @@ func (m *customModule) OutputFiles(tag string) (Paths, error) {
return PathsForTesting("one.out"), nil
case ".multiple":
return PathsForTesting("two.out", "three/four.out"), nil
+ case ".another-tag":
+ return PathsForTesting("another.out"), nil
default:
return nil, fmt.Errorf("unsupported module reference tag %q", tag)
}
@@ -123,6 +125,38 @@ func TestGetDistForGoals(t *testing.T) {
bp: `
custom {
name: "foo",
+ dist: {
+ targets: ["my_goal"],
+ tag: ".another-tag",
+ }
+ }
+ `,
+ expectedAndroidMkLines: []string{
+ ".PHONY: my_goal\n",
+ "$(call dist-for-goals,my_goal,another.out:another.out)\n",
+ },
+ },
+ {
+ bp: `
+ custom {
+ name: "foo",
+ dists: [
+ {
+ targets: ["my_goal"],
+ tag: ".another-tag",
+ },
+ ],
+ }
+ `,
+ expectedAndroidMkLines: []string{
+ ".PHONY: my_goal\n",
+ "$(call dist-for-goals,my_goal,another.out:another.out)\n",
+ },
+ },
+ {
+ bp: `
+ custom {
+ name: "foo",
dists: [
{
targets: ["my_goal"],
diff --git a/android/apex.go b/android/apex.go
index 47f07ca96..f857ec692 100644
--- a/android/apex.go
+++ b/android/apex.go
@@ -29,11 +29,22 @@ const (
)
type ApexInfo struct {
- // Name of the apex variant that this module is mutated into
- ApexName string
+ // Name of the apex variation that this module is mutated into
+ ApexVariationName string
MinSdkVersion int
Updatable bool
+ RequiredSdks SdkRefs
+
+ InApexes []string
+}
+
+func (i ApexInfo) mergedName() string {
+ name := "apex" + strconv.Itoa(i.MinSdkVersion)
+ for _, sdk := range i.RequiredSdks {
+ name += "_" + sdk.Name + "_" + sdk.Version
+ }
+ return name
}
// Extracted from ApexModule to make it easier to define custom subsets of the
@@ -65,23 +76,26 @@ type ApexModule interface {
apexModuleBase() *ApexModuleBase
- // Marks that this module should be built for the specified APEXes.
+ // Marks that this module should be built for the specified APEX.
// Call this before apex.apexMutator is run.
- BuildForApexes(apexes []ApexInfo)
-
- // Returns the APEXes that this module will be built for
- ApexVariations() []ApexInfo
+ BuildForApex(apex ApexInfo)
+
+ // Returns the name of APEX variation that this module will be built for.
+ // Empty string is returned when 'IsForPlatform() == true'. Note that a
+ // module can beincluded in multiple APEXes, in which case, the module
+ // is mutated into one or more variants, each of which is for one or
+ // more APEXes. This method returns the name of the APEX variation of
+ // the module.
+ // Call this after apex.apexMutator is run.
+ ApexVariationName() string
- // Returns the name of APEX that this module will be built for. Empty string
- // is returned when 'IsForPlatform() == true'. Note that a module can be
- // included in multiple APEXes, in which case, the module is mutated into
- // multiple modules each of which for an APEX. This method returns the
- // name of the APEX that a variant module is for.
+ // Returns the name of the APEX modules that this variant of this module
+ // is present in.
// Call this after apex.apexMutator is run.
- ApexName() string
+ InApexes() []string
// Tests whether this module will be built for the platform or not.
- // This is a shortcut for ApexName() == ""
+ // This is a shortcut for ApexVariationName() == ""
IsForPlatform() bool
// Tests if this module could have APEX variants. APEX variants are
@@ -96,7 +110,7 @@ type ApexModule interface {
IsInstallableToApex() bool
// Mutate this module into one or more variants each of which is built
- // for an APEX marked via BuildForApexes().
+ // for an APEX marked via BuildForApex().
CreateApexVariations(mctx BottomUpMutatorContext) []Module
// Tests if this module is available for the specified APEX or ":platform"
@@ -128,6 +142,15 @@ type ApexModule interface {
// Returns nil if this module supports sdkVersion
// Otherwise, returns error with reason
ShouldSupportSdkVersion(ctx BaseModuleContext, sdkVersion int) error
+
+ // Returns true if this module needs a unique variation per apex, for example if
+ // use_apex_name_macro is set.
+ UniqueApexVariations() bool
+
+ // UpdateUniqueApexVariationsForDeps sets UniqueApexVariationsForDeps if any dependencies
+ // that are in the same APEX have unique APEX variations so that the module can link against
+ // the right variant.
+ UpdateUniqueApexVariationsForDeps(mctx BottomUpMutatorContext)
}
type ApexProperties struct {
@@ -137,12 +160,15 @@ type ApexProperties struct {
//
// "//apex_available:anyapex" is a pseudo APEX name that matches to any APEX.
// "//apex_available:platform" refers to non-APEX partitions like "system.img".
+ // "com.android.gki.*" matches any APEX module name with the prefix "com.android.gki.".
// Default is ["//apex_available:platform"].
Apex_available []string
Info ApexInfo `blueprint:"mutated"`
NotAvailableForPlatform bool `blueprint:"mutated"`
+
+ UniqueApexVariationsForDeps bool `blueprint:"mutated"`
}
// Marker interface that identifies dependencies that are excluded from APEX
@@ -178,30 +204,68 @@ func (m *ApexModuleBase) TestFor() []string {
return nil
}
-func (m *ApexModuleBase) BuildForApexes(apexes []ApexInfo) {
+func (m *ApexModuleBase) UniqueApexVariations() bool {
+ return false
+}
+
+func (m *ApexModuleBase) UpdateUniqueApexVariationsForDeps(mctx BottomUpMutatorContext) {
+ // anyInSameApex returns true if the two ApexInfo lists contain any values in an InApexes list
+ // in common. It is used instead of DepIsInSameApex because it needs to determine if the dep
+ // is in the same APEX due to being directly included, not only if it is included _because_ it
+ // is a dependency.
+ anyInSameApex := func(a, b []ApexInfo) bool {
+ collectApexes := func(infos []ApexInfo) []string {
+ var ret []string
+ for _, info := range infos {
+ ret = append(ret, info.InApexes...)
+ }
+ return ret
+ }
+
+ aApexes := collectApexes(a)
+ bApexes := collectApexes(b)
+ sort.Strings(bApexes)
+ for _, aApex := range aApexes {
+ index := sort.SearchStrings(bApexes, aApex)
+ if index < len(bApexes) && bApexes[index] == aApex {
+ return true
+ }
+ }
+ return false
+ }
+
+ mctx.VisitDirectDeps(func(dep Module) {
+ if depApexModule, ok := dep.(ApexModule); ok {
+ if anyInSameApex(depApexModule.apexModuleBase().apexVariations, m.apexVariations) &&
+ (depApexModule.UniqueApexVariations() ||
+ depApexModule.apexModuleBase().ApexProperties.UniqueApexVariationsForDeps) {
+ m.ApexProperties.UniqueApexVariationsForDeps = true
+ }
+ }
+ })
+}
+
+func (m *ApexModuleBase) BuildForApex(apex ApexInfo) {
m.apexVariationsLock.Lock()
defer m.apexVariationsLock.Unlock()
-nextApex:
- for _, apex := range apexes {
- for _, v := range m.apexVariations {
- if v.ApexName == apex.ApexName {
- continue nextApex
- }
+ for _, v := range m.apexVariations {
+ if v.ApexVariationName == apex.ApexVariationName {
+ return
}
- m.apexVariations = append(m.apexVariations, apex)
}
+ m.apexVariations = append(m.apexVariations, apex)
}
-func (m *ApexModuleBase) ApexVariations() []ApexInfo {
- return m.apexVariations
+func (m *ApexModuleBase) ApexVariationName() string {
+ return m.ApexProperties.Info.ApexVariationName
}
-func (m *ApexModuleBase) ApexName() string {
- return m.ApexProperties.Info.ApexName
+func (m *ApexModuleBase) InApexes() []string {
+ return m.ApexProperties.Info.InApexes
}
func (m *ApexModuleBase) IsForPlatform() bool {
- return m.ApexProperties.Info.ApexName == ""
+ return m.ApexProperties.Info.ApexVariationName == ""
}
func (m *ApexModuleBase) CanHaveApexVariants() bool {
@@ -216,6 +280,7 @@ func (m *ApexModuleBase) IsInstallableToApex() bool {
const (
AvailableToPlatform = "//apex_available:platform"
AvailableToAnyApex = "//apex_available:anyapex"
+ AvailableToGkiApex = "com.android.gki.*"
)
func CheckAvailableForApex(what string, apex_available []string) bool {
@@ -225,7 +290,8 @@ func CheckAvailableForApex(what string, apex_available []string) bool {
return what == AvailableToPlatform
}
return InList(what, apex_available) ||
- (what != AvailableToPlatform && InList(AvailableToAnyApex, apex_available))
+ (what != AvailableToPlatform && InList(AvailableToAnyApex, apex_available)) ||
+ (strings.HasPrefix(what, "com.android.gki.") && InList(AvailableToGkiApex, apex_available))
}
func (m *ApexModuleBase) AvailableFor(what string) bool {
@@ -259,7 +325,7 @@ func (m *ApexModuleBase) ChooseSdkVersion(versionList []string, maxSdkVersion in
func (m *ApexModuleBase) checkApexAvailableProperty(mctx BaseModuleContext) {
for _, n := range m.ApexProperties.Apex_available {
- if n == AvailableToPlatform || n == AvailableToAnyApex {
+ if n == AvailableToPlatform || n == AvailableToAnyApex || n == AvailableToGkiApex {
continue
}
if !mctx.OtherModuleExists(n) && !mctx.Config().AllowMissingDependencies() {
@@ -276,17 +342,48 @@ type byApexName []ApexInfo
func (a byApexName) Len() int { return len(a) }
func (a byApexName) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
-func (a byApexName) Less(i, j int) bool { return a[i].ApexName < a[j].ApexName }
+func (a byApexName) Less(i, j int) bool { return a[i].ApexVariationName < a[j].ApexVariationName }
+
+// mergeApexVariations deduplicates APEX variations that would build identically into a common
+// variation. It returns the reduced list of variations and a list of aliases from the original
+// variation names to the new variation names.
+func mergeApexVariations(apexVariations []ApexInfo) (merged []ApexInfo, aliases [][2]string) {
+ sort.Sort(byApexName(apexVariations))
+ seen := make(map[string]int)
+ for _, apexInfo := range apexVariations {
+ apexName := apexInfo.ApexVariationName
+ mergedName := apexInfo.mergedName()
+ if index, exists := seen[mergedName]; exists {
+ merged[index].InApexes = append(merged[index].InApexes, apexName)
+ merged[index].Updatable = merged[index].Updatable || apexInfo.Updatable
+ } else {
+ seen[mergedName] = len(merged)
+ apexInfo.ApexVariationName = apexInfo.mergedName()
+ apexInfo.InApexes = CopyOf(apexInfo.InApexes)
+ merged = append(merged, apexInfo)
+ }
+ aliases = append(aliases, [2]string{apexName, mergedName})
+ }
+ return merged, aliases
+}
func (m *ApexModuleBase) CreateApexVariations(mctx BottomUpMutatorContext) []Module {
if len(m.apexVariations) > 0 {
m.checkApexAvailableProperty(mctx)
- sort.Sort(byApexName(m.apexVariations))
+ var apexVariations []ApexInfo
+ var aliases [][2]string
+ if !mctx.Module().(ApexModule).UniqueApexVariations() && !m.ApexProperties.UniqueApexVariationsForDeps {
+ apexVariations, aliases = mergeApexVariations(m.apexVariations)
+ } else {
+ apexVariations = m.apexVariations
+ }
+
+ sort.Sort(byApexName(apexVariations))
variations := []string{}
variations = append(variations, "") // Original variation for platform
- for _, apex := range m.apexVariations {
- variations = append(variations, apex.ApexName)
+ for _, apex := range apexVariations {
+ variations = append(variations, apex.ApexVariationName)
}
defaultVariation := ""
@@ -296,12 +393,20 @@ func (m *ApexModuleBase) CreateApexVariations(mctx BottomUpMutatorContext) []Mod
for i, mod := range modules {
platformVariation := i == 0
if platformVariation && !mctx.Host() && !mod.(ApexModule).AvailableFor(AvailableToPlatform) {
- mod.SkipInstall()
+ // Do not install the module for platform, but still allow it to output
+ // uninstallable AndroidMk entries in certain cases when they have
+ // side effects.
+ mod.MakeUninstallable()
}
if !platformVariation {
- mod.(ApexModule).apexModuleBase().ApexProperties.Info = m.apexVariations[i-1]
+ mod.(ApexModule).apexModuleBase().ApexProperties.Info = apexVariations[i-1]
}
}
+
+ for _, alias := range aliases {
+ mctx.CreateAliasVariation(alias[0], alias[1])
+ }
+
return modules
}
return nil
@@ -327,16 +432,17 @@ func apexNamesMap() map[string]map[string]bool {
// depended on by the specified APEXes. Directly depending means that a module
// is explicitly listed in the build definition of the APEX via properties like
// native_shared_libs, java_libs, etc.
-func UpdateApexDependency(apexes []ApexInfo, moduleName string, directDep bool) {
+func UpdateApexDependency(apex ApexInfo, moduleName string, directDep bool) {
apexNamesMapMutex.Lock()
defer apexNamesMapMutex.Unlock()
- for _, apex := range apexes {
- apexesForModule, ok := apexNamesMap()[moduleName]
- if !ok {
- apexesForModule = make(map[string]bool)
- apexNamesMap()[moduleName] = apexesForModule
- }
- apexesForModule[apex.ApexName] = apexesForModule[apex.ApexName] || directDep
+ apexesForModule, ok := apexNamesMap()[moduleName]
+ if !ok {
+ apexesForModule = make(map[string]bool)
+ apexNamesMap()[moduleName] = apexesForModule
+ }
+ apexesForModule[apex.ApexVariationName] = apexesForModule[apex.ApexVariationName] || directDep
+ for _, apexName := range apex.InApexes {
+ apexesForModule[apexName] = apexesForModule[apex.ApexVariationName] || directDep
}
}
@@ -353,12 +459,26 @@ func ClearApexDependency() {
func DirectlyInApex(apexName string, moduleName string) bool {
apexNamesMapMutex.Lock()
defer apexNamesMapMutex.Unlock()
- if apexNames, ok := apexNamesMap()[moduleName]; ok {
- return apexNames[apexName]
+ if apexNamesForModule, ok := apexNamesMap()[moduleName]; ok {
+ return apexNamesForModule[apexName]
}
return false
}
+// Tests whether a module named moduleName is directly depended on by all APEXes
+// in a list of apexNames.
+func DirectlyInAllApexes(apexNames []string, moduleName string) bool {
+ apexNamesMapMutex.Lock()
+ defer apexNamesMapMutex.Unlock()
+ for _, apexName := range apexNames {
+ apexNamesForModule := apexNamesMap()[moduleName]
+ if !apexNamesForModule[apexName] {
+ return false
+ }
+ }
+ return true
+}
+
type hostContext interface {
Host() bool
}
diff --git a/android/apex_test.go b/android/apex_test.go
new file mode 100644
index 000000000..db02833e7
--- /dev/null
+++ b/android/apex_test.go
@@ -0,0 +1,111 @@
+// Copyright 2020 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package android
+
+import (
+ "reflect"
+ "testing"
+)
+
+func Test_mergeApexVariations(t *testing.T) {
+ tests := []struct {
+ name string
+ in []ApexInfo
+ wantMerged []ApexInfo
+ wantAliases [][2]string
+ }{
+ {
+ name: "single",
+ in: []ApexInfo{
+ {"foo", 10000, false, nil, []string{"foo"}},
+ },
+ wantMerged: []ApexInfo{
+ {"apex10000", 10000, false, nil, []string{"foo"}},
+ },
+ wantAliases: [][2]string{
+ {"foo", "apex10000"},
+ },
+ },
+ {
+ name: "merge",
+ in: []ApexInfo{
+ {"foo", 10000, false, SdkRefs{{"baz", "1"}}, []string{"foo"}},
+ {"bar", 10000, false, SdkRefs{{"baz", "1"}}, []string{"bar"}},
+ },
+ wantMerged: []ApexInfo{
+ {"apex10000_baz_1", 10000, false, SdkRefs{{"baz", "1"}}, []string{"bar", "foo"}},
+ },
+ wantAliases: [][2]string{
+ {"bar", "apex10000_baz_1"},
+ {"foo", "apex10000_baz_1"},
+ },
+ },
+ {
+ name: "don't merge version",
+ in: []ApexInfo{
+ {"foo", 10000, false, nil, []string{"foo"}},
+ {"bar", 30, false, nil, []string{"bar"}},
+ },
+ wantMerged: []ApexInfo{
+ {"apex30", 30, false, nil, []string{"bar"}},
+ {"apex10000", 10000, false, nil, []string{"foo"}},
+ },
+ wantAliases: [][2]string{
+ {"bar", "apex30"},
+ {"foo", "apex10000"},
+ },
+ },
+ {
+ name: "merge updatable",
+ in: []ApexInfo{
+ {"foo", 10000, false, nil, []string{"foo"}},
+ {"bar", 10000, true, nil, []string{"bar"}},
+ },
+ wantMerged: []ApexInfo{
+ {"apex10000", 10000, true, nil, []string{"bar", "foo"}},
+ },
+ wantAliases: [][2]string{
+ {"bar", "apex10000"},
+ {"foo", "apex10000"},
+ },
+ },
+ {
+ name: "don't merge sdks",
+ in: []ApexInfo{
+ {"foo", 10000, false, SdkRefs{{"baz", "1"}}, []string{"foo"}},
+ {"bar", 10000, false, SdkRefs{{"baz", "2"}}, []string{"bar"}},
+ },
+ wantMerged: []ApexInfo{
+ {"apex10000_baz_2", 10000, false, SdkRefs{{"baz", "2"}}, []string{"bar"}},
+ {"apex10000_baz_1", 10000, false, SdkRefs{{"baz", "1"}}, []string{"foo"}},
+ },
+ wantAliases: [][2]string{
+ {"bar", "apex10000_baz_2"},
+ {"foo", "apex10000_baz_1"},
+ },
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ gotMerged, gotAliases := mergeApexVariations(tt.in)
+ if !reflect.DeepEqual(gotMerged, tt.wantMerged) {
+ t.Errorf("mergeApexVariations() gotMerged = %v, want %v", gotMerged, tt.wantMerged)
+ }
+ if !reflect.DeepEqual(gotAliases, tt.wantAliases) {
+ t.Errorf("mergeApexVariations() gotAliases = %v, want %v", gotAliases, tt.wantAliases)
+ }
+ })
+ }
+}
diff --git a/android/bazel_overlay.go b/android/bazel_overlay.go
new file mode 100644
index 000000000..a0342826d
--- /dev/null
+++ b/android/bazel_overlay.go
@@ -0,0 +1,76 @@
+// Copyright 2020 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package android
+
+import (
+ "fmt"
+ "os"
+ "strings"
+
+ "github.com/google/blueprint"
+)
+
+// The Bazel Overlay singleton is responsible for generating the Ninja actions
+// for calling the soong_build primary builder in the main build.ninja file.
+func init() {
+ RegisterSingletonType("bazel_overlay", BazelOverlaySingleton)
+}
+
+func BazelOverlaySingleton() Singleton {
+ return &bazelOverlaySingleton{}
+}
+
+type bazelOverlaySingleton struct{}
+
+func (c *bazelOverlaySingleton) GenerateBuildActions(ctx SingletonContext) {
+ // Create a build and rule statement, using the Bazel overlay's WORKSPACE
+ // file as the output file marker.
+ var deps Paths
+ moduleListFilePath := pathForBuildToolDep(ctx, ctx.Config().moduleListFile)
+ deps = append(deps, moduleListFilePath)
+ deps = append(deps, pathForBuildToolDep(ctx, ctx.Config().ProductVariablesFileName))
+
+ bazelOverlayDirectory := PathForOutput(ctx, "bazel_overlay")
+ bazelOverlayWorkspaceFile := bazelOverlayDirectory.Join(ctx, "WORKSPACE")
+ primaryBuilder := primaryBuilderPath(ctx)
+ bazelOverlay := ctx.Rule(pctx, "bazelOverlay",
+ blueprint.RuleParams{
+ Command: fmt.Sprintf(
+ "rm -rf ${outDir}/* && %s --bazel_overlay_dir ${outDir} %s && echo WORKSPACE: `cat %s` > ${outDir}/.overlay-depfile.d",
+ primaryBuilder.String(),
+ strings.Join(os.Args[1:], " "),
+ moduleListFilePath.String(), // Use the contents of Android.bp.list as the depfile.
+ ),
+ CommandDeps: []string{primaryBuilder.String()},
+ Description: fmt.Sprintf(
+ "Creating the Bazel overlay workspace with %s at $outDir",
+ primaryBuilder.Base()),
+ Deps: blueprint.DepsGCC,
+ Depfile: "${outDir}/.overlay-depfile.d",
+ },
+ "outDir")
+
+ ctx.Build(pctx, BuildParams{
+ Rule: bazelOverlay,
+ Output: bazelOverlayWorkspaceFile,
+ Inputs: deps,
+ Args: map[string]string{
+ "outDir": bazelOverlayDirectory.String(),
+ },
+ })
+
+ // Add a phony target for building the bazel overlay
+ ctx.Phony("bazel_overlay", bazelOverlayWorkspaceFile)
+}
diff --git a/android/config.go b/android/config.go
index d680b652b..dd622e5b2 100644
--- a/android/config.go
+++ b/android/config.go
@@ -35,6 +35,7 @@ import (
var Bool = proptools.Bool
var String = proptools.String
+var StringDefault = proptools.StringDefault
const FutureApiLevel = 10000
@@ -337,8 +338,8 @@ func NewConfig(srcDir, buildDir string, moduleListFile string) (Config, error) {
config: config,
}
- // Sanity check the build and source directories. This won't catch strange
- // configurations with symlinks, but at least checks the obvious cases.
+ // Soundness check of the build and source directories. This won't catch strange
+ // configurations with symlinks, but at least checks the obvious case.
absBuildDir, err := filepath.Abs(buildDir)
if err != nil {
return Config{}, err
@@ -722,7 +723,7 @@ func (c *config) AllowMissingDependencies() bool {
return Bool(c.productVariables.Allow_missing_dependencies)
}
-// Returns true if building without full platform sources.
+// Returns true if a full platform source tree cannot be assumed.
func (c *config) UnbundledBuild() bool {
return Bool(c.productVariables.Unbundled_build)
}
@@ -733,18 +734,15 @@ func (c *config) UnbundledBuildApps() bool {
return Bool(c.productVariables.Unbundled_build_apps)
}
-func (c *config) UnbundledBuildUsePrebuiltSdks() bool {
- return Bool(c.productVariables.Unbundled_build) && !Bool(c.productVariables.Unbundled_build_sdks_from_source)
+// Returns true if building modules against prebuilt SDKs.
+func (c *config) AlwaysUsePrebuiltSdks() bool {
+ return Bool(c.productVariables.Always_use_prebuilt_sdks)
}
func (c *config) Fuchsia() bool {
return Bool(c.productVariables.Fuchsia)
}
-func (c *config) IsPdkBuild() bool {
- return Bool(c.productVariables.Pdk)
-}
-
func (c *config) MinimizeJavaDebugInfo() bool {
return Bool(c.productVariables.MinimizeJavaDebugInfo) && !Bool(c.productVariables.Eng)
}
@@ -913,34 +911,6 @@ func (c *config) ModulesLoadedByPrivilegedModules() []string {
return c.productVariables.ModulesLoadedByPrivilegedModules
}
-// Expected format for apexJarValue = <apex name>:<jar name>
-func SplitApexJarPair(ctx PathContext, str string) (string, string) {
- pair := strings.SplitN(str, ":", 2)
- if len(pair) == 2 {
- return pair[0], pair[1]
- } else {
- reportPathErrorf(ctx, "malformed (apex, jar) pair: '%s', expected format: <apex>:<jar>", str)
- return "error-apex", "error-jar"
- }
-}
-
-func GetJarsFromApexJarPairs(ctx PathContext, apexJarPairs []string) []string {
- modules := make([]string, len(apexJarPairs))
- for i, p := range apexJarPairs {
- _, jar := SplitApexJarPair(ctx, p)
- modules[i] = jar
- }
- return modules
-}
-
-func (c *config) BootJars() []string {
- ctx := NullPathContext{Config{
- config: c,
- }}
- return append(GetJarsFromApexJarPairs(ctx, c.productVariables.BootJars),
- GetJarsFromApexJarPairs(ctx, c.productVariables.UpdatableBootJars)...)
-}
-
func (c *config) DexpreoptGlobalConfig(ctx PathContext) ([]byte, error) {
if c.productVariables.DexpreoptGlobalConfig == nil {
return nil, nil
@@ -989,6 +959,10 @@ func (c *deviceConfig) VndkVersion() string {
return String(c.config.productVariables.DeviceVndkVersion)
}
+func (c *deviceConfig) CurrentApiLevelForVendorModules() string {
+ return StringDefault(c.config.productVariables.DeviceCurrentApiLevelForVendorModules, "current")
+}
+
func (c *deviceConfig) PlatformVndkVersion() string {
return String(c.config.productVariables.Platform_vndk_version)
}
@@ -1252,10 +1226,6 @@ func (c *config) MissingUsesLibraries() []string {
return c.productVariables.MissingUsesLibraries
}
-func (c *deviceConfig) BoardVndkRuntimeDisable() bool {
- return Bool(c.config.productVariables.BoardVndkRuntimeDisable)
-}
-
func (c *deviceConfig) DeviceArch() string {
return String(c.config.productVariables.DeviceArch)
}
@@ -1275,3 +1245,189 @@ func (c *deviceConfig) DeviceSecondaryArchVariant() string {
func (c *deviceConfig) BoardUsesRecoveryAsBoot() bool {
return Bool(c.config.productVariables.BoardUsesRecoveryAsBoot)
}
+
+func (c *deviceConfig) BoardKernelBinaries() []string {
+ return c.config.productVariables.BoardKernelBinaries
+}
+
+func (c *deviceConfig) BoardKernelModuleInterfaceVersions() []string {
+ return c.config.productVariables.BoardKernelModuleInterfaceVersions
+}
+
+// The ConfiguredJarList struct provides methods for handling a list of (apex, jar) pairs.
+// Such lists are used in the build system for things like bootclasspath jars or system server jars.
+// The apex part is either an apex name, or a special names "platform" or "system_ext". Jar is a
+// module name. The pairs come from Make product variables as a list of colon-separated strings.
+//
+// Examples:
+// - "com.android.art:core-oj"
+// - "platform:framework"
+// - "system_ext:foo"
+//
+type ConfiguredJarList struct {
+ apexes []string // A list of apex components.
+ jars []string // A list of jar components.
+}
+
+// The length of the list.
+func (l *ConfiguredJarList) Len() int {
+ return len(l.jars)
+}
+
+// Apex component of idx-th pair on the list.
+func (l *ConfiguredJarList) apex(idx int) string {
+ return l.apexes[idx]
+}
+
+// Jar component of idx-th pair on the list.
+func (l *ConfiguredJarList) Jar(idx int) string {
+ return l.jars[idx]
+}
+
+// If the list contains a pair with the given jar.
+func (l *ConfiguredJarList) ContainsJar(jar string) bool {
+ return InList(jar, l.jars)
+}
+
+// If the list contains the given (apex, jar) pair.
+func (l *ConfiguredJarList) containsApexJarPair(apex, jar string) bool {
+ for i := 0; i < l.Len(); i++ {
+ if apex == l.apex(i) && jar == l.Jar(i) {
+ return true
+ }
+ }
+ return false
+}
+
+// Index of the first pair with the given jar on the list, or -1 if none.
+func (l *ConfiguredJarList) IndexOfJar(jar string) int {
+ return IndexList(jar, l.jars)
+}
+
+// Append an (apex, jar) pair to the list.
+func (l *ConfiguredJarList) Append(apex string, jar string) {
+ l.apexes = append(l.apexes, apex)
+ l.jars = append(l.jars, jar)
+}
+
+// Filter out sublist.
+func (l *ConfiguredJarList) RemoveList(list ConfiguredJarList) {
+ apexes := make([]string, 0, l.Len())
+ jars := make([]string, 0, l.Len())
+
+ for i, jar := range l.jars {
+ apex := l.apex(i)
+ if !list.containsApexJarPair(apex, jar) {
+ apexes = append(apexes, apex)
+ jars = append(jars, jar)
+ }
+ }
+
+ l.apexes = apexes
+ l.jars = jars
+}
+
+// A copy of itself.
+func (l *ConfiguredJarList) CopyOf() ConfiguredJarList {
+ return ConfiguredJarList{CopyOf(l.apexes), CopyOf(l.jars)}
+}
+
+// A copy of the list of strings containing jar components.
+func (l *ConfiguredJarList) CopyOfJars() []string {
+ return CopyOf(l.jars)
+}
+
+// A copy of the list of strings with colon-separated (apex, jar) pairs.
+func (l *ConfiguredJarList) CopyOfApexJarPairs() []string {
+ pairs := make([]string, 0, l.Len())
+
+ for i, jar := range l.jars {
+ apex := l.apex(i)
+ pairs = append(pairs, apex+":"+jar)
+ }
+
+ return pairs
+}
+
+// A list of build paths based on the given directory prefix.
+func (l *ConfiguredJarList) BuildPaths(ctx PathContext, dir OutputPath) WritablePaths {
+ paths := make(WritablePaths, l.Len())
+ for i, jar := range l.jars {
+ paths[i] = dir.Join(ctx, ModuleStem(jar)+".jar")
+ }
+ return paths
+}
+
+func ModuleStem(module string) string {
+ // b/139391334: the stem of framework-minus-apex is framework. This is hard coded here until we
+ // find a good way to query the stem of a module before any other mutators are run.
+ if module == "framework-minus-apex" {
+ return "framework"
+ }
+ return module
+}
+
+// A list of on-device paths.
+func (l *ConfiguredJarList) DevicePaths(cfg Config, ostype OsType) []string {
+ paths := make([]string, l.Len())
+ for i, jar := range l.jars {
+ apex := l.apexes[i]
+ name := ModuleStem(jar) + ".jar"
+
+ var subdir string
+ if apex == "platform" {
+ subdir = "system/framework"
+ } else if apex == "system_ext" {
+ subdir = "system_ext/framework"
+ } else {
+ subdir = filepath.Join("apex", apex, "javalib")
+ }
+
+ if ostype.Class == Host {
+ paths[i] = filepath.Join(cfg.Getenv("OUT_DIR"), "host", cfg.PrebuiltOS(), subdir, name)
+ } else {
+ paths[i] = filepath.Join("/", subdir, name)
+ }
+ }
+ return paths
+}
+
+// Expected format for apexJarValue = <apex name>:<jar name>
+func splitConfiguredJarPair(ctx PathContext, str string) (string, string) {
+ pair := strings.SplitN(str, ":", 2)
+ if len(pair) == 2 {
+ return pair[0], pair[1]
+ } else {
+ ReportPathErrorf(ctx, "malformed (apex, jar) pair: '%s', expected format: <apex>:<jar>", str)
+ return "error-apex", "error-jar"
+ }
+}
+
+func CreateConfiguredJarList(ctx PathContext, list []string) ConfiguredJarList {
+ apexes := make([]string, 0, len(list))
+ jars := make([]string, 0, len(list))
+
+ l := ConfiguredJarList{apexes, jars}
+
+ for _, apexjar := range list {
+ apex, jar := splitConfiguredJarPair(ctx, apexjar)
+ l.Append(apex, jar)
+ }
+
+ return l
+}
+
+func EmptyConfiguredJarList() ConfiguredJarList {
+ return ConfiguredJarList{}
+}
+
+var earlyBootJarsKey = NewOnceKey("earlyBootJars")
+
+func (c *config) BootJars() []string {
+ return c.Once(earlyBootJarsKey, func() interface{} {
+ ctx := NullPathContext{Config{c}}
+ list := CreateConfiguredJarList(ctx,
+ append(CopyOf(c.productVariables.BootJars), c.productVariables.UpdatableBootJars...))
+ return list.CopyOfJars()
+ }).([]string)
+}
diff --git a/android/defs.go b/android/defs.go
index 45522246f..83daa0368 100644
--- a/android/defs.go
+++ b/android/defs.go
@@ -69,7 +69,7 @@ var (
// A symlink rule.
Symlink = pctx.AndroidStaticRule("Symlink",
blueprint.RuleParams{
- Command: "ln -f -s $fromPath $out",
+ Command: "rm -f $out && ln -f -s $fromPath $out",
Description: "symlink $out",
},
"fromPath")
diff --git a/android/filegroup.go b/android/filegroup.go
index ec522fc06..68311e39a 100644
--- a/android/filegroup.go
+++ b/android/filegroup.go
@@ -15,9 +15,7 @@
package android
import (
- "io"
"strings"
- "text/template"
)
func init() {
@@ -71,23 +69,8 @@ func (fg *fileGroup) Srcs() Paths {
return append(Paths{}, fg.srcs...)
}
-var androidMkTemplate = template.Must(template.New("filegroup").Parse(`
-ifdef {{.makeVar}}
- $(error variable {{.makeVar}} set by soong module is already set in make)
-endif
-{{.makeVar}} := {{.value}}
-.KATI_READONLY := {{.makeVar}}
-`))
-
-func (fg *fileGroup) AndroidMk() AndroidMkData {
- return AndroidMkData{
- Custom: func(w io.Writer, name, prefix, moduleDir string, data AndroidMkData) {
- if makeVar := String(fg.properties.Export_to_make_var); makeVar != "" {
- androidMkTemplate.Execute(w, map[string]string{
- "makeVar": makeVar,
- "value": strings.Join(fg.srcs.Strings(), " "),
- })
- }
- },
+func (fg *fileGroup) MakeVars(ctx MakeVarsModuleContext) {
+ if makeVar := String(fg.properties.Export_to_make_var); makeVar != "" {
+ ctx.StrictRaw(makeVar, strings.Join(fg.srcs.Strings(), " "))
}
}
diff --git a/android/makefile_goal.go b/android/makefile_goal.go
new file mode 100644
index 000000000..eae3976a8
--- /dev/null
+++ b/android/makefile_goal.go
@@ -0,0 +1,99 @@
+// Copyright 2020 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package android
+
+import (
+ "fmt"
+ "io"
+ "path/filepath"
+
+ "github.com/google/blueprint/proptools"
+)
+
+func init() {
+ RegisterModuleType("makefile_goal", MakefileGoalFactory)
+}
+
+type makefileGoalProperties struct {
+ // Sources.
+
+ // Makefile goal output file path, relative to PRODUCT_OUT.
+ Product_out_path *string
+}
+
+type makefileGoal struct {
+ ModuleBase
+
+ properties makefileGoalProperties
+
+ // Destination. Output file path of this module.
+ outputFilePath OutputPath
+}
+
+var _ AndroidMkEntriesProvider = (*makefileGoal)(nil)
+var _ OutputFileProducer = (*makefileGoal)(nil)
+
+// Input file of this makefile_goal module. Nil if none specified. May use variable names in makefiles.
+func (p *makefileGoal) inputPath() *string {
+ if p.properties.Product_out_path != nil {
+ return proptools.StringPtr(filepath.Join("$(PRODUCT_OUT)", proptools.String(p.properties.Product_out_path)))
+ }
+ return nil
+}
+
+// OutputFileProducer
+func (p *makefileGoal) OutputFiles(tag string) (Paths, error) {
+ if tag != "" {
+ return nil, fmt.Errorf("unsupported tag %q", tag)
+ }
+ return Paths{p.outputFilePath}, nil
+}
+
+// AndroidMkEntriesProvider
+func (p *makefileGoal) DepsMutator(ctx BottomUpMutatorContext) {
+ if p.inputPath() == nil {
+ ctx.PropertyErrorf("product_out_path", "Path relative to PRODUCT_OUT required")
+ }
+}
+
+func (p *makefileGoal) GenerateAndroidBuildActions(ctx ModuleContext) {
+ filename := filepath.Base(proptools.String(p.inputPath()))
+ p.outputFilePath = PathForModuleOut(ctx, filename).OutputPath
+
+ ctx.InstallFile(PathForModuleInstall(ctx, "etc"), ctx.ModuleName(), p.outputFilePath)
+}
+
+func (p *makefileGoal) AndroidMkEntries() []AndroidMkEntries {
+ return []AndroidMkEntries{AndroidMkEntries{
+ Class: "ETC",
+ OutputFile: OptionalPathForPath(p.outputFilePath),
+ ExtraFooters: []AndroidMkExtraFootersFunc{
+ func(w io.Writer, name, prefix, moduleDir string, entries *AndroidMkEntries) {
+ // Can't use Cp because inputPath() is not a valid Path.
+ fmt.Fprintf(w, "$(eval $(call copy-one-file,%s,%s))\n", proptools.String(p.inputPath()), p.outputFilePath)
+ },
+ },
+ }}
+}
+
+// Import a Makefile goal to Soong by copying the file built by
+// the goal to a path visible to Soong. This rule only works on boot images.
+func MakefileGoalFactory() Module {
+ module := &makefileGoal{}
+ module.AddProperties(&module.properties)
+ // This module is device-only
+ InitAndroidArchModule(module, DeviceSupported, MultilibFirst)
+ return module
+}
diff --git a/android/makevars.go b/android/makevars.go
index ff7c8e4a7..86f4b424b 100644
--- a/android/makevars.go
+++ b/android/makevars.go
@@ -17,6 +17,7 @@ package android
import (
"bytes"
"fmt"
+ "sort"
"strconv"
"strings"
@@ -34,43 +35,16 @@ func androidMakeVarsProvider(ctx MakeVarsContext) {
}
///////////////////////////////////////////////////////////////////////////////
-// Interface for other packages to use to declare make variables
-type MakeVarsContext interface {
+
+// BaseMakeVarsContext contains the common functions for other packages to use
+// to declare make variables
+type BaseMakeVarsContext interface {
Config() Config
DeviceConfig() DeviceConfig
AddNinjaFileDeps(deps ...string)
- ModuleName(module blueprint.Module) string
- ModuleDir(module blueprint.Module) string
- ModuleSubDir(module blueprint.Module) string
- ModuleType(module blueprint.Module) string
- BlueprintFile(module blueprint.Module) string
-
- ModuleErrorf(module blueprint.Module, format string, args ...interface{})
- Errorf(format string, args ...interface{})
Failed() bool
- VisitAllModules(visit func(Module))
- VisitAllModulesIf(pred func(Module) bool, visit func(Module))
-
- // Verify the make variable matches the Soong version, fail the build
- // if it does not. If the make variable is empty, just set it.
- Strict(name, ninjaStr string)
- // Check to see if the make variable matches the Soong version, warn if
- // it does not. If the make variable is empty, just set it.
- Check(name, ninjaStr string)
-
- // These are equivalent to the above, but sort the make and soong
- // variables before comparing them. They also show the unique entries
- // in each list when displaying the difference, instead of the entire
- // string.
- StrictSorted(name, ninjaStr string)
- CheckSorted(name, ninjaStr string)
-
- // Evaluates a ninja string and returns the result. Used if more
- // complicated modification needs to happen before giving it to Make.
- Eval(ninjaStr string) (string, error)
-
// These are equivalent to Strict and Check, but do not attempt to
// evaluate the values before writing them to the Makefile. They can
// be used when all ninja variables have already been evaluated through
@@ -108,6 +82,48 @@ type MakeVarsContext interface {
DistForGoalsWithFilename(goals []string, path Path, filename string)
}
+// MakeVarsContext contains the set of functions available for MakeVarsProvider
+// and SingletonMakeVarsProvider implementations.
+type MakeVarsContext interface {
+ BaseMakeVarsContext
+
+ ModuleName(module blueprint.Module) string
+ ModuleDir(module blueprint.Module) string
+ ModuleSubDir(module blueprint.Module) string
+ ModuleType(module blueprint.Module) string
+ BlueprintFile(module blueprint.Module) string
+
+ ModuleErrorf(module blueprint.Module, format string, args ...interface{})
+ Errorf(format string, args ...interface{})
+
+ VisitAllModules(visit func(Module))
+ VisitAllModulesIf(pred func(Module) bool, visit func(Module))
+
+ // Verify the make variable matches the Soong version, fail the build
+ // if it does not. If the make variable is empty, just set it.
+ Strict(name, ninjaStr string)
+ // Check to see if the make variable matches the Soong version, warn if
+ // it does not. If the make variable is empty, just set it.
+ Check(name, ninjaStr string)
+
+ // These are equivalent to the above, but sort the make and soong
+ // variables before comparing them. They also show the unique entries
+ // in each list when displaying the difference, instead of the entire
+ // string.
+ StrictSorted(name, ninjaStr string)
+ CheckSorted(name, ninjaStr string)
+
+ // Evaluates a ninja string and returns the result. Used if more
+ // complicated modification needs to happen before giving it to Make.
+ Eval(ninjaStr string) (string, error)
+}
+
+// MakeVarsModuleContext contains the set of functions available for modules
+// implementing the ModuleMakeVarsProvider interface.
+type MakeVarsModuleContext interface {
+ BaseMakeVarsContext
+}
+
var _ PathContext = MakeVarsContext(nil)
type MakeVarsProvider func(ctx MakeVarsContext)
@@ -135,6 +151,14 @@ func SingletonmakeVarsProviderAdapter(singleton SingletonMakeVarsProvider) MakeV
return func(ctx MakeVarsContext) { singleton.MakeVars(ctx) }
}
+// ModuleMakeVarsProvider is a Module with an extra method to provide extra values to be exported to Make.
+type ModuleMakeVarsProvider interface {
+ Module
+
+ // MakeVars uses a MakeVarsModuleContext to provide extra values to be exported to Make.
+ MakeVars(ctx MakeVarsModuleContext)
+}
+
///////////////////////////////////////////////////////////////////////////////
func makeVarsSingletonFunc() Singleton {
@@ -209,10 +233,45 @@ func (s *makeVarsSingleton) GenerateBuildActions(ctx SingletonContext) {
dists = append(dists, mctx.dists...)
}
+ ctx.VisitAllModules(func(m Module) {
+ if provider, ok := m.(ModuleMakeVarsProvider); ok {
+ mctx := &makeVarsContext{
+ SingletonContext: ctx,
+ }
+
+ provider.MakeVars(mctx)
+
+ vars = append(vars, mctx.vars...)
+ phonies = append(phonies, mctx.phonies...)
+ dists = append(dists, mctx.dists...)
+ }
+ })
+
if ctx.Failed() {
return
}
+ sort.Slice(vars, func(i, j int) bool {
+ return vars[i].name < vars[j].name
+ })
+ sort.Slice(phonies, func(i, j int) bool {
+ return phonies[i].name < phonies[j].name
+ })
+ lessArr := func(a, b []string) bool {
+ if len(a) == len(b) {
+ for i := range a {
+ if a[i] < b[i] {
+ return true
+ }
+ }
+ return false
+ }
+ return len(a) < len(b)
+ }
+ sort.Slice(dists, func(i, j int) bool {
+ return lessArr(dists[i].goals, dists[j].goals) || lessArr(dists[i].paths, dists[j].paths)
+ })
+
outBytes := s.writeVars(vars)
if err := pathtools.WriteFileIfChanged(outFile, outBytes, 0666); err != nil {
diff --git a/android/module.go b/android/module.go
index 634538f49..32d49fb72 100644
--- a/android/module.go
+++ b/android/module.go
@@ -97,6 +97,8 @@ type EarlyModuleContext interface {
GlobFiles(globPattern string, excludes []string) Paths
IsSymlink(path Path) bool
Readlink(path Path) string
+
+ Namespace() *Namespace
}
// BaseModuleContext is the same as blueprint.BaseModuleContext except that Config() returns
@@ -219,7 +221,6 @@ type ModuleContext interface {
VisitAllModuleVariants(visit func(Module))
GetMissingDependencies() []string
- Namespace() blueprint.Namespace
}
type Module interface {
@@ -257,6 +258,7 @@ type Module interface {
InstallForceOS() *OsType
SkipInstall()
IsSkipInstall() bool
+ MakeUninstallable()
ExportedToMake() bool
InitRc() Paths
VintfFragments() Paths
@@ -549,6 +551,9 @@ type commonProperties struct {
SkipInstall bool `blueprint:"mutated"`
+ // Disabled by mutators. If set to true, it overrides Enabled property.
+ ForcedDisabled bool `blueprint:"mutated"`
+
NamespaceExportedToMake bool `blueprint:"mutated"`
MissingDeps []string `blueprint:"mutated"`
@@ -566,6 +571,12 @@ type commonProperties struct {
type TaggedDistFiles map[string]Paths
func MakeDefaultDistFiles(paths ...Path) TaggedDistFiles {
+ for _, path := range paths {
+ if path == nil {
+ panic("The path to a dist file cannot be nil.")
+ }
+ }
+
// The default OutputFile tag is the empty "" string.
return TaggedDistFiles{"": paths}
}
@@ -1023,6 +1034,9 @@ func (m *ModuleBase) PartitionTag(config DeviceConfig) string {
}
func (m *ModuleBase) Enabled() bool {
+ if m.commonProperties.ForcedDisabled {
+ return false
+ }
if m.commonProperties.Enabled == nil {
return !m.Os().DefaultDisabled
}
@@ -1030,7 +1044,7 @@ func (m *ModuleBase) Enabled() bool {
}
func (m *ModuleBase) Disable() {
- m.commonProperties.Enabled = proptools.BoolPtr(false)
+ m.commonProperties.ForcedDisabled = true
}
func (m *ModuleBase) SkipInstall() {
@@ -1041,6 +1055,15 @@ func (m *ModuleBase) IsSkipInstall() bool {
return m.commonProperties.SkipInstall == true
}
+// Similar to SkipInstall, 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()
+}
+
func (m *ModuleBase) ExportedToMake() bool {
return m.commonProperties.NamespaceExportedToMake
}
@@ -1166,7 +1189,7 @@ func (m *ModuleBase) generateModuleTarget(ctx ModuleContext) {
var deps Paths
- namespacePrefix := ctx.Namespace().(*Namespace).id
+ namespacePrefix := ctx.Namespace().id
if namespacePrefix != "" {
namespacePrefix = namespacePrefix + "-"
}
@@ -1310,7 +1333,7 @@ func (m *ModuleBase) GenerateBuildActions(blueprintCtx blueprint.ModuleContext)
suffix = append(suffix, ctx.Arch().ArchType.String())
}
if apex, ok := m.module.(ApexModule); ok && !apex.IsForPlatform() {
- suffix = append(suffix, apex.ApexName())
+ suffix = append(suffix, apex.ApexVariationName())
}
ctx.Variable(pctx, "moduleDesc", desc)
@@ -1477,6 +1500,10 @@ func (e *earlyModuleContext) SystemExtSpecific() bool {
return e.kind == systemExtSpecificModule
}
+func (e *earlyModuleContext) Namespace() *Namespace {
+ return e.EarlyModuleContext.Namespace().(*Namespace)
+}
+
type baseModuleContext struct {
bp blueprint.BaseModuleContext
earlyModuleContext
@@ -1834,7 +1861,7 @@ func (b *baseModuleContext) GetTagPath() []blueprint.DependencyTag {
// A regexp for removing boilerplate from BaseDependencyTag from the string representation of
// a dependency tag.
-var tagCleaner = regexp.MustCompile(`\QBaseDependencyTag:blueprint.BaseDependencyTag{}\E(, )?`)
+var tagCleaner = regexp.MustCompile(`\QBaseDependencyTag:{}\E(, )?`)
// PrettyPrintTag returns string representation of the tag, but prefers
// custom String() method if available.
@@ -1845,7 +1872,7 @@ func PrettyPrintTag(tag blueprint.DependencyTag) string {
}
// Otherwise, get a default string representation of the tag's struct.
- tagString := fmt.Sprintf("%#v", tag)
+ tagString := fmt.Sprintf("%T: %+v", tag, tag)
// Remove the boilerplate from BaseDependencyTag as it adds no value.
tagString = tagCleaner.ReplaceAllString(tagString, "")
@@ -2220,7 +2247,7 @@ func OutputFileForModule(ctx PathContext, module blueprint.Module, tag string) P
return nil
}
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))
return nil
}
diff --git a/android/mutator.go b/android/mutator.go
index b70c4ff64..40e61deb2 100644
--- a/android/mutator.go
+++ b/android/mutator.go
@@ -216,6 +216,7 @@ type BottomUpMutatorContext interface {
ReplaceDependencies(string)
ReplaceDependenciesIf(string, blueprint.ReplaceDependencyPredicate)
AliasVariation(variationName string)
+ CreateAliasVariation(fromVariationName, toVariationName string)
}
type bottomUpMutatorContext struct {
@@ -436,3 +437,7 @@ func (b *bottomUpMutatorContext) ReplaceDependenciesIf(name string, predicate bl
func (b *bottomUpMutatorContext) AliasVariation(variationName string) {
b.bp.AliasVariation(variationName)
}
+
+func (b *bottomUpMutatorContext) CreateAliasVariation(fromVariationName, toVariationName string) {
+ b.bp.CreateAliasVariation(fromVariationName, toVariationName)
+}
diff --git a/android/neverallow.go b/android/neverallow.go
index 425303153..8b8e1accf 100644
--- a/android/neverallow.go
+++ b/android/neverallow.go
@@ -56,6 +56,7 @@ func init() {
AddNeverAllowRules(createJavaDeviceForHostRules()...)
AddNeverAllowRules(createCcSdkVariantRules()...)
AddNeverAllowRules(createUncompressDexRules()...)
+ AddNeverAllowRules(createMakefileGoalRules()...)
}
// Add a NeverAllow rule to the set of rules to apply.
@@ -193,7 +194,7 @@ func createCcSdkVariantRules() []Rule {
// This sometimes works because the APEX modules that contain derive_sdk and
// derive_sdk_prefer32 suppress the platform installation rules, but fails when
// the APEX modules contain the SDK variant and the platform variant still exists.
- "frameworks/base/apex/sdkextensions/derive_sdk",
+ "packages/modules/SdkExtensions/derive_sdk",
// These are for apps and shouldn't be used by non-SDK variant modules.
"prebuilts/ndk",
"tools/test/graphicsbenchmark/apps/sample_app",
@@ -232,6 +233,15 @@ func createUncompressDexRules() []Rule {
}
}
+func createMakefileGoalRules() []Rule {
+ return []Rule{
+ NeverAllow().
+ ModuleType("makefile_goal").
+ WithoutMatcher("product_out_path", Regexp("^boot[0-9a-zA-Z.-]*[.]img$")).
+ Because("Only boot images may be imported as a makefile goal."),
+ }
+}
+
func neverallowMutator(ctx BottomUpMutatorContext) {
m, ok := ctx.Module().(Module)
if !ok {
diff --git a/android/neverallow_test.go b/android/neverallow_test.go
index 45d36a69b..56a07dc9d 100644
--- a/android/neverallow_test.go
+++ b/android/neverallow_test.go
@@ -326,6 +326,20 @@ var neverallowTests = []struct {
"module \"outside_art_libraries\": violates neverallow",
},
},
+ {
+ name: "disallowed makefile_goal",
+ fs: map[string][]byte{
+ "Android.bp": []byte(`
+ makefile_goal {
+ name: "foo",
+ product_out_path: "boot/trap.img"
+ }
+ `),
+ },
+ expectedErrors: []string{
+ "Only boot images may be imported as a makefile goal.",
+ },
+ },
}
func TestNeverallow(t *testing.T) {
@@ -350,6 +364,7 @@ func testNeverallow(config Config) (*TestContext, []error) {
ctx.RegisterModuleType("java_library", newMockJavaLibraryModule)
ctx.RegisterModuleType("java_library_host", newMockJavaLibraryModule)
ctx.RegisterModuleType("java_device_for_host", newMockJavaLibraryModule)
+ ctx.RegisterModuleType("makefile_goal", newMockMakefileGoalModule)
ctx.PostDepsMutators(RegisterNeverallowMutator)
ctx.Register(config)
@@ -438,3 +453,22 @@ func newMockJavaLibraryModule() Module {
func (p *mockJavaLibraryModule) GenerateAndroidBuildActions(ModuleContext) {
}
+
+type mockMakefileGoalProperties struct {
+ Product_out_path *string
+}
+
+type mockMakefileGoalModule struct {
+ ModuleBase
+ properties mockMakefileGoalProperties
+}
+
+func newMockMakefileGoalModule() Module {
+ m := &mockMakefileGoalModule{}
+ m.AddProperties(&m.properties)
+ InitAndroidModule(m)
+ return m
+}
+
+func (p *mockMakefileGoalModule) GenerateAndroidBuildActions(ModuleContext) {
+}
diff --git a/android/override_module.go b/android/override_module.go
index 3994084a8..f8342d52d 100644
--- a/android/override_module.go
+++ b/android/override_module.go
@@ -313,3 +313,15 @@ func replaceDepsOnOverridingModuleMutator(ctx BottomUpMutatorContext) {
}
}
}
+
+// ModuleNameWithPossibleOverride returns the name of the OverrideModule that overrides the current
+// variant of this OverridableModule, or ctx.ModuleName() if this module is not an OverridableModule
+// or if this variant is not overridden.
+func ModuleNameWithPossibleOverride(ctx ModuleContext) string {
+ if overridable, ok := ctx.Module().(OverridableModule); ok {
+ if o := overridable.GetOverriddenBy(); o != "" {
+ return o
+ }
+ }
+ return ctx.ModuleName()
+}
diff --git a/android/paths.go b/android/paths.go
index 20ff55e85..6b603ba41 100644
--- a/android/paths.go
+++ b/android/paths.go
@@ -86,13 +86,13 @@ var _ moduleErrorf = blueprint.ModuleContext(nil)
// attempts ctx.ModuleErrorf for a better error message first, then falls
// back to ctx.Errorf.
func reportPathError(ctx PathContext, err error) {
- reportPathErrorf(ctx, "%s", err.Error())
+ ReportPathErrorf(ctx, "%s", err.Error())
}
-// reportPathErrorf will register an error with the attached context. It
+// ReportPathErrorf will register an error with the attached context. It
// attempts ctx.ModuleErrorf for a better error message first, then falls
// back to ctx.Errorf.
-func reportPathErrorf(ctx PathContext, format string, args ...interface{}) {
+func ReportPathErrorf(ctx PathContext, format string, args ...interface{}) {
if mctx, ok := ctx.(moduleErrorf); ok {
mctx.ModuleErrorf(format, args...)
} else if ectx, ok := ctx.(errorfContext); ok {
@@ -155,7 +155,7 @@ func GenPathWithExt(ctx ModuleContext, subdir string, p Path, ext string) Module
if path, ok := p.(genPathProvider); ok {
return path.genPathWithExt(ctx, subdir, ext)
}
- reportPathErrorf(ctx, "Tried to create generated file from unsupported path: %s(%s)", reflect.TypeOf(p).Name(), p)
+ ReportPathErrorf(ctx, "Tried to create generated file from unsupported path: %s(%s)", reflect.TypeOf(p).Name(), p)
return PathForModuleGen(ctx)
}
@@ -165,7 +165,7 @@ func ObjPathWithExt(ctx ModuleContext, subdir string, p Path, ext string) Module
if path, ok := p.(objPathProvider); ok {
return path.objPathWithExt(ctx, subdir, ext)
}
- reportPathErrorf(ctx, "Tried to create object file from unsupported path: %s (%s)", reflect.TypeOf(p).Name(), p)
+ ReportPathErrorf(ctx, "Tried to create object file from unsupported path: %s (%s)", reflect.TypeOf(p).Name(), p)
return PathForModuleObj(ctx)
}
@@ -176,7 +176,7 @@ func ResPathWithName(ctx ModuleContext, p Path, name string) ModuleResPath {
if path, ok := p.(resPathProvider); ok {
return path.resPathWithName(ctx, name)
}
- reportPathErrorf(ctx, "Tried to create res file from unsupported path: %s (%s)", reflect.TypeOf(p).Name(), p)
+ ReportPathErrorf(ctx, "Tried to create res file from unsupported path: %s (%s)", reflect.TypeOf(p).Name(), p)
return PathForModuleRes(ctx)
}
@@ -416,9 +416,9 @@ func expandOneSrcPath(ctx ModuleContext, s string, expandedExcludes []string) (P
} else {
p := pathForModuleSrc(ctx, s)
if exists, _, err := ctx.Config().fs.Exists(p.String()); err != nil {
- reportPathErrorf(ctx, "%s: %s", p, err.Error())
+ ReportPathErrorf(ctx, "%s: %s", p, err.Error())
} else if !exists && !ctx.Config().testAllowNonExistentPaths {
- reportPathErrorf(ctx, "module source path %q does not exist", p)
+ ReportPathErrorf(ctx, "module source path %q does not exist", p)
}
if InList(p.String(), expandedExcludes) {
@@ -445,7 +445,7 @@ func pathsForModuleSrcFromFullPath(ctx EarlyModuleContext, paths []string, incDi
}
path := filepath.Clean(p)
if !strings.HasPrefix(path, prefix) {
- reportPathErrorf(ctx, "Path %q is not in module source directory %q", p, prefix)
+ ReportPathErrorf(ctx, "Path %q is not in module source directory %q", p, prefix)
continue
}
@@ -801,7 +801,7 @@ func PathForSource(ctx PathContext, pathComponents ...string) SourcePath {
}
if pathtools.IsGlob(path.String()) {
- reportPathErrorf(ctx, "path may not contain a glob: %s", path.String())
+ ReportPathErrorf(ctx, "path may not contain a glob: %s", path.String())
}
if modCtx, ok := ctx.(ModuleContext); ok && ctx.Config().AllowMissingDependencies() {
@@ -813,9 +813,9 @@ func PathForSource(ctx PathContext, pathComponents ...string) SourcePath {
modCtx.AddMissingDependencies([]string{path.String()})
}
} else if exists, _, err := ctx.Config().fs.Exists(path.String()); err != nil {
- reportPathErrorf(ctx, "%s: %s", path, err.Error())
+ ReportPathErrorf(ctx, "%s: %s", path, err.Error())
} else if !exists && !ctx.Config().testAllowNonExistentPaths {
- reportPathErrorf(ctx, "source path %q does not exist", path)
+ ReportPathErrorf(ctx, "source path %q does not exist", path)
}
return path
}
@@ -831,7 +831,7 @@ func ExistentPathForSource(ctx PathContext, pathComponents ...string) OptionalPa
}
if pathtools.IsGlob(path.String()) {
- reportPathErrorf(ctx, "path may not contain a glob: %s", path.String())
+ ReportPathErrorf(ctx, "path may not contain a glob: %s", path.String())
return OptionalPath{}
}
@@ -876,17 +876,17 @@ func (p SourcePath) OverlayPath(ctx ModuleContext, path Path) OptionalPath {
if srcPath, ok := path.(SourcePath); ok {
relDir = srcPath.path
} else {
- reportPathErrorf(ctx, "Cannot find relative path for %s(%s)", reflect.TypeOf(path).Name(), path)
+ ReportPathErrorf(ctx, "Cannot find relative path for %s(%s)", reflect.TypeOf(path).Name(), path)
return OptionalPath{}
}
dir := filepath.Join(p.config.srcDir, p.path, relDir)
// Use Glob so that we are run again if the directory is added.
if pathtools.IsGlob(dir) {
- reportPathErrorf(ctx, "Path may not contain a glob: %s", dir)
+ ReportPathErrorf(ctx, "Path may not contain a glob: %s", dir)
}
paths, err := ctx.GlobWithDeps(dir, nil)
if err != nil {
- reportPathErrorf(ctx, "glob: %s", err.Error())
+ ReportPathErrorf(ctx, "glob: %s", err.Error())
return OptionalPath{}
}
if len(paths) == 0 {
@@ -977,7 +977,7 @@ func (p OutputPath) Join(ctx PathContext, paths ...string) OutputPath {
// ReplaceExtension creates a new OutputPath with the extension replaced with ext.
func (p OutputPath) ReplaceExtension(ctx PathContext, ext string) OutputPath {
if strings.Contains(ext, "/") {
- reportPathErrorf(ctx, "extension %q cannot contain /", ext)
+ ReportPathErrorf(ctx, "extension %q cannot contain /", ext)
}
ret := PathForOutput(ctx, pathtools.ReplaceExtension(p.path, ext))
ret.rel = pathtools.ReplaceExtension(p.rel, ext)
@@ -1030,10 +1030,10 @@ func PathForModuleSrc(ctx ModuleContext, pathComponents ...string) Path {
}
return nil
} else if len(paths) == 0 {
- reportPathErrorf(ctx, "%q produced no files, expected exactly one", p)
+ ReportPathErrorf(ctx, "%q produced no files, expected exactly one", p)
return nil
} else if len(paths) > 1 {
- reportPathErrorf(ctx, "%q produced %d files, expected exactly one", p, len(paths))
+ ReportPathErrorf(ctx, "%q produced %d files, expected exactly one", p, len(paths))
}
return paths[0]
}
@@ -1447,7 +1447,7 @@ func validatePath(pathComponents ...string) (string, error) {
func PathForPhony(ctx PathContext, phony string) WritablePath {
if strings.ContainsAny(phony, "$/") {
- reportPathErrorf(ctx, "Phony target contains invalid character ($ or /): %s", phony)
+ ReportPathErrorf(ctx, "Phony target contains invalid character ($ or /): %s", phony)
}
return PhonyPath{basePath{phony, ctx.Config(), ""}}
}
@@ -1513,7 +1513,7 @@ func PathContextForTesting(config Config) PathContext {
func Rel(ctx PathContext, basePath string, targetPath string) string {
rel, isRel := MaybeRel(ctx, basePath, targetPath)
if !isRel {
- reportPathErrorf(ctx, "path %q is not under path %q", targetPath, basePath)
+ ReportPathErrorf(ctx, "path %q is not under path %q", targetPath, basePath)
return ""
}
return rel
@@ -1555,3 +1555,15 @@ func absolutePath(path string) string {
}
return filepath.Join(absSrcDir, path)
}
+
+// A DataPath represents the path of a file to be used as data, for example
+// a test library to be installed alongside a test.
+// The data file should be installed (copied from `<SrcPath>`) to
+// `<install_root>/<RelativeInstallPath>/<filename>`, or
+// `<install_root>/<filename>` if RelativeInstallPath is empty.
+type DataPath struct {
+ // The path of the data file that should be copied into the data directory
+ SrcPath Path
+ // The install path of the data file, relative to the install root.
+ RelativeInstallPath string
+}
diff --git a/android/prebuilt_build_tool.go b/android/prebuilt_build_tool.go
new file mode 100644
index 000000000..1dcf1996b
--- /dev/null
+++ b/android/prebuilt_build_tool.go
@@ -0,0 +1,94 @@
+// Copyright 2020 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package android
+
+func init() {
+ RegisterModuleType("prebuilt_build_tool", prebuiltBuildToolFactory)
+}
+
+type prebuiltBuildToolProperties struct {
+ // Source file to be executed for this build tool
+ Src *string `android:"path,arch_variant"`
+
+ // Extra files that should trigger rules using this tool to rebuild
+ Deps []string `android:"path,arch_variant"`
+
+ // Create a make variable with the specified name that contains the path to
+ // this prebuilt built tool, relative to the root of the source tree.
+ Export_to_make_var *string
+}
+
+type prebuiltBuildTool struct {
+ ModuleBase
+ prebuilt Prebuilt
+
+ properties prebuiltBuildToolProperties
+
+ toolPath OptionalPath
+}
+
+func (t *prebuiltBuildTool) Name() string {
+ return t.prebuilt.Name(t.ModuleBase.Name())
+}
+
+func (t *prebuiltBuildTool) Prebuilt() *Prebuilt {
+ return &t.prebuilt
+}
+
+func (t *prebuiltBuildTool) DepsMutator(ctx BottomUpMutatorContext) {
+ if t.properties.Src == nil {
+ ctx.PropertyErrorf("src", "missing prebuilt source file")
+ }
+}
+
+func (t *prebuiltBuildTool) GenerateAndroidBuildActions(ctx ModuleContext) {
+ sourcePath := t.prebuilt.SingleSourcePath(ctx)
+ installedPath := PathForModuleOut(ctx, t.ModuleBase.Name())
+ deps := PathsForModuleSrc(ctx, t.properties.Deps)
+
+ ctx.Build(pctx, BuildParams{
+ Rule: Symlink,
+ Output: installedPath,
+ Input: sourcePath,
+ Implicits: deps,
+ Args: map[string]string{
+ "fromPath": "$$PWD/" + sourcePath.String(),
+ },
+ })
+
+ t.toolPath = OptionalPathForPath(installedPath)
+}
+
+func (t *prebuiltBuildTool) MakeVars(ctx MakeVarsModuleContext) {
+ if makeVar := String(t.properties.Export_to_make_var); makeVar != "" {
+ ctx.StrictRaw(makeVar, t.toolPath.String())
+ }
+}
+
+func (t *prebuiltBuildTool) HostToolPath() OptionalPath {
+ return t.toolPath
+}
+
+var _ HostToolProvider = &prebuiltBuildTool{}
+
+// prebuilt_build_tool is to declare prebuilts to be used during the build, particularly for use
+// in genrules with the "tools" property.
+func prebuiltBuildToolFactory() Module {
+ module := &prebuiltBuildTool{}
+ module.AddProperties(&module.properties)
+ InitSingleSourcePrebuiltModule(module, &module.properties, "Src")
+ InitAndroidArchModule(module, HostSupportedNoCross, MultilibFirst)
+ return module
+}
diff --git a/android/sdk.go b/android/sdk.go
index 8115b690b..9ea7ff49c 100644
--- a/android/sdk.go
+++ b/android/sdk.go
@@ -34,10 +34,8 @@ type RequiredSdks interface {
RequiredSdks() SdkRefs
}
-// SdkAware is the interface that must be supported by any module to become a member of SDK or to be
-// built with SDK
-type SdkAware interface {
- Module
+// Provided to improve code navigation with the IDE.
+type sdkAwareWithoutModule interface {
RequiredSdks
sdkBase() *SdkBase
@@ -48,6 +46,13 @@ type SdkAware interface {
BuildWithSdks(sdks SdkRefs)
}
+// SdkAware is the interface that must be supported by any module to become a member of SDK or to be
+// built with SDK
+type SdkAware interface {
+ Module
+ sdkAwareWithoutModule
+}
+
// SdkRef refers to a version of an SDK
type SdkRef struct {
Name string
@@ -322,6 +327,12 @@ type SdkMemberType interface {
// SdkAware and be added with an SdkMemberTypeDependencyTag tag.
HasTransitiveSdkMembers() bool
+ // Return true if prebuilt host artifacts may be specific to the host OS. Only
+ // applicable to modules where HostSupported() is true. If this is true,
+ // snapshots will list each host OS variant explicitly and disable all other
+ // host OS'es.
+ IsHostOsDependent() bool
+
// Add dependencies from the SDK module to all the module variants the member
// type contributes to the SDK. `names` is the list of module names given in
// the member type property (as returned by SdkPropertyName()) in the SDK
@@ -384,6 +395,7 @@ type SdkMemberTypeBase struct {
PropertyName string
SupportsSdk bool
TransitiveSdkMembers bool
+ HostOsDependent bool
}
func (b *SdkMemberTypeBase) SdkPropertyName() string {
@@ -398,6 +410,10 @@ func (b *SdkMemberTypeBase) HasTransitiveSdkMembers() bool {
return b.TransitiveSdkMembers
}
+func (b *SdkMemberTypeBase) IsHostOsDependent() bool {
+ return b.HostOsDependent
+}
+
// Encapsulates the information about registered SdkMemberTypes.
type SdkMemberTypesRegistry struct {
// The list of types sorted by property name.
@@ -466,8 +482,7 @@ func RegisterSdkMemberType(memberType SdkMemberType) {
// Base structure for all implementations of SdkMemberProperties.
//
-// Contains common properties that apply across many different member types. These
-// are not affected by the optimization to extract common values.
+// Contains common properties that apply across many different member types.
type SdkMemberPropertiesBase struct {
// The number of unique os types supported by the member variants.
//
@@ -489,9 +504,7 @@ type SdkMemberPropertiesBase struct {
Os OsType `sdk:"keep"`
// The setting to use for the compile_multilib property.
- //
- // This property is set after optimization so there is no point in trying to optimize it.
- Compile_multilib string `sdk:"keep"`
+ Compile_multilib string `android:"arch_variant"`
}
// The os prefix to use for any file paths in the sdk.
diff --git a/android/test_suites.go b/android/test_suites.go
new file mode 100644
index 000000000..79d0fbc60
--- /dev/null
+++ b/android/test_suites.go
@@ -0,0 +1,75 @@
+// Copyright 2020 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package android
+
+func init() {
+ RegisterSingletonType("testsuites", testSuiteFilesFactory)
+}
+
+func testSuiteFilesFactory() Singleton {
+ return &testSuiteFiles{}
+}
+
+type testSuiteFiles struct {
+ robolectric WritablePath
+}
+
+type TestSuiteModule interface {
+ Module
+ TestSuites() []string
+}
+
+func (t *testSuiteFiles) GenerateBuildActions(ctx SingletonContext) {
+ files := make(map[string]map[string]InstallPaths)
+
+ ctx.VisitAllModules(func(m Module) {
+ if tsm, ok := m.(TestSuiteModule); ok {
+ for _, testSuite := range tsm.TestSuites() {
+ if files[testSuite] == nil {
+ files[testSuite] = make(map[string]InstallPaths)
+ }
+ name := ctx.ModuleName(m)
+ files[testSuite][name] = append(files[testSuite][name], tsm.filesToInstall()...)
+ }
+ }
+ })
+
+ t.robolectric = robolectricTestSuite(ctx, files["robolectric-tests"])
+
+ ctx.Phony("robolectric-tests", t.robolectric)
+}
+
+func (t *testSuiteFiles) MakeVars(ctx MakeVarsContext) {
+ ctx.DistForGoal("robolectric-tests", t.robolectric)
+}
+
+func robolectricTestSuite(ctx SingletonContext, files map[string]InstallPaths) WritablePath {
+ var installedPaths InstallPaths
+ for _, module := range SortedStringKeys(files) {
+ installedPaths = append(installedPaths, files[module]...)
+ }
+ testCasesDir := pathForInstall(ctx, BuildOs, "testcases", false).ToMakePath()
+
+ outputFile := PathForOutput(ctx, "packaging", "robolectric-tests.zip")
+ rule := NewRuleBuilder()
+ rule.Command().BuiltTool(ctx, "soong_zip").
+ FlagWithOutput("-o ", outputFile).
+ FlagWithArg("-P ", "host/testcases").
+ FlagWithArg("-C ", testCasesDir.String()).
+ FlagWithRspFileInputList("-r ", installedPaths.Paths())
+ rule.Build(pctx, ctx, "robolectric_tests_zip", "robolectric-tests.zip")
+
+ return outputFile
+}
diff --git a/android/testing.go b/android/testing.go
index 696efb6f8..8ea4168d1 100644
--- a/android/testing.go
+++ b/android/testing.go
@@ -119,14 +119,24 @@ func (ctx *TestContext) ModuleForTests(name, variant string) TestingModule {
if module == nil {
// find all the modules that do exist
- allModuleNames := []string{}
+ var allModuleNames []string
+ var allVariants []string
ctx.VisitAllModules(func(m blueprint.Module) {
- allModuleNames = append(allModuleNames, m.(Module).Name()+"("+ctx.ModuleSubDir(m)+")")
+ allModuleNames = append(allModuleNames, ctx.ModuleName(m))
+ if ctx.ModuleName(m) == name {
+ allVariants = append(allVariants, ctx.ModuleSubDir(m))
+ }
})
sort.Strings(allModuleNames)
-
- panic(fmt.Errorf("failed to find module %q variant %q. All modules:\n %s",
- name, variant, strings.Join(allModuleNames, "\n ")))
+ sort.Strings(allVariants)
+
+ if len(allVariants) == 0 {
+ panic(fmt.Errorf("failed to find module %q. All modules:\n %s",
+ name, strings.Join(allModuleNames, "\n ")))
+ } else {
+ panic(fmt.Errorf("failed to find module %q variant %q. All variants:\n %s",
+ name, variant, strings.Join(allVariants, "\n ")))
+ }
}
return TestingModule{module}
@@ -177,19 +187,21 @@ func newTestingBuildParams(provider testBuildProvider, bparams BuildParams) Test
}
}
-func maybeBuildParamsFromRule(provider testBuildProvider, rule string) TestingBuildParams {
+func maybeBuildParamsFromRule(provider testBuildProvider, rule string) (TestingBuildParams, []string) {
+ var searchedRules []string
for _, p := range provider.BuildParamsForTests() {
+ searchedRules = append(searchedRules, p.Rule.String())
if strings.Contains(p.Rule.String(), rule) {
- return newTestingBuildParams(provider, p)
+ return newTestingBuildParams(provider, p), searchedRules
}
}
- return TestingBuildParams{}
+ return TestingBuildParams{}, searchedRules
}
func buildParamsFromRule(provider testBuildProvider, rule string) TestingBuildParams {
- p := maybeBuildParamsFromRule(provider, rule)
+ p, searchRules := maybeBuildParamsFromRule(provider, rule)
if p.Rule == nil {
- panic(fmt.Errorf("couldn't find rule %q", rule))
+ panic(fmt.Errorf("couldn't find rule %q.\nall rules: %v", rule, searchRules))
}
return p
}
@@ -265,7 +277,8 @@ func (m TestingModule) Module() Module {
// MaybeRule finds a call to ctx.Build with BuildParams.Rule set to a rule with the given name. Returns an empty
// BuildParams if no rule is found.
func (m TestingModule) MaybeRule(rule string) TestingBuildParams {
- return maybeBuildParamsFromRule(m.module, rule)
+ r, _ := maybeBuildParamsFromRule(m.module, rule)
+ return r
}
// Rule finds a call to ctx.Build with BuildParams.Rule set to a rule with the given name. Panics if no rule is found.
@@ -318,7 +331,8 @@ func (s TestingSingleton) Singleton() Singleton {
// MaybeRule finds a call to ctx.Build with BuildParams.Rule set to a rule with the given name. Returns an empty
// BuildParams if no rule is found.
func (s TestingSingleton) MaybeRule(rule string) TestingBuildParams {
- return maybeBuildParamsFromRule(s.provider, rule)
+ r, _ := maybeBuildParamsFromRule(s.provider, rule)
+ return r
}
// Rule finds a call to ctx.Build with BuildParams.Rule set to a rule with the given name. Panics if no rule is found.
@@ -384,7 +398,7 @@ func FailIfNoMatchingErrors(t *testing.T, pattern string, errs []error) {
if !found {
t.Errorf("missing the expected error %q (checked %d error(s))", pattern, len(errs))
for i, err := range errs {
- t.Errorf("errs[%d] = %s", i, err)
+ t.Errorf("errs[%d] = %q", i, err)
}
}
}
diff --git a/android/util.go b/android/util.go
index 8dbf21459..65c5f1b28 100644
--- a/android/util.go
+++ b/android/util.go
@@ -79,6 +79,20 @@ func JoinWithSuffix(strs []string, suffix string, separator string) string {
return string(ret)
}
+func SortedIntKeys(m interface{}) []int {
+ v := reflect.ValueOf(m)
+ if v.Kind() != reflect.Map {
+ panic(fmt.Sprintf("%#v is not a map", m))
+ }
+ keys := v.MapKeys()
+ s := make([]int, 0, len(keys))
+ for _, key := range keys {
+ s = append(s, int(key.Int()))
+ }
+ sort.Ints(s)
+ return s
+}
+
func SortedStringKeys(m interface{}) []string {
v := reflect.ValueOf(m)
if v.Kind() != reflect.Map {
diff --git a/android/variable.go b/android/variable.go
index 2c8bd0720..53f081e8c 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -166,13 +166,14 @@ type productVariables struct {
Platform_min_supported_target_sdk_version *string `json:",omitempty"`
Platform_base_os *string `json:",omitempty"`
- DeviceName *string `json:",omitempty"`
- DeviceArch *string `json:",omitempty"`
- DeviceArchVariant *string `json:",omitempty"`
- DeviceCpuVariant *string `json:",omitempty"`
- DeviceAbi []string `json:",omitempty"`
- DeviceVndkVersion *string `json:",omitempty"`
- DeviceSystemSdkVersions []string `json:",omitempty"`
+ DeviceName *string `json:",omitempty"`
+ DeviceArch *string `json:",omitempty"`
+ DeviceArchVariant *string `json:",omitempty"`
+ DeviceCpuVariant *string `json:",omitempty"`
+ DeviceAbi []string `json:",omitempty"`
+ DeviceVndkVersion *string `json:",omitempty"`
+ DeviceCurrentApiLevelForVendorModules *string `json:",omitempty"`
+ DeviceSystemSdkVersions []string `json:",omitempty"`
DeviceSecondaryArch *string `json:",omitempty"`
DeviceSecondaryArchVariant *string `json:",omitempty"`
@@ -214,30 +215,29 @@ type productVariables struct {
AppsDefaultVersionName *string `json:",omitempty"`
- Allow_missing_dependencies *bool `json:",omitempty"`
- Unbundled_build *bool `json:",omitempty"`
- Unbundled_build_apps *bool `json:",omitempty"`
- Unbundled_build_sdks_from_source *bool `json:",omitempty"`
- Malloc_not_svelte *bool `json:",omitempty"`
- Malloc_zero_contents *bool `json:",omitempty"`
- Malloc_pattern_fill_contents *bool `json:",omitempty"`
- Safestack *bool `json:",omitempty"`
- HostStaticBinaries *bool `json:",omitempty"`
- Binder32bit *bool `json:",omitempty"`
- UseGoma *bool `json:",omitempty"`
- UseRBE *bool `json:",omitempty"`
- UseRBEJAVAC *bool `json:",omitempty"`
- UseRBER8 *bool `json:",omitempty"`
- UseRBED8 *bool `json:",omitempty"`
- Debuggable *bool `json:",omitempty"`
- Eng *bool `json:",omitempty"`
- Treble_linker_namespaces *bool `json:",omitempty"`
- Enforce_vintf_manifest *bool `json:",omitempty"`
- Pdk *bool `json:",omitempty"`
- Uml *bool `json:",omitempty"`
- Use_lmkd_stats_log *bool `json:",omitempty"`
- Arc *bool `json:",omitempty"`
- MinimizeJavaDebugInfo *bool `json:",omitempty"`
+ Allow_missing_dependencies *bool `json:",omitempty"`
+ Unbundled_build *bool `json:",omitempty"`
+ Unbundled_build_apps *bool `json:",omitempty"`
+ Always_use_prebuilt_sdks *bool `json:",omitempty"`
+ Malloc_not_svelte *bool `json:",omitempty"`
+ Malloc_zero_contents *bool `json:",omitempty"`
+ Malloc_pattern_fill_contents *bool `json:",omitempty"`
+ Safestack *bool `json:",omitempty"`
+ HostStaticBinaries *bool `json:",omitempty"`
+ Binder32bit *bool `json:",omitempty"`
+ UseGoma *bool `json:",omitempty"`
+ UseRBE *bool `json:",omitempty"`
+ UseRBEJAVAC *bool `json:",omitempty"`
+ UseRBER8 *bool `json:",omitempty"`
+ UseRBED8 *bool `json:",omitempty"`
+ Debuggable *bool `json:",omitempty"`
+ Eng *bool `json:",omitempty"`
+ Treble_linker_namespaces *bool `json:",omitempty"`
+ Enforce_vintf_manifest *bool `json:",omitempty"`
+ Uml *bool `json:",omitempty"`
+ Use_lmkd_stats_log *bool `json:",omitempty"`
+ Arc *bool `json:",omitempty"`
+ MinimizeJavaDebugInfo *bool `json:",omitempty"`
Check_elf_files *bool `json:",omitempty"`
@@ -308,8 +308,6 @@ type productVariables struct {
BoardPlatPrivateSepolicyDirs []string `json:",omitempty"`
BoardSepolicyM4Defs []string `json:",omitempty"`
- BoardVndkRuntimeDisable *bool `json:",omitempty"`
-
VendorVars map[string]map[string]string `json:",omitempty"`
Ndk_abis *bool `json:",omitempty"`
@@ -346,6 +344,9 @@ type productVariables struct {
InstallExtraFlattenedApexes *bool `json:",omitempty"`
BoardUsesRecoveryAsBoot *bool `json:",omitempty"`
+
+ BoardKernelBinaries []string `json:",omitempty"`
+ BoardKernelModuleInterfaceVersions []string `json:",omitempty"`
}
func boolPtr(v bool) *bool {
diff --git a/apex/androidmk.go b/apex/androidmk.go
index 00a38aa4e..af2ec3d2a 100644
--- a/apex/androidmk.go
+++ b/apex/androidmk.go
@@ -50,6 +50,11 @@ func (a *apexBundle) androidMkForFiles(w io.Writer, apexBundleName, apexName, mo
return moduleNames
}
+ // b/162366062. Prevent GKI APEXes to emit make rules to avoid conflicts.
+ if strings.HasPrefix(apexName, "com.android.gki.") && apexType != flattenedApex {
+ return moduleNames
+ }
+
// b/140136207. When there are overriding APEXes for a VNDK APEX, the symbols file for the overridden
// APEX and the overriding APEX will have the same installation paths at /apex/com.android.vndk.v<ver>
// as their apexName will be the same. To avoid the path conflicts, skip installing the symbol files
@@ -82,9 +87,9 @@ func (a *apexBundle) androidMkForFiles(w io.Writer, apexBundleName, apexName, mo
var moduleName string
if linkToSystemLib {
- moduleName = fi.moduleName
+ moduleName = fi.androidMkModuleName
} else {
- moduleName = fi.moduleName + "." + apexBundleName + a.suffix
+ moduleName = fi.androidMkModuleName + "." + apexBundleName + a.suffix
}
if !android.InList(moduleName, moduleNames) {
@@ -119,9 +124,9 @@ func (a *apexBundle) androidMkForFiles(w io.Writer, apexBundleName, apexName, mo
if len(fi.symlinks) > 0 {
fmt.Fprintln(w, "LOCAL_MODULE_SYMLINKS :=", strings.Join(fi.symlinks, " "))
}
- newDataPaths := []android.Path{}
+ newDataPaths := []android.DataPath{}
for _, path := range fi.dataPaths {
- dataOutPath := modulePath + ":" + path.Rel()
+ dataOutPath := modulePath + ":" + path.SrcPath.Rel()
if ok := seenDataOutPaths[dataOutPath]; !ok {
newDataPaths = append(newDataPaths, path)
seenDataOutPaths[dataOutPath] = true
@@ -212,7 +217,7 @@ func (a *apexBundle) androidMkForFiles(w io.Writer, apexBundleName, apexName, mo
if !ok {
panic(fmt.Sprintf("Expected %s to be AndroidAppSet", fi.module))
}
- fmt.Fprintln(w, "LOCAL_APK_SET_MASTER_FILE :=", as.MasterFile())
+ fmt.Fprintln(w, "LOCAL_APK_SET_INSTALL_FILE :=", as.InstallFile())
fmt.Fprintln(w, "LOCAL_APKCERTS_FILE :=", as.APKCertsFile().String())
fmt.Fprintln(w, "include $(BUILD_SYSTEM)/soong_android_app_set.mk")
case nativeSharedLib, nativeExecutable, nativeTest:
@@ -253,9 +258,9 @@ func (a *apexBundle) androidMkForFiles(w io.Writer, apexBundleName, apexName, mo
}
// m <module_name> will build <module_name>.<apex_name> as well.
- if fi.moduleName != moduleName && a.primaryApexType {
- fmt.Fprintln(w, ".PHONY: "+fi.moduleName)
- fmt.Fprintln(w, fi.moduleName+": "+moduleName)
+ if fi.androidMkModuleName != moduleName && a.primaryApexType {
+ fmt.Fprintf(w, ".PHONY: %s\n", fi.androidMkModuleName)
+ fmt.Fprintf(w, "%s: %s\n", fi.androidMkModuleName, moduleName)
}
}
return moduleNames
@@ -356,6 +361,10 @@ func (a *apexBundle) androidMkForType() android.AndroidMkData {
if apexType == imageApex {
fmt.Fprintln(w, "ALL_MODULES.$(my_register_name).BUNDLE :=", a.bundleModuleFile.String())
}
+ if len(a.lintReports) > 0 {
+ fmt.Fprintln(w, "ALL_MODULES.$(my_register_name).LINT_REPORTS :=",
+ strings.Join(a.lintReports.Strings(), " "))
+ }
if a.installedFilesFile != nil {
goal := "checkbuild"
diff --git a/apex/apex.go b/apex/apex.go
index da309ca9e..1b995c3f2 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -41,6 +41,9 @@ const (
imageApexType = "image"
zipApexType = "zip"
flattenedApexType = "flattened"
+
+ ext4FsType = "ext4"
+ f2fsFsType = "f2fs"
)
type dependencyTag struct {
@@ -584,7 +587,6 @@ func makeApexAvailableBaseline() map[string][]string {
"android.hardware.tetheroffload.config-V1.0-java",
"android.hardware.tetheroffload.control-V1.0-java",
"android.hidl.base-V1.0-java",
- "ipmemorystore-aidl-interfaces-java",
"libcgrouprc",
"libcgrouprc_format",
"libtetherutilsjni",
@@ -771,7 +773,8 @@ func RegisterPreDepsMutators(ctx android.RegisterMutatorsContext) {
}
func RegisterPostDepsMutators(ctx android.RegisterMutatorsContext) {
- ctx.TopDown("apex_deps", apexDepsMutator)
+ ctx.TopDown("apex_deps", apexDepsMutator).Parallel()
+ ctx.BottomUp("apex_unique", apexUniqueVariationsMutator).Parallel()
ctx.BottomUp("apex", apexMutator).Parallel()
ctx.BottomUp("apex_flattened", apexFlattenedMutator).Parallel()
ctx.BottomUp("apex_uses", apexUsesMutator).Parallel()
@@ -784,36 +787,59 @@ func apexDepsMutator(mctx android.TopDownMutatorContext) {
if !mctx.Module().Enabled() {
return
}
- var apexBundles []android.ApexInfo
- var directDep bool
- if a, ok := mctx.Module().(*apexBundle); ok && !a.vndkApex {
- apexBundles = []android.ApexInfo{{
- ApexName: mctx.ModuleName(),
- MinSdkVersion: a.minSdkVersion(mctx),
- Updatable: a.Updatable(),
- }}
- directDep = true
- } else if am, ok := mctx.Module().(android.ApexModule); ok {
- apexBundles = am.ApexVariations()
- directDep = false
- }
-
- if len(apexBundles) == 0 {
+ a, ok := mctx.Module().(*apexBundle)
+ if !ok || a.vndkApex {
return
}
+ apexInfo := android.ApexInfo{
+ ApexVariationName: mctx.ModuleName(),
+ MinSdkVersion: a.minSdkVersion(mctx),
+ RequiredSdks: a.RequiredSdks(),
+ Updatable: a.Updatable(),
+ InApexes: []string{mctx.ModuleName()},
+ }
- cur := mctx.Module().(android.DepIsInSameApex)
+ useVndk := a.SocSpecific() || a.DeviceSpecific() || (a.ProductSpecific() && mctx.Config().EnforceProductPartitionInterface())
+ excludeVndkLibs := useVndk && proptools.Bool(a.properties.Use_vndk_as_stable)
+ if !useVndk && proptools.Bool(a.properties.Use_vndk_as_stable) {
+ mctx.PropertyErrorf("use_vndk_as_stable", "not supported for system/system_ext APEXes")
+ return
+ }
- mctx.VisitDirectDeps(func(child android.Module) {
- depName := mctx.OtherModuleName(child)
- if am, ok := child.(android.ApexModule); ok && am.CanHaveApexVariants() &&
- (cur.DepIsInSameApex(mctx, child) || inAnySdk(child)) {
- android.UpdateApexDependency(apexBundles, depName, directDep)
- am.BuildForApexes(apexBundles)
+ mctx.WalkDeps(func(child, parent android.Module) bool {
+ am, ok := child.(android.ApexModule)
+ if !ok || !am.CanHaveApexVariants() {
+ return false
}
+ if !parent.(android.DepIsInSameApex).DepIsInSameApex(mctx, child) {
+ return false
+ }
+ if excludeVndkLibs {
+ if c, ok := child.(*cc.Module); ok && c.IsVndk() {
+ return false
+ }
+ }
+
+ depName := mctx.OtherModuleName(child)
+ // If the parent is apexBundle, this child is directly depended.
+ _, directDep := parent.(*apexBundle)
+ android.UpdateApexDependency(apexInfo, depName, directDep)
+ am.BuildForApex(apexInfo)
+ return true
})
}
+func apexUniqueVariationsMutator(mctx android.BottomUpMutatorContext) {
+ if !mctx.Module().Enabled() {
+ return
+ }
+ if am, ok := mctx.Module().(android.ApexModule); ok {
+ // Check if any dependencies use unique apex variations. If so, use unique apex variations
+ // for this module.
+ am.UpdateUniqueApexVariationsForDeps(mctx)
+ }
+}
+
// mark if a module cannot be available to platform. A module cannot be available
// to platform if 1) it is explicitly marked as not available (i.e. "//apex_available:platform"
// is absent) or 2) it depends on another module that isn't (or can't be) available to platform
@@ -1114,6 +1140,15 @@ type apexBundleProperties struct {
// The minimum SDK version that this apex must be compatibile with.
Min_sdk_version *string
+
+ // If set true, VNDK libs are considered as stable libs and are not included in this apex.
+ // Should be only used in non-system apexes (e.g. vendor: true).
+ // Default is false.
+ Use_vndk_as_stable *bool
+
+ // The type of filesystem to use for an image apex. Either 'ext4' or 'f2fs'.
+ // Default 'ext4'.
+ Payload_fs_type *string
}
type apexTargetBundleProperties struct {
@@ -1239,15 +1274,17 @@ func (class apexFileClass) NameInMake() string {
// apexFile represents a file in an APEX bundle
type apexFile struct {
- builtFile android.Path
- stem string
- moduleName string
- installDir string
- class apexFileClass
- module android.Module
+ builtFile android.Path
+ stem string
+ // Module name of `module` in AndroidMk. Note the generated AndroidMk module for
+ // apexFile is named something like <AndroidMk module name>.<apex name>[<apex suffix>]
+ androidMkModuleName string
+ installDir string
+ class apexFileClass
+ module android.Module
// list of symlinks that will be created in installDir that point to this apexFile
symlinks []string
- dataPaths android.Paths
+ dataPaths []android.DataPath
transitiveDep bool
moduleDir string
@@ -1256,19 +1293,20 @@ type apexFile struct {
hostRequiredModuleNames []string
jacocoReportClassesFile android.Path // only for javalibs and apps
+ lintDepSets java.LintDepSets // only for javalibs and apps
certificate java.Certificate // only for apps
overriddenPackageName string // only for apps
isJniLib bool
}
-func newApexFile(ctx android.BaseModuleContext, builtFile android.Path, moduleName string, installDir string, class apexFileClass, module android.Module) apexFile {
+func newApexFile(ctx android.BaseModuleContext, builtFile android.Path, androidMkModuleName string, installDir string, class apexFileClass, module android.Module) apexFile {
ret := apexFile{
- builtFile: builtFile,
- moduleName: moduleName,
- installDir: installDir,
- class: class,
- module: module,
+ builtFile: builtFile,
+ androidMkModuleName: androidMkModuleName,
+ installDir: installDir,
+ class: class,
+ module: module,
}
if module != nil {
ret.moduleDir = ctx.OtherModuleDir(module)
@@ -1318,6 +1356,24 @@ func (af *apexFile) AvailableToPlatform() bool {
return false
}
+type fsType int
+
+const (
+ ext4 fsType = iota
+ f2fs
+)
+
+func (f fsType) string() string {
+ switch f {
+ case ext4:
+ return ext4FsType
+ case f2fs:
+ return f2fsFsType
+ default:
+ panic(fmt.Errorf("unknown APEX payload type %d", f))
+ }
+}
+
type apexBundle struct {
android.ModuleBase
android.DefaultableModuleBase
@@ -1380,6 +1436,11 @@ type apexBundle struct {
// Struct holding the merged notice file paths in different formats
mergedNotices android.NoticeOutputs
+
+ // Optional list of lint report zip files for apexes that contain java or app modules
+ lintReports android.Paths
+
+ payloadFsType fsType
}
func addDependenciesForNativeModules(ctx android.BottomUpMutatorContext,
@@ -1722,7 +1783,8 @@ func apexFileForNativeLibrary(ctx android.BaseModuleContext, ccMod *cc.Module, h
}
fileToCopy := ccMod.OutputFile().Path()
- return newApexFile(ctx, fileToCopy, ccMod.Name(), dirInApex, nativeSharedLib, ccMod)
+ androidMkModuleName := ccMod.BaseModuleName() + ccMod.Properties.SubName
+ return newApexFile(ctx, fileToCopy, androidMkModuleName, dirInApex, nativeSharedLib, ccMod)
}
func apexFileForExecutable(ctx android.BaseModuleContext, cc *cc.Module) apexFile {
@@ -1732,7 +1794,8 @@ func apexFileForExecutable(ctx android.BaseModuleContext, cc *cc.Module) apexFil
}
dirInApex = filepath.Join(dirInApex, cc.RelativeInstallPath())
fileToCopy := cc.OutputFile().Path()
- af := newApexFile(ctx, fileToCopy, cc.Name(), dirInApex, nativeExecutable, cc)
+ androidMkModuleName := cc.BaseModuleName() + cc.Properties.SubName
+ af := newApexFile(ctx, fileToCopy, androidMkModuleName, dirInApex, nativeExecutable, cc)
af.symlinks = cc.Symlinks()
af.dataPaths = cc.DataPaths()
return af
@@ -1741,7 +1804,7 @@ func apexFileForExecutable(ctx android.BaseModuleContext, cc *cc.Module) apexFil
func apexFileForPyBinary(ctx android.BaseModuleContext, py *python.Module) apexFile {
dirInApex := "bin"
fileToCopy := py.HostToolPath().Path()
- return newApexFile(ctx, fileToCopy, py.Name(), dirInApex, pyBinary, py)
+ return newApexFile(ctx, fileToCopy, py.BaseModuleName(), dirInApex, pyBinary, py)
}
func apexFileForGoBinary(ctx android.BaseModuleContext, depName string, gb bootstrap.GoBinaryTool) apexFile {
dirInApex := "bin"
@@ -1760,25 +1823,33 @@ func apexFileForGoBinary(ctx android.BaseModuleContext, depName string, gb boots
func apexFileForShBinary(ctx android.BaseModuleContext, sh *sh.ShBinary) apexFile {
dirInApex := filepath.Join("bin", sh.SubDir())
fileToCopy := sh.OutputFile()
- af := newApexFile(ctx, fileToCopy, sh.Name(), dirInApex, shBinary, sh)
+ af := newApexFile(ctx, fileToCopy, sh.BaseModuleName(), dirInApex, shBinary, sh)
af.symlinks = sh.Symlinks()
return af
}
-type javaDependency interface {
+type javaModule interface {
+ android.Module
+ BaseModuleName() string
DexJarBuildPath() android.Path
JacocoReportClassesFile() android.Path
+ LintDepSets() java.LintDepSets
+
Stem() string
}
-func apexFileForJavaLibrary(ctx android.BaseModuleContext, lib javaDependency, module android.Module) apexFile {
+var _ javaModule = (*java.Library)(nil)
+var _ javaModule = (*java.SdkLibrary)(nil)
+var _ javaModule = (*java.DexImport)(nil)
+var _ javaModule = (*java.SdkLibraryImport)(nil)
+
+func apexFileForJavaLibrary(ctx android.BaseModuleContext, module javaModule) apexFile {
dirInApex := "javalib"
- fileToCopy := lib.DexJarBuildPath()
- // Remove prebuilt_ if necessary so the source and prebuilt modules have the same name.
- name := strings.TrimPrefix(module.Name(), "prebuilt_")
- af := newApexFile(ctx, fileToCopy, name, dirInApex, javaSharedLib, module)
- af.jacocoReportClassesFile = lib.JacocoReportClassesFile()
- af.stem = lib.Stem() + ".jar"
+ fileToCopy := module.DexJarBuildPath()
+ af := newApexFile(ctx, fileToCopy, module.BaseModuleName(), dirInApex, javaSharedLib, module)
+ af.jacocoReportClassesFile = module.JacocoReportClassesFile()
+ af.lintDepSets = module.LintDepSets()
+ af.stem = module.Stem() + ".jar"
return af
}
@@ -1801,6 +1872,7 @@ func apexFileForAndroidApp(ctx android.BaseModuleContext, aapp interface {
OutputFile() android.Path
JacocoReportClassesFile() android.Path
Certificate() java.Certificate
+ BaseModuleName() string
}) apexFile {
appDir := "app"
if aapp.Privileged() {
@@ -1808,7 +1880,7 @@ func apexFileForAndroidApp(ctx android.BaseModuleContext, aapp interface {
}
dirInApex := filepath.Join(appDir, aapp.InstallApkName())
fileToCopy := aapp.OutputFile()
- af := newApexFile(ctx, fileToCopy, aapp.Name(), dirInApex, app, aapp)
+ af := newApexFile(ctx, fileToCopy, aapp.BaseModuleName(), dirInApex, app, aapp)
af.jacocoReportClassesFile = aapp.JacocoReportClassesFile()
af.certificate = aapp.Certificate()
@@ -1868,7 +1940,7 @@ func (a *apexBundle) WalkPayloadDeps(ctx android.ModuleContext, do android.Paylo
}
// Check for the indirect dependencies if it is considered as part of the APEX
- if am.ApexName() != "" {
+ if android.InList(ctx.ModuleName(), am.InApexes()) {
return do(ctx, parent, am, false /* externalDep */)
}
@@ -1914,7 +1986,8 @@ func (a *apexBundle) checkApexAvailability(ctx android.ModuleContext) {
// Because APEXes targeting other than system/system_ext partitions
// can't set apex_available, we skip checks for these APEXes
- if ctx.SocSpecific() || ctx.DeviceSpecific() || ctx.ProductSpecific() {
+ if a.SocSpecific() || a.DeviceSpecific() ||
+ (a.ProductSpecific() && ctx.Config().EnforceProductPartitionInterface()) {
return
}
@@ -2126,7 +2199,7 @@ func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) {
case javaLibTag:
switch child.(type) {
case *java.Library, *java.SdkLibrary, *java.DexImport, *java.SdkLibraryImport:
- af := apexFileForJavaLibrary(ctx, child.(javaDependency), child.(android.Module))
+ af := apexFileForJavaLibrary(ctx, child.(javaModule))
if !af.Ok() {
ctx.PropertyErrorf("java_libs", "%q is not configured to be compiled into dex", depName)
return false
@@ -2149,7 +2222,7 @@ func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) {
if ap.Privileged() {
appDir = "priv-app"
}
- af := newApexFile(ctx, ap.OutputFile(), ap.Name(),
+ af := newApexFile(ctx, ap.OutputFile(), ap.BaseModuleName(),
filepath.Join(appDir, ap.BaseModuleName()), appSet, ap)
af.certificate = java.PresignedCertificate
filesInfo = append(filesInfo, af)
@@ -2207,7 +2280,7 @@ func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) {
case android.PrebuiltDepTag:
// If the prebuilt is force disabled, remember to delete the prebuilt file
// that might have been installed in the previous builds
- if prebuilt, ok := child.(*Prebuilt); ok && prebuilt.isForceDisabled() {
+ if prebuilt, ok := child.(prebuilt); ok && prebuilt.isForceDisabled() {
a.prebuiltFileToDelete = prebuilt.InstallFilename()
}
}
@@ -2223,6 +2296,10 @@ func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) {
// don't include it in this APEX
return false
}
+ if cc.UseVndk() && proptools.Bool(a.properties.Use_vndk_as_stable) && cc.IsVndk() {
+ requireNativeLibs = append(requireNativeLibs, ":vndk")
+ return false
+ }
af := apexFileForNativeLibrary(ctx, cc, handleSpecialLibs)
af.transitiveDep = true
if !a.Host() && !android.DirectlyInApex(ctx.ModuleName(), depName) && (cc.IsStubs() || cc.HasStubsVariants()) {
@@ -2259,7 +2336,7 @@ func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) {
// use the name of the generated test binary (`fileToCopy`) instead of the name
// of the original test module (`depName`, shared by all `test_per_src`
// variations of that module).
- af.moduleName = filepath.Base(af.builtFile.String())
+ af.androidMkModuleName = filepath.Base(af.builtFile.String())
// these are not considered transitive dep
af.transitiveDep = false
filesInfo = append(filesInfo, af)
@@ -2329,6 +2406,15 @@ func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) {
a.installDir = android.PathForModuleInstall(ctx, "apex")
a.filesInfo = filesInfo
+ switch proptools.StringDefault(a.properties.Payload_fs_type, ext4FsType) {
+ case ext4FsType:
+ a.payloadFsType = ext4
+ case f2fsFsType:
+ a.payloadFsType = f2fs
+ default:
+ ctx.PropertyErrorf("payload_fs_type", "%q is not a valid filesystem for apex [ext4, f2fs]", *a.properties.Payload_fs_type)
+ }
+
// Optimization. If we are building bundled APEX, for the files that are gathered due to the
// transitive dependencies, don't place them inside the APEX, but place a symlink pointing
// the same library in the system partition, thus effectively sharing the same libraries
@@ -2340,7 +2426,8 @@ func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) {
// APEXes targeting other than system/system_ext partitions use vendor/product variants.
// So we can't link them to /system/lib libs which are core variants.
- if a.SocSpecific() || a.DeviceSpecific() || a.ProductSpecific() {
+ if a.SocSpecific() || a.DeviceSpecific() ||
+ (a.ProductSpecific() && ctx.Config().EnforceProductPartitionInterface()) {
a.linkToSystemLib = false
}
@@ -2370,6 +2457,8 @@ func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) {
a.compatSymlinks = makeCompatSymlinks(a.BaseModuleName(), ctx)
a.buildApexDependencyInfo(ctx)
+
+ a.buildLintReports(ctx)
}
// Enforce that Java deps of the apex are using stable SDKs to compile
diff --git a/apex/apex_test.go b/apex/apex_test.go
index 3c37ca304..f7e02e338 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -236,13 +236,15 @@ func testApexContext(_ *testing.T, bp string, handlers ...testCustomizer) (*andr
ctx.PreArchMutators(android.RegisterComponentsMutator)
ctx.PostDepsMutators(android.RegisterOverridePostDepsMutators)
- cc.RegisterRequiredBuildComponentsForTest(ctx)
+ android.RegisterPrebuiltMutators(ctx)
- // Register this after the prebuilt mutators have been registered (in
- // cc.RegisterRequiredBuildComponentsForTest) to match what happens at runtime.
+ // Register these after the prebuilt mutators have been registered to match what
+ // happens at runtime.
ctx.PreArchMutators(android.RegisterVisibilityRuleGatherer)
ctx.PostDepsMutators(android.RegisterVisibilityRuleEnforcer)
+ cc.RegisterRequiredBuildComponentsForTest(ctx)
+
ctx.RegisterModuleType("cc_test", cc.TestFactory)
ctx.RegisterModuleType("vndk_prebuilt_shared", cc.VndkPrebuiltSharedFactory)
ctx.RegisterModuleType("vndk_libraries_txt", cc.VndkLibrariesTxtFactory)
@@ -412,7 +414,14 @@ func TestBasicApex(t *testing.T) {
system_shared_libs: [],
static_executable: true,
stl: "none",
- apex_available: [ "myapex" ],
+ apex_available: [ "myapex", "com.android.gki.*" ],
+ }
+
+ apex {
+ name: "com.android.gki.fake",
+ binaries: ["foo"],
+ key: "myapex.key",
+ file_contexts: ":myapex-file_contexts",
}
cc_library_shared {
@@ -519,13 +528,13 @@ func TestBasicApex(t *testing.T) {
ensureContains(t, apexRule.Output.String(), "myapex.apex.unsigned")
// Ensure that apex variant is created for the direct dep
- ensureListContains(t, ctx.ModuleVariantsForTests("mylib"), "android_arm64_armv8-a_shared_myapex")
- ensureListContains(t, ctx.ModuleVariantsForTests("myjar"), "android_common_myapex")
- ensureListContains(t, ctx.ModuleVariantsForTests("myjar_dex"), "android_common_myapex")
+ ensureListContains(t, ctx.ModuleVariantsForTests("mylib"), "android_arm64_armv8-a_shared_apex10000")
+ ensureListContains(t, ctx.ModuleVariantsForTests("myjar"), "android_common_apex10000")
+ ensureListContains(t, ctx.ModuleVariantsForTests("myjar_dex"), "android_common_apex10000")
// Ensure that apex variant is created for the indirect dep
- ensureListContains(t, ctx.ModuleVariantsForTests("mylib2"), "android_arm64_armv8-a_shared_myapex")
- ensureListContains(t, ctx.ModuleVariantsForTests("myotherjar"), "android_common_myapex")
+ ensureListContains(t, ctx.ModuleVariantsForTests("mylib2"), "android_arm64_armv8-a_shared_apex10000")
+ ensureListContains(t, ctx.ModuleVariantsForTests("myotherjar"), "android_common_apex10000")
// Ensure that both direct and indirect deps are copied into apex
ensureContains(t, copyCmds, "image.apex/lib64/mylib.so")
@@ -714,10 +723,10 @@ func TestBasicZipApex(t *testing.T) {
ensureContains(t, zipApexRule.Output.String(), "myapex.zipapex.unsigned")
// Ensure that APEX variant is created for the direct dep
- ensureListContains(t, ctx.ModuleVariantsForTests("mylib"), "android_arm64_armv8-a_shared_myapex")
+ ensureListContains(t, ctx.ModuleVariantsForTests("mylib"), "android_arm64_armv8-a_shared_apex10000")
// Ensure that APEX variant is created for the indirect dep
- ensureListContains(t, ctx.ModuleVariantsForTests("mylib2"), "android_arm64_armv8-a_shared_myapex")
+ ensureListContains(t, ctx.ModuleVariantsForTests("mylib2"), "android_arm64_armv8-a_shared_apex10000")
// Ensure that both direct and indirect deps are copied into apex
ensureContains(t, copyCmds, "image.zipapex/lib64/mylib.so")
@@ -791,7 +800,7 @@ func TestApexWithStubs(t *testing.T) {
// Ensure that direct stubs dep is included
ensureContains(t, copyCmds, "image.apex/lib64/mylib3.so")
- mylibLdFlags := ctx.ModuleForTests("mylib", "android_arm64_armv8-a_shared_myapex").Rule("ld").Args["libFlags"]
+ mylibLdFlags := ctx.ModuleForTests("mylib", "android_arm64_armv8-a_shared_apex10000").Rule("ld").Args["libFlags"]
// Ensure that mylib is linking with the latest version of stubs for mylib2
ensureContains(t, mylibLdFlags, "mylib2/android_arm64_armv8-a_shared_3/mylib2.so")
@@ -799,9 +808,9 @@ func TestApexWithStubs(t *testing.T) {
ensureNotContains(t, mylibLdFlags, "mylib2/android_arm64_armv8-a_shared/mylib2.so")
// Ensure that mylib is linking with the non-stub (impl) of mylib3 (because mylib3 is in the same apex)
- ensureContains(t, mylibLdFlags, "mylib3/android_arm64_armv8-a_shared_myapex/mylib3.so")
+ ensureContains(t, mylibLdFlags, "mylib3/android_arm64_armv8-a_shared_apex10000/mylib3.so")
// .. and not linking to the stubs variant of mylib3
- ensureNotContains(t, mylibLdFlags, "mylib3/android_arm64_armv8-a_shared_12_myapex/mylib3.so")
+ ensureNotContains(t, mylibLdFlags, "mylib3/android_arm64_armv8-a_shared_12/mylib3.so")
// Ensure that stubs libs are built without -include flags
mylib2Cflags := ctx.ModuleForTests("mylib2", "android_arm64_armv8-a_static").Rule("cc").Args["cFlags"]
@@ -881,7 +890,7 @@ func TestApexWithExplicitStubsDependency(t *testing.T) {
// Ensure that dependency of stubs is not included
ensureNotContains(t, copyCmds, "image.apex/lib64/libbar.so")
- mylibLdFlags := ctx.ModuleForTests("mylib", "android_arm64_armv8-a_shared_myapex2").Rule("ld").Args["libFlags"]
+ mylibLdFlags := ctx.ModuleForTests("mylib", "android_arm64_armv8-a_shared_apex10000").Rule("ld").Args["libFlags"]
// Ensure that mylib is linking with version 10 of libfoo
ensureContains(t, mylibLdFlags, "libfoo/android_arm64_armv8-a_shared_10/libfoo.so")
@@ -1101,18 +1110,21 @@ func TestApexDependsOnLLNDKTransitively(t *testing.T) {
testcases := []struct {
name string
minSdkVersion string
+ apexVariant string
shouldLink string
shouldNotLink []string
}{
{
name: "should link to the latest",
minSdkVersion: "",
+ apexVariant: "apex10000",
shouldLink: "30",
shouldNotLink: []string{"29"},
},
{
name: "should link to llndk#29",
minSdkVersion: "min_sdk_version: \"29\",",
+ apexVariant: "apex29",
shouldLink: "29",
shouldNotLink: []string{"30"},
},
@@ -1171,13 +1183,13 @@ func TestApexDependsOnLLNDKTransitively(t *testing.T) {
ensureListEmpty(t, names(apexManifestRule.Args["provideNativeLibs"]))
ensureListContains(t, names(apexManifestRule.Args["requireNativeLibs"]), "libbar.so")
- mylibLdFlags := ctx.ModuleForTests("mylib", "android_vendor.VER_arm64_armv8-a_shared_myapex").Rule("ld").Args["libFlags"]
+ mylibLdFlags := ctx.ModuleForTests("mylib", "android_vendor.VER_arm64_armv8-a_shared_"+tc.apexVariant).Rule("ld").Args["libFlags"]
ensureContains(t, mylibLdFlags, "libbar.llndk/android_vendor.VER_arm64_armv8-a_shared_"+tc.shouldLink+"/libbar.so")
for _, ver := range tc.shouldNotLink {
ensureNotContains(t, mylibLdFlags, "libbar.llndk/android_vendor.VER_arm64_armv8-a_shared_"+ver+"/libbar.so")
}
- mylibCFlags := ctx.ModuleForTests("mylib", "android_vendor.VER_arm64_armv8-a_static_myapex").Rule("cc").Args["cFlags"]
+ mylibCFlags := ctx.ModuleForTests("mylib", "android_vendor.VER_arm64_armv8-a_static_"+tc.apexVariant).Rule("cc").Args["cFlags"]
ensureContains(t, mylibCFlags, "__LIBBAR_API__="+tc.shouldLink)
})
}
@@ -1232,9 +1244,9 @@ func TestApexWithSystemLibsStubs(t *testing.T) {
// Ensure that libc is not included (since it has stubs and not listed in native_shared_libs)
ensureNotContains(t, copyCmds, "image.apex/lib64/bionic/libc.so")
- mylibLdFlags := ctx.ModuleForTests("mylib", "android_arm64_armv8-a_shared_myapex").Rule("ld").Args["libFlags"]
- mylibCFlags := ctx.ModuleForTests("mylib", "android_arm64_armv8-a_static_myapex").Rule("cc").Args["cFlags"]
- mylibSharedCFlags := ctx.ModuleForTests("mylib_shared", "android_arm64_armv8-a_shared_myapex").Rule("cc").Args["cFlags"]
+ mylibLdFlags := ctx.ModuleForTests("mylib", "android_arm64_armv8-a_shared_apex10000").Rule("ld").Args["libFlags"]
+ mylibCFlags := ctx.ModuleForTests("mylib", "android_arm64_armv8-a_static_apex10000").Rule("cc").Args["cFlags"]
+ mylibSharedCFlags := ctx.ModuleForTests("mylib_shared", "android_arm64_armv8-a_shared_apex10000").Rule("cc").Args["cFlags"]
// For dependency to libc
// Ensure that mylib is linking with the latest version of stubs
@@ -1247,7 +1259,7 @@ func TestApexWithSystemLibsStubs(t *testing.T) {
// For dependency to libm
// Ensure that mylib is linking with the non-stub (impl) variant
- ensureContains(t, mylibLdFlags, "libm/android_arm64_armv8-a_shared_myapex/libm.so")
+ ensureContains(t, mylibLdFlags, "libm/android_arm64_armv8-a_shared_apex10000/libm.so")
// ... and not linking to the stub variant
ensureNotContains(t, mylibLdFlags, "libm/android_arm64_armv8-a_shared_29/libm.so")
// ... and is not compiling with the stub
@@ -1261,7 +1273,7 @@ func TestApexWithSystemLibsStubs(t *testing.T) {
ensureNotContains(t, mylibLdFlags, "libdl/android_arm64_armv8-a_shared_28/libdl.so")
ensureNotContains(t, mylibLdFlags, "libdl/android_arm64_armv8-a_shared_29/libdl.so")
// ... and not linking to the non-stub (impl) variant
- ensureNotContains(t, mylibLdFlags, "libdl/android_arm64_armv8-a_shared_myapex/libdl.so")
+ ensureNotContains(t, mylibLdFlags, "libdl/android_arm64_armv8-a_shared_apex10000/libdl.so")
// ... Cflags from stub is correctly exported to mylib
ensureContains(t, mylibCFlags, "__LIBDL_API__=27")
ensureContains(t, mylibSharedCFlags, "__LIBDL_API__=27")
@@ -1350,13 +1362,13 @@ func TestApexMinSdkVersion_NativeModulesShouldBeBuiltAgainstStubs(t *testing.T)
// platform liba is linked to non-stub version
expectLink("liba", "shared", "libz", "shared")
// liba in myapex is linked to #28
- expectLink("liba", "shared_myapex", "libz", "shared_28")
- expectNoLink("liba", "shared_myapex", "libz", "shared_30")
- expectNoLink("liba", "shared_myapex", "libz", "shared")
+ expectLink("liba", "shared_apex29", "libz", "shared_28")
+ expectNoLink("liba", "shared_apex29", "libz", "shared_30")
+ expectNoLink("liba", "shared_apex29", "libz", "shared")
// liba in otherapex is linked to #30
- expectLink("liba", "shared_otherapex", "libz", "shared_30")
- expectNoLink("liba", "shared_otherapex", "libz", "shared_28")
- expectNoLink("liba", "shared_otherapex", "libz", "shared")
+ expectLink("liba", "shared_apex30", "libz", "shared_30")
+ expectNoLink("liba", "shared_apex30", "libz", "shared_28")
+ expectNoLink("liba", "shared_apex30", "libz", "shared")
}
func TestApexMinSdkVersion_SupportsCodeNames(t *testing.T) {
@@ -1409,9 +1421,9 @@ func TestApexMinSdkVersion_SupportsCodeNames(t *testing.T) {
// to distinguish them from finalized and future_api(10000)
// In this test, "R" is assumed not finalized yet( listed in Platform_version_active_codenames) and translated into 9000
// (refer android/api_levels.go)
- expectLink("libx", "shared_myapex", "libz", "shared_9000")
- expectNoLink("libx", "shared_myapex", "libz", "shared_29")
- expectNoLink("libx", "shared_myapex", "libz", "shared")
+ expectLink("libx", "shared_apex10000", "libz", "shared_9000")
+ expectNoLink("libx", "shared_apex10000", "libz", "shared_29")
+ expectNoLink("libx", "shared_apex10000", "libz", "shared")
}
func TestApexMinSdkVersion_DefaultsToLatest(t *testing.T) {
@@ -1454,9 +1466,9 @@ func TestApexMinSdkVersion_DefaultsToLatest(t *testing.T) {
ldArgs := ctx.ModuleForTests(from, "android_arm64_armv8-a_"+from_variant).Rule("ld").Args["libFlags"]
ensureNotContains(t, ldArgs, "android_arm64_armv8-a_"+to_variant+"/"+to+".so")
}
- expectLink("libx", "shared_myapex", "libz", "shared_2")
- expectNoLink("libx", "shared_myapex", "libz", "shared_1")
- expectNoLink("libx", "shared_myapex", "libz", "shared")
+ expectLink("libx", "shared_apex10000", "libz", "shared_2")
+ expectNoLink("libx", "shared_apex10000", "libz", "shared_1")
+ expectNoLink("libx", "shared_apex10000", "libz", "shared")
}
func TestPlatformUsesLatestStubsFromApexes(t *testing.T) {
@@ -1540,7 +1552,7 @@ func TestQApexesUseLatestStubsInBundledBuildsAndHWASAN(t *testing.T) {
libFlags := ld.Args["libFlags"]
ensureContains(t, libFlags, "android_arm64_armv8-a_"+to_variant+"/"+to+".so")
}
- expectLink("libx", "shared_hwasan_myapex", "libbar", "shared_30")
+ expectLink("libx", "shared_hwasan_apex29", "libbar", "shared_30")
}
func TestQTargetApexUsesStaticUnwinder(t *testing.T) {
@@ -1566,7 +1578,7 @@ func TestQTargetApexUsesStaticUnwinder(t *testing.T) {
`)
// ensure apex variant of c++ is linked with static unwinder
- cm := ctx.ModuleForTests("libc++", "android_arm64_armv8-a_shared_myapex").Module().(*cc.Module)
+ cm := ctx.ModuleForTests("libc++", "android_arm64_armv8-a_shared_apex29").Module().(*cc.Module)
ensureListContains(t, cm.Properties.AndroidMkStaticLibs, "libgcc_stripped")
// note that platform variant is not.
cm = ctx.ModuleForTests("libc++", "android_arm64_armv8-a_shared").Module().(*cc.Module)
@@ -1928,8 +1940,8 @@ func TestApexMinSdkVersion_OkayEvenWhenDepIsNewer_IfItSatisfiesApexMinSdkVersion
libFlags := ld.Args["libFlags"]
ensureContains(t, libFlags, "android_arm64_armv8-a_"+to_variant+"/"+to+".so")
}
- expectLink("mylib", "shared_myapex", "mylib2", "shared_29")
- expectLink("mylib", "shared_otherapex", "mylib2", "shared_otherapex")
+ expectLink("mylib", "shared_apex29", "mylib2", "shared_29")
+ expectLink("mylib", "shared_apex30", "mylib2", "shared_apex30")
}
func TestFilesInSubDir(t *testing.T) {
@@ -2098,12 +2110,12 @@ func TestUseVendor(t *testing.T) {
inputsString := strings.Join(inputsList, " ")
// ensure that the apex includes vendor variants of the direct and indirect deps
- ensureContains(t, inputsString, "android_vendor.VER_arm64_armv8-a_shared_myapex/mylib.so")
- ensureContains(t, inputsString, "android_vendor.VER_arm64_armv8-a_shared_myapex/mylib2.so")
+ ensureContains(t, inputsString, "android_vendor.VER_arm64_armv8-a_shared_apex10000/mylib.so")
+ ensureContains(t, inputsString, "android_vendor.VER_arm64_armv8-a_shared_apex10000/mylib2.so")
// ensure that the apex does not include core variants
- ensureNotContains(t, inputsString, "android_arm64_armv8-a_shared_myapex/mylib.so")
- ensureNotContains(t, inputsString, "android_arm64_armv8-a_shared_myapex/mylib2.so")
+ ensureNotContains(t, inputsString, "android_arm64_armv8-a_shared_apex10000/mylib.so")
+ ensureNotContains(t, inputsString, "android_arm64_armv8-a_shared_apex10000/mylib2.so")
}
func TestUseVendorNotAllowedForSystemApexes(t *testing.T) {
@@ -2201,6 +2213,63 @@ func TestVendorApex(t *testing.T) {
data.Custom(&builder, name, prefix, "", data)
androidMk := builder.String()
ensureContains(t, androidMk, `LOCAL_MODULE_PATH := /tmp/target/product/test_device/vendor/apex`)
+
+ apexManifestRule := ctx.ModuleForTests("myapex", "android_common_myapex_image").Rule("apexManifestRule")
+ requireNativeLibs := names(apexManifestRule.Args["requireNativeLibs"])
+ ensureListNotContains(t, requireNativeLibs, ":vndk")
+}
+
+func TestVendorApex_use_vndk_as_stable(t *testing.T) {
+ ctx, _ := testApex(t, `
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ binaries: ["mybin"],
+ vendor: true,
+ use_vndk_as_stable: true,
+ }
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+ cc_binary {
+ name: "mybin",
+ vendor: true,
+ shared_libs: ["libvndk", "libvendor"],
+ }
+ cc_library {
+ name: "libvndk",
+ vndk: {
+ enabled: true,
+ },
+ vendor_available: true,
+ }
+ cc_library {
+ name: "libvendor",
+ vendor: true,
+ }
+ `)
+
+ vendorVariant := "android_vendor.VER_arm64_armv8-a"
+
+ ldRule := ctx.ModuleForTests("mybin", vendorVariant+"_apex10000").Rule("ld")
+ libs := names(ldRule.Args["libFlags"])
+ // VNDK libs(libvndk/libc++) as they are
+ ensureListContains(t, libs, buildDir+"/.intermediates/libvndk/"+vendorVariant+"_shared/libvndk.so")
+ ensureListContains(t, libs, buildDir+"/.intermediates/libc++/"+vendorVariant+"_shared/libc++.so")
+ // non-stable Vendor libs as APEX variants
+ ensureListContains(t, libs, buildDir+"/.intermediates/libvendor/"+vendorVariant+"_shared_apex10000/libvendor.so")
+
+ // VNDK libs are not included when use_vndk_as_stable: true
+ ensureExactContents(t, ctx, "myapex", "android_common_myapex_image", []string{
+ "bin/mybin",
+ "lib64/libvendor.so",
+ })
+
+ apexManifestRule := ctx.ModuleForTests("myapex", "android_common_myapex_image").Rule("apexManifestRule")
+ requireNativeLibs := names(apexManifestRule.Args["requireNativeLibs"])
+ ensureListContains(t, requireNativeLibs, ":vndk")
}
func TestAndroidMk_UseVendorRequired(t *testing.T) {
@@ -2567,7 +2636,21 @@ func TestMacro(t *testing.T) {
"myapex",
"otherapex",
],
+ static_libs: ["mylib3"],
+ recovery_available: true,
+ min_sdk_version: "29",
+ }
+ cc_library {
+ name: "mylib3",
+ srcs: ["mylib.cpp"],
+ system_shared_libs: [],
+ stl: "none",
+ apex_available: [
+ "myapex",
+ "otherapex",
+ ],
use_apex_name_macro: true,
+ recovery_available: true,
min_sdk_version: "29",
}
`)
@@ -2578,19 +2661,43 @@ func TestMacro(t *testing.T) {
ensureNotContains(t, mylibCFlags, "-D__ANDROID_SDK_VERSION__")
// APEX variant has __ANDROID_APEX__ and __ANDROID_APEX_SDK__ defined
- mylibCFlags = ctx.ModuleForTests("mylib", "android_arm64_armv8-a_static_myapex").Rule("cc").Args["cFlags"]
+ mylibCFlags = ctx.ModuleForTests("mylib", "android_arm64_armv8-a_static_apex10000").Rule("cc").Args["cFlags"]
ensureContains(t, mylibCFlags, "-D__ANDROID_APEX__")
ensureContains(t, mylibCFlags, "-D__ANDROID_SDK_VERSION__=10000")
ensureNotContains(t, mylibCFlags, "-D__ANDROID_APEX_MYAPEX__")
// APEX variant has __ANDROID_APEX__ and __ANDROID_APEX_SDK__ defined
- mylibCFlags = ctx.ModuleForTests("mylib", "android_arm64_armv8-a_static_otherapex").Rule("cc").Args["cFlags"]
+ mylibCFlags = ctx.ModuleForTests("mylib", "android_arm64_armv8-a_static_apex29").Rule("cc").Args["cFlags"]
ensureContains(t, mylibCFlags, "-D__ANDROID_APEX__")
ensureContains(t, mylibCFlags, "-D__ANDROID_SDK_VERSION__=29")
ensureNotContains(t, mylibCFlags, "-D__ANDROID_APEX_OTHERAPEX__")
- // When cc_library sets use_apex_name_macro: true
- // apex variants define additional macro to distinguish which apex variant it is built for
+ // When a cc_library sets use_apex_name_macro: true each apex gets a unique variant and
+ // each variant defines additional macros to distinguish which apex variant it is built for
+
+ // non-APEX variant does not have __ANDROID_APEX__ defined
+ mylibCFlags = ctx.ModuleForTests("mylib3", "android_arm64_armv8-a_static").Rule("cc").Args["cFlags"]
+ ensureNotContains(t, mylibCFlags, "-D__ANDROID_APEX__")
+
+ // APEX variant has __ANDROID_APEX__ defined
+ mylibCFlags = ctx.ModuleForTests("mylib3", "android_arm64_armv8-a_static_myapex").Rule("cc").Args["cFlags"]
+ ensureContains(t, mylibCFlags, "-D__ANDROID_APEX__")
+ ensureContains(t, mylibCFlags, "-D__ANDROID_APEX_MYAPEX__")
+ ensureNotContains(t, mylibCFlags, "-D__ANDROID_APEX_OTHERAPEX__")
+
+ // APEX variant has __ANDROID_APEX__ defined
+ mylibCFlags = ctx.ModuleForTests("mylib3", "android_arm64_armv8-a_static_otherapex").Rule("cc").Args["cFlags"]
+ ensureContains(t, mylibCFlags, "-D__ANDROID_APEX__")
+ ensureNotContains(t, mylibCFlags, "-D__ANDROID_APEX_MYAPEX__")
+ ensureContains(t, mylibCFlags, "-D__ANDROID_APEX_OTHERAPEX__")
+
+ // recovery variant does not set __ANDROID_SDK_VERSION__
+ mylibCFlags = ctx.ModuleForTests("mylib3", "android_recovery_arm64_armv8-a_static").Rule("cc").Args["cFlags"]
+ ensureNotContains(t, mylibCFlags, "-D__ANDROID_APEX__")
+ ensureNotContains(t, mylibCFlags, "-D__ANDROID_SDK_VERSION__")
+
+ // When a dependency of a cc_library sets use_apex_name_macro: true each apex gets a unique
+ // variant.
// non-APEX variant does not have __ANDROID_APEX__ defined
mylibCFlags = ctx.ModuleForTests("mylib2", "android_arm64_armv8-a_static").Rule("cc").Args["cFlags"]
@@ -2599,17 +2706,17 @@ func TestMacro(t *testing.T) {
// APEX variant has __ANDROID_APEX__ defined
mylibCFlags = ctx.ModuleForTests("mylib2", "android_arm64_armv8-a_static_myapex").Rule("cc").Args["cFlags"]
ensureContains(t, mylibCFlags, "-D__ANDROID_APEX__")
- ensureContains(t, mylibCFlags, "-D__ANDROID_APEX_MYAPEX__")
+ ensureNotContains(t, mylibCFlags, "-D__ANDROID_APEX_MYAPEX__")
ensureNotContains(t, mylibCFlags, "-D__ANDROID_APEX_OTHERAPEX__")
// APEX variant has __ANDROID_APEX__ defined
mylibCFlags = ctx.ModuleForTests("mylib2", "android_arm64_armv8-a_static_otherapex").Rule("cc").Args["cFlags"]
ensureContains(t, mylibCFlags, "-D__ANDROID_APEX__")
ensureNotContains(t, mylibCFlags, "-D__ANDROID_APEX_MYAPEX__")
- ensureContains(t, mylibCFlags, "-D__ANDROID_APEX_OTHERAPEX__")
+ ensureNotContains(t, mylibCFlags, "-D__ANDROID_APEX_OTHERAPEX__")
// recovery variant does not set __ANDROID_SDK_VERSION__
- mylibCFlags = ctx.ModuleForTests("mylib", "android_recovery_arm64_armv8-a_static").Rule("cc").Args["cFlags"]
+ mylibCFlags = ctx.ModuleForTests("mylib2", "android_recovery_arm64_armv8-a_static").Rule("cc").Args["cFlags"]
ensureNotContains(t, mylibCFlags, "-D__ANDROID_APEX__")
ensureNotContains(t, mylibCFlags, "-D__ANDROID_SDK_VERSION__")
}
@@ -3389,7 +3496,7 @@ func TestNonTestApex(t *testing.T) {
ensureContains(t, apexRule.Output.String(), "myapex.apex.unsigned")
// Ensure that apex variant is created for the direct dep
- ensureListContains(t, ctx.ModuleVariantsForTests("mylib_common"), "android_arm64_armv8-a_shared_myapex")
+ ensureListContains(t, ctx.ModuleVariantsForTests("mylib_common"), "android_arm64_armv8-a_shared_apex10000")
// Ensure that both direct and indirect deps are copied into apex
ensureContains(t, copyCmds, "image.apex/lib64/mylib_common.so")
@@ -3445,7 +3552,7 @@ func TestTestApex(t *testing.T) {
ensureContains(t, apexRule.Output.String(), "myapex.apex.unsigned")
// Ensure that apex variant is created for the direct dep
- ensureListContains(t, ctx.ModuleVariantsForTests("mylib_common_test"), "android_arm64_armv8-a_shared_myapex")
+ ensureListContains(t, ctx.ModuleVariantsForTests("mylib_common_test"), "android_arm64_armv8-a_shared_apex10000")
// Ensure that both direct and indirect deps are copied into apex
ensureContains(t, copyCmds, "image.apex/lib64/mylib_common_test.so")
@@ -3529,9 +3636,9 @@ func TestApexWithTarget(t *testing.T) {
ensureContains(t, apexRule.Output.String(), "myapex.apex.unsigned")
// Ensure that apex variant is created for the direct dep
- ensureListContains(t, ctx.ModuleVariantsForTests("mylib"), "android_arm64_armv8-a_shared_myapex")
- ensureListContains(t, ctx.ModuleVariantsForTests("mylib_common"), "android_arm64_armv8-a_shared_myapex")
- ensureListNotContains(t, ctx.ModuleVariantsForTests("mylib2"), "android_arm64_armv8-a_shared_myapex")
+ ensureListContains(t, ctx.ModuleVariantsForTests("mylib"), "android_arm64_armv8-a_shared_apex10000")
+ ensureListContains(t, ctx.ModuleVariantsForTests("mylib_common"), "android_arm64_armv8-a_shared_apex10000")
+ ensureListNotContains(t, ctx.ModuleVariantsForTests("mylib2"), "android_arm64_armv8-a_shared_apex10000")
// Ensure that both direct and indirect deps are copied into apex
ensureContains(t, copyCmds, "image.apex/lib64/mylib.so")
@@ -3996,8 +4103,8 @@ func TestApexUsesOtherApex(t *testing.T) {
apexRule2 := module2.Rule("apexRule")
copyCmds2 := apexRule2.Args["copy_commands"]
- ensureListContains(t, ctx.ModuleVariantsForTests("mylib"), "android_arm64_armv8-a_shared_myapex")
- ensureListContains(t, ctx.ModuleVariantsForTests("libcommon"), "android_arm64_armv8-a_shared_commonapex")
+ ensureListContains(t, ctx.ModuleVariantsForTests("mylib"), "android_arm64_armv8-a_shared_apex10000")
+ ensureListContains(t, ctx.ModuleVariantsForTests("libcommon"), "android_arm64_armv8-a_shared_apex10000")
ensureContains(t, copyCmds1, "image.apex/lib64/mylib.so")
ensureContains(t, copyCmds2, "image.apex/lib64/libcommon.so")
ensureNotContains(t, copyCmds1, "image.apex/lib64/libcommon.so")
@@ -4177,14 +4284,14 @@ func TestApexWithApps(t *testing.T) {
ensureContains(t, copyCmds, "image.apex/app/AppFoo/AppFoo.apk")
ensureContains(t, copyCmds, "image.apex/priv-app/AppFooPriv/AppFooPriv.apk")
- appZipRule := ctx.ModuleForTests("AppFoo", "android_common_myapex").Description("zip jni libs")
+ appZipRule := ctx.ModuleForTests("AppFoo", "android_common_apex10000").Description("zip jni libs")
// JNI libraries are uncompressed
if args := appZipRule.Args["jarArgs"]; !strings.Contains(args, "-L 0") {
t.Errorf("jni libs are not uncompressed for AppFoo")
}
// JNI libraries including transitive deps are
for _, jni := range []string{"libjni", "libfoo"} {
- jniOutput := ctx.ModuleForTests(jni, "android_arm64_armv8-a_sdk_shared_myapex").Module().(*cc.Module).OutputFile()
+ jniOutput := ctx.ModuleForTests(jni, "android_arm64_armv8-a_sdk_shared_apex10000").Module().(*cc.Module).OutputFile()
// ... embedded inside APK (jnilibs.zip)
ensureListContains(t, appZipRule.Implicits.Strings(), jniOutput.String())
// ... and not directly inside the APEX
@@ -4384,11 +4491,11 @@ func TestApexAvailable_DirectDep(t *testing.T) {
func TestApexAvailable_IndirectDep(t *testing.T) {
// libbbaz is an indirect dep
testApexError(t, `requires "libbaz" that is not available for the APEX. Dependency path:
-.*via tag apex\.dependencyTag.*"sharedLib".*
+.*via tag apex\.dependencyTag.*name:sharedLib.*
.*-> libfoo.*link:shared.*
-.*via tag cc\.DependencyTag.*"shared".*
+.*via tag cc\.libraryDependencyTag.*Kind:sharedLibraryDependency.*
.*-> libbar.*link:shared.*
-.*via tag cc\.DependencyTag.*"shared".*
+.*via tag cc\.libraryDependencyTag.*Kind:sharedLibraryDependency.*
.*-> libbaz.*link:shared.*`, `
apex {
name: "myapex",
@@ -4698,7 +4805,7 @@ func TestLegacyAndroid10Support(t *testing.T) {
// the dependency names directly here but for some reason the names are blank in
// this test.
for _, lib := range []string{"libc++", "mylib"} {
- apexImplicits := ctx.ModuleForTests(lib, "android_arm64_armv8-a_shared_myapex").Rule("ld").Implicits
+ apexImplicits := ctx.ModuleForTests(lib, "android_arm64_armv8-a_shared_apex29").Rule("ld").Implicits
nonApexImplicits := ctx.ModuleForTests(lib, "android_arm64_armv8-a_shared").Rule("ld").Implicits
if len(apexImplicits) != len(nonApexImplicits)+1 {
t.Errorf("%q missing unwinder dep", lib)
@@ -5179,6 +5286,57 @@ func TestSymlinksFromApexToSystem(t *testing.T) {
ensureRealfileExists(t, files, "lib64/myotherlib.so") // this is a real file
}
+func TestSymlinksFromApexToSystemRequiredModuleNames(t *testing.T) {
+ ctx, config := testApex(t, `
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ native_shared_libs: ["mylib"],
+ }
+
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+
+ cc_library_shared {
+ name: "mylib",
+ srcs: ["mylib.cpp"],
+ shared_libs: ["myotherlib"],
+ system_shared_libs: [],
+ stl: "none",
+ apex_available: [
+ "myapex",
+ "//apex_available:platform",
+ ],
+ }
+
+ cc_prebuilt_library_shared {
+ name: "myotherlib",
+ srcs: ["prebuilt.so"],
+ system_shared_libs: [],
+ stl: "none",
+ apex_available: [
+ "myapex",
+ "//apex_available:platform",
+ ],
+ }
+ `)
+
+ apexBundle := ctx.ModuleForTests("myapex", "android_common_myapex_image").Module().(*apexBundle)
+ data := android.AndroidMkDataForTest(t, config, "", apexBundle)
+ var builder strings.Builder
+ data.Custom(&builder, apexBundle.BaseModuleName(), "TARGET_", "", data)
+ androidMk := builder.String()
+ // `myotherlib` is added to `myapex` as symlink
+ ensureContains(t, androidMk, "LOCAL_MODULE := mylib.myapex\n")
+ ensureNotContains(t, androidMk, "LOCAL_MODULE := prebuilt_myotherlib.myapex\n")
+ ensureNotContains(t, androidMk, "LOCAL_MODULE := myotherlib.myapex\n")
+ // `myapex` should have `myotherlib` in its required line, not `prebuilt_myotherlib`
+ ensureContains(t, androidMk, "LOCAL_REQUIRED_MODULES += mylib.myapex myotherlib apex_manifest.pb.myapex apex_pubkey.myapex\n")
+}
+
func TestApexWithJniLibs(t *testing.T) {
ctx, _ := testApex(t, `
apex {
@@ -5241,29 +5399,6 @@ func TestApexMutatorsDontRunIfDisabled(t *testing.T) {
}
}
-func TestApexWithJniLibs_Errors(t *testing.T) {
- testApexError(t, `jni_libs: "xxx" is not a cc_library`, `
- apex {
- name: "myapex",
- key: "myapex.key",
- jni_libs: ["xxx"],
- }
-
- apex_key {
- name: "myapex.key",
- public_key: "testkey.avbpubkey",
- private_key: "testkey.pem",
- }
-
- prebuilt_etc {
- name: "xxx",
- src: "xxx",
- }
- `, withFiles(map[string][]byte{
- "xxx": nil,
- }))
-}
-
func TestAppBundle(t *testing.T) {
ctx, _ := testApex(t, `
apex {
@@ -5434,6 +5569,7 @@ func testNoUpdatableJarsInBootImage(t *testing.T, errmsg string, transformDexpre
ctx.RegisterModuleType("apex_key", ApexKeyFactory)
ctx.RegisterModuleType("filegroup", android.FileGroupFactory)
ctx.PreArchMutators(android.RegisterDefaultsPreArchMutators)
+ android.RegisterPrebuiltMutators(ctx)
cc.RegisterRequiredBuildComponentsForTest(ctx)
java.RegisterJavaBuildComponents(ctx)
java.RegisterSystemModulesBuildComponents(ctx)
@@ -5484,52 +5620,54 @@ func TestUpdatable_should_set_min_sdk_version(t *testing.T) {
}
func TestNoUpdatableJarsInBootImage(t *testing.T) {
-
var err string
var transform func(*dexpreopt.GlobalConfig)
+ config := android.TestArchConfig(buildDir, nil, "", nil)
+ ctx := android.PathContextForTesting(config)
+
t.Run("updatable jar from ART apex in the ART boot image => ok", func(t *testing.T) {
transform = func(config *dexpreopt.GlobalConfig) {
- config.ArtApexJars = []string{"com.android.art.something:some-art-lib"}
+ config.ArtApexJars = android.CreateConfiguredJarList(ctx, []string{"com.android.art.something:some-art-lib"})
}
testNoUpdatableJarsInBootImage(t, "", transform)
})
t.Run("updatable jar from ART apex in the framework boot image => error", func(t *testing.T) {
- err = "module 'some-art-lib' from updatable apex 'com.android.art.something' is not allowed in the framework boot image"
+ err = `module "some-art-lib" from updatable apexes \["com.android.art.something"\] is not allowed in the framework boot image`
transform = func(config *dexpreopt.GlobalConfig) {
- config.BootJars = []string{"com.android.art.something:some-art-lib"}
+ config.BootJars = android.CreateConfiguredJarList(ctx, []string{"com.android.art.something:some-art-lib"})
}
testNoUpdatableJarsInBootImage(t, err, transform)
})
t.Run("updatable jar from some other apex in the ART boot image => error", func(t *testing.T) {
- err = "module 'some-updatable-apex-lib' from updatable apex 'some-updatable-apex' is not allowed in the ART boot image"
+ err = `module "some-updatable-apex-lib" from updatable apexes \["some-updatable-apex"\] is not allowed in the ART boot image`
transform = func(config *dexpreopt.GlobalConfig) {
- config.ArtApexJars = []string{"some-updatable-apex:some-updatable-apex-lib"}
+ config.ArtApexJars = android.CreateConfiguredJarList(ctx, []string{"some-updatable-apex:some-updatable-apex-lib"})
}
testNoUpdatableJarsInBootImage(t, err, transform)
})
t.Run("non-updatable jar from some other apex in the ART boot image => error", func(t *testing.T) {
- err = "module 'some-non-updatable-apex-lib' is not allowed in the ART boot image"
+ err = `module "some-non-updatable-apex-lib" is not allowed in the ART boot image`
transform = func(config *dexpreopt.GlobalConfig) {
- config.ArtApexJars = []string{"some-non-updatable-apex:some-non-updatable-apex-lib"}
+ config.ArtApexJars = android.CreateConfiguredJarList(ctx, []string{"some-non-updatable-apex:some-non-updatable-apex-lib"})
}
testNoUpdatableJarsInBootImage(t, err, transform)
})
t.Run("updatable jar from some other apex in the framework boot image => error", func(t *testing.T) {
- err = "module 'some-updatable-apex-lib' from updatable apex 'some-updatable-apex' is not allowed in the framework boot image"
+ err = `module "some-updatable-apex-lib" from updatable apexes \["some-updatable-apex"\] is not allowed in the framework boot image`
transform = func(config *dexpreopt.GlobalConfig) {
- config.BootJars = []string{"some-updatable-apex:some-updatable-apex-lib"}
+ config.BootJars = android.CreateConfiguredJarList(ctx, []string{"some-updatable-apex:some-updatable-apex-lib"})
}
testNoUpdatableJarsInBootImage(t, err, transform)
})
t.Run("non-updatable jar from some other apex in the framework boot image => ok", func(t *testing.T) {
transform = func(config *dexpreopt.GlobalConfig) {
- config.BootJars = []string{"some-non-updatable-apex:some-non-updatable-apex-lib"}
+ config.BootJars = android.CreateConfiguredJarList(ctx, []string{"some-non-updatable-apex:some-non-updatable-apex-lib"})
}
testNoUpdatableJarsInBootImage(t, "", transform)
})
@@ -5537,7 +5675,7 @@ func TestNoUpdatableJarsInBootImage(t *testing.T) {
t.Run("nonexistent jar in the ART boot image => error", func(t *testing.T) {
err = "failed to find a dex jar path for module 'nonexistent'"
transform = func(config *dexpreopt.GlobalConfig) {
- config.ArtApexJars = []string{"platform:nonexistent"}
+ config.ArtApexJars = android.CreateConfiguredJarList(ctx, []string{"platform:nonexistent"})
}
testNoUpdatableJarsInBootImage(t, err, transform)
})
@@ -5545,22 +5683,22 @@ func TestNoUpdatableJarsInBootImage(t *testing.T) {
t.Run("nonexistent jar in the framework boot image => error", func(t *testing.T) {
err = "failed to find a dex jar path for module 'nonexistent'"
transform = func(config *dexpreopt.GlobalConfig) {
- config.BootJars = []string{"platform:nonexistent"}
+ config.BootJars = android.CreateConfiguredJarList(ctx, []string{"platform:nonexistent"})
}
testNoUpdatableJarsInBootImage(t, err, transform)
})
t.Run("platform jar in the ART boot image => error", func(t *testing.T) {
- err = "module 'some-platform-lib' is not allowed in the ART boot image"
+ err = `module "some-platform-lib" is not allowed in the ART boot image`
transform = func(config *dexpreopt.GlobalConfig) {
- config.ArtApexJars = []string{"platform:some-platform-lib"}
+ config.ArtApexJars = android.CreateConfiguredJarList(ctx, []string{"platform:some-platform-lib"})
}
testNoUpdatableJarsInBootImage(t, err, transform)
})
t.Run("platform jar in the framework boot image => ok", func(t *testing.T) {
transform = func(config *dexpreopt.GlobalConfig) {
- config.BootJars = []string{"platform:some-platform-lib"}
+ config.BootJars = android.CreateConfiguredJarList(ctx, []string{"platform:some-platform-lib"})
}
testNoUpdatableJarsInBootImage(t, "", transform)
})
diff --git a/apex/builder.go b/apex/builder.go
index a31429c86..307142097 100644
--- a/apex/builder.go
+++ b/apex/builder.go
@@ -63,6 +63,8 @@ func init() {
pctx.HostBinToolVariable("jsonmodify", "jsonmodify")
pctx.HostBinToolVariable("conv_apex_manifest", "conv_apex_manifest")
pctx.HostBinToolVariable("extract_apks", "extract_apks")
+ pctx.HostBinToolVariable("make_f2fs", "make_f2fs")
+ pctx.HostBinToolVariable("sload_f2fs", "sload_f2fs")
}
var (
@@ -116,12 +118,12 @@ var (
`--payload_type image ` +
`--key ${key} ${opt_flags} ${image_dir} ${out} `,
CommandDeps: []string{"${apexer}", "${avbtool}", "${e2fsdroid}", "${merge_zips}",
- "${mke2fs}", "${resize2fs}", "${sefcontext_compile}",
+ "${mke2fs}", "${resize2fs}", "${sefcontext_compile}", "${make_f2fs}", "${sload_f2fs}",
"${soong_zip}", "${zipalign}", "${aapt2}", "prebuilts/sdk/current/public/android.jar"},
Rspfile: "${out}.copy_commands",
RspfileContent: "${copy_commands}",
Description: "APEX ${image_dir} => ${out}",
- }, "tool_path", "image_dir", "copy_commands", "file_contexts", "canned_fs_config", "key", "opt_flags", "manifest")
+ }, "tool_path", "image_dir", "copy_commands", "file_contexts", "canned_fs_config", "key", "opt_flags", "manifest", "payload_fs_type")
zipApexRule = pctx.StaticRule("zipApexRule", blueprint.RuleParams{
Command: `rm -rf ${image_dir} && mkdir -p ${image_dir} && ` +
@@ -193,7 +195,7 @@ func (a *apexBundle) buildManifest(ctx android.ModuleContext, provideNativeLibs,
// collect jniLibs. Notice that a.filesInfo is already sorted
var jniLibs []string
for _, fi := range a.filesInfo {
- if fi.isJniLib {
+ if fi.isJniLib && !android.InList(fi.Stem(), jniLibs) {
jniLibs = append(jniLibs, fi.Stem())
}
}
@@ -403,16 +405,16 @@ func (a *apexBundle) buildUnflattenedApex(ctx android.ModuleContext) {
}
for _, d := range fi.dataPaths {
// TODO(eakammer): This is now the third repetition of ~this logic for test paths, refactoring should be possible
- relPath := d.Rel()
- dataPath := d.String()
+ relPath := d.SrcPath.Rel()
+ dataPath := d.SrcPath.String()
if !strings.HasSuffix(dataPath, relPath) {
panic(fmt.Errorf("path %q does not end with %q", dataPath, relPath))
}
- dataDest := android.PathForModuleOut(ctx, "image"+suffix, fi.apexRelativePath(relPath)).String()
+ dataDest := android.PathForModuleOut(ctx, "image"+suffix, fi.apexRelativePath(relPath), d.RelativeInstallPath).String()
- copyCommands = append(copyCommands, "cp -f "+d.String()+" "+dataDest)
- implicitInputs = append(implicitInputs, d)
+ copyCommands = append(copyCommands, "cp -f "+d.SrcPath.String()+" "+dataDest)
+ implicitInputs = append(implicitInputs, d.SrcPath)
}
}
@@ -473,7 +475,7 @@ func (a *apexBundle) buildUnflattenedApex(ctx android.ModuleContext) {
if f.installDir == "bin" || strings.HasPrefix(f.installDir, "bin/") {
executablePaths = append(executablePaths, pathInApex)
for _, d := range f.dataPaths {
- readOnlyPaths = append(readOnlyPaths, filepath.Join(f.installDir, d.Rel()))
+ readOnlyPaths = append(readOnlyPaths, filepath.Join(f.installDir, d.RelativeInstallPath, d.SrcPath.Rel()))
}
for _, s := range f.symlinks {
executablePaths = append(executablePaths, filepath.Join(f.installDir, s))
@@ -582,6 +584,8 @@ func (a *apexBundle) buildUnflattenedApex(ctx android.ModuleContext) {
optFlags = append(optFlags, "--manifest_json "+a.manifestJsonOut.String())
}
+ optFlags = append(optFlags, "--payload_fs_type "+a.payloadFsType.string())
+
ctx.Build(pctx, android.BuildParams{
Rule: apexRule,
Implicits: implicitInputs,
@@ -815,3 +819,12 @@ func (a *apexBundle) buildApexDependencyInfo(ctx android.ModuleContext) {
},
})
}
+
+func (a *apexBundle) buildLintReports(ctx android.ModuleContext) {
+ depSetsBuilder := java.NewLintDepSetBuilder()
+ for _, fi := range a.filesInfo {
+ depSetsBuilder.Transitive(fi.lintDepSets)
+ }
+
+ a.lintReports = java.BuildModuleLintReportZips(ctx, depSetsBuilder.Build())
+}
diff --git a/apex/prebuilt.go b/apex/prebuilt.go
index 794799ee6..37457e921 100644
--- a/apex/prebuilt.go
+++ b/apex/prebuilt.go
@@ -40,9 +40,55 @@ var (
"abis", "allow-prereleased", "sdk-version")
)
+type prebuilt interface {
+ isForceDisabled() bool
+ InstallFilename() string
+}
+
+type prebuiltCommon struct {
+ prebuilt android.Prebuilt
+ properties prebuiltCommonProperties
+}
+
+type prebuiltCommonProperties struct {
+ ForceDisable bool `blueprint:"mutated"`
+}
+
+func (p *prebuiltCommon) Prebuilt() *android.Prebuilt {
+ return &p.prebuilt
+}
+
+func (p *prebuiltCommon) isForceDisabled() bool {
+ return p.properties.ForceDisable
+}
+
+func (p *prebuiltCommon) checkForceDisable(ctx android.ModuleContext) bool {
+ // If the device is configured to use flattened APEX, force disable the prebuilt because
+ // the prebuilt is a non-flattened one.
+ forceDisable := ctx.Config().FlattenApex()
+
+ // Force disable the prebuilts when we are doing unbundled build. We do unbundled build
+ // to build the prebuilts themselves.
+ forceDisable = forceDisable || ctx.Config().UnbundledBuild()
+
+ // Force disable the prebuilts when coverage is enabled.
+ forceDisable = forceDisable || ctx.DeviceConfig().NativeCoverageEnabled()
+ forceDisable = forceDisable || ctx.Config().IsEnvTrue("EMMA_INSTRUMENT")
+
+ // b/137216042 don't use prebuilts when address sanitizer is on
+ forceDisable = forceDisable || android.InList("address", ctx.Config().SanitizeDevice()) ||
+ android.InList("hwaddress", ctx.Config().SanitizeDevice())
+
+ if forceDisable && p.prebuilt.SourceExists() {
+ p.properties.ForceDisable = true
+ return true
+ }
+ return false
+}
+
type Prebuilt struct {
android.ModuleBase
- prebuilt android.Prebuilt
+ prebuiltCommon
properties PrebuiltProperties
@@ -58,8 +104,7 @@ type Prebuilt struct {
type PrebuiltProperties struct {
// the path to the prebuilt .apex file to import.
- Source string `blueprint:"mutated"`
- ForceDisable bool `blueprint:"mutated"`
+ Source string `blueprint:"mutated"`
Src *string
Arch struct {
@@ -94,10 +139,6 @@ func (p *Prebuilt) installable() bool {
return p.properties.Installable == nil || proptools.Bool(p.properties.Installable)
}
-func (p *Prebuilt) isForceDisabled() bool {
- return p.properties.ForceDisable
-}
-
func (p *Prebuilt) OutputFiles(tag string) (android.Paths, error) {
switch tag {
case "":
@@ -111,12 +152,8 @@ func (p *Prebuilt) InstallFilename() string {
return proptools.StringDefault(p.properties.Filename, p.BaseModuleName()+imageApexSuffix)
}
-func (p *Prebuilt) Prebuilt() *android.Prebuilt {
- return &p.prebuilt
-}
-
func (p *Prebuilt) Name() string {
- return p.prebuilt.Name(p.ModuleBase.Name())
+ return p.prebuiltCommon.prebuilt.Name(p.ModuleBase.Name())
}
// prebuilt_apex imports an `.apex` file into the build graph as if it was built with apex.
@@ -129,27 +166,6 @@ func PrebuiltFactory() android.Module {
}
func (p *Prebuilt) DepsMutator(ctx android.BottomUpMutatorContext) {
- // If the device is configured to use flattened APEX, force disable the prebuilt because
- // the prebuilt is a non-flattened one.
- forceDisable := ctx.Config().FlattenApex()
-
- // Force disable the prebuilts when we are doing unbundled build. We do unbundled build
- // to build the prebuilts themselves.
- forceDisable = forceDisable || ctx.Config().UnbundledBuild()
-
- // Force disable the prebuilts when coverage is enabled.
- forceDisable = forceDisable || ctx.DeviceConfig().NativeCoverageEnabled()
- forceDisable = forceDisable || ctx.Config().IsEnvTrue("EMMA_INSTRUMENT")
-
- // b/137216042 don't use prebuilts when address sanitizer is on
- forceDisable = forceDisable || android.InList("address", ctx.Config().SanitizeDevice()) ||
- android.InList("hwaddress", ctx.Config().SanitizeDevice())
-
- if forceDisable && p.prebuilt.SourceExists() {
- p.properties.ForceDisable = true
- return
- }
-
// This is called before prebuilt_select and prebuilt_postdeps mutators
// The mutators requires that src to be set correctly for each arch so that
// arch variants are disabled when src is not provided for the arch.
@@ -178,10 +194,6 @@ func (p *Prebuilt) DepsMutator(ctx android.BottomUpMutatorContext) {
}
func (p *Prebuilt) GenerateAndroidBuildActions(ctx android.ModuleContext) {
- if p.properties.ForceDisable {
- return
- }
-
// TODO(jungjw): Check the key validity.
p.inputApex = p.Prebuilt().SingleSourcePath(ctx)
p.installDir = android.PathForModuleInstall(ctx, "apex")
@@ -195,6 +207,12 @@ func (p *Prebuilt) GenerateAndroidBuildActions(ctx android.ModuleContext) {
Input: p.inputApex,
Output: p.outputApex,
})
+
+ if p.prebuiltCommon.checkForceDisable(ctx) {
+ p.SkipInstall()
+ return
+ }
+
if p.installable() {
ctx.InstallFile(p.installDir, p.installFilename, p.inputApex)
}
@@ -228,7 +246,7 @@ func (p *Prebuilt) AndroidMkEntries() []android.AndroidMkEntries {
type ApexSet struct {
android.ModuleBase
- prebuilt android.Prebuilt
+ prebuiltCommon
properties ApexSetProperties
@@ -274,12 +292,8 @@ func (a *ApexSet) InstallFilename() string {
return proptools.StringDefault(a.properties.Filename, a.BaseModuleName()+imageApexSuffix)
}
-func (a *ApexSet) Prebuilt() *android.Prebuilt {
- return &a.prebuilt
-}
-
func (a *ApexSet) Name() string {
- return a.prebuilt.Name(a.ModuleBase.Name())
+ return a.prebuiltCommon.prebuilt.Name(a.ModuleBase.Name())
}
func (a *ApexSet) Overrides() []string {
@@ -301,7 +315,7 @@ func (a *ApexSet) GenerateAndroidBuildActions(ctx android.ModuleContext) {
ctx.ModuleErrorf("filename should end in %s for apex_set", imageApexSuffix)
}
- apexSet := a.prebuilt.SingleSourcePath(ctx)
+ apexSet := a.prebuiltCommon.prebuilt.SingleSourcePath(ctx)
a.outputApex = android.PathForModuleOut(ctx, a.installFilename)
ctx.Build(pctx,
android.BuildParams{
@@ -315,6 +329,12 @@ func (a *ApexSet) GenerateAndroidBuildActions(ctx android.ModuleContext) {
"sdk-version": ctx.Config().PlatformSdkVersion(),
},
})
+
+ if a.prebuiltCommon.checkForceDisable(ctx) {
+ a.SkipInstall()
+ return
+ }
+
a.installDir = android.PathForModuleInstall(ctx, "apex")
if a.installable() {
ctx.InstallFile(a.installDir, a.installFilename, a.outputApex)
diff --git a/bpfix/bpfix/bpfix.go b/bpfix/bpfix/bpfix.go
index 689cbd15b..faec473a4 100644
--- a/bpfix/bpfix/bpfix.go
+++ b/bpfix/bpfix/bpfix.go
@@ -128,6 +128,10 @@ var fixSteps = []FixStep{
Name: "removeSoongConfigBoolVariable",
Fix: removeSoongConfigBoolVariable,
},
+ {
+ Name: "removePdkProperty",
+ Fix: runPatchListMod(removePdkProperty),
+ },
}
func NewFixRequest() FixRequest {
@@ -993,6 +997,25 @@ func removeTags(mod *parser.Module, buf []byte, patchlist *parser.PatchList) err
return patchlist.Add(prop.Pos().Offset, prop.End().Offset+2, replaceStr)
}
+func removePdkProperty(mod *parser.Module, buf []byte, patchlist *parser.PatchList) error {
+ prop, ok := mod.GetProperty("product_variables")
+ if !ok {
+ return nil
+ }
+ propMap, ok := prop.Value.(*parser.Map)
+ if !ok {
+ return nil
+ }
+ pdkProp, ok := propMap.GetProperty("pdk")
+ if !ok {
+ return nil
+ }
+ if len(propMap.Properties) > 1 {
+ return patchlist.Add(pdkProp.Pos().Offset, pdkProp.End().Offset+2, "")
+ }
+ return patchlist.Add(prop.Pos().Offset, prop.End().Offset+2, "")
+}
+
func mergeMatchingModuleProperties(mod *parser.Module, buf []byte, patchlist *parser.PatchList) error {
return mergeMatchingProperties(&mod.Properties, buf, patchlist)
}
diff --git a/bpfix/bpfix/bpfix_test.go b/bpfix/bpfix/bpfix_test.go
index 8988177b1..ef9814fb8 100644
--- a/bpfix/bpfix/bpfix_test.go
+++ b/bpfix/bpfix/bpfix_test.go
@@ -998,3 +998,61 @@ func TestRemoveSoongConfigBoolVariable(t *testing.T) {
})
}
}
+
+func TestRemovePdkProperty(t *testing.T) {
+ tests := []struct {
+ name string
+ in string
+ out string
+ }{
+ {
+ name: "remove property",
+ in: `
+ cc_library_shared {
+ name: "foo",
+ product_variables: {
+ other: {
+ bar: true,
+ },
+ pdk: {
+ enabled: false,
+ },
+ },
+ }
+ `,
+ out: `
+ cc_library_shared {
+ name: "foo",
+ product_variables: {
+ other: {
+ bar: true,
+ },
+ },
+ }
+ `,
+ },
+ {
+ name: "remove property and empty product_variables",
+ in: `
+ cc_library_shared {
+ name: "foo",
+ product_variables: {
+ pdk: {
+ enabled: false,
+ },
+ },
+ }
+ `,
+ out: `
+ cc_library_shared {
+ name: "foo",
+ }
+ `,
+ },
+ }
+ for _, test := range tests {
+ t.Run(test.name, func(t *testing.T) {
+ runPass(t, test.in, test.out, runPatchListMod(removePdkProperty))
+ })
+ }
+}
diff --git a/cc/Android.bp b/cc/Android.bp
index 9ece05f6c..831911e45 100644
--- a/cc/Android.bp
+++ b/cc/Android.bp
@@ -19,6 +19,7 @@ bootstrap_go_package {
"check.go",
"coverage.go",
"gen.go",
+ "image.go",
"linkable.go",
"lto.go",
"makevars.go",
diff --git a/cc/androidmk.go b/cc/androidmk.go
index 3f812c2c0..c899cdd72 100644
--- a/cc/androidmk.go
+++ b/cc/androidmk.go
@@ -149,21 +149,33 @@ func (c *Module) AndroidMkEntries() []android.AndroidMkEntries {
return []android.AndroidMkEntries{entries}
}
-func AndroidMkDataPaths(data android.Paths) []string {
+func AndroidMkDataPaths(data []android.DataPath) []string {
var testFiles []string
for _, d := range data {
- rel := d.Rel()
- path := d.String()
+ rel := d.SrcPath.Rel()
+ path := d.SrcPath.String()
if !strings.HasSuffix(path, rel) {
panic(fmt.Errorf("path %q does not end with %q", path, rel))
}
path = strings.TrimSuffix(path, rel)
- testFiles = append(testFiles, path+":"+rel)
+ testFileString := path + ":" + rel
+ if len(d.RelativeInstallPath) > 0 {
+ testFileString += ":" + d.RelativeInstallPath
+ }
+ testFiles = append(testFiles, testFileString)
}
return testFiles
}
-func androidMkWriteTestData(data android.Paths, ctx AndroidMkContext, entries *android.AndroidMkEntries) {
+func androidMkWriteExtraTestConfigs(extraTestConfigs android.Paths, entries *android.AndroidMkEntries) {
+ if len(extraTestConfigs) > 0 {
+ entries.ExtraEntries = append(entries.ExtraEntries, func(entries *android.AndroidMkEntries) {
+ entries.AddStrings("LOCAL_EXTRA_FULL_TEST_CONFIGS", extraTestConfigs.Strings()...)
+ })
+ }
+}
+
+func androidMkWriteTestData(data []android.DataPath, ctx AndroidMkContext, entries *android.AndroidMkEntries) {
testFiles := AndroidMkDataPaths(data)
if len(testFiles) > 0 {
entries.ExtraEntries = append(entries.ExtraEntries, func(entries *android.AndroidMkEntries) {
@@ -202,29 +214,15 @@ func (library *libraryDecorator) androidMkWriteExportedFlags(entries *android.An
}
func (library *libraryDecorator) androidMkEntriesWriteAdditionalDependenciesForSourceAbiDiff(entries *android.AndroidMkEntries) {
- if library.sAbiOutputFile.Valid() {
- entries.SetString("LOCAL_ADDITIONAL_DEPENDENCIES",
- "$(LOCAL_ADDITIONAL_DEPENDENCIES) "+library.sAbiOutputFile.String())
- if library.sAbiDiff.Valid() && !library.static() {
- entries.SetString("LOCAL_ADDITIONAL_DEPENDENCIES",
- "$(LOCAL_ADDITIONAL_DEPENDENCIES) "+library.sAbiDiff.String())
- entries.SetString("HEADER_ABI_DIFFS",
- "$(HEADER_ABI_DIFFS) "+library.sAbiDiff.String())
- }
+ if library.sAbiDiff.Valid() && !library.static() {
+ entries.AddStrings("LOCAL_ADDITIONAL_DEPENDENCIES", library.sAbiDiff.String())
}
}
// TODO(ccross): remove this once apex/androidmk.go is converted to AndroidMkEntries
func (library *libraryDecorator) androidMkWriteAdditionalDependenciesForSourceAbiDiff(w io.Writer) {
- if library.sAbiOutputFile.Valid() {
- fmt.Fprintln(w, "LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_ADDITIONAL_DEPENDENCIES) ",
- library.sAbiOutputFile.String())
- if library.sAbiDiff.Valid() && !library.static() {
- fmt.Fprintln(w, "LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_ADDITIONAL_DEPENDENCIES) ",
- library.sAbiDiff.String())
- fmt.Fprintln(w, "HEADER_ABI_DIFFS := $(HEADER_ABI_DIFFS) ",
- library.sAbiDiff.String())
- }
+ if library.sAbiDiff.Valid() && !library.static() {
+ fmt.Fprintln(w, "LOCAL_ADDITIONAL_DEPENDENCIES +=", library.sAbiDiff.String())
}
}
@@ -282,10 +280,8 @@ func (library *libraryDecorator) AndroidMkEntries(ctx AndroidMkContext, entries
entries.SubName = "." + library.stubsVersion()
}
entries.ExtraEntries = append(entries.ExtraEntries, func(entries *android.AndroidMkEntries) {
- // Note library.skipInstall() has a special case to get here for static
- // libraries that otherwise would have skipped installation and hence not
- // have executed AndroidMkEntries at all. The reason is to ensure they get
- // a NOTICE file make target which other libraries might depend on.
+ // library.makeUninstallable() depends on this to bypass SkipInstall() for
+ // static libraries.
entries.SetBool("LOCAL_UNINSTALLABLE_MODULE", true)
if library.buildStubs() {
entries.SetBool("LOCAL_NO_NOTICE_FILE", true)
@@ -357,8 +353,11 @@ func (benchmark *benchmarkDecorator) AndroidMkEntries(ctx AndroidMkContext, entr
entries.SetBool("LOCAL_DISABLE_AUTO_GENERATE_TEST_CONFIG", true)
}
})
-
- androidMkWriteTestData(benchmark.data, ctx, entries)
+ dataPaths := []android.DataPath{}
+ for _, srcPath := range benchmark.data {
+ dataPaths = append(dataPaths, android.DataPath{SrcPath: srcPath})
+ }
+ androidMkWriteTestData(dataPaths, ctx, entries)
}
func (test *testBinary) AndroidMkEntries(ctx AndroidMkContext, entries *android.AndroidMkEntries) {
@@ -381,6 +380,7 @@ func (test *testBinary) AndroidMkEntries(ctx AndroidMkContext, entries *android.
})
androidMkWriteTestData(test.data, ctx, entries)
+ androidMkWriteExtraTestConfigs(test.extraTestConfigs, entries)
}
func (fuzz *fuzzBinary) AndroidMkEntries(ctx AndroidMkContext, entries *android.AndroidMkEntries) {
@@ -511,10 +511,14 @@ func (c *vendorSnapshotLibraryDecorator) AndroidMkEntries(ctx AndroidMkContext,
entries.Class = "HEADER_LIBRARIES"
}
+ entries.SubName = ""
+
+ if c.sanitizerProperties.CfiEnabled {
+ entries.SubName += ".cfi"
+ }
+
if c.androidMkVendorSuffix {
- entries.SubName = vendorSuffix
- } else {
- entries.SubName = ""
+ entries.SubName += vendorSuffix
}
entries.ExtraEntries = append(entries.ExtraEntries, func(entries *android.AndroidMkEntries) {
diff --git a/cc/binary.go b/cc/binary.go
index 565cb8ae7..b3ce5ff1c 100644
--- a/cc/binary.go
+++ b/cc/binary.go
@@ -83,7 +83,7 @@ func binaryHostFactory() android.Module {
type binaryDecorator struct {
*baseLinker
*baseInstaller
- stripper
+ stripper Stripper
Properties BinaryLinkerProperties
@@ -130,34 +130,12 @@ func (binary *binaryDecorator) linkerDeps(ctx DepsContext, deps Deps) Deps {
deps = binary.baseLinker.linkerDeps(ctx, deps)
if ctx.toolchain().Bionic() {
if !Bool(binary.baseLinker.Properties.Nocrt) {
- if !ctx.useSdk() {
- if binary.static() {
- deps.CrtBegin = "crtbegin_static"
- } else {
- deps.CrtBegin = "crtbegin_dynamic"
- }
- deps.CrtEnd = "crtend_android"
+ if binary.static() {
+ deps.CrtBegin = "crtbegin_static"
} else {
- // TODO(danalbert): Add generation of crt objects.
- // For `sdk_version: "current"`, we don't actually have a
- // freshly generated set of CRT objects. Use the last stable
- // version.
- version := ctx.sdkVersion()
- if version == "current" {
- version = getCurrentNdkPrebuiltVersion(ctx)
- }
-
- if binary.static() {
- deps.CrtBegin = "ndk_crtbegin_static." + version
- } else {
- if binary.static() {
- deps.CrtBegin = "ndk_crtbegin_static." + version
- } else {
- deps.CrtBegin = "ndk_crtbegin_dynamic." + version
- }
- deps.CrtEnd = "ndk_crtend_android." + version
- }
+ deps.CrtBegin = "crtbegin_dynamic"
}
+ deps.CrtEnd = "crtend_android"
}
if binary.static() {
@@ -339,14 +317,14 @@ func (binary *binaryDecorator) link(ctx ModuleContext,
}
builderFlags := flagsToBuilderFlags(flags)
-
- if binary.stripper.needsStrip(ctx) {
+ stripFlags := flagsToStripFlags(flags)
+ if binary.stripper.NeedsStrip(ctx) {
if ctx.Darwin() {
- builderFlags.stripUseGnuStrip = true
+ stripFlags.StripUseGnuStrip = true
}
strippedOutputFile := outputFile
outputFile = android.PathForModuleOut(ctx, "unstripped", fileName)
- binary.stripper.stripExecutableOrSharedLib(ctx, outputFile, strippedOutputFile, builderFlags)
+ binary.stripper.StripExecutableOrSharedLib(ctx, outputFile, strippedOutputFile, stripFlags)
}
binary.unstrippedOutputFile = outputFile
@@ -355,7 +333,7 @@ func (binary *binaryDecorator) link(ctx ModuleContext,
afterPrefixSymbols := outputFile
outputFile = android.PathForModuleOut(ctx, "unprefixed", fileName)
TransformBinaryPrefixSymbols(ctx, String(binary.Properties.Prefix_symbols), outputFile,
- flagsToBuilderFlags(flags), afterPrefixSymbols)
+ builderFlags, afterPrefixSymbols)
}
outputFile = maybeInjectBoringSSLHash(ctx, outputFile, binary.Properties.Inject_bssl_hash, fileName)
@@ -369,10 +347,10 @@ func (binary *binaryDecorator) link(ctx ModuleContext,
versionedOutputFile := android.PathForModuleOut(ctx, "versioned", fileName)
binary.distFiles = android.MakeDefaultDistFiles(versionedOutputFile)
- if binary.stripper.needsStrip(ctx) {
+ if binary.stripper.NeedsStrip(ctx) {
out := android.PathForModuleOut(ctx, "versioned-stripped", fileName)
binary.distFiles = android.MakeDefaultDistFiles(out)
- binary.stripper.stripExecutableOrSharedLib(ctx, versionedOutputFile, out, builderFlags)
+ binary.stripper.StripExecutableOrSharedLib(ctx, versionedOutputFile, out, stripFlags)
}
binary.injectVersionSymbol(ctx, outputFile, versionedOutputFile)
@@ -467,7 +445,7 @@ func (binary *binaryDecorator) install(ctx ModuleContext, file android.Path) {
// The original path becomes a symlink to the corresponding file in the
// runtime APEX.
translatedArch := ctx.Target().NativeBridge == android.NativeBridgeEnabled
- if InstallToBootstrap(ctx.baseModuleName(), ctx.Config()) && !translatedArch && ctx.apexName() == "" && !ctx.inRamdisk() && !ctx.inRecovery() {
+ if android.DirectlyInAnyApex(ctx, ctx.ModuleName()) && InstallToBootstrap(ctx.baseModuleName(), ctx.Config()) && !translatedArch && ctx.apexVariationName() == "" && !ctx.inRamdisk() && !ctx.inRecovery() {
if ctx.Device() && isBionic(ctx.baseModuleName()) {
binary.installSymlinkToRuntimeApex(ctx, file)
}
diff --git a/cc/binary_sdk_member.go b/cc/binary_sdk_member.go
index 372a72e2c..337de55b3 100644
--- a/cc/binary_sdk_member.go
+++ b/cc/binary_sdk_member.go
@@ -29,7 +29,8 @@ func init() {
var ccBinarySdkMemberType = &binarySdkMemberType{
SdkMemberTypeBase: android.SdkMemberTypeBase{
- PropertyName: "native_binaries",
+ PropertyName: "native_binaries",
+ HostOsDependent: true,
},
}
@@ -140,10 +141,6 @@ func (p *nativeBinaryInfoProperties) PopulateFromVariant(ctx android.SdkMemberCo
}
func (p *nativeBinaryInfoProperties) AddToPropertySet(ctx android.SdkMemberContext, propertySet android.BpPropertySet) {
- if p.Compile_multilib != "" {
- propertySet.AddProperty("compile_multilib", p.Compile_multilib)
- }
-
builder := ctx.SnapshotBuilder()
if p.outputFile != nil {
propertySet.AddProperty("srcs", []string{nativeBinaryPathFor(*p)})
diff --git a/cc/builder.go b/cc/builder.go
index b4f9947d7..8f2da34eb 100644
--- a/cc/builder.go
+++ b/cc/builder.go
@@ -174,12 +174,21 @@ var (
},
"crossCompile", "format")
- clangTidy = pctx.AndroidStaticRule("clangTidy",
+ clangTidy, clangTidyRE = remoteexec.StaticRules(pctx, "clangTidy",
blueprint.RuleParams{
- Command: "rm -f $out && ${config.ClangBin}/clang-tidy $tidyFlags $in -- $cFlags && touch $out",
+ Command: "rm -f $out && $reTemplate${config.ClangBin}/clang-tidy $tidyFlags $in -- $cFlags && touch $out",
CommandDeps: []string{"${config.ClangBin}/clang-tidy"},
},
- "cFlags", "tidyFlags")
+ &remoteexec.REParams{
+ Labels: map[string]string{"type": "lint", "tool": "clang-tidy", "lang": "cpp"},
+ ExecStrategy: "${config.REClangTidyExecStrategy}",
+ Inputs: []string{"$in"},
+ // OutputFile here is $in for remote-execution since its possible that
+ // clang-tidy modifies the given input file itself and $out refers to the
+ // ".tidy" file generated for ninja-dependency reasons.
+ OutputFiles: []string{"$in"},
+ Platform: map[string]string{remoteexec.PoolKey: "${config.REClangTidyPool}"},
+ }, []string{"cFlags", "tidyFlags"}, []string{})
_ = pctx.SourcePathVariable("yasmCmd", "prebuilts/misc/${config.HostPrebuiltTag}/yasm/yasm")
@@ -256,9 +265,9 @@ var (
zip = pctx.AndroidStaticRule("zip",
blueprint.RuleParams{
- Command: "cat $out.rsp | tr ' ' '\\n' | tr -d \\' | sort -u > ${out}.tmp && ${SoongZipCmd} -o ${out} -C $$OUT_DIR -l ${out}.tmp",
+ Command: "${SoongZipCmd} -o ${out} -C $$OUT_DIR -r ${out}.rsp",
CommandDeps: []string{"${SoongZipCmd}"},
- Rspfile: "$out.rsp",
+ Rspfile: "${out}.rsp",
RspfileContent: "$in",
})
@@ -340,18 +349,22 @@ type builderFlags struct {
groupStaticLibs bool
- stripKeepSymbols bool
- stripKeepSymbolsList string
- stripKeepSymbolsAndDebugFrame bool
- stripKeepMiniDebugInfo bool
- stripAddGnuDebuglink bool
- stripUseGnuStrip bool
-
proto android.ProtoFlags
protoC bool
protoOptionsFile bool
yacc *YaccProperties
+ lex *LexProperties
+}
+
+type StripFlags struct {
+ Toolchain config.Toolchain
+ StripKeepSymbols bool
+ StripKeepSymbolsList string
+ StripKeepSymbolsAndDebugFrame bool
+ StripKeepMiniDebugInfo bool
+ StripAddGnuDebuglink bool
+ StripUseGnuStrip bool
}
type Objects struct {
@@ -569,8 +582,13 @@ func TransformSourceToObj(ctx android.ModuleContext, subdir string, srcFiles and
tidyFile := android.ObjPathWithExt(ctx, subdir, srcFile, "tidy")
tidyFiles = append(tidyFiles, tidyFile)
+ rule := clangTidy
+ if ctx.Config().IsEnvTrue("RBE_CLANG_TIDY") {
+ rule = clangTidyRE
+ }
+
ctx.Build(pctx, android.BuildParams{
- Rule: clangTidy,
+ Rule: rule,
Description: "clang-tidy " + srcFile.Rel(),
Output: tidyFile,
Input: srcFile,
@@ -925,26 +943,26 @@ func TransformBinaryPrefixSymbols(ctx android.ModuleContext, prefix string, inpu
}
func TransformStrip(ctx android.ModuleContext, inputFile android.Path,
- outputFile android.WritablePath, flags builderFlags) {
+ outputFile android.WritablePath, flags StripFlags) {
- crossCompile := gccCmd(flags.toolchain, "")
+ crossCompile := gccCmd(flags.Toolchain, "")
args := ""
- if flags.stripAddGnuDebuglink {
+ if flags.StripAddGnuDebuglink {
args += " --add-gnu-debuglink"
}
- if flags.stripKeepMiniDebugInfo {
+ if flags.StripKeepMiniDebugInfo {
args += " --keep-mini-debug-info"
}
- if flags.stripKeepSymbols {
+ if flags.StripKeepSymbols {
args += " --keep-symbols"
}
- if flags.stripKeepSymbolsList != "" {
- args += " -k" + flags.stripKeepSymbolsList
+ if flags.StripKeepSymbolsList != "" {
+ args += " -k" + flags.StripKeepSymbolsList
}
- if flags.stripKeepSymbolsAndDebugFrame {
+ if flags.StripKeepSymbolsAndDebugFrame {
args += " --keep-symbols-and-debug-frame"
}
- if flags.stripUseGnuStrip {
+ if flags.StripUseGnuStrip {
args += " --use-gnu-strip"
}
diff --git a/cc/cc.go b/cc/cc.go
index 0d5b6bdf5..9196d47ba 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -210,6 +210,7 @@ type Flags struct {
protoOptionsFile bool // Whether to look for a .options file next to the .proto
Yacc *YaccProperties
+ Lex *LexProperties
}
// Properties used to compile all C or C++ modules
@@ -344,7 +345,7 @@ type ModuleContextIntf interface {
isNDKStubLibrary() bool
useClangLld(actx ModuleContext) bool
isForPlatform() bool
- apexName() string
+ apexVariationName() string
apexSdkVersion() int
hasStubsVariants() bool
isStubs() bool
@@ -418,51 +419,137 @@ type installer interface {
inSanitizerDir() bool
hostToolPath() android.OptionalPath
relativeInstallPath() string
- skipInstall(mod *Module)
+ makeUninstallable(mod *Module)
}
type xref interface {
XrefCcFiles() android.Paths
}
+type libraryDependencyKind int
+
+const (
+ headerLibraryDependency = iota
+ sharedLibraryDependency
+ staticLibraryDependency
+)
+
+func (k libraryDependencyKind) String() string {
+ switch k {
+ case headerLibraryDependency:
+ return "headerLibraryDependency"
+ case sharedLibraryDependency:
+ return "sharedLibraryDependency"
+ case staticLibraryDependency:
+ return "staticLibraryDependency"
+ default:
+ panic(fmt.Errorf("unknown libraryDependencyKind %d", k))
+ }
+}
+
+type libraryDependencyOrder int
+
+const (
+ earlyLibraryDependency = -1
+ normalLibraryDependency = 0
+ lateLibraryDependency = 1
+)
+
+func (o libraryDependencyOrder) String() string {
+ switch o {
+ case earlyLibraryDependency:
+ return "earlyLibraryDependency"
+ case normalLibraryDependency:
+ return "normalLibraryDependency"
+ case lateLibraryDependency:
+ return "lateLibraryDependency"
+ default:
+ panic(fmt.Errorf("unknown libraryDependencyOrder %d", o))
+ }
+}
+
+// libraryDependencyTag is used to tag dependencies on libraries. Unlike many dependency
+// tags that have a set of predefined tag objects that are reused for each dependency, a
+// libraryDependencyTag is designed to contain extra metadata and is constructed as needed.
+// That means that comparing a libraryDependencyTag for equality will only be equal if all
+// of the metadata is equal. Most usages will want to type assert to libraryDependencyTag and
+// then check individual metadata fields instead.
+type libraryDependencyTag struct {
+ blueprint.BaseDependencyTag
+
+ // These are exported so that fmt.Printf("%#v") can call their String methods.
+ Kind libraryDependencyKind
+ Order libraryDependencyOrder
+
+ wholeStatic bool
+
+ reexportFlags bool
+ explicitlyVersioned bool
+ dataLib bool
+ ndk bool
+
+ staticUnwinder bool
+
+ makeSuffix string
+}
+
+// header returns true if the libraryDependencyTag is tagging a header lib dependency.
+func (d libraryDependencyTag) header() bool {
+ return d.Kind == headerLibraryDependency
+}
+
+// shared returns true if the libraryDependencyTag is tagging a shared lib dependency.
+func (d libraryDependencyTag) shared() bool {
+ return d.Kind == sharedLibraryDependency
+}
+
+// shared returns true if the libraryDependencyTag is tagging a static lib dependency.
+func (d libraryDependencyTag) static() bool {
+ return d.Kind == staticLibraryDependency
+}
+
+// dependencyTag is used for tagging miscellanous dependency types that don't fit into
+// libraryDependencyTag. Each tag object is created globally and reused for multiple
+// dependencies (although since the object contains no references, assigning a tag to a
+// variable and modifying it will not modify the original). Users can compare the tag
+// returned by ctx.OtherModuleDependencyTag against the global original
+type dependencyTag struct {
+ blueprint.BaseDependencyTag
+ name string
+}
+
var (
- dataLibDepTag = DependencyTag{Name: "data_lib", Library: true, Shared: true}
- sharedExportDepTag = DependencyTag{Name: "shared", Library: true, Shared: true, ReexportFlags: true}
- earlySharedDepTag = DependencyTag{Name: "early_shared", Library: true, Shared: true}
- lateSharedDepTag = DependencyTag{Name: "late shared", Library: true, Shared: true}
- staticExportDepTag = DependencyTag{Name: "static", Library: true, ReexportFlags: true}
- lateStaticDepTag = DependencyTag{Name: "late static", Library: true}
- staticUnwinderDepTag = DependencyTag{Name: "static unwinder", Library: true}
- wholeStaticDepTag = DependencyTag{Name: "whole static", Library: true, ReexportFlags: true}
- headerDepTag = DependencyTag{Name: "header", Library: true}
- headerExportDepTag = DependencyTag{Name: "header", Library: true, ReexportFlags: true}
- genSourceDepTag = DependencyTag{Name: "gen source"}
- genHeaderDepTag = DependencyTag{Name: "gen header"}
- genHeaderExportDepTag = DependencyTag{Name: "gen header", ReexportFlags: true}
- objDepTag = DependencyTag{Name: "obj"}
- linkerFlagsDepTag = DependencyTag{Name: "linker flags file"}
- dynamicLinkerDepTag = DependencyTag{Name: "dynamic linker"}
- reuseObjTag = DependencyTag{Name: "reuse objects"}
- staticVariantTag = DependencyTag{Name: "static variant"}
- ndkStubDepTag = DependencyTag{Name: "ndk stub", Library: true}
- ndkLateStubDepTag = DependencyTag{Name: "ndk late stub", Library: true}
- vndkExtDepTag = DependencyTag{Name: "vndk extends", Library: true}
- runtimeDepTag = DependencyTag{Name: "runtime lib"}
- testPerSrcDepTag = DependencyTag{Name: "test_per_src"}
+ genSourceDepTag = dependencyTag{name: "gen source"}
+ genHeaderDepTag = dependencyTag{name: "gen header"}
+ genHeaderExportDepTag = dependencyTag{name: "gen header export"}
+ objDepTag = dependencyTag{name: "obj"}
+ linkerFlagsDepTag = dependencyTag{name: "linker flags file"}
+ dynamicLinkerDepTag = dependencyTag{name: "dynamic linker"}
+ reuseObjTag = dependencyTag{name: "reuse objects"}
+ staticVariantTag = dependencyTag{name: "static variant"}
+ vndkExtDepTag = dependencyTag{name: "vndk extends"}
+ dataLibDepTag = dependencyTag{name: "data lib"}
+ runtimeDepTag = dependencyTag{name: "runtime lib"}
+ testPerSrcDepTag = dependencyTag{name: "test_per_src"}
)
func IsSharedDepTag(depTag blueprint.DependencyTag) bool {
- ccDepTag, ok := depTag.(DependencyTag)
- return ok && ccDepTag.Shared
+ ccLibDepTag, ok := depTag.(libraryDependencyTag)
+ return ok && ccLibDepTag.shared()
+}
+
+func IsStaticDepTag(depTag blueprint.DependencyTag) bool {
+ ccLibDepTag, ok := depTag.(libraryDependencyTag)
+ return ok && ccLibDepTag.static()
}
func IsRuntimeDepTag(depTag blueprint.DependencyTag) bool {
- ccDepTag, ok := depTag.(DependencyTag)
+ ccDepTag, ok := depTag.(dependencyTag)
return ok && ccDepTag == runtimeDepTag
}
func IsTestPerSrcDepTag(depTag blueprint.DependencyTag) bool {
- ccDepTag, ok := depTag.(DependencyTag)
+ ccDepTag, ok := depTag.(dependencyTag)
return ok && ccDepTag == testPerSrcDepTag
}
@@ -595,6 +682,13 @@ func (c *Module) MinSdkVersion() string {
return String(c.Properties.Min_sdk_version)
}
+func (c *Module) SplitPerApiLevel() bool {
+ if linker, ok := c.linker.(*objectLinker); ok {
+ return linker.isCrt()
+ }
+ return false
+}
+
func (c *Module) AlwaysSdk() bool {
return c.Properties.AlwaysSdk || Bool(c.Properties.Sdk_variant_only)
}
@@ -866,7 +960,7 @@ func (c *Module) canUseSdk() bool {
func (c *Module) UseSdk() bool {
if c.canUseSdk() {
- return String(c.Properties.Sdk_version) != ""
+ return String(c.Properties.Sdk_version) != "" || c.SplitPerApiLevel()
}
return false
}
@@ -876,7 +970,7 @@ func (c *Module) isCoverageVariant() bool {
}
func (c *Module) IsNdk() bool {
- return inList(c.Name(), ndkKnownLibs)
+ return inList(c.BaseModuleName(), ndkKnownLibs)
}
func (c *Module) isLlndk(config android.Config) bool {
@@ -941,48 +1035,6 @@ func (c *Module) getVndkExtendsModuleName() string {
return ""
}
-// Returns true only when this module is configured to have core, product and vendor
-// variants.
-func (c *Module) HasVendorVariant() bool {
- return c.IsVndk() || Bool(c.VendorProperties.Vendor_available)
-}
-
-const (
- // VendorVariationPrefix is the variant prefix used for /vendor code that compiles
- // against the VNDK.
- VendorVariationPrefix = "vendor."
-
- // ProductVariationPrefix is the variant prefix used for /product code that compiles
- // against the VNDK.
- ProductVariationPrefix = "product."
-)
-
-// Returns true if the module is "product" variant. Usually these modules are installed in /product
-func (c *Module) inProduct() bool {
- return c.Properties.ImageVariationPrefix == ProductVariationPrefix
-}
-
-// Returns true if the module is "vendor" variant. Usually these modules are installed in /vendor
-func (c *Module) inVendor() bool {
- return c.Properties.ImageVariationPrefix == VendorVariationPrefix
-}
-
-func (c *Module) InRamdisk() bool {
- return c.ModuleBase.InRamdisk() || c.ModuleBase.InstallInRamdisk()
-}
-
-func (c *Module) InRecovery() bool {
- return c.ModuleBase.InRecovery() || c.ModuleBase.InstallInRecovery()
-}
-
-func (c *Module) OnlyInRamdisk() bool {
- return c.ModuleBase.InstallInRamdisk()
-}
-
-func (c *Module) OnlyInRecovery() bool {
- return c.ModuleBase.InstallInRecovery()
-}
-
func (c *Module) IsStubs() bool {
if library, ok := c.linker.(*libraryDecorator); ok {
return library.buildStubs()
@@ -1090,16 +1142,6 @@ type moduleContext struct {
moduleContextImpl
}
-func (ctx *moduleContext) ProductSpecific() bool {
- return ctx.ModuleContext.ProductSpecific() ||
- (ctx.mod.HasVendorVariant() && ctx.mod.inProduct() && !ctx.mod.IsVndk())
-}
-
-func (ctx *moduleContext) SocSpecific() bool {
- return ctx.ModuleContext.SocSpecific() ||
- (ctx.mod.HasVendorVariant() && ctx.mod.inVendor() && !ctx.mod.IsVndk())
-}
-
type moduleContextImpl struct {
mod *Module
ctx BaseModuleContext
@@ -1195,22 +1237,6 @@ func (ctx *moduleContextImpl) mustUseVendorVariant() bool {
return ctx.mod.MustUseVendorVariant()
}
-func (ctx *moduleContextImpl) inProduct() bool {
- return ctx.mod.inProduct()
-}
-
-func (ctx *moduleContextImpl) inVendor() bool {
- return ctx.mod.inVendor()
-}
-
-func (ctx *moduleContextImpl) inRamdisk() bool {
- return ctx.mod.InRamdisk()
-}
-
-func (ctx *moduleContextImpl) inRecovery() bool {
- return ctx.mod.InRecovery()
-}
-
// Check whether ABI dumps should be created for this module.
func (ctx *moduleContextImpl) shouldCreateSourceAbiDump() bool {
if ctx.ctx.Config().IsEnvTrue("SKIP_ABI_CHECKS") {
@@ -1265,8 +1291,8 @@ func (ctx *moduleContextImpl) isForPlatform() bool {
return ctx.mod.IsForPlatform()
}
-func (ctx *moduleContextImpl) apexName() string {
- return ctx.mod.ApexName()
+func (ctx *moduleContextImpl) apexVariationName() string {
+ return ctx.mod.ApexVariationName()
}
func (ctx *moduleContextImpl) apexSdkVersion() int {
@@ -1401,9 +1427,9 @@ func (c *Module) IsTestPerSrcAllTestsVariation() bool {
return ok && test.isAllTestsVariation()
}
-func (c *Module) DataPaths() android.Paths {
+func (c *Module) DataPaths() []android.DataPath {
if p, ok := c.installer.(interface {
- dataPaths() android.Paths
+ dataPaths() []android.DataPath
}); ok {
return p.dataPaths()
}
@@ -1467,8 +1493,11 @@ func (c *Module) GenerateAndroidBuildActions(actx android.ModuleContext) {
c.Properties.SubName += ramdiskSuffix
} else if c.InRecovery() && !c.OnlyInRecovery() {
c.Properties.SubName += recoverySuffix
- } else if c.Properties.IsSdkVariant && c.Properties.SdkAndPlatformVariantVisibleToMake {
+ } else if c.IsSdkVariant() && (c.Properties.SdkAndPlatformVariantVisibleToMake || c.SplitPerApiLevel()) {
c.Properties.SubName += sdkSuffix
+ if c.SplitPerApiLevel() {
+ c.Properties.SubName += "." + c.SdkVersion()
+ }
}
ctx := &moduleContext{
@@ -1641,7 +1670,7 @@ func (c *Module) begin(ctx BaseModuleContext) {
for _, feature := range c.features {
feature.begin(ctx)
}
- if ctx.useSdk() {
+ if ctx.useSdk() && c.IsSdkVariant() {
version, err := normalizeNdkApiLevel(ctx, ctx.sdkVersion(), ctx.Arch())
if err != nil {
ctx.PropertyErrorf("sdk_version", err.Error())
@@ -1744,6 +1773,22 @@ func StubsLibNameAndVersion(name string) (string, string) {
return name, ""
}
+func GetCrtVariations(ctx android.BottomUpMutatorContext,
+ m LinkableInterface) []blueprint.Variation {
+ if ctx.Os() != android.Android {
+ return nil
+ }
+ if m.UseSdk() {
+ return []blueprint.Variation{
+ {Mutator: "sdk", Variation: "sdk"},
+ {Mutator: "ndk_api", Variation: m.SdkVersion()},
+ }
+ }
+ return []blueprint.Variation{
+ {Mutator: "sdk", Variation: ""},
+ }
+}
+
func (c *Module) DepsMutator(actx android.BottomUpMutatorContext) {
if !c.Enabled() {
return
@@ -1859,9 +1904,9 @@ func (c *Module) DepsMutator(actx android.BottomUpMutatorContext) {
vendorSnapshotHeaderLibs := vendorSnapshotHeaderLibs(actx.Config())
for _, lib := range deps.HeaderLibs {
- depTag := headerDepTag
+ depTag := libraryDependencyTag{Kind: headerLibraryDependency}
if inList(lib, deps.ReexportHeaderLibHeaders) {
- depTag = headerExportDepTag
+ depTag.reexportFlags = true
}
lib = rewriteSnapshotLibs(lib, vendorSnapshotHeaderLibs)
@@ -1884,7 +1929,7 @@ func (c *Module) DepsMutator(actx android.BottomUpMutatorContext) {
vendorSnapshotStaticLibs := vendorSnapshotStaticLibs(actx.Config())
for _, lib := range deps.WholeStaticLibs {
- depTag := wholeStaticDepTag
+ depTag := libraryDependencyTag{Kind: staticLibraryDependency, wholeStatic: true, reexportFlags: true}
if impl, ok := syspropImplLibraries[lib]; ok {
lib = impl
}
@@ -1897,9 +1942,9 @@ func (c *Module) DepsMutator(actx android.BottomUpMutatorContext) {
}
for _, lib := range deps.StaticLibs {
- depTag := StaticDepTag
+ depTag := libraryDependencyTag{Kind: staticLibraryDependency}
if inList(lib, deps.ReexportStaticLibHeaders) {
- depTag = staticExportDepTag
+ depTag.reexportFlags = true
}
if impl, ok := syspropImplLibraries[lib]; ok {
@@ -1917,24 +1962,26 @@ func (c *Module) DepsMutator(actx android.BottomUpMutatorContext) {
// so that native libraries/binaries are linked with static unwinder
// because Q libc doesn't have unwinder APIs
if deps.StaticUnwinderIfLegacy {
+ depTag := libraryDependencyTag{Kind: staticLibraryDependency, staticUnwinder: true}
actx.AddVariationDependencies([]blueprint.Variation{
{Mutator: "link", Variation: "static"},
- }, staticUnwinderDepTag, rewriteSnapshotLibs(staticUnwinder(actx), vendorSnapshotStaticLibs))
+ }, depTag, rewriteSnapshotLibs(staticUnwinder(actx), vendorSnapshotStaticLibs))
}
for _, lib := range deps.LateStaticLibs {
+ depTag := libraryDependencyTag{Kind: staticLibraryDependency, Order: lateLibraryDependency}
actx.AddVariationDependencies([]blueprint.Variation{
{Mutator: "link", Variation: "static"},
- }, lateStaticDepTag, rewriteSnapshotLibs(lib, vendorSnapshotStaticLibs))
+ }, depTag, rewriteSnapshotLibs(lib, vendorSnapshotStaticLibs))
}
- addSharedLibDependencies := func(depTag DependencyTag, name string, version string) {
+ addSharedLibDependencies := func(depTag libraryDependencyTag, name string, version string) {
var variations []blueprint.Variation
variations = append(variations, blueprint.Variation{Mutator: "link", Variation: "shared"})
if version != "" && VersionVariantAvailable(c) {
// Version is explicitly specified. i.e. libFoo#30
variations = append(variations, blueprint.Variation{Mutator: "version", Variation: version})
- depTag.ExplicitlyVersioned = true
+ depTag.explicitlyVersioned = true
}
actx.AddVariationDependencies(variations, depTag, name)
@@ -1956,12 +2003,9 @@ func (c *Module) DepsMutator(actx android.BottomUpMutatorContext) {
var sharedLibNames []string
for _, lib := range deps.SharedLibs {
- depTag := SharedDepTag
- if c.static() {
- depTag = SharedFromStaticDepTag
- }
+ depTag := libraryDependencyTag{Kind: sharedLibraryDependency}
if inList(lib, deps.ReexportSharedLibHeaders) {
- depTag = sharedExportDepTag
+ depTag.reexportFlags = true
}
if impl, ok := syspropImplLibraries[lib]; ok {
@@ -1981,7 +2025,8 @@ func (c *Module) DepsMutator(actx android.BottomUpMutatorContext) {
// linking against both the stubs lib and the non-stubs lib at the same time.
continue
}
- addSharedLibDependencies(lateSharedDepTag, lib, "")
+ depTag := libraryDependencyTag{Kind: sharedLibraryDependency, Order: lateLibraryDependency}
+ addSharedLibDependencies(depTag, lib, "")
}
actx.AddVariationDependencies([]blueprint.Variation{
@@ -2006,11 +2051,14 @@ func (c *Module) DepsMutator(actx android.BottomUpMutatorContext) {
vendorSnapshotObjects := vendorSnapshotObjects(actx.Config())
+ crtVariations := GetCrtVariations(ctx, c)
if deps.CrtBegin != "" {
- actx.AddVariationDependencies(nil, CrtBeginDepTag, rewriteSnapshotLibs(deps.CrtBegin, vendorSnapshotObjects))
+ actx.AddVariationDependencies(crtVariations, CrtBeginDepTag,
+ rewriteSnapshotLibs(deps.CrtBegin, vendorSnapshotObjects))
}
if deps.CrtEnd != "" {
- actx.AddVariationDependencies(nil, CrtEndDepTag, rewriteSnapshotLibs(deps.CrtEnd, vendorSnapshotObjects))
+ actx.AddVariationDependencies(crtVariations, CrtEndDepTag,
+ rewriteSnapshotLibs(deps.CrtEnd, vendorSnapshotObjects))
}
if deps.LinkerFlagsFile != "" {
actx.AddDependency(c, linkerFlagsDepTag, deps.LinkerFlagsFile)
@@ -2020,10 +2068,14 @@ func (c *Module) DepsMutator(actx android.BottomUpMutatorContext) {
}
version := ctx.sdkVersion()
+
+ ndkStubDepTag := libraryDependencyTag{Kind: sharedLibraryDependency, ndk: true, makeSuffix: "." + version}
actx.AddVariationDependencies([]blueprint.Variation{
{Mutator: "ndk_api", Variation: version},
{Mutator: "link", Variation: "shared"},
}, ndkStubDepTag, variantNdkLibs...)
+
+ ndkLateStubDepTag := libraryDependencyTag{Kind: sharedLibraryDependency, Order: lateLibraryDependency, ndk: true, makeSuffix: "." + version}
actx.AddVariationDependencies([]blueprint.Variation{
{Mutator: "ndk_api", Variation: version},
{Mutator: "link", Variation: "shared"},
@@ -2047,7 +2099,19 @@ func BeginMutator(ctx android.BottomUpMutatorContext) {
// Whether a module can link to another module, taking into
// account NDK linking.
-func checkLinkType(ctx android.ModuleContext, from LinkableInterface, to LinkableInterface, tag DependencyTag) {
+func checkLinkType(ctx android.ModuleContext, from LinkableInterface, to LinkableInterface,
+ tag blueprint.DependencyTag) {
+
+ switch t := tag.(type) {
+ case dependencyTag:
+ if t != vndkExtDepTag {
+ return
+ }
+ case libraryDependencyTag:
+ default:
+ return
+ }
+
if from.Module().Target().Os != android.Android {
// Host code is not restricted
return
@@ -2205,8 +2269,6 @@ func (c *Module) depsToPaths(ctx android.ModuleContext) PathDeps {
directStaticDeps := []LinkableInterface{}
directSharedDeps := []LinkableInterface{}
- vendorPublicLibraries := vendorPublicLibraries(ctx.Config())
-
reexportExporter := func(exporter exportedFlagsProducer) {
depPaths.ReexportedDirs = append(depPaths.ReexportedDirs, exporter.exportedDirs()...)
depPaths.ReexportedSystemDirs = append(depPaths.ReexportedSystemDirs, exporter.exportedSystemDirs()...)
@@ -2215,6 +2277,19 @@ func (c *Module) depsToPaths(ctx android.ModuleContext) PathDeps {
depPaths.ReexportedGeneratedHeaders = append(depPaths.ReexportedGeneratedHeaders, exporter.exportedGeneratedHeaders()...)
}
+ // For the dependency from platform to apex, use the latest stubs
+ c.apexSdkVersion = android.FutureApiLevel
+ if !c.IsForPlatform() {
+ c.apexSdkVersion = c.ApexProperties.Info.MinSdkVersion
+ }
+
+ if android.InList("hwaddress", ctx.Config().SanitizeDevice()) {
+ // In hwasan build, we override apexSdkVersion to the FutureApiLevel(10000)
+ // so that even Q(29/Android10) apexes could use the dynamic unwinder by linking the newer stubs(e.g libc(R+)).
+ // (b/144430859)
+ c.apexSdkVersion = android.FutureApiLevel
+ }
+
ctx.VisitDirectDeps(func(dep android.Module) {
depName := ctx.OtherModuleName(dep)
depTag := ctx.OtherModuleDependencyTag(dep)
@@ -2303,52 +2378,24 @@ func (c *Module) depsToPaths(ctx android.ModuleContext) PathDeps {
}
}
- // For the dependency from platform to apex, use the latest stubs
- c.apexSdkVersion = android.FutureApiLevel
- if !c.IsForPlatform() {
- c.apexSdkVersion = c.ApexProperties.Info.MinSdkVersion
- }
+ checkLinkType(ctx, c, ccDep, depTag)
- if android.InList("hwaddress", ctx.Config().SanitizeDevice()) {
- // In hwasan build, we override apexSdkVersion to the FutureApiLevel(10000)
- // so that even Q(29/Android10) apexes could use the dynamic unwinder by linking the newer stubs(e.g libc(R+)).
- // (b/144430859)
- c.apexSdkVersion = android.FutureApiLevel
- }
+ linkFile := ccDep.OutputFile()
- if depTag == staticUnwinderDepTag {
- // Use static unwinder for legacy (min_sdk_version = 29) apexes (b/144430859)
- if c.apexSdkVersion <= android.SdkVersion_Android10 {
- depTag = StaticDepTag
- } else {
+ if libDepTag, ok := depTag.(libraryDependencyTag); ok {
+ // Only use static unwinder for legacy (min_sdk_version = 29) apexes (b/144430859)
+ if libDepTag.staticUnwinder && c.apexSdkVersion > android.SdkVersion_Android10 {
return
}
- }
- // Extract ExplicitlyVersioned field from the depTag and reset it inside the struct.
- // Otherwise, SharedDepTag and lateSharedDepTag with ExplicitlyVersioned set to true
- // won't be matched to SharedDepTag and lateSharedDepTag.
- explicitlyVersioned := false
- if t, ok := depTag.(DependencyTag); ok {
- explicitlyVersioned = t.ExplicitlyVersioned
- t.ExplicitlyVersioned = false
- depTag = t
- }
-
- if t, ok := depTag.(DependencyTag); ok && t.Library {
- depIsStatic := false
- switch depTag {
- case StaticDepTag, staticExportDepTag, lateStaticDepTag, wholeStaticDepTag:
- depIsStatic = true
- }
- if ccDep.CcLibrary() && !depIsStatic {
+ if ccDep.CcLibrary() && !libDepTag.static() {
depIsStubs := ccDep.BuildStubs()
depHasStubs := VersionVariantAvailable(c) && ccDep.HasStubsVariants()
- depInSameApex := android.DirectlyInApex(c.ApexName(), depName)
+ depInSameApexes := android.DirectlyInAllApexes(c.InApexes(), depName)
depInPlatform := !android.DirectlyInAnyApex(ctx, depName)
var useThisDep bool
- if depIsStubs && explicitlyVersioned {
+ if depIsStubs && libDepTag.explicitlyVersioned {
// Always respect dependency to the versioned stubs (i.e. libX#10)
useThisDep = true
} else if !depHasStubs {
@@ -2374,13 +2421,13 @@ func (c *Module) depsToPaths(ctx android.ModuleContext) PathDeps {
}
}
} else {
- // If building for APEX, use stubs only when it is not from
- // the same APEX
- useThisDep = (depInSameApex != depIsStubs)
+ // If building for APEX, use stubs when the parent is in any APEX that
+ // the child is not in.
+ useThisDep = (depInSameApexes != depIsStubs)
}
// when to use (unspecified) stubs, check min_sdk_version and choose the right one
- if useThisDep && depIsStubs && !explicitlyVersioned {
+ if useThisDep && depIsStubs && !libDepTag.explicitlyVersioned {
versionToUse, err := c.ChooseSdkVersion(ccDep.StubsVersions(), c.apexSdkVersion)
if err != nil {
ctx.OtherModuleErrorf(dep, err.Error())
@@ -2400,7 +2447,7 @@ func (c *Module) depsToPaths(ctx android.ModuleContext) PathDeps {
// by default, use current version of LLNDK
versionToUse := ""
versions := stubsVersionsFor(ctx.Config())[depName]
- if c.ApexName() != "" && len(versions) > 0 {
+ if c.ApexVariationName() != "" && len(versions) > 0 {
// if this is for use_vendor apex && dep has stubsVersions
// apply the same rule of apex sdk enforcement to choose right version
var err error
@@ -2425,7 +2472,7 @@ func (c *Module) depsToPaths(ctx android.ModuleContext) PathDeps {
depPaths.GeneratedDeps = append(depPaths.GeneratedDeps, i.exportedDeps()...)
depPaths.Flags = append(depPaths.Flags, i.exportedFlags()...)
- if t.ReexportFlags {
+ if libDepTag.reexportFlags {
reexportExporter(i)
// Add these re-exported flags to help header-abi-dumper to infer the abi exported by a library.
// Re-exported shared library headers must be included as well since they can help us with type information
@@ -2437,210 +2484,169 @@ func (c *Module) depsToPaths(ctx android.ModuleContext) PathDeps {
}
}
}
- checkLinkType(ctx, c, ccDep, t)
- }
-
- var ptr *android.Paths
- var depPtr *android.Paths
- linkFile := ccDep.OutputFile()
- depFile := android.OptionalPath{}
-
- switch depTag {
- case ndkStubDepTag, SharedDepTag, SharedFromStaticDepTag, sharedExportDepTag:
- ptr = &depPaths.SharedLibs
- depPtr = &depPaths.SharedLibsDeps
- depFile = ccDep.Toc()
- directSharedDeps = append(directSharedDeps, ccDep)
-
- case earlySharedDepTag:
- ptr = &depPaths.EarlySharedLibs
- depPtr = &depPaths.EarlySharedLibsDeps
- depFile = ccDep.Toc()
- directSharedDeps = append(directSharedDeps, ccDep)
- case lateSharedDepTag, ndkLateStubDepTag:
- ptr = &depPaths.LateSharedLibs
- depPtr = &depPaths.LateSharedLibsDeps
- depFile = ccDep.Toc()
- case StaticDepTag, staticExportDepTag:
- ptr = nil
- directStaticDeps = append(directStaticDeps, ccDep)
- case lateStaticDepTag:
- ptr = &depPaths.LateStaticLibs
- case wholeStaticDepTag:
- ptr = &depPaths.WholeStaticLibs
- if !ccDep.CcLibraryInterface() || !ccDep.Static() {
- ctx.ModuleErrorf("module %q not a static library", depName)
- return
- }
+ var ptr *android.Paths
+ var depPtr *android.Paths
+
+ depFile := android.OptionalPath{}
+
+ switch {
+ case libDepTag.header():
+ // nothing
+ case libDepTag.shared():
+ ptr = &depPaths.SharedLibs
+ switch libDepTag.Order {
+ case earlyLibraryDependency:
+ ptr = &depPaths.EarlySharedLibs
+ depPtr = &depPaths.EarlySharedLibsDeps
+ case normalLibraryDependency:
+ ptr = &depPaths.SharedLibs
+ depPtr = &depPaths.SharedLibsDeps
+ directSharedDeps = append(directSharedDeps, ccDep)
+ case lateLibraryDependency:
+ ptr = &depPaths.LateSharedLibs
+ depPtr = &depPaths.LateSharedLibsDeps
+ default:
+ panic(fmt.Errorf("unexpected library dependency order %d", libDepTag.Order))
+ }
+ depFile = ccDep.Toc()
+ case libDepTag.static():
+ if libDepTag.wholeStatic {
+ ptr = &depPaths.WholeStaticLibs
+ if !ccDep.CcLibraryInterface() || !ccDep.Static() {
+ ctx.ModuleErrorf("module %q not a static library", depName)
+ return
+ }
- // Because the static library objects are included, this only makes sense
- // in the context of proper cc.Modules.
- if ccWholeStaticLib, ok := ccDep.(*Module); ok {
- staticLib := ccWholeStaticLib.linker.(libraryInterface)
- if missingDeps := staticLib.getWholeStaticMissingDeps(); missingDeps != nil {
- postfix := " (required by " + ctx.OtherModuleName(dep) + ")"
- for i := range missingDeps {
- missingDeps[i] += postfix
+ // Because the static library objects are included, this only makes sense
+ // in the context of proper cc.Modules.
+ if ccWholeStaticLib, ok := ccDep.(*Module); ok {
+ staticLib := ccWholeStaticLib.linker.(libraryInterface)
+ if missingDeps := staticLib.getWholeStaticMissingDeps(); missingDeps != nil {
+ postfix := " (required by " + ctx.OtherModuleName(dep) + ")"
+ for i := range missingDeps {
+ missingDeps[i] += postfix
+ }
+ ctx.AddMissingDependencies(missingDeps)
+ }
+ if _, ok := ccWholeStaticLib.linker.(prebuiltLinkerInterface); ok {
+ depPaths.WholeStaticLibsFromPrebuilts = append(depPaths.WholeStaticLibsFromPrebuilts, linkFile.Path())
+ } else {
+ depPaths.WholeStaticLibObjs = depPaths.WholeStaticLibObjs.Append(staticLib.objs())
+ }
+ } else {
+ ctx.ModuleErrorf(
+ "non-cc.Modules cannot be included as whole static libraries.", depName)
+ return
}
- ctx.AddMissingDependencies(missingDeps)
- }
- if _, ok := ccWholeStaticLib.linker.(prebuiltLinkerInterface); ok {
- depPaths.WholeStaticLibsFromPrebuilts = append(depPaths.WholeStaticLibsFromPrebuilts, linkFile.Path())
+
} else {
- depPaths.WholeStaticLibObjs = depPaths.WholeStaticLibObjs.Append(staticLib.objs())
+ switch libDepTag.Order {
+ case earlyLibraryDependency:
+ panic(fmt.Errorf("early static libs not suppported"))
+ case normalLibraryDependency:
+ // static dependencies will be handled separately so they can be ordered
+ // using transitive dependencies.
+ ptr = nil
+ directStaticDeps = append(directStaticDeps, ccDep)
+ case lateLibraryDependency:
+ ptr = &depPaths.LateStaticLibs
+ default:
+ panic(fmt.Errorf("unexpected library dependency order %d", libDepTag.Order))
+ }
}
- } else {
- ctx.ModuleErrorf(
- "non-cc.Modules cannot be included as whole static libraries.", depName)
- return
- }
- case headerDepTag:
- // Nothing
- case objDepTag:
- depPaths.Objs.objFiles = append(depPaths.Objs.objFiles, linkFile.Path())
- case CrtBeginDepTag:
- depPaths.CrtBegin = linkFile
- case CrtEndDepTag:
- depPaths.CrtEnd = linkFile
- case dynamicLinkerDepTag:
- depPaths.DynamicLinker = linkFile
- }
-
- switch depTag {
- case StaticDepTag, staticExportDepTag, lateStaticDepTag:
- if !ccDep.CcLibraryInterface() || !ccDep.Static() {
- ctx.ModuleErrorf("module %q not a static library", depName)
- return
- }
-
- // When combining coverage files for shared libraries and executables, coverage files
- // in static libraries act as if they were whole static libraries. The same goes for
- // source based Abi dump files.
- if c, ok := ccDep.(*Module); ok {
- staticLib := c.linker.(libraryInterface)
- depPaths.StaticLibObjs.coverageFiles = append(depPaths.StaticLibObjs.coverageFiles,
- staticLib.objs().coverageFiles...)
- depPaths.StaticLibObjs.sAbiDumpFiles = append(depPaths.StaticLibObjs.sAbiDumpFiles,
- staticLib.objs().sAbiDumpFiles...)
- } else if c, ok := ccDep.(LinkableInterface); ok {
- // Handle non-CC modules here
- depPaths.StaticLibObjs.coverageFiles = append(depPaths.StaticLibObjs.coverageFiles,
- c.CoverageFiles()...)
}
- }
- if ptr != nil {
- if !linkFile.Valid() {
- if !ctx.Config().AllowMissingDependencies() {
- ctx.ModuleErrorf("module %q missing output file", depName)
- } else {
- ctx.AddMissingDependencies([]string{depName})
+ if libDepTag.static() && !libDepTag.wholeStatic {
+ if !ccDep.CcLibraryInterface() || !ccDep.Static() {
+ ctx.ModuleErrorf("module %q not a static library", depName)
+ return
}
- return
- }
- *ptr = append(*ptr, linkFile.Path())
- }
- if depPtr != nil {
- dep := depFile
- if !dep.Valid() {
- dep = linkFile
+ // When combining coverage files for shared libraries and executables, coverage files
+ // in static libraries act as if they were whole static libraries. The same goes for
+ // source based Abi dump files.
+ if c, ok := ccDep.(*Module); ok {
+ staticLib := c.linker.(libraryInterface)
+ depPaths.StaticLibObjs.coverageFiles = append(depPaths.StaticLibObjs.coverageFiles,
+ staticLib.objs().coverageFiles...)
+ depPaths.StaticLibObjs.sAbiDumpFiles = append(depPaths.StaticLibObjs.sAbiDumpFiles,
+ staticLib.objs().sAbiDumpFiles...)
+ } else if c, ok := ccDep.(LinkableInterface); ok {
+ // Handle non-CC modules here
+ depPaths.StaticLibObjs.coverageFiles = append(depPaths.StaticLibObjs.coverageFiles,
+ c.CoverageFiles()...)
+ }
}
- *depPtr = append(*depPtr, dep.Path())
- }
-
- vendorSuffixModules := vendorSuffixModules(ctx.Config())
- baseLibName := func(depName string) string {
- libName := strings.TrimSuffix(depName, llndkLibrarySuffix)
- libName = strings.TrimSuffix(libName, vendorPublicLibrarySuffix)
- libName = strings.TrimPrefix(libName, "prebuilt_")
- return libName
- }
-
- makeLibName := func(depName string) string {
- libName := baseLibName(depName)
- isLLndk := isLlndkLibrary(libName, ctx.Config())
- isVendorPublicLib := inList(libName, *vendorPublicLibraries)
- bothVendorAndCoreVariantsExist := ccDep.HasVendorVariant() || isLLndk
-
- if c, ok := ccDep.(*Module); ok {
- // Use base module name for snapshots when exporting to Makefile.
- if c.isSnapshotPrebuilt() {
- baseName := c.BaseModuleName()
-
- if c.IsVndk() {
- return baseName + ".vendor"
- }
-
- if vendorSuffixModules[baseName] {
- return baseName + ".vendor"
+ if ptr != nil {
+ if !linkFile.Valid() {
+ if !ctx.Config().AllowMissingDependencies() {
+ ctx.ModuleErrorf("module %q missing output file", depName)
} else {
- return baseName
+ ctx.AddMissingDependencies([]string{depName})
}
+ return
}
+ *ptr = append(*ptr, linkFile.Path())
}
- if ctx.DeviceConfig().VndkUseCoreVariant() && ccDep.IsVndk() && !ccDep.MustUseVendorVariant() && !c.InRamdisk() && !c.InRecovery() {
- // The vendor module is a no-vendor-variant VNDK library. Depend on the
- // core module instead.
- return libName
- } else if c.UseVndk() && bothVendorAndCoreVariantsExist {
- // The vendor module in Make will have been renamed to not conflict with the core
- // module, so update the dependency name here accordingly.
- return libName + c.getNameSuffixWithVndkVersion(ctx)
- } else if (ctx.Platform() || ctx.ProductSpecific()) && isVendorPublicLib {
- return libName + vendorPublicLibrarySuffix
- } else if ccDep.InRamdisk() && !ccDep.OnlyInRamdisk() {
- return libName + ramdiskSuffix
- } else if ccDep.InRecovery() && !ccDep.OnlyInRecovery() {
- return libName + recoverySuffix
- } else if ccDep.Module().Target().NativeBridge == android.NativeBridgeEnabled {
- return libName + nativeBridgeSuffix
- } else {
- return libName
+ if depPtr != nil {
+ dep := depFile
+ if !dep.Valid() {
+ dep = linkFile
+ }
+ *depPtr = append(*depPtr, dep.Path())
}
- }
- // Export the shared libs to Make.
- switch depTag {
- case SharedDepTag, sharedExportDepTag, lateSharedDepTag, earlySharedDepTag:
- if ccDep.CcLibrary() {
- if ccDep.BuildStubs() && android.InAnyApex(depName) {
- // Add the dependency to the APEX(es) providing the library so that
- // m <module> can trigger building the APEXes as well.
- for _, an := range android.GetApexesForModule(depName) {
- c.Properties.ApexesProvidingSharedLibs = append(
- c.Properties.ApexesProvidingSharedLibs, an)
+ makeLibName := c.makeLibName(ctx, ccDep, depName) + libDepTag.makeSuffix
+ switch {
+ case libDepTag.header():
+ c.Properties.AndroidMkHeaderLibs = append(
+ c.Properties.AndroidMkHeaderLibs, makeLibName)
+ case libDepTag.shared():
+ if ccDep.CcLibrary() {
+ if ccDep.BuildStubs() && android.InAnyApex(depName) {
+ // Add the dependency to the APEX(es) providing the library so that
+ // m <module> can trigger building the APEXes as well.
+ for _, an := range android.GetApexesForModule(depName) {
+ c.Properties.ApexesProvidingSharedLibs = append(
+ c.Properties.ApexesProvidingSharedLibs, an)
+ }
}
}
- }
- // Note: the order of libs in this list is not important because
- // they merely serve as Make dependencies and do not affect this lib itself.
- c.Properties.AndroidMkSharedLibs = append(
- c.Properties.AndroidMkSharedLibs, makeLibName(depName))
- // Record baseLibName for snapshots.
- c.Properties.SnapshotSharedLibs = append(c.Properties.SnapshotSharedLibs, baseLibName(depName))
- case ndkStubDepTag, ndkLateStubDepTag:
- c.Properties.AndroidMkSharedLibs = append(
- c.Properties.AndroidMkSharedLibs,
- depName+"."+ccDep.ApiLevel())
- case StaticDepTag, staticExportDepTag, lateStaticDepTag:
- c.Properties.AndroidMkStaticLibs = append(
- c.Properties.AndroidMkStaticLibs, makeLibName(depName))
- case runtimeDepTag:
- c.Properties.AndroidMkRuntimeLibs = append(
- c.Properties.AndroidMkRuntimeLibs, makeLibName(depName))
- // Record baseLibName for snapshots.
- c.Properties.SnapshotRuntimeLibs = append(c.Properties.SnapshotRuntimeLibs, baseLibName(depName))
- case wholeStaticDepTag:
- c.Properties.AndroidMkWholeStaticLibs = append(
- c.Properties.AndroidMkWholeStaticLibs, makeLibName(depName))
- case headerDepTag:
- c.Properties.AndroidMkHeaderLibs = append(
- c.Properties.AndroidMkHeaderLibs, makeLibName(depName))
+ // Note: the order of libs in this list is not important because
+ // they merely serve as Make dependencies and do not affect this lib itself.
+ c.Properties.AndroidMkSharedLibs = append(
+ c.Properties.AndroidMkSharedLibs, makeLibName)
+ // Record baseLibName for snapshots.
+ c.Properties.SnapshotSharedLibs = append(c.Properties.SnapshotSharedLibs, baseLibName(depName))
+ case libDepTag.static():
+ if libDepTag.wholeStatic {
+ c.Properties.AndroidMkWholeStaticLibs = append(
+ c.Properties.AndroidMkWholeStaticLibs, makeLibName)
+ } else {
+ c.Properties.AndroidMkStaticLibs = append(
+ c.Properties.AndroidMkStaticLibs, makeLibName)
+ }
+ }
+ } else {
+ switch depTag {
+ case runtimeDepTag:
+ c.Properties.AndroidMkRuntimeLibs = append(
+ c.Properties.AndroidMkRuntimeLibs, c.makeLibName(ctx, ccDep, depName)+libDepTag.makeSuffix)
+ // Record baseLibName for snapshots.
+ c.Properties.SnapshotRuntimeLibs = append(c.Properties.SnapshotRuntimeLibs, baseLibName(depName))
+ case objDepTag:
+ depPaths.Objs.objFiles = append(depPaths.Objs.objFiles, linkFile.Path())
+ case CrtBeginDepTag:
+ depPaths.CrtBegin = linkFile
+ case CrtEndDepTag:
+ depPaths.CrtEnd = linkFile
+ case dynamicLinkerDepTag:
+ depPaths.DynamicLinker = linkFile
+ }
}
})
@@ -2665,6 +2671,61 @@ func (c *Module) depsToPaths(ctx android.ModuleContext) PathDeps {
return depPaths
}
+// baseLibName trims known prefixes and suffixes
+func baseLibName(depName string) string {
+ libName := strings.TrimSuffix(depName, llndkLibrarySuffix)
+ libName = strings.TrimSuffix(libName, vendorPublicLibrarySuffix)
+ libName = strings.TrimPrefix(libName, "prebuilt_")
+ return libName
+}
+
+func (c *Module) makeLibName(ctx android.ModuleContext, ccDep LinkableInterface, depName string) string {
+ vendorSuffixModules := vendorSuffixModules(ctx.Config())
+ vendorPublicLibraries := vendorPublicLibraries(ctx.Config())
+
+ libName := baseLibName(depName)
+ isLLndk := isLlndkLibrary(libName, ctx.Config())
+ isVendorPublicLib := inList(libName, *vendorPublicLibraries)
+ bothVendorAndCoreVariantsExist := ccDep.HasVendorVariant() || isLLndk
+
+ if c, ok := ccDep.(*Module); ok {
+ // Use base module name for snapshots when exporting to Makefile.
+ if c.isSnapshotPrebuilt() {
+ baseName := c.BaseModuleName()
+
+ if c.IsVndk() {
+ return baseName + ".vendor"
+ }
+
+ if vendorSuffixModules[baseName] {
+ return baseName + ".vendor"
+ } else {
+ return baseName
+ }
+ }
+ }
+
+ if ctx.DeviceConfig().VndkUseCoreVariant() && ccDep.IsVndk() && !ccDep.MustUseVendorVariant() && !c.InRamdisk() && !c.InRecovery() {
+ // The vendor module is a no-vendor-variant VNDK library. Depend on the
+ // core module instead.
+ return libName
+ } else if c.UseVndk() && bothVendorAndCoreVariantsExist {
+ // The vendor module in Make will have been renamed to not conflict with the core
+ // module, so update the dependency name here accordingly.
+ return libName + c.getNameSuffixWithVndkVersion(ctx)
+ } else if (ctx.Platform() || ctx.ProductSpecific()) && isVendorPublicLib {
+ return libName + vendorPublicLibrarySuffix
+ } else if ccDep.InRamdisk() && !ccDep.OnlyInRamdisk() {
+ return libName + ramdiskSuffix
+ } else if ccDep.InRecovery() && !ccDep.OnlyInRecovery() {
+ return libName + recoverySuffix
+ } else if ccDep.Module().Target().NativeBridge == android.NativeBridgeEnabled {
+ return libName + nativeBridgeSuffix
+ } else {
+ return libName
+ }
+}
+
func (c *Module) InstallInData() bool {
if c.installer == nil {
return false
@@ -2690,12 +2751,12 @@ func (c *Module) InstallInRecovery() bool {
return c.InRecovery()
}
-func (c *Module) SkipInstall() {
+func (c *Module) MakeUninstallable() {
if c.installer == nil {
- c.ModuleBase.SkipInstall()
+ c.ModuleBase.MakeUninstallable()
return
}
- c.installer.skipInstall(c)
+ c.installer.makeUninstallable(c)
}
func (c *Module) HostToolPath() android.OptionalPath {
@@ -2835,6 +2896,16 @@ func (c *Module) TestFor() []string {
}
}
+func (c *Module) UniqueApexVariations() bool {
+ if u, ok := c.compiler.(interface {
+ uniqueApexVariations() bool
+ }); ok {
+ return u.uniqueApexVariations()
+ } else {
+ return false
+ }
+}
+
// Return true if the module is ever installable.
func (c *Module) EverInstallable() bool {
return c.installer != nil &&
@@ -2876,26 +2947,28 @@ func (c *Module) AndroidMkWriteAdditionalDependenciesForSourceAbiDiff(w io.Write
}
func (c *Module) DepIsInSameApex(ctx android.BaseModuleContext, dep android.Module) bool {
- if depTag, ok := ctx.OtherModuleDependencyTag(dep).(DependencyTag); ok {
- if cc, ok := dep.(*Module); ok {
- if cc.HasStubsVariants() {
- if depTag.Shared && depTag.Library {
- // dynamic dep to a stubs lib crosses APEX boundary
- return false
- }
- if IsRuntimeDepTag(depTag) {
- // runtime dep to a stubs lib also crosses APEX boundary
- return false
- }
+ depTag := ctx.OtherModuleDependencyTag(dep)
+ libDepTag, isLibDepTag := depTag.(libraryDependencyTag)
+
+ if cc, ok := dep.(*Module); ok {
+ if cc.HasStubsVariants() {
+ if isLibDepTag && libDepTag.shared() {
+ // dynamic dep to a stubs lib crosses APEX boundary
+ return false
}
- if depTag.FromStatic {
- // shared_lib dependency from a static lib is considered as crossing
- // the APEX boundary because the dependency doesn't actually is
- // linked; the dependency is used only during the compilation phase.
+ if IsRuntimeDepTag(depTag) {
+ // runtime dep to a stubs lib also crosses APEX boundary
return false
}
}
- } else if ctx.OtherModuleDependencyTag(dep) == llndkImplDep {
+ if isLibDepTag && c.static() && libDepTag.shared() {
+ // shared_lib dependency from a static lib is considered as crossing
+ // the APEX boundary because the dependency doesn't actually is
+ // linked; the dependency is used only during the compilation phase.
+ return false
+ }
+ }
+ if depTag == llndkImplDep {
// We don't track beyond LLNDK
return false
}
@@ -3031,238 +3104,8 @@ func squashRecoverySrcs(m *Module) {
}
}
-var _ android.ImageInterface = (*Module)(nil)
-
-func (m *Module) ImageMutatorBegin(mctx android.BaseModuleContext) {
- // Sanity check
- vendorSpecific := mctx.SocSpecific() || mctx.DeviceSpecific()
- productSpecific := mctx.ProductSpecific()
-
- if m.VendorProperties.Vendor_available != nil && vendorSpecific {
- mctx.PropertyErrorf("vendor_available",
- "doesn't make sense at the same time as `vendor: true`, `proprietary: true`, or `device_specific:true`")
- }
-
- if vndkdep := m.vndkdep; vndkdep != nil {
- if vndkdep.isVndk() {
- if vendorSpecific || productSpecific {
- if !vndkdep.isVndkExt() {
- mctx.PropertyErrorf("vndk",
- "must set `extends: \"...\"` to vndk extension")
- } else if m.VendorProperties.Vendor_available != nil {
- mctx.PropertyErrorf("vendor_available",
- "must not set at the same time as `vndk: {extends: \"...\"}`")
- }
- } else {
- if vndkdep.isVndkExt() {
- mctx.PropertyErrorf("vndk",
- "must set `vendor: true` or `product_specific: true` to set `extends: %q`",
- m.getVndkExtendsModuleName())
- }
- if m.VendorProperties.Vendor_available == nil {
- mctx.PropertyErrorf("vndk",
- "vendor_available must be set to either true or false when `vndk: {enabled: true}`")
- }
- }
- } else {
- if vndkdep.isVndkSp() {
- mctx.PropertyErrorf("vndk",
- "must set `enabled: true` to set `support_system_process: true`")
- }
- if vndkdep.isVndkExt() {
- mctx.PropertyErrorf("vndk",
- "must set `enabled: true` to set `extends: %q`",
- m.getVndkExtendsModuleName())
- }
- }
- }
-
- var coreVariantNeeded bool = false
- var ramdiskVariantNeeded bool = false
- var recoveryVariantNeeded bool = false
-
- var vendorVariants []string
- var productVariants []string
-
- platformVndkVersion := mctx.DeviceConfig().PlatformVndkVersion()
- boardVndkVersion := mctx.DeviceConfig().VndkVersion()
- productVndkVersion := mctx.DeviceConfig().ProductVndkVersion()
- if boardVndkVersion == "current" {
- boardVndkVersion = platformVndkVersion
- }
- if productVndkVersion == "current" {
- productVndkVersion = platformVndkVersion
- }
-
- if boardVndkVersion == "" {
- // If the device isn't compiling against the VNDK, we always
- // use the core mode.
- coreVariantNeeded = true
- } else if _, ok := m.linker.(*llndkStubDecorator); ok {
- // LL-NDK stubs only exist in the vendor and product variants,
- // since the real libraries will be used in the core variant.
- vendorVariants = append(vendorVariants,
- platformVndkVersion,
- boardVndkVersion,
- )
- productVariants = append(productVariants,
- platformVndkVersion,
- productVndkVersion,
- )
- } else if _, ok := m.linker.(*llndkHeadersDecorator); ok {
- // ... and LL-NDK headers as well
- vendorVariants = append(vendorVariants,
- platformVndkVersion,
- boardVndkVersion,
- )
- productVariants = append(productVariants,
- platformVndkVersion,
- productVndkVersion,
- )
- } else if m.isSnapshotPrebuilt() {
- // Make vendor variants only for the versions in BOARD_VNDK_VERSION and
- // PRODUCT_EXTRA_VNDK_VERSIONS.
- if snapshot, ok := m.linker.(interface {
- version() string
- }); ok {
- vendorVariants = append(vendorVariants, snapshot.version())
- } else {
- mctx.ModuleErrorf("version is unknown for snapshot prebuilt")
- }
- } else if m.HasVendorVariant() && !m.isVndkExt() {
- // This will be available in /system, /vendor and /product
- // or a /system directory that is available to vendor and product.
- coreVariantNeeded = true
-
- // We assume that modules under proprietary paths are compatible for
- // BOARD_VNDK_VERSION. The other modules are regarded as AOSP, or
- // PLATFORM_VNDK_VERSION.
- if isVendorProprietaryPath(mctx.ModuleDir()) {
- vendorVariants = append(vendorVariants, boardVndkVersion)
- } else {
- vendorVariants = append(vendorVariants, platformVndkVersion)
- }
-
- // vendor_available modules are also available to /product.
- productVariants = append(productVariants, platformVndkVersion)
- // VNDK is always PLATFORM_VNDK_VERSION
- if !m.IsVndk() {
- productVariants = append(productVariants, productVndkVersion)
- }
- } else if vendorSpecific && String(m.Properties.Sdk_version) == "" {
- // This will be available in /vendor (or /odm) only
-
- // kernel_headers is a special module type whose exported headers
- // are coming from DeviceKernelHeaders() which is always vendor
- // dependent. They'll always have both vendor variants.
- // For other modules, we assume that modules under proprietary
- // paths are compatible for BOARD_VNDK_VERSION. The other modules
- // are regarded as AOSP, which is PLATFORM_VNDK_VERSION.
- if _, ok := m.linker.(*kernelHeadersDecorator); ok {
- vendorVariants = append(vendorVariants,
- platformVndkVersion,
- boardVndkVersion,
- )
- } else if isVendorProprietaryPath(mctx.ModuleDir()) {
- vendorVariants = append(vendorVariants, boardVndkVersion)
- } else {
- vendorVariants = append(vendorVariants, platformVndkVersion)
- }
- } else {
- // This is either in /system (or similar: /data), or is a
- // modules built with the NDK. Modules built with the NDK
- // will be restricted using the existing link type checks.
- coreVariantNeeded = true
- }
-
- if boardVndkVersion != "" && productVndkVersion != "" {
- if coreVariantNeeded && productSpecific && String(m.Properties.Sdk_version) == "" {
- // The module has "product_specific: true" that does not create core variant.
- coreVariantNeeded = false
- productVariants = append(productVariants, productVndkVersion)
- }
- } else {
- // Unless PRODUCT_PRODUCT_VNDK_VERSION is set, product partition has no
- // restriction to use system libs.
- // No product variants defined in this case.
- productVariants = []string{}
- }
-
- if Bool(m.Properties.Ramdisk_available) {
- ramdiskVariantNeeded = true
- }
-
- if m.ModuleBase.InstallInRamdisk() {
- ramdiskVariantNeeded = true
- coreVariantNeeded = false
- }
-
- if Bool(m.Properties.Recovery_available) {
- recoveryVariantNeeded = true
- }
-
- if m.ModuleBase.InstallInRecovery() {
- recoveryVariantNeeded = true
- coreVariantNeeded = false
- }
-
- for _, variant := range android.FirstUniqueStrings(vendorVariants) {
- m.Properties.ExtraVariants = append(m.Properties.ExtraVariants, VendorVariationPrefix+variant)
- }
-
- for _, variant := range android.FirstUniqueStrings(productVariants) {
- m.Properties.ExtraVariants = append(m.Properties.ExtraVariants, ProductVariationPrefix+variant)
- }
-
- m.Properties.RamdiskVariantNeeded = ramdiskVariantNeeded
- m.Properties.RecoveryVariantNeeded = recoveryVariantNeeded
- m.Properties.CoreVariantNeeded = coreVariantNeeded
-}
-
-func (c *Module) CoreVariantNeeded(ctx android.BaseModuleContext) bool {
- return c.Properties.CoreVariantNeeded
-}
-
-func (c *Module) RamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
- return c.Properties.RamdiskVariantNeeded
-}
-
-func (c *Module) RecoveryVariantNeeded(ctx android.BaseModuleContext) bool {
- return c.Properties.RecoveryVariantNeeded
-}
-
-func (c *Module) ExtraImageVariations(ctx android.BaseModuleContext) []string {
- return c.Properties.ExtraVariants
-}
-
-func (c *Module) SetImageVariation(ctx android.BaseModuleContext, variant string, module android.Module) {
- m := module.(*Module)
- if variant == android.RamdiskVariation {
- m.MakeAsPlatform()
- } else if variant == android.RecoveryVariation {
- m.MakeAsPlatform()
- squashRecoverySrcs(m)
- } else if strings.HasPrefix(variant, VendorVariationPrefix) {
- m.Properties.ImageVariationPrefix = VendorVariationPrefix
- m.Properties.VndkVersion = strings.TrimPrefix(variant, VendorVariationPrefix)
- squashVendorSrcs(m)
-
- // Makefile shouldn't know vendor modules other than BOARD_VNDK_VERSION.
- // Hide other vendor variants to avoid collision.
- vndkVersion := ctx.DeviceConfig().VndkVersion()
- if vndkVersion != "current" && vndkVersion != "" && vndkVersion != m.Properties.VndkVersion {
- m.Properties.HideFromMake = true
- m.SkipInstall()
- }
- } else if strings.HasPrefix(variant, ProductVariationPrefix) {
- m.Properties.ImageVariationPrefix = ProductVariationPrefix
- m.Properties.VndkVersion = strings.TrimPrefix(variant, ProductVariationPrefix)
- squashVendorSrcs(m)
- }
-}
-
func (c *Module) IsSdkVariant() bool {
- return c.Properties.IsSdkVariant
+ return c.Properties.IsSdkVariant || c.AlwaysSdk()
}
func getCurrentNdkPrebuiltVersion(ctx DepsContext) string {
diff --git a/cc/cc_test.go b/cc/cc_test.go
index 8a1c8ed4c..77b5c527b 100644
--- a/cc/cc_test.go
+++ b/cc/cc_test.go
@@ -539,7 +539,7 @@ func TestDataLibs(t *testing.T) {
data_libs: ["test_lib"],
gtest: false,
}
- `
+ `
config := TestConfig(buildDir, android.Android, nil, bp, nil)
config.TestProductVariables.DeviceVndkVersion = StringPtr("current")
@@ -564,7 +564,7 @@ func TestDataLibs(t *testing.T) {
}
outputPath := outputFiles[0].String()
- testBinaryPath := testBinary.dataPaths()[0].String()
+ testBinaryPath := testBinary.dataPaths()[0].SrcPath.String()
if !strings.HasSuffix(outputPath, "/main_test") {
t.Errorf("expected test output file to be 'main_test', but was '%s'", outputPath)
@@ -576,6 +576,53 @@ func TestDataLibs(t *testing.T) {
}
}
+func TestDataLibsRelativeInstallPath(t *testing.T) {
+ bp := `
+ cc_test_library {
+ name: "test_lib",
+ srcs: ["test_lib.cpp"],
+ relative_install_path: "foo/bar/baz",
+ gtest: false,
+ }
+
+ cc_test {
+ name: "main_test",
+ data_libs: ["test_lib"],
+ gtest: false,
+ }
+ `
+
+ config := TestConfig(buildDir, android.Android, nil, bp, nil)
+ config.TestProductVariables.DeviceVndkVersion = StringPtr("current")
+ config.TestProductVariables.Platform_vndk_version = StringPtr("VER")
+ config.TestProductVariables.VndkUseCoreVariant = BoolPtr(true)
+
+ ctx := testCcWithConfig(t, config)
+ module := ctx.ModuleForTests("main_test", "android_arm_armv7-a-neon").Module()
+ testBinary := module.(*Module).linker.(*testBinary)
+ outputFiles, err := module.(android.OutputFileProducer).OutputFiles("")
+ if err != nil {
+ t.Fatalf("Expected cc_test to produce output files, error: %s", err)
+ }
+ if len(outputFiles) != 1 {
+ t.Errorf("expected exactly one output file. output files: [%s]", outputFiles)
+ }
+ if len(testBinary.dataPaths()) != 1 {
+ t.Errorf("expected exactly one test data file. test data files: [%s]", testBinary.dataPaths())
+ }
+
+ outputPath := outputFiles[0].String()
+
+ if !strings.HasSuffix(outputPath, "/main_test") {
+ t.Errorf("expected test output file to be 'main_test', but was '%s'", outputPath)
+ }
+ entries := android.AndroidMkEntriesForTest(t, config, "", module)[0]
+ if !strings.HasSuffix(entries.EntryMap["LOCAL_TEST_DATA"][0], ":test_lib.so:foo/bar/baz") {
+ t.Errorf("expected LOCAL_TEST_DATA to end with `:test_lib.so:foo/bar/baz`,"+
+ " but was '%s'", entries.EntryMap["LOCAL_TEST_DATA"][0])
+ }
+}
+
func TestVndkWhenVndkVersionIsNotSet(t *testing.T) {
ctx := testCcNoVndk(t, `
cc_library {
@@ -966,17 +1013,25 @@ func TestVendorSnapshot(t *testing.T) {
filepath.Join(sharedDir, "libvendor_available.so.json"))
// For static libraries, all vendor:true and vendor_available modules (including VNDK) are captured.
+ // Also cfi variants are captured, except for prebuilts like toolchain_library
staticVariant := fmt.Sprintf("android_vendor.VER_%s_%s_static", archType, archVariant)
+ staticCfiVariant := fmt.Sprintf("android_vendor.VER_%s_%s_static_cfi", archType, archVariant)
staticDir := filepath.Join(snapshotVariantPath, archDir, "static")
checkSnapshot(t, ctx, snapshotSingleton, "libb", "libb.a", staticDir, staticVariant)
checkSnapshot(t, ctx, snapshotSingleton, "libvndk", "libvndk.a", staticDir, staticVariant)
+ checkSnapshot(t, ctx, snapshotSingleton, "libvndk", "libvndk.cfi.a", staticDir, staticCfiVariant)
checkSnapshot(t, ctx, snapshotSingleton, "libvendor", "libvendor.a", staticDir, staticVariant)
+ checkSnapshot(t, ctx, snapshotSingleton, "libvendor", "libvendor.cfi.a", staticDir, staticCfiVariant)
checkSnapshot(t, ctx, snapshotSingleton, "libvendor_available", "libvendor_available.a", staticDir, staticVariant)
+ checkSnapshot(t, ctx, snapshotSingleton, "libvendor_available", "libvendor_available.cfi.a", staticDir, staticCfiVariant)
jsonFiles = append(jsonFiles,
filepath.Join(staticDir, "libb.a.json"),
filepath.Join(staticDir, "libvndk.a.json"),
+ filepath.Join(staticDir, "libvndk.cfi.a.json"),
filepath.Join(staticDir, "libvendor.a.json"),
- filepath.Join(staticDir, "libvendor_available.a.json"))
+ filepath.Join(staticDir, "libvendor.cfi.a.json"),
+ filepath.Join(staticDir, "libvendor_available.a.json"),
+ filepath.Join(staticDir, "libvendor_available.cfi.a.json"))
// For binary executables, all vendor:true and vendor_available modules are captured.
if archType == "arm64" {
@@ -1008,6 +1063,39 @@ func TestVendorSnapshot(t *testing.T) {
}
}
+func TestVendorSnapshotSanitizer(t *testing.T) {
+ bp := `
+ vendor_snapshot_static {
+ name: "libsnapshot",
+ vendor: true,
+ target_arch: "arm64",
+ version: "BOARD",
+ arch: {
+ arm64: {
+ src: "libsnapshot.a",
+ cfi: {
+ src: "libsnapshot.cfi.a",
+ }
+ },
+ },
+ }
+`
+ config := TestConfig(buildDir, android.Android, nil, bp, nil)
+ config.TestProductVariables.DeviceVndkVersion = StringPtr("BOARD")
+ config.TestProductVariables.Platform_vndk_version = StringPtr("VER")
+ ctx := testCcWithConfig(t, config)
+
+ // Check non-cfi and cfi variant.
+ staticVariant := "android_vendor.BOARD_arm64_armv8-a_static"
+ staticCfiVariant := "android_vendor.BOARD_arm64_armv8-a_static_cfi"
+
+ staticModule := ctx.ModuleForTests("libsnapshot.vendor_static.BOARD.arm64", staticVariant).Module().(*Module)
+ assertString(t, staticModule.outputFile.Path().Base(), "libsnapshot.a")
+
+ staticCfiModule := ctx.ModuleForTests("libsnapshot.vendor_static.BOARD.arm64", staticCfiVariant).Module().(*Module)
+ assertString(t, staticCfiModule.outputFile.Path().Base(), "libsnapshot.cfi.a")
+}
+
func TestDoubleLoadableDepError(t *testing.T) {
// Check whether an error is emitted when a LLNDK depends on a non-double_loadable VNDK lib.
testCcError(t, "module \".*\" variant \".*\": link.* \".*\" which is not LL-NDK, VNDK-SP, .*double_loadable", `
@@ -2919,6 +3007,52 @@ func TestRecovery(t *testing.T) {
}
}
+func TestDataLibsPrebuiltSharedTestLibrary(t *testing.T) {
+ bp := `
+ cc_prebuilt_test_library_shared {
+ name: "test_lib",
+ relative_install_path: "foo/bar/baz",
+ srcs: ["srcpath/dontusethispath/baz.so"],
+ }
+
+ cc_test {
+ name: "main_test",
+ data_libs: ["test_lib"],
+ gtest: false,
+ }
+ `
+
+ config := TestConfig(buildDir, android.Android, nil, bp, nil)
+ config.TestProductVariables.DeviceVndkVersion = StringPtr("current")
+ config.TestProductVariables.Platform_vndk_version = StringPtr("VER")
+ config.TestProductVariables.VndkUseCoreVariant = BoolPtr(true)
+
+ ctx := testCcWithConfig(t, config)
+ module := ctx.ModuleForTests("main_test", "android_arm_armv7-a-neon").Module()
+ testBinary := module.(*Module).linker.(*testBinary)
+ outputFiles, err := module.(android.OutputFileProducer).OutputFiles("")
+ if err != nil {
+ t.Fatalf("Expected cc_test to produce output files, error: %s", err)
+ }
+ if len(outputFiles) != 1 {
+ t.Errorf("expected exactly one output file. output files: [%s]", outputFiles)
+ }
+ if len(testBinary.dataPaths()) != 1 {
+ t.Errorf("expected exactly one test data file. test data files: [%s]", testBinary.dataPaths())
+ }
+
+ outputPath := outputFiles[0].String()
+
+ if !strings.HasSuffix(outputPath, "/main_test") {
+ t.Errorf("expected test output file to be 'main_test', but was '%s'", outputPath)
+ }
+ entries := android.AndroidMkEntriesForTest(t, config, "", module)[0]
+ if !strings.HasSuffix(entries.EntryMap["LOCAL_TEST_DATA"][0], ":test_lib.so:foo/bar/baz") {
+ t.Errorf("expected LOCAL_TEST_DATA to end with `:test_lib.so:foo/bar/baz`,"+
+ " but was '%s'", entries.EntryMap["LOCAL_TEST_DATA"][0])
+ }
+}
+
func TestVersionedStubs(t *testing.T) {
ctx := testCc(t, `
cc_library_shared {
diff --git a/cc/compiler.go b/cc/compiler.go
index d5ea2c3ae..f504c38a2 100644
--- a/cc/compiler.go
+++ b/cc/compiler.go
@@ -111,6 +111,7 @@ type BaseCompilerProperties struct {
Gnu_extensions *bool
Yacc *YaccProperties
+ Lex *LexProperties
Aidl struct {
// list of directories that will be added to the aidl include paths.
@@ -189,8 +190,14 @@ type BaseCompilerProperties struct {
// Build and link with OpenMP
Openmp *bool `android:"arch_variant"`
+ // Deprecated.
// Adds __ANDROID_APEX_<APEX_MODULE_NAME>__ macro defined for apex variants in addition to __ANDROID_APEX__
Use_apex_name_macro *bool
+
+ // Adds two macros for apex variants in addition to __ANDROID_APEX__
+ // * __ANDROID_APEX_COM_ANDROID_FOO__
+ // * __ANDROID_APEX_NAME__="com.android.foo"
+ UseApexNameMacro bool `blueprint:"mutated"`
}
func NewBaseCompiler() *baseCompiler {
@@ -254,6 +261,10 @@ func (compiler *baseCompiler) compilerDeps(ctx DepsContext, deps Deps) Deps {
return deps
}
+func (compiler *baseCompiler) useApexNameMacro() bool {
+ return Bool(compiler.Properties.Use_apex_name_macro) || compiler.Properties.UseApexNameMacro
+}
+
// Return true if the module is in the WarningAllowedProjects.
func warningsAreAllowed(subdir string) bool {
subdir += "/"
@@ -289,6 +300,7 @@ func (compiler *baseCompiler) compilerFlags(ctx ModuleContext, flags Flags, deps
flags.Local.YasmFlags = append(flags.Local.YasmFlags, esc(compiler.Properties.Asflags)...)
flags.Yacc = compiler.Properties.Yacc
+ flags.Lex = compiler.Properties.Lex
// Include dir cflags
localIncludeDirs := android.PathsForModuleSrc(ctx, compiler.Properties.Local_include_dirs)
@@ -335,10 +347,11 @@ func (compiler *baseCompiler) compilerFlags(ctx ModuleContext, flags Flags, deps
flags.Global.CommonFlags = append(flags.Global.CommonFlags, "-D__ANDROID_RECOVERY__")
}
- if ctx.apexName() != "" {
+ if ctx.apexVariationName() != "" {
flags.Global.CommonFlags = append(flags.Global.CommonFlags, "-D__ANDROID_APEX__")
- if Bool(compiler.Properties.Use_apex_name_macro) {
- flags.Global.CommonFlags = append(flags.Global.CommonFlags, "-D__ANDROID_APEX_"+makeDefineString(ctx.apexName())+"__")
+ if compiler.useApexNameMacro() {
+ flags.Global.CommonFlags = append(flags.Global.CommonFlags, "-D__ANDROID_APEX_"+makeDefineString(ctx.apexVariationName())+"__")
+ flags.Global.CommonFlags = append(flags.Global.CommonFlags, "-D__ANDROID_APEX_NAME__='\""+ctx.apexVariationName()+"\"'")
}
if ctx.Device() {
flags.Global.CommonFlags = append(flags.Global.CommonFlags, "-D__ANDROID_SDK_VERSION__="+strconv.Itoa(ctx.apexSdkVersion()))
@@ -556,6 +569,10 @@ func (compiler *baseCompiler) hasSrcExt(ext string) bool {
return false
}
+func (compiler *baseCompiler) uniqueApexVariations() bool {
+ return compiler.useApexNameMacro()
+}
+
// makeDefineString transforms a name of an APEX module into a value to be used as value for C define
// For example, com.android.foo => COM_ANDROID_FOO
func makeDefineString(name string) string {
@@ -565,7 +582,7 @@ func makeDefineString(name string) string {
var gnuToCReplacer = strings.NewReplacer("gnu", "c")
func ndkPathDeps(ctx ModuleContext) android.Paths {
- if ctx.useSdk() {
+ if ctx.Module().(*Module).IsSdkVariant() {
// The NDK sysroot timestamp file depends on all the NDK sysroot files
// (headers and libraries).
return android.Paths{getNdkBaseTimestampFile(ctx)}
diff --git a/cc/config/clang.go b/cc/config/clang.go
index 24dc6b932..7db405c2e 100644
--- a/cc/config/clang.go
+++ b/cc/config/clang.go
@@ -15,6 +15,7 @@
package config
import (
+ "android/soong/android"
"sort"
"strings"
)
@@ -88,6 +89,12 @@ var ClangUnknownLldflags = sorted([]string{
var ClangLibToolingUnknownCflags = sorted([]string{})
+// List of tidy checks that should be disabled globally. When the compiler is
+// updated, some checks enabled by this module may be disabled if they have
+// become more strict, or if they are a new match for a wildcard group like
+// `modernize-*`.
+var ClangTidyDisableChecks = []string{}
+
func init() {
pctx.StaticVariable("ClangExtraCflags", strings.Join([]string{
"-D__compiler_offsetof=__builtin_offsetof",
@@ -202,25 +209,34 @@ func init() {
}
func ClangFilterUnknownCflags(cflags []string) []string {
- ret := make([]string, 0, len(cflags))
- for _, f := range cflags {
- if !inListSorted(f, ClangUnknownCflags) {
- ret = append(ret, f)
+ result, _ := android.FilterList(cflags, ClangUnknownCflags)
+ return result
+}
+
+func clangTidyNegateChecks(checks []string) []string {
+ ret := make([]string, 0, len(checks))
+ for _, c := range checks {
+ if strings.HasPrefix(c, "-") {
+ ret = append(ret, c)
+ } else {
+ ret = append(ret, "-"+c)
}
}
-
return ret
}
-func ClangFilterUnknownLldflags(lldflags []string) []string {
- ret := make([]string, 0, len(lldflags))
- for _, f := range lldflags {
- if !inListSorted(f, ClangUnknownLldflags) {
- ret = append(ret, f)
- }
- }
+func ClangRewriteTidyChecks(checks []string) []string {
+ checks = append(checks, clangTidyNegateChecks(ClangTidyDisableChecks)...)
+ // clang-tidy does not allow later arguments to override earlier arguments,
+ // so if we just disabled an argument that was explicitly enabled we must
+ // remove the enabling argument from the list.
+ result, _ := android.FilterList(checks, ClangTidyDisableChecks)
+ return result
+}
- return ret
+func ClangFilterUnknownLldflags(lldflags []string) []string {
+ result, _ := android.FilterList(lldflags, ClangUnknownLldflags)
+ return result
}
func inListSorted(s string, list []string) bool {
diff --git a/cc/config/global.go b/cc/config/global.go
index 373fc77f4..32f163d88 100644
--- a/cc/config/global.go
+++ b/cc/config/global.go
@@ -261,7 +261,9 @@ func init() {
pctx.VariableFunc("RECXXPool", remoteexec.EnvOverrideFunc("RBE_CXX_POOL", remoteexec.DefaultPool))
pctx.VariableFunc("RECXXLinksPool", remoteexec.EnvOverrideFunc("RBE_CXX_LINKS_POOL", remoteexec.DefaultPool))
+ pctx.VariableFunc("REClangTidyPool", remoteexec.EnvOverrideFunc("RBE_CLANG_TIDY_POOL", remoteexec.DefaultPool))
pctx.VariableFunc("RECXXLinksExecStrategy", remoteexec.EnvOverrideFunc("RBE_CXX_LINKS_EXEC_STRATEGY", remoteexec.LocalExecStrategy))
+ pctx.VariableFunc("REClangTidyExecStrategy", remoteexec.EnvOverrideFunc("RBE_CLANG_TIDY_EXEC_STRATEGY", remoteexec.LocalExecStrategy))
pctx.VariableFunc("REAbiDumperExecStrategy", remoteexec.EnvOverrideFunc("RBE_ABI_DUMPER_EXEC_STRATEGY", remoteexec.LocalExecStrategy))
pctx.VariableFunc("REAbiLinkerExecStrategy", remoteexec.EnvOverrideFunc("RBE_ABI_LINKER_EXEC_STRATEGY", remoteexec.LocalExecStrategy))
}
diff --git a/cc/config/integer_overflow_blacklist.txt b/cc/config/integer_overflow_blocklist.txt
index 3480c3c08..3480c3c08 100644
--- a/cc/config/integer_overflow_blacklist.txt
+++ b/cc/config/integer_overflow_blocklist.txt
diff --git a/cc/coverage.go b/cc/coverage.go
index c8233247f..aa1fdf6c5 100644
--- a/cc/coverage.go
+++ b/cc/coverage.go
@@ -22,6 +22,8 @@ import (
"android/soong/android"
)
+const profileInstrFlag = "-fprofile-instr-generate=/data/misc/trace/clang-%p-%m.profraw"
+
type CoverageProperties struct {
Native_coverage *bool
@@ -92,7 +94,7 @@ func (cov *coverage) flags(ctx ModuleContext, flags Flags, deps PathDeps) (Flags
// flags that the module may use.
flags.Local.CFlags = append(flags.Local.CFlags, "-Wno-frame-larger-than=", "-O0")
} else if clangCoverage {
- flags.Local.CommonFlags = append(flags.Local.CommonFlags, "-fprofile-instr-generate", "-fcoverage-mapping", "-Wno-pass-failed")
+ flags.Local.CommonFlags = append(flags.Local.CommonFlags, profileInstrFlag, "-fcoverage-mapping", "-Wno-pass-failed")
}
}
@@ -103,10 +105,14 @@ func (cov *coverage) flags(ctx ModuleContext, flags Flags, deps PathDeps) (Flags
// For static libraries, the only thing that changes our object files
// are included whole static libraries, so check to see if any of
// those have coverage enabled.
- ctx.VisitDirectDepsWithTag(wholeStaticDepTag, func(m android.Module) {
- if cc, ok := m.(*Module); ok && cc.coverage != nil {
- if cc.coverage.linkCoverage {
- cov.linkCoverage = true
+ ctx.VisitDirectDeps(func(m android.Module) {
+ if depTag, ok := ctx.OtherModuleDependencyTag(m).(libraryDependencyTag); ok {
+ if depTag.static() && depTag.wholeStatic {
+ if cc, ok := m.(*Module); ok && cc.coverage != nil {
+ if cc.coverage.linkCoverage {
+ cov.linkCoverage = true
+ }
+ }
}
}
})
@@ -139,7 +145,7 @@ func (cov *coverage) flags(ctx ModuleContext, flags Flags, deps PathDeps) (Flags
flags.Local.LdFlags = append(flags.Local.LdFlags, "-Wl,--wrap,getenv")
} else if clangCoverage {
- flags.Local.LdFlags = append(flags.Local.LdFlags, "-fprofile-instr-generate")
+ flags.Local.LdFlags = append(flags.Local.LdFlags, profileInstrFlag)
coverage := ctx.GetDirectDepWithTag(getClangProfileLibraryName(ctx), CoverageDepTag).(*Module)
deps.WholeStaticLibs = append(deps.WholeStaticLibs, coverage.OutputFile().Path())
diff --git a/cc/fuzz.go b/cc/fuzz.go
index 58c1888ad..529541859 100644
--- a/cc/fuzz.go
+++ b/cc/fuzz.go
@@ -402,7 +402,7 @@ func (s *fuzzPackager) GenerateBuildActions(ctx android.SingletonContext) {
command := builder.Command().BuiltTool(ctx, "soong_zip").
Flag("-j").
FlagWithOutput("-o ", corpusZip)
- command.FlagWithRspFileInputList("-l ", fuzzModule.corpus)
+ command.FlagWithRspFileInputList("-r ", fuzzModule.corpus)
files = append(files, fileToZip{corpusZip, ""})
}
diff --git a/cc/gen.go b/cc/gen.go
index b0aadc650..ccc3d0ef9 100644
--- a/cc/gen.go
+++ b/cc/gen.go
@@ -34,9 +34,9 @@ func init() {
var (
lex = pctx.AndroidStaticRule("lex",
blueprint.RuleParams{
- Command: "M4=$m4Cmd $lexCmd -o$out $in",
+ Command: "M4=$m4Cmd $lexCmd $flags -o$out $in",
CommandDeps: []string{"$lexCmd", "$m4Cmd"},
- })
+ }, "flags")
sysprop = pctx.AndroidStaticRule("sysprop",
blueprint.RuleParams{
@@ -153,12 +153,23 @@ func genAidl(ctx android.ModuleContext, rule *android.RuleBuilder, aidlFile andr
}
}
-func genLex(ctx android.ModuleContext, lexFile android.Path, outFile android.ModuleGenPath) {
+type LexProperties struct {
+ // list of module-specific flags that will be used for .l and .ll compiles
+ Flags []string
+}
+
+func genLex(ctx android.ModuleContext, lexFile android.Path, outFile android.ModuleGenPath, props *LexProperties) {
+ var flags []string
+ if props != nil {
+ flags = props.Flags
+ }
+ flagsString := strings.Join(flags[:], " ")
ctx.Build(pctx, android.BuildParams{
Rule: lex,
Description: "lex " + lexFile.Rel(),
Output: outFile,
Input: lexFile,
+ Args: map[string]string{"flags": flagsString},
})
}
@@ -235,11 +246,11 @@ func genSources(ctx android.ModuleContext, srcFiles android.Paths,
case ".l":
cFile := android.GenPathWithExt(ctx, "lex", srcFile, "c")
srcFiles[i] = cFile
- genLex(ctx, srcFile, cFile)
+ genLex(ctx, srcFile, cFile, buildFlags.lex)
case ".ll":
cppFile := android.GenPathWithExt(ctx, "lex", srcFile, "cpp")
srcFiles[i] = cppFile
- genLex(ctx, srcFile, cppFile)
+ genLex(ctx, srcFile, cppFile, buildFlags.lex)
case ".proto":
ccFile, headerFile := genProto(ctx, srcFile, buildFlags)
srcFiles[i] = ccFile
diff --git a/cc/genrule_test.go b/cc/genrule_test.go
index d38cf27f0..a366f765c 100644
--- a/cc/genrule_test.go
+++ b/cc/genrule_test.go
@@ -76,3 +76,42 @@ func TestArchGenruleCmd(t *testing.T) {
t.Errorf(`want arm64 inputs %v, got %v`, expected, gen.Inputs.Strings())
}
}
+
+func TestLibraryGenruleCmd(t *testing.T) {
+ bp := `
+ cc_library {
+ name: "libboth",
+ }
+
+ cc_library_shared {
+ name: "libshared",
+ }
+
+ cc_library_static {
+ name: "libstatic",
+ }
+
+ cc_genrule {
+ name: "gen",
+ tool_files: ["tool"],
+ srcs: [
+ ":libboth",
+ ":libshared",
+ ":libstatic",
+ ],
+ cmd: "$(location tool) $(in) $(out)",
+ out: ["out"],
+ }
+ `
+ ctx := testCc(t, bp)
+
+ gen := ctx.ModuleForTests("gen", "android_arm_armv7-a-neon").Output("out")
+ expected := []string{"libboth.so", "libshared.so", "libstatic.a"}
+ var got []string
+ for _, input := range gen.Inputs {
+ got = append(got, input.Base())
+ }
+ if !reflect.DeepEqual(expected, got) {
+ t.Errorf(`want inputs %v, got %v`, expected, got)
+ }
+}
diff --git a/cc/image.go b/cc/image.go
new file mode 100644
index 000000000..4daed7c00
--- /dev/null
+++ b/cc/image.go
@@ -0,0 +1,348 @@
+// Copyright 2020 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+package cc
+
+// This file contains image variant related things, including image mutator functions, utility
+// functions to determine where a module is installed, etc.
+
+import (
+ "strings"
+
+ "android/soong/android"
+)
+
+var _ android.ImageInterface = (*Module)(nil)
+
+type imageVariantType string
+
+const (
+ coreImageVariant imageVariantType = "core"
+ vendorImageVariant imageVariantType = "vendor"
+ productImageVariant imageVariantType = "product"
+ ramdiskImageVariant imageVariantType = "ramdisk"
+ recoveryImageVariant imageVariantType = "recovery"
+ hostImageVariant imageVariantType = "host"
+)
+
+func (c *Module) getImageVariantType() imageVariantType {
+ if c.Host() {
+ return hostImageVariant
+ } else if c.inVendor() {
+ return vendorImageVariant
+ } else if c.inProduct() {
+ return productImageVariant
+ } else if c.InRamdisk() {
+ return ramdiskImageVariant
+ } else if c.InRecovery() {
+ return recoveryImageVariant
+ } else {
+ return coreImageVariant
+ }
+}
+
+const (
+ // VendorVariationPrefix is the variant prefix used for /vendor code that compiles
+ // against the VNDK.
+ VendorVariationPrefix = "vendor."
+
+ // ProductVariationPrefix is the variant prefix used for /product code that compiles
+ // against the VNDK.
+ ProductVariationPrefix = "product."
+)
+
+func (ctx *moduleContext) ProductSpecific() bool {
+ return ctx.ModuleContext.ProductSpecific() ||
+ (ctx.mod.HasVendorVariant() && ctx.mod.inProduct() && !ctx.mod.IsVndk())
+}
+
+func (ctx *moduleContext) SocSpecific() bool {
+ return ctx.ModuleContext.SocSpecific() ||
+ (ctx.mod.HasVendorVariant() && ctx.mod.inVendor() && !ctx.mod.IsVndk())
+}
+
+func (ctx *moduleContextImpl) inProduct() bool {
+ return ctx.mod.inProduct()
+}
+
+func (ctx *moduleContextImpl) inVendor() bool {
+ return ctx.mod.inVendor()
+}
+
+func (ctx *moduleContextImpl) inRamdisk() bool {
+ return ctx.mod.InRamdisk()
+}
+
+func (ctx *moduleContextImpl) inRecovery() bool {
+ return ctx.mod.InRecovery()
+}
+
+// Returns true only when this module is configured to have core, product and vendor
+// variants.
+func (c *Module) HasVendorVariant() bool {
+ return c.IsVndk() || Bool(c.VendorProperties.Vendor_available)
+}
+
+// Returns true if the module is "product" variant. Usually these modules are installed in /product
+func (c *Module) inProduct() bool {
+ return c.Properties.ImageVariationPrefix == ProductVariationPrefix
+}
+
+// Returns true if the module is "vendor" variant. Usually these modules are installed in /vendor
+func (c *Module) inVendor() bool {
+ return c.Properties.ImageVariationPrefix == VendorVariationPrefix
+}
+
+func (c *Module) InRamdisk() bool {
+ return c.ModuleBase.InRamdisk() || c.ModuleBase.InstallInRamdisk()
+}
+
+func (c *Module) InRecovery() bool {
+ return c.ModuleBase.InRecovery() || c.ModuleBase.InstallInRecovery()
+}
+
+func (c *Module) OnlyInRamdisk() bool {
+ return c.ModuleBase.InstallInRamdisk()
+}
+
+func (c *Module) OnlyInRecovery() bool {
+ return c.ModuleBase.InstallInRecovery()
+}
+
+func (m *Module) ImageMutatorBegin(mctx android.BaseModuleContext) {
+ // Validation check
+ vendorSpecific := mctx.SocSpecific() || mctx.DeviceSpecific()
+ productSpecific := mctx.ProductSpecific()
+
+ if m.VendorProperties.Vendor_available != nil && vendorSpecific {
+ mctx.PropertyErrorf("vendor_available",
+ "doesn't make sense at the same time as `vendor: true`, `proprietary: true`, or `device_specific:true`")
+ }
+
+ if vndkdep := m.vndkdep; vndkdep != nil {
+ if vndkdep.isVndk() {
+ if vendorSpecific || productSpecific {
+ if !vndkdep.isVndkExt() {
+ mctx.PropertyErrorf("vndk",
+ "must set `extends: \"...\"` to vndk extension")
+ } else if m.VendorProperties.Vendor_available != nil {
+ mctx.PropertyErrorf("vendor_available",
+ "must not set at the same time as `vndk: {extends: \"...\"}`")
+ }
+ } else {
+ if vndkdep.isVndkExt() {
+ mctx.PropertyErrorf("vndk",
+ "must set `vendor: true` or `product_specific: true` to set `extends: %q`",
+ m.getVndkExtendsModuleName())
+ }
+ if m.VendorProperties.Vendor_available == nil {
+ mctx.PropertyErrorf("vndk",
+ "vendor_available must be set to either true or false when `vndk: {enabled: true}`")
+ }
+ }
+ } else {
+ if vndkdep.isVndkSp() {
+ mctx.PropertyErrorf("vndk",
+ "must set `enabled: true` to set `support_system_process: true`")
+ }
+ if vndkdep.isVndkExt() {
+ mctx.PropertyErrorf("vndk",
+ "must set `enabled: true` to set `extends: %q`",
+ m.getVndkExtendsModuleName())
+ }
+ }
+ }
+
+ var coreVariantNeeded bool = false
+ var ramdiskVariantNeeded bool = false
+ var recoveryVariantNeeded bool = false
+
+ var vendorVariants []string
+ var productVariants []string
+
+ platformVndkVersion := mctx.DeviceConfig().PlatformVndkVersion()
+ boardVndkVersion := mctx.DeviceConfig().VndkVersion()
+ productVndkVersion := mctx.DeviceConfig().ProductVndkVersion()
+ if boardVndkVersion == "current" {
+ boardVndkVersion = platformVndkVersion
+ }
+ if productVndkVersion == "current" {
+ productVndkVersion = platformVndkVersion
+ }
+
+ if boardVndkVersion == "" {
+ // If the device isn't compiling against the VNDK, we always
+ // use the core mode.
+ coreVariantNeeded = true
+ } else if _, ok := m.linker.(*llndkStubDecorator); ok {
+ // LL-NDK stubs only exist in the vendor and product variants,
+ // since the real libraries will be used in the core variant.
+ vendorVariants = append(vendorVariants,
+ platformVndkVersion,
+ boardVndkVersion,
+ )
+ productVariants = append(productVariants,
+ platformVndkVersion,
+ productVndkVersion,
+ )
+ } else if _, ok := m.linker.(*llndkHeadersDecorator); ok {
+ // ... and LL-NDK headers as well
+ vendorVariants = append(vendorVariants,
+ platformVndkVersion,
+ boardVndkVersion,
+ )
+ productVariants = append(productVariants,
+ platformVndkVersion,
+ productVndkVersion,
+ )
+ } else if m.isSnapshotPrebuilt() {
+ // Make vendor variants only for the versions in BOARD_VNDK_VERSION and
+ // PRODUCT_EXTRA_VNDK_VERSIONS.
+ if snapshot, ok := m.linker.(interface {
+ version() string
+ }); ok {
+ vendorVariants = append(vendorVariants, snapshot.version())
+ } else {
+ mctx.ModuleErrorf("version is unknown for snapshot prebuilt")
+ }
+ } else if m.HasVendorVariant() && !m.isVndkExt() {
+ // This will be available in /system, /vendor and /product
+ // or a /system directory that is available to vendor and product.
+ coreVariantNeeded = true
+
+ // We assume that modules under proprietary paths are compatible for
+ // BOARD_VNDK_VERSION. The other modules are regarded as AOSP, or
+ // PLATFORM_VNDK_VERSION.
+ if isVendorProprietaryPath(mctx.ModuleDir()) {
+ vendorVariants = append(vendorVariants, boardVndkVersion)
+ } else {
+ vendorVariants = append(vendorVariants, platformVndkVersion)
+ }
+
+ // vendor_available modules are also available to /product.
+ productVariants = append(productVariants, platformVndkVersion)
+ // VNDK is always PLATFORM_VNDK_VERSION
+ if !m.IsVndk() {
+ productVariants = append(productVariants, productVndkVersion)
+ }
+ } else if vendorSpecific && String(m.Properties.Sdk_version) == "" {
+ // This will be available in /vendor (or /odm) only
+
+ // kernel_headers is a special module type whose exported headers
+ // are coming from DeviceKernelHeaders() which is always vendor
+ // dependent. They'll always have both vendor variants.
+ // For other modules, we assume that modules under proprietary
+ // paths are compatible for BOARD_VNDK_VERSION. The other modules
+ // are regarded as AOSP, which is PLATFORM_VNDK_VERSION.
+ if _, ok := m.linker.(*kernelHeadersDecorator); ok {
+ vendorVariants = append(vendorVariants,
+ platformVndkVersion,
+ boardVndkVersion,
+ )
+ } else if isVendorProprietaryPath(mctx.ModuleDir()) {
+ vendorVariants = append(vendorVariants, boardVndkVersion)
+ } else {
+ vendorVariants = append(vendorVariants, platformVndkVersion)
+ }
+ } else {
+ // This is either in /system (or similar: /data), or is a
+ // modules built with the NDK. Modules built with the NDK
+ // will be restricted using the existing link type checks.
+ coreVariantNeeded = true
+ }
+
+ if boardVndkVersion != "" && productVndkVersion != "" {
+ if coreVariantNeeded && productSpecific && String(m.Properties.Sdk_version) == "" {
+ // The module has "product_specific: true" that does not create core variant.
+ coreVariantNeeded = false
+ productVariants = append(productVariants, productVndkVersion)
+ }
+ } else {
+ // Unless PRODUCT_PRODUCT_VNDK_VERSION is set, product partition has no
+ // restriction to use system libs.
+ // No product variants defined in this case.
+ productVariants = []string{}
+ }
+
+ if Bool(m.Properties.Ramdisk_available) {
+ ramdiskVariantNeeded = true
+ }
+
+ if m.ModuleBase.InstallInRamdisk() {
+ ramdiskVariantNeeded = true
+ coreVariantNeeded = false
+ }
+
+ if Bool(m.Properties.Recovery_available) {
+ recoveryVariantNeeded = true
+ }
+
+ if m.ModuleBase.InstallInRecovery() {
+ recoveryVariantNeeded = true
+ coreVariantNeeded = false
+ }
+
+ for _, variant := range android.FirstUniqueStrings(vendorVariants) {
+ m.Properties.ExtraVariants = append(m.Properties.ExtraVariants, VendorVariationPrefix+variant)
+ }
+
+ for _, variant := range android.FirstUniqueStrings(productVariants) {
+ m.Properties.ExtraVariants = append(m.Properties.ExtraVariants, ProductVariationPrefix+variant)
+ }
+
+ m.Properties.RamdiskVariantNeeded = ramdiskVariantNeeded
+ m.Properties.RecoveryVariantNeeded = recoveryVariantNeeded
+ m.Properties.CoreVariantNeeded = coreVariantNeeded
+}
+
+func (c *Module) CoreVariantNeeded(ctx android.BaseModuleContext) bool {
+ return c.Properties.CoreVariantNeeded
+}
+
+func (c *Module) RamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
+ return c.Properties.RamdiskVariantNeeded
+}
+
+func (c *Module) RecoveryVariantNeeded(ctx android.BaseModuleContext) bool {
+ return c.Properties.RecoveryVariantNeeded
+}
+
+func (c *Module) ExtraImageVariations(ctx android.BaseModuleContext) []string {
+ return c.Properties.ExtraVariants
+}
+
+func (c *Module) SetImageVariation(ctx android.BaseModuleContext, variant string, module android.Module) {
+ m := module.(*Module)
+ if variant == android.RamdiskVariation {
+ m.MakeAsPlatform()
+ } else if variant == android.RecoveryVariation {
+ m.MakeAsPlatform()
+ squashRecoverySrcs(m)
+ } else if strings.HasPrefix(variant, VendorVariationPrefix) {
+ m.Properties.ImageVariationPrefix = VendorVariationPrefix
+ m.Properties.VndkVersion = strings.TrimPrefix(variant, VendorVariationPrefix)
+ squashVendorSrcs(m)
+
+ // Makefile shouldn't know vendor modules other than BOARD_VNDK_VERSION.
+ // Hide other vendor variants to avoid collision.
+ vndkVersion := ctx.DeviceConfig().VndkVersion()
+ if vndkVersion != "current" && vndkVersion != "" && vndkVersion != m.Properties.VndkVersion {
+ m.Properties.HideFromMake = true
+ m.SkipInstall()
+ }
+ } else if strings.HasPrefix(variant, ProductVariationPrefix) {
+ m.Properties.ImageVariationPrefix = ProductVariationPrefix
+ m.Properties.VndkVersion = strings.TrimPrefix(variant, ProductVariationPrefix)
+ squashVendorSrcs(m)
+ }
+}
diff --git a/cc/installer.go b/cc/installer.go
index 0b4a68cc8..e551c63e2 100644
--- a/cc/installer.go
+++ b/cc/installer.go
@@ -107,6 +107,6 @@ func (installer *baseInstaller) relativeInstallPath() string {
return String(installer.Properties.Relative_install_path)
}
-func (installer *baseInstaller) skipInstall(mod *Module) {
- mod.ModuleBase.SkipInstall()
+func (installer *baseInstaller) makeUninstallable(mod *Module) {
+ mod.ModuleBase.MakeUninstallable()
}
diff --git a/cc/library.go b/cc/library.go
index 98f4d48d6..92853b5d3 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -28,7 +28,6 @@ import (
"android/soong/android"
"android/soong/cc/config"
- "android/soong/genrule"
)
type LibraryProperties struct {
@@ -337,7 +336,7 @@ type libraryDecorator struct {
tocFile android.OptionalPath
flagExporter
- stripper
+ stripper Stripper
// If we're used as a whole_static_lib, our missing dependencies need
// to be given
@@ -801,21 +800,8 @@ func (library *libraryDecorator) linkerDeps(ctx DepsContext, deps Deps) Deps {
deps.ReexportStaticLibHeaders = append(deps.ReexportStaticLibHeaders, library.StaticProperties.Static.Export_static_lib_headers...)
} else if library.shared() {
if ctx.toolchain().Bionic() && !Bool(library.baseLinker.Properties.Nocrt) {
- if !ctx.useSdk() {
- deps.CrtBegin = "crtbegin_so"
- deps.CrtEnd = "crtend_so"
- } else {
- // TODO(danalbert): Add generation of crt objects.
- // For `sdk_version: "current"`, we don't actually have a
- // freshly generated set of CRT objects. Use the last stable
- // version.
- version := ctx.sdkVersion()
- if version == "current" {
- version = getCurrentNdkPrebuiltVersion(ctx)
- }
- deps.CrtBegin = "ndk_crtbegin_so." + version
- deps.CrtEnd = "ndk_crtend_so." + version
- }
+ deps.CrtBegin = "crtbegin_so"
+ deps.CrtEnd = "crtend_so"
}
deps.WholeStaticLibs = append(deps.WholeStaticLibs, library.SharedProperties.Shared.Whole_static_libs...)
deps.StaticLibs = append(deps.StaticLibs, library.SharedProperties.Shared.Static_libs...)
@@ -969,13 +955,14 @@ func (library *libraryDecorator) linkShared(ctx ModuleContext,
library.tocFile = android.OptionalPathForPath(tocFile)
TransformSharedObjectToToc(ctx, outputFile, tocFile, builderFlags)
- if library.stripper.needsStrip(ctx) {
+ stripFlags := flagsToStripFlags(flags)
+ if library.stripper.NeedsStrip(ctx) {
if ctx.Darwin() {
- builderFlags.stripUseGnuStrip = true
+ stripFlags.StripUseGnuStrip = true
}
strippedOutputFile := outputFile
outputFile = android.PathForModuleOut(ctx, "unstripped", fileName)
- library.stripper.stripExecutableOrSharedLib(ctx, outputFile, strippedOutputFile, builderFlags)
+ library.stripper.StripExecutableOrSharedLib(ctx, outputFile, strippedOutputFile, stripFlags)
}
library.unstrippedOutputFile = outputFile
@@ -990,10 +977,10 @@ func (library *libraryDecorator) linkShared(ctx ModuleContext,
versionedOutputFile := android.PathForModuleOut(ctx, "versioned", fileName)
library.distFile = versionedOutputFile
- if library.stripper.needsStrip(ctx) {
+ if library.stripper.NeedsStrip(ctx) {
out := android.PathForModuleOut(ctx, "versioned-stripped", fileName)
library.distFile = out
- library.stripper.stripExecutableOrSharedLib(ctx, versionedOutputFile, out, builderFlags)
+ library.stripper.StripExecutableOrSharedLib(ctx, versionedOutputFile, out, stripFlags)
}
library.injectVersionSymbol(ctx, outputFile, versionedOutputFile)
@@ -1041,6 +1028,10 @@ func (library *libraryDecorator) unstrippedOutputFilePath() android.Path {
return library.unstrippedOutputFile
}
+func (library *libraryDecorator) disableStripping() {
+ library.stripper.StripProperties.Strip.None = BoolPtr(true)
+}
+
func (library *libraryDecorator) nativeCoverage() bool {
if library.header() || library.buildStubs() {
return false
@@ -1365,16 +1356,15 @@ func (library *libraryDecorator) availableFor(what string) bool {
return android.CheckAvailableForApex(what, list)
}
-func (library *libraryDecorator) skipInstall(mod *Module) {
+func (library *libraryDecorator) makeUninstallable(mod *Module) {
if library.static() && library.buildStatic() && !library.buildStubs() {
- // If we're asked to skip installation of a static library (in particular
- // when it's not //apex_available:platform) we still want an AndroidMk entry
- // for it to ensure we get the relevant NOTICE file targets (cf.
- // notice_files.mk) that other libraries might depend on. AndroidMkEntries
- // always sets LOCAL_UNINSTALLABLE_MODULE for these entries.
+ // If we're asked to make a static library uninstallable we don't do
+ // anything since AndroidMkEntries always sets LOCAL_UNINSTALLABLE_MODULE
+ // for these entries. This is done to still get the make targets for NOTICE
+ // files from notice_files.mk, which other libraries might depend on.
return
}
- mod.ModuleBase.SkipInstall()
+ mod.ModuleBase.MakeUninstallable()
}
var versioningMacroNamesListKey = android.NewOnceKey("versioningMacroNamesList")
@@ -1470,6 +1460,12 @@ func LinkageMutator(mctx android.BottomUpMutatorContext) {
static.linker.(prebuiltLibraryInterface).setStatic()
shared.linker.(prebuiltLibraryInterface).setShared()
+ if library.buildShared() {
+ mctx.AliasVariation("shared")
+ } else if library.buildStatic() {
+ mctx.AliasVariation("static")
+ }
+
if !library.buildStatic() {
static.linker.(prebuiltLibraryInterface).disablePrebuilt()
}
@@ -1501,18 +1497,22 @@ func LinkageMutator(mctx android.BottomUpMutatorContext) {
if _, ok := library.(*Module); ok {
reuseStaticLibrary(mctx, static.(*Module), shared.(*Module))
}
+ mctx.AliasVariation("shared")
} else if library.BuildStaticVariant() {
variations := append([]string{"static"}, variations...)
modules := mctx.CreateLocalVariations(variations...)
modules[0].(LinkableInterface).SetStatic()
+ mctx.AliasVariation("static")
} else if library.BuildSharedVariant() {
variations := append([]string{"shared"}, variations...)
modules := mctx.CreateLocalVariations(variations...)
modules[0].(LinkableInterface).SetShared()
+ mctx.AliasVariation("shared")
} else if len(variations) > 0 {
mctx.CreateLocalVariations(variations...)
+ mctx.AliasVariation(variations[0])
}
}
}
@@ -1559,13 +1559,14 @@ func createVersionVariations(mctx android.BottomUpMutatorContext, versions []str
// "" is for the non-stubs variant
versions = append([]string{""}, versions...)
- modules := mctx.CreateVariations(versions...)
+ modules := mctx.CreateLocalVariations(versions...)
for i, m := range modules {
if versions[i] != "" {
m.(LinkableInterface).SetBuildStubs()
m.(LinkableInterface).SetStubsVersions(versions[i])
}
}
+ mctx.AliasVariation("")
}
func VersionVariantAvailable(module interface {
@@ -1600,7 +1601,7 @@ func VersionMutator(mctx android.BottomUpMutatorContext) {
if c, ok := library.(*Module); ok && c.IsStubs() {
stubsVersionsLock.Lock()
defer stubsVersionsLock.Unlock()
- // For LLNDK llndk_library, we borrow vstubs.ersions from its implementation library.
+ // For LLNDK llndk_library, we borrow stubs.versions from its implementation library.
// Since llndk_library has dependency to its implementation library,
// we can safely access stubsVersionsFor() with its baseModuleName.
versions := stubsVersionsFor(mctx.Config())[c.BaseModuleName()]
@@ -1611,17 +1612,10 @@ func VersionMutator(mctx android.BottomUpMutatorContext) {
return
}
- mctx.CreateVariations("")
+ mctx.CreateLocalVariations("")
+ mctx.AliasVariation("")
return
}
- if genrule, ok := mctx.Module().(*genrule.Module); ok {
- if _, ok := genrule.Extra.(*GenruleExtraProperties); ok {
- if VersionVariantAvailable(genrule) {
- mctx.CreateVariations("")
- return
- }
- }
- }
}
// maybeInjectBoringSSLHash adds a rule to run bssl_inject_hash on the output file if the module has the
@@ -1633,8 +1627,7 @@ func maybeInjectBoringSSLHash(ctx android.ModuleContext, outputFile android.Modu
// TODO(b/137267623): Remove this in favor of a cc_genrule when they support operating on shared libraries.
injectBoringSSLHash := Bool(inject)
ctx.VisitDirectDeps(func(dep android.Module) {
- tag := ctx.OtherModuleDependencyTag(dep)
- if tag == StaticDepTag || tag == staticExportDepTag || tag == wholeStaticDepTag || tag == lateStaticDepTag {
+ if tag, ok := ctx.OtherModuleDependencyTag(dep).(libraryDependencyTag); ok && tag.static() {
if cc, ok := dep.(*Module); ok {
if library, ok := cc.linker.(*libraryDecorator); ok {
if Bool(library.Properties.Inject_bssl_hash) {
diff --git a/cc/library_headers.go b/cc/library_headers.go
index b7ab3907c..8b3dbeb8b 100644
--- a/cc/library_headers.go
+++ b/cc/library_headers.go
@@ -25,8 +25,9 @@ func init() {
var headersLibrarySdkMemberType = &librarySdkMemberType{
SdkMemberTypeBase: android.SdkMemberTypeBase{
- PropertyName: "native_header_libs",
- SupportsSdk: true,
+ PropertyName: "native_header_libs",
+ SupportsSdk: true,
+ HostOsDependent: true,
},
prebuiltModuleType: "cc_prebuilt_library_headers",
noOutputFiles: true,
diff --git a/cc/library_sdk_member.go b/cc/library_sdk_member.go
index 4b9eb302c..9328a2596 100644
--- a/cc/library_sdk_member.go
+++ b/cc/library_sdk_member.go
@@ -27,8 +27,9 @@ import (
var sharedLibrarySdkMemberType = &librarySdkMemberType{
SdkMemberTypeBase: android.SdkMemberTypeBase{
- PropertyName: "native_shared_libs",
- SupportsSdk: true,
+ PropertyName: "native_shared_libs",
+ SupportsSdk: true,
+ HostOsDependent: true,
},
prebuiltModuleType: "cc_prebuilt_library_shared",
linkTypes: []string{"shared"},
@@ -36,8 +37,9 @@ var sharedLibrarySdkMemberType = &librarySdkMemberType{
var staticLibrarySdkMemberType = &librarySdkMemberType{
SdkMemberTypeBase: android.SdkMemberTypeBase{
- PropertyName: "native_static_libs",
- SupportsSdk: true,
+ PropertyName: "native_static_libs",
+ SupportsSdk: true,
+ HostOsDependent: true,
},
prebuiltModuleType: "cc_prebuilt_library_static",
linkTypes: []string{"static"},
@@ -45,8 +47,9 @@ var staticLibrarySdkMemberType = &librarySdkMemberType{
var staticAndSharedLibrarySdkMemberType = &librarySdkMemberType{
SdkMemberTypeBase: android.SdkMemberTypeBase{
- PropertyName: "native_libs",
- SupportsSdk: true,
+ PropertyName: "native_libs",
+ SupportsSdk: true,
+ HostOsDependent: true,
},
prebuiltModuleType: "cc_prebuilt_library",
linkTypes: []string{"static", "shared"},
@@ -209,6 +212,11 @@ var includeDirProperties = []includeDirsProperty{
// Add properties that may, or may not, be arch specific.
func addPossiblyArchSpecificProperties(sdkModuleContext android.ModuleContext, builder android.SnapshotBuilder, libInfo *nativeLibInfoProperties, outputProperties android.BpPropertySet) {
+ if libInfo.SanitizeNever {
+ sanitizeSet := outputProperties.AddPropertySet("sanitize")
+ sanitizeSet.AddProperty("never", true)
+ }
+
// Copy the generated library to the snapshot and add a reference to it in the .bp module.
if libInfo.outputFile != nil {
nativeLibraryPath := nativeLibraryPathFor(libInfo)
@@ -356,6 +364,9 @@ type nativeLibInfoProperties struct {
// not vary by arch so cannot be android specific.
StubsVersion string `sdk:"ignored-on-host"`
+ // Value of SanitizeProperties.Sanitize.Never. Needs to be propagated for CRT objects.
+ SanitizeNever bool `android:"arch_variant"`
+
// outputFile is not exported as it is always arch specific.
outputFile android.Path
}
@@ -402,6 +413,10 @@ func (p *nativeLibInfoProperties) PopulateFromVariant(ctx android.SdkMemberConte
if ccModule.HasStubsVariants() {
p.StubsVersion = ccModule.StubsVersion()
}
+
+ if ccModule.sanitize != nil && proptools.Bool(ccModule.sanitize.Properties.Sanitize.Never) {
+ p.SanitizeNever = true
+ }
}
func getRequiredMemberOutputFile(ctx android.SdkMemberContext, ccModule *Module) android.Path {
diff --git a/cc/linkable.go b/cc/linkable.go
index 66b1c3fea..4c8416347 100644
--- a/cc/linkable.go
+++ b/cc/linkable.go
@@ -1,9 +1,9 @@
package cc
import (
- "github.com/google/blueprint"
-
"android/soong/android"
+
+ "github.com/google/blueprint"
)
type LinkableInterface interface {
@@ -63,27 +63,16 @@ type LinkableInterface interface {
StubDecorator() bool
}
-type DependencyTag struct {
- blueprint.BaseDependencyTag
- Name string
- Library bool
- Shared bool
-
- ReexportFlags bool
-
- ExplicitlyVersioned bool
-
- FromStatic bool
-}
-
var (
- SharedDepTag = DependencyTag{Name: "shared", Library: true, Shared: true}
- StaticDepTag = DependencyTag{Name: "static", Library: true}
+ CrtBeginDepTag = dependencyTag{name: "crtbegin"}
+ CrtEndDepTag = dependencyTag{name: "crtend"}
+ CoverageDepTag = dependencyTag{name: "coverage"}
+)
- // Same as SharedDepTag, but from a static lib
- SharedFromStaticDepTag = DependencyTag{Name: "shared from static", Library: true, Shared: true, FromStatic: true}
+func SharedDepTag() blueprint.DependencyTag {
+ return libraryDependencyTag{Kind: sharedLibraryDependency}
+}
- CrtBeginDepTag = DependencyTag{Name: "crtbegin"}
- CrtEndDepTag = DependencyTag{Name: "crtend"}
- CoverageDepTag = DependencyTag{Name: "coverage"}
-)
+func StaticDepTag() blueprint.DependencyTag {
+ return libraryDependencyTag{Kind: staticLibraryDependency}
+}
diff --git a/cc/llndk_library.go b/cc/llndk_library.go
index 71c92042a..b3f9d6177 100644
--- a/cc/llndk_library.go
+++ b/cc/llndk_library.go
@@ -179,7 +179,7 @@ func NewLLndkStubLibrary() *Module {
library.BuildOnlyShared()
module.stl = nil
module.sanitize = nil
- library.StripProperties.Strip.None = BoolPtr(true)
+ library.disableStripping()
stub := &llndkStubDecorator{
libraryDecorator: library,
diff --git a/cc/lto.go b/cc/lto.go
index 4489fc7dd..9868cdfb9 100644
--- a/cc/lto.go
+++ b/cc/lto.go
@@ -148,24 +148,31 @@ func ltoDepsMutator(mctx android.TopDownMutatorContext) {
mctx.WalkDeps(func(dep android.Module, parent android.Module) bool {
tag := mctx.OtherModuleDependencyTag(dep)
- switch tag {
- case StaticDepTag, staticExportDepTag, lateStaticDepTag, wholeStaticDepTag, objDepTag, reuseObjTag:
- if dep, ok := dep.(*Module); ok && dep.lto != nil &&
- !dep.lto.Disabled() {
- if full && !Bool(dep.lto.Properties.Lto.Full) {
- dep.lto.Properties.FullDep = true
- }
- if thin && !Bool(dep.lto.Properties.Lto.Thin) {
- dep.lto.Properties.ThinDep = true
- }
+ libTag, isLibTag := tag.(libraryDependencyTag)
+
+ // Do not recurse down non-static dependencies
+ if isLibTag {
+ if !libTag.static() {
+ return false
}
+ } else {
+ if tag != objDepTag && tag != reuseObjTag {
+ return false
+ }
+ }
- // Recursively walk static dependencies
- return true
+ if dep, ok := dep.(*Module); ok && dep.lto != nil &&
+ !dep.lto.Disabled() {
+ if full && !Bool(dep.lto.Properties.Lto.Full) {
+ dep.lto.Properties.FullDep = true
+ }
+ if thin && !Bool(dep.lto.Properties.Lto.Thin) {
+ dep.lto.Properties.ThinDep = true
+ }
}
- // Do not recurse down non-static dependencies
- return false
+ // Recursively walk static dependencies
+ return true
})
}
}
diff --git a/cc/makevars.go b/cc/makevars.go
index 968eeb5f4..dcfd6d8ef 100644
--- a/cc/makevars.go
+++ b/cc/makevars.go
@@ -148,8 +148,6 @@ func makeVarsProvider(ctx android.MakeVarsContext) {
ctx.Strict("AIDL_CPP", "${aidlCmd}")
ctx.Strict("ALLOWED_MANUAL_INTERFACE_PATHS", strings.Join(allowedManualInterfacePaths, " "))
- ctx.Strict("M4", "${m4Cmd}")
-
ctx.Strict("RS_GLOBAL_INCLUDES", "${config.RsGlobalIncludes}")
ctx.Strict("SOONG_STRIP_PATH", "${stripPath}")
diff --git a/cc/ndk_library.go b/cc/ndk_library.go
index 4578fd329..fe3efc01e 100644
--- a/cc/ndk_library.go
+++ b/cc/ndk_library.go
@@ -110,6 +110,10 @@ func intMax(a int, b int) int {
func normalizeNdkApiLevel(ctx android.BaseModuleContext, apiLevel string,
arch android.Arch) (string, error) {
+ if apiLevel == "" {
+ panic("empty apiLevel not allowed")
+ }
+
if apiLevel == "current" {
return apiLevel, nil
}
@@ -136,7 +140,8 @@ func normalizeNdkApiLevel(ctx android.BaseModuleContext, apiLevel string,
// supported version here instead.
version, err := strconv.Atoi(apiLevel)
if err != nil {
- return "", fmt.Errorf("API level must be an integer (is %q)", apiLevel)
+ // Non-integer API levels are codenames.
+ return apiLevel, nil
}
version = intMax(version, minVersion)
@@ -182,40 +187,61 @@ func shouldUseVersionScript(ctx android.BaseModuleContext, stub *stubDecorator)
return version >= unversionedUntil, nil
}
-func generateStubApiVariants(mctx android.BottomUpMutatorContext, c *stubDecorator) {
- platformVersion := mctx.Config().PlatformSdkVersionInt()
+func generatePerApiVariants(ctx android.BottomUpMutatorContext, m *Module,
+ propName string, propValue string, perSplit func(*Module, string)) {
+ platformVersion := ctx.Config().PlatformSdkVersionInt()
- firstSupportedVersion, err := normalizeNdkApiLevel(mctx, String(c.properties.First_version),
- mctx.Arch())
+ firstSupportedVersion, err := normalizeNdkApiLevel(ctx, propValue,
+ ctx.Arch())
if err != nil {
- mctx.PropertyErrorf("first_version", err.Error())
+ ctx.PropertyErrorf(propName, err.Error())
}
- firstGenVersion, err := getFirstGeneratedVersion(firstSupportedVersion, platformVersion)
+ firstGenVersion, err := getFirstGeneratedVersion(firstSupportedVersion,
+ platformVersion)
if err != nil {
// In theory this is impossible because we've already run this through
// normalizeNdkApiLevel above.
- mctx.PropertyErrorf("first_version", err.Error())
+ ctx.PropertyErrorf(propName, err.Error())
}
var versionStrs []string
for version := firstGenVersion; version <= platformVersion; version++ {
versionStrs = append(versionStrs, strconv.Itoa(version))
}
- versionStrs = append(versionStrs, mctx.Config().PlatformVersionActiveCodenames()...)
+ versionStrs = append(versionStrs, ctx.Config().PlatformVersionActiveCodenames()...)
versionStrs = append(versionStrs, "current")
- modules := mctx.CreateVariations(versionStrs...)
+ modules := ctx.CreateVariations(versionStrs...)
for i, module := range modules {
- module.(*Module).compiler.(*stubDecorator).properties.ApiLevel = versionStrs[i]
+ perSplit(module.(*Module), versionStrs[i])
}
}
-func NdkApiMutator(mctx android.BottomUpMutatorContext) {
- if m, ok := mctx.Module().(*Module); ok {
+func NdkApiMutator(ctx android.BottomUpMutatorContext) {
+ if m, ok := ctx.Module().(*Module); ok {
if m.Enabled() {
if compiler, ok := m.compiler.(*stubDecorator); ok {
- generateStubApiVariants(mctx, compiler)
+ if ctx.Os() != android.Android {
+ // These modules are always android.DeviceEnabled only, but
+ // those include Fuchsia devices, which we don't support.
+ ctx.Module().Disable()
+ return
+ }
+ generatePerApiVariants(ctx, m, "first_version",
+ String(compiler.properties.First_version),
+ func(m *Module, version string) {
+ m.compiler.(*stubDecorator).properties.ApiLevel =
+ version
+ })
+ } else if m.SplitPerApiLevel() && m.IsSdkVariant() {
+ if ctx.Os() != android.Android {
+ return
+ }
+ generatePerApiVariants(ctx, m, "min_sdk_version",
+ m.MinSdkVersion(), func(m *Module, version string) {
+ m.Properties.Sdk_version = &version
+ })
}
}
}
@@ -379,7 +405,7 @@ func newStubLibrary() *Module {
library.BuildOnlyShared()
module.stl = nil
module.sanitize = nil
- library.StripProperties.Strip.None = BoolPtr(true)
+ library.disableStripping()
stub := &stubDecorator{
libraryDecorator: library,
@@ -396,8 +422,8 @@ func newStubLibrary() *Module {
return module
}
-// ndk_library creates a stub library that exposes dummy implementation
-// of functions and variables for use at build time only.
+// ndk_library creates a library that exposes a stub implementation of functions
+// and variables for use at build time only.
func NdkLibraryFactory() android.Module {
module := newStubLibrary()
android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibBoth)
diff --git a/cc/object.go b/cc/object.go
index 15a529e85..778d131ba 100644
--- a/cc/object.go
+++ b/cc/object.go
@@ -55,6 +55,10 @@ type ObjectLinkerProperties struct {
// if set, the path to a linker script to pass to ld -r when combining multiple object files.
Linker_script *string `android:"path,arch_variant"`
+
+ // Indicates that this module is a CRT object. CRT objects will be split
+ // into a variant per-API level between min_sdk_version and current.
+ Crt *bool
}
func newObject() *Module {
@@ -162,3 +166,7 @@ func (object *objectLinker) coverageOutputFilePath() android.OptionalPath {
func (object *objectLinker) object() bool {
return true
}
+
+func (object *objectLinker) isCrt() bool {
+ return Bool(object.Properties.Crt)
+}
diff --git a/cc/pgo.go b/cc/pgo.go
index 9298e7a74..674e1bbf1 100644
--- a/cc/pgo.go
+++ b/cc/pgo.go
@@ -199,8 +199,8 @@ func (props *PgoProperties) isPGO(ctx BaseModuleContext) bool {
return false
}
- // If at least one property exists, validate that all properties exist
- if !profileKindPresent || !filePresent || !benchmarksPresent {
+ // profileKindPresent and filePresent are mandatory properties.
+ if !profileKindPresent || !filePresent {
var missing []string
if !profileKindPresent {
missing = append(missing, "profile kind (either \"instrumentation\" or \"sampling\" property)")
@@ -208,13 +208,15 @@ func (props *PgoProperties) isPGO(ctx BaseModuleContext) bool {
if !filePresent {
missing = append(missing, "profile_file property")
}
- if !benchmarksPresent {
- missing = append(missing, "non-empty benchmarks property")
- }
missingProps := strings.Join(missing, ", ")
ctx.ModuleErrorf("PGO specification is missing properties: " + missingProps)
}
+ // Benchmark property is mandatory for instrumentation PGO.
+ if isInstrumentation && !benchmarksPresent {
+ ctx.ModuleErrorf("Instrumentation PGO specification is missing benchmark property")
+ }
+
if isSampling && isInstrumentation {
ctx.PropertyErrorf("pgo", "Exactly one of \"instrumentation\" and \"sampling\" properties must be set")
}
@@ -288,15 +290,17 @@ func (pgo *pgo) flags(ctx ModuleContext, flags Flags) Flags {
// Add flags to profile this module based on its profile_kind
if props.ShouldProfileModule && props.isInstrumentation() {
- return props.addInstrumentationProfileGatherFlags(ctx, flags)
+ props.addInstrumentationProfileGatherFlags(ctx, flags)
+ // Instrumentation PGO use and gather flags cannot coexist.
+ return flags
} else if props.ShouldProfileModule && props.isSampling() {
- return props.addSamplingProfileGatherFlags(ctx, flags)
+ props.addSamplingProfileGatherFlags(ctx, flags)
} else if ctx.DeviceConfig().SamplingPGO() {
- return props.addSamplingProfileGatherFlags(ctx, flags)
+ props.addSamplingProfileGatherFlags(ctx, flags)
}
if !ctx.Config().IsEnvTrue("ANDROID_PGO_NO_PROFILE_USE") {
- return props.addProfileUseFlags(ctx, flags)
+ props.addProfileUseFlags(ctx, flags)
}
return flags
diff --git a/cc/prebuilt.go b/cc/prebuilt.go
index 0751f1ca6..3af65d654 100644
--- a/cc/prebuilt.go
+++ b/cc/prebuilt.go
@@ -26,6 +26,7 @@ func RegisterPrebuiltBuildComponents(ctx android.RegistrationContext) {
ctx.RegisterModuleType("cc_prebuilt_library", PrebuiltLibraryFactory)
ctx.RegisterModuleType("cc_prebuilt_library_shared", PrebuiltSharedLibraryFactory)
ctx.RegisterModuleType("cc_prebuilt_library_static", PrebuiltStaticLibraryFactory)
+ ctx.RegisterModuleType("cc_prebuilt_test_library_shared", PrebuiltSharedTestLibraryFactory)
ctx.RegisterModuleType("cc_prebuilt_object", prebuiltObjectFactory)
ctx.RegisterModuleType("cc_prebuilt_binary", prebuiltBinaryFactory)
}
@@ -124,9 +125,10 @@ func (p *prebuiltLibraryLinker) link(ctx ModuleContext,
outputFile := android.PathForModuleOut(ctx, libName)
var implicits android.Paths
- if p.needsStrip(ctx) {
+ if p.stripper.NeedsStrip(ctx) {
+ stripFlags := flagsToStripFlags(flags)
stripped := android.PathForModuleOut(ctx, "stripped", libName)
- p.stripExecutableOrSharedLib(ctx, in, stripped, builderFlags)
+ p.stripper.StripExecutableOrSharedLib(ctx, in, stripped, stripFlags)
in = stripped
}
@@ -198,10 +200,6 @@ func (p *prebuiltLibraryLinker) disablePrebuilt() {
p.properties.Srcs = nil
}
-func (p *prebuiltLibraryLinker) skipInstall(mod *Module) {
- mod.ModuleBase.SkipInstall()
-}
-
func NewPrebuiltLibrary(hod android.HostOrDeviceSupported) (*Module, *libraryDecorator) {
module, library := NewLibrary(hod)
module.compiler = nil
@@ -210,7 +208,6 @@ func NewPrebuiltLibrary(hod android.HostOrDeviceSupported) (*Module, *libraryDec
libraryDecorator: library,
}
module.linker = prebuilt
- module.installer = prebuilt
module.AddProperties(&prebuilt.properties)
@@ -243,6 +240,16 @@ func PrebuiltSharedLibraryFactory() android.Module {
return module.Init()
}
+// cc_prebuilt_test_library_shared installs a precompiled shared library
+// to be used as a data dependency of a test-related module (such as cc_test, or
+// cc_test_library).
+func PrebuiltSharedTestLibraryFactory() android.Module {
+ module, library := NewPrebuiltLibrary(android.HostAndDeviceSupported)
+ library.BuildOnlyShared()
+ library.baseInstaller = NewTestInstaller()
+ return module.Init()
+}
+
func NewPrebuiltSharedLibrary(hod android.HostOrDeviceSupported) (*Module, *libraryDecorator) {
module, library := NewPrebuiltLibrary(hod)
library.BuildOnlyShared()
@@ -325,16 +332,16 @@ func (p *prebuiltBinaryLinker) link(ctx ModuleContext,
flags Flags, deps PathDeps, objs Objects) android.Path {
// TODO(ccross): verify shared library dependencies
if len(p.properties.Srcs) > 0 {
- builderFlags := flagsToBuilderFlags(flags)
+ stripFlags := flagsToStripFlags(flags)
fileName := p.getStem(ctx) + flags.Toolchain.ExecutableSuffix()
in := p.Prebuilt.SingleSourcePath(ctx)
p.unstrippedOutputFile = in
- if p.needsStrip(ctx) {
+ if p.stripper.NeedsStrip(ctx) {
stripped := android.PathForModuleOut(ctx, "stripped", fileName)
- p.stripExecutableOrSharedLib(ctx, in, stripped, builderFlags)
+ p.stripper.StripExecutableOrSharedLib(ctx, in, stripped, stripFlags)
in = stripped
}
diff --git a/cc/rs.go b/cc/rs.go
index 9149e1767..ba69f2339 100644
--- a/cc/rs.go
+++ b/cc/rs.go
@@ -25,8 +25,8 @@ import (
func init() {
pctx.VariableFunc("rsCmd", func(ctx android.PackageVarContext) string {
- if ctx.Config().UnbundledBuild() {
- // Use RenderScript prebuilts for unbundled builds but not PDK builds
+ if ctx.Config().AlwaysUsePrebuiltSdks() {
+ // Use RenderScript prebuilts for unbundled builds
return filepath.Join("prebuilts/sdk/tools", runtime.GOOS, "bin/llvm-rs-cc")
} else {
return ctx.Config().HostToolPath(ctx, "llvm-rs-cc").String()
diff --git a/cc/sabi.go b/cc/sabi.go
index 8cef1700c..ef6beada6 100644
--- a/cc/sabi.go
+++ b/cc/sabi.go
@@ -83,10 +83,7 @@ func sabiDepsMutator(mctx android.TopDownMutatorContext) {
((c.IsVndk() && c.UseVndk()) || c.isLlndk(mctx.Config()) ||
(c.sabi != nil && c.sabi.Properties.CreateSAbiDumps)) {
mctx.VisitDirectDeps(func(m android.Module) {
- tag := mctx.OtherModuleDependencyTag(m)
- switch tag {
- case StaticDepTag, staticExportDepTag, lateStaticDepTag, wholeStaticDepTag:
-
+ if tag, ok := mctx.OtherModuleDependencyTag(m).(libraryDependencyTag); ok && tag.static() {
cc, _ := m.(*Module)
if cc == nil {
return
diff --git a/cc/sanitize.go b/cc/sanitize.go
index 69563e09e..418671fcd 100644
--- a/cc/sanitize.go
+++ b/cc/sanitize.go
@@ -55,17 +55,15 @@ var (
}
cfiCflags = []string{"-flto", "-fsanitize-cfi-cross-dso",
- "-fsanitize-blacklist=external/compiler-rt/lib/cfi/cfi_blacklist.txt"}
+ "-fsanitize-blacklist=external/compiler-rt/lib/cfi/cfi_blocklist.txt"}
// -flto and -fvisibility are required by clang when -fsanitize=cfi is
// used, but have no effect on assembly files
cfiAsflags = []string{"-flto", "-fvisibility=default"}
cfiLdflags = []string{"-flto", "-fsanitize-cfi-cross-dso", "-fsanitize=cfi",
"-Wl,-plugin-opt,O1"}
- cfiExportsMapPath = "build/soong/cc/config/cfi_exports.map"
- cfiStaticLibsMutex sync.Mutex
- hwasanStaticLibsMutex sync.Mutex
+ cfiExportsMapPath = "build/soong/cc/config/cfi_exports.map"
- intOverflowCflags = []string{"-fsanitize-blacklist=build/soong/cc/config/integer_overflow_blacklist.txt"}
+ intOverflowCflags = []string{"-fsanitize-blacklist=build/soong/cc/config/integer_overflow_blocklist.txt"}
minimalRuntimeFlags = []string{"-fsanitize-minimal-runtime", "-fno-sanitize-trap=integer,undefined",
"-fno-sanitize-recover=integer,undefined"}
@@ -162,6 +160,9 @@ type SanitizeProperties struct {
Scudo *bool `android:"arch_variant"`
Scs *bool `android:"arch_variant"`
+ // A modifier for ASAN and HWASAN for write only instrumentation
+ Writeonly *bool `android:"arch_variant"`
+
// Sanitizers to run in the diagnostic mode (as opposed to the release mode).
// Replaces abort() on error with a human-readable error message.
// Address and Thread sanitizers always run in diagnostic mode.
@@ -177,7 +178,7 @@ type SanitizeProperties struct {
Recover []string
// value to pass to -fsanitize-blacklist
- Blacklist *string
+ Blocklist *string
} `android:"arch_variant"`
SanitizerEnabled bool `blueprint:"mutated"`
@@ -283,6 +284,15 @@ func (sanitize *sanitize) begin(ctx BaseModuleContext) {
s.Hwaddress = boolPtr(true)
}
+ if found, globalSanitizers = removeFromList("writeonly", globalSanitizers); found && s.Writeonly == nil {
+ // Hwaddress and Address are set before, so we can check them here
+ // If they aren't explicitly set in the blueprint/SANITIZE_(HOST|TARGET), they would be nil instead of false
+ if s.Address == nil && s.Hwaddress == nil {
+ ctx.ModuleErrorf("writeonly modifier cannot be used without 'address' or 'hwaddress'")
+ }
+ s.Writeonly = boolPtr(true)
+ }
+
if len(globalSanitizers) > 0 {
ctx.ModuleErrorf("unknown global sanitizer option %s", globalSanitizers[0])
}
@@ -313,14 +323,14 @@ func (sanitize *sanitize) begin(ctx BaseModuleContext) {
// Is CFI actually enabled?
if !ctx.Config().EnableCFI() {
- s.Cfi = nil
- s.Diag.Cfi = nil
+ s.Cfi = boolPtr(false)
+ s.Diag.Cfi = boolPtr(false)
}
// Also disable CFI for arm32 until b/35157333 is fixed.
if ctx.Arch().ArchType == android.Arm {
- s.Cfi = nil
- s.Diag.Cfi = nil
+ s.Cfi = boolPtr(false)
+ s.Diag.Cfi = boolPtr(false)
}
// HWASan requires AArch64 hardware feature (top-byte-ignore).
@@ -335,14 +345,14 @@ func (sanitize *sanitize) begin(ctx BaseModuleContext) {
// Also disable CFI if ASAN is enabled.
if Bool(s.Address) || Bool(s.Hwaddress) {
- s.Cfi = nil
- s.Diag.Cfi = nil
+ s.Cfi = boolPtr(false)
+ s.Diag.Cfi = boolPtr(false)
}
// Disable sanitizers that depend on the UBSan runtime for windows/darwin builds.
if !ctx.Os().Linux() {
- s.Cfi = nil
- s.Diag.Cfi = nil
+ s.Cfi = boolPtr(false)
+ s.Diag.Cfi = boolPtr(false)
s.Misc_undefined = nil
s.Undefined = nil
s.All_undefined = nil
@@ -351,14 +361,15 @@ func (sanitize *sanitize) begin(ctx BaseModuleContext) {
// Also disable CFI for VNDK variants of components
if ctx.isVndk() && ctx.useVndk() {
- s.Cfi = nil
- s.Diag.Cfi = nil
- }
-
- // Also disable CFI if building against snapshot.
- vndkVersion := ctx.DeviceConfig().VndkVersion()
- if ctx.useVndk() && vndkVersion != "current" && vndkVersion != "" {
- s.Cfi = nil
+ if ctx.static() {
+ // Cfi variant for static vndk should be captured as vendor snapshot,
+ // so don't strictly disable Cfi.
+ s.Cfi = nil
+ s.Diag.Cfi = nil
+ } else {
+ s.Cfi = boolPtr(false)
+ s.Diag.Cfi = boolPtr(false)
+ }
}
// HWASan ramdisk (which is built from recovery) goes over some bootloader limit.
@@ -403,7 +414,7 @@ func (sanitize *sanitize) begin(ctx BaseModuleContext) {
// TODO(b/131771163): CFI transiently depends on LTO, and thus Fuzzer is
// mutually incompatible.
if Bool(s.Fuzzer) {
- s.Cfi = nil
+ s.Cfi = boolPtr(false)
}
}
@@ -460,6 +471,10 @@ func (sanitize *sanitize) flags(ctx ModuleContext, flags Flags) Flags {
flags.Local.CFlags = append(flags.Local.CFlags, asanCflags...)
flags.Local.LdFlags = append(flags.Local.LdFlags, asanLdflags...)
+ if Bool(sanitize.Properties.Sanitize.Writeonly) {
+ flags.Local.CFlags = append(flags.Local.CFlags, "-mllvm", "-asan-instrument-reads=0")
+ }
+
if ctx.Host() {
// -nodefaultlibs (provided with libc++) prevents the driver from linking
// libraries needed with -fsanitize=address. http://b/18650275 (WAI)
@@ -479,6 +494,9 @@ func (sanitize *sanitize) flags(ctx ModuleContext, flags Flags) Flags {
if Bool(sanitize.Properties.Sanitize.Hwaddress) {
flags.Local.CFlags = append(flags.Local.CFlags, hwasanCflags...)
+ if Bool(sanitize.Properties.Sanitize.Writeonly) {
+ flags.Local.CFlags = append(flags.Local.CFlags, "-mllvm", "-hwasan-instrument-reads=0")
+ }
}
if Bool(sanitize.Properties.Sanitize.Fuzzer) {
@@ -594,10 +612,10 @@ func (sanitize *sanitize) flags(ctx ModuleContext, flags Flags) Flags {
strings.Join(sanitize.Properties.Sanitize.Diag.No_recover, ","))
}
- blacklist := android.OptionalPathForModuleSrc(ctx, sanitize.Properties.Sanitize.Blacklist)
- if blacklist.Valid() {
- flags.Local.CFlags = append(flags.Local.CFlags, "-fsanitize-blacklist="+blacklist.String())
- flags.CFlagsDeps = append(flags.CFlagsDeps, blacklist.Path())
+ blocklist := android.OptionalPathForModuleSrc(ctx, sanitize.Properties.Sanitize.Blocklist)
+ if blocklist.Valid() {
+ flags.Local.CFlags = append(flags.Local.CFlags, "-fsanitize-blacklist="+blocklist.String())
+ flags.CFlagsDeps = append(flags.CFlagsDeps, blocklist.Path())
}
return flags
@@ -710,31 +728,74 @@ func (sanitize *sanitize) isSanitizerEnabled(t sanitizerType) bool {
}
func isSanitizableDependencyTag(tag blueprint.DependencyTag) bool {
- t, ok := tag.(DependencyTag)
- return ok && t.Library || t == reuseObjTag || t == objDepTag
+ switch t := tag.(type) {
+ case dependencyTag:
+ return t == reuseObjTag || t == objDepTag
+ case libraryDependencyTag:
+ return true
+ default:
+ return false
+ }
+}
+
+// Determines if the current module is a static library going to be captured
+// as vendor snapshot. Such modules must create both cfi and non-cfi variants,
+// except for ones which explicitly disable cfi.
+func needsCfiForVendorSnapshot(mctx android.TopDownMutatorContext) bool {
+ if isVendorProprietaryPath(mctx.ModuleDir()) {
+ return false
+ }
+
+ c := mctx.Module().(*Module)
+
+ if !c.inVendor() {
+ return false
+ }
+
+ if !c.static() {
+ return false
+ }
+
+ if c.Prebuilt() != nil {
+ return false
+ }
+
+ return c.sanitize != nil &&
+ !Bool(c.sanitize.Properties.Sanitize.Never) &&
+ !c.sanitize.isSanitizerExplicitlyDisabled(cfi)
}
// Propagate sanitizer requirements down from binaries
func sanitizerDepsMutator(t sanitizerType) func(android.TopDownMutatorContext) {
return func(mctx android.TopDownMutatorContext) {
- if c, ok := mctx.Module().(*Module); ok && c.sanitize.isSanitizerEnabled(t) {
- mctx.WalkDeps(func(child, parent android.Module) bool {
- if !isSanitizableDependencyTag(mctx.OtherModuleDependencyTag(child)) {
- return false
- }
- if d, ok := child.(*Module); ok && d.sanitize != nil &&
- !Bool(d.sanitize.Properties.Sanitize.Never) &&
- !d.sanitize.isSanitizerExplicitlyDisabled(t) {
- if t == cfi || t == hwasan || t == scs {
- if d.static() {
+ if c, ok := mctx.Module().(*Module); ok {
+ enabled := c.sanitize.isSanitizerEnabled(t)
+ if t == cfi && needsCfiForVendorSnapshot(mctx) {
+ // We shouldn't change the result of isSanitizerEnabled(cfi) to correctly
+ // determine defaultVariation in sanitizerMutator below.
+ // Instead, just mark SanitizeDep to forcefully create cfi variant.
+ enabled = true
+ c.sanitize.Properties.SanitizeDep = true
+ }
+ if enabled {
+ mctx.WalkDeps(func(child, parent android.Module) bool {
+ if !isSanitizableDependencyTag(mctx.OtherModuleDependencyTag(child)) {
+ return false
+ }
+ if d, ok := child.(*Module); ok && d.sanitize != nil &&
+ !Bool(d.sanitize.Properties.Sanitize.Never) &&
+ !d.sanitize.isSanitizerExplicitlyDisabled(t) {
+ if t == cfi || t == hwasan || t == scs {
+ if d.static() {
+ d.sanitize.Properties.SanitizeDep = true
+ }
+ } else {
d.sanitize.Properties.SanitizeDep = true
}
- } else {
- d.sanitize.Properties.SanitizeDep = true
}
- }
- return true
- })
+ return true
+ })
+ }
} else if sanitizeable, ok := mctx.Module().(Sanitizeable); ok {
// If an APEX module includes a lib which is enabled for a sanitizer T, then
// the APEX module is also enabled for the same sanitizer type.
@@ -953,10 +1014,11 @@ func sanitizerRuntimeMutator(mctx android.BottomUpMutatorContext) {
}
// static executable gets static runtime libs
+ depTag := libraryDependencyTag{Kind: staticLibraryDependency}
mctx.AddFarVariationDependencies(append(mctx.Target().Variations(), []blueprint.Variation{
{Mutator: "link", Variation: "static"},
c.ImageVariation(),
- }...), StaticDepTag, deps...)
+ }...), depTag, deps...)
} else if !c.static() && !c.header() {
// If we're using snapshots and in vendor, redirect to snapshot whenever possible
if c.VndkVersion() == mctx.DeviceConfig().VndkVersion() {
@@ -967,10 +1029,11 @@ func sanitizerRuntimeMutator(mctx android.BottomUpMutatorContext) {
}
// dynamic executable and shared libs get shared runtime libs
+ depTag := libraryDependencyTag{Kind: sharedLibraryDependency, Order: earlyLibraryDependency}
mctx.AddFarVariationDependencies(append(mctx.Target().Variations(), []blueprint.Variation{
{Mutator: "link", Variation: "shared"},
c.ImageVariation(),
- }...), earlySharedDepTag, runtimeLibrary)
+ }...), depTag, runtimeLibrary)
}
// static lib does not have dependency to the runtime library. The
// dependency will be added to the executables or shared libs using
@@ -1038,15 +1101,9 @@ func sanitizerMutator(t sanitizerType) func(android.BottomUpMutatorContext) {
// Export the static lib name to make
if c.static() && c.ExportedToMake() {
if t == cfi {
- appendStringSync(c.Name(), cfiStaticLibs(mctx.Config()), &cfiStaticLibsMutex)
+ cfiStaticLibs(mctx.Config()).add(c, c.Name())
} else if t == hwasan {
- if c.UseVndk() {
- appendStringSync(c.Name(), hwasanVendorStaticLibs(mctx.Config()),
- &hwasanStaticLibsMutex)
- } else {
- appendStringSync(c.Name(), hwasanStaticLibs(mctx.Config()),
- &hwasanStaticLibsMutex)
- }
+ hwasanStaticLibs(mctx.Config()).add(c, c.Name())
}
}
} else {
@@ -1072,38 +1129,96 @@ func sanitizerMutator(t sanitizerType) func(android.BottomUpMutatorContext) {
// APEX modules fall here
sanitizeable.AddSanitizerDependencies(mctx, t.name())
mctx.CreateVariations(t.variationName())
+ } else if c, ok := mctx.Module().(*Module); ok {
+ // Check if it's a snapshot module supporting sanitizer
+ if s, ok := c.linker.(snapshotSanitizer); ok && s.isSanitizerEnabled(t) {
+ // Set default variation as above.
+ defaultVariation := t.variationName()
+ mctx.SetDefaultDependencyVariation(&defaultVariation)
+ modules := mctx.CreateVariations("", t.variationName())
+ modules[0].(*Module).linker.(snapshotSanitizer).setSanitizerVariation(t, false)
+ modules[1].(*Module).linker.(snapshotSanitizer).setSanitizerVariation(t, true)
+
+ // Export the static lib name to make
+ if c.static() && c.ExportedToMake() {
+ if t == cfi {
+ // use BaseModuleName which is the name for Make.
+ cfiStaticLibs(mctx.Config()).add(c, c.BaseModuleName())
+ }
+ }
+ }
}
}
}
-var cfiStaticLibsKey = android.NewOnceKey("cfiStaticLibs")
+type sanitizerStaticLibsMap struct {
+ // libsMap contains one list of modules per each image and each arch.
+ // e.g. libs[vendor]["arm"] contains arm modules installed to vendor
+ libsMap map[imageVariantType]map[string][]string
+ libsMapLock sync.Mutex
+ sanitizerType sanitizerType
+}
-func cfiStaticLibs(config android.Config) *[]string {
- return config.Once(cfiStaticLibsKey, func() interface{} {
- return &[]string{}
- }).(*[]string)
+func newSanitizerStaticLibsMap(t sanitizerType) *sanitizerStaticLibsMap {
+ return &sanitizerStaticLibsMap{
+ sanitizerType: t,
+ libsMap: make(map[imageVariantType]map[string][]string),
+ }
}
-var hwasanStaticLibsKey = android.NewOnceKey("hwasanStaticLibs")
+// Add the current module to sanitizer static libs maps
+// Each module should pass its exported name as names of Make and Soong can differ.
+func (s *sanitizerStaticLibsMap) add(c *Module, name string) {
+ image := c.getImageVariantType()
+ arch := c.Arch().ArchType.String()
-func hwasanStaticLibs(config android.Config) *[]string {
- return config.Once(hwasanStaticLibsKey, func() interface{} {
- return &[]string{}
- }).(*[]string)
+ s.libsMapLock.Lock()
+ defer s.libsMapLock.Unlock()
+
+ if _, ok := s.libsMap[image]; !ok {
+ s.libsMap[image] = make(map[string][]string)
+ }
+
+ s.libsMap[image][arch] = append(s.libsMap[image][arch], name)
}
-var hwasanVendorStaticLibsKey = android.NewOnceKey("hwasanVendorStaticLibs")
+// Exports makefile variables in the following format:
+// SOONG_{sanitizer}_{image}_{arch}_STATIC_LIBRARIES
+// e.g. SOONG_cfi_core_x86_STATIC_LIBRARIES
+// These are to be used by use_soong_sanitized_static_libraries.
+// See build/make/core/binary.mk for more details.
+func (s *sanitizerStaticLibsMap) exportToMake(ctx android.MakeVarsContext) {
+ for _, image := range android.SortedStringKeys(s.libsMap) {
+ archMap := s.libsMap[imageVariantType(image)]
+ for _, arch := range android.SortedStringKeys(archMap) {
+ libs := archMap[arch]
+ sort.Strings(libs)
+
+ key := fmt.Sprintf(
+ "SOONG_%s_%s_%s_STATIC_LIBRARIES",
+ s.sanitizerType.variationName(),
+ image, // already upper
+ arch)
+
+ ctx.Strict(key, strings.Join(libs, " "))
+ }
+ }
+}
-func hwasanVendorStaticLibs(config android.Config) *[]string {
- return config.Once(hwasanVendorStaticLibsKey, func() interface{} {
- return &[]string{}
- }).(*[]string)
+var cfiStaticLibsKey = android.NewOnceKey("cfiStaticLibs")
+
+func cfiStaticLibs(config android.Config) *sanitizerStaticLibsMap {
+ return config.Once(cfiStaticLibsKey, func() interface{} {
+ return newSanitizerStaticLibsMap(cfi)
+ }).(*sanitizerStaticLibsMap)
}
-func appendStringSync(item string, list *[]string, mutex *sync.Mutex) {
- mutex.Lock()
- *list = append(*list, item)
- mutex.Unlock()
+var hwasanStaticLibsKey = android.NewOnceKey("hwasanStaticLibs")
+
+func hwasanStaticLibs(config android.Config) *sanitizerStaticLibsMap {
+ return config.Once(hwasanStaticLibsKey, func() interface{} {
+ return newSanitizerStaticLibsMap(hwasan)
+ }).(*sanitizerStaticLibsMap)
}
func enableMinimalRuntime(sanitize *sanitize) bool {
@@ -1133,17 +1248,9 @@ func enableUbsanRuntime(sanitize *sanitize) bool {
}
func cfiMakeVarsProvider(ctx android.MakeVarsContext) {
- cfiStaticLibs := cfiStaticLibs(ctx.Config())
- sort.Strings(*cfiStaticLibs)
- ctx.Strict("SOONG_CFI_STATIC_LIBRARIES", strings.Join(*cfiStaticLibs, " "))
+ cfiStaticLibs(ctx.Config()).exportToMake(ctx)
}
func hwasanMakeVarsProvider(ctx android.MakeVarsContext) {
- hwasanStaticLibs := hwasanStaticLibs(ctx.Config())
- sort.Strings(*hwasanStaticLibs)
- ctx.Strict("SOONG_HWASAN_STATIC_LIBRARIES", strings.Join(*hwasanStaticLibs, " "))
-
- hwasanVendorStaticLibs := hwasanVendorStaticLibs(ctx.Config())
- sort.Strings(*hwasanVendorStaticLibs)
- ctx.Strict("SOONG_HWASAN_VENDOR_STATIC_LIBRARIES", strings.Join(*hwasanVendorStaticLibs, " "))
+ hwasanStaticLibs(ctx.Config()).exportToMake(ctx)
}
diff --git a/cc/strip.go b/cc/strip.go
index 7e560ec9c..18150dc8d 100644
--- a/cc/strip.go
+++ b/cc/strip.go
@@ -30,42 +30,42 @@ type StripProperties struct {
} `android:"arch_variant"`
}
-type stripper struct {
+type Stripper struct {
StripProperties StripProperties
}
-func (stripper *stripper) needsStrip(ctx ModuleContext) bool {
+func (stripper *Stripper) NeedsStrip(actx android.ModuleContext) bool {
// TODO(ccross): enable host stripping when embedded in make? Make never had support for stripping host binaries.
- return (!ctx.Config().EmbeddedInMake() || ctx.Device()) && !Bool(stripper.StripProperties.Strip.None)
+ return (!actx.Config().EmbeddedInMake() || actx.Device()) && !Bool(stripper.StripProperties.Strip.None)
}
-func (stripper *stripper) strip(ctx ModuleContext, in android.Path, out android.ModuleOutPath,
- flags builderFlags, isStaticLib bool) {
- if ctx.Darwin() {
- TransformDarwinStrip(ctx, in, out)
+func (stripper *Stripper) strip(actx android.ModuleContext, in android.Path, out android.ModuleOutPath,
+ flags StripFlags, isStaticLib bool) {
+ if actx.Darwin() {
+ TransformDarwinStrip(actx, in, out)
} else {
if Bool(stripper.StripProperties.Strip.Keep_symbols) {
- flags.stripKeepSymbols = true
+ flags.StripKeepSymbols = true
} else if Bool(stripper.StripProperties.Strip.Keep_symbols_and_debug_frame) {
- flags.stripKeepSymbolsAndDebugFrame = true
+ flags.StripKeepSymbolsAndDebugFrame = true
} else if len(stripper.StripProperties.Strip.Keep_symbols_list) > 0 {
- flags.stripKeepSymbolsList = strings.Join(stripper.StripProperties.Strip.Keep_symbols_list, ",")
+ flags.StripKeepSymbolsList = strings.Join(stripper.StripProperties.Strip.Keep_symbols_list, ",")
} else if !Bool(stripper.StripProperties.Strip.All) {
- flags.stripKeepMiniDebugInfo = true
+ flags.StripKeepMiniDebugInfo = true
}
- if ctx.Config().Debuggable() && !flags.stripKeepMiniDebugInfo && !isStaticLib {
- flags.stripAddGnuDebuglink = true
+ if actx.Config().Debuggable() && !flags.StripKeepMiniDebugInfo && !isStaticLib {
+ flags.StripAddGnuDebuglink = true
}
- TransformStrip(ctx, in, out, flags)
+ TransformStrip(actx, in, out, flags)
}
}
-func (stripper *stripper) stripExecutableOrSharedLib(ctx ModuleContext, in android.Path,
- out android.ModuleOutPath, flags builderFlags) {
- stripper.strip(ctx, in, out, flags, false)
+func (stripper *Stripper) StripExecutableOrSharedLib(actx android.ModuleContext, in android.Path,
+ out android.ModuleOutPath, flags StripFlags) {
+ stripper.strip(actx, in, out, flags, false)
}
-func (stripper *stripper) stripStaticLib(ctx ModuleContext, in android.Path, out android.ModuleOutPath,
- flags builderFlags) {
- stripper.strip(ctx, in, out, flags, true)
+func (stripper *Stripper) StripStaticLib(actx android.ModuleContext, in android.Path, out android.ModuleOutPath,
+ flags StripFlags) {
+ stripper.strip(actx, in, out, flags, true)
}
diff --git a/cc/test.go b/cc/test.go
index 37afb0ca4..a8056479f 100644
--- a/cc/test.go
+++ b/cc/test.go
@@ -40,8 +40,12 @@ type TestProperties struct {
type TestOptions struct {
// The UID that you want to run the test as on a device.
Run_test_as *string
+
// A list of free-formed strings without spaces that categorize the test.
Test_suite_tag []string
+
+ // a list of extra test configuration files that should be installed with the module.
+ Extra_test_configs []string `android:"path,arch_variant"`
}
type TestBinaryProperties struct {
@@ -165,7 +169,7 @@ func (test *testBinary) srcs() []string {
return test.baseCompiler.Properties.Srcs
}
-func (test *testBinary) dataPaths() android.Paths {
+func (test *testBinary) dataPaths() []android.DataPath {
return test.data
}
@@ -309,9 +313,10 @@ type testBinary struct {
testDecorator
*binaryDecorator
*baseCompiler
- Properties TestBinaryProperties
- data android.Paths
- testConfig android.Path
+ Properties TestBinaryProperties
+ data []android.DataPath
+ testConfig android.Path
+ extraTestConfigs android.Paths
}
func (test *testBinary) linkerProps() []interface{} {
@@ -339,7 +344,11 @@ func (test *testBinary) linkerFlags(ctx ModuleContext, flags Flags) Flags {
}
func (test *testBinary) install(ctx ModuleContext, file android.Path) {
- test.data = android.PathsForModuleSrc(ctx, test.Properties.Data)
+ dataSrcPaths := android.PathsForModuleSrc(ctx, test.Properties.Data)
+
+ for _, dataSrcPath := range dataSrcPaths {
+ test.data = append(test.data, android.DataPath{SrcPath: dataSrcPath})
+ }
ctx.VisitDirectDepsWithTag(dataLibDepTag, func(dep android.Module) {
depName := ctx.OtherModuleName(dep)
@@ -348,10 +357,14 @@ func (test *testBinary) install(ctx ModuleContext, file android.Path) {
if !ok {
ctx.ModuleErrorf("data_lib %q is not a linkable cc module", depName)
}
+ ccModule, ok := dep.(*Module)
+ if !ok {
+ ctx.ModuleErrorf("data_lib %q is not a cc module", depName)
+ }
if ccDep.OutputFile().Valid() {
- test.data = append(test.data, ccDep.OutputFile().Path())
- } else {
- ctx.ModuleErrorf("data_lib %q has no output file", depName)
+ test.data = append(test.data,
+ android.DataPath{SrcPath: ccDep.OutputFile().Path(),
+ RelativeInstallPath: ccModule.installer.relativeInstallPath()})
}
})
@@ -400,6 +413,8 @@ func (test *testBinary) install(ctx ModuleContext, file android.Path) {
test.testConfig = tradefed.AutoGenNativeTestConfig(ctx, test.Properties.Test_config,
test.Properties.Test_config_template, test.Properties.Test_suites, configs, test.Properties.Auto_gen_config)
+ test.extraTestConfigs = android.PathsForModuleSrc(ctx, test.Properties.Test_options.Extra_test_configs)
+
test.binaryDecorator.baseInstaller.dir = "nativetest"
test.binaryDecorator.baseInstaller.dir64 = "nativetest64"
diff --git a/cc/testing.go b/cc/testing.go
index 4d0b28b7f..06e5f832c 100644
--- a/cc/testing.go
+++ b/cc/testing.go
@@ -20,8 +20,6 @@ import (
func RegisterRequiredBuildComponentsForTest(ctx android.RegistrationContext) {
RegisterPrebuiltBuildComponents(ctx)
- android.RegisterPrebuiltMutators(ctx)
-
RegisterCCBuildComponents(ctx)
RegisterBinaryBuildComponents(ctx)
RegisterLibraryBuildComponents(ctx)
@@ -340,6 +338,8 @@ func GatherRequiredDepsForTest(oses ...android.OsType) string {
vendor_available: true,
native_bridge_supported: true,
stl: "none",
+ min_sdk_version: "16",
+ crt: true,
apex_available: [
"//apex_available:platform",
"//apex_available:anyapex",
@@ -349,48 +349,26 @@ func GatherRequiredDepsForTest(oses ...android.OsType) string {
cc_object {
name: "crtbegin_so",
defaults: ["crt_defaults"],
- recovery_available: true,
- vendor_available: true,
- native_bridge_supported: true,
- min_sdk_version: "29",
- stl: "none",
}
cc_object {
name: "crtbegin_dynamic",
defaults: ["crt_defaults"],
- recovery_available: true,
- vendor_available: true,
- native_bridge_supported: true,
- stl: "none",
}
cc_object {
name: "crtbegin_static",
defaults: ["crt_defaults"],
- recovery_available: true,
- vendor_available: true,
- native_bridge_supported: true,
- stl: "none",
}
cc_object {
name: "crtend_so",
defaults: ["crt_defaults"],
- recovery_available: true,
- vendor_available: true,
- native_bridge_supported: true,
- min_sdk_version: "29",
- stl: "none",
}
cc_object {
name: "crtend_android",
defaults: ["crt_defaults"],
- recovery_available: true,
- vendor_available: true,
- native_bridge_supported: true,
- stl: "none",
}
cc_library {
@@ -422,26 +400,6 @@ func GatherRequiredDepsForTest(oses ...android.OsType) string {
symbol_file: "libdl.map.txt",
}
- ndk_prebuilt_object {
- name: "ndk_crtbegin_so.27",
- sdk_version: "27",
- }
-
- ndk_prebuilt_object {
- name: "ndk_crtend_so.27",
- sdk_version: "27",
- }
-
- ndk_prebuilt_object {
- name: "ndk_crtbegin_dynamic.27",
- sdk_version: "27",
- }
-
- ndk_prebuilt_object {
- name: "ndk_crtend_android.27",
- sdk_version: "27",
- }
-
ndk_prebuilt_shared_stl {
name: "ndk_libc++_shared",
}
@@ -569,7 +527,9 @@ func CreateTestContext() *android.TestContext {
ctx.RegisterModuleType("filegroup", android.FileGroupFactory)
ctx.RegisterModuleType("vndk_prebuilt_shared", VndkPrebuiltSharedFactory)
ctx.RegisterModuleType("vndk_libraries_txt", VndkLibrariesTxtFactory)
+ ctx.RegisterModuleType("vendor_snapshot_static", VendorSnapshotStaticFactory)
ctx.PreArchMutators(android.RegisterDefaultsPreArchMutators)
+ android.RegisterPrebuiltMutators(ctx)
RegisterRequiredBuildComponentsForTest(ctx)
ctx.RegisterSingletonType("vndk-snapshot", VndkSnapshotSingleton)
ctx.RegisterSingletonType("vendor-snapshot", VendorSnapshotSingleton)
diff --git a/cc/tidy.go b/cc/tidy.go
index 364e56c5d..17471e674 100644
--- a/cc/tidy.go
+++ b/cc/tidy.go
@@ -109,7 +109,8 @@ func (tidy *tidyFeature) flags(ctx ModuleContext, flags Flags) Flags {
tidyChecks += config.TidyChecksForDir(ctx.ModuleDir())
}
if len(tidy.Properties.Tidy_checks) > 0 {
- tidyChecks = tidyChecks + "," + strings.Join(esc(tidy.Properties.Tidy_checks), ",")
+ tidyChecks = tidyChecks + "," + strings.Join(esc(
+ config.ClangRewriteTidyChecks(tidy.Properties.Tidy_checks)), ",")
}
if ctx.Windows() {
// https://b.corp.google.com/issues/120614316
diff --git a/cc/toolchain_library.go b/cc/toolchain_library.go
index 042e012d9..19f5ea4f7 100644
--- a/cc/toolchain_library.go
+++ b/cc/toolchain_library.go
@@ -36,8 +36,7 @@ type toolchainLibraryProperties struct {
type toolchainLibraryDecorator struct {
*libraryDecorator
-
- stripper
+ stripper Stripper
Properties toolchainLibraryProperties
}
@@ -89,8 +88,8 @@ func (library *toolchainLibraryDecorator) link(ctx ModuleContext,
if library.stripper.StripProperties.Strip.Keep_symbols_list != nil {
fileName := ctx.ModuleName() + staticLibraryExtension
outputFile := android.PathForModuleOut(ctx, fileName)
- buildFlags := flagsToBuilderFlags(flags)
- library.stripper.stripStaticLib(ctx, srcPath, outputFile, buildFlags)
+ stripFlags := flagsToStripFlags(flags)
+ library.stripper.StripStaticLib(ctx, srcPath, outputFile, stripFlags)
return outputFile
}
diff --git a/cc/util.go b/cc/util.go
index af26268e2..40374bff7 100644
--- a/cc/util.go
+++ b/cc/util.go
@@ -97,9 +97,14 @@ func flagsToBuilderFlags(in Flags) builderFlags {
protoOptionsFile: in.protoOptionsFile,
yacc: in.Yacc,
+ lex: in.Lex,
}
}
+func flagsToStripFlags(in Flags) StripFlags {
+ return StripFlags{Toolchain: in.Toolchain}
+}
+
func addPrefix(list []string, prefix string) []string {
for i := range list {
list[i] = prefix + list[i]
diff --git a/cc/vendor_public_library.go b/cc/vendor_public_library.go
index e9d1c7378..85f514c83 100644
--- a/cc/vendor_public_library.go
+++ b/cc/vendor_public_library.go
@@ -144,7 +144,7 @@ func vendorPublicLibraryFactory() android.Module {
library.BuildOnlyShared()
module.stl = nil
module.sanitize = nil
- library.StripProperties.Strip.None = BoolPtr(true)
+ library.disableStripping()
stub := &vendorPublicLibraryStubDecorator{
libraryDecorator: library,
diff --git a/cc/vendor_snapshot.go b/cc/vendor_snapshot.go
index fec0c8bb6..93aece4fc 100644
--- a/cc/vendor_snapshot.go
+++ b/cc/vendor_snapshot.go
@@ -80,64 +80,98 @@ func vendorSnapshotObjects(config android.Config) *snapshotMap {
}).(*snapshotMap)
}
-type vendorSnapshotLibraryProperties struct {
+type vendorSnapshotBaseProperties struct {
// snapshot version.
Version string
// Target arch name of the snapshot (e.g. 'arm64' for variant 'aosp_arm64')
Target_arch string
-
- // Prebuilt file for each arch.
- Src *string `android:"arch_variant"`
-
- // list of flags that will be used for any module that links against this module.
- Export_flags []string `android:"arch_variant"`
-
- // Check the prebuilt ELF files (e.g. DT_SONAME, DT_NEEDED, resolution of undefined symbols,
- // etc).
- Check_elf_files *bool
-
- // Whether this prebuilt needs to depend on sanitize ubsan runtime or not.
- Sanitize_ubsan_dep *bool `android:"arch_variant"`
-
- // Whether this prebuilt needs to depend on sanitize minimal runtime or not.
- Sanitize_minimal_dep *bool `android:"arch_variant"`
}
-type vendorSnapshotLibraryDecorator struct {
- *libraryDecorator
- properties vendorSnapshotLibraryProperties
- androidMkVendorSuffix bool
+// vendorSnapshotModuleBase provides common basic functions for all snapshot modules.
+type vendorSnapshotModuleBase struct {
+ baseProperties vendorSnapshotBaseProperties
+ moduleSuffix string
}
-func (p *vendorSnapshotLibraryDecorator) Name(name string) string {
+func (p *vendorSnapshotModuleBase) Name(name string) string {
return name + p.NameSuffix()
}
-func (p *vendorSnapshotLibraryDecorator) NameSuffix() string {
+func (p *vendorSnapshotModuleBase) NameSuffix() string {
versionSuffix := p.version()
if p.arch() != "" {
versionSuffix += "." + p.arch()
}
- var linkageSuffix string
- if p.buildShared() {
- linkageSuffix = vendorSnapshotSharedSuffix
- } else if p.buildStatic() {
- linkageSuffix = vendorSnapshotStaticSuffix
- } else {
- linkageSuffix = vendorSnapshotHeaderSuffix
+ return p.moduleSuffix + versionSuffix
+}
+
+func (p *vendorSnapshotModuleBase) version() string {
+ return p.baseProperties.Version
+}
+
+func (p *vendorSnapshotModuleBase) arch() string {
+ return p.baseProperties.Target_arch
+}
+
+func (p *vendorSnapshotModuleBase) isSnapshotPrebuilt() bool {
+ return true
+}
+
+// Call this after creating a snapshot module with module suffix
+// such as vendorSnapshotSharedSuffix
+func (p *vendorSnapshotModuleBase) init(m *Module, suffix string) {
+ p.moduleSuffix = suffix
+ m.AddProperties(&p.baseProperties)
+ android.AddLoadHook(m, func(ctx android.LoadHookContext) {
+ vendorSnapshotLoadHook(ctx, p)
+ })
+}
+
+func vendorSnapshotLoadHook(ctx android.LoadHookContext, p *vendorSnapshotModuleBase) {
+ if p.version() != ctx.DeviceConfig().VndkVersion() {
+ ctx.Module().Disable()
+ return
}
+}
+
+type vendorSnapshotLibraryProperties struct {
+ // Prebuilt file for each arch.
+ Src *string `android:"arch_variant"`
+
+ // list of directories that will be added to the include path (using -I).
+ Export_include_dirs []string `android:"arch_variant"`
+
+ // list of directories that will be added to the system path (using -isystem).
+ Export_system_include_dirs []string `android:"arch_variant"`
+
+ // list of flags that will be used for any module that links against this module.
+ Export_flags []string `android:"arch_variant"`
+
+ // Whether this prebuilt needs to depend on sanitize ubsan runtime or not.
+ Sanitize_ubsan_dep *bool `android:"arch_variant"`
- return linkageSuffix + versionSuffix
+ // Whether this prebuilt needs to depend on sanitize minimal runtime or not.
+ Sanitize_minimal_dep *bool `android:"arch_variant"`
}
-func (p *vendorSnapshotLibraryDecorator) version() string {
- return p.properties.Version
+type snapshotSanitizer interface {
+ isSanitizerEnabled(t sanitizerType) bool
+ setSanitizerVariation(t sanitizerType, enabled bool)
}
-func (p *vendorSnapshotLibraryDecorator) arch() string {
- return p.properties.Target_arch
+type vendorSnapshotLibraryDecorator struct {
+ vendorSnapshotModuleBase
+ *libraryDecorator
+ properties vendorSnapshotLibraryProperties
+ sanitizerProperties struct {
+ CfiEnabled bool `blueprint:"mutated"`
+
+ // Library flags for cfi variant.
+ Cfi vendorSnapshotLibraryProperties `android:"arch_variant"`
+ }
+ androidMkVendorSuffix bool
}
func (p *vendorSnapshotLibraryDecorator) linkerFlags(ctx ModuleContext, flags Flags) Flags {
@@ -165,11 +199,16 @@ func (p *vendorSnapshotLibraryDecorator) link(ctx ModuleContext,
return p.libraryDecorator.link(ctx, flags, deps, objs)
}
+ if p.sanitizerProperties.CfiEnabled {
+ p.properties = p.sanitizerProperties.Cfi
+ }
+
if !p.matchesWithDevice(ctx.DeviceConfig()) {
return nil
}
- p.libraryDecorator.exportIncludes(ctx)
+ p.libraryDecorator.reexportDirs(android.PathsForModuleSrc(ctx, p.properties.Export_include_dirs)...)
+ p.libraryDecorator.reexportSystemDirs(android.PathsForModuleSrc(ctx, p.properties.Export_system_include_dirs)...)
p.libraryDecorator.reexportFlags(p.properties.Export_flags...)
in := android.PathForModuleSrc(ctx, *p.properties.Src)
@@ -189,37 +228,43 @@ func (p *vendorSnapshotLibraryDecorator) link(ctx ModuleContext,
return in
}
-func (p *vendorSnapshotLibraryDecorator) nativeCoverage() bool {
- return false
-}
-
-func (p *vendorSnapshotLibraryDecorator) isSnapshotPrebuilt() bool {
- return true
-}
-
func (p *vendorSnapshotLibraryDecorator) install(ctx ModuleContext, file android.Path) {
if p.matchesWithDevice(ctx.DeviceConfig()) && (p.shared() || p.static()) {
p.baseInstaller.install(ctx, file)
}
}
-type vendorSnapshotInterface interface {
- version() string
+func (p *vendorSnapshotLibraryDecorator) nativeCoverage() bool {
+ return false
}
-func vendorSnapshotLoadHook(ctx android.LoadHookContext, p vendorSnapshotInterface) {
- if p.version() != ctx.DeviceConfig().VndkVersion() {
- ctx.Module().Disable()
+func (p *vendorSnapshotLibraryDecorator) isSanitizerEnabled(t sanitizerType) bool {
+ switch t {
+ case cfi:
+ return p.sanitizerProperties.Cfi.Src != nil
+ default:
+ return false
+ }
+}
+
+func (p *vendorSnapshotLibraryDecorator) setSanitizerVariation(t sanitizerType, enabled bool) {
+ if !enabled {
+ return
+ }
+ switch t {
+ case cfi:
+ p.sanitizerProperties.CfiEnabled = true
+ default:
return
}
}
-func vendorSnapshotLibrary() (*Module, *vendorSnapshotLibraryDecorator) {
+func vendorSnapshotLibrary(suffix string) (*Module, *vendorSnapshotLibraryDecorator) {
module, library := NewLibrary(android.DeviceSupported)
module.stl = nil
module.sanitize = nil
- library.StripProperties.Strip.None = BoolPtr(true)
+ library.disableStripping()
prebuilt := &vendorSnapshotLibraryDecorator{
libraryDecorator: library,
@@ -237,77 +282,47 @@ func vendorSnapshotLibrary() (*Module, *vendorSnapshotLibraryDecorator) {
module.linker = prebuilt
module.installer = prebuilt
+ prebuilt.init(module, suffix)
module.AddProperties(
&prebuilt.properties,
+ &prebuilt.sanitizerProperties,
)
return module, prebuilt
}
func VendorSnapshotSharedFactory() android.Module {
- module, prebuilt := vendorSnapshotLibrary()
+ module, prebuilt := vendorSnapshotLibrary(vendorSnapshotSharedSuffix)
prebuilt.libraryDecorator.BuildOnlyShared()
- android.AddLoadHook(module, func(ctx android.LoadHookContext) {
- vendorSnapshotLoadHook(ctx, prebuilt)
- })
return module.Init()
}
func VendorSnapshotStaticFactory() android.Module {
- module, prebuilt := vendorSnapshotLibrary()
+ module, prebuilt := vendorSnapshotLibrary(vendorSnapshotStaticSuffix)
prebuilt.libraryDecorator.BuildOnlyStatic()
- android.AddLoadHook(module, func(ctx android.LoadHookContext) {
- vendorSnapshotLoadHook(ctx, prebuilt)
- })
return module.Init()
}
func VendorSnapshotHeaderFactory() android.Module {
- module, prebuilt := vendorSnapshotLibrary()
+ module, prebuilt := vendorSnapshotLibrary(vendorSnapshotHeaderSuffix)
prebuilt.libraryDecorator.HeaderOnly()
- android.AddLoadHook(module, func(ctx android.LoadHookContext) {
- vendorSnapshotLoadHook(ctx, prebuilt)
- })
return module.Init()
}
-type vendorSnapshotBinaryProperties struct {
- // snapshot version.
- Version string
-
- // Target arch name of the snapshot (e.g. 'arm64' for variant 'aosp_arm64_ab')
- Target_arch string
+var _ snapshotSanitizer = (*vendorSnapshotLibraryDecorator)(nil)
+type vendorSnapshotBinaryProperties struct {
// Prebuilt file for each arch.
Src *string `android:"arch_variant"`
}
type vendorSnapshotBinaryDecorator struct {
+ vendorSnapshotModuleBase
*binaryDecorator
properties vendorSnapshotBinaryProperties
androidMkVendorSuffix bool
}
-func (p *vendorSnapshotBinaryDecorator) Name(name string) string {
- return name + p.NameSuffix()
-}
-
-func (p *vendorSnapshotBinaryDecorator) NameSuffix() string {
- versionSuffix := p.version()
- if p.arch() != "" {
- versionSuffix += "." + p.arch()
- }
- return vendorSnapshotBinarySuffix + versionSuffix
-}
-
-func (p *vendorSnapshotBinaryDecorator) version() string {
- return p.properties.Version
-}
-
-func (p *vendorSnapshotBinaryDecorator) arch() string {
- return p.properties.Target_arch
-}
-
func (p *vendorSnapshotBinaryDecorator) matchesWithDevice(config android.DeviceConfig) bool {
if config.DeviceArch() != p.arch() {
return false
@@ -325,12 +340,12 @@ func (p *vendorSnapshotBinaryDecorator) link(ctx ModuleContext,
}
in := android.PathForModuleSrc(ctx, *p.properties.Src)
- builderFlags := flagsToBuilderFlags(flags)
+ stripFlags := flagsToStripFlags(flags)
p.unstrippedOutputFile = in
binName := in.Base()
- if p.needsStrip(ctx) {
+ if p.stripper.NeedsStrip(ctx) {
stripped := android.PathForModuleOut(ctx, "stripped", binName)
- p.stripExecutableOrSharedLib(ctx, in, stripped, builderFlags)
+ p.stripper.StripExecutableOrSharedLib(ctx, in, stripped, stripFlags)
in = stripped
}
@@ -349,8 +364,8 @@ func (p *vendorSnapshotBinaryDecorator) link(ctx ModuleContext,
return outputFile
}
-func (p *vendorSnapshotBinaryDecorator) isSnapshotPrebuilt() bool {
- return true
+func (p *vendorSnapshotBinaryDecorator) nativeCoverage() bool {
+ return false
}
func VendorSnapshotBinaryFactory() android.Module {
@@ -372,51 +387,23 @@ func VendorSnapshotBinaryFactory() android.Module {
module.stl = nil
module.linker = prebuilt
- android.AddLoadHook(module, func(ctx android.LoadHookContext) {
- vendorSnapshotLoadHook(ctx, prebuilt)
- })
-
+ prebuilt.init(module, vendorSnapshotBinarySuffix)
module.AddProperties(&prebuilt.properties)
return module.Init()
}
type vendorSnapshotObjectProperties struct {
- // snapshot version.
- Version string
-
- // Target arch name of the snapshot (e.g. 'arm64' for variant 'aosp_arm64_ab')
- Target_arch string
-
// Prebuilt file for each arch.
Src *string `android:"arch_variant"`
}
type vendorSnapshotObjectLinker struct {
+ vendorSnapshotModuleBase
objectLinker
properties vendorSnapshotObjectProperties
androidMkVendorSuffix bool
}
-func (p *vendorSnapshotObjectLinker) Name(name string) string {
- return name + p.NameSuffix()
-}
-
-func (p *vendorSnapshotObjectLinker) NameSuffix() string {
- versionSuffix := p.version()
- if p.arch() != "" {
- versionSuffix += "." + p.arch()
- }
- return vendorSnapshotObjectSuffix + versionSuffix
-}
-
-func (p *vendorSnapshotObjectLinker) version() string {
- return p.properties.Version
-}
-
-func (p *vendorSnapshotObjectLinker) arch() string {
- return p.properties.Target_arch
-}
-
func (p *vendorSnapshotObjectLinker) matchesWithDevice(config android.DeviceConfig) bool {
if config.DeviceArch() != p.arch() {
return false
@@ -443,10 +430,6 @@ func (p *vendorSnapshotObjectLinker) nativeCoverage() bool {
return false
}
-func (p *vendorSnapshotObjectLinker) isSnapshotPrebuilt() bool {
- return true
-}
-
func VendorSnapshotObjectFactory() android.Module {
module := newObject()
@@ -457,10 +440,7 @@ func VendorSnapshotObjectFactory() android.Module {
}
module.linker = prebuilt
- android.AddLoadHook(module, func(ctx android.LoadHookContext) {
- vendorSnapshotLoadHook(ctx, prebuilt)
- })
-
+ prebuilt.init(module, vendorSnapshotObjectSuffix)
module.AddProperties(&prebuilt.properties)
return module.Init()
}
@@ -484,18 +464,22 @@ type vendorSnapshotSingleton struct {
var (
// Modules under following directories are ignored. They are OEM's and vendor's
- // proprietary modules(device/, vendor/, and hardware/).
+ // proprietary modules(device/, kernel/, vendor/, and hardware/).
// TODO(b/65377115): Clean up these with more maintainable way
vendorProprietaryDirs = []string{
"device",
+ "kernel",
"vendor",
"hardware",
}
// Modules under following directories are included as they are in AOSP,
- // although hardware/ is normally for vendor's own.
+ // although hardware/ and kernel/ are normally for vendor's own.
// TODO(b/65377115): Clean up these with more maintainable way
aospDirsUnderProprietary = []string{
+ "kernel/configs",
+ "kernel/prebuilts",
+ "kernel/tests",
"hardware/interfaces",
"hardware/libhardware",
"hardware/libhardware_legacy",
@@ -552,18 +536,29 @@ func isVendorSnapshotModule(m *Module, moduleDir string) bool {
if _, ok := m.linker.(*kernelHeadersDecorator); ok {
return false
}
+ // skip llndk_library and llndk_headers which are backward compatible
+ if _, ok := m.linker.(*llndkStubDecorator); ok {
+ return false
+ }
+ if _, ok := m.linker.(*llndkHeadersDecorator); ok {
+ return false
+ }
// Libraries
if l, ok := m.linker.(snapshotLibraryInterface); ok {
// TODO(b/65377115): add full support for sanitizer
if m.sanitize != nil {
- // cfi, scs and hwasan export both sanitized and unsanitized variants for static and header
+ // scs and hwasan export both sanitized and unsanitized variants for static and header
// Always use unsanitized variants of them.
- for _, t := range []sanitizerType{cfi, scs, hwasan} {
+ for _, t := range []sanitizerType{scs, hwasan} {
if !l.shared() && m.sanitize.isSanitizerEnabled(t) {
return false
}
}
+ // cfi also exports both variants. But for static, we capture both.
+ if !l.static() && !l.shared() && m.sanitize.isSanitizerEnabled(cfi) {
+ return false
+ }
}
if l.static() {
return m.outputFile.Valid() && proptools.BoolDefault(m.VendorProperties.Vendor_available, true)
@@ -657,6 +652,7 @@ func (c *vendorSnapshotSingleton) GenerateBuildActions(ctx android.SingletonCont
ExportedDirs []string `json:",omitempty"`
ExportedSystemDirs []string `json:",omitempty"`
ExportedFlags []string `json:",omitempty"`
+ Sanitize string `json:",omitempty"`
SanitizeMinimalDep bool `json:",omitempty"`
SanitizeUbsanDep bool `json:",omitempty"`
@@ -706,6 +702,7 @@ func (c *vendorSnapshotSingleton) GenerateBuildActions(ctx android.SingletonCont
var propOut string
if l, ok := m.linker.(snapshotLibraryInterface); ok {
+
// library flags
prop.ExportedFlags = l.exportedFlags()
for _, dir := range l.exportedDirs() {
@@ -738,6 +735,15 @@ func (c *vendorSnapshotSingleton) GenerateBuildActions(ctx android.SingletonCont
if libType != "header" {
libPath := m.outputFile.Path()
stem = libPath.Base()
+ if l.static() && m.sanitize != nil && m.sanitize.isSanitizerEnabled(cfi) {
+ // both cfi and non-cfi variant for static libraries can exist.
+ // attach .cfi to distinguish between cfi and non-cfi.
+ // e.g. libbase.a -> libbase.cfi.a
+ ext := filepath.Ext(stem)
+ stem = strings.TrimSuffix(stem, ext) + ".cfi" + ext
+ prop.Sanitize = "cfi"
+ prop.ModuleName += ".cfi"
+ }
snapshotLibOut := filepath.Join(snapshotArchDir, targetArch, libType, stem)
ret = append(ret, copyFile(ctx, libPath, snapshotLibOut))
} else {
diff --git a/cc/vndk.go b/cc/vndk.go
index 4adf9d226..23bb095bc 100644
--- a/cc/vndk.go
+++ b/cc/vndk.go
@@ -26,6 +26,8 @@ import (
"android/soong/android"
"android/soong/cc/config"
"android/soong/etc"
+
+ "github.com/google/blueprint"
)
const (
@@ -127,7 +129,7 @@ func (vndk *vndkdep) typeName() string {
return "native:vendor:vndkspext"
}
-func (vndk *vndkdep) vndkCheckLinkType(ctx android.ModuleContext, to *Module, tag DependencyTag) {
+func (vndk *vndkdep) vndkCheckLinkType(ctx android.ModuleContext, to *Module, tag blueprint.DependencyTag) {
if to.linker == nil {
return
}
@@ -340,7 +342,7 @@ func processVndkLibrary(mctx android.BottomUpMutatorContext, m *Module) {
}
}
-// Sanity check for modules that mustn't be VNDK
+// Check for modules that mustn't be VNDK
func shouldSkipVndkMutator(m *Module) bool {
if !m.Enabled() {
return true
@@ -559,10 +561,6 @@ func (c *vndkSnapshotSingleton) GenerateBuildActions(ctx android.SingletonContex
return
}
- if ctx.DeviceConfig().BoardVndkRuntimeDisable() {
- return
- }
-
var snapshotOutputs android.Paths
/*
diff --git a/cc/vndk_prebuilt.go b/cc/vndk_prebuilt.go
index 5a44c4663..94847601e 100644
--- a/cc/vndk_prebuilt.go
+++ b/cc/vndk_prebuilt.go
@@ -142,9 +142,10 @@ func (p *vndkPrebuiltLibraryDecorator) link(ctx ModuleContext,
builderFlags := flagsToBuilderFlags(flags)
p.unstrippedOutputFile = in
libName := in.Base()
- if p.needsStrip(ctx) {
+ if p.stripper.NeedsStrip(ctx) {
+ stripFlags := flagsToStripFlags(flags)
stripped := android.PathForModuleOut(ctx, "stripped", libName)
- p.stripExecutableOrSharedLib(ctx, in, stripped, builderFlags)
+ p.stripper.StripExecutableOrSharedLib(ctx, in, stripped, stripFlags)
in = stripped
}
@@ -213,7 +214,7 @@ func vndkPrebuiltSharedLibrary() *Module {
library.BuildOnlyShared()
module.stl = nil
module.sanitize = nil
- library.StripProperties.Strip.None = BoolPtr(true)
+ library.disableStripping()
prebuilt := &vndkPrebuiltLibraryDecorator{
libraryDecorator: library,
diff --git a/cmd/diff_target_files/Android.bp b/cmd/diff_target_files/Android.bp
index 5397f4b74..bc6b068b9 100644
--- a/cmd/diff_target_files/Android.bp
+++ b/cmd/diff_target_files/Android.bp
@@ -5,12 +5,12 @@ blueprint_go_binary {
"diff_target_files.go",
"glob.go",
"target_files.go",
- "whitelist.go",
+ "allow_list.go",
"zip_artifact.go",
],
testSrcs: [
"compare_test.go",
"glob_test.go",
- "whitelist_test.go",
+ "allow_list_test.go",
],
}
diff --git a/cmd/diff_target_files/whitelist.go b/cmd/diff_target_files/allow_list.go
index f00fc1ee2..ca55b43e1 100644
--- a/cmd/diff_target_files/whitelist.go
+++ b/cmd/diff_target_files/allow_list.go
@@ -25,18 +25,13 @@ import (
"unicode"
)
-type jsonWhitelist struct {
- Paths []string
- IgnoreMatchingLines []string
-}
-
-type whitelist struct {
+type allowList struct {
path string
ignoreMatchingLines []string
}
-func parseWhitelists(whitelists []string, whitelistFiles []string) ([]whitelist, error) {
- var ret []whitelist
+func parseAllowLists(allowLists []string, allowListFiles []string) ([]allowList, error) {
+ var ret []allowList
add := func(path string, ignoreMatchingLines []string) {
for _, x := range ret {
@@ -46,24 +41,24 @@ func parseWhitelists(whitelists []string, whitelistFiles []string) ([]whitelist,
}
}
- ret = append(ret, whitelist{
+ ret = append(ret, allowList{
path: path,
ignoreMatchingLines: ignoreMatchingLines,
})
}
- for _, file := range whitelistFiles {
- newWhitelists, err := parseWhitelistFile(file)
+ for _, file := range allowListFiles {
+ newAllowlists, err := parseAllowListFile(file)
if err != nil {
return nil, err
}
- for _, w := range newWhitelists {
+ for _, w := range newAllowlists {
add(w.path, w.ignoreMatchingLines)
}
}
- for _, s := range whitelists {
+ for _, s := range allowLists {
colon := strings.IndexRune(s, ':')
var ignoreMatchingLines []string
if colon >= 0 {
@@ -75,7 +70,7 @@ func parseWhitelists(whitelists []string, whitelistFiles []string) ([]whitelist,
return ret, nil
}
-func parseWhitelistFile(file string) ([]whitelist, error) {
+func parseAllowListFile(file string) ([]allowList, error) {
r, err := os.Open(file)
if err != nil {
return nil, err
@@ -84,27 +79,32 @@ func parseWhitelistFile(file string) ([]whitelist, error) {
d := json.NewDecoder(newJSONCommentStripper(r))
- var jsonWhitelists []jsonWhitelist
+ var jsonAllowLists []struct {
+ Paths []string
+ IgnoreMatchingLines []string
+ }
- err = d.Decode(&jsonWhitelists)
+ if err := d.Decode(&jsonAllowLists); err != nil {
+ return nil, err
+ }
- var whitelists []whitelist
- for _, w := range jsonWhitelists {
+ var allowLists []allowList
+ for _, w := range jsonAllowLists {
for _, p := range w.Paths {
- whitelists = append(whitelists, whitelist{
+ allowLists = append(allowLists, allowList{
path: p,
ignoreMatchingLines: w.IgnoreMatchingLines,
})
}
}
- return whitelists, err
+ return allowLists, err
}
-func filterModifiedPaths(l [][2]*ZipArtifactFile, whitelists []whitelist) ([][2]*ZipArtifactFile, error) {
+func filterModifiedPaths(l [][2]*ZipArtifactFile, allowLists []allowList) ([][2]*ZipArtifactFile, error) {
outer:
for i := 0; i < len(l); i++ {
- for _, w := range whitelists {
+ for _, w := range allowLists {
if match, err := Match(w.path, l[i][0].Name); err != nil {
return l, err
} else if match {
@@ -126,10 +126,10 @@ outer:
return l, nil
}
-func filterNewPaths(l []*ZipArtifactFile, whitelists []whitelist) ([]*ZipArtifactFile, error) {
+func filterNewPaths(l []*ZipArtifactFile, allowLists []allowList) ([]*ZipArtifactFile, error) {
outer:
for i := 0; i < len(l); i++ {
- for _, w := range whitelists {
+ for _, w := range allowLists {
if match, err := Match(w.path, l[i].Name); err != nil {
return l, err
} else if match && len(w.ignoreMatchingLines) == 0 {
@@ -192,18 +192,18 @@ func diffIgnoringMatchingLines(a *ZipArtifactFile, b *ZipArtifactFile, ignoreMat
return bytes.Compare(bufA, bufB) == 0, nil
}
-func applyWhitelists(diff zipDiff, whitelists []whitelist) (zipDiff, error) {
+func applyAllowLists(diff zipDiff, allowLists []allowList) (zipDiff, error) {
var err error
- diff.modified, err = filterModifiedPaths(diff.modified, whitelists)
+ diff.modified, err = filterModifiedPaths(diff.modified, allowLists)
if err != nil {
return diff, err
}
- diff.onlyInA, err = filterNewPaths(diff.onlyInA, whitelists)
+ diff.onlyInA, err = filterNewPaths(diff.onlyInA, allowLists)
if err != nil {
return diff, err
}
- diff.onlyInB, err = filterNewPaths(diff.onlyInB, whitelists)
+ diff.onlyInB, err = filterNewPaths(diff.onlyInB, allowLists)
if err != nil {
return diff, err
}
diff --git a/cmd/diff_target_files/whitelist_test.go b/cmd/diff_target_files/allow_list_test.go
index 4b19fdd21..8410e5acc 100644
--- a/cmd/diff_target_files/whitelist_test.go
+++ b/cmd/diff_target_files/allow_list_test.go
@@ -57,10 +57,10 @@ c
var f2 = bytesToZipArtifactFile("dir/f2", nil)
-func Test_applyWhitelists(t *testing.T) {
+func Test_applyAllowLists(t *testing.T) {
type args struct {
diff zipDiff
- whitelists []whitelist
+ allowLists []allowList
}
tests := []struct {
name string
@@ -74,7 +74,7 @@ func Test_applyWhitelists(t *testing.T) {
diff: zipDiff{
onlyInA: []*ZipArtifactFile{f1a, f2},
},
- whitelists: []whitelist{{path: "dir/f1"}},
+ allowLists: []allowList{{path: "dir/f1"}},
},
want: zipDiff{
onlyInA: []*ZipArtifactFile{f2},
@@ -86,7 +86,7 @@ func Test_applyWhitelists(t *testing.T) {
diff: zipDiff{
onlyInA: []*ZipArtifactFile{f1a, f2},
},
- whitelists: []whitelist{{path: "dir/*"}},
+ allowLists: []allowList{{path: "dir/*"}},
},
want: zipDiff{},
},
@@ -96,7 +96,7 @@ func Test_applyWhitelists(t *testing.T) {
diff: zipDiff{
modified: [][2]*ZipArtifactFile{{f1a, f1b}},
},
- whitelists: []whitelist{{path: "dir/*"}},
+ allowLists: []allowList{{path: "dir/*"}},
},
want: zipDiff{},
},
@@ -106,20 +106,20 @@ func Test_applyWhitelists(t *testing.T) {
diff: zipDiff{
modified: [][2]*ZipArtifactFile{{f1a, f1b}},
},
- whitelists: []whitelist{{path: "dir/*", ignoreMatchingLines: []string{"foo: .*"}}},
+ allowLists: []allowList{{path: "dir/*", ignoreMatchingLines: []string{"foo: .*"}}},
},
want: zipDiff{},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
- got, err := applyWhitelists(tt.args.diff, tt.args.whitelists)
+ got, err := applyAllowLists(tt.args.diff, tt.args.allowLists)
if (err != nil) != tt.wantErr {
- t.Errorf("applyWhitelists() error = %v, wantErr %v", err, tt.wantErr)
+ t.Errorf("Test_applyAllowLists() error = %v, wantErr %v", err, tt.wantErr)
return
}
if !reflect.DeepEqual(got, tt.want) {
- t.Errorf("applyWhitelists() = %v, want %v", got, tt.want)
+ t.Errorf("Test_applyAllowLists() = %v, want %v", got, tt.want)
}
})
}
diff --git a/cmd/diff_target_files/compare.go b/cmd/diff_target_files/compare.go
index 00cd9ca10..45b6d6b1c 100644
--- a/cmd/diff_target_files/compare.go
+++ b/cmd/diff_target_files/compare.go
@@ -21,7 +21,7 @@ import (
// compareTargetFiles takes two ZipArtifacts and compares the files they contain by examining
// the path, size, and CRC of each file.
-func compareTargetFiles(priZip, refZip ZipArtifact, artifact string, whitelists []whitelist, filters []string) (zipDiff, error) {
+func compareTargetFiles(priZip, refZip ZipArtifact, artifact string, allowLists []allowList, filters []string) (zipDiff, error) {
priZipFiles, err := priZip.Files()
if err != nil {
return zipDiff{}, fmt.Errorf("error fetching target file lists from primary zip %v", err)
@@ -45,7 +45,7 @@ func compareTargetFiles(priZip, refZip ZipArtifact, artifact string, whitelists
// Compare the file lists from both builds
diff := diffTargetFilesLists(refZipFiles, priZipFiles)
- return applyWhitelists(diff, whitelists)
+ return applyAllowLists(diff, allowLists)
}
// zipDiff contains the list of files that differ between two zip files.
diff --git a/cmd/diff_target_files/diff_target_files.go b/cmd/diff_target_files/diff_target_files.go
index 75bc8ee4e..634565bca 100644
--- a/cmd/diff_target_files/diff_target_files.go
+++ b/cmd/diff_target_files/diff_target_files.go
@@ -22,8 +22,8 @@ import (
)
var (
- whitelists = newMultiString("whitelist", "whitelist patterns in the form <pattern>[:<regex of line to ignore>]")
- whitelistFiles = newMultiString("whitelist_file", "files containing whitelist definitions")
+ allowLists = newMultiString("allowlist", "allowlist patterns in the form <pattern>[:<regex of line to ignore>]")
+ allowListFiles = newMultiString("allowlist_file", "files containing allowlist definitions")
filters = newMultiString("filter", "filter patterns to apply to files in target-files.zip before comparing")
)
@@ -47,9 +47,9 @@ func main() {
os.Exit(1)
}
- whitelists, err := parseWhitelists(*whitelists, *whitelistFiles)
+ allowLists, err := parseAllowLists(*allowLists, *allowListFiles)
if err != nil {
- fmt.Fprintf(os.Stderr, "Error parsing whitelists: %v\n", err)
+ fmt.Fprintf(os.Stderr, "Error parsing allowlists: %v\n", err)
os.Exit(1)
}
@@ -67,7 +67,7 @@ func main() {
}
defer refZip.Close()
- diff, err := compareTargetFiles(priZip, refZip, targetFilesPattern, whitelists, *filters)
+ diff, err := compareTargetFiles(priZip, refZip, targetFilesPattern, allowLists, *filters)
if err != nil {
fmt.Fprintf(os.Stderr, "Error comparing zip files: %v\n", err)
os.Exit(1)
diff --git a/cmd/merge_zips/merge_zips.go b/cmd/merge_zips/merge_zips.go
index a95aca9f0..274c8eee5 100644
--- a/cmd/merge_zips/merge_zips.go
+++ b/cmd/merge_zips/merge_zips.go
@@ -429,7 +429,7 @@ func NewInputZipsManager(nInputZips, maxOpenZips int) *InputZipsManager {
if maxOpenZips < 3 {
panic(fmt.Errorf("open zips limit should be above 3"))
}
- // In the dummy element .older points to the most recently opened InputZip, and .newer points to the oldest.
+ // In the fake element .older points to the most recently opened InputZip, and .newer points to the oldest.
head := new(ManagedInputZip)
head.older = head
head.newer = head
diff --git a/cmd/soong_build/Android.bp b/cmd/soong_build/Android.bp
index b559bac86..4ebbe6895 100644
--- a/cmd/soong_build/Android.bp
+++ b/cmd/soong_build/Android.bp
@@ -26,6 +26,10 @@ bootstrap_go_binary {
srcs: [
"main.go",
"writedocs.go",
+ "bazel_overlay.go",
+ ],
+ testSrcs: [
+ "bazel_overlay_test.go",
],
primaryBuilder: true,
}
diff --git a/cmd/soong_build/bazel_overlay.go b/cmd/soong_build/bazel_overlay.go
new file mode 100644
index 000000000..308076d52
--- /dev/null
+++ b/cmd/soong_build/bazel_overlay.go
@@ -0,0 +1,449 @@
+// Copyright 2020 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package main
+
+import (
+ "android/soong/android"
+ "fmt"
+ "io/ioutil"
+ "os"
+ "path/filepath"
+ "reflect"
+ "strings"
+
+ "github.com/google/blueprint"
+ "github.com/google/blueprint/proptools"
+)
+
+const (
+ soongModuleLoad = `package(default_visibility = ["//visibility:public"])
+load("//:soong_module.bzl", "soong_module")
+
+`
+
+ // A BUILD file target snippet representing a Soong module
+ soongModuleTarget = `soong_module(
+ name = "%s",
+ module_name = "%s",
+ module_type = "%s",
+ module_variant = "%s",
+ module_deps = %s,
+%s)`
+
+ // The soong_module rule implementation in a .bzl file
+ soongModuleBzl = `SoongModuleInfo = provider(
+ fields = {
+ "name": "Name of module",
+ "type": "Type of module",
+ "variant": "Variant of module",
+ },
+)
+
+def _merge_dicts(*dicts):
+ """Adds a list of dictionaries into a single dictionary."""
+
+ # If keys are repeated in multiple dictionaries, the latter one "wins".
+ result = {}
+ for d in dicts:
+ result.update(d)
+
+ return result
+
+def _generic_soong_module_impl(ctx):
+ return [
+ SoongModuleInfo(
+ name = ctx.attr.module_name,
+ type = ctx.attr.module_type,
+ variant = ctx.attr.module_variant,
+ ),
+ ]
+
+_COMMON_ATTRS = {
+ "module_name": attr.string(mandatory = True),
+ "module_type": attr.string(mandatory = True),
+ "module_variant": attr.string(),
+ "module_deps": attr.label_list(providers = [SoongModuleInfo]),
+}
+
+
+generic_soong_module = rule(
+ implementation = _generic_soong_module_impl,
+ attrs = _COMMON_ATTRS,
+)
+
+# TODO(jingwen): auto generate Soong module shims
+def _soong_filegroup_impl(ctx):
+ return [SoongModuleInfo(),]
+
+soong_filegroup = rule(
+ implementation = _soong_filegroup_impl,
+ # Matches https://cs.android.com/android/platform/superproject/+/master:build/soong/android/filegroup.go;l=25-40;drc=6a6478d49e78703ba22a432c41d819c8df79ef6c
+ attrs = _merge_dicts(_COMMON_ATTRS, {
+ "srcs": attr.string_list(doc = "srcs lists files that will be included in this filegroup"),
+ "exclude_srcs": attr.string_list(),
+ "path": attr.string(doc = "The base path to the files. May be used by other modules to determine which portion of the path to use. For example, when a filegroup is used as data in a cc_test rule, the base path is stripped off the path and the remaining path is used as the installation directory."),
+ "export_to_make_var": attr.string(doc = "Create a make variable with the specified name that contains the list of files in the filegroup, relative to the root of the source tree."),
+ })
+)
+
+soong_module_rule_map = {
+ "filegroup": soong_filegroup,
+}
+
+# soong_module is a macro that supports arbitrary kwargs, and uses module_type to
+# expand to the right underlying shim.
+def soong_module(name, module_type, **kwargs):
+ soong_module_rule = soong_module_rule_map.get(module_type)
+
+ if soong_module_rule == None:
+ # This module type does not have an existing rule to map to, so use the
+ # generic_soong_module rule instead.
+ generic_soong_module(
+ name = name,
+ module_type = module_type,
+ module_name = kwargs.pop("module_name", ""),
+ module_variant = kwargs.pop("module_variant", ""),
+ module_deps = kwargs.pop("module_deps", []),
+ )
+ else:
+ soong_module_rule(
+ name = name,
+ module_type = module_type,
+ **kwargs,
+ )
+`
+)
+
+func targetNameWithVariant(c *blueprint.Context, logicModule blueprint.Module) string {
+ name := ""
+ if c.ModuleSubDir(logicModule) != "" {
+ // TODO(b/162720883): Figure out a way to drop the "--" variant suffixes.
+ name = c.ModuleName(logicModule) + "--" + c.ModuleSubDir(logicModule)
+ } else {
+ name = c.ModuleName(logicModule)
+ }
+
+ return strings.Replace(name, "//", "", 1)
+}
+
+func qualifiedTargetLabel(c *blueprint.Context, logicModule blueprint.Module) string {
+ return "//" +
+ packagePath(c, logicModule) +
+ ":" +
+ targetNameWithVariant(c, logicModule)
+}
+
+func packagePath(c *blueprint.Context, logicModule blueprint.Module) string {
+ return filepath.Dir(c.BlueprintFile(logicModule))
+}
+
+func escapeString(s string) string {
+ s = strings.ReplaceAll(s, "\\", "\\\\")
+ return strings.ReplaceAll(s, "\"", "\\\"")
+}
+
+func makeIndent(indent int) string {
+ if indent < 0 {
+ panic(fmt.Errorf("indent column cannot be less than 0, but got %d", indent))
+ }
+ return strings.Repeat(" ", indent)
+}
+
+// prettyPrint a property value into the equivalent Starlark representation
+// recursively.
+func prettyPrint(propertyValue reflect.Value, indent int) (string, error) {
+ if isZero(propertyValue) {
+ // A property value being set or unset actually matters -- Soong does set default
+ // values for unset properties, like system_shared_libs = ["libc", "libm", "libdl"] at
+ // https://cs.android.com/android/platform/superproject/+/master:build/soong/cc/linker.go;l=281-287;drc=f70926eef0b9b57faf04c17a1062ce50d209e480
+ //
+ // In Bazel-parlance, we would use "attr.<type>(default = <default value>)" to set the default
+ // value of unset attributes.
+ return "", nil
+ }
+
+ var ret string
+ switch propertyValue.Kind() {
+ case reflect.String:
+ ret = fmt.Sprintf("\"%v\"", escapeString(propertyValue.String()))
+ case reflect.Bool:
+ ret = strings.Title(fmt.Sprintf("%v", propertyValue.Interface()))
+ case reflect.Int, reflect.Uint, reflect.Int64:
+ ret = fmt.Sprintf("%v", propertyValue.Interface())
+ case reflect.Ptr:
+ return prettyPrint(propertyValue.Elem(), indent)
+ case reflect.Slice:
+ ret = "[\n"
+ for i := 0; i < propertyValue.Len(); i++ {
+ indexedValue, err := prettyPrint(propertyValue.Index(i), indent+1)
+ if err != nil {
+ return "", err
+ }
+
+ if indexedValue != "" {
+ ret += makeIndent(indent + 1)
+ ret += indexedValue
+ ret += ",\n"
+ }
+ }
+ ret += makeIndent(indent)
+ ret += "]"
+ case reflect.Struct:
+ ret = "{\n"
+ // Sort and print the struct props by the key.
+ structProps := extractStructProperties(propertyValue, indent)
+ for _, k := range android.SortedStringKeys(structProps) {
+ ret += makeIndent(indent + 1)
+ ret += "\"" + k + "\": "
+ ret += structProps[k]
+ ret += ",\n"
+ }
+ ret += makeIndent(indent)
+ ret += "}"
+ case reflect.Interface:
+ // TODO(b/164227191): implement pretty print for interfaces.
+ // Interfaces are used for for arch, multilib and target properties.
+ return "", nil
+ default:
+ return "", fmt.Errorf(
+ "unexpected kind for property struct field: %s", propertyValue.Kind())
+ }
+ return ret, nil
+}
+
+func extractStructProperties(structValue reflect.Value, indent int) map[string]string {
+ if structValue.Kind() != reflect.Struct {
+ panic(fmt.Errorf("Expected a reflect.Struct type, but got %s", structValue.Kind()))
+ }
+
+ ret := map[string]string{}
+ structType := structValue.Type()
+ for i := 0; i < structValue.NumField(); i++ {
+ field := structType.Field(i)
+ if field.PkgPath != "" {
+ // Skip unexported fields. Some properties are
+ // internal to Soong only, and these fields do not have PkgPath.
+ continue
+ }
+ if proptools.HasTag(field, "blueprint", "mutated") {
+ continue
+ }
+
+ fieldValue := structValue.Field(i)
+ if isZero(fieldValue) {
+ // Ignore zero-valued fields
+ continue
+ }
+
+ propertyName := proptools.PropertyNameForField(field.Name)
+ prettyPrintedValue, err := prettyPrint(fieldValue, indent+1)
+ if err != nil {
+ panic(
+ fmt.Errorf(
+ "Error while parsing property: %q. %s",
+ propertyName,
+ err))
+ }
+ if prettyPrintedValue != "" {
+ ret[propertyName] = prettyPrintedValue
+ }
+ }
+
+ return ret
+}
+
+func isStructPtr(t reflect.Type) bool {
+ return t.Kind() == reflect.Ptr && t.Elem().Kind() == reflect.Struct
+}
+
+// Generically extract module properties and types into a map, keyed by the module property name.
+func extractModuleProperties(aModule android.Module) map[string]string {
+ ret := map[string]string{}
+
+ // Iterate over this android.Module's property structs.
+ for _, properties := range aModule.GetProperties() {
+ propertiesValue := reflect.ValueOf(properties)
+ // Check that propertiesValue is a pointer to the Properties struct, like
+ // *cc.BaseLinkerProperties or *java.CompilerProperties.
+ //
+ // propertiesValue can also be type-asserted to the structs to
+ // manipulate internal props, if needed.
+ if isStructPtr(propertiesValue.Type()) {
+ structValue := propertiesValue.Elem()
+ for k, v := range extractStructProperties(structValue, 0) {
+ ret[k] = v
+ }
+ } else {
+ panic(fmt.Errorf(
+ "properties must be a pointer to a struct, got %T",
+ propertiesValue.Interface()))
+ }
+
+ }
+
+ return ret
+}
+
+func createBazelOverlay(ctx *android.Context, bazelOverlayDir string) error {
+ blueprintCtx := ctx.Context
+ blueprintCtx.VisitAllModules(func(module blueprint.Module) {
+ buildFile, err := buildFileForModule(blueprintCtx, module)
+ if err != nil {
+ panic(err)
+ }
+
+ buildFile.Write([]byte(generateSoongModuleTarget(blueprintCtx, module) + "\n\n"))
+ buildFile.Close()
+ })
+
+ if err := writeReadOnlyFile(bazelOverlayDir, "WORKSPACE", ""); err != nil {
+ return err
+ }
+
+ if err := writeReadOnlyFile(bazelOverlayDir, "BUILD", ""); err != nil {
+ return err
+ }
+
+ return writeReadOnlyFile(bazelOverlayDir, "soong_module.bzl", soongModuleBzl)
+}
+
+var ignoredProps map[string]bool = map[string]bool{
+ "name": true, // redundant, since this is explicitly generated for every target
+ "from": true, // reserved keyword
+ "in": true, // reserved keyword
+ "arch": true, // interface prop type is not supported yet.
+ "multilib": true, // interface prop type is not supported yet.
+ "target": true, // interface prop type is not supported yet.
+ "visibility": true, // Bazel has native visibility semantics. Handle later.
+}
+
+func shouldGenerateAttribute(prop string) bool {
+ return !ignoredProps[prop]
+}
+
+// props is an unsorted map. This function ensures that
+// the generated attributes are sorted to ensure determinism.
+func propsToAttributes(props map[string]string) string {
+ var attributes string
+ for _, propName := range android.SortedStringKeys(props) {
+ if shouldGenerateAttribute(propName) {
+ attributes += fmt.Sprintf(" %s = %s,\n", propName, props[propName])
+ }
+ }
+ return attributes
+}
+
+// Convert a module and its deps and props into a Bazel macro/rule
+// representation in the BUILD file.
+func generateSoongModuleTarget(
+ blueprintCtx *blueprint.Context,
+ module blueprint.Module) string {
+
+ var props map[string]string
+ if aModule, ok := module.(android.Module); ok {
+ props = extractModuleProperties(aModule)
+ }
+ attributes := propsToAttributes(props)
+
+ // TODO(b/163018919): DirectDeps can have duplicate (module, variant)
+ // items, if the modules are added using different DependencyTag. Figure
+ // out the implications of that.
+ depLabels := map[string]bool{}
+ blueprintCtx.VisitDirectDeps(module, func(depModule blueprint.Module) {
+ depLabels[qualifiedTargetLabel(blueprintCtx, depModule)] = true
+ })
+
+ depLabelList := "[\n"
+ for depLabel, _ := range depLabels {
+ depLabelList += " \""
+ depLabelList += depLabel
+ depLabelList += "\",\n"
+ }
+ depLabelList += " ]"
+
+ return fmt.Sprintf(
+ soongModuleTarget,
+ targetNameWithVariant(blueprintCtx, module),
+ blueprintCtx.ModuleName(module),
+ blueprintCtx.ModuleType(module),
+ blueprintCtx.ModuleSubDir(module),
+ depLabelList,
+ attributes)
+}
+
+func buildFileForModule(ctx *blueprint.Context, module blueprint.Module) (*os.File, error) {
+ // Create nested directories for the BUILD file
+ dirPath := filepath.Join(bazelOverlayDir, packagePath(ctx, module))
+ if _, err := os.Stat(dirPath); os.IsNotExist(err) {
+ os.MkdirAll(dirPath, os.ModePerm)
+ }
+ // Open the file for appending, and create it if it doesn't exist
+ f, err := os.OpenFile(
+ filepath.Join(dirPath, "BUILD.bazel"),
+ os.O_APPEND|os.O_CREATE|os.O_WRONLY,
+ 0644)
+ if err != nil {
+ return nil, err
+ }
+
+ // If the file is empty, add the load statement for the `soong_module` rule
+ fi, err := f.Stat()
+ if err != nil {
+ return nil, err
+ }
+ if fi.Size() == 0 {
+ f.Write([]byte(soongModuleLoad + "\n"))
+ }
+
+ return f, nil
+}
+
+// The overlay directory should be read-only, sufficient for bazel query.
+func writeReadOnlyFile(dir string, baseName string, content string) error {
+ workspaceFile := filepath.Join(bazelOverlayDir, baseName)
+ // 0444 is read-only
+ return ioutil.WriteFile(workspaceFile, []byte(content), 0444)
+}
+
+func isZero(value reflect.Value) bool {
+ switch value.Kind() {
+ case reflect.Func, reflect.Map, reflect.Slice:
+ return value.IsNil()
+ case reflect.Array:
+ valueIsZero := true
+ for i := 0; i < value.Len(); i++ {
+ valueIsZero = valueIsZero && isZero(value.Index(i))
+ }
+ return valueIsZero
+ case reflect.Struct:
+ valueIsZero := true
+ for i := 0; i < value.NumField(); i++ {
+ if value.Field(i).CanSet() {
+ valueIsZero = valueIsZero && isZero(value.Field(i))
+ }
+ }
+ return valueIsZero
+ case reflect.Ptr:
+ if !value.IsNil() {
+ return isZero(reflect.Indirect(value))
+ } else {
+ return true
+ }
+ default:
+ zeroValue := reflect.Zero(value.Type())
+ result := value.Interface() == zeroValue.Interface()
+ return result
+ }
+}
diff --git a/cmd/soong_build/bazel_overlay_test.go b/cmd/soong_build/bazel_overlay_test.go
new file mode 100644
index 000000000..8db784d6b
--- /dev/null
+++ b/cmd/soong_build/bazel_overlay_test.go
@@ -0,0 +1,255 @@
+// Copyright 2020 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package main
+
+import (
+ "android/soong/android"
+ "io/ioutil"
+ "os"
+ "testing"
+)
+
+var buildDir string
+
+func setUp() {
+ var err error
+ buildDir, err = ioutil.TempDir("", "bazel_overlay_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())
+}
+
+type customModule struct {
+ android.ModuleBase
+}
+
+func (m *customModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ // nothing for now.
+}
+
+func customModuleFactory() android.Module {
+ module := &customModule{}
+ android.InitAndroidModule(module)
+ return module
+}
+
+func TestGenerateBazelOverlayFromBlueprint(t *testing.T) {
+ testCases := []struct {
+ bp string
+ expectedBazelTarget string
+ }{
+ {
+ bp: `custom {
+ name: "foo",
+}
+ `,
+ expectedBazelTarget: `soong_module(
+ name = "foo",
+ module_name = "foo",
+ module_type = "custom",
+ module_variant = "",
+ module_deps = [
+ ],
+)`,
+ },
+ {
+ bp: `custom {
+ name: "foo",
+ ramdisk: true,
+}
+ `,
+ expectedBazelTarget: `soong_module(
+ name = "foo",
+ module_name = "foo",
+ module_type = "custom",
+ module_variant = "",
+ module_deps = [
+ ],
+ ramdisk = True,
+)`,
+ },
+ {
+ bp: `custom {
+ name: "foo",
+ owner: "a_string_with\"quotes\"_and_\\backslashes\\\\",
+}
+ `,
+ expectedBazelTarget: `soong_module(
+ name = "foo",
+ module_name = "foo",
+ module_type = "custom",
+ module_variant = "",
+ module_deps = [
+ ],
+ owner = "a_string_with\"quotes\"_and_\\backslashes\\\\",
+)`,
+ },
+ {
+ bp: `custom {
+ name: "foo",
+ required: ["bar"],
+}
+ `,
+ expectedBazelTarget: `soong_module(
+ name = "foo",
+ module_name = "foo",
+ module_type = "custom",
+ module_variant = "",
+ module_deps = [
+ ],
+ required = [
+ "bar",
+ ],
+)`,
+ },
+ {
+ bp: `custom {
+ name: "foo",
+ target_required: ["qux", "bazqux"],
+}
+ `,
+ expectedBazelTarget: `soong_module(
+ name = "foo",
+ module_name = "foo",
+ module_type = "custom",
+ module_variant = "",
+ module_deps = [
+ ],
+ target_required = [
+ "qux",
+ "bazqux",
+ ],
+)`,
+ },
+ {
+ bp: `custom {
+ name: "foo",
+ dist: {
+ targets: ["goal_foo"],
+ tag: ".foo",
+ },
+ dists: [
+ {
+ targets: ["goal_bar"],
+ tag: ".bar",
+ },
+ ],
+}
+ `,
+ expectedBazelTarget: `soong_module(
+ name = "foo",
+ module_name = "foo",
+ module_type = "custom",
+ module_variant = "",
+ module_deps = [
+ ],
+ dist = {
+ "tag": ".foo",
+ "targets": [
+ "goal_foo",
+ ],
+ },
+ dists = [
+ {
+ "tag": ".bar",
+ "targets": [
+ "goal_bar",
+ ],
+ },
+ ],
+)`,
+ },
+ {
+ bp: `custom {
+ name: "foo",
+ required: ["bar"],
+ target_required: ["qux", "bazqux"],
+ ramdisk: true,
+ owner: "custom_owner",
+ dists: [
+ {
+ tag: ".tag",
+ targets: ["my_goal"],
+ },
+ ],
+}
+ `,
+ expectedBazelTarget: `soong_module(
+ name = "foo",
+ module_name = "foo",
+ module_type = "custom",
+ module_variant = "",
+ module_deps = [
+ ],
+ dists = [
+ {
+ "tag": ".tag",
+ "targets": [
+ "my_goal",
+ ],
+ },
+ ],
+ owner = "custom_owner",
+ ramdisk = True,
+ required = [
+ "bar",
+ ],
+ target_required = [
+ "qux",
+ "bazqux",
+ ],
+)`,
+ },
+ }
+
+ for _, testCase := range testCases {
+ config := android.TestConfig(buildDir, nil, testCase.bp, nil)
+ ctx := android.NewTestContext()
+ ctx.RegisterModuleType("custom", customModuleFactory)
+ ctx.Register(config)
+
+ _, errs := ctx.ParseFileList(".", []string{"Android.bp"})
+ android.FailIfErrored(t, errs)
+ _, errs = ctx.PrepareBuildActions(config)
+ android.FailIfErrored(t, errs)
+
+ module := ctx.ModuleForTests("foo", "").Module().(*customModule)
+ blueprintCtx := ctx.Context.Context
+
+ actualBazelTarget := generateSoongModuleTarget(blueprintCtx, module)
+ if actualBazelTarget != testCase.expectedBazelTarget {
+ t.Errorf(
+ "Expected generated Bazel target to be '%s', got '%s'",
+ testCase.expectedBazelTarget,
+ actualBazelTarget,
+ )
+ }
+ }
+}
diff --git a/cmd/soong_build/main.go b/cmd/soong_build/main.go
index 532d9e486..01a39a216 100644
--- a/cmd/soong_build/main.go
+++ b/cmd/soong_build/main.go
@@ -26,11 +26,13 @@ import (
)
var (
- docFile string
+ docFile string
+ bazelOverlayDir string
)
func init() {
flag.StringVar(&docFile, "soong_docs", "", "build documentation file to output")
+ flag.StringVar(&bazelOverlayDir, "bazel_overlay_dir", "", "path to the bazel overlay directory")
}
func newNameResolver(config android.Config) *android.NameResolver {
@@ -65,7 +67,7 @@ func main() {
os.Exit(1)
}
- if docFile != "" {
+ if !shouldPrepareBuildActions() {
configuration.SetStopBefore(bootstrap.StopBeforePrepareBuildActions)
}
@@ -85,6 +87,13 @@ func main() {
bootstrap.Main(ctx.Context, configuration, extraNinjaDeps...)
+ if bazelOverlayDir != "" {
+ if err := createBazelOverlay(ctx, bazelOverlayDir); err != nil {
+ fmt.Fprintf(os.Stderr, "%s", err)
+ os.Exit(1)
+ }
+ }
+
if docFile != "" {
if err := writeDocs(ctx, docFile); err != nil {
fmt.Fprintf(os.Stderr, "%s", err)
@@ -94,7 +103,7 @@ func main() {
// TODO(ccross): make this a command line argument. Requires plumbing through blueprint
// to affect the command line of the primary builder.
- if docFile == "" {
+ if shouldPrepareBuildActions() {
metricsFile := filepath.Join(bootstrap.BuildDir, "soong_build_metrics.pb")
err = android.WriteMetrics(configuration, metricsFile)
if err != nil {
@@ -103,3 +112,9 @@ func main() {
}
}
}
+
+func shouldPrepareBuildActions() bool {
+ // If we're writing soong_docs or bazel_overlay, don't write build.ninja or
+ // collect metrics.
+ return docFile == "" && bazelOverlayDir == ""
+}
diff --git a/cmd/soong_ui/main.go b/cmd/soong_ui/main.go
index e485c60e0..4aa62be3c 100644
--- a/cmd/soong_ui/main.go
+++ b/cmd/soong_ui/main.go
@@ -35,14 +35,14 @@ import (
// A command represents an operation to be executed in the soong build
// system.
type command struct {
- // the flag name (must have double dashes)
+ // The flag name (must have double dashes).
flag string
- // description for the flag (to display when running help)
+ // Description for the flag (to display when running help).
description string
- // Forces the status output into dumb terminal mode.
- forceDumbOutput bool
+ // Stream the build status output into the simple terminal mode.
+ simpleOutput bool
// Sets a prefix string to use for filenames of log files.
logsPrefix string
@@ -70,21 +70,21 @@ var commands []command = []command{
stdio: stdio,
run: make,
}, {
- flag: "--dumpvar-mode",
- description: "print the value of the legacy make variable VAR to stdout",
- forceDumbOutput: true,
- logsPrefix: "dumpvars-",
- config: dumpVarConfig,
- stdio: customStdio,
- run: dumpVar,
+ flag: "--dumpvar-mode",
+ description: "print the value of the legacy make variable VAR to stdout",
+ simpleOutput: true,
+ logsPrefix: "dumpvars-",
+ config: dumpVarConfig,
+ stdio: customStdio,
+ run: dumpVar,
}, {
- flag: "--dumpvars-mode",
- description: "dump the values of one or more legacy make variables, in shell syntax",
- forceDumbOutput: true,
- logsPrefix: "dumpvars-",
- config: dumpVarConfig,
- stdio: customStdio,
- run: dumpVars,
+ flag: "--dumpvars-mode",
+ description: "dump the values of one or more legacy make variables, in shell syntax",
+ simpleOutput: true,
+ logsPrefix: "dumpvars-",
+ config: dumpVarConfig,
+ stdio: customStdio,
+ run: dumpVars,
}, {
flag: "--build-mode",
description: "build modules based on the specified build action",
@@ -125,7 +125,7 @@ func main() {
os.Exit(1)
}
- output := terminal.NewStatusOutput(c.stdio().Stdout(), os.Getenv("NINJA_STATUS"), c.forceDumbOutput,
+ output := terminal.NewStatusOutput(c.stdio().Stdout(), os.Getenv("NINJA_STATUS"), c.simpleOutput,
build.OsEnvironment().IsEnvTrue("ANDROID_QUIET_BUILD"))
log := logger.New(output)
@@ -172,7 +172,8 @@ func main() {
buildErrorFile := filepath.Join(logsDir, c.logsPrefix+"build_error")
rbeMetricsFile := filepath.Join(logsDir, c.logsPrefix+"rbe_metrics.pb")
soongMetricsFile := filepath.Join(logsDir, c.logsPrefix+"soong_metrics")
- defer build.UploadMetrics(buildCtx, config, c.forceDumbOutput, buildStarted, buildErrorFile, rbeMetricsFile, soongMetricsFile)
+ defer build.UploadMetrics(buildCtx, config, c.simpleOutput, buildStarted, buildErrorFile, rbeMetricsFile, soongMetricsFile)
+ defer build.PrintGomaDeprecation(buildCtx, config)
os.MkdirAll(logsDir, 0777)
log.SetOutput(filepath.Join(logsDir, c.logsPrefix+"soong.log"))
diff --git a/dexpreopt/config.go b/dexpreopt/config.go
index 2cf65feca..f22ee4735 100644
--- a/dexpreopt/config.go
+++ b/dexpreopt/config.go
@@ -40,15 +40,15 @@ type GlobalConfig struct {
DisableGenerateProfile bool // don't generate profiles
ProfileDir string // directory to find profiles in
- BootJars []string // modules for jars that form the boot class path
- UpdatableBootJars []string // jars within apex that form the boot class path
+ BootJars android.ConfiguredJarList // modules for jars that form the boot class path
+ UpdatableBootJars android.ConfiguredJarList // jars within apex that form the boot class path
- ArtApexJars []string // modules for jars that are in the ART APEX
+ ArtApexJars android.ConfiguredJarList // modules for jars that are in the ART APEX
- SystemServerJars []string // jars that form the system server
- SystemServerApps []string // apps that are loaded into system server
- UpdatableSystemServerJars []string // jars within apex that are loaded into system server
- SpeedApps []string // apps that should be speed optimized
+ SystemServerJars []string // jars that form the system server
+ SystemServerApps []string // apps that are loaded into system server
+ UpdatableSystemServerJars android.ConfiguredJarList // jars within apex that are loaded into system server
+ SpeedApps []string // apps that should be speed optimized
BrokenSuboptimalOrderOfSystemServerJars bool // if true, sub-optimal order does not cause a build error
@@ -100,6 +100,8 @@ type GlobalSoongConfig struct {
ConstructContext android.Path
}
+const UnknownInstallLibraryPath = "error"
+
// LibraryPath contains paths to the library DEX jar on host and on device.
type LibraryPath struct {
Host android.Path
@@ -109,6 +111,54 @@ type LibraryPath struct {
// LibraryPaths is a map from library name to on-host and on-device paths to its DEX jar.
type LibraryPaths map[string]*LibraryPath
+// Add a new library path to the map, unless a path for this library already exists.
+func (libPaths LibraryPaths) addLibraryPath(ctx android.PathContext, lib string, hostPath, installPath android.Path) {
+ if _, present := libPaths[lib]; !present {
+ var devicePath string
+ if installPath != nil {
+ devicePath = android.InstallPathToOnDevicePath(ctx, installPath.(android.InstallPath))
+ } else {
+ // For some stub libraries the only known thing is the name of their implementation
+ // library, but the library itself is unavailable (missing or part of a prebuilt). In
+ // such cases we still need to add the library to <uses-library> tags in the manifest,
+ // but we cannot use if for dexpreopt.
+ devicePath = UnknownInstallLibraryPath
+ }
+ libPaths[lib] = &LibraryPath{hostPath, devicePath}
+ }
+}
+
+// Add a new library path to the map. Ensure that the build path to the library exists.
+func (libPaths LibraryPaths) AddLibraryPath(ctx android.PathContext, lib string, hostPath, installPath android.Path) {
+ if hostPath != nil {
+ // Add a library only if the build path to it is known.
+ libPaths.addLibraryPath(ctx, lib, hostPath, installPath)
+ } else if !ctx.Config().AllowMissingDependencies() {
+ // Error on libraries with unknown build paths, unless missing dependencies are allowed.
+ android.ReportPathErrorf(ctx, "unknown build path to <uses-library> '%s'", lib)
+ } else {
+ // Not adding a library to the map will likely result in disabling dexpreopt.
+ }
+}
+
+// Add a new library path to the map, if the library exists (name is not nil).
+func (libPaths LibraryPaths) MaybeAddLibraryPath(ctx android.PathContext, lib *string, hostPath, installPath android.Path) {
+ if lib != nil {
+ // Don't check the build paths, add in any case. Some libraries may be missing from the
+ // build, but their names still need to be added to <uses-library> tags in the manifest.
+ libPaths.addLibraryPath(ctx, *lib, hostPath, installPath)
+ }
+}
+
+// Add library paths from the second map to the first map (do not override existing entries).
+func (libPaths LibraryPaths) AddLibraryPaths(otherPaths LibraryPaths) {
+ for lib, path := range otherPaths {
+ if _, present := libPaths[lib]; !present {
+ libPaths[lib] = path
+ }
+ }
+}
+
type ModuleConfig struct {
Name string
DexLocation string // dex location on device
@@ -189,8 +239,12 @@ func ParseGlobalConfig(ctx android.PathContext, data []byte) (*GlobalConfig, err
// Copies of entries in GlobalConfig that are not constructable without extra parameters. They will be
// used to construct the real value manually below.
- DirtyImageObjects string
- BootImageProfiles []string
+ BootJars []string
+ UpdatableBootJars []string
+ ArtApexJars []string
+ UpdatableSystemServerJars []string
+ DirtyImageObjects string
+ BootImageProfiles []string
}
config := GlobalJSONConfig{}
@@ -200,6 +254,10 @@ func ParseGlobalConfig(ctx android.PathContext, data []byte) (*GlobalConfig, err
}
// Construct paths that require a PathContext.
+ config.GlobalConfig.BootJars = android.CreateConfiguredJarList(ctx, config.BootJars)
+ config.GlobalConfig.UpdatableBootJars = android.CreateConfiguredJarList(ctx, config.UpdatableBootJars)
+ config.GlobalConfig.ArtApexJars = android.CreateConfiguredJarList(ctx, config.ArtApexJars)
+ config.GlobalConfig.UpdatableSystemServerJars = android.CreateConfiguredJarList(ctx, config.UpdatableSystemServerJars)
config.GlobalConfig.DirtyImageObjects = android.OptionalPathForPath(constructPath(ctx, config.DirtyImageObjects))
config.GlobalConfig.BootImageProfiles = constructPaths(ctx, config.BootImageProfiles)
@@ -352,7 +410,33 @@ func RegisterToolDeps(ctx android.BottomUpMutatorContext) {
func dex2oatPathFromDep(ctx android.ModuleContext) android.Path {
dex2oatBin := dex2oatModuleName(ctx.Config())
- dex2oatModule := ctx.GetDirectDepWithTag(dex2oatBin, dex2oatDepTag)
+ // Find the right dex2oat module, trying to follow PrebuiltDepTag from source
+ // to prebuilt if there is one. We wouldn't have to do this if the
+ // prebuilt_postdeps mutator that replaces source deps with prebuilt deps was
+ // run after RegisterToolDeps above, but changing that leads to ordering
+ // problems between mutators (RegisterToolDeps needs to run late to act on
+ // final variants, while prebuilt_postdeps needs to run before many of the
+ // PostDeps mutators, like the APEX mutators). Hence we need to dig out the
+ // prebuilt explicitly here instead.
+ var dex2oatModule android.Module
+ ctx.WalkDeps(func(child, parent android.Module) bool {
+ if parent == ctx.Module() && ctx.OtherModuleDependencyTag(child) == dex2oatDepTag {
+ // Found the source module, or prebuilt module that has replaced the source.
+ dex2oatModule = child
+ if p, ok := child.(android.PrebuiltInterface); ok && p.Prebuilt() != nil {
+ return false // If it's the prebuilt we're done.
+ } else {
+ return true // Recurse to check if the source has a prebuilt dependency.
+ }
+ }
+ if parent == dex2oatModule && ctx.OtherModuleDependencyTag(child) == android.PrebuiltDepTag {
+ if p, ok := child.(android.PrebuiltInterface); ok && p.Prebuilt() != nil && p.Prebuilt().UsePrebuilt() {
+ dex2oatModule = child // Found a prebuilt that should be used.
+ }
+ }
+ return false
+ })
+
if dex2oatModule == nil {
// If this happens there's probably a missing call to AddToolDeps in DepsMutator.
panic(fmt.Sprintf("Failed to lookup %s dependency", dex2oatBin))
@@ -530,12 +614,12 @@ func GlobalConfigForTests(ctx android.PathContext) *GlobalConfig {
PatternsOnSystemOther: nil,
DisableGenerateProfile: false,
ProfileDir: "",
- BootJars: nil,
- UpdatableBootJars: nil,
- ArtApexJars: nil,
+ BootJars: android.EmptyConfiguredJarList(),
+ UpdatableBootJars: android.EmptyConfiguredJarList(),
+ ArtApexJars: android.EmptyConfiguredJarList(),
SystemServerJars: nil,
SystemServerApps: nil,
- UpdatableSystemServerJars: nil,
+ UpdatableSystemServerJars: android.EmptyConfiguredJarList(),
SpeedApps: nil,
PreoptFlags: nil,
DefaultCompilerFilter: "",
diff --git a/dexpreopt/dexpreopt.go b/dexpreopt/dexpreopt.go
index e49fa984e..4dbda49b3 100644
--- a/dexpreopt/dexpreopt.go
+++ b/dexpreopt/dexpreopt.go
@@ -37,7 +37,6 @@ import (
"fmt"
"path/filepath"
"runtime"
- "sort"
"strings"
"android/soong/android"
@@ -82,15 +81,14 @@ func GenerateDexpreoptRule(ctx android.PathContext, globalSoong *GlobalSoongConf
}
if !dexpreoptDisabled(ctx, global, module) {
- // Don't preopt individual boot jars, they will be preopted together.
- if !contains(android.GetJarsFromApexJarPairs(ctx, global.BootJars), module.Name) {
+ if clc := genClassLoaderContext(ctx, global, module); clc != nil {
appImage := (generateProfile || module.ForceCreateAppImage || global.DefaultAppImages) &&
!module.NoCreateAppImage
generateDM := shouldGenerateDM(module, global)
for archIdx, _ := range module.Archs {
- dexpreoptCommand(ctx, globalSoong, global, module, rule, archIdx, profile, appImage, generateDM)
+ dexpreoptCommand(ctx, globalSoong, global, module, rule, archIdx, *clc, profile, appImage, generateDM)
}
}
}
@@ -103,18 +101,21 @@ func dexpreoptDisabled(ctx android.PathContext, global *GlobalConfig, module *Mo
return true
}
+ // Don't preopt individual boot jars, they will be preopted together.
+ if global.BootJars.ContainsJar(module.Name) {
+ return true
+ }
+
// Don't preopt system server jars that are updatable.
- for _, p := range global.UpdatableSystemServerJars {
- if _, jar := android.SplitApexJarPair(ctx, p); jar == module.Name {
- return true
- }
+ if global.UpdatableSystemServerJars.ContainsJar(module.Name) {
+ return true
}
// If OnlyPreoptBootImageAndSystemServer=true and module is not in boot class path skip
// Also preopt system server jars since selinux prevents system server from loading anything from
// /data. If we don't do this they will need to be extracted which is not favorable for RAM usage
// or performance. If PreoptExtractedApk is true, we ignore the only preopt boot image options.
- if global.OnlyPreoptBootImageAndSystemServer && !contains(android.GetJarsFromApexJarPairs(ctx, global.BootJars), module.Name) &&
+ if global.OnlyPreoptBootImageAndSystemServer && !global.BootJars.ContainsJar(module.Name) &&
!contains(global.SystemServerJars, module.Name) && !module.PreoptExtractedApk {
return true
}
@@ -210,15 +211,6 @@ type classLoaderContextMap map[int]*classLoaderContext
const anySdkVersion int = 9999 // should go last in class loader context
-func (m classLoaderContextMap) getSortedKeys() []int {
- keys := make([]int, 0, len(m))
- for k := range m {
- keys = append(keys, k)
- }
- sort.Ints(keys)
- return keys
-}
-
func (m classLoaderContextMap) getValue(sdkVer int) *classLoaderContext {
if _, ok := m[sdkVer]; !ok {
m[sdkVer] = &classLoaderContext{}
@@ -226,13 +218,17 @@ func (m classLoaderContextMap) getValue(sdkVer int) *classLoaderContext {
return m[sdkVer]
}
-func (m classLoaderContextMap) addLibs(sdkVer int, module *ModuleConfig, libs ...string) {
+func (m classLoaderContextMap) addLibs(sdkVer int, module *ModuleConfig, libs ...string) bool {
clc := m.getValue(sdkVer)
for _, lib := range libs {
- p := pathForLibrary(module, lib)
- clc.Host = append(clc.Host, p.Host)
- clc.Target = append(clc.Target, p.Device)
+ if p := pathForLibrary(module, lib); p != nil {
+ clc.Host = append(clc.Host, p.Host)
+ clc.Target = append(clc.Target, p.Device)
+ } else {
+ return false
+ }
}
+ return true
}
func (m classLoaderContextMap) addSystemServerLibs(sdkVer int, ctx android.PathContext, module *ModuleConfig, libs ...string) {
@@ -243,9 +239,79 @@ func (m classLoaderContextMap) addSystemServerLibs(sdkVer int, ctx android.PathC
}
}
+// genClassLoaderContext generates host and target class loader context to be passed to the dex2oat
+// command for the dexpreopted module. There are three possible cases:
+//
+// 1. System server jars. They have a special class loader context that includes other system
+// server jars.
+//
+// 2. Library jars or APKs which have precise list of their <uses-library> libs. Their class loader
+// context includes build and on-device paths to these libs. In some cases it may happen that
+// the path to a <uses-library> is unknown (e.g. the dexpreopted module may depend on stubs
+// library, whose implementation library is missing from the build altogether). In such case
+// dexpreopting with the <uses-library> is impossible, and dexpreopting without it is pointless,
+// as the runtime classpath won't match and the dexpreopted code will be discarded. Therefore in
+// such cases the function returns nil, which disables dexpreopt.
+//
+// 2. All other library jars or APKs for which the exact <uses-library> list is unknown. They use
+// the unsafe &-classpath workaround that means empty class loader context and absence of runtime
+// check that the class loader context provided by the PackageManager agrees with the stored
+// class loader context recorded in the .odex file.
+//
+func genClassLoaderContext(ctx android.PathContext, global *GlobalConfig, module *ModuleConfig) *classLoaderContextMap {
+ classLoaderContexts := make(classLoaderContextMap)
+ systemServerJars := NonUpdatableSystemServerJars(ctx, global)
+
+ if jarIndex := android.IndexList(module.Name, systemServerJars); jarIndex >= 0 {
+ // System server jars should be dexpreopted together: class loader context of each jar
+ // should include all preceding jars on the system server classpath.
+ classLoaderContexts.addSystemServerLibs(anySdkVersion, ctx, module, systemServerJars[:jarIndex]...)
+
+ } else if module.EnforceUsesLibraries {
+ // Unconditional class loader context.
+ usesLibs := append(copyOf(module.UsesLibraries), module.OptionalUsesLibraries...)
+ if !classLoaderContexts.addLibs(anySdkVersion, module, usesLibs...) {
+ return nil
+ }
+
+ // Conditional class loader context for API version < 28.
+ const httpLegacy = "org.apache.http.legacy"
+ if !contains(usesLibs, httpLegacy) {
+ if !classLoaderContexts.addLibs(28, module, httpLegacy) {
+ return nil
+ }
+ }
+
+ // Conditional class loader context for API version < 29.
+ usesLibs29 := []string{
+ "android.hidl.base-V1.0-java",
+ "android.hidl.manager-V1.0-java",
+ }
+ if !classLoaderContexts.addLibs(29, module, usesLibs29...) {
+ return nil
+ }
+
+ // Conditional class loader context for API version < 30.
+ const testBase = "android.test.base"
+ if !contains(usesLibs, testBase) {
+ if !classLoaderContexts.addLibs(30, module, testBase) {
+ return nil
+ }
+ }
+
+ } else {
+ // Pass special class loader context to skip the classpath and collision check.
+ // This will get removed once LOCAL_USES_LIBRARIES is enforced.
+ // Right now LOCAL_USES_LIBRARIES is opt in, for the case where it's not specified we still default
+ // to the &.
+ }
+
+ return &classLoaderContexts
+}
+
func dexpreoptCommand(ctx android.PathContext, globalSoong *GlobalSoongConfig, global *GlobalConfig,
- module *ModuleConfig, rule *android.RuleBuilder, archIdx int, profile android.WritablePath,
- appImage bool, generateDM bool) {
+ module *ModuleConfig, rule *android.RuleBuilder, archIdx int, classLoaderContexts classLoaderContextMap,
+ profile android.WritablePath, appImage bool, generateDM bool) {
arch := module.Archs[archIdx]
@@ -276,17 +342,12 @@ func dexpreoptCommand(ctx android.PathContext, globalSoong *GlobalSoongConfig, g
invocationPath := odexPath.ReplaceExtension(ctx, "invocation")
- classLoaderContexts := make(classLoaderContextMap)
systemServerJars := NonUpdatableSystemServerJars(ctx, global)
rule.Command().FlagWithArg("mkdir -p ", filepath.Dir(odexPath.String()))
rule.Command().FlagWithOutput("rm -f ", odexPath)
if jarIndex := android.IndexList(module.Name, systemServerJars); jarIndex >= 0 {
- // System server jars should be dexpreopted together: class loader context of each jar
- // should include all preceding jars on the system server classpath.
- classLoaderContexts.addSystemServerLibs(anySdkVersion, ctx, module, systemServerJars[:jarIndex]...)
-
// Copy the system server jar to a predefined location where dex2oat will find it.
dexPathHost := SystemServerDexJarHostPath(ctx, module.Name)
rule.Command().Text("mkdir -p").Flag(filepath.Dir(dexPathHost.String()))
@@ -300,29 +361,6 @@ func dexpreoptCommand(ctx android.PathContext, globalSoong *GlobalSoongConfig, g
Implicits(clc.Host).
Text("stored_class_loader_context_arg=--stored-class-loader-context=PCL[" + strings.Join(clc.Target, ":") + "]")
} else if module.EnforceUsesLibraries {
- // Unconditional class loader context.
- usesLibs := append(copyOf(module.UsesLibraries), module.OptionalUsesLibraries...)
- classLoaderContexts.addLibs(anySdkVersion, module, usesLibs...)
-
- // Conditional class loader context for API version < 28.
- const httpLegacy = "org.apache.http.legacy"
- if !contains(usesLibs, httpLegacy) {
- classLoaderContexts.addLibs(28, module, httpLegacy)
- }
-
- // Conditional class loader context for API version < 29.
- usesLibs29 := []string{
- "android.hidl.base-V1.0-java",
- "android.hidl.manager-V1.0-java",
- }
- classLoaderContexts.addLibs(29, module, usesLibs29...)
-
- // Conditional class loader context for API version < 30.
- const testBase = "android.test.base"
- if !contains(usesLibs, testBase) {
- classLoaderContexts.addLibs(30, module, testBase)
- }
-
// Generate command that saves target SDK version in a shell variable.
if module.ManifestPath != nil {
rule.Command().Text(`target_sdk_version="$(`).
@@ -344,7 +382,7 @@ func dexpreoptCommand(ctx android.PathContext, globalSoong *GlobalSoongConfig, g
cmd := rule.Command().
Text(`eval "$(`).Tool(globalSoong.ConstructContext).
Text(` --target-sdk-version ${target_sdk_version}`)
- for _, ver := range classLoaderContexts.getSortedKeys() {
+ for _, ver := range android.SortedIntKeys(classLoaderContexts) {
clc := classLoaderContexts.getValue(ver)
verString := fmt.Sprintf("%d", ver)
if ver == anySdkVersion {
@@ -552,11 +590,11 @@ func PathToLocation(path android.Path, arch android.ArchType) string {
}
func pathForLibrary(module *ModuleConfig, lib string) *LibraryPath {
- path, ok := module.LibraryPaths[lib]
- if !ok {
- panic(fmt.Errorf("unknown library path for %q", lib))
+ if path, ok := module.LibraryPaths[lib]; ok && path.Host != nil && path.Device != "error" {
+ return path
+ } else {
+ return nil
}
- return path
}
func makefileMatch(pattern, s string) bool {
@@ -571,20 +609,13 @@ func makefileMatch(pattern, s string) bool {
}
}
-// Expected format for apexJarValue = <apex name>:<jar name>
-func GetJarLocationFromApexJarPair(ctx android.PathContext, apexJarValue string) string {
- apex, jar := android.SplitApexJarPair(ctx, apexJarValue)
- return filepath.Join("/apex", apex, "javalib", jar+".jar")
-}
-
var nonUpdatableSystemServerJarsKey = android.NewOnceKey("nonUpdatableSystemServerJars")
// TODO: eliminate the superficial global config parameter by moving global config definition
// from java subpackage to dexpreopt.
func NonUpdatableSystemServerJars(ctx android.PathContext, global *GlobalConfig) []string {
return ctx.Config().Once(nonUpdatableSystemServerJarsKey, func() interface{} {
- return android.RemoveListFromList(global.SystemServerJars,
- android.GetJarsFromApexJarPairs(ctx, global.UpdatableSystemServerJars))
+ return android.RemoveListFromList(global.SystemServerJars, global.UpdatableSystemServerJars.CopyOfJars())
}).([]string)
}
diff --git a/genrule/genrule.go b/genrule/genrule.go
index 00baa57cb..1cec2893a 100644
--- a/genrule/genrule.go
+++ b/genrule/genrule.go
@@ -259,9 +259,9 @@ func (g *Module) GenerateAndroidBuildActions(ctx android.ModuleContext) {
// If AllowMissingDependencies is enabled, the build will not have stopped when
// AddFarVariationDependencies was called on a missing tool, which will result in nonsensical
- // "cmd: unknown location label ..." errors later. Add a dummy file to the local label. The
- // command that uses this dummy file will never be executed because the rule will be replaced with
- // an android.Error rule reporting the missing dependencies.
+ // "cmd: unknown location label ..." errors later. Add a placeholder file to the local label.
+ // The command that uses this placeholder file will never be executed because the rule will be
+ // replaced with an android.Error rule reporting the missing dependencies.
if ctx.Config().AllowMissingDependencies() {
for _, tool := range g.properties.Tools {
if !seenTools[tool] {
@@ -292,9 +292,9 @@ func (g *Module) GenerateAndroidBuildActions(ctx android.ModuleContext) {
// If AllowMissingDependencies is enabled, the build will not have stopped when
// the dependency was added on a missing SourceFileProducer module, which will result in nonsensical
- // "cmd: label ":..." has no files" errors later. Add a dummy file to the local label. The
- // command that uses this dummy file will never be executed because the rule will be replaced with
- // an android.Error rule reporting the missing dependencies.
+ // "cmd: label ":..." has no files" errors later. Add a placeholder file to the local label.
+ // The command that uses this placeholder file will never be executed because the rule will be
+ // replaced with an android.Error rule reporting the missing dependencies.
ctx.AddMissingDependencies(missingDeps)
addLocationLabel(in, []string{"***missing srcs " + in + "***"})
} else {
diff --git a/go.mod b/go.mod
index 1483a3180..7297dea74 100644
--- a/go.mod
+++ b/go.mod
@@ -8,4 +8,4 @@ replace github.com/golang/protobuf v0.0.0 => ../../external/golang-protobuf
replace github.com/google/blueprint v0.0.0 => ../blueprint
-go 1.13
+go 1.15
diff --git a/java/Android.bp b/java/Android.bp
index 1fda7f71d..e345014ce 100644
--- a/java/Android.bp
+++ b/java/Android.bp
@@ -10,6 +10,7 @@ bootstrap_go_package {
"soong-dexpreopt",
"soong-genrule",
"soong-java-config",
+ "soong-python",
"soong-remoteexec",
"soong-tradefed",
],
@@ -38,6 +39,7 @@ bootstrap_go_package {
"java_resources.go",
"kotlin.go",
"lint.go",
+ "legacy_core_platform_api_usage.go",
"platform_compat_config.go",
"plugin.go",
"prebuilt_apis.go",
diff --git a/java/aar.go b/java/aar.go
index ad9b5e7d2..0f5e30deb 100644
--- a/java/aar.go
+++ b/java/aar.go
@@ -20,6 +20,7 @@ import (
"strings"
"android/soong/android"
+ "android/soong/dexpreopt"
"github.com/google/blueprint"
"github.com/google/blueprint/proptools"
@@ -99,7 +100,7 @@ type aapt struct {
useEmbeddedNativeLibs bool
useEmbeddedDex bool
usesNonSdkApis bool
- sdkLibraries []string
+ sdkLibraries dexpreopt.LibraryPaths
hasNoCode bool
LoggingParent string
resourceFiles android.Paths
@@ -231,6 +232,8 @@ func (a *aapt) buildActions(ctx android.ModuleContext, sdkContext sdkContext, ex
transitiveStaticLibs, transitiveStaticLibManifests, staticRRODirs, assetPackages, libDeps, libFlags, sdkLibraries :=
aaptLibs(ctx, sdkContext)
+ a.sdkLibraries = sdkLibraries
+
// App manifest file
manifestFile := proptools.StringDefault(a.aaptProperties.Manifest, "AndroidManifest.xml")
manifestSrcPath := android.PathForModuleSrc(ctx, manifestFile)
@@ -357,7 +360,7 @@ func (a *aapt) buildActions(ctx android.ModuleContext, sdkContext sdkContext, ex
// aaptLibs collects libraries from dependencies and sdk_version and converts them into paths
func aaptLibs(ctx android.ModuleContext, sdkContext sdkContext) (transitiveStaticLibs, transitiveStaticLibManifests android.Paths,
- staticRRODirs []rroDir, assets, deps android.Paths, flags []string, sdkLibraries []string) {
+ staticRRODirs []rroDir, assets, deps android.Paths, flags []string, sdkLibraries dexpreopt.LibraryPaths) {
var sharedLibs android.Paths
@@ -366,6 +369,8 @@ func aaptLibs(ctx android.ModuleContext, sdkContext sdkContext) (transitiveStati
sharedLibs = append(sharedLibs, sdkDep.jars...)
}
+ sdkLibraries = make(dexpreopt.LibraryPaths)
+
ctx.VisitDirectDeps(func(module android.Module) {
var exportPackage android.Path
aarDep, _ := module.(AndroidLibraryDependency)
@@ -385,7 +390,8 @@ func aaptLibs(ctx android.ModuleContext, sdkContext sdkContext) (transitiveStati
// (including the java_sdk_library) itself then append any implicit sdk library
// names to the list of sdk libraries to be added to the manifest.
if component, ok := module.(SdkLibraryComponentDependency); ok {
- sdkLibraries = append(sdkLibraries, component.OptionalImplicitSdkLibrary()...)
+ sdkLibraries.MaybeAddLibraryPath(ctx, component.OptionalImplicitSdkLibrary(),
+ component.DexJarBuildPath(), component.DexJarInstallPath())
}
case frameworkResTag:
@@ -393,11 +399,14 @@ func aaptLibs(ctx android.ModuleContext, sdkContext sdkContext) (transitiveStati
sharedLibs = append(sharedLibs, exportPackage)
}
case staticLibTag:
+ if dep, ok := module.(Dependency); ok {
+ sdkLibraries.AddLibraryPaths(dep.ExportedSdkLibs())
+ }
if exportPackage != nil {
transitiveStaticLibs = append(transitiveStaticLibs, aarDep.ExportedStaticPackages()...)
transitiveStaticLibs = append(transitiveStaticLibs, exportPackage)
transitiveStaticLibManifests = append(transitiveStaticLibManifests, aarDep.ExportedManifests()...)
- sdkLibraries = append(sdkLibraries, aarDep.ExportedSdkLibs()...)
+ sdkLibraries.AddLibraryPaths(aarDep.ExportedSdkLibs())
if aarDep.ExportedAssets().Valid() {
assets = append(assets, aarDep.ExportedAssets().Path())
}
@@ -428,7 +437,6 @@ func aaptLibs(ctx android.ModuleContext, sdkContext sdkContext) (transitiveStati
transitiveStaticLibs = android.FirstUniquePaths(transitiveStaticLibs)
transitiveStaticLibManifests = android.FirstUniquePaths(transitiveStaticLibManifests)
- sdkLibraries = android.FirstUniqueStrings(sdkLibraries)
return transitiveStaticLibs, transitiveStaticLibManifests, staticRRODirs, assets, deps, flags, sdkLibraries
}
@@ -465,8 +473,8 @@ func (a *AndroidLibrary) DepsMutator(ctx android.BottomUpMutatorContext) {
func (a *AndroidLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
a.aapt.isLibrary = true
- a.aapt.sdkLibraries = a.exportedSdkLibs
a.aapt.buildActions(ctx, sdkContext(a))
+ a.exportedSdkLibs = a.aapt.sdkLibraries
ctx.CheckbuildFile(a.proguardOptionsFile)
ctx.CheckbuildFile(a.exportPackage)
@@ -625,7 +633,7 @@ func (a *AARImport) JacocoReportClassesFile() android.Path {
}
func (a *AARImport) DepsMutator(ctx android.BottomUpMutatorContext) {
- if !ctx.Config().UnbundledBuildUsePrebuiltSdks() {
+ if !ctx.Config().AlwaysUsePrebuiltSdks() {
sdkDep := decodeSdkDep(ctx, sdkContext(a))
if sdkDep.useModule && sdkDep.frameworkResModule != "" {
ctx.AddVariationDependencies(nil, frameworkResTag, sdkDep.frameworkResModule)
@@ -641,9 +649,11 @@ func (a *AARImport) DepsMutator(ctx android.BottomUpMutatorContext) {
var unzipAAR = pctx.AndroidStaticRule("unzipAAR",
blueprint.RuleParams{
Command: `rm -rf $outDir && mkdir -p $outDir && ` +
- `unzip -qoDD -d $outDir $in && rm -rf $outDir/res && touch $out`,
+ `unzip -qoDD -d $outDir $in && rm -rf $outDir/res && touch $out && ` +
+ `${config.MergeZipsCmd} $combinedClassesJar $$(ls $outDir/classes.jar 2> /dev/null) $$(ls $outDir/libs/*.jar 2> /dev/null)`,
+ CommandDeps: []string{"${config.MergeZipsCmd}"},
},
- "outDir")
+ "outDir", "combinedClassesJar")
func (a *AARImport) GenerateAndroidBuildActions(ctx android.ModuleContext) {
if len(a.properties.Aars) != 1 {
@@ -661,7 +671,7 @@ func (a *AARImport) GenerateAndroidBuildActions(ctx android.ModuleContext) {
}
extractedAARDir := android.PathForModuleOut(ctx, "aar")
- a.classpathFile = extractedAARDir.Join(ctx, "classes.jar")
+ a.classpathFile = extractedAARDir.Join(ctx, "classes-combined.jar")
a.proguardFlags = extractedAARDir.Join(ctx, "proguard.txt")
a.manifest = extractedAARDir.Join(ctx, "AndroidManifest.xml")
@@ -671,7 +681,8 @@ func (a *AARImport) GenerateAndroidBuildActions(ctx android.ModuleContext) {
Outputs: android.WritablePaths{a.classpathFile, a.proguardFlags, a.manifest},
Description: "unzip AAR",
Args: map[string]string{
- "outDir": extractedAARDir.String(),
+ "outDir": extractedAARDir.String(),
+ "combinedClassesJar": a.classpathFile.String(),
},
})
@@ -746,7 +757,7 @@ func (a *AARImport) AidlIncludeDirs() android.Paths {
return nil
}
-func (a *AARImport) ExportedSdkLibs() []string {
+func (a *AARImport) ExportedSdkLibs() dexpreopt.LibraryPaths {
return nil
}
diff --git a/java/android_manifest.go b/java/android_manifest.go
index 8280cb1b1..f45ebe8d5 100644
--- a/java/android_manifest.go
+++ b/java/android_manifest.go
@@ -21,6 +21,7 @@ import (
"github.com/google/blueprint"
"android/soong/android"
+ "android/soong/dexpreopt"
)
var manifestFixerRule = pctx.AndroidStaticRule("manifestFixer",
@@ -52,7 +53,7 @@ var optionalUsesLibs = []string{
}
// Uses manifest_fixer.py to inject minSdkVersion, etc. into an AndroidManifest.xml
-func manifestFixer(ctx android.ModuleContext, manifest android.Path, sdkContext sdkContext, sdkLibraries []string,
+func manifestFixer(ctx android.ModuleContext, manifest android.Path, sdkContext sdkContext, sdkLibraries dexpreopt.LibraryPaths,
isLibrary, useEmbeddedNativeLibs, usesNonSdkApis, useEmbeddedDex, hasNoCode bool, loggingParent string) android.Path {
var args []string
@@ -79,7 +80,7 @@ func manifestFixer(ctx android.ModuleContext, manifest android.Path, sdkContext
args = append(args, "--use-embedded-dex")
}
- for _, usesLib := range sdkLibraries {
+ for usesLib, _ := range sdkLibraries {
if inList(usesLib, optionalUsesLibs) {
args = append(args, "--optional-uses-library", usesLib)
} else {
@@ -130,7 +131,7 @@ func manifestFixer(ctx android.ModuleContext, manifest android.Path, sdkContext
},
})
- return fixedManifest
+ return fixedManifest.WithoutRel()
}
func manifestMerger(ctx android.ModuleContext, manifest android.Path, staticLibManifests android.Paths,
@@ -155,5 +156,5 @@ func manifestMerger(ctx android.ModuleContext, manifest android.Path, staticLibM
},
})
- return mergedManifest
+ return mergedManifest.WithoutRel()
}
diff --git a/java/androidmk.go b/java/androidmk.go
index 03994bfd6..2c02e5f38 100644
--- a/java/androidmk.go
+++ b/java/androidmk.go
@@ -121,20 +121,17 @@ func (library *Library) AndroidMkEntries() []android.AndroidMkEntries {
entries.SetPath("LOCAL_SOONG_JACOCO_REPORT_CLASSES_JAR", library.jacocoReportClassesFile)
}
- entries.AddStrings("LOCAL_EXPORT_SDK_LIBRARIES", library.exportedSdkLibs...)
+ entries.AddStrings("LOCAL_EXPORT_SDK_LIBRARIES", android.SortedStringKeys(library.exportedSdkLibs)...)
if len(library.additionalCheckedModules) != 0 {
entries.AddStrings("LOCAL_ADDITIONAL_CHECKED_MODULE", library.additionalCheckedModules.Strings()...)
}
- if library.proguardDictionary != nil {
- entries.SetPath("LOCAL_SOONG_PROGUARD_DICT", library.proguardDictionary)
- }
+ entries.SetOptionalPath("LOCAL_SOONG_PROGUARD_DICT", library.dexer.proguardDictionary)
+ entries.SetOptionalPath("LOCAL_SOONG_PROGUARD_USAGE_ZIP", library.dexer.proguardUsageZip)
entries.SetString("LOCAL_MODULE_STEM", library.Stem())
- entries.AddOptionalPath("LOCAL_SOONG_LINT_REPORTS", library.linter.outputs.transitiveHTMLZip)
- entries.AddOptionalPath("LOCAL_SOONG_LINT_REPORTS", library.linter.outputs.transitiveTextZip)
- entries.AddOptionalPath("LOCAL_SOONG_LINT_REPORTS", library.linter.outputs.transitiveXMLZip)
+ entries.SetOptionalPaths("LOCAL_SOONG_LINT_REPORTS", library.linter.reports)
},
},
}
@@ -164,6 +161,7 @@ func (j *Test) AndroidMkEntries() []android.AndroidMkEntries {
if j.testConfig != nil {
entries.SetPath("LOCAL_FULL_TEST_CONFIG", j.testConfig)
}
+ androidMkWriteExtraTestConfigs(j.extraTestConfigs, entries)
androidMkWriteTestData(j.data, entries)
if !BoolDefault(j.testProperties.Auto_gen_config, true) {
entries.SetString("LOCAL_DISABLE_AUTO_GENERATE_TEST_CONFIG", "true")
@@ -173,6 +171,12 @@ func (j *Test) AndroidMkEntries() []android.AndroidMkEntries {
return entriesList
}
+func androidMkWriteExtraTestConfigs(extraTestConfigs android.Paths, entries *android.AndroidMkEntries) {
+ if len(extraTestConfigs) > 0 {
+ entries.AddStrings("LOCAL_EXTRA_FULL_TEST_CONFIGS", extraTestConfigs.Strings()...)
+ }
+}
+
func (j *TestHelperLibrary) AndroidMkEntries() []android.AndroidMkEntries {
entriesList := j.Library.AndroidMkEntries()
entries := &entriesList[0]
@@ -198,7 +202,7 @@ func (prebuilt *Import) AndroidMkEntries() []android.AndroidMkEntries {
entries.SetBool("LOCAL_UNINSTALLABLE_MODULE", !Bool(prebuilt.properties.Installable))
entries.SetPath("LOCAL_SOONG_HEADER_JAR", prebuilt.combinedClasspathFile)
entries.SetPath("LOCAL_SOONG_CLASSES_JAR", prebuilt.combinedClasspathFile)
- entries.SetString("LOCAL_SDK_VERSION", prebuilt.sdkVersion().raw)
+ entries.SetString("LOCAL_SDK_VERSION", prebuilt.makeSdkVersion())
entries.SetString("LOCAL_MODULE_STEM", prebuilt.Stem())
},
},
@@ -334,9 +338,8 @@ func (app *AndroidApp) AndroidMkEntries() []android.AndroidMkEntries {
if app.jacocoReportClassesFile != nil {
entries.SetPath("LOCAL_SOONG_JACOCO_REPORT_CLASSES_JAR", app.jacocoReportClassesFile)
}
- if app.proguardDictionary != nil {
- entries.SetPath("LOCAL_SOONG_PROGUARD_DICT", app.proguardDictionary)
- }
+ entries.SetOptionalPath("LOCAL_SOONG_PROGUARD_DICT", app.dexer.proguardDictionary)
+ entries.SetOptionalPath("LOCAL_SOONG_PROGUARD_USAGE_ZIP", app.dexer.proguardUsageZip)
if app.Name() == "framework-res" {
entries.SetString("LOCAL_MODULE_PATH", "$(TARGET_OUT_JAVA_LIBRARIES)")
@@ -394,9 +397,7 @@ func (app *AndroidApp) AndroidMkEntries() []android.AndroidMkEntries {
entries.AddStrings("LOCAL_SOONG_BUILT_INSTALLED", extra.String()+":"+install)
}
- entries.AddOptionalPath("LOCAL_SOONG_LINT_REPORTS", app.linter.outputs.transitiveHTMLZip)
- entries.AddOptionalPath("LOCAL_SOONG_LINT_REPORTS", app.linter.outputs.transitiveTextZip)
- entries.AddOptionalPath("LOCAL_SOONG_LINT_REPORTS", app.linter.outputs.transitiveXMLZip)
+ entries.SetOptionalPaths("LOCAL_SOONG_LINT_REPORTS", app.linter.reports)
},
},
ExtraFooters: []android.AndroidMkExtraFootersFunc{
@@ -437,6 +438,7 @@ func (a *AndroidTest) AndroidMkEntries() []android.AndroidMkEntries {
if a.testConfig != nil {
entries.SetPath("LOCAL_FULL_TEST_CONFIG", a.testConfig)
}
+ androidMkWriteExtraTestConfigs(a.extraTestConfigs, entries)
androidMkWriteTestData(a.data, entries)
})
@@ -563,15 +565,21 @@ func (dstubs *Droidstubs) AndroidMkEntries() []android.AndroidMkEntries {
// are created in make if only the api txt file is being generated. This is
// needed because an invalid output file would prevent the make entries from
// being written.
+ //
+ // Note that dstubs.apiFile can be also be nil if WITHOUT_CHECKS_API is true.
// TODO(b/146727827): Revert when we do not need to generate stubs and API separately.
- distFile := dstubs.apiFile
+
+ var distFiles android.TaggedDistFiles
+ if dstubs.apiFile != nil {
+ distFiles = android.MakeDefaultDistFiles(dstubs.apiFile)
+ }
outputFile := android.OptionalPathForPath(dstubs.stubsSrcJar)
if !outputFile.Valid() {
- outputFile = android.OptionalPathForPath(distFile)
+ outputFile = android.OptionalPathForPath(dstubs.apiFile)
}
return []android.AndroidMkEntries{android.AndroidMkEntries{
Class: "JAVA_LIBRARIES",
- DistFiles: android.MakeDefaultDistFiles(distFile),
+ DistFiles: distFiles,
OutputFile: outputFile,
Include: "$(BUILD_SYSTEM)/soong_droiddoc_prebuilt.mk",
ExtraEntries: []android.AndroidMkExtraEntriesFunc{
@@ -732,7 +740,7 @@ func (apkSet *AndroidAppSet) AndroidMkEntries() []android.AndroidMkEntries {
ExtraEntries: []android.AndroidMkExtraEntriesFunc{
func(entries *android.AndroidMkEntries) {
entries.SetBoolIfTrue("LOCAL_PRIVILEGED_MODULE", apkSet.Privileged())
- entries.SetString("LOCAL_APK_SET_MASTER_FILE", apkSet.masterFile)
+ entries.SetString("LOCAL_APK_SET_INSTALL_FILE", apkSet.InstallFile())
entries.SetPath("LOCAL_APKCERTS_FILE", apkSet.apkcertsFile)
entries.AddStrings("LOCAL_OVERRIDES_PACKAGES", apkSet.properties.Overrides...)
},
diff --git a/java/app.go b/java/app.go
index b4bc39e0f..900f6a6d7 100755
--- a/java/app.go
+++ b/java/app.go
@@ -78,7 +78,7 @@ type AndroidAppSet struct {
properties AndroidAppSetProperties
packedOutput android.WritablePath
- masterFile string
+ installFile string
apkcertsFile android.ModuleOutPath
}
@@ -102,8 +102,8 @@ func (as *AndroidAppSet) OutputFile() android.Path {
return as.packedOutput
}
-func (as *AndroidAppSet) MasterFile() string {
- return as.masterFile
+func (as *AndroidAppSet) InstallFile() string {
+ return as.installFile
}
func (as *AndroidAppSet) APKCertsFile() android.Path {
@@ -136,10 +136,10 @@ func SupportedAbis(ctx android.ModuleContext) []string {
func (as *AndroidAppSet) GenerateAndroidBuildActions(ctx android.ModuleContext) {
as.packedOutput = android.PathForModuleOut(ctx, ctx.ModuleName()+".zip")
as.apkcertsFile = android.PathForModuleOut(ctx, "apkcerts.txt")
- // We are assuming here that the master file in the APK
+ // We are assuming here that the install file in the APK
// set has `.apk` suffix. If it doesn't the build will fail.
// APK sets containing APEX files are handled elsewhere.
- as.masterFile = as.BaseModuleName() + ".apk"
+ as.installFile = as.BaseModuleName() + ".apk"
screenDensities := "all"
if dpis := ctx.Config().ProductAAPTPrebuiltDPI(); len(dpis) > 0 {
screenDensities = strings.ToUpper(strings.Join(dpis, ","))
@@ -167,7 +167,7 @@ func (as *AndroidAppSet) GenerateAndroidBuildActions(ctx android.ModuleContext)
// android_app_set extracts a set of APKs based on the target device
// configuration and installs this set as "split APKs".
-// The extracted set always contains 'master' APK whose name is
+// The extracted set always contains an APK whose name is
// _module_name_.apk and every split APK matching target device.
// The extraction of the density-specific splits depends on
// PRODUCT_AAPT_PREBUILT_DPI variable. If present (its value should
@@ -602,18 +602,20 @@ func (a *AndroidApp) installPath(ctx android.ModuleContext) android.InstallPath
return android.PathForModuleInstall(ctx, installDir, a.installApkName+".apk")
}
-func (a *AndroidApp) dexBuildActions(ctx android.ModuleContext) android.Path {
+func (a *AndroidApp) dexBuildActions(ctx android.ModuleContext, sdkLibs dexpreopt.LibraryPaths) android.Path {
a.dexpreopter.installPath = a.installPath(ctx)
- if a.deviceProperties.Uncompress_dex == nil {
+ if a.dexProperties.Uncompress_dex == nil {
// If the value was not force-set by the user, use reasonable default based on the module.
- a.deviceProperties.Uncompress_dex = proptools.BoolPtr(a.shouldUncompressDex(ctx))
+ a.dexProperties.Uncompress_dex = proptools.BoolPtr(a.shouldUncompressDex(ctx))
}
- a.dexpreopter.uncompressedDex = *a.deviceProperties.Uncompress_dex
+ a.dexpreopter.uncompressedDex = *a.dexProperties.Uncompress_dex
a.dexpreopter.enforceUsesLibs = a.usesLibrary.enforceUsesLibraries()
a.dexpreopter.usesLibs = a.usesLibrary.usesLibraryProperties.Uses_libs
a.dexpreopter.optionalUsesLibs = a.usesLibrary.presentOptionalUsesLibs(ctx)
a.dexpreopter.libraryPaths = a.usesLibrary.usesLibraryPaths(ctx)
+ a.dexpreopter.libraryPaths.AddLibraryPaths(sdkLibs)
a.dexpreopter.manifestFile = a.mergedManifestFile
+ a.exportedSdkLibs = make(dexpreopt.LibraryPaths)
if ctx.ModuleName() != "framework-res" {
a.Module.compile(ctx, a.aaptSrcJar)
@@ -782,6 +784,15 @@ func (a *AndroidApp) generateAndroidBuildActions(ctx android.ModuleContext) {
// Process all building blocks, from AAPT to certificates.
a.aaptBuildActions(ctx)
+ // The decision to enforce <uses-library> checks is made before adding implicit SDK libraries.
+ a.usesLibrary.freezeEnforceUsesLibraries()
+
+ // Add implicit SDK libraries to <uses-library> list.
+ for _, usesLib := range android.SortedStringKeys(a.aapt.sdkLibraries) {
+ a.usesLibrary.addLib(usesLib, inList(usesLib, optionalUsesLibs))
+ }
+
+ // Check that the <uses-library> list is coherent with the manifest.
if a.usesLibrary.enforceUsesLibraries() {
manifestCheckFile := a.usesLibrary.verifyUsesLibrariesManifest(ctx, a.mergedManifestFile)
apkDeps = append(apkDeps, manifestCheckFile)
@@ -794,7 +805,7 @@ func (a *AndroidApp) generateAndroidBuildActions(ctx android.ModuleContext) {
a.linter.resources = a.aapt.resourceFiles
a.linter.buildModuleReportZip = ctx.Config().UnbundledBuildApps()
- dexJarFile := a.dexBuildActions(ctx)
+ dexJarFile := a.dexBuildActions(ctx, a.aapt.sdkLibraries)
jniLibs, certificateDeps := collectAppDeps(ctx, a, a.shouldEmbedJnis(ctx), !Bool(a.appProperties.Jni_uses_platform_apis))
jniJarFile := a.jniBuildActions(jniLibs, ctx)
@@ -875,7 +886,7 @@ func collectAppDeps(ctx android.ModuleContext, app appDepsInterface,
otherName := ctx.OtherModuleName(module)
tag := ctx.OtherModuleDependencyTag(module)
- if IsJniDepTag(tag) || tag == cc.SharedDepTag {
+ if IsJniDepTag(tag) || cc.IsSharedDepTag(tag) {
if dep, ok := module.(*cc.Module); ok {
if dep.IsNdk() || dep.IsStubs() {
return false
@@ -993,6 +1004,8 @@ func (a *AndroidApp) OutputFiles(tag string) (android.Paths, error) {
switch tag {
case ".aapt.srcjar":
return []android.Path{a.aaptSrcJar}, nil
+ case ".export-package.apk":
+ return []android.Path{a.exportPackage}, nil
}
return a.Library.OutputFiles(tag)
}
@@ -1025,8 +1038,8 @@ var _ cc.Coverage = (*AndroidApp)(nil)
func AndroidAppFactory() android.Module {
module := &AndroidApp{}
- module.Module.deviceProperties.Optimize.EnabledByDefault = true
- module.Module.deviceProperties.Optimize.Shrink = proptools.BoolPtr(true)
+ module.Module.dexProperties.Optimize.EnabledByDefault = true
+ module.Module.dexProperties.Optimize.Shrink = proptools.BoolPtr(true)
module.Module.properties.Instrument = true
module.Module.properties.Installable = proptools.BoolPtr(true)
@@ -1061,8 +1074,9 @@ type AndroidTest struct {
testProperties testProperties
- testConfig android.Path
- data android.Paths
+ testConfig android.Path
+ extraTestConfigs android.Paths
+ data android.Paths
}
func (a *AndroidTest) InstallInTestcases() bool {
@@ -1090,6 +1104,7 @@ func (a *AndroidTest) GenerateAndroidBuildActions(ctx android.ModuleContext) {
testConfig := tradefed.AutoGenInstrumentationTestConfig(ctx, a.testProperties.Test_config,
a.testProperties.Test_config_template, a.manifestPath, a.testProperties.Test_suites, a.testProperties.Auto_gen_config, configs)
a.testConfig = a.FixTestConfig(ctx, testConfig)
+ a.extraTestConfigs = android.PathsForModuleSrc(ctx, a.testProperties.Test_options.Extra_test_configs)
a.data = android.PathsForModuleSrc(ctx, a.testProperties.Data)
}
@@ -1140,7 +1155,7 @@ func (a *AndroidTest) OverridablePropertiesDepsMutator(ctx android.BottomUpMutat
func AndroidTestFactory() android.Module {
module := &AndroidTest{}
- module.Module.deviceProperties.Optimize.EnabledByDefault = true
+ module.Module.dexProperties.Optimize.EnabledByDefault = true
module.Module.properties.Instrument = true
module.Module.properties.Installable = proptools.BoolPtr(true)
@@ -1191,7 +1206,7 @@ func (a *AndroidTestHelperApp) InstallInTestcases() bool {
func AndroidTestHelperAppFactory() android.Module {
module := &AndroidTestHelperApp{}
- module.Module.deviceProperties.Optimize.EnabledByDefault = true
+ module.Module.dexProperties.Optimize.EnabledByDefault = true
module.Module.properties.Installable = proptools.BoolPtr(true)
module.appProperties.Use_embedded_native_libs = proptools.BoolPtr(true)
@@ -1913,6 +1928,16 @@ type usesLibrary struct {
usesLibraryProperties UsesLibraryProperties
}
+func (u *usesLibrary) addLib(lib string, optional bool) {
+ if !android.InList(lib, u.usesLibraryProperties.Uses_libs) && !android.InList(lib, u.usesLibraryProperties.Optional_uses_libs) {
+ if optional {
+ u.usesLibraryProperties.Optional_uses_libs = append(u.usesLibraryProperties.Optional_uses_libs, lib)
+ } else {
+ u.usesLibraryProperties.Uses_libs = append(u.usesLibraryProperties.Uses_libs, lib)
+ }
+ }
+}
+
func (u *usesLibrary) deps(ctx android.BottomUpMutatorContext, hasFrameworkLibs bool) {
if !ctx.Config().UnbundledBuild() {
ctx.AddVariationDependencies(nil, usesLibTag, u.usesLibraryProperties.Uses_libs...)
@@ -1985,6 +2010,12 @@ func (u *usesLibrary) enforceUsesLibraries() bool {
return BoolDefault(u.usesLibraryProperties.Enforce_uses_libs, defaultEnforceUsesLibs)
}
+// Freeze the value of `enforce_uses_libs` based on the current values of `uses_libs` and `optional_uses_libs`.
+func (u *usesLibrary) freezeEnforceUsesLibraries() {
+ enforce := u.enforceUsesLibraries()
+ u.usesLibraryProperties.Enforce_uses_libs = &enforce
+}
+
// verifyUsesLibrariesManifest checks the <uses-library> tags in an AndroidManifest.xml against the ones specified
// in the uses_libs and optional_uses_libs properties. It returns the path to a copy of the manifest.
func (u *usesLibrary) verifyUsesLibrariesManifest(ctx android.ModuleContext, manifest android.Path) android.Path {
diff --git a/java/app_test.go b/java/app_test.go
index 6b83cd2e1..536797119 100644
--- a/java/app_test.go
+++ b/java/app_test.go
@@ -161,11 +161,11 @@ func TestAndroidAppSet(t *testing.T) {
t.Errorf("wrong partition value: '%s', expected 'system'", s)
}
mkEntries := android.AndroidMkEntriesForTest(t, config, "", module.Module())[0]
- actualMaster := mkEntries.EntryMap["LOCAL_APK_SET_MASTER_FILE"]
- expectedMaster := []string{"foo.apk"}
- if !reflect.DeepEqual(actualMaster, expectedMaster) {
- t.Errorf("Unexpected LOCAL_APK_SET_MASTER_FILE value: '%s', expected: '%s',",
- actualMaster, expectedMaster)
+ actualInstallFile := mkEntries.EntryMap["LOCAL_APK_SET_INSTALL_FILE"]
+ expectedInstallFile := []string{"foo.apk"}
+ if !reflect.DeepEqual(actualInstallFile, expectedInstallFile) {
+ t.Errorf("Unexpected LOCAL_APK_SET_INSTALL_FILE value: '%s', expected: '%s',",
+ actualInstallFile, expectedInstallFile)
}
}
@@ -533,16 +533,6 @@ func TestUpdatableApps_JniLibShouldBeBuiltAgainstMinSdkVersion(t *testing.T) {
system_shared_libs: [],
sdk_version: "29",
}
-
- ndk_prebuilt_object {
- name: "ndk_crtbegin_so.29",
- sdk_version: "29",
- }
-
- ndk_prebuilt_object {
- name: "ndk_crtend_so.29",
- sdk_version: "29",
- }
`
fs := map[string][]byte{
"prebuilts/ndk/current/platforms/android-29/arch-arm64/usr/lib/crtbegin_so.o": nil,
@@ -555,16 +545,28 @@ func TestUpdatableApps_JniLibShouldBeBuiltAgainstMinSdkVersion(t *testing.T) {
inputs := ctx.ModuleForTests("libjni", "android_arm64_armv8-a_sdk_shared").Description("link").Implicits
var crtbeginFound, crtendFound bool
+ expectedCrtBegin := ctx.ModuleForTests("crtbegin_so",
+ "android_arm64_armv8-a_sdk_29").Rule("partialLd").Output
+ expectedCrtEnd := ctx.ModuleForTests("crtend_so",
+ "android_arm64_armv8-a_sdk_29").Rule("partialLd").Output
+ implicits := []string{}
for _, input := range inputs {
- switch input.String() {
- case "prebuilts/ndk/current/platforms/android-29/arch-arm64/usr/lib/crtbegin_so.o":
+ implicits = append(implicits, input.String())
+ if strings.HasSuffix(input.String(), expectedCrtBegin.String()) {
crtbeginFound = true
- case "prebuilts/ndk/current/platforms/android-29/arch-arm64/usr/lib/crtend_so.o":
+ } else if strings.HasSuffix(input.String(), expectedCrtEnd.String()) {
crtendFound = true
}
}
- if !crtbeginFound || !crtendFound {
- t.Error("should link with ndk_crtbegin_so.29 and ndk_crtend_so.29")
+ if !crtbeginFound {
+ t.Error(fmt.Sprintf(
+ "expected implicit with suffix %q, have the following implicits:\n%s",
+ expectedCrtBegin, strings.Join(implicits, "\n")))
+ }
+ if !crtendFound {
+ t.Error(fmt.Sprintf(
+ "expected implicit with suffix %q, have the following implicits:\n%s",
+ expectedCrtEnd, strings.Join(implicits, "\n")))
}
}
@@ -1038,6 +1040,35 @@ func TestAndroidResources(t *testing.T) {
}
}
+func checkSdkVersion(t *testing.T, config android.Config, expectedSdkVersion string) {
+ ctx := testContext()
+
+ run(t, ctx, config)
+
+ foo := ctx.ModuleForTests("foo", "android_common")
+ link := foo.Output("package-res.apk")
+ linkFlags := strings.Split(link.Args["flags"], " ")
+ min := android.IndexList("--min-sdk-version", linkFlags)
+ target := android.IndexList("--target-sdk-version", linkFlags)
+
+ if min == -1 || target == -1 || min == len(linkFlags)-1 || target == len(linkFlags)-1 {
+ t.Fatalf("missing --min-sdk-version or --target-sdk-version in link flags: %q", linkFlags)
+ }
+
+ gotMinSdkVersion := linkFlags[min+1]
+ gotTargetSdkVersion := linkFlags[target+1]
+
+ if gotMinSdkVersion != expectedSdkVersion {
+ t.Errorf("incorrect --min-sdk-version, expected %q got %q",
+ expectedSdkVersion, gotMinSdkVersion)
+ }
+
+ if gotTargetSdkVersion != expectedSdkVersion {
+ t.Errorf("incorrect --target-sdk-version, expected %q got %q",
+ expectedSdkVersion, gotTargetSdkVersion)
+ }
+}
+
func TestAppSdkVersion(t *testing.T) {
testCases := []struct {
name string
@@ -1107,34 +1138,81 @@ func TestAppSdkVersion(t *testing.T) {
config.TestProductVariables.Platform_sdk_version = &test.platformSdkInt
config.TestProductVariables.Platform_sdk_codename = &test.platformSdkCodename
config.TestProductVariables.Platform_sdk_final = &test.platformSdkFinal
+ checkSdkVersion(t, config, test.expectedMinSdkVersion)
- ctx := testContext()
-
- run(t, ctx, config)
-
- foo := ctx.ModuleForTests("foo", "android_common")
- link := foo.Output("package-res.apk")
- linkFlags := strings.Split(link.Args["flags"], " ")
- min := android.IndexList("--min-sdk-version", linkFlags)
- target := android.IndexList("--target-sdk-version", linkFlags)
-
- if min == -1 || target == -1 || min == len(linkFlags)-1 || target == len(linkFlags)-1 {
- t.Fatalf("missing --min-sdk-version or --target-sdk-version in link flags: %q", linkFlags)
- }
-
- gotMinSdkVersion := linkFlags[min+1]
- gotTargetSdkVersion := linkFlags[target+1]
+ })
+ }
+ }
+}
- if gotMinSdkVersion != test.expectedMinSdkVersion {
- t.Errorf("incorrect --min-sdk-version, expected %q got %q",
- test.expectedMinSdkVersion, gotMinSdkVersion)
- }
+func TestVendorAppSdkVersion(t *testing.T) {
+ testCases := []struct {
+ name string
+ sdkVersion string
+ platformSdkInt int
+ platformSdkCodename string
+ platformSdkFinal bool
+ deviceCurrentApiLevelForVendorModules string
+ expectedMinSdkVersion string
+ }{
+ {
+ name: "current final SDK",
+ sdkVersion: "current",
+ platformSdkInt: 29,
+ platformSdkCodename: "REL",
+ platformSdkFinal: true,
+ deviceCurrentApiLevelForVendorModules: "29",
+ expectedMinSdkVersion: "29",
+ },
+ {
+ name: "current final SDK",
+ sdkVersion: "current",
+ platformSdkInt: 29,
+ platformSdkCodename: "REL",
+ platformSdkFinal: true,
+ deviceCurrentApiLevelForVendorModules: "28",
+ expectedMinSdkVersion: "28",
+ },
+ {
+ name: "current final SDK",
+ sdkVersion: "current",
+ platformSdkInt: 29,
+ platformSdkCodename: "Q",
+ platformSdkFinal: false,
+ deviceCurrentApiLevelForVendorModules: "current",
+ expectedMinSdkVersion: "Q",
+ },
+ {
+ name: "current final SDK",
+ sdkVersion: "current",
+ platformSdkInt: 29,
+ platformSdkCodename: "Q",
+ platformSdkFinal: false,
+ deviceCurrentApiLevelForVendorModules: "28",
+ expectedMinSdkVersion: "28",
+ },
+ }
- if gotTargetSdkVersion != test.expectedMinSdkVersion {
- t.Errorf("incorrect --target-sdk-version, expected %q got %q",
- test.expectedMinSdkVersion, gotTargetSdkVersion)
- }
- })
+ for _, moduleType := range []string{"android_app", "android_library"} {
+ for _, sdkKind := range []string{"", "system_"} {
+ for _, test := range testCases {
+ t.Run(moduleType+" "+test.name, func(t *testing.T) {
+ bp := fmt.Sprintf(`%s {
+ name: "foo",
+ srcs: ["a.java"],
+ sdk_version: "%s%s",
+ vendor: true,
+ }`, moduleType, sdkKind, test.sdkVersion)
+
+ config := testAppConfig(nil, bp, nil)
+ config.TestProductVariables.Platform_sdk_version = &test.platformSdkInt
+ config.TestProductVariables.Platform_sdk_codename = &test.platformSdkCodename
+ config.TestProductVariables.Platform_sdk_final = &test.platformSdkFinal
+ config.TestProductVariables.DeviceCurrentApiLevelForVendorModules = &test.deviceCurrentApiLevelForVendorModules
+ config.TestProductVariables.DeviceSystemSdkVersions = []string{"28", "29"}
+ checkSdkVersion(t, config, test.expectedMinSdkVersion)
+ })
+ }
}
}
}
@@ -2663,10 +2741,37 @@ func TestUsesLibraries(t *testing.T) {
sdk_version: "current",
}
+ java_sdk_library {
+ name: "runtime-library",
+ srcs: ["a.java"],
+ sdk_version: "current",
+ }
+
+ java_library {
+ name: "static-runtime-helper",
+ srcs: ["a.java"],
+ libs: ["runtime-library"],
+ sdk_version: "current",
+ }
+
android_app {
name: "app",
srcs: ["a.java"],
+ libs: ["qux", "quuz"],
+ static_libs: ["static-runtime-helper"],
+ uses_libs: ["foo"],
+ sdk_version: "current",
+ optional_uses_libs: [
+ "bar",
+ "baz",
+ ],
+ }
+
+ android_app {
+ name: "app_with_stub_deps",
+ srcs: ["a.java"],
libs: ["qux", "quuz.stubs"],
+ static_libs: ["static-runtime-helper"],
uses_libs: ["foo"],
sdk_version: "current",
optional_uses_libs: [
@@ -2695,15 +2800,15 @@ func TestUsesLibraries(t *testing.T) {
run(t, ctx, config)
app := ctx.ModuleForTests("app", "android_common")
+ appWithStubDeps := ctx.ModuleForTests("app_with_stub_deps", "android_common")
prebuilt := ctx.ModuleForTests("prebuilt", "android_common")
// Test that implicit dependencies on java_sdk_library instances are passed to the manifest.
manifestFixerArgs := app.Output("manifest_fixer/AndroidManifest.xml").Args["args"]
- if w := "--uses-library qux"; !strings.Contains(manifestFixerArgs, w) {
- t.Errorf("unexpected manifest_fixer args: wanted %q in %q", w, manifestFixerArgs)
- }
- if w := "--uses-library quuz"; !strings.Contains(manifestFixerArgs, w) {
- t.Errorf("unexpected manifest_fixer args: wanted %q in %q", w, manifestFixerArgs)
+ for _, w := range []string{"qux", "quuz", "runtime-library"} {
+ if !strings.Contains(manifestFixerArgs, "--uses-library "+w) {
+ t.Errorf("unexpected manifest_fixer args: wanted %q in %q", w, manifestFixerArgs)
+ }
}
// Test that all libraries are verified
@@ -2726,15 +2831,24 @@ func TestUsesLibraries(t *testing.T) {
t.Errorf("wanted %q in %q", w, cmd)
}
- // Test that only present libraries are preopted
+ // Test that all present libraries are preopted, including implicit SDK dependencies
cmd = app.Rule("dexpreopt").RuleParams.Command
-
- if w := `--target-classpath-for-sdk any /system/framework/foo.jar:/system/framework/bar.jar`; !strings.Contains(cmd, w) {
+ w := `--target-classpath-for-sdk any` +
+ ` /system/framework/foo.jar` +
+ `:/system/framework/quuz.jar` +
+ `:/system/framework/qux.jar` +
+ `:/system/framework/runtime-library.jar` +
+ `:/system/framework/bar.jar`
+ if !strings.Contains(cmd, w) {
t.Errorf("wanted %q in %q", w, cmd)
}
- cmd = prebuilt.Rule("dexpreopt").RuleParams.Command
+ // TODO(skvadrik) fix dexpreopt for stub libraries for which the implementation is present
+ if appWithStubDeps.MaybeRule("dexpreopt").RuleParams.Command != "" {
+ t.Errorf("dexpreopt should be disabled for apps with dependencies on stub libraries")
+ }
+ cmd = prebuilt.Rule("dexpreopt").RuleParams.Command
if w := `--target-classpath-for-sdk any /system/framework/foo.jar:/system/framework/bar.jar`; !strings.Contains(cmd, w) {
t.Errorf("wanted %q in %q", w, cmd)
}
@@ -3005,6 +3119,7 @@ func TestUncompressDex(t *testing.T) {
config := testAppConfig(nil, bp, nil)
if unbundled {
config.TestProductVariables.Unbundled_build = proptools.BoolPtr(true)
+ config.TestProductVariables.Always_use_prebuilt_sdks = proptools.BoolPtr(true)
}
ctx := testContext()
diff --git a/java/config/config.go b/java/config/config.go
index 54a709c5e..31e2b0ffe 100644
--- a/java/config/config.go
+++ b/java/config/config.go
@@ -30,6 +30,8 @@ var (
LegacyCorePlatformBootclasspathLibraries = []string{"legacy.core.platform.api.stubs", "core-lambda-stubs"}
LegacyCorePlatformSystemModules = "legacy-core-platform-api-stubs-system-modules"
+ StableCorePlatformBootclasspathLibraries = []string{"stable.core.platform.api.stubs", "core-lambda-stubs"}
+ StableCorePlatformSystemModules = "stable-core-platform-api-stubs-system-modules"
FrameworkLibraries = []string{"ext", "framework"}
DefaultLambdaStubsLibrary = "core-lambda-stubs"
SdkLambdaStubsPath = "prebuilts/sdk/tools/core-lambda-stubs.jar"
@@ -128,7 +130,7 @@ func init() {
pctx.HostBinToolVariable("ExtractApksCmd", "extract_apks")
pctx.VariableFunc("TurbineJar", func(ctx android.PackageVarContext) string {
turbine := "turbine.jar"
- if ctx.Config().UnbundledBuild() {
+ if ctx.Config().AlwaysUsePrebuiltSdks() {
return "prebuilts/build-tools/common/framework/" + turbine
} else {
return ctx.Config().HostJavaToolPath(ctx, turbine).String()
@@ -148,9 +150,9 @@ func init() {
pctx.HostBinToolVariable("DexpreoptGen", "dexpreopt_gen")
pctx.VariableFunc("REJavaPool", remoteexec.EnvOverrideFunc("RBE_JAVA_POOL", "java16"))
- pctx.VariableFunc("REJavacExecStrategy", remoteexec.EnvOverrideFunc("RBE_JAVAC_EXEC_STRATEGY", remoteexec.LocalExecStrategy))
- pctx.VariableFunc("RED8ExecStrategy", remoteexec.EnvOverrideFunc("RBE_D8_EXEC_STRATEGY", remoteexec.LocalExecStrategy))
- pctx.VariableFunc("RER8ExecStrategy", remoteexec.EnvOverrideFunc("RBE_R8_EXEC_STRATEGY", remoteexec.LocalExecStrategy))
+ pctx.VariableFunc("REJavacExecStrategy", remoteexec.EnvOverrideFunc("RBE_JAVAC_EXEC_STRATEGY", remoteexec.RemoteLocalFallbackExecStrategy))
+ pctx.VariableFunc("RED8ExecStrategy", remoteexec.EnvOverrideFunc("RBE_D8_EXEC_STRATEGY", remoteexec.RemoteLocalFallbackExecStrategy))
+ pctx.VariableFunc("RER8ExecStrategy", remoteexec.EnvOverrideFunc("RBE_R8_EXEC_STRATEGY", remoteexec.RemoteLocalFallbackExecStrategy))
pctx.VariableFunc("RETurbineExecStrategy", remoteexec.EnvOverrideFunc("RBE_TURBINE_EXEC_STRATEGY", remoteexec.LocalExecStrategy))
pctx.VariableFunc("RESignApkExecStrategy", remoteexec.EnvOverrideFunc("RBE_SIGNAPK_EXEC_STRATEGY", remoteexec.LocalExecStrategy))
pctx.VariableFunc("REJarExecStrategy", remoteexec.EnvOverrideFunc("RBE_JAR_EXEC_STRATEGY", remoteexec.LocalExecStrategy))
@@ -163,7 +165,7 @@ func init() {
pctx.HostBinToolVariable("ManifestMergerCmd", "manifest-merger")
- pctx.HostBinToolVariable("Class2Greylist", "class2greylist")
+ pctx.HostBinToolVariable("Class2NonSdkList", "class2nonsdklist")
pctx.HostBinToolVariable("HiddenAPI", "hiddenapi")
hostBinToolVariableWithSdkToolsPrebuilt("Aapt2Cmd", "aapt2")
@@ -178,7 +180,7 @@ func init() {
func hostBinToolVariableWithSdkToolsPrebuilt(name, tool string) {
pctx.VariableFunc(name, func(ctx android.PackageVarContext) string {
- if ctx.Config().UnbundledBuild() || ctx.Config().IsPdkBuild() {
+ if ctx.Config().AlwaysUsePrebuiltSdks() {
return filepath.Join("prebuilts/sdk/tools", runtime.GOOS, "bin", tool)
} else {
return ctx.Config().HostToolPath(ctx, tool).String()
@@ -188,7 +190,7 @@ func hostBinToolVariableWithSdkToolsPrebuilt(name, tool string) {
func hostJavaToolVariableWithSdkToolsPrebuilt(name, tool string) {
pctx.VariableFunc(name, func(ctx android.PackageVarContext) string {
- if ctx.Config().UnbundledBuild() || ctx.Config().IsPdkBuild() {
+ if ctx.Config().AlwaysUsePrebuiltSdks() {
return filepath.Join("prebuilts/sdk/tools/lib", tool+".jar")
} else {
return ctx.Config().HostJavaToolPath(ctx, tool+".jar").String()
@@ -198,7 +200,7 @@ func hostJavaToolVariableWithSdkToolsPrebuilt(name, tool string) {
func hostJNIToolVariableWithSdkToolsPrebuilt(name, tool string) {
pctx.VariableFunc(name, func(ctx android.PackageVarContext) string {
- if ctx.Config().UnbundledBuild() || ctx.Config().IsPdkBuild() {
+ if ctx.Config().AlwaysUsePrebuiltSdks() {
ext := ".so"
if runtime.GOOS == "darwin" {
ext = ".dylib"
@@ -212,7 +214,7 @@ func hostJNIToolVariableWithSdkToolsPrebuilt(name, tool string) {
func hostBinToolVariableWithBuildToolsPrebuilt(name, tool string) {
pctx.VariableFunc(name, func(ctx android.PackageVarContext) string {
- if ctx.Config().UnbundledBuild() || ctx.Config().IsPdkBuild() {
+ if ctx.Config().AlwaysUsePrebuiltSdks() {
return filepath.Join("prebuilts/build-tools", ctx.Config().PrebuiltOS(), "bin", tool)
} else {
return ctx.Config().HostToolPath(ctx, tool).String()
diff --git a/java/config/makevars.go b/java/config/makevars.go
index 708a72aa4..df447a129 100644
--- a/java/config/makevars.go
+++ b/java/config/makevars.go
@@ -75,7 +75,7 @@ func makeVarsProvider(ctx android.MakeVarsContext) {
ctx.Strict("ANDROID_MANIFEST_MERGER", "${ManifestMergerCmd}")
- ctx.Strict("CLASS2GREYLIST", "${Class2Greylist}")
+ ctx.Strict("CLASS2NONSDKLIST", "${Class2NonSdkList}")
ctx.Strict("HIDDENAPI", "${HiddenAPI}")
ctx.Strict("DEX_FLAGS", "${DexFlags}")
diff --git a/java/device_host_converter.go b/java/device_host_converter.go
index 9191a8321..40a2280d9 100644
--- a/java/device_host_converter.go
+++ b/java/device_host_converter.go
@@ -19,6 +19,7 @@ import (
"io"
"android/soong/android"
+ "android/soong/dexpreopt"
)
type DeviceHostConverter struct {
@@ -162,7 +163,7 @@ func (d *DeviceHostConverter) AidlIncludeDirs() android.Paths {
return nil
}
-func (d *DeviceHostConverter) ExportedSdkLibs() []string {
+func (d *DeviceHostConverter) ExportedSdkLibs() dexpreopt.LibraryPaths {
return nil
}
diff --git a/java/dex.go b/java/dex.go
index 9e61e95ad..c85914c41 100644
--- a/java/dex.go
+++ b/java/dex.go
@@ -24,6 +24,61 @@ import (
"android/soong/remoteexec"
)
+type DexProperties struct {
+ // If set to true, compile dex regardless of installable. Defaults to false.
+ Compile_dex *bool
+
+ // list of module-specific flags that will be used for dex compiles
+ Dxflags []string `android:"arch_variant"`
+
+ Optimize struct {
+ // If false, disable all optimization. Defaults to true for android_app and android_test
+ // modules, false for java_library and java_test modules.
+ Enabled *bool
+ // True if the module containing this has it set by default.
+ EnabledByDefault bool `blueprint:"mutated"`
+
+ // If true, optimize for size by removing unused code. Defaults to true for apps,
+ // false for libraries and tests.
+ Shrink *bool
+
+ // If true, optimize bytecode. Defaults to false.
+ Optimize *bool
+
+ // If true, obfuscate bytecode. Defaults to false.
+ Obfuscate *bool
+
+ // If true, do not use the flag files generated by aapt that automatically keep
+ // classes referenced by the app manifest. Defaults to false.
+ No_aapt_flags *bool
+
+ // Flags to pass to proguard.
+ Proguard_flags []string
+
+ // Specifies the locations of files containing proguard flags.
+ Proguard_flags_files []string `android:"path"`
+ }
+
+ // Keep the data uncompressed. We always need uncompressed dex for execution,
+ // so this might actually save space by avoiding storing the same data twice.
+ // This defaults to reasonable value based on module and should not be set.
+ // It exists only to support ART tests.
+ Uncompress_dex *bool
+}
+
+type dexer struct {
+ dexProperties DexProperties
+
+ // list of extra proguard flag files
+ extraProguardFlagFiles android.Paths
+ proguardDictionary android.OptionalPath
+ proguardUsageZip android.OptionalPath
+}
+
+func (d *dexer) effectiveOptimizeEnabled() bool {
+ return BoolDefault(d.dexProperties.Optimize.Enabled, d.dexProperties.Optimize.EnabledByDefault)
+}
+
var d8, d8RE = remoteexec.MultiCommandStaticRules(pctx, "d8",
blueprint.RuleParams{
Command: `rm -rf "$outDir" && mkdir -p "$outDir" && ` +
@@ -55,13 +110,17 @@ var d8, d8RE = remoteexec.MultiCommandStaticRules(pctx, "d8",
var r8, r8RE = remoteexec.MultiCommandStaticRules(pctx, "r8",
blueprint.RuleParams{
Command: `rm -rf "$outDir" && mkdir -p "$outDir" && ` +
- `rm -f "$outDict" && ` +
+ `rm -f "$outDict" && rm -rf "${outUsageDir}" && ` +
+ `mkdir -p $$(dirname ${outUsage}) && ` +
`$r8Template${config.R8Cmd} ${config.DexFlags} -injars $in --output $outDir ` +
`--force-proguard-compatibility ` +
`--no-data-resources ` +
- `-printmapping $outDict ` +
+ `-printmapping ${outDict} ` +
+ `-printusage ${outUsage} ` +
`$r8Flags && ` +
- `touch "$outDict" && ` +
+ `touch "${outDict}" "${outUsage}" && ` +
+ `${config.SoongZipCmd} -o ${outUsageZip} -C ${outUsageDir} -f ${outUsage} && ` +
+ `rm -rf ${outUsageDir} && ` +
`$zipTemplate${config.SoongZipCmd} $zipFlags -o $outDir/classes.dex.jar -C $outDir -f "$outDir/classes*.dex" && ` +
`${config.MergeZipsCmd} -D -stripFile "**/*.class" $out $outDir/classes.dex.jar $in`,
CommandDeps: []string{
@@ -84,10 +143,18 @@ var r8, r8RE = remoteexec.MultiCommandStaticRules(pctx, "r8",
ExecStrategy: "${config.RER8ExecStrategy}",
Platform: map[string]string{remoteexec.PoolKey: "${config.REJavaPool}"},
},
- }, []string{"outDir", "outDict", "r8Flags", "zipFlags"}, []string{"implicits"})
+ "$zipUsageTemplate": &remoteexec.REParams{
+ Labels: map[string]string{"type": "tool", "name": "soong_zip"},
+ Inputs: []string{"${config.SoongZipCmd}", "${outUsage}"},
+ OutputFiles: []string{"${outUsageZip}"},
+ ExecStrategy: "${config.RER8ExecStrategy}",
+ Platform: map[string]string{remoteexec.PoolKey: "${config.REJavaPool}"},
+ },
+ }, []string{"outDir", "outDict", "outUsage", "outUsageZip", "outUsageDir",
+ "r8Flags", "zipFlags"}, []string{"implicits"})
-func (j *Module) dexCommonFlags(ctx android.ModuleContext) []string {
- flags := j.deviceProperties.Dxflags
+func (d *dexer) dexCommonFlags(ctx android.ModuleContext, minSdkVersion sdkSpec) []string {
+ flags := d.dexProperties.Dxflags
// Translate all the DX flags to D8 ones until all the build files have been migrated
// to D8 flags. See: b/69377755
flags = android.RemoveListFromList(flags,
@@ -103,30 +170,27 @@ func (j *Module) dexCommonFlags(ctx android.ModuleContext) []string {
"--verbose")
}
- minSdkVersion, err := j.minSdkVersion().effectiveVersion(ctx)
+ effectiveVersion, err := minSdkVersion.effectiveVersion(ctx)
if err != nil {
ctx.PropertyErrorf("min_sdk_version", "%s", err)
}
- flags = append(flags, "--min-api "+minSdkVersion.asNumberString())
+ flags = append(flags, "--min-api "+effectiveVersion.asNumberString())
return flags
}
-func (j *Module) d8Flags(ctx android.ModuleContext, flags javaBuilderFlags) ([]string, android.Paths) {
- d8Flags := j.dexCommonFlags(ctx)
-
+func d8Flags(flags javaBuilderFlags) (d8Flags []string, d8Deps android.Paths) {
d8Flags = append(d8Flags, flags.bootClasspath.FormRepeatedClassPath("--lib ")...)
d8Flags = append(d8Flags, flags.classpath.FormRepeatedClassPath("--lib ")...)
- var d8Deps android.Paths
d8Deps = append(d8Deps, flags.bootClasspath...)
d8Deps = append(d8Deps, flags.classpath...)
return d8Flags, d8Deps
}
-func (j *Module) r8Flags(ctx android.ModuleContext, flags javaBuilderFlags) (r8Flags []string, r8Deps android.Paths) {
- opt := j.deviceProperties.Optimize
+func (d *dexer) r8Flags(ctx android.ModuleContext, flags javaBuilderFlags) (r8Flags []string, r8Deps android.Paths) {
+ opt := d.dexProperties.Optimize
// When an app contains references to APIs that are not in the SDK specified by
// its LOCAL_SDK_VERSION for example added by support library or by runtime
@@ -140,8 +204,6 @@ func (j *Module) r8Flags(ctx android.ModuleContext, flags javaBuilderFlags) (r8F
proguardRaiseDeps = append(proguardRaiseDeps, dep.(Dependency).HeaderJars()...)
})
- r8Flags = append(r8Flags, j.dexCommonFlags(ctx)...)
-
r8Flags = append(r8Flags, proguardRaiseDeps.FormJavaClassPath("-libraryjars"))
r8Flags = append(r8Flags, flags.bootClasspath.FormJavaClassPath("-libraryjars"))
r8Flags = append(r8Flags, flags.classpath.FormJavaClassPath("-libraryjars"))
@@ -154,15 +216,10 @@ func (j *Module) r8Flags(ctx android.ModuleContext, flags javaBuilderFlags) (r8F
android.PathForSource(ctx, "build/make/core/proguard.flags"),
}
- if j.shouldInstrumentStatic(ctx) {
- flagFiles = append(flagFiles,
- android.PathForSource(ctx, "build/make/core/proguard.jacoco.flags"))
- }
-
- flagFiles = append(flagFiles, j.extraProguardFlagFiles...)
+ flagFiles = append(flagFiles, d.extraProguardFlagFiles...)
// TODO(ccross): static android library proguard files
- flagFiles = append(flagFiles, android.PathsForModuleSrc(ctx, j.deviceProperties.Optimize.Proguard_flags_files)...)
+ flagFiles = append(flagFiles, android.PathsForModuleSrc(ctx, opt.Proguard_flags_files)...)
r8Flags = append(r8Flags, android.JoinWithPrefix(flagFiles.Strings(), "-include "))
r8Deps = append(r8Deps, flagFiles...)
@@ -171,7 +228,7 @@ func (j *Module) r8Flags(ctx android.ModuleContext, flags javaBuilderFlags) (r8F
r8Deps = append(r8Deps, android.PathForSource(ctx,
"build/make/core/proguard_basic_keeps.flags"))
- r8Flags = append(r8Flags, j.deviceProperties.Optimize.Proguard_flags...)
+ r8Flags = append(r8Flags, opt.Proguard_flags...)
// TODO(ccross): Don't shrink app instrumentation tests by default.
if !Bool(opt.Shrink) {
@@ -197,46 +254,55 @@ func (j *Module) r8Flags(ctx android.ModuleContext, flags javaBuilderFlags) (r8F
return r8Flags, r8Deps
}
-func (j *Module) compileDex(ctx android.ModuleContext, flags javaBuilderFlags,
+func (d *dexer) compileDex(ctx android.ModuleContext, flags javaBuilderFlags, minSdkVersion sdkSpec,
classesJar android.Path, jarName string) android.ModuleOutPath {
- useR8 := j.deviceProperties.EffectiveOptimizeEnabled()
-
// Compile classes.jar into classes.dex and then javalib.jar
javalibJar := android.PathForModuleOut(ctx, "dex", jarName)
outDir := android.PathForModuleOut(ctx, "dex")
zipFlags := "--ignore_missing_files"
- if proptools.Bool(j.deviceProperties.Uncompress_dex) {
+ if proptools.Bool(d.dexProperties.Uncompress_dex) {
zipFlags += " -L 0"
}
+ commonFlags := d.dexCommonFlags(ctx, minSdkVersion)
+
+ useR8 := d.effectiveOptimizeEnabled()
if useR8 {
proguardDictionary := android.PathForModuleOut(ctx, "proguard_dictionary")
- j.proguardDictionary = proguardDictionary
- r8Flags, r8Deps := j.r8Flags(ctx, flags)
+ d.proguardDictionary = android.OptionalPathForPath(proguardDictionary)
+ proguardUsageDir := android.PathForModuleOut(ctx, "proguard_usage")
+ proguardUsage := proguardUsageDir.Join(ctx, ctx.Namespace().Path,
+ android.ModuleNameWithPossibleOverride(ctx), "unused.txt")
+ proguardUsageZip := android.PathForModuleOut(ctx, "proguard_usage.zip")
+ d.proguardUsageZip = android.OptionalPathForPath(proguardUsageZip)
+ r8Flags, r8Deps := d.r8Flags(ctx, flags)
rule := r8
args := map[string]string{
- "r8Flags": strings.Join(r8Flags, " "),
- "zipFlags": zipFlags,
- "outDict": j.proguardDictionary.String(),
- "outDir": outDir.String(),
+ "r8Flags": strings.Join(append(commonFlags, r8Flags...), " "),
+ "zipFlags": zipFlags,
+ "outDict": proguardDictionary.String(),
+ "outUsageDir": proguardUsageDir.String(),
+ "outUsage": proguardUsage.String(),
+ "outUsageZip": proguardUsageZip.String(),
+ "outDir": outDir.String(),
}
if ctx.Config().IsEnvTrue("RBE_R8") {
rule = r8RE
args["implicits"] = strings.Join(r8Deps.Strings(), ",")
}
ctx.Build(pctx, android.BuildParams{
- Rule: rule,
- Description: "r8",
- Output: javalibJar,
- ImplicitOutput: proguardDictionary,
- Input: classesJar,
- Implicits: r8Deps,
- Args: args,
+ Rule: rule,
+ Description: "r8",
+ Output: javalibJar,
+ ImplicitOutputs: android.WritablePaths{proguardDictionary, proguardUsageZip},
+ Input: classesJar,
+ Implicits: r8Deps,
+ Args: args,
})
} else {
- d8Flags, d8Deps := j.d8Flags(ctx, flags)
+ d8Flags, d8Deps := d8Flags(flags)
rule := d8
if ctx.Config().IsEnvTrue("RBE_D8") {
rule = d8RE
@@ -248,13 +314,13 @@ func (j *Module) compileDex(ctx android.ModuleContext, flags javaBuilderFlags,
Input: classesJar,
Implicits: d8Deps,
Args: map[string]string{
- "d8Flags": strings.Join(d8Flags, " "),
+ "d8Flags": strings.Join(append(commonFlags, d8Flags...), " "),
"zipFlags": zipFlags,
"outDir": outDir.String(),
},
})
}
- if proptools.Bool(j.deviceProperties.Uncompress_dex) {
+ if proptools.Bool(d.dexProperties.Uncompress_dex) {
alignedJavalibJar := android.PathForModuleOut(ctx, "aligned", jarName)
TransformZipAlign(ctx, alignedJavalibJar, javalibJar)
javalibJar = alignedJavalibJar
diff --git a/java/dexpreopt_bootjars.go b/java/dexpreopt_bootjars.go
index 41205598e..3addc1a74 100644
--- a/java/dexpreopt_bootjars.go
+++ b/java/dexpreopt_bootjars.go
@@ -49,8 +49,8 @@ type bootImageConfig struct {
// Subdirectory where the image files are installed.
installSubdir string
- // The names of jars that constitute this image.
- modules []string
+ // A list of (location, jar) pairs for the Java modules in this image.
+ modules android.ConfiguredJarList
// File paths to jars.
dexPaths android.WritablePaths // for this image
@@ -113,16 +113,16 @@ func (image bootImageConfig) moduleName(ctx android.PathContext, idx int) string
// Dexpreopt on the boot class path produces multiple files. The first dex file
// is converted into 'name'.art (to match the legacy assumption that 'name'.art
// exists), and the rest are converted to 'name'-<jar>.art.
- _, m := android.SplitApexJarPair(ctx, image.modules[idx])
+ m := image.modules.Jar(idx)
name := image.stem
if idx != 0 || image.extends != nil {
- name += "-" + stemOf(m)
+ name += "-" + android.ModuleStem(m)
}
return name
}
func (image bootImageConfig) firstModuleNameOrStem(ctx android.PathContext) string {
- if len(image.modules) > 0 {
+ if image.modules.Len() > 0 {
return image.moduleName(ctx, 0)
} else {
return image.stem
@@ -130,8 +130,8 @@ func (image bootImageConfig) firstModuleNameOrStem(ctx android.PathContext) stri
}
func (image bootImageConfig) moduleFiles(ctx android.PathContext, dir android.OutputPath, exts ...string) android.OutputPaths {
- ret := make(android.OutputPaths, 0, len(image.modules)*len(exts))
- for i := range image.modules {
+ ret := make(android.OutputPaths, 0, image.modules.Len()*len(exts))
+ for i := 0; i < image.modules.Len(); i++ {
name := image.moduleName(ctx, i)
for _, ext := range exts {
ret = append(ret, dir.Join(ctx, name+ext))
@@ -253,7 +253,7 @@ func getBootImageJar(ctx android.SingletonContext, image *bootImageConfig, modul
}
name := ctx.ModuleName(module)
- index := android.IndexList(name, android.GetJarsFromApexJarPairs(ctx, image.modules))
+ index := image.modules.IndexOfJar(name)
if index == -1 {
return -1, nil
}
@@ -262,7 +262,7 @@ func getBootImageJar(ctx android.SingletonContext, image *bootImageConfig, modul
apex, isApexModule := module.(android.ApexModule)
fromUpdatableApex := isApexModule && apex.Updatable()
if image.name == artBootImageName {
- if isApexModule && strings.HasPrefix(apex.ApexName(), "com.android.art.") {
+ if isApexModule && len(apex.InApexes()) > 0 && allHavePrefix(apex.InApexes(), "com.android.art.") {
// ok: found the jar in the ART apex
} else if isApexModule && apex.IsForPlatform() && Bool(module.(*Library).deviceProperties.Hostdex) {
// exception (skip and continue): special "hostdex" platform variant
@@ -272,17 +272,17 @@ func getBootImageJar(ctx android.SingletonContext, image *bootImageConfig, modul
return -1, nil
} else if fromUpdatableApex {
// error: this jar is part of an updatable apex other than ART
- ctx.Errorf("module '%s' from updatable apex '%s' is not allowed in the ART boot image", name, apex.ApexName())
+ ctx.Errorf("module %q from updatable apexes %q is not allowed in the ART boot image", name, apex.InApexes())
} else {
// error: this jar is part of the platform or a non-updatable apex
- ctx.Errorf("module '%s' is not allowed in the ART boot image", name)
+ ctx.Errorf("module %q is not allowed in the ART boot image", name)
}
} else if image.name == frameworkBootImageName {
if !fromUpdatableApex {
// ok: this jar is part of the platform or a non-updatable apex
} else {
// error: this jar is part of an updatable apex
- ctx.Errorf("module '%s' from updatable apex '%s' is not allowed in the framework boot image", name, apex.ApexName())
+ ctx.Errorf("module %q from updatable apexes %q is not allowed in the framework boot image", name, apex.InApexes())
}
} else {
panic("unknown boot image: " + image.name)
@@ -291,11 +291,20 @@ func getBootImageJar(ctx android.SingletonContext, image *bootImageConfig, modul
return index, jar.DexJarBuildPath()
}
+func allHavePrefix(list []string, prefix string) bool {
+ for _, s := range list {
+ if !strings.HasPrefix(s, prefix) {
+ return false
+ }
+ }
+ return true
+}
+
// buildBootImage takes a bootImageConfig, creates rules to build it, and returns the image.
func buildBootImage(ctx android.SingletonContext, image *bootImageConfig) *bootImageConfig {
// Collect dex jar paths for the boot image modules.
// This logic is tested in the apex package to avoid import cycle apex <-> java.
- bootDexJars := make(android.Paths, len(image.modules))
+ bootDexJars := make(android.Paths, image.modules.Len())
ctx.VisitAllModules(func(module android.Module) {
if i, j := getBootImageJar(ctx, image, module); i != -1 {
bootDexJars[i] = j
@@ -306,7 +315,7 @@ func buildBootImage(ctx android.SingletonContext, image *bootImageConfig) *bootI
// Ensure all modules were converted to paths
for i := range bootDexJars {
if bootDexJars[i] == nil {
- _, m := android.SplitApexJarPair(ctx, image.modules[i])
+ m := image.modules.Jar(i)
if ctx.Config().AllowMissingDependencies() {
missingDeps = append(missingDeps, m)
bootDexJars[i] = android.PathForOutput(ctx, "missing")
@@ -505,7 +514,7 @@ func bootImageProfileRule(ctx android.SingletonContext, image *bootImageConfig,
globalSoong := dexpreopt.GetCachedGlobalSoongConfig(ctx)
global := dexpreopt.GetGlobalConfig(ctx)
- if global.DisableGenerateProfile || ctx.Config().IsPdkBuild() || ctx.Config().UnbundledBuild() {
+ if global.DisableGenerateProfile || ctx.Config().UnbundledBuild() {
return nil
}
profile := ctx.Config().Once(bootImageProfileRuleKey, func() interface{} {
@@ -560,7 +569,7 @@ func bootFrameworkProfileRule(ctx android.SingletonContext, image *bootImageConf
globalSoong := dexpreopt.GetCachedGlobalSoongConfig(ctx)
global := dexpreopt.GetGlobalConfig(ctx)
- if global.DisableGenerateProfile || ctx.Config().IsPdkBuild() || ctx.Config().UnbundledBuild() {
+ if global.DisableGenerateProfile || ctx.Config().UnbundledBuild() {
return nil
}
return ctx.Config().Once(bootFrameworkProfileRuleKey, func() interface{} {
@@ -602,13 +611,13 @@ func bootFrameworkProfileRule(ctx android.SingletonContext, image *bootImageConf
var bootFrameworkProfileRuleKey = android.NewOnceKey("bootFrameworkProfileRule")
func updatableBcpPackagesRule(ctx android.SingletonContext, image *bootImageConfig, missingDeps []string) android.WritablePath {
- if ctx.Config().IsPdkBuild() || ctx.Config().UnbundledBuild() {
+ if ctx.Config().UnbundledBuild() {
return nil
}
return ctx.Config().Once(updatableBcpPackagesRuleKey, func() interface{} {
global := dexpreopt.GetGlobalConfig(ctx)
- updatableModules := android.GetJarsFromApexJarPairs(ctx, global.UpdatableBootJars)
+ updatableModules := global.UpdatableBootJars.CopyOfJars()
// Collect `permitted_packages` for updatable boot jars.
var updatablePackages []string
diff --git a/java/dexpreopt_bootjars_test.go b/java/dexpreopt_bootjars_test.go
index 9670c7f4b..4a8d3cd50 100644
--- a/java/dexpreopt_bootjars_test.go
+++ b/java/dexpreopt_bootjars_test.go
@@ -48,7 +48,7 @@ func testDexpreoptBoot(t *testing.T, ruleFile string, expectedInputs, expectedOu
pathCtx := android.PathContextForTesting(config)
dexpreoptConfig := dexpreopt.GlobalConfigForTests(pathCtx)
- dexpreoptConfig.BootJars = []string{"platform:foo", "platform:bar", "platform:baz"}
+ dexpreoptConfig.BootJars = android.CreateConfiguredJarList(pathCtx, []string{"platform:foo", "platform:bar", "platform:baz"})
dexpreopt.SetTestGlobalConfig(config, dexpreoptConfig)
ctx := testContext()
diff --git a/java/dexpreopt_config.go b/java/dexpreopt_config.go
index f13d9f210..f0d82ff92 100644
--- a/java/dexpreopt_config.go
+++ b/java/dexpreopt_config.go
@@ -37,14 +37,12 @@ func systemServerClasspath(ctx android.MakeVarsContext) []string {
filepath.Join("/system/framework", m+".jar"))
}
// 2) The jars that are from an updatable apex.
- for _, m := range global.UpdatableSystemServerJars {
- systemServerClasspathLocations = append(systemServerClasspathLocations,
- dexpreopt.GetJarLocationFromApexJarPair(ctx, m))
- }
- if len(systemServerClasspathLocations) != len(global.SystemServerJars)+len(global.UpdatableSystemServerJars) {
+ systemServerClasspathLocations = append(systemServerClasspathLocations,
+ global.UpdatableSystemServerJars.DevicePaths(ctx.Config(), android.Android)...)
+ if len(systemServerClasspathLocations) != len(global.SystemServerJars)+global.UpdatableSystemServerJars.Len() {
panic(fmt.Errorf("Wrong number of system server jars, got %d, expected %d",
len(systemServerClasspathLocations),
- len(global.SystemServerJars)+len(global.UpdatableSystemServerJars)))
+ len(global.SystemServerJars)+global.UpdatableSystemServerJars.Len()))
}
return systemServerClasspathLocations
})
@@ -69,39 +67,6 @@ func dexpreoptTargets(ctx android.PathContext) []android.Target {
return targets
}
-func stemOf(moduleName string) string {
- // b/139391334: the stem of framework-minus-apex is framework
- // This is hard coded here until we find a good way to query the stem
- // of a module before any other mutators are run
- if moduleName == "framework-minus-apex" {
- return "framework"
- }
- return moduleName
-}
-
-func getDexLocation(ctx android.PathContext, target android.Target, module string) string {
- apex, jar := android.SplitApexJarPair(ctx, module)
-
- name := stemOf(jar) + ".jar"
-
- var subdir string
- if apex == "platform" {
- // Special apex name "platform" denotes jars do not come from an apex, but are part
- // of the platform. Such jars are installed on the /system partition on device.
- subdir = "system/framework"
- } else if apex == "system_ext" {
- subdir = "system_ext/framework"
- } else {
- subdir = filepath.Join("apex", apex, "javalib")
- }
-
- if target.Os.Class == android.Host {
- return filepath.Join(ctx.Config().Getenv("OUT_DIR"), "host", ctx.Config().PrebuiltOS(), subdir, name)
- } else {
- return filepath.Join("/", subdir, name)
- }
-}
-
var (
bootImageConfigKey = android.NewOnceKey("bootImageConfig")
artBootImageName = "art"
@@ -116,12 +81,13 @@ func genBootImageConfigs(ctx android.PathContext) map[string]*bootImageConfig {
targets := dexpreoptTargets(ctx)
deviceDir := android.PathForOutput(ctx, ctx.Config().DeviceName())
- artModules := global.ArtApexJars
+ artModules := global.ArtApexJars.CopyOf()
// With EMMA_INSTRUMENT_FRAMEWORK=true the Core libraries depend on jacoco.
if ctx.Config().IsEnvTrue("EMMA_INSTRUMENT_FRAMEWORK") {
- artModules = append(artModules, "com.android.art:jacocoagent")
+ artModules.Append("com.android.art", "jacocoagent")
}
- frameworkModules := android.RemoveListFromList(global.BootJars, artModules)
+ frameworkModules := global.BootJars.CopyOf()
+ frameworkModules.RemoveList(artModules)
artSubdir := "apex/com.android.art/javalib"
frameworkSubdir := "system/framework"
@@ -163,10 +129,7 @@ func genBootImageConfigs(ctx android.PathContext) map[string]*bootImageConfig {
// Set up known paths for them, the singleton rules will copy them there.
// TODO(b/143682396): use module dependencies instead
inputDir := deviceDir.Join(ctx, "dex_"+c.name+"jars_input")
- for _, m := range c.modules {
- _, jar := android.SplitApexJarPair(ctx, m)
- c.dexPaths = append(c.dexPaths, inputDir.Join(ctx, stemOf(jar)+".jar"))
- }
+ c.dexPaths = c.modules.BuildPaths(ctx, inputDir)
c.dexPathsDeps = c.dexPaths
// Create target-specific variants.
@@ -178,9 +141,7 @@ func genBootImageConfigs(ctx android.PathContext) map[string]*bootImageConfig {
target: target,
images: imageDir.Join(ctx, imageName),
imagesDeps: c.moduleFiles(ctx, imageDir, ".art", ".oat", ".vdex"),
- }
- for _, m := range c.modules {
- variant.dexLocations = append(variant.dexLocations, getDexLocation(ctx, target, m))
+ dexLocations: c.modules.DevicePaths(ctx.Config(), target.Os),
}
variant.dexLocationsDeps = variant.dexLocations
c.variants = append(c.variants, variant)
@@ -213,10 +174,7 @@ func defaultBootclasspath(ctx android.PathContext) []string {
global := dexpreopt.GetGlobalConfig(ctx)
image := defaultBootImageConfig(ctx)
- updatableBootclasspath := make([]string, len(global.UpdatableBootJars))
- for i, p := range global.UpdatableBootJars {
- updatableBootclasspath[i] = dexpreopt.GetJarLocationFromApexJarPair(ctx, p)
- }
+ updatableBootclasspath := global.UpdatableBootJars.DevicePaths(ctx.Config(), android.Android)
bootclasspath := append(copyOf(image.getAnyAndroidVariant().dexLocationsDeps), updatableBootclasspath...)
return bootclasspath
@@ -236,5 +194,5 @@ func dexpreoptConfigMakevars(ctx android.MakeVarsContext) {
ctx.Strict("PRODUCT_DEX2OAT_BOOTCLASSPATH", strings.Join(defaultBootImageConfig(ctx).getAnyAndroidVariant().dexLocationsDeps, ":"))
ctx.Strict("PRODUCT_SYSTEM_SERVER_CLASSPATH", strings.Join(systemServerClasspath(ctx), ":"))
- ctx.Strict("DEXPREOPT_BOOT_JARS_MODULES", strings.Join(defaultBootImageConfig(ctx).modules, ":"))
+ ctx.Strict("DEXPREOPT_BOOT_JARS_MODULES", strings.Join(defaultBootImageConfig(ctx).modules.CopyOfApexJarPairs(), ":"))
}
diff --git a/java/droiddoc.go b/java/droiddoc.go
index fde18d5a5..3b192ba55 100644
--- a/java/droiddoc.go
+++ b/java/droiddoc.go
@@ -198,7 +198,7 @@ type DroiddocProperties struct {
// the generated removed Dex API filename by Doclava.
Removed_dex_api_filename *string
- // if set to false, don't allow droiddoc to generate stubs source files. Defaults to true.
+ // if set to false, don't allow droiddoc to generate stubs source files. Defaults to false.
Create_stubs *bool
Check_api struct {
@@ -294,6 +294,9 @@ type DroidstubsProperties struct {
// the dirs which Metalava extracts API levels annotations from.
Api_levels_annotations_dirs []string
+ // the filename which Metalava extracts API levels annotations from. Defaults to android.jar.
+ Api_levels_jar_filename *string
+
// if set to true, collect the values used by the Dev tools and
// write them in files packaged with the SDK. Defaults to false.
Write_sdk_values *bool
@@ -870,6 +873,10 @@ func (d *Droiddoc) doclavaDocsFlags(ctx android.ModuleContext, cmd *android.Rule
}
}
+func (d *Droiddoc) createStubs() bool {
+ return BoolDefault(d.properties.Create_stubs, false)
+}
+
func (d *Droiddoc) stubsFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, stubsDir android.WritablePath) {
if apiCheckEnabled(ctx, d.properties.Check_api.Current, "current") ||
apiCheckEnabled(ctx, d.properties.Check_api.Last_released, "last_released") ||
@@ -892,7 +899,7 @@ func (d *Droiddoc) stubsFlags(ctx android.ModuleContext, cmd *android.RuleBuilde
cmd.FlagWithOutput("-removedDexApi ", d.removedDexApiFile)
}
- if BoolDefault(d.properties.Create_stubs, true) {
+ if d.createStubs() {
cmd.FlagWithArg("-stubs ", stubsDir.String())
}
@@ -1074,9 +1081,7 @@ func (d *Droiddoc) GenerateAndroidBuildActions(ctx android.ModuleContext) {
rule.Build(pctx, ctx, "javadoc", desc)
- if apiCheckEnabled(ctx, d.properties.Check_api.Current, "current") &&
- !ctx.Config().IsPdkBuild() {
-
+ if apiCheckEnabled(ctx, d.properties.Check_api.Current, "current") {
apiFile := android.PathForModuleSrc(ctx, String(d.properties.Check_api.Current.Api_file))
removedApiFile := android.PathForModuleSrc(ctx, String(d.properties.Check_api.Current.Removed_api_file))
@@ -1143,9 +1148,7 @@ func (d *Droiddoc) GenerateAndroidBuildActions(ctx android.ModuleContext) {
rule.Build(pctx, ctx, "doclavaCurrentApiUpdate", "update current API")
}
- if apiCheckEnabled(ctx, d.properties.Check_api.Last_released, "last_released") &&
- !ctx.Config().IsPdkBuild() {
-
+ if apiCheckEnabled(ctx, d.properties.Check_api.Last_released, "last_released") {
apiFile := android.PathForModuleSrc(ctx, String(d.properties.Check_api.Last_released.Api_file))
removedApiFile := android.PathForModuleSrc(ctx, String(d.properties.Check_api.Last_released.Removed_api_file))
@@ -1403,38 +1406,41 @@ func (d *Droidstubs) inclusionAnnotationsFlags(ctx android.ModuleContext, cmd *a
}
func (d *Droidstubs) apiLevelsAnnotationsFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand) {
- if Bool(d.properties.Api_levels_annotations_enabled) {
- d.apiVersionsXml = android.PathForModuleOut(ctx, "api-versions.xml")
+ if !Bool(d.properties.Api_levels_annotations_enabled) {
+ return
+ }
- if len(d.properties.Api_levels_annotations_dirs) == 0 {
- ctx.PropertyErrorf("api_levels_annotations_dirs",
- "has to be non-empty if api levels annotations was enabled!")
- }
+ d.apiVersionsXml = android.PathForModuleOut(ctx, "api-versions.xml")
+
+ if len(d.properties.Api_levels_annotations_dirs) == 0 {
+ ctx.PropertyErrorf("api_levels_annotations_dirs",
+ "has to be non-empty if api levels annotations was enabled!")
+ }
- cmd.FlagWithOutput("--generate-api-levels ", d.apiVersionsXml)
- cmd.FlagWithInput("--apply-api-levels ", d.apiVersionsXml)
- cmd.FlagWithArg("--current-version ", ctx.Config().PlatformSdkVersion())
- cmd.FlagWithArg("--current-codename ", ctx.Config().PlatformSdkCodename())
-
- ctx.VisitDirectDepsWithTag(metalavaAPILevelsAnnotationsDirTag, func(m android.Module) {
- if t, ok := m.(*ExportedDroiddocDir); ok {
- for _, dep := range t.deps {
- if strings.HasSuffix(dep.String(), "android.jar") {
- cmd.Implicit(dep)
- }
+ cmd.FlagWithOutput("--generate-api-levels ", d.apiVersionsXml)
+ cmd.FlagWithInput("--apply-api-levels ", d.apiVersionsXml)
+ cmd.FlagWithArg("--current-version ", ctx.Config().PlatformSdkVersion())
+ cmd.FlagWithArg("--current-codename ", ctx.Config().PlatformSdkCodename())
+
+ filename := proptools.StringDefault(d.properties.Api_levels_jar_filename, "android.jar")
+
+ ctx.VisitDirectDepsWithTag(metalavaAPILevelsAnnotationsDirTag, func(m android.Module) {
+ if t, ok := m.(*ExportedDroiddocDir); ok {
+ for _, dep := range t.deps {
+ if strings.HasSuffix(dep.String(), filename) {
+ cmd.Implicit(dep)
}
- cmd.FlagWithArg("--android-jar-pattern ", t.dir.String()+"/%/public/android.jar")
- } else {
- ctx.PropertyErrorf("api_levels_annotations_dirs",
- "module %q is not a metalava api-levels-annotations dir", ctx.OtherModuleName(m))
}
- })
-
- }
+ cmd.FlagWithArg("--android-jar-pattern ", t.dir.String()+"/%/public/"+filename)
+ } else {
+ ctx.PropertyErrorf("api_levels_annotations_dirs",
+ "module %q is not a metalava api-levels-annotations dir", ctx.OtherModuleName(m))
+ }
+ })
}
func (d *Droidstubs) apiToXmlFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand) {
- if Bool(d.properties.Jdiff_enabled) && !ctx.Config().IsPdkBuild() && d.apiFile != nil {
+ if Bool(d.properties.Jdiff_enabled) && d.apiFile != nil {
if d.apiFile.String() == "" {
ctx.ModuleErrorf("API signature file has to be specified in Metalava when jdiff is enabled.")
}
@@ -1582,7 +1588,7 @@ func (d *Droidstubs) GenerateAndroidBuildActions(ctx android.ModuleContext) {
// Add API lint options.
- if BoolDefault(d.properties.Check_api.Api_lint.Enabled, false) && !ctx.Config().IsPdkBuild() {
+ if BoolDefault(d.properties.Check_api.Api_lint.Enabled, false) {
doApiLint = true
newSince := android.OptionalPathForModuleSrc(ctx, d.properties.Check_api.Api_lint.New_since)
@@ -1649,8 +1655,7 @@ func (d *Droidstubs) GenerateAndroidBuildActions(ctx android.ModuleContext) {
// Add "check released" options. (Detect incompatible API changes from the last public release)
- if apiCheckEnabled(ctx, d.properties.Check_api.Last_released, "last_released") &&
- !ctx.Config().IsPdkBuild() {
+ if apiCheckEnabled(ctx, d.properties.Check_api.Last_released, "last_released") {
doCheckReleased = true
if len(d.Javadoc.properties.Out) > 0 {
@@ -1683,7 +1688,7 @@ func (d *Droidstubs) GenerateAndroidBuildActions(ctx android.ModuleContext) {
impRule := android.NewRuleBuilder()
impCmd := impRule.Command()
- // A dummy action that copies the ninja generated rsp file to a new location. This allows us to
+ // An action that copies the ninja generated rsp file to a new location. This allows us to
// add a large number of inputs to a file without exceeding bash command length limits (which
// would happen if we use the WriteFile rule). The cp is needed because RuleBuilder sets the
// rsp file to be ${output}.rsp.
@@ -1727,8 +1732,7 @@ func (d *Droidstubs) GenerateAndroidBuildActions(ctx android.ModuleContext) {
rule.Build(pctx, ctx, "metalava", "metalava merged")
- if apiCheckEnabled(ctx, d.properties.Check_api.Current, "current") &&
- !ctx.Config().IsPdkBuild() {
+ if apiCheckEnabled(ctx, d.properties.Check_api.Current, "current") {
if len(d.Javadoc.properties.Out) > 0 {
ctx.PropertyErrorf("out", "out property may not be combined with check_api")
@@ -1842,7 +1846,7 @@ func (d *Droidstubs) GenerateAndroidBuildActions(ctx android.ModuleContext) {
rule.Build(pctx, ctx, "nullabilityWarningsCheck", "nullability warnings check")
}
- if Bool(d.properties.Jdiff_enabled) && !ctx.Config().IsPdkBuild() {
+ if Bool(d.properties.Jdiff_enabled) {
if len(d.Javadoc.properties.Out) > 0 {
ctx.PropertyErrorf("out", "out property may not be combined with jdiff")
}
diff --git a/java/hiddenapi.go b/java/hiddenapi.go
index b5a021785..63b801a5c 100644
--- a/java/hiddenapi.go
+++ b/java/hiddenapi.go
@@ -23,8 +23,8 @@ import (
)
var hiddenAPIGenerateCSVRule = pctx.AndroidStaticRule("hiddenAPIGenerateCSV", blueprint.RuleParams{
- Command: "${config.Class2Greylist} --stub-api-flags ${stubAPIFlags} $in $outFlag $out",
- CommandDeps: []string{"${config.Class2Greylist}"},
+ Command: "${config.Class2NonSdkList} --stub-api-flags ${stubAPIFlags} $in $outFlag $out",
+ CommandDeps: []string{"${config.Class2NonSdkList}"},
}, "outFlag", "stubAPIFlags")
type hiddenAPI struct {
diff --git a/java/hiddenapi_singleton.go b/java/hiddenapi_singleton.go
index 857894958..29b6bcd7d 100644
--- a/java/hiddenapi_singleton.go
+++ b/java/hiddenapi_singleton.go
@@ -43,7 +43,7 @@ func hiddenAPISingletonPaths(ctx android.PathContext) hiddenAPISingletonPathsStr
return hiddenAPISingletonPathsStruct{
flags: android.PathForOutput(ctx, "hiddenapi", "hiddenapi-flags.csv"),
index: android.PathForOutput(ctx, "hiddenapi", "hiddenapi-index.csv"),
- metadata: android.PathForOutput(ctx, "hiddenapi", "hiddenapi-greylist.csv"),
+ metadata: android.PathForOutput(ctx, "hiddenapi", "hiddenapi-unsupported.csv"),
stubFlags: android.PathForOutput(ctx, "hiddenapi", "hiddenapi-stub-flags.txt"),
}
}).(hiddenAPISingletonPathsStruct)
@@ -100,7 +100,7 @@ func stubFlagsRule(ctx android.SingletonContext) {
// Add the android.test.base to the set of stubs only if the android.test.base module is on
// the boot jars list as the runtime will only enforce hiddenapi access against modules on
// that list.
- if inList("android.test.base", ctx.Config().BootJars()) && !ctx.Config().UnbundledBuildUsePrebuiltSdks() {
+ if inList("android.test.base", ctx.Config().BootJars()) && !ctx.Config().AlwaysUsePrebuiltSdks() {
publicStubModules = append(publicStubModules, "android.test.base.stubs")
}
@@ -217,7 +217,7 @@ func moduleForGreyListRemovedApis(ctx android.SingletonContext, module android.M
}
// flagsRule creates a rule to build hiddenapi-flags.csv out of flags.csv files generated for boot image modules and
-// the greylists.
+// the unsupported API.
func flagsRule(ctx android.SingletonContext) android.Path {
var flagsCSV android.Paths
var greylistRemovedApis android.Paths
@@ -256,19 +256,19 @@ func flagsRule(ctx android.SingletonContext) android.Path {
Tool(android.PathForSource(ctx, "frameworks/base/tools/hiddenapi/generate_hiddenapi_lists.py")).
FlagWithInput("--csv ", stubFlags).
Inputs(flagsCSV).
- FlagWithInput("--greylist ",
- android.PathForSource(ctx, "frameworks/base/config/hiddenapi-greylist.txt")).
- FlagWithInput("--greylist-ignore-conflicts ", combinedRemovedApis).
- FlagWithInput("--greylist-max-q ",
- android.PathForSource(ctx, "frameworks/base/config/hiddenapi-greylist-max-q.txt")).
- FlagWithInput("--greylist-max-p ",
- android.PathForSource(ctx, "frameworks/base/config/hiddenapi-greylist-max-p.txt")).
- FlagWithInput("--greylist-max-o-ignore-conflicts ",
- android.PathForSource(ctx, "frameworks/base/config/hiddenapi-greylist-max-o.txt")).
- FlagWithInput("--blacklist ",
- android.PathForSource(ctx, "frameworks/base/config/hiddenapi-force-blacklist.txt")).
- FlagWithInput("--greylist-packages ",
- android.PathForSource(ctx, "frameworks/base/config/hiddenapi-greylist-packages.txt")).
+ FlagWithInput("--unsupported ",
+ android.PathForSource(ctx, "frameworks/base/config/hiddenapi-unsupported.txt")).
+ FlagWithInput("--unsupported-ignore-conflicts ", combinedRemovedApis).
+ FlagWithInput("--max-target-q ",
+ android.PathForSource(ctx, "frameworks/base/config/hiddenapi-max-target-q.txt")).
+ FlagWithInput("--max-target-p ",
+ android.PathForSource(ctx, "frameworks/base/config/hiddenapi-max-target-p.txt")).
+ FlagWithInput("--max-target-o-ignore-conflicts ",
+ android.PathForSource(ctx, "frameworks/base/config/hiddenapi-max-target-o.txt")).
+ FlagWithInput("--blocked ",
+ android.PathForSource(ctx, "frameworks/base/config/hiddenapi-force-blocked.txt")).
+ FlagWithInput("--unsupported-packages ",
+ android.PathForSource(ctx, "frameworks/base/config/hiddenapi-unsupported-packages.txt")).
FlagWithOutput("--output ", tempPath)
commitChangeForRestat(rule, tempPath, outputPath)
@@ -293,7 +293,7 @@ func emptyFlagsRule(ctx android.SingletonContext) android.Path {
return outputPath
}
-// metadataRule creates a rule to build hiddenapi-greylist.csv out of the metadata.csv files generated for boot image
+// metadataRule creates a rule to build hiddenapi-unsupported.csv out of the metadata.csv files generated for boot image
// modules.
func metadataRule(ctx android.SingletonContext) android.Path {
var metadataCSV android.Paths
diff --git a/java/java.go b/java/java.go
index ebff4e01b..79ad74a1f 100644
--- a/java/java.go
+++ b/java/java.go
@@ -29,6 +29,7 @@ import (
"github.com/google/blueprint/proptools"
"android/soong/android"
+ "android/soong/dexpreopt"
"android/soong/java/config"
"android/soong/tradefed"
)
@@ -264,9 +265,6 @@ type CompilerProperties struct {
}
type CompilerDeviceProperties struct {
- // list of module-specific flags that will be used for dex compiles
- Dxflags []string `android:"arch_variant"`
-
// if not blank, set to the version of the sdk to compile against.
// Defaults to compiling against the current platform.
Sdk_version *string
@@ -312,37 +310,6 @@ type CompilerDeviceProperties struct {
}
}
- // If set to true, compile dex regardless of installable. Defaults to false.
- Compile_dex *bool
-
- Optimize struct {
- // If false, disable all optimization. Defaults to true for android_app and android_test
- // modules, false for java_library and java_test modules.
- Enabled *bool
- // True if the module containing this has it set by default.
- EnabledByDefault bool `blueprint:"mutated"`
-
- // If true, optimize for size by removing unused code. Defaults to true for apps,
- // false for libraries and tests.
- Shrink *bool
-
- // If true, optimize bytecode. Defaults to false.
- Optimize *bool
-
- // If true, obfuscate bytecode. Defaults to false.
- Obfuscate *bool
-
- // If true, do not use the flag files generated by aapt that automatically keep
- // classes referenced by the app manifest. Defaults to false.
- No_aapt_flags *bool
-
- // Flags to pass to proguard.
- Proguard_flags []string
-
- // Specifies the locations of files containing proguard flags.
- Proguard_flags_files []string `android:"path"`
- }
-
// When targeting 1.9 and above, override the modules to use with --system,
// otherwise provides defaults libraries to add to the bootclasspath.
System_modules *string
@@ -356,12 +323,6 @@ type CompilerDeviceProperties struct {
// set the name of the output
Stem *string
- // Keep the data uncompressed. We always need uncompressed dex for execution,
- // so this might actually save space by avoiding storing the same data twice.
- // This defaults to reasonable value based on module and should not be set.
- // It exists only to support ART tests.
- Uncompress_dex *bool
-
IsSDKLibrary bool `blueprint:"mutated"`
// If true, generate the signature file of APK Signing Scheme V4, along side the signed APK file.
@@ -369,10 +330,6 @@ type CompilerDeviceProperties struct {
V4_signature *bool
}
-func (me *CompilerDeviceProperties) EffectiveOptimizeEnabled() bool {
- return BoolDefault(me.Optimize.Enabled, me.Optimize.EnabledByDefault)
-}
-
// Functionality common to Module and Import
//
// It is embedded in Module so its functionality can be used by methods in Module
@@ -441,9 +398,6 @@ type Module struct {
// output file containing uninstrumented classes that will be instrumented by jacoco
jacocoReportClassesFile android.Path
- // output file containing mapping of obfuscated names
- proguardDictionary android.Path
-
// output file of the module, which may be a classes jar or a dex jar
outputFile android.Path
extraOutputFiles android.Paths
@@ -459,14 +413,11 @@ type Module struct {
compiledJavaSrcs android.Paths
compiledSrcJars android.Paths
- // list of extra progurad flag files
- extraProguardFlagFiles android.Paths
-
// manifest file to use instead of properties.Manifest
overrideManifest android.OptionalPath
- // list of SDK lib names that this java module is exporting
- exportedSdkLibs []string
+ // map of SDK libs exported by this java module to their build and install paths
+ exportedSdkLibs dexpreopt.LibraryPaths
// list of plugins that this java module is exporting
exportedPluginJars android.Paths
@@ -488,6 +439,7 @@ type Module struct {
extraResources android.Paths
hiddenAPI
+ dexer
dexpreopter
linter
@@ -511,6 +463,7 @@ func (j *Module) addHostAndDeviceProperties() {
j.addHostProperties()
j.AddProperties(
&j.deviceProperties,
+ &j.dexer.dexProperties,
&j.dexpreoptProperties,
&j.linter.properties,
)
@@ -523,7 +476,10 @@ func (j *Module) OutputFiles(tag string) (android.Paths, error) {
case ".jar":
return android.Paths{j.implementationAndResourcesJar}, nil
case ".proguard_map":
- return android.Paths{j.proguardDictionary}, nil
+ if j.dexer.proguardDictionary.Valid() {
+ return android.Paths{j.dexer.proguardDictionary.Path()}, nil
+ }
+ return nil, fmt.Errorf("%q was requested, but no output file was found.", tag)
default:
return nil, fmt.Errorf("unsupported module reference tag %q", tag)
}
@@ -537,14 +493,19 @@ type ApexDependency interface {
ImplementationAndResourcesJars() android.Paths
}
+// Provides build path and install path to DEX jars.
+type UsesLibraryDependency interface {
+ DexJarBuildPath() android.Path
+ DexJarInstallPath() android.Path
+}
+
type Dependency interface {
ApexDependency
+ UsesLibraryDependency
ImplementationJars() android.Paths
ResourceJars() android.Paths
- DexJarBuildPath() android.Path
- DexJarInstallPath() android.Path
AidlIncludeDirs() android.Paths
- ExportedSdkLibs() []string
+ ExportedSdkLibs() dexpreopt.LibraryPaths
ExportedPlugins() (android.Paths, []string)
SrcJarArgs() ([]string, android.Paths)
BaseModuleName() string
@@ -560,7 +521,20 @@ func (j *Module) XrefJavaFiles() android.Paths {
}
func InitJavaModule(module android.DefaultableModule, hod android.HostOrDeviceSupported) {
- android.InitAndroidArchModule(module, hod, android.MultilibCommon)
+ initJavaModule(module, hod, false)
+}
+
+func InitJavaModuleMultiTargets(module android.DefaultableModule, hod android.HostOrDeviceSupported) {
+ initJavaModule(module, hod, true)
+}
+
+func initJavaModule(module android.DefaultableModule, hod android.HostOrDeviceSupported, multiTargets bool) {
+ multilib := android.MultilibCommon
+ if multiTargets {
+ android.InitAndroidMultiTargetsArchModule(module, hod, multilib)
+ } else {
+ android.InitAndroidArchModule(module, hod, multilib)
+ }
android.InitDefaultableModule(module)
}
@@ -579,6 +553,7 @@ func IsJniDepTag(depTag blueprint.DependencyTag) bool {
}
var (
+ dataNativeBinsTag = dependencyTag{name: "dataNativeBins"}
staticLibTag = dependencyTag{name: "staticlib"}
libTag = dependencyTag{name: "javalib"}
java9LibTag = dependencyTag{name: "java9lib"}
@@ -587,7 +562,6 @@ var (
bootClasspathTag = dependencyTag{name: "bootclasspath"}
systemModulesTag = dependencyTag{name: "system modules"}
frameworkResTag = dependencyTag{name: "framework-res"}
- frameworkApkTag = dependencyTag{name: "framework-apk"}
kotlinStdlibTag = dependencyTag{name: "kotlin-stdlib"}
kotlinAnnotationsTag = dependencyTag{name: "kotlin-annotations"}
proguardRaiseTag = dependencyTag{name: "proguard-raise"}
@@ -718,22 +692,16 @@ func (j *Module) deps(ctx android.BottomUpMutatorContext) {
ctx.AddVariationDependencies(nil, bootClasspathTag, sdkDep.bootclasspath...)
ctx.AddVariationDependencies(nil, java9LibTag, sdkDep.java9Classpath...)
ctx.AddVariationDependencies(nil, libTag, sdkDep.classpath...)
- if j.deviceProperties.EffectiveOptimizeEnabled() && sdkDep.hasStandardLibs() {
+ if j.effectiveOptimizeEnabled() && sdkDep.hasStandardLibs() {
ctx.AddVariationDependencies(nil, proguardRaiseTag, config.LegacyCorePlatformBootclasspathLibraries...)
}
- if j.deviceProperties.EffectiveOptimizeEnabled() && sdkDep.hasFrameworkLibs() {
+ if j.effectiveOptimizeEnabled() && sdkDep.hasFrameworkLibs() {
ctx.AddVariationDependencies(nil, proguardRaiseTag, config.FrameworkLibraries...)
}
}
if sdkDep.systemModules != "" {
ctx.AddVariationDependencies(nil, systemModulesTag, sdkDep.systemModules)
}
-
- if ctx.ModuleName() == "android_stubs_current" ||
- ctx.ModuleName() == "android_system_stubs_current" ||
- ctx.ModuleName() == "android_test_stubs_current" {
- ctx.AddVariationDependencies(nil, frameworkApkTag, "framework-res")
- }
}
syspropPublicStubs := syspropPublicStubs(ctx.Config())
@@ -1008,12 +976,6 @@ func (j *Module) collectDeps(ctx android.ModuleContext) deps {
}
}
- // If this is a component library (stubs, etc.) for a java_sdk_library then
- // add the name of that java_sdk_library to the exported sdk libs to make sure
- // that, if necessary, a <uses-library> element for that java_sdk_library is
- // added to the Android manifest.
- j.exportedSdkLibs = append(j.exportedSdkLibs, j.OptionalImplicitSdkLibrary()...)
-
ctx.VisitDirectDeps(func(module android.Module) {
otherName := ctx.OtherModuleName(module)
tag := ctx.OtherModuleDependencyTag(module)
@@ -1033,7 +995,7 @@ func (j *Module) collectDeps(ctx android.ModuleContext) deps {
case libTag:
deps.classpath = append(deps.classpath, dep.SdkHeaderJars(ctx, j.sdkVersion())...)
// names of sdk libs that are directly depended are exported
- j.exportedSdkLibs = append(j.exportedSdkLibs, dep.OptionalImplicitSdkLibrary()...)
+ j.exportedSdkLibs.MaybeAddLibraryPath(ctx, dep.OptionalImplicitSdkLibrary(), dep.DexJarBuildPath(), dep.DexJarInstallPath())
case staticLibTag:
ctx.ModuleErrorf("dependency on java_sdk_library %q can only be in libs", otherName)
}
@@ -1044,7 +1006,7 @@ func (j *Module) collectDeps(ctx android.ModuleContext) deps {
case libTag, instrumentationForTag:
deps.classpath = append(deps.classpath, dep.HeaderJars()...)
// sdk lib names from dependencies are re-exported
- j.exportedSdkLibs = append(j.exportedSdkLibs, dep.ExportedSdkLibs()...)
+ j.exportedSdkLibs.AddLibraryPaths(dep.ExportedSdkLibs())
deps.aidlIncludeDirs = append(deps.aidlIncludeDirs, dep.AidlIncludeDirs()...)
pluginJars, pluginClasses := dep.ExportedPlugins()
addPlugins(&deps, pluginJars, pluginClasses...)
@@ -1056,7 +1018,7 @@ func (j *Module) collectDeps(ctx android.ModuleContext) deps {
deps.staticHeaderJars = append(deps.staticHeaderJars, dep.HeaderJars()...)
deps.staticResourceJars = append(deps.staticResourceJars, dep.ResourceJars()...)
// sdk lib names from dependencies are re-exported
- j.exportedSdkLibs = append(j.exportedSdkLibs, dep.ExportedSdkLibs()...)
+ j.exportedSdkLibs.AddLibraryPaths(dep.ExportedSdkLibs())
deps.aidlIncludeDirs = append(deps.aidlIncludeDirs, dep.AidlIncludeDirs()...)
pluginJars, pluginClasses := dep.ExportedPlugins()
addPlugins(&deps, pluginJars, pluginClasses...)
@@ -1083,18 +1045,6 @@ func (j *Module) collectDeps(ctx android.ModuleContext) deps {
} else {
ctx.PropertyErrorf("exported_plugins", "%q is not a java_plugin module", otherName)
}
- case frameworkApkTag:
- if ctx.ModuleName() == "android_stubs_current" ||
- ctx.ModuleName() == "android_system_stubs_current" ||
- ctx.ModuleName() == "android_test_stubs_current" {
- // framework stubs.jar need to depend on framework-res.apk, in order to pull the
- // resource files out of there for aapt.
- //
- // Normally the package rule runs aapt, which includes the resource,
- // but we're not running that in our package rule so just copy in the
- // resource files here.
- deps.staticResourceJars = append(deps.staticResourceJars, dep.(*AndroidApp).exportPackage)
- }
case kotlinStdlibTag:
deps.kotlinStdlib = append(deps.kotlinStdlib, dep.HeaderJars()...)
case kotlinAnnotationsTag:
@@ -1131,8 +1081,6 @@ func (j *Module) collectDeps(ctx android.ModuleContext) deps {
}
})
- j.exportedSdkLibs = android.FirstUniqueStrings(j.exportedSdkLibs)
-
return deps
}
@@ -1637,8 +1585,8 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) {
// Enable dex compilation for the APEX variants, unless it is disabled explicitly
if android.DirectlyInAnyApex(ctx, ctx.ModuleName()) && !j.IsForPlatform() {
- if j.deviceProperties.Compile_dex == nil {
- j.deviceProperties.Compile_dex = proptools.BoolPtr(true)
+ if j.dexProperties.Compile_dex == nil {
+ j.dexProperties.Compile_dex = proptools.BoolPtr(true)
}
if j.deviceProperties.Hostdex == nil {
j.deviceProperties.Hostdex = proptools.BoolPtr(true)
@@ -1646,10 +1594,14 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) {
}
if ctx.Device() && j.hasCode(ctx) &&
- (Bool(j.properties.Installable) || Bool(j.deviceProperties.Compile_dex)) {
+ (Bool(j.properties.Installable) || Bool(j.dexProperties.Compile_dex)) {
+ if j.shouldInstrumentStatic(ctx) {
+ j.dexer.extraProguardFlagFiles = append(j.dexer.extraProguardFlagFiles,
+ android.PathForSource(ctx, "build/make/core/proguard.jacoco.flags"))
+ }
// Dex compilation
var dexOutputFile android.ModuleOutPath
- dexOutputFile = j.compileDex(ctx, flags, outputFile, jarName)
+ dexOutputFile = j.dexer.compileDex(ctx, flags, j.minSdkVersion(), outputFile, jarName)
if ctx.Failed() {
return
}
@@ -1659,7 +1611,7 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) {
// Hidden API CSV generation and dex encoding
dexOutputFile = j.hiddenAPI.hiddenAPI(ctx, configurationName, primary, dexOutputFile, j.implementationJarFile,
- proptools.Bool(j.deviceProperties.Uncompress_dex))
+ proptools.Bool(j.dexProperties.Uncompress_dex))
// merge dex jar with resources if necessary
if j.resourceJar != nil {
@@ -1667,7 +1619,7 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) {
combinedJar := android.PathForModuleOut(ctx, "dex-withres", jarName)
TransformJarsToJar(ctx, combinedJar, "for dex resources", jars, android.OptionalPath{},
false, nil, nil)
- if *j.deviceProperties.Uncompress_dex {
+ if *j.dexProperties.Uncompress_dex {
combinedAlignedJar := android.PathForModuleOut(ctx, "dex-withres-aligned", jarName)
TransformZipAlign(ctx, combinedAlignedJar, combinedJar)
dexOutputFile = combinedAlignedJar
@@ -1711,6 +1663,9 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) {
j.linter.compileSdkVersion = lintSDKVersionString(j.sdkVersion())
j.linter.javaLanguageLevel = flags.javaVersion.String()
j.linter.kotlinLanguageLevel = "1.3"
+ if j.ApexVariationName() != "" && ctx.Config().UnbundledBuildApps() {
+ j.linter.buildModuleReportZip = true
+ }
j.linter.lint(ctx)
}
@@ -1866,8 +1821,7 @@ func (j *Module) AidlIncludeDirs() android.Paths {
return j.exportAidlIncludeDirs
}
-func (j *Module) ExportedSdkLibs() []string {
- // exportedSdkLibs is type []string
+func (j *Module) ExportedSdkLibs() dexpreopt.LibraryPaths {
return j.exportedSdkLibs
}
@@ -1995,11 +1949,12 @@ func (j *Library) GenerateAndroidBuildActions(ctx android.ModuleContext) {
j.checkSdkVersions(ctx)
j.dexpreopter.installPath = android.PathForModuleInstall(ctx, "framework", j.Stem()+".jar")
j.dexpreopter.isSDKLibrary = j.deviceProperties.IsSDKLibrary
- if j.deviceProperties.Uncompress_dex == nil {
+ if j.dexProperties.Uncompress_dex == nil {
// If the value was not force-set by the user, use reasonable default based on the module.
- j.deviceProperties.Uncompress_dex = proptools.BoolPtr(shouldUncompressDex(ctx, &j.dexpreopter))
+ j.dexProperties.Uncompress_dex = proptools.BoolPtr(shouldUncompressDex(ctx, &j.dexpreopter))
}
- j.dexpreopter.uncompressedDex = *j.deviceProperties.Uncompress_dex
+ j.dexpreopter.uncompressedDex = *j.dexProperties.Uncompress_dex
+ j.exportedSdkLibs = make(dexpreopt.LibraryPaths)
j.compile(ctx, nil)
// Collect the module directory for IDE info in java/jdeps.go.
@@ -2015,6 +1970,12 @@ func (j *Library) GenerateAndroidBuildActions(ctx android.ModuleContext) {
j.Stem()+".jar", j.outputFile, extraInstallDeps...)
}
+ // If this is a component library (stubs, etc.) for a java_sdk_library then
+ // add the name of that java_sdk_library to the exported sdk libs to make sure
+ // that, if necessary, a <uses-library> element for that java_sdk_library is
+ // added to the Android manifest.
+ j.exportedSdkLibs.MaybeAddLibraryPath(ctx, j.OptionalImplicitSdkLibrary(), j.DexJarBuildPath(), j.DexJarInstallPath())
+
j.distFiles = j.GenerateTaggedDistFiles(ctx)
}
@@ -2167,6 +2128,12 @@ func LibraryHostFactory() android.Module {
// Java Tests
//
+// Test option struct.
+type TestOptions struct {
+ // a list of extra test configuration files that should be installed with the module.
+ Extra_test_configs []string `android:"path,arch_variant"`
+}
+
type testProperties struct {
// list of compatibility suites (for example "cts", "vts") that the module should be
// installed into.
@@ -2192,6 +2159,14 @@ type testProperties struct {
// Add parameterized mainline modules to auto generated test config. The options will be
// handled by TradeFed to do downloading and installing the specified modules on the device.
Test_mainline_modules []string
+
+ // Test options.
+ Test_options TestOptions
+}
+
+type hostTestProperties struct {
+ // list of native binary modules that should be installed alongside the test
+ Data_native_bins []string `android:"arch_variant"`
}
type testHelperLibraryProperties struct {
@@ -2215,8 +2190,15 @@ type Test struct {
testProperties testProperties
- testConfig android.Path
- data android.Paths
+ testConfig android.Path
+ extraTestConfigs android.Paths
+ data android.Paths
+}
+
+type TestHost struct {
+ Test
+
+ testHostProperties hostTestProperties
}
type TestHelperLibrary struct {
@@ -2233,11 +2215,28 @@ type JavaTestImport struct {
testConfig android.Path
}
+func (j *TestHost) DepsMutator(ctx android.BottomUpMutatorContext) {
+ if len(j.testHostProperties.Data_native_bins) > 0 {
+ for _, target := range ctx.MultiTargets() {
+ ctx.AddVariationDependencies(target.Variations(), dataNativeBinsTag, j.testHostProperties.Data_native_bins...)
+ }
+ }
+
+ j.deps(ctx)
+}
+
func (j *Test) GenerateAndroidBuildActions(ctx android.ModuleContext) {
j.testConfig = tradefed.AutoGenJavaTestConfig(ctx, j.testProperties.Test_config, j.testProperties.Test_config_template,
j.testProperties.Test_suites, j.testProperties.Auto_gen_config)
+
j.data = android.PathsForModuleSrc(ctx, j.testProperties.Data)
+ j.extraTestConfigs = android.PathsForModuleSrc(ctx, j.testProperties.Test_options.Extra_test_configs)
+
+ ctx.VisitDirectDepsWithTag(dataNativeBinsTag, func(dep android.Module) {
+ j.data = append(j.data, android.OutputFileForModule(ctx, dep, ""))
+ })
+
j.Library.GenerateAndroidBuildActions(ctx)
}
@@ -2378,14 +2377,15 @@ func JavaTestImportFactory() android.Module {
// A java_test_host has a single variant that produces a `.jar` file containing `.class` files that were
// compiled against the host bootclasspath.
func TestHostFactory() android.Module {
- module := &Test{}
+ module := &TestHost{}
module.addHostProperties()
module.AddProperties(&module.testProperties)
+ module.AddProperties(&module.testHostProperties)
module.Module.properties.Installable = proptools.BoolPtr(true)
- InitJavaModule(module, android.HostSupported)
+ InitJavaModuleMultiTargets(module, android.HostSupported)
return module
}
@@ -2538,7 +2538,7 @@ type Import struct {
properties ImportProperties
combinedClasspathFile android.Path
- exportedSdkLibs []string
+ exportedSdkLibs dexpreopt.LibraryPaths
exportAidlIncludeDirs android.Paths
}
@@ -2546,6 +2546,10 @@ func (j *Import) sdkVersion() sdkSpec {
return sdkSpecFrom(String(j.properties.Sdk_version))
}
+func (j *Import) makeSdkVersion() string {
+ return j.sdkVersion().raw
+}
+
func (j *Import) minSdkVersion() sdkSpec {
return j.sdkVersion()
}
@@ -2591,12 +2595,7 @@ func (j *Import) GenerateAndroidBuildActions(ctx android.ModuleContext) {
TransformJetifier(ctx, outputFile, inputFile)
}
j.combinedClasspathFile = outputFile
-
- // If this is a component library (impl, stubs, etc.) for a java_sdk_library then
- // add the name of that java_sdk_library to the exported sdk libs to make sure
- // that, if necessary, a <uses-library> element for that java_sdk_library is
- // added to the Android manifest.
- j.exportedSdkLibs = append(j.exportedSdkLibs, j.OptionalImplicitSdkLibrary()...)
+ j.exportedSdkLibs = make(dexpreopt.LibraryPaths)
ctx.VisitDirectDeps(func(module android.Module) {
otherName := ctx.OtherModuleName(module)
@@ -2607,23 +2606,29 @@ func (j *Import) GenerateAndroidBuildActions(ctx android.ModuleContext) {
switch tag {
case libTag, staticLibTag:
// sdk lib names from dependencies are re-exported
- j.exportedSdkLibs = append(j.exportedSdkLibs, dep.ExportedSdkLibs()...)
+ j.exportedSdkLibs.AddLibraryPaths(dep.ExportedSdkLibs())
}
case SdkLibraryDependency:
switch tag {
case libTag:
// names of sdk libs that are directly depended are exported
- j.exportedSdkLibs = append(j.exportedSdkLibs, otherName)
+ j.exportedSdkLibs.AddLibraryPath(ctx, otherName, dep.DexJarBuildPath(), dep.DexJarInstallPath())
}
}
})
- j.exportedSdkLibs = android.FirstUniqueStrings(j.exportedSdkLibs)
+ var installFile android.Path
if Bool(j.properties.Installable) {
- ctx.InstallFile(android.PathForModuleInstall(ctx, "framework"),
+ installFile = ctx.InstallFile(android.PathForModuleInstall(ctx, "framework"),
jarName, outputFile)
}
+ // If this is a component library (impl, stubs, etc.) for a java_sdk_library then
+ // add the name of that java_sdk_library to the exported sdk libs to make sure
+ // that, if necessary, a <uses-library> element for that java_sdk_library is
+ // added to the Android manifest.
+ j.exportedSdkLibs.MaybeAddLibraryPath(ctx, j.OptionalImplicitSdkLibrary(), outputFile, installFile)
+
j.exportAidlIncludeDirs = android.PathsForModuleSrc(ctx, j.properties.Aidl.Export_include_dirs)
}
@@ -2666,7 +2671,7 @@ func (j *Import) AidlIncludeDirs() android.Paths {
return j.exportAidlIncludeDirs
}
-func (j *Import) ExportedSdkLibs() []string {
+func (j *Import) ExportedSdkLibs() dexpreopt.LibraryPaths {
return j.exportedSdkLibs
}
@@ -2793,6 +2798,10 @@ func (a *DexImport) JacocoReportClassesFile() android.Path {
return nil
}
+func (a *DexImport) LintDepSets() LintDepSets {
+ return LintDepSets{}
+}
+
func (j *DexImport) IsInstallable() bool {
return true
}
@@ -2926,6 +2935,7 @@ func DefaultsFactory() android.Module {
module.AddProperties(
&CompilerProperties{},
&CompilerDeviceProperties{},
+ &DexProperties{},
&DexpreoptProperties{},
&android.ProtoProperties{},
&aaptProperties{},
diff --git a/java/java_test.go b/java/java_test.go
index db3f18740..0e936118c 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -20,7 +20,6 @@ import (
"path/filepath"
"reflect"
"regexp"
- "sort"
"strconv"
"strings"
"testing"
@@ -31,6 +30,7 @@ import (
"android/soong/cc"
"android/soong/dexpreopt"
"android/soong/genrule"
+ "android/soong/python"
)
var buildDir string
@@ -81,6 +81,7 @@ func testContext() *android.TestContext {
ctx.RegisterModuleType("java_plugin", PluginFactory)
ctx.RegisterModuleType("filegroup", android.FileGroupFactory)
ctx.RegisterModuleType("genrule", genrule.GenRuleFactory)
+ ctx.RegisterModuleType("python_binary_host", python.PythonBinaryHostFactory)
RegisterDocsBuildComponents(ctx)
RegisterStubsBuildComponents(ctx)
RegisterSdkLibraryBuildComponents(ctx)
@@ -89,10 +90,13 @@ func testContext() *android.TestContext {
RegisterPrebuiltApisBuildComponents(ctx)
+ ctx.PreDepsMutators(python.RegisterPythonPreDepsMutators)
ctx.PostDepsMutators(android.RegisterOverridePostDepsMutators)
ctx.RegisterPreSingletonType("overlay", android.SingletonFactoryAdaptor(OverlaySingletonFactory))
ctx.RegisterPreSingletonType("sdk_versions", android.SingletonFactoryAdaptor(sdkPreSingletonFactory))
+ android.RegisterPrebuiltMutators(ctx)
+
// Register module types and mutators from cc needed for JNI testing
cc.RegisterRequiredBuildComponentsForTest(ctx)
@@ -486,7 +490,7 @@ func TestHostBinaryNoJavaDebugInfoOverride(t *testing.T) {
ctx, _ := testJavaWithConfig(t, config)
- // first, sanity check that the -g flag is added to target modules
+ // first, check that the -g flag is added to target modules
targetLibrary := ctx.ModuleForTests("target_library", "android_common")
targetJavaFlags := targetLibrary.Module().VariablesForTests()["javacFlags"]
if !strings.Contains(targetJavaFlags, "-g:source,lines") {
@@ -1104,8 +1108,13 @@ func TestDroiddoc(t *testing.T) {
"bar-doc/a.java": nil,
"bar-doc/b.java": nil,
})
+ barDocModule := ctx.ModuleForTests("bar-doc", "android_common")
+ barDoc := barDocModule.Rule("javadoc")
+ notExpected := " -stubs "
+ if strings.Contains(barDoc.RuleParams.Command, notExpected) {
+ t.Errorf("bar-doc command contains flag %q to create stubs, but should not", notExpected)
+ }
- barDoc := ctx.ModuleForTests("bar-doc", "android_common").Rule("javadoc")
var javaSrcs []string
for _, i := range barDoc.Inputs {
javaSrcs = append(javaSrcs, i.Base())
@@ -1114,7 +1123,7 @@ func TestDroiddoc(t *testing.T) {
t.Errorf("inputs of bar-doc must be []string{\"a.java\"}, but was %#v.", javaSrcs)
}
- aidl := ctx.ModuleForTests("bar-doc", "android_common").Rule("aidl")
+ aidl := barDocModule.Rule("aidl")
if g, w := barDoc.Implicits.Strings(), aidl.Output.String(); !inList(w, g) {
t.Errorf("implicits of bar-doc must contain %q, but was %q.", w, g)
}
@@ -1160,6 +1169,62 @@ func TestDroiddocArgsAndFlagsCausesError(t *testing.T) {
`)
}
+func TestDroidstubs(t *testing.T) {
+ ctx, _ := testJavaWithFS(t, `
+ droiddoc_exported_dir {
+ name: "droiddoc-templates-sdk",
+ path: ".",
+ }
+
+ droidstubs {
+ name: "bar-stubs",
+ srcs: [
+ "bar-doc/a.java",
+ ],
+ api_levels_annotations_dirs: [
+ "droiddoc-templates-sdk",
+ ],
+ api_levels_annotations_enabled: true,
+ }
+
+ droidstubs {
+ name: "bar-stubs-other",
+ srcs: [
+ "bar-doc/a.java",
+ ],
+ api_levels_annotations_dirs: [
+ "droiddoc-templates-sdk",
+ ],
+ api_levels_annotations_enabled: true,
+ api_levels_jar_filename: "android.other.jar",
+ }
+ `,
+ map[string][]byte{
+ "bar-doc/a.java": nil,
+ })
+ testcases := []struct {
+ moduleName string
+ expectedJarFilename string
+ }{
+ {
+ moduleName: "bar-stubs",
+ expectedJarFilename: "android.jar",
+ },
+ {
+ moduleName: "bar-stubs-other",
+ expectedJarFilename: "android.other.jar",
+ },
+ }
+ for _, c := range testcases {
+ m := ctx.ModuleForTests(c.moduleName, "android_common")
+ metalava := m.Rule("metalava")
+ expected := "--android-jar-pattern ./%/public/" + c.expectedJarFilename
+ if actual := metalava.RuleParams.Command; !strings.Contains(actual, expected) {
+ t.Errorf("For %q, expected metalava argument %q, but was not found %q", c.moduleName, expected, actual)
+ }
+ }
+}
+
func TestDroidstubsWithSystemModules(t *testing.T) {
ctx, _ := testJava(t, `
droidstubs {
@@ -1430,8 +1495,7 @@ func TestJavaSdkLibrary(t *testing.T) {
// test if baz has exported SDK lib names foo and bar to qux
qux := ctx.ModuleForTests("qux", "android_common")
if quxLib, ok := qux.Module().(*Library); ok {
- sdkLibs := quxLib.ExportedSdkLibs()
- sort.Strings(sdkLibs)
+ sdkLibs := android.SortedStringKeys(quxLib.ExportedSdkLibs())
if w := []string{"bar", "foo", "fred", "quuz"}; !reflect.DeepEqual(w, sdkLibs) {
t.Errorf("qux should export %q but exports %q", w, sdkLibs)
}
@@ -2008,3 +2072,28 @@ func TestAidlExportIncludeDirsFromImports(t *testing.T) {
t.Errorf("aidl command %q does not contain %q", aidlCommand, expectedAidlFlag)
}
}
+
+func TestDataNativeBinaries(t *testing.T) {
+ ctx, config := testJava(t, `
+ java_test_host {
+ name: "foo",
+ srcs: ["a.java"],
+ data_native_bins: ["bin"]
+ }
+
+ python_binary_host {
+ name: "bin",
+ srcs: ["bin.py"],
+ }
+ `)
+
+ buildOS := android.BuildOs.String()
+
+ test := ctx.ModuleForTests("foo", buildOS+"_common").Module().(*TestHost)
+ entries := android.AndroidMkEntriesForTest(t, config, "", test)[0]
+ expected := []string{buildDir + "/.intermediates/bin/" + buildOS + "_x86_64_PY3/bin:bin"}
+ actual := entries.EntryMap["LOCAL_COMPATIBILITY_SUPPORT_FILES"]
+ if !reflect.DeepEqual(expected, actual) {
+ t.Errorf("Unexpected test data - expected: %q, actual: %q", expected, actual)
+ }
+}
diff --git a/java/legacy_core_platform_api_usage.go b/java/legacy_core_platform_api_usage.go
new file mode 100644
index 000000000..021920af6
--- /dev/null
+++ b/java/legacy_core_platform_api_usage.go
@@ -0,0 +1,174 @@
+// Copyright 2020 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package java
+
+import (
+ "android/soong/android"
+ "android/soong/java/config"
+)
+
+// This variable is effectively unused in pre-master branches, and is
+// included (with the same value as it has in AOSP) only to ease
+// merges between branches (see the comment in the
+// useLegacyCorePlatformApi() function):
+var legacyCorePlatformApiModules = []string{
+ "ahat-test-dump",
+ "android.car",
+ "android.test.mock",
+ "android.test.mock.impl",
+ "AoapTestDeviceApp",
+ "AoapTestHostApp",
+ "api-stubs-docs",
+ "art_cts_jvmti_test_library",
+ "art-gtest-jars-MyClassNatives",
+ "BackupFrameworksServicesRoboTests",
+ "BandwidthEnforcementTest",
+ "BlockedNumberProvider",
+ "BluetoothInstrumentationTests",
+ "BluetoothMidiService",
+ "car-apps-common",
+ "CertInstaller",
+ "ConnectivityManagerTest",
+ "ContactsProvider",
+ "core-tests-support",
+ "CtsContentTestCases",
+ "CtsIkeTestCases",
+ "CtsLibcoreWycheproofBCTestCases",
+ "CtsMediaTestCases",
+ "CtsNetTestCases",
+ "CtsNetTestCasesLatestSdk",
+ "CtsSecurityTestCases",
+ "CtsUsageStatsTestCases",
+ "DisplayCutoutEmulationEmu01Overlay",
+ "DocumentsUIPerfTests",
+ "DocumentsUITests",
+ "DownloadProvider",
+ "DownloadProviderTests",
+ "DownloadProviderUi",
+ "DynamicSystemInstallationService",
+ "EmergencyInfo-lib",
+ "ethernet-service",
+ "EthernetServiceTests",
+ "ExternalStorageProvider",
+ "ExtServices",
+ "ExtServices-core",
+ "framework-all",
+ "framework-minus-apex",
+ "FrameworksCoreTests",
+ "FrameworksIkeTests",
+ "FrameworksNetCommonTests",
+ "FrameworksNetTests",
+ "FrameworksServicesRoboTests",
+ "FrameworksServicesTests",
+ "FrameworksUtilTests",
+ "hid",
+ "hidl_test_java_java",
+ "hwbinder",
+ "ims",
+ "KeyChain",
+ "ksoap2",
+ "LocalTransport",
+ "lockagent",
+ "mediaframeworktest",
+ "MediaProvider",
+ "MmsService",
+ "MtpDocumentsProvider",
+ "MultiDisplayProvider",
+ "NetworkStackIntegrationTestsLib",
+ "NetworkStackNextIntegrationTests",
+ "NetworkStackNextTests",
+ "NetworkStackTests",
+ "NetworkStackTestsLib",
+ "NfcNci",
+ "platform_library-docs",
+ "PrintSpooler",
+ "RollbackTest",
+ "services",
+ "services.accessibility",
+ "services.backup",
+ "services.core.unboosted",
+ "services.devicepolicy",
+ "services.print",
+ "services.usage",
+ "services.usb",
+ "Settings-core",
+ "SettingsLib",
+ "SettingsProvider",
+ "SettingsProviderTest",
+ "SettingsRoboTests",
+ "Shell",
+ "ShellTests",
+ "sl4a.Common",
+ "StatementService",
+ "SystemUI-core",
+ "SystemUISharedLib",
+ "SystemUI-tests",
+ "Telecom",
+ "TelecomUnitTests",
+ "telephony-common",
+ "TelephonyProvider",
+ "TelephonyProviderTests",
+ "TeleService",
+ "testables",
+ "TetheringTests",
+ "TetheringTestsLib",
+ "time_zone_distro_installer",
+ "time_zone_distro_installer-tests",
+ "time_zone_distro-tests",
+ "time_zone_updater",
+ "TvProvider",
+ "uiautomator-stubs-docs",
+ "UsbHostExternalManagementTestApp",
+ "UserDictionaryProvider",
+ "WallpaperBackup",
+ "wifi-service",
+}
+
+// This variable is effectively unused in pre-master branches, and is
+// included (with the same value as it has in AOSP) only to ease
+// merges between branches (see the comment in the
+// useLegacyCorePlatformApi() function):
+var legacyCorePlatformApiLookup = make(map[string]struct{})
+
+func init() {
+ for _, module := range legacyCorePlatformApiModules {
+ legacyCorePlatformApiLookup[module] = struct{}{}
+ }
+}
+
+func useLegacyCorePlatformApi(ctx android.EarlyModuleContext) bool {
+ // In pre-master branches, we don't attempt to force usage of the stable
+ // version of the core/platform API. Instead, we always use the legacy
+ // version --- except in tests, where we always use stable, so that we
+ // can make the test assertions the same as other branches.
+ // This should be false in tests and true otherwise:
+ return ctx.Config().TestProductVariables == nil
+}
+
+func corePlatformSystemModules(ctx android.EarlyModuleContext) string {
+ if useLegacyCorePlatformApi(ctx) {
+ return config.LegacyCorePlatformSystemModules
+ } else {
+ return config.StableCorePlatformSystemModules
+ }
+}
+
+func corePlatformBootclasspathLibraries(ctx android.EarlyModuleContext) []string {
+ if useLegacyCorePlatformApi(ctx) {
+ return config.LegacyCorePlatformBootclasspathLibraries
+ } else {
+ return config.StableCorePlatformBootclasspathLibraries
+ }
+}
diff --git a/java/lint.go b/java/lint.go
index 20a7dc49f..3a210cc0b 100644
--- a/java/lint.go
+++ b/java/lint.go
@@ -17,6 +17,7 @@ package java
import (
"fmt"
"sort"
+ "strings"
"android/soong/android"
)
@@ -68,28 +69,78 @@ type linter struct {
outputs lintOutputs
properties LintProperties
+ reports android.Paths
+
buildModuleReportZip bool
}
type lintOutputs struct {
- html android.ModuleOutPath
- text android.ModuleOutPath
- xml android.ModuleOutPath
-
- transitiveHTML *android.DepSet
- transitiveText *android.DepSet
- transitiveXML *android.DepSet
+ html android.Path
+ text android.Path
+ xml android.Path
- transitiveHTMLZip android.OptionalPath
- transitiveTextZip android.OptionalPath
- transitiveXMLZip android.OptionalPath
+ depSets LintDepSets
}
-type lintOutputIntf interface {
+type lintOutputsIntf interface {
lintOutputs() *lintOutputs
}
-var _ lintOutputIntf = (*linter)(nil)
+type lintDepSetsIntf interface {
+ LintDepSets() LintDepSets
+}
+
+type LintDepSets struct {
+ HTML, Text, XML *android.DepSet
+}
+
+type LintDepSetsBuilder struct {
+ HTML, Text, XML *android.DepSetBuilder
+}
+
+func NewLintDepSetBuilder() LintDepSetsBuilder {
+ return LintDepSetsBuilder{
+ HTML: android.NewDepSetBuilder(android.POSTORDER),
+ Text: android.NewDepSetBuilder(android.POSTORDER),
+ XML: android.NewDepSetBuilder(android.POSTORDER),
+ }
+}
+
+func (l LintDepSetsBuilder) Direct(html, text, xml android.Path) LintDepSetsBuilder {
+ l.HTML.Direct(html)
+ l.Text.Direct(text)
+ l.XML.Direct(xml)
+ return l
+}
+
+func (l LintDepSetsBuilder) Transitive(depSets LintDepSets) LintDepSetsBuilder {
+ if depSets.HTML != nil {
+ l.HTML.Transitive(depSets.HTML)
+ }
+ if depSets.Text != nil {
+ l.Text.Transitive(depSets.Text)
+ }
+ if depSets.XML != nil {
+ l.XML.Transitive(depSets.XML)
+ }
+ return l
+}
+
+func (l LintDepSetsBuilder) Build() LintDepSets {
+ return LintDepSets{
+ HTML: l.HTML.Build(),
+ Text: l.Text.Build(),
+ XML: l.XML.Build(),
+ }
+}
+
+func (l *linter) LintDepSets() LintDepSets {
+ return l.outputs.depSets
+}
+
+var _ lintDepSetsIntf = (*linter)(nil)
+
+var _ lintOutputsIntf = (*linter)(nil)
func (l *linter) lintOutputs() *lintOutputs {
return &l.outputs
@@ -104,7 +155,16 @@ func (l *linter) deps(ctx android.BottomUpMutatorContext) {
return
}
- ctx.AddFarVariationDependencies(ctx.Config().BuildOSCommonTarget.Variations(), extraLintCheckTag, l.properties.Lint.Extra_check_modules...)
+ extraCheckModules := l.properties.Lint.Extra_check_modules
+
+ if checkOnly := ctx.Config().Getenv("ANDROID_LINT_CHECK"); checkOnly != "" {
+ if checkOnlyModules := ctx.Config().Getenv("ANDROID_LINT_CHECK_EXTRA_MODULES"); checkOnlyModules != "" {
+ extraCheckModules = strings.Split(checkOnlyModules, ",")
+ }
+ }
+
+ ctx.AddFarVariationDependencies(ctx.Config().BuildOSCommonTarget.Variations(),
+ extraLintCheckTag, extraCheckModules...)
}
func (l *linter) writeLintProjectXML(ctx android.ModuleContext,
@@ -192,7 +252,7 @@ func (l *linter) writeLintProjectXML(ctx android.ModuleContext,
return projectXMLPath, configXMLPath, cacheDir, homeDir, deps
}
-// generateManifest adds a command to the rule to write a dummy manifest cat contains the
+// generateManifest adds a command to the rule to write a simple manifest that contains the
// minSdkVersion and targetSdkVersion for modules (like java_library) that don't have a manifest.
func (l *linter) generateManifest(ctx android.ModuleContext, rule *android.RuleBuilder) android.Path {
manifestPath := android.PathForModuleOut(ctx, "lint", "AndroidManifest.xml")
@@ -237,16 +297,11 @@ func (l *linter) lint(ctx android.ModuleContext) {
text := android.PathForModuleOut(ctx, "lint-report.txt")
xml := android.PathForModuleOut(ctx, "lint-report.xml")
- htmlDeps := android.NewDepSetBuilder(android.POSTORDER).Direct(html)
- textDeps := android.NewDepSetBuilder(android.POSTORDER).Direct(text)
- xmlDeps := android.NewDepSetBuilder(android.POSTORDER).Direct(xml)
+ depSetsBuilder := NewLintDepSetBuilder().Direct(html, text, xml)
ctx.VisitDirectDepsWithTag(staticLibTag, func(dep android.Module) {
- if depLint, ok := dep.(lintOutputIntf); ok {
- depLintOutputs := depLint.lintOutputs()
- htmlDeps.Transitive(depLintOutputs.transitiveHTML)
- textDeps.Transitive(depLintOutputs.transitiveText)
- xmlDeps.Transitive(depLintOutputs.transitiveXML)
+ if depLint, ok := dep.(lintDepSetsIntf); ok {
+ depSetsBuilder.Transitive(depLint.LintDepSets())
}
})
@@ -254,7 +309,7 @@ func (l *linter) lint(ctx android.ModuleContext) {
rule.Command().Text("mkdir -p").Flag(cacheDir.String()).Flag(homeDir.String())
var annotationsZipPath, apiVersionsXMLPath android.Path
- if ctx.Config().UnbundledBuildUsePrebuiltSdks() {
+ if ctx.Config().AlwaysUsePrebuiltSdks() {
annotationsZipPath = android.PathForSource(ctx, "prebuilts/sdk/current/public/data/annotations.zip")
apiVersionsXMLPath = android.PathForSource(ctx, "prebuilts/sdk/current/public/data/api-versions.xml")
} else {
@@ -262,9 +317,9 @@ func (l *linter) lint(ctx android.ModuleContext) {
apiVersionsXMLPath = copiedAPIVersionsXmlPath(ctx)
}
- rule.Command().
+ cmd := rule.Command().
Text("(").
- Flag("JAVA_OPTS=-Xmx2048m").
+ Flag("JAVA_OPTS=-Xmx3072m").
FlagWithArg("ANDROID_SDK_HOME=", homeDir.String()).
FlagWithInput("SDK_ANNOTATIONS=", annotationsZipPath).
FlagWithInput("LINT_OPTS=-DLINT_API_DATABASE=", apiVersionsXMLPath).
@@ -282,9 +337,13 @@ func (l *linter) lint(ctx android.ModuleContext) {
FlagWithArg("--url ", fmt.Sprintf(".=.,%s=out", android.PathForOutput(ctx).String())).
Flag("--exitcode").
Flags(l.properties.Lint.Flags).
- Implicits(deps).
- Text("|| (").Text("cat").Input(text).Text("; exit 7)").
- Text(")")
+ Implicits(deps)
+
+ if checkOnly := ctx.Config().Getenv("ANDROID_LINT_CHECK"); checkOnly != "" {
+ cmd.FlagWithArg("--check ", checkOnly)
+ }
+
+ cmd.Text("|| (").Text("cat").Input(text).Text("; exit 7)").Text(")")
rule.Command().Text("rm -rf").Flag(cacheDir.String()).Flag(homeDir.String())
@@ -295,24 +354,33 @@ func (l *linter) lint(ctx android.ModuleContext) {
text: text,
xml: xml,
- transitiveHTML: htmlDeps.Build(),
- transitiveText: textDeps.Build(),
- transitiveXML: xmlDeps.Build(),
+ depSets: depSetsBuilder.Build(),
}
if l.buildModuleReportZip {
- htmlZip := android.PathForModuleOut(ctx, "lint-report-html.zip")
- l.outputs.transitiveHTMLZip = android.OptionalPathForPath(htmlZip)
- lintZip(ctx, l.outputs.transitiveHTML.ToSortedList(), htmlZip)
+ l.reports = BuildModuleLintReportZips(ctx, l.LintDepSets())
+ }
+}
- textZip := android.PathForModuleOut(ctx, "lint-report-text.zip")
- l.outputs.transitiveTextZip = android.OptionalPathForPath(textZip)
- lintZip(ctx, l.outputs.transitiveText.ToSortedList(), textZip)
+func BuildModuleLintReportZips(ctx android.ModuleContext, depSets LintDepSets) android.Paths {
+ htmlList := depSets.HTML.ToSortedList()
+ textList := depSets.Text.ToSortedList()
+ xmlList := depSets.XML.ToSortedList()
- xmlZip := android.PathForModuleOut(ctx, "lint-report-xml.zip")
- l.outputs.transitiveXMLZip = android.OptionalPathForPath(xmlZip)
- lintZip(ctx, l.outputs.transitiveXML.ToSortedList(), xmlZip)
+ if len(htmlList) == 0 && len(textList) == 0 && len(xmlList) == 0 {
+ return nil
}
+
+ htmlZip := android.PathForModuleOut(ctx, "lint-report-html.zip")
+ lintZip(ctx, htmlList, htmlZip)
+
+ textZip := android.PathForModuleOut(ctx, "lint-report-text.zip")
+ lintZip(ctx, textList, textZip)
+
+ xmlZip := android.PathForModuleOut(ctx, "lint-report-xml.zip")
+ lintZip(ctx, xmlList, xmlZip)
+
+ return android.Paths{htmlZip, textZip, xmlZip}
}
type lintSingleton struct {
@@ -327,7 +395,7 @@ func (l *lintSingleton) GenerateBuildActions(ctx android.SingletonContext) {
}
func (l *lintSingleton) copyLintDependencies(ctx android.SingletonContext) {
- if ctx.Config().UnbundledBuildUsePrebuiltSdks() {
+ if ctx.Config().AlwaysUsePrebuiltSdks() {
return
}
@@ -389,7 +457,7 @@ func (l *lintSingleton) generateLintReportZips(ctx android.SingletonContext) {
return
}
- if l, ok := m.(lintOutputIntf); ok {
+ if l, ok := m.(lintOutputsIntf); ok {
outputs = append(outputs, l.lintOutputs())
}
})
@@ -400,7 +468,9 @@ func (l *lintSingleton) generateLintReportZips(ctx android.SingletonContext) {
var paths android.Paths
for _, output := range outputs {
- paths = append(paths, get(output))
+ if p := get(output); p != nil {
+ paths = append(paths, p)
+ }
}
lintZip(ctx, paths, outputPath)
@@ -443,7 +513,7 @@ func lintZip(ctx android.BuilderContext, paths android.Paths, outputPath android
rule.Command().BuiltTool(ctx, "soong_zip").
FlagWithOutput("-o ", outputPath).
FlagWithArg("-C ", android.PathForIntermediates(ctx).String()).
- FlagWithRspFileInputList("-l ", paths)
+ FlagWithRspFileInputList("-r ", paths)
rule.Build(pctx, ctx, outputPath.Base(), outputPath.Base())
}
diff --git a/java/prebuilt_apis.go b/java/prebuilt_apis.go
index b10e6c7fe..ac8337dc5 100644
--- a/java/prebuilt_apis.go
+++ b/java/prebuilt_apis.go
@@ -34,6 +34,10 @@ func RegisterPrebuiltApisBuildComponents(ctx android.RegistrationContext) {
type prebuiltApisProperties struct {
// list of api version directories
Api_dirs []string
+
+ // The sdk_version of java_import modules generated based on jar files.
+ // Defaults to "current"
+ Imports_sdk_version *string
}
type prebuiltApis struct {
@@ -74,7 +78,7 @@ func prebuiltApiModuleName(mctx android.LoadHookContext, module string, scope st
return mctx.ModuleName() + "_" + scope + "_" + apiver + "_" + module
}
-func createImport(mctx android.LoadHookContext, module string, scope string, apiver string, path string) {
+func createImport(mctx android.LoadHookContext, module, scope, apiver, path, sdk_version string) {
props := struct {
Name *string
Jars []string
@@ -83,7 +87,7 @@ func createImport(mctx android.LoadHookContext, module string, scope string, api
}{}
props.Name = proptools.StringPtr(prebuiltApiModuleName(mctx, module, scope, apiver))
props.Jars = append(props.Jars, path)
- props.Sdk_version = proptools.StringPtr(scope)
+ props.Sdk_version = proptools.StringPtr(sdk_version)
props.Installable = proptools.BoolPtr(false)
mctx.CreateModule(ImportFactory, &props)
@@ -100,10 +104,10 @@ func createFilegroup(mctx android.LoadHookContext, module string, scope string,
mctx.CreateModule(android.FileGroupFactory, &filegroupProps)
}
-func getPrebuiltFiles(mctx android.LoadHookContext, name string) []string {
+func getPrebuiltFiles(mctx android.LoadHookContext, p *prebuiltApis, name string) []string {
mydir := mctx.ModuleDir() + "/"
var files []string
- for _, apiver := range mctx.Module().(*prebuiltApis).properties.Api_dirs {
+ for _, apiver := range p.properties.Api_dirs {
for _, scope := range []string{"public", "system", "test", "core", "module-lib", "system-server"} {
vfiles, err := mctx.GlobWithDeps(mydir+apiver+"/"+scope+"/"+name, nil)
if err != nil {
@@ -115,16 +119,18 @@ func getPrebuiltFiles(mctx android.LoadHookContext, name string) []string {
return files
}
-func prebuiltSdkStubs(mctx android.LoadHookContext) {
+func prebuiltSdkStubs(mctx android.LoadHookContext, p *prebuiltApis) {
mydir := mctx.ModuleDir() + "/"
// <apiver>/<scope>/<module>.jar
- files := getPrebuiltFiles(mctx, "*.jar")
+ files := getPrebuiltFiles(mctx, p, "*.jar")
+
+ sdk_version := proptools.StringDefault(p.properties.Imports_sdk_version, "current")
for _, f := range files {
// create a Import module for each jar file
localPath := strings.TrimPrefix(f, mydir)
module, apiver, scope := parseJarPath(localPath)
- createImport(mctx, module, scope, apiver, localPath)
+ createImport(mctx, module, scope, apiver, localPath, sdk_version)
}
}
@@ -139,8 +145,8 @@ func createSystemModules(mctx android.LoadHookContext, apiver string) {
mctx.CreateModule(SystemModulesFactory, &props)
}
-func prebuiltSdkSystemModules(mctx android.LoadHookContext) {
- for _, apiver := range mctx.Module().(*prebuiltApis).properties.Api_dirs {
+func prebuiltSdkSystemModules(mctx android.LoadHookContext, p *prebuiltApis) {
+ for _, apiver := range p.properties.Api_dirs {
jar := android.ExistentPathForSource(mctx,
mctx.ModuleDir(), apiver, "public", "core-for-system-modules.jar")
if jar.Valid() {
@@ -149,10 +155,10 @@ func prebuiltSdkSystemModules(mctx android.LoadHookContext) {
}
}
-func prebuiltApiFiles(mctx android.LoadHookContext) {
+func prebuiltApiFiles(mctx android.LoadHookContext, p *prebuiltApis) {
mydir := mctx.ModuleDir() + "/"
// <apiver>/<scope>/api/<module>.txt
- files := getPrebuiltFiles(mctx, "api/*.txt")
+ files := getPrebuiltFiles(mctx, p, "api/*.txt")
if len(files) == 0 {
mctx.ModuleErrorf("no api file found under %q", mydir)
@@ -200,10 +206,10 @@ func prebuiltApiFiles(mctx android.LoadHookContext) {
}
func createPrebuiltApiModules(mctx android.LoadHookContext) {
- if _, ok := mctx.Module().(*prebuiltApis); ok {
- prebuiltApiFiles(mctx)
- prebuiltSdkStubs(mctx)
- prebuiltSdkSystemModules(mctx)
+ if p, ok := mctx.Module().(*prebuiltApis); ok {
+ prebuiltApiFiles(mctx, p)
+ prebuiltSdkStubs(mctx, p)
+ prebuiltSdkSystemModules(mctx, p)
}
}
diff --git a/java/robolectric.go b/java/robolectric.go
index c6b07a17e..3fe6626bb 100644
--- a/java/robolectric.go
+++ b/java/robolectric.go
@@ -21,10 +21,13 @@ import (
"strings"
"android/soong/android"
+ "android/soong/java/config"
+ "android/soong/tradefed"
)
func init() {
android.RegisterModuleType("android_robolectric_test", RobolectricTestFactory)
+ android.RegisterModuleType("android_robolectric_runtimes", robolectricRuntimesFactory)
}
var robolectricDefaultLibs = []string{
@@ -32,10 +35,13 @@ var robolectricDefaultLibs = []string{
"Robolectric_all-target",
"mockito-robolectric-prebuilt",
"truth-prebuilt",
+ // TODO(ccross): this is not needed at link time
+ "junitxml",
}
var (
- roboCoverageLibsTag = dependencyTag{name: "roboSrcs"}
+ roboCoverageLibsTag = dependencyTag{name: "roboCoverageLibs"}
+ roboRuntimesTag = dependencyTag{name: "roboRuntimes"}
)
type robolectricProperties struct {
@@ -58,13 +64,28 @@ type robolectricTest struct {
Library
robolectricProperties robolectricProperties
+ testProperties testProperties
libs []string
tests []string
+ manifest android.Path
+ resourceApk android.Path
+
+ combinedJar android.WritablePath
+
roboSrcJar android.Path
+
+ testConfig android.Path
+ data android.Paths
+}
+
+func (r *robolectricTest) TestSuites() []string {
+ return r.testProperties.Test_suites
}
+var _ android.TestSuiteModule = (*robolectricTest)(nil)
+
func (r *robolectricTest) DepsMutator(ctx android.BottomUpMutatorContext) {
r.Library.DepsMutator(ctx)
@@ -77,9 +98,16 @@ func (r *robolectricTest) DepsMutator(ctx android.BottomUpMutatorContext) {
ctx.AddVariationDependencies(nil, libTag, robolectricDefaultLibs...)
ctx.AddVariationDependencies(nil, roboCoverageLibsTag, r.robolectricProperties.Coverage_libs...)
+
+ ctx.AddVariationDependencies(nil, roboRuntimesTag, "robolectric-android-all-prebuilts")
}
func (r *robolectricTest) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ r.testConfig = tradefed.AutoGenRobolectricTestConfig(ctx, r.testProperties.Test_config,
+ r.testProperties.Test_config_template, r.testProperties.Test_suites,
+ r.testProperties.Auto_gen_config)
+ r.data = android.PathsForModuleSrc(ctx, r.testProperties.Data)
+
roboTestConfig := android.PathForModuleGen(ctx, "robolectric").
Join(ctx, "com/android/tools/test_config.properties")
@@ -95,6 +123,9 @@ func (r *robolectricTest) GenerateAndroidBuildActions(ctx android.ModuleContext)
ctx.PropertyErrorf("instrumentation_for", "dependency must be an android_app")
}
+ r.manifest = instrumentedApp.mergedManifestFile
+ r.resourceApk = instrumentedApp.outputFile
+
generateRoboTestConfig(ctx, roboTestConfig, instrumentedApp)
r.extraResources = android.Paths{roboTestConfig}
@@ -104,10 +135,30 @@ func (r *robolectricTest) GenerateAndroidBuildActions(ctx android.ModuleContext)
r.generateRoboSrcJar(ctx, roboSrcJar, instrumentedApp)
r.roboSrcJar = roboSrcJar
+ roboTestConfigJar := android.PathForModuleOut(ctx, "robolectric_samedir", "samedir_config.jar")
+ generateSameDirRoboTestConfigJar(ctx, roboTestConfigJar)
+
+ combinedJarJars := android.Paths{
+ // roboTestConfigJar comes first so that its com/android/tools/test_config.properties
+ // overrides the one from r.extraResources. The r.extraResources one can be removed
+ // once the Make test runner is removed.
+ roboTestConfigJar,
+ r.outputFile,
+ instrumentedApp.implementationAndResourcesJar,
+ }
+
for _, dep := range ctx.GetDirectDepsWithTag(libTag) {
- r.libs = append(r.libs, dep.(Dependency).BaseModuleName())
+ m := dep.(Dependency)
+ r.libs = append(r.libs, m.BaseModuleName())
+ if !android.InList(m.BaseModuleName(), config.FrameworkLibraries) {
+ combinedJarJars = append(combinedJarJars, m.ImplementationAndResourcesJars()...)
+ }
}
+ r.combinedJar = android.PathForModuleOut(ctx, "robolectric_combined", r.outputFile.Base())
+ TransformJarsToJar(ctx, r.combinedJar, "combine jars", combinedJarJars, android.OptionalPath{},
+ false, nil, nil)
+
// TODO: this could all be removed if tradefed was used as the test runner, it will find everything
// annotated as a test and run it.
for _, src := range r.compiledJavaSrcs {
@@ -121,14 +172,38 @@ func (r *robolectricTest) GenerateAndroidBuildActions(ctx android.ModuleContext)
}
r.tests = append(r.tests, s)
}
+
+ r.data = append(r.data, r.manifest, r.resourceApk)
+
+ runtimes := ctx.GetDirectDepWithTag("robolectric-android-all-prebuilts", roboRuntimesTag)
+
+ installPath := android.PathForModuleInstall(ctx, r.BaseModuleName())
+
+ installedResourceApk := ctx.InstallFile(installPath, ctx.ModuleName()+".apk", r.resourceApk)
+ installedManifest := ctx.InstallFile(installPath, ctx.ModuleName()+"-AndroidManifest.xml", r.manifest)
+ installedConfig := ctx.InstallFile(installPath, ctx.ModuleName()+".config", r.testConfig)
+
+ var installDeps android.Paths
+ for _, runtime := range runtimes.(*robolectricRuntimes).runtimes {
+ installDeps = append(installDeps, runtime)
+ }
+ installDeps = append(installDeps, installedResourceApk, installedManifest, installedConfig)
+
+ for _, data := range android.PathsForModuleSrc(ctx, r.testProperties.Data) {
+ installedData := ctx.InstallFile(installPath, data.Rel(), data)
+ installDeps = append(installDeps, installedData)
+ }
+
+ ctx.InstallFile(installPath, ctx.ModuleName()+".jar", r.combinedJar, installDeps...)
}
-func generateRoboTestConfig(ctx android.ModuleContext, outputFile android.WritablePath, instrumentedApp *AndroidApp) {
+func generateRoboTestConfig(ctx android.ModuleContext, outputFile android.WritablePath,
+ instrumentedApp *AndroidApp) {
+ rule := android.NewRuleBuilder()
+
manifest := instrumentedApp.mergedManifestFile
resourceApk := instrumentedApp.outputFile
- rule := android.NewRuleBuilder()
-
rule.Command().Text("rm -f").Output(outputFile)
rule.Command().
Textf(`echo "android_merged_manifest=%s" >>`, manifest.String()).Output(outputFile).Text("&&").
@@ -141,6 +216,28 @@ func generateRoboTestConfig(ctx android.ModuleContext, outputFile android.Writab
rule.Build(pctx, ctx, "generate_test_config", "generate test_config.properties")
}
+func generateSameDirRoboTestConfigJar(ctx android.ModuleContext, outputFile android.ModuleOutPath) {
+ rule := android.NewRuleBuilder()
+
+ outputDir := outputFile.InSameDir(ctx)
+ configFile := outputDir.Join(ctx, "com/android/tools/test_config.properties")
+ rule.Temporary(configFile)
+ rule.Command().Text("rm -f").Output(outputFile).Output(configFile)
+ rule.Command().Textf("mkdir -p $(dirname %s)", configFile.String())
+ rule.Command().
+ Text("(").
+ Textf(`echo "android_merged_manifest=%s-AndroidManifest.xml" &&`, ctx.ModuleName()).
+ Textf(`echo "android_resource_apk=%s.apk"`, ctx.ModuleName()).
+ Text(") >>").Output(configFile)
+ rule.Command().
+ BuiltTool(ctx, "soong_zip").
+ FlagWithArg("-C ", outputDir.String()).
+ FlagWithInput("-f ", configFile).
+ FlagWithOutput("-o ", outputFile)
+
+ rule.Build(pctx, ctx, "generate_test_config_samedir", "generate test_config.properties")
+}
+
func (r *robolectricTest) generateRoboSrcJar(ctx android.ModuleContext, outputFile android.WritablePath,
instrumentedApp *AndroidApp) {
@@ -202,7 +299,6 @@ func (r *robolectricTest) writeTestRunner(w io.Writer, module, name string, test
fmt.Fprintln(w, "LOCAL_ROBOTEST_TIMEOUT :=", *t)
}
fmt.Fprintln(w, "-include external/robolectric-shadows/run_robotests.mk")
-
}
// An android_robolectric_test module compiles tests against the Robolectric framework that can run on the local host
@@ -218,11 +314,82 @@ func RobolectricTestFactory() android.Module {
module.addHostProperties()
module.AddProperties(
&module.Module.deviceProperties,
- &module.robolectricProperties)
+ &module.robolectricProperties,
+ &module.testProperties)
module.Module.dexpreopter.isTest = true
module.Module.linter.test = true
+ module.testProperties.Test_suites = []string{"robolectric-tests"}
+
InitJavaModule(module, android.DeviceSupported)
return module
}
+
+func (r *robolectricTest) InstallBypassMake() bool { return true }
+func (r *robolectricTest) InstallInTestcases() bool { return true }
+func (r *robolectricTest) InstallForceOS() *android.OsType { return &android.BuildOs }
+
+func robolectricRuntimesFactory() android.Module {
+ module := &robolectricRuntimes{}
+ module.AddProperties(&module.props)
+ android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibCommon)
+ return module
+}
+
+type robolectricRuntimesProperties struct {
+ Jars []string `android:"path"`
+ Lib *string
+}
+
+type robolectricRuntimes struct {
+ android.ModuleBase
+
+ props robolectricRuntimesProperties
+
+ runtimes []android.InstallPath
+}
+
+func (r *robolectricRuntimes) TestSuites() []string {
+ return []string{"robolectric-tests"}
+}
+
+var _ android.TestSuiteModule = (*robolectricRuntimes)(nil)
+
+func (r *robolectricRuntimes) DepsMutator(ctx android.BottomUpMutatorContext) {
+ if !ctx.Config().AlwaysUsePrebuiltSdks() && r.props.Lib != nil {
+ ctx.AddVariationDependencies(nil, libTag, String(r.props.Lib))
+ }
+}
+
+func (r *robolectricRuntimes) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ files := android.PathsForModuleSrc(ctx, r.props.Jars)
+
+ androidAllDir := android.PathForModuleInstall(ctx, "android-all")
+ for _, from := range files {
+ installedRuntime := ctx.InstallFile(androidAllDir, from.Base(), from)
+ r.runtimes = append(r.runtimes, installedRuntime)
+ }
+
+ if !ctx.Config().AlwaysUsePrebuiltSdks() && r.props.Lib != nil {
+ runtimeFromSourceModule := ctx.GetDirectDepWithTag(String(r.props.Lib), libTag)
+ if runtimeFromSourceModule == nil {
+ if ctx.Config().AllowMissingDependencies() {
+ ctx.AddMissingDependencies([]string{String(r.props.Lib)})
+ } else {
+ ctx.PropertyErrorf("lib", "missing dependency %q", String(r.props.Lib))
+ }
+ return
+ }
+ runtimeFromSourceJar := android.OutputFileForModule(ctx, runtimeFromSourceModule, "")
+
+ runtimeName := fmt.Sprintf("android-all-%s-robolectric-r0.jar",
+ ctx.Config().PlatformSdkCodename())
+ installedRuntime := ctx.InstallFile(androidAllDir, runtimeName, runtimeFromSourceJar)
+ r.runtimes = append(r.runtimes, installedRuntime)
+ }
+}
+
+func (r *robolectricRuntimes) InstallBypassMake() bool { return true }
+func (r *robolectricRuntimes) InstallInTestcases() bool { return true }
+func (r *robolectricRuntimes) InstallForceOS() *android.OsType { return &android.BuildOs }
diff --git a/java/sdk.go b/java/sdk.go
index 6564f6d28..56fa12b3e 100644
--- a/java/sdk.go
+++ b/java/sdk.go
@@ -53,7 +53,7 @@ type sdkContext interface {
func UseApiFingerprint(ctx android.BaseModuleContext) bool {
if ctx.Config().UnbundledBuild() &&
- !ctx.Config().UnbundledBuildUsePrebuiltSdks() &&
+ !ctx.Config().AlwaysUsePrebuiltSdks() &&
ctx.Config().IsEnvTrue("UNBUNDLED_BUILD_TARGET_SDK_WITH_API_FINGERPRINT") {
return true
}
@@ -191,19 +191,22 @@ func (s sdkSpec) prebuiltSdkAvailableForUnbundledBuild() bool {
return s.kind != sdkPrivate && s.kind != sdkNone && s.kind != sdkCorePlatform
}
-// forPdkBuild converts this sdkSpec into another sdkSpec that is for the PDK builds.
-func (s sdkSpec) forPdkBuild(ctx android.EarlyModuleContext) sdkSpec {
- // For PDK builds, use the latest SDK version instead of "current" or ""
- if s.kind == sdkPrivate || s.kind == sdkPublic {
- kind := s.kind
- if kind == sdkPrivate {
- // We don't have prebuilt SDK for private APIs, so use the public SDK
- // instead. This looks odd, but that's how it has been done.
- // TODO(b/148271073): investigate the need for this.
- kind = sdkPublic
+func (s sdkSpec) forVendorPartition(ctx android.EarlyModuleContext) sdkSpec {
+ // If BOARD_CURRENT_API_LEVEL_FOR_VENDOR_MODULES has a numeric value,
+ // use it instead of "current" for the vendor partition.
+ currentSdkVersion := ctx.DeviceConfig().CurrentApiLevelForVendorModules()
+ if currentSdkVersion == "current" {
+ return s
+ }
+
+ if s.kind == sdkPublic || s.kind == sdkSystem {
+ if s.version.isCurrent() {
+ if i, err := strconv.Atoi(currentSdkVersion); err == nil {
+ version := sdkVersion(i)
+ return sdkSpec{s.kind, version, s.raw}
+ }
+ panic(fmt.Errorf("BOARD_CURRENT_API_LEVEL_FOR_VENDOR_MODULES must be either \"current\" or a number, but was %q", currentSdkVersion))
}
- version := sdkVersion(LatestSdkVersionInt(ctx))
- return sdkSpec{kind, version, s.raw}
}
return s
}
@@ -212,9 +215,9 @@ func (s sdkSpec) forPdkBuild(ctx android.EarlyModuleContext) sdkSpec {
func (s sdkSpec) usePrebuilt(ctx android.EarlyModuleContext) bool {
if s.version.isCurrent() {
// "current" can be built from source and be from prebuilt SDK
- return ctx.Config().UnbundledBuildUsePrebuiltSdks()
+ return ctx.Config().AlwaysUsePrebuiltSdks()
} else if s.version.isNumbered() {
- // sanity check
+ // validation check
if s.kind != sdkPublic && s.kind != sdkSystem && s.kind != sdkTest {
panic(fmt.Errorf("prebuilt SDK is not not available for sdkKind=%q", s.kind))
return false
@@ -233,8 +236,9 @@ func (s sdkSpec) effectiveVersion(ctx android.EarlyModuleContext) (sdkVersion, e
if !s.valid() {
return s.version, fmt.Errorf("invalid sdk version %q", s.raw)
}
- if ctx.Config().IsPdkBuild() {
- s = s.forPdkBuild(ctx)
+
+ if ctx.DeviceSpecific() || ctx.SocSpecific() {
+ s = s.forVendorPartition(ctx)
}
if s.version.isNumbered() {
return s.version, nil
@@ -350,9 +354,10 @@ func decodeSdkDep(ctx android.EarlyModuleContext, sdkContext sdkContext) sdkDep
return sdkDep{}
}
- if ctx.Config().IsPdkBuild() {
- sdkVersion = sdkVersion.forPdkBuild(ctx)
+ if ctx.DeviceSpecific() || ctx.SocSpecific() {
+ sdkVersion = sdkVersion.forVendorPartition(ctx)
}
+
if !sdkVersion.validateSystemSdk(ctx) {
return sdkDep{}
}
@@ -413,8 +418,8 @@ func decodeSdkDep(ctx android.EarlyModuleContext, sdkContext sdkContext) sdkDep
case sdkPrivate:
return sdkDep{
useModule: true,
- systemModules: config.LegacyCorePlatformSystemModules,
- bootclasspath: config.LegacyCorePlatformBootclasspathLibraries,
+ systemModules: corePlatformSystemModules(ctx),
+ bootclasspath: corePlatformBootclasspathLibraries(ctx),
classpath: config.FrameworkLibraries,
frameworkResModule: "framework-res",
}
@@ -438,8 +443,8 @@ func decodeSdkDep(ctx android.EarlyModuleContext, sdkContext sdkContext) sdkDep
case sdkCorePlatform:
return sdkDep{
useModule: true,
- systemModules: config.LegacyCorePlatformSystemModules,
- bootclasspath: config.LegacyCorePlatformBootclasspathLibraries,
+ systemModules: corePlatformSystemModules(ctx),
+ bootclasspath: corePlatformBootclasspathLibraries(ctx),
noFrameworksLibs: true,
}
case sdkPublic:
@@ -511,7 +516,7 @@ func sdkSingletonFactory() android.Singleton {
type sdkSingleton struct{}
func (sdkSingleton) GenerateBuildActions(ctx android.SingletonContext) {
- if ctx.Config().UnbundledBuildUsePrebuiltSdks() || ctx.Config().IsPdkBuild() {
+ if ctx.Config().AlwaysUsePrebuiltSdks() {
return
}
@@ -631,10 +636,7 @@ func createAPIFingerprint(ctx android.SingletonContext) {
if ctx.Config().PlatformSdkCodename() == "REL" {
cmd.Text("echo REL >").Output(out)
- } else if ctx.Config().IsPdkBuild() {
- // TODO: get this from the PDK artifacts?
- cmd.Text("echo PDK >").Output(out)
- } else if !ctx.Config().UnbundledBuildUsePrebuiltSdks() {
+ } else if !ctx.Config().AlwaysUsePrebuiltSdks() {
in, err := ctx.GlobWithDeps("frameworks/base/api/*current.txt", nil)
if err != nil {
ctx.Errorf("error globbing API files: %s", err)
@@ -663,7 +665,7 @@ func ApiFingerprintPath(ctx android.PathContext) android.OutputPath {
}
func sdkMakeVars(ctx android.MakeVarsContext) {
- if ctx.Config().UnbundledBuildUsePrebuiltSdks() || ctx.Config().IsPdkBuild() {
+ if ctx.Config().AlwaysUsePrebuiltSdks() {
return
}
diff --git a/java/sdk_library.go b/java/sdk_library.go
index 68713df82..30478a1fb 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -126,25 +126,23 @@ type apiScope struct {
// the prebuilt jar.
sdkVersion string
- // Extra arguments to pass to droidstubs for this scope.
- droidstubsArgs []string
+ // The annotation that identifies this API level, empty for the public API scope.
+ annotation string
- // The args that must be passed to droidstubs to generate the stubs source
- // for this scope.
+ // Extra arguments to pass to droidstubs for this scope.
//
- // The stubs source must include the definitions of everything that is in this
- // api scope and all the scopes that this one extends.
- droidstubsArgsForGeneratingStubsSource []string
+ // This is not used directly but is used to construct the droidstubsArgs.
+ extraArgs []string
- // The args that must be passed to droidstubs to generate the API for this scope.
+ // The args that must be passed to droidstubs to generate the API and stubs source
+ // for this scope, constructed dynamically by initApiScope().
//
// The API only includes the additional members that this scope adds over the scope
// that it extends.
- droidstubsArgsForGeneratingApi []string
-
- // True if the stubs source and api can be created by the same metalava invocation.
- // TODO(b/146727827) Now that metalava supports "API hierarchy", do we still need it?
- createStubsSourceAndApiTogether bool
+ //
+ // The stubs source must include the definitions of everything that is in this
+ // api scope and all the scopes that this one extends.
+ droidstubsArgs []string
// Whether the api scope can be treated as unstable, and should skip compat checks.
unstable bool
@@ -181,21 +179,23 @@ func initApiScope(scope *apiScope) *apiScope {
// To get the args needed to generate the stubs source append all the args from
// this scope and all the scopes it extends as each set of args adds additional
// members to the stubs.
- var stubsSourceArgs []string
- for s := scope; s != nil; s = s.extends {
- stubsSourceArgs = append(stubsSourceArgs, s.droidstubsArgs...)
+ var scopeSpecificArgs []string
+ if scope.annotation != "" {
+ scopeSpecificArgs = []string{"--show-annotation", scope.annotation}
}
- scope.droidstubsArgsForGeneratingStubsSource = stubsSourceArgs
+ for s := scope; s != nil; s = s.extends {
+ scopeSpecificArgs = append(scopeSpecificArgs, s.extraArgs...)
- // Currently the args needed to generate the API are the same as the args
- // needed to add additional members.
- apiArgs := scope.droidstubsArgs
- scope.droidstubsArgsForGeneratingApi = apiArgs
+ // Ensure that the generated stubs includes all the API elements from the API scope
+ // that this scope extends.
+ if s != scope && s.annotation != "" {
+ scopeSpecificArgs = append(scopeSpecificArgs, "--show-for-stub-purposes-annotation", s.annotation)
+ }
+ }
- // If the args needed to generate the stubs and API are the same then they
- // can be generated in a single invocation of metalava, otherwise they will
- // need separate invocations.
- scope.createStubsSourceAndApiTogether = reflect.DeepEqual(stubsSourceArgs, apiArgs)
+ // Escape any special characters in the arguments. This is needed because droidstubs
+ // passes these directly to the shell command.
+ scope.droidstubsArgs = proptools.ShellEscapeList(scopeSpecificArgs)
return scope
}
@@ -250,10 +250,10 @@ var (
scopeSpecificProperties: func(module *SdkLibrary) *ApiScopeProperties {
return &module.sdkLibraryProperties.System
},
- apiFilePrefix: "system-",
- moduleSuffix: ".system",
- sdkVersion: "system_current",
- droidstubsArgs: []string{"-showAnnotation android.annotation.SystemApi\\(client=android.annotation.SystemApi.Client.PRIVILEGED_APPS\\)"},
+ apiFilePrefix: "system-",
+ moduleSuffix: ".system",
+ sdkVersion: "system_current",
+ annotation: "android.annotation.SystemApi(client=android.annotation.SystemApi.Client.PRIVILEGED_APPS)",
})
apiScopeTest = initApiScope(&apiScope{
name: "test",
@@ -262,11 +262,11 @@ var (
scopeSpecificProperties: func(module *SdkLibrary) *ApiScopeProperties {
return &module.sdkLibraryProperties.Test
},
- apiFilePrefix: "test-",
- moduleSuffix: ".test",
- sdkVersion: "test_current",
- droidstubsArgs: []string{"-showAnnotation android.annotation.TestApi"},
- unstable: true,
+ apiFilePrefix: "test-",
+ moduleSuffix: ".test",
+ sdkVersion: "test_current",
+ annotation: "android.annotation.TestApi",
+ unstable: true,
})
apiScopeModuleLib = initApiScope(&apiScope{
name: "module-lib",
@@ -283,10 +283,7 @@ var (
apiFilePrefix: "module-lib-",
moduleSuffix: ".module_lib",
sdkVersion: "module_current",
- droidstubsArgs: []string{
- "--show-annotation android.annotation.SystemApi\\(client=android.annotation.SystemApi.Client.MODULE_LIBRARIES\\)",
- "--show-for-stub-purposes-annotation android.annotation.SystemApi\\(client=android.annotation.SystemApi.Client.PRIVILEGED_APPS\\)",
- },
+ annotation: "android.annotation.SystemApi(client=android.annotation.SystemApi.Client.MODULE_LIBRARIES)",
})
apiScopeSystemServer = initApiScope(&apiScope{
name: "system-server",
@@ -303,11 +300,11 @@ var (
apiFilePrefix: "system-server-",
moduleSuffix: ".system_server",
sdkVersion: "system_server_current",
- droidstubsArgs: []string{
- "--show-annotation android.annotation.SystemApi\\(client=android.annotation.SystemApi.Client.SYSTEM_SERVER\\) ",
- "--hide-annotation android.annotation.Hide",
+ annotation: "android.annotation.SystemApi(client=android.annotation.SystemApi.Client.SYSTEM_SERVER)",
+ extraArgs: []string{
+ "--hide-annotation", "android.annotation.Hide",
// com.android.* classes are okay in this interface"
- "--hide InternalClasses",
+ "--hide", "InternalClasses",
},
})
allApiScopes = apiScopes{
@@ -855,22 +852,20 @@ func (e *EmbeddableSdkLibraryComponent) initSdkLibraryComponent(moduleBase *andr
}
// to satisfy SdkLibraryComponentDependency
-func (e *EmbeddableSdkLibraryComponent) OptionalImplicitSdkLibrary() []string {
- if e.sdkLibraryComponentProperties.SdkLibraryToImplicitlyTrack != nil {
- return []string{*e.sdkLibraryComponentProperties.SdkLibraryToImplicitlyTrack}
- }
- return nil
+func (e *EmbeddableSdkLibraryComponent) OptionalImplicitSdkLibrary() *string {
+ return e.sdkLibraryComponentProperties.SdkLibraryToImplicitlyTrack
}
// Implemented by modules that are (or possibly could be) a component of a java_sdk_library
// (including the java_sdk_library) itself.
type SdkLibraryComponentDependency interface {
+ UsesLibraryDependency
+
// The optional name of the sdk library that should be implicitly added to the
// AndroidManifest of an app that contains code which references the sdk library.
//
- // Returns an array containing 0 or 1 items rather than a *string to make it easier
- // to append this to the list of exported sdk libraries.
- OptionalImplicitSdkLibrary() []string
+ // Returns the name of the optional implicit SDK library or nil, if there isn't one.
+ OptionalImplicitSdkLibrary() *string
}
// Make sure that all the module types that are components of java_sdk_library/_import
@@ -990,16 +985,8 @@ func (module *SdkLibrary) ComponentDepsMutator(ctx android.BottomUpMutatorContex
// Add dependencies to the stubs library
ctx.AddVariationDependencies(nil, apiScope.stubsTag, module.stubsLibraryModuleName(apiScope))
- // If the stubs source and API cannot be generated together then add an additional dependency on
- // the API module.
- if apiScope.createStubsSourceAndApiTogether {
- // Add a dependency on the stubs source in order to access both stubs source and api information.
- ctx.AddVariationDependencies(nil, apiScope.stubsSourceAndApiTag, module.stubsSourceModuleName(apiScope))
- } else {
- // Add separate dependencies on the creators of the stubs source files and the API.
- ctx.AddVariationDependencies(nil, apiScope.stubsSourceTag, module.stubsSourceModuleName(apiScope))
- ctx.AddVariationDependencies(nil, apiScope.apiFileTag, module.apiModuleName(apiScope))
- }
+ // Add a dependency on the stubs source in order to access both stubs source and api information.
+ ctx.AddVariationDependencies(nil, apiScope.stubsSourceAndApiTag, module.stubsSourceModuleName(apiScope))
}
if module.requiresRuntimeImplementationLibrary() {
@@ -1126,6 +1113,7 @@ func (module *SdkLibrary) createImplLibrary(mctx android.DefaultableHookContext)
&module.properties,
&module.protoProperties,
&module.deviceProperties,
+ &module.dexProperties,
&module.dexpreoptProperties,
&module.linter.properties,
&props,
@@ -1137,22 +1125,17 @@ func (module *SdkLibrary) createImplLibrary(mctx android.DefaultableHookContext)
// Creates a static java library that has API stubs
func (module *SdkLibrary) createStubsLibrary(mctx android.DefaultableHookContext, apiScope *apiScope) {
props := struct {
- Name *string
- Visibility []string
- Srcs []string
- Installable *bool
- Sdk_version *string
- System_modules *string
- Patch_module *string
- Libs []string
- Compile_dex *bool
- Java_version *string
- Product_variables struct {
- Pdk struct {
- Enabled *bool
- }
- }
- Openjdk9 struct {
+ Name *string
+ Visibility []string
+ Srcs []string
+ Installable *bool
+ Sdk_version *string
+ System_modules *string
+ Patch_module *string
+ Libs []string
+ Compile_dex *bool
+ Java_version *string
+ Openjdk9 struct {
Srcs []string
Javacflags []string
}
@@ -1184,14 +1167,13 @@ func (module *SdkLibrary) createStubsLibrary(mctx android.DefaultableHookContext
if proptools.Bool(module.sdkLibraryProperties.Annotations_enabled) {
props.Libs = append(props.Libs, "stub-annotations")
}
- props.Product_variables.Pdk.Enabled = proptools.BoolPtr(false)
props.Openjdk9.Srcs = module.properties.Openjdk9.Srcs
props.Openjdk9.Javacflags = module.properties.Openjdk9.Javacflags
// We compile the stubs for 1.8 in line with the main android.jar stubs, and potential
// interop with older developer tools that don't support 1.9.
props.Java_version = proptools.StringPtr("1.8")
- if module.deviceProperties.Compile_dex != nil {
- props.Compile_dex = module.deviceProperties.Compile_dex
+ if module.dexProperties.Compile_dex != nil {
+ props.Compile_dex = module.dexProperties.Compile_dex
}
// Dist the class jar artifact for sdk builds.
@@ -1207,7 +1189,7 @@ func (module *SdkLibrary) createStubsLibrary(mctx android.DefaultableHookContext
// Creates a droidstubs module that creates stubs source files from the given full source
// files and also updates and checks the API specification files.
-func (module *SdkLibrary) createStubsSourcesAndApi(mctx android.DefaultableHookContext, apiScope *apiScope, name string, createStubSources, createApi bool, scopeSpecificDroidstubsArgs []string) {
+func (module *SdkLibrary) createStubsSourcesAndApi(mctx android.DefaultableHookContext, apiScope *apiScope, name string, scopeSpecificDroidstubsArgs []string) {
props := struct {
Name *string
Visibility []string
@@ -1296,64 +1278,57 @@ func (module *SdkLibrary) createStubsSourcesAndApi(mctx android.DefaultableHookC
}
droidstubsArgs = append(droidstubsArgs, android.JoinWithPrefix(disabledWarnings, "--hide "))
- if !createStubSources {
- // Stubs are not required.
- props.Generate_stubs = proptools.BoolPtr(false)
- }
-
// Add in scope specific arguments.
droidstubsArgs = append(droidstubsArgs, scopeSpecificDroidstubsArgs...)
props.Arg_files = module.sdkLibraryProperties.Droiddoc_option_files
props.Args = proptools.StringPtr(strings.Join(droidstubsArgs, " "))
- if createApi {
- // List of APIs identified from the provided source files are created. They are later
- // compared against to the not-yet-released (a.k.a current) list of APIs and to the
- // last-released (a.k.a numbered) list of API.
- currentApiFileName := apiScope.apiFilePrefix + "current.txt"
- removedApiFileName := apiScope.apiFilePrefix + "removed.txt"
- apiDir := module.getApiDir()
- currentApiFileName = path.Join(apiDir, currentApiFileName)
- removedApiFileName = path.Join(apiDir, removedApiFileName)
-
- // check against the not-yet-release API
- props.Check_api.Current.Api_file = proptools.StringPtr(currentApiFileName)
- props.Check_api.Current.Removed_api_file = proptools.StringPtr(removedApiFileName)
-
- if !apiScope.unstable {
- // check against the latest released API
- latestApiFilegroupName := proptools.StringPtr(module.latestApiFilegroupName(apiScope))
- props.Check_api.Last_released.Api_file = latestApiFilegroupName
- props.Check_api.Last_released.Removed_api_file = proptools.StringPtr(
- module.latestRemovedApiFilegroupName(apiScope))
- props.Check_api.Ignore_missing_latest_api = proptools.BoolPtr(true)
-
- if proptools.Bool(module.sdkLibraryProperties.Api_lint.Enabled) {
- // Enable api lint.
- props.Check_api.Api_lint.Enabled = proptools.BoolPtr(true)
- props.Check_api.Api_lint.New_since = latestApiFilegroupName
-
- // If it exists then pass a lint-baseline.txt through to droidstubs.
- baselinePath := path.Join(apiDir, apiScope.apiFilePrefix+"lint-baseline.txt")
- baselinePathRelativeToRoot := path.Join(mctx.ModuleDir(), baselinePath)
- paths, err := mctx.GlobWithDeps(baselinePathRelativeToRoot, nil)
- if err != nil {
- mctx.ModuleErrorf("error checking for presence of %s: %s", baselinePathRelativeToRoot, err)
- }
- if len(paths) == 1 {
- props.Check_api.Api_lint.Baseline_file = proptools.StringPtr(baselinePath)
- } else if len(paths) != 0 {
- mctx.ModuleErrorf("error checking for presence of %s: expected one path, found: %v", baselinePathRelativeToRoot, paths)
- }
+ // List of APIs identified from the provided source files are created. They are later
+ // compared against to the not-yet-released (a.k.a current) list of APIs and to the
+ // last-released (a.k.a numbered) list of API.
+ currentApiFileName := apiScope.apiFilePrefix + "current.txt"
+ removedApiFileName := apiScope.apiFilePrefix + "removed.txt"
+ apiDir := module.getApiDir()
+ currentApiFileName = path.Join(apiDir, currentApiFileName)
+ removedApiFileName = path.Join(apiDir, removedApiFileName)
+
+ // check against the not-yet-release API
+ props.Check_api.Current.Api_file = proptools.StringPtr(currentApiFileName)
+ props.Check_api.Current.Removed_api_file = proptools.StringPtr(removedApiFileName)
+
+ if !apiScope.unstable {
+ // check against the latest released API
+ latestApiFilegroupName := proptools.StringPtr(module.latestApiFilegroupName(apiScope))
+ props.Check_api.Last_released.Api_file = latestApiFilegroupName
+ props.Check_api.Last_released.Removed_api_file = proptools.StringPtr(
+ module.latestRemovedApiFilegroupName(apiScope))
+ props.Check_api.Ignore_missing_latest_api = proptools.BoolPtr(true)
+
+ if proptools.Bool(module.sdkLibraryProperties.Api_lint.Enabled) {
+ // Enable api lint.
+ props.Check_api.Api_lint.Enabled = proptools.BoolPtr(true)
+ props.Check_api.Api_lint.New_since = latestApiFilegroupName
+
+ // If it exists then pass a lint-baseline.txt through to droidstubs.
+ baselinePath := path.Join(apiDir, apiScope.apiFilePrefix+"lint-baseline.txt")
+ baselinePathRelativeToRoot := path.Join(mctx.ModuleDir(), baselinePath)
+ paths, err := mctx.GlobWithDeps(baselinePathRelativeToRoot, nil)
+ if err != nil {
+ mctx.ModuleErrorf("error checking for presence of %s: %s", baselinePathRelativeToRoot, err)
+ }
+ if len(paths) == 1 {
+ props.Check_api.Api_lint.Baseline_file = proptools.StringPtr(baselinePath)
+ } else if len(paths) != 0 {
+ mctx.ModuleErrorf("error checking for presence of %s: expected one path, found: %v", baselinePathRelativeToRoot, paths)
}
}
+ }
- // Dist the api txt artifact for sdk builds.
- if !Bool(module.sdkLibraryProperties.No_dist) {
- props.Dist.Targets = []string{"sdk", "win_sdk"}
- props.Dist.Dest = proptools.StringPtr(fmt.Sprintf("%v.txt", module.BaseModuleName()))
- props.Dist.Dir = proptools.StringPtr(path.Join(module.apiDistPath(apiScope), "api"))
- }
+ // Dist the api txt artifact for sdk builds.
+ if !Bool(module.sdkLibraryProperties.No_dist) {
+ props.Dist.Targets = []string{"sdk", "win_sdk"}
+ props.Dist.Dest = proptools.StringPtr(fmt.Sprintf("%v.txt", module.BaseModuleName()))
+ props.Dist.Dir = proptools.StringPtr(path.Join(module.apiDistPath(apiScope), "api"))
}
mctx.CreateModule(DroidstubsFactory, &props)
@@ -1409,22 +1384,22 @@ func PrebuiltJars(ctx android.BaseModuleContext, baseName string, s sdkSpec) and
return android.Paths{jarPath.Path()}
}
-// Get the apex name for module, "" if it is for platform.
-func getApexNameForModule(module android.Module) string {
+// Get the apex names for module, nil if it is for platform.
+func getApexNamesForModule(module android.Module) []string {
if apex, ok := module.(android.ApexModule); ok {
- return apex.ApexName()
+ return apex.InApexes()
}
- return ""
+ return nil
}
-// Check to see if the other module is within the same named APEX as this module.
+// Check to see if the other module is within the same set of named APEXes as this module.
//
// If either this or the other module are on the platform then this will return
// false.
-func withinSameApexAs(module android.ApexModule, other android.Module) bool {
- name := module.ApexName()
- return name != "" && getApexNameForModule(other) == name
+func withinSameApexesAs(module android.ApexModule, other android.Module) bool {
+ names := module.InApexes()
+ return len(names) > 0 && reflect.DeepEqual(names, getApexNamesForModule(other))
}
func (module *SdkLibrary) sdkJars(ctx android.BaseModuleContext, sdkVersion sdkSpec, headerJars bool) android.Paths {
@@ -1443,7 +1418,7 @@ func (module *SdkLibrary) sdkJars(ctx android.BaseModuleContext, sdkVersion sdkS
// Only allow access to the implementation library in the following condition:
// * No sdk_version specified on the referencing module.
// * The referencing module is in the same apex as this.
- if sdkVersion.kind == sdkPrivate || withinSameApexAs(module, ctx.Module()) {
+ if sdkVersion.kind == sdkPrivate || withinSameApexesAs(module, ctx.Module()) {
if headerJars {
return module.HeaderJars()
} else {
@@ -1536,22 +1511,8 @@ func (module *SdkLibrary) CreateInternalModules(mctx android.DefaultableHookCont
}
for _, scope := range generatedScopes {
- stubsSourceArgs := scope.droidstubsArgsForGeneratingStubsSource
- stubsSourceModuleName := module.stubsSourceModuleName(scope)
-
- // If the args needed to generate the stubs and API are the same then they
- // can be generated in a single invocation of metalava, otherwise they will
- // need separate invocations.
- if scope.createStubsSourceAndApiTogether {
- // Use the stubs source name for legacy reasons.
- module.createStubsSourcesAndApi(mctx, scope, stubsSourceModuleName, true, true, stubsSourceArgs)
- } else {
- module.createStubsSourcesAndApi(mctx, scope, stubsSourceModuleName, true, false, stubsSourceArgs)
-
- apiArgs := scope.droidstubsArgsForGeneratingApi
- apiName := module.apiModuleName(scope)
- module.createStubsSourcesAndApi(mctx, scope, apiName, false, true, apiArgs)
- }
+ // Use the stubs source name for legacy reasons.
+ module.createStubsSourcesAndApi(mctx, scope, module.stubsSourceModuleName(scope), scope.droidstubsArgs)
module.createStubsLibrary(mctx, scope)
}
@@ -1840,7 +1801,7 @@ func (module *SdkLibraryImport) Name() string {
func (module *SdkLibraryImport) createInternalModules(mctx android.DefaultableHookContext) {
// If the build is configured to use prebuilts then force this to be preferred.
- if mctx.Config().UnbundledBuildUsePrebuiltSdks() {
+ if mctx.Config().AlwaysUsePrebuiltSdks() {
module.prebuilt.ForcePrefer()
}
@@ -1996,7 +1957,7 @@ func (module *SdkLibraryImport) sdkJars(ctx android.BaseModuleContext, sdkVersio
// For consistency with SdkLibrary make the implementation jar available to libraries that
// are within the same APEX.
implLibraryModule := module.implLibraryModule
- if implLibraryModule != nil && withinSameApexAs(module, ctx.Module()) {
+ if implLibraryModule != nil && withinSameApexesAs(module, ctx.Module()) {
if headerJars {
return implLibraryModule.HeaderJars()
} else {
@@ -2019,7 +1980,7 @@ func (module *SdkLibraryImport) SdkImplementationJars(ctx android.BaseModuleCont
return module.sdkJars(ctx, sdkVersion, false)
}
-// to satisfy apex.javaDependency interface
+// to satisfy SdkLibraryDependency interface
func (module *SdkLibraryImport) DexJarBuildPath() android.Path {
if module.implLibraryModule == nil {
return nil
@@ -2028,6 +1989,15 @@ func (module *SdkLibraryImport) DexJarBuildPath() android.Path {
}
}
+// to satisfy SdkLibraryDependency interface
+func (module *SdkLibraryImport) DexJarInstallPath() android.Path {
+ if module.implLibraryModule == nil {
+ return nil
+ } else {
+ return module.implLibraryModule.DexJarInstallPath()
+ }
+}
+
// to satisfy apex.javaDependency interface
func (module *SdkLibraryImport) JacocoReportClassesFile() android.Path {
if module.implLibraryModule == nil {
@@ -2038,6 +2008,15 @@ func (module *SdkLibraryImport) JacocoReportClassesFile() android.Path {
}
// to satisfy apex.javaDependency interface
+func (module *SdkLibraryImport) LintDepSets() LintDepSets {
+ if module.implLibraryModule == nil {
+ return LintDepSets{}
+ } else {
+ return module.implLibraryModule.LintDepSets()
+ }
+}
+
+// to satisfy apex.javaDependency interface
func (module *SdkLibraryImport) Stem() string {
return module.BaseModuleName()
}
@@ -2094,6 +2073,12 @@ func sdkLibraryXmlFactory() android.Module {
return module
}
+func (module *sdkLibraryXml) UniqueApexVariations() bool {
+ // sdkLibraryXml needs a unique variation per APEX because the generated XML file contains the path to the
+ // mounted APEX, which contains the name of the APEX.
+ return true
+}
+
// from android.PrebuiltEtcModule
func (module *sdkLibraryXml) SubDir() string {
return "permissions"
@@ -2121,8 +2106,8 @@ func (module *sdkLibraryXml) ShouldSupportSdkVersion(ctx android.BaseModuleConte
// File path to the runtime implementation library
func (module *sdkLibraryXml) implPath() string {
implName := proptools.String(module.properties.Lib_name)
- if apexName := module.ApexName(); apexName != "" {
- // TODO(b/146468504): ApexName() is only a soong module name, not apex name.
+ if apexName := module.ApexVariationName(); apexName != "" {
+ // TODO(b/146468504): ApexVariationName() is only a soong module name, not apex name.
// In most cases, this works fine. But when apex_name is set or override_apex is used
// this can be wrong.
return fmt.Sprintf("/apex/%s/javalib/%s.jar", apexName, implName)
diff --git a/java/sdk_test.go b/java/sdk_test.go
index 1f23b140c..776069dc9 100644
--- a/java/sdk_test.go
+++ b/java/sdk_test.go
@@ -30,7 +30,6 @@ func TestClasspath(t *testing.T) {
var classpathTestcases = []struct {
name string
unbundled bool
- pdk bool
moduleType string
host android.OsClass
properties string
@@ -49,8 +48,8 @@ func TestClasspath(t *testing.T) {
}{
{
name: "default",
- bootclasspath: config.LegacyCorePlatformBootclasspathLibraries,
- system: config.LegacyCorePlatformSystemModules,
+ bootclasspath: config.StableCorePlatformBootclasspathLibraries,
+ system: config.StableCorePlatformSystemModules,
java8classpath: config.FrameworkLibraries,
java9classpath: config.FrameworkLibraries,
aidl: "-Iframework/aidl",
@@ -58,16 +57,16 @@ func TestClasspath(t *testing.T) {
{
name: `sdk_version:"core_platform"`,
properties: `sdk_version:"core_platform"`,
- bootclasspath: config.LegacyCorePlatformBootclasspathLibraries,
- system: config.LegacyCorePlatformSystemModules,
+ bootclasspath: config.StableCorePlatformBootclasspathLibraries,
+ system: config.StableCorePlatformSystemModules,
java8classpath: []string{},
aidl: "",
},
{
name: "blank sdk version",
properties: `sdk_version: "",`,
- bootclasspath: config.LegacyCorePlatformBootclasspathLibraries,
- system: config.LegacyCorePlatformSystemModules,
+ bootclasspath: config.StableCorePlatformBootclasspathLibraries,
+ system: config.StableCorePlatformSystemModules,
java8classpath: config.FrameworkLibraries,
java9classpath: config.FrameworkLibraries,
aidl: "-Iframework/aidl",
@@ -155,9 +154,9 @@ func TestClasspath(t *testing.T) {
{
name: "nostdlib system_modules",
- properties: `sdk_version: "none", system_modules: "legacy-core-platform-api-stubs-system-modules"`,
- system: "legacy-core-platform-api-stubs-system-modules",
- bootclasspath: []string{"legacy-core-platform-api-stubs-system-modules-lib"},
+ properties: `sdk_version: "none", system_modules: "stable-core-platform-api-stubs-system-modules"`,
+ system: "stable-core-platform-api-stubs-system-modules",
+ bootclasspath: []string{"stable-core-platform-api-stubs-system-modules-lib"},
java8classpath: []string{},
},
{
@@ -217,35 +216,6 @@ func TestClasspath(t *testing.T) {
},
{
- name: "pdk default",
- pdk: true,
- bootclasspath: []string{`""`},
- system: "sdk_public_30_system_modules",
- java8classpath: []string{"prebuilts/sdk/30/public/android.jar", "prebuilts/sdk/tools/core-lambda-stubs.jar"},
- java9classpath: []string{"prebuilts/sdk/30/public/android.jar", "prebuilts/sdk/tools/core-lambda-stubs.jar"},
- aidl: "-pprebuilts/sdk/30/public/framework.aidl",
- },
- {
- name: "pdk current",
- pdk: true,
- properties: `sdk_version: "current",`,
- bootclasspath: []string{`""`},
- system: "sdk_public_30_system_modules",
- java8classpath: []string{"prebuilts/sdk/30/public/android.jar", "prebuilts/sdk/tools/core-lambda-stubs.jar"},
- java9classpath: []string{"prebuilts/sdk/30/public/android.jar", "prebuilts/sdk/tools/core-lambda-stubs.jar"},
- aidl: "-pprebuilts/sdk/30/public/framework.aidl",
- },
- {
- name: "pdk 29",
- pdk: true,
- properties: `sdk_version: "29",`,
- bootclasspath: []string{`""`},
- system: "sdk_public_30_system_modules",
- java8classpath: []string{"prebuilts/sdk/30/public/android.jar", "prebuilts/sdk/tools/core-lambda-stubs.jar"},
- java9classpath: []string{"prebuilts/sdk/30/public/android.jar", "prebuilts/sdk/tools/core-lambda-stubs.jar"},
- aidl: "-pprebuilts/sdk/30/public/framework.aidl",
- },
- {
name: "module_current",
properties: `sdk_version: "module_current",`,
bootclasspath: []string{"android_module_lib_stubs_current", "core-lambda-stubs"},
@@ -384,9 +354,7 @@ func TestClasspath(t *testing.T) {
config := testConfig(nil, bpJava8, nil)
if testcase.unbundled {
config.TestProductVariables.Unbundled_build = proptools.BoolPtr(true)
- }
- if testcase.pdk {
- config.TestProductVariables.Pdk = proptools.BoolPtr(true)
+ config.TestProductVariables.Always_use_prebuilt_sdks = proptools.BoolPtr(true)
}
ctx := testContext()
run(t, ctx, config)
@@ -407,9 +375,7 @@ func TestClasspath(t *testing.T) {
config := testConfig(nil, bp, nil)
if testcase.unbundled {
config.TestProductVariables.Unbundled_build = proptools.BoolPtr(true)
- }
- if testcase.pdk {
- config.TestProductVariables.Pdk = proptools.BoolPtr(true)
+ config.TestProductVariables.Always_use_prebuilt_sdks = proptools.BoolPtr(true)
}
ctx := testContext()
run(t, ctx, config)
@@ -433,9 +399,7 @@ func TestClasspath(t *testing.T) {
if testcase.unbundled {
config.TestProductVariables.Unbundled_build = proptools.BoolPtr(true)
- }
- if testcase.pdk {
- config.TestProductVariables.Pdk = proptools.BoolPtr(true)
+ config.TestProductVariables.Always_use_prebuilt_sdks = proptools.BoolPtr(true)
}
ctx := testContext()
run(t, ctx, config)
@@ -451,9 +415,7 @@ func TestClasspath(t *testing.T) {
if testcase.unbundled {
config.TestProductVariables.Unbundled_build = proptools.BoolPtr(true)
- }
- if testcase.pdk {
- config.TestProductVariables.Pdk = proptools.BoolPtr(true)
+ config.TestProductVariables.Always_use_prebuilt_sdks = proptools.BoolPtr(true)
}
ctx := testContext()
run(t, ctx, config)
diff --git a/java/testing.go b/java/testing.go
index 4f3f9f160..70c857f39 100644
--- a/java/testing.go
+++ b/java/testing.go
@@ -22,6 +22,8 @@ import (
"android/soong/android"
"android/soong/cc"
+ "android/soong/python"
+
"github.com/google/blueprint"
)
@@ -42,6 +44,9 @@ func TestConfig(buildDir string, env map[string]string, bp string, fs map[string
"prebuilts/sdk/17/public/android.jar": nil,
"prebuilts/sdk/17/public/framework.aidl": nil,
"prebuilts/sdk/17/system/android.jar": nil,
+ "prebuilts/sdk/28/public/android.jar": nil,
+ "prebuilts/sdk/28/public/framework.aidl": nil,
+ "prebuilts/sdk/28/system/android.jar": nil,
"prebuilts/sdk/29/public/android.jar": nil,
"prebuilts/sdk/29/public/framework.aidl": nil,
"prebuilts/sdk/29/system/android.jar": nil,
@@ -85,6 +90,10 @@ func TestConfig(buildDir string, env map[string]string, bp string, fs map[string
"prebuilts/sdk/tools/core-lambda-stubs.jar": nil,
"prebuilts/sdk/Android.bp": []byte(`prebuilt_apis { name: "sdk", api_dirs: ["14", "28", "30", "current"],}`),
+ "bin.py": nil,
+ python.StubTemplateHost: []byte(`PYTHON_BINARY = '%interpreter%'
+ MAIN_FILE = '%main%'`),
+
// For java_sdk_library
"api/module-lib-current.txt": nil,
"api/module-lib-removed.txt": nil,
@@ -135,7 +144,7 @@ func GatherRequiredDepsForTest() string {
name: "%s",
srcs: ["a.java"],
sdk_version: "none",
- system_modules: "legacy-core-platform-api-stubs-system-modules",
+ system_modules: "stable-core-platform-api-stubs-system-modules",
}
`, extra)
}
@@ -145,7 +154,7 @@ func GatherRequiredDepsForTest() string {
name: "framework",
srcs: ["a.java"],
sdk_version: "none",
- system_modules: "legacy-core-platform-api-stubs-system-modules",
+ system_modules: "stable-core-platform-api-stubs-system-modules",
aidl: {
export_include_dirs: ["framework/aidl"],
},
@@ -160,7 +169,7 @@ func GatherRequiredDepsForTest() string {
name: "android.hidl.base-V1.0-java",
srcs: ["a.java"],
sdk_version: "none",
- system_modules: "legacy-core-platform-api-stubs-system-modules",
+ system_modules: "stable-core-platform-api-stubs-system-modules",
installable: true,
}
@@ -168,7 +177,7 @@ func GatherRequiredDepsForTest() string {
name: "android.hidl.manager-V1.0-java",
srcs: ["a.java"],
sdk_version: "none",
- system_modules: "legacy-core-platform-api-stubs-system-modules",
+ system_modules: "stable-core-platform-api-stubs-system-modules",
installable: true,
}
@@ -176,7 +185,7 @@ func GatherRequiredDepsForTest() string {
name: "org.apache.http.legacy",
srcs: ["a.java"],
sdk_version: "none",
- system_modules: "legacy-core-platform-api-stubs-system-modules",
+ system_modules: "stable-core-platform-api-stubs-system-modules",
installable: true,
}
@@ -184,7 +193,7 @@ func GatherRequiredDepsForTest() string {
name: "android.test.base",
srcs: ["a.java"],
sdk_version: "none",
- system_modules: "legacy-core-platform-api-stubs-system-modules",
+ system_modules: "stable-core-platform-api-stubs-system-modules",
installable: true,
}
@@ -192,7 +201,7 @@ func GatherRequiredDepsForTest() string {
name: "android.test.mock",
srcs: ["a.java"],
sdk_version: "none",
- system_modules: "legacy-core-platform-api-stubs-system-modules",
+ system_modules: "stable-core-platform-api-stubs-system-modules",
installable: true,
}
`
diff --git a/phony/phony.go b/phony/phony.go
index 305a434f4..cb60b9f9e 100644
--- a/phony/phony.go
+++ b/phony/phony.go
@@ -44,11 +44,6 @@ func (p *phony) GenerateAndroidBuildActions(ctx android.ModuleContext) {
p.requiredModuleNames = ctx.RequiredModuleNames()
p.hostRequiredModuleNames = ctx.HostRequiredModuleNames()
p.targetRequiredModuleNames = ctx.TargetRequiredModuleNames()
- if len(p.requiredModuleNames) == 0 &&
- len(p.hostRequiredModuleNames) == 0 && len(p.targetRequiredModuleNames) == 0 {
- ctx.PropertyErrorf("required", "phony must not have empty required dependencies "+
- "in order to be useful(and therefore permitted).")
- }
}
func (p *phony) AndroidMk() android.AndroidMkData {
diff --git a/python/binary.go b/python/binary.go
index 695fa123b..5a7492648 100644
--- a/python/binary.go
+++ b/python/binary.go
@@ -65,7 +65,7 @@ type IntermPathProvider interface {
}
var (
- stubTemplateHost = "build/soong/python/scripts/stub_template_host.txt"
+ StubTemplateHost = "build/soong/python/scripts/stub_template_host.txt"
)
func NewBinary(hod android.HostOrDeviceSupported) (*Module, *binaryDecorator) {
diff --git a/python/builder.go b/python/builder.go
index 36baecdf1..dc2d1f127 100644
--- a/python/builder.go
+++ b/python/builder.go
@@ -91,7 +91,7 @@ func registerBuildActionForParFile(ctx android.ModuleContext, embeddedLauncher b
if !embeddedLauncher {
// the path of stub_template_host.txt from source tree.
- template := android.PathForSource(ctx, stubTemplateHost)
+ template := android.PathForSource(ctx, StubTemplateHost)
implicits = append(implicits, template)
// intermediate output path for __main__.py
diff --git a/python/python.go b/python/python.go
index a6c9e2a07..479c7291d 100644
--- a/python/python.go
+++ b/python/python.go
@@ -30,9 +30,11 @@ import (
)
func init() {
- android.PreDepsMutators(func(ctx android.RegisterMutatorsContext) {
- ctx.BottomUp("version_split", versionSplitMutator()).Parallel()
- })
+ android.PreDepsMutators(RegisterPythonPreDepsMutators)
+}
+
+func RegisterPythonPreDepsMutators(ctx android.RegisterMutatorsContext) {
+ ctx.BottomUp("version_split", versionSplitMutator()).Parallel()
}
// the version properties that apply to python libraries and binaries.
@@ -226,15 +228,20 @@ func versionSplitMutator() func(android.BottomUpMutatorContext) {
return func(mctx android.BottomUpMutatorContext) {
if base, ok := mctx.Module().(*Module); ok {
versionNames := []string{}
- if base.properties.Version.Py2.Enabled != nil &&
- *(base.properties.Version.Py2.Enabled) == true {
- versionNames = append(versionNames, pyVersion2)
- }
+ // PY3 is first so that we alias the PY3 variant rather than PY2 if both
+ // are available
if !(base.properties.Version.Py3.Enabled != nil &&
*(base.properties.Version.Py3.Enabled) == false) {
versionNames = append(versionNames, pyVersion3)
}
+ if base.properties.Version.Py2.Enabled != nil &&
+ *(base.properties.Version.Py2.Enabled) == true {
+ versionNames = append(versionNames, pyVersion2)
+ }
modules := mctx.CreateVariations(versionNames...)
+ if len(versionNames) > 0 {
+ mctx.AliasVariation(versionNames[0])
+ }
for i, v := range versionNames {
// set the actual version for Python module.
modules[i].(*Module).properties.Actual_version = v
diff --git a/python/python_test.go b/python/python_test.go
index 1245ca184..23db24e8f 100644
--- a/python/python_test.go
+++ b/python/python_test.go
@@ -301,7 +301,7 @@ var (
filepath.Join("dir", "file2.py"): nil,
filepath.Join("dir", "bin.py"): nil,
filepath.Join("dir", "file4.py"): nil,
- stubTemplateHost: []byte(`PYTHON_BINARY = '%interpreter%'
+ StubTemplateHost: []byte(`PYTHON_BINARY = '%interpreter%'
MAIN_FILE = '%main%'`),
},
expectedBinaries: []pyModule{
@@ -330,9 +330,7 @@ func TestPythonModule(t *testing.T) {
t.Run(d.desc, func(t *testing.T) {
config := android.TestConfig(buildDir, nil, "", d.mockFiles)
ctx := android.NewTestContext()
- ctx.PreDepsMutators(func(ctx android.RegisterMutatorsContext) {
- ctx.BottomUp("version_split", versionSplitMutator()).Parallel()
- })
+ ctx.PreDepsMutators(RegisterPythonPreDepsMutators)
ctx.RegisterModuleType("python_library_host", PythonLibraryHostFactory)
ctx.RegisterModuleType("python_binary_host", PythonBinaryHostFactory)
ctx.RegisterModuleType("python_defaults", defaultsFactory)
diff --git a/rust/Android.bp b/rust/Android.bp
index d56de870f..bbeb28d0b 100644
--- a/rust/Android.bp
+++ b/rust/Android.bp
@@ -10,6 +10,7 @@ bootstrap_go_package {
srcs: [
"androidmk.go",
"binary.go",
+ "bindgen.go",
"builder.go",
"clippy.go",
"compiler.go",
@@ -19,17 +20,21 @@ bootstrap_go_package {
"proc_macro.go",
"project_json.go",
"rust.go",
+ "source_provider.go",
"test.go",
"testing.go",
],
testSrcs: [
"binary_test.go",
+ "bindgen_test.go",
+ "builder_test.go",
"clippy_test.go",
"compiler_test.go",
"coverage_test.go",
"library_test.go",
"project_json_test.go",
"rust_test.go",
+ "source_provider_test.go",
"test_test.go",
],
pluginFor: ["soong_build"],
diff --git a/rust/androidmk.go b/rust/androidmk.go
index aea899baa..fda0a2579 100644
--- a/rust/androidmk.go
+++ b/rust/androidmk.go
@@ -26,18 +26,18 @@ import (
type AndroidMkContext interface {
Name() string
Target() android.Target
- subAndroidMk(*android.AndroidMkData, interface{})
+ SubAndroidMk(*android.AndroidMkData, interface{})
}
-type subAndroidMkProvider interface {
+type SubAndroidMkProvider interface {
AndroidMk(AndroidMkContext, *android.AndroidMkData)
}
-func (mod *Module) subAndroidMk(data *android.AndroidMkData, obj interface{}) {
+func (mod *Module) SubAndroidMk(data *android.AndroidMkData, obj interface{}) {
if mod.subAndroidMkOnce == nil {
- mod.subAndroidMkOnce = make(map[subAndroidMkProvider]bool)
+ mod.subAndroidMkOnce = make(map[SubAndroidMkProvider]bool)
}
- if androidmk, ok := obj.(subAndroidMkProvider); ok {
+ if androidmk, ok := obj.(SubAndroidMkProvider); ok {
if !mod.subAndroidMkOnce[androidmk] {
mod.subAndroidMkOnce[androidmk] = true
androidmk.AndroidMk(mod, data)
@@ -76,15 +76,19 @@ func (mod *Module) AndroidMk() android.AndroidMkData {
},
}
- mod.subAndroidMk(&ret, mod.compiler)
-
+ if mod.compiler != nil && !mod.compiler.Disabled() {
+ mod.SubAndroidMk(&ret, mod.compiler)
+ } else if mod.sourceProvider != nil {
+ // If the compiler is disabled, this is a SourceProvider.
+ mod.SubAndroidMk(&ret, mod.sourceProvider)
+ }
ret.SubName += mod.Properties.SubName
return ret
}
func (binary *binaryDecorator) AndroidMk(ctx AndroidMkContext, ret *android.AndroidMkData) {
- ctx.subAndroidMk(ret, binary.baseCompiler)
+ ctx.SubAndroidMk(ret, binary.baseCompiler)
if binary.distFile.Valid() {
ret.DistFiles = android.MakeDefaultDistFiles(binary.distFile.Path())
@@ -118,7 +122,7 @@ func (test *testDecorator) AndroidMk(ctx AndroidMkContext, ret *android.AndroidM
}
func (library *libraryDecorator) AndroidMk(ctx AndroidMkContext, ret *android.AndroidMkData) {
- ctx.subAndroidMk(ret, library.baseCompiler)
+ ctx.SubAndroidMk(ret, library.baseCompiler)
if library.rlib() {
ret.Class = "RLIB_LIBRARIES"
@@ -146,7 +150,7 @@ func (library *libraryDecorator) AndroidMk(ctx AndroidMkContext, ret *android.An
}
func (procMacro *procMacroDecorator) AndroidMk(ctx AndroidMkContext, ret *android.AndroidMkData) {
- ctx.subAndroidMk(ret, procMacro.baseCompiler)
+ ctx.SubAndroidMk(ret, procMacro.baseCompiler)
ret.Class = "PROC_MACRO_LIBRARIES"
if procMacro.distFile.Valid() {
@@ -155,6 +159,26 @@ func (procMacro *procMacroDecorator) AndroidMk(ctx AndroidMkContext, ret *androi
}
+func (sourceProvider *BaseSourceProvider) AndroidMk(ctx AndroidMkContext, ret *android.AndroidMkData) {
+ outFile := sourceProvider.OutputFile
+ ret.Class = "ETC"
+ ret.OutputFile = android.OptionalPathForPath(outFile)
+ ret.SubName += sourceProvider.subName
+ ret.Extra = append(ret.Extra, func(w io.Writer, outputFile android.Path) {
+ _, file := filepath.Split(outFile.String())
+ stem, suffix, _ := android.SplitFileExt(file)
+ fmt.Fprintln(w, "LOCAL_MODULE_SUFFIX := "+suffix)
+ fmt.Fprintln(w, "LOCAL_MODULE_STEM := "+stem)
+ })
+}
+
+func (bindgen *bindgenDecorator) AndroidMk(ctx AndroidMkContext, ret *android.AndroidMkData) {
+ ctx.SubAndroidMk(ret, bindgen.BaseSourceProvider)
+ ret.Extra = append(ret.Extra, func(w io.Writer, outputFile android.Path) {
+ fmt.Fprintln(w, "LOCAL_UNINSTALLABLE_MODULE := true")
+ })
+}
+
func (compiler *baseCompiler) AndroidMk(ctx AndroidMkContext, ret *android.AndroidMkData) {
// Soong installation is only supported for host modules. Have Make
// installation trigger Soong installation.
diff --git a/rust/binary.go b/rust/binary.go
index 9fc52cdb8..d287a06ef 100644
--- a/rust/binary.go
+++ b/rust/binary.go
@@ -24,9 +24,6 @@ func init() {
}
type BinaryCompilerProperties struct {
- // passes -C prefer-dynamic to rustc, which tells it to dynamically link the stdlib
- // (assuming it has no dylib dependencies already)
- Prefer_dynamic *bool
}
type binaryDecorator struct {
@@ -60,10 +57,6 @@ func NewRustBinary(hod android.HostOrDeviceSupported) (*Module, *binaryDecorator
return module, binary
}
-func (binary *binaryDecorator) preferDynamic() bool {
- return Bool(binary.Properties.Prefer_dynamic)
-}
-
func (binary *binaryDecorator) compilerFlags(ctx ModuleContext, flags Flags) Flags {
flags = binary.baseCompiler.compilerFlags(ctx, flags)
@@ -76,9 +69,6 @@ func (binary *binaryDecorator) compilerFlags(ctx ModuleContext, flags Flags) Fla
"-Wl,--no-undefined-version")
}
- if binary.preferDynamic() {
- flags.RustFlags = append(flags.RustFlags, "-C prefer-dynamic")
- }
return flags
}
@@ -86,7 +76,7 @@ func (binary *binaryDecorator) compilerDeps(ctx DepsContext, deps Deps) Deps {
deps = binary.baseCompiler.compilerDeps(ctx, deps)
if ctx.toolchain().Bionic() {
- deps = binary.baseCompiler.bionicDeps(ctx, deps)
+ deps = bionicDeps(deps)
deps.CrtBegin = "crtbegin_dynamic"
deps.CrtEnd = "crtend_android"
}
@@ -106,13 +96,13 @@ func (binary *binaryDecorator) nativeCoverage() bool {
func (binary *binaryDecorator) compile(ctx ModuleContext, flags Flags, deps PathDeps) android.Path {
fileName := binary.getStem(ctx) + ctx.toolchain().ExecutableSuffix()
- srcPath, paths := srcPathFromModuleSrcs(ctx, binary.baseCompiler.Properties.Srcs)
- deps.SrcDeps = paths
+ srcPath, _ := srcPathFromModuleSrcs(ctx, binary.baseCompiler.Properties.Srcs)
outputFile := android.PathForModuleOut(ctx, fileName)
binary.unstrippedOutputFile = outputFile
flags.RustFlags = append(flags.RustFlags, deps.depFlags...)
+ flags.LinkFlags = append(flags.LinkFlags, deps.linkObjects...)
outputs := TransformSrcToBinary(ctx, srcPath, deps, flags, outputFile, deps.linkDirs)
binary.coverageFile = outputs.coverageFile
@@ -133,8 +123,9 @@ func (binary *binaryDecorator) coverageOutputZipPath() android.OptionalPath {
return binary.coverageOutputZipFile
}
-func (binary *binaryDecorator) autoDep() autoDep {
- if binary.preferDynamic() {
+func (binary *binaryDecorator) autoDep(ctx BaseModuleContext) autoDep {
+ // Binaries default to dylib dependencies for device, rlib for host.
+ if ctx.Device() {
return dylibAutoDep
} else {
return rlibAutoDep
diff --git a/rust/binary_test.go b/rust/binary_test.go
index ab2dae153..2fc38ed74 100644
--- a/rust/binary_test.go
+++ b/rust/binary_test.go
@@ -17,39 +17,82 @@ package rust
import (
"strings"
"testing"
+
+ "android/soong/android"
)
-// Test that the prefer_dynamic property is handled correctly.
-func TestPreferDynamicBinary(t *testing.T) {
+// Test that rustlibs default linkage is correct for binaries.
+func TestBinaryLinkage(t *testing.T) {
ctx := testRust(t, `
- rust_binary_host {
- name: "fizz-buzz-dynamic",
+ rust_binary {
+ name: "fizz-buzz",
srcs: ["foo.rs"],
- prefer_dynamic: true,
+ rustlibs: ["libfoo"],
+ host_supported: true,
}
+ rust_library {
+ name: "libfoo",
+ srcs: ["foo.rs"],
+ crate_name: "foo",
+ host_supported: true,
+ }`)
+
+ fizzBuzzHost := ctx.ModuleForTests("fizz-buzz", "linux_glibc_x86_64").Module().(*Module)
+ fizzBuzzDevice := ctx.ModuleForTests("fizz-buzz", "android_arm64_armv8-a").Module().(*Module)
+
+ if !android.InList("libfoo", fizzBuzzHost.Properties.AndroidMkRlibs) {
+ t.Errorf("rustlibs dependency libfoo should be an rlib dep for host modules")
+ }
+
+ if !android.InList("libfoo", fizzBuzzDevice.Properties.AndroidMkDylibs) {
+ t.Errorf("rustlibs dependency libfoo should be an dylib dep for device modules")
+ }
+}
+
+// Test that the path returned by HostToolPath is correct
+func TestHostToolPath(t *testing.T) {
+ ctx := testRust(t, `
+ rust_binary_host {
+ name: "fizz-buzz",
+ srcs: ["foo.rs"],
+ }`)
+
+ path := ctx.ModuleForTests("fizz-buzz", "linux_glibc_x86_64").Module().(*Module).HostToolPath()
+ if g, w := path.String(), "/host/linux-x86/bin/fizz-buzz"; !strings.Contains(g, w) {
+ t.Errorf("wrong host tool path, expected %q got %q", w, g)
+ }
+}
+// Test that the flags being passed to rust_binary modules are as expected
+func TestBinaryFlags(t *testing.T) {
+ ctx := testRust(t, `
rust_binary_host {
name: "fizz-buzz",
srcs: ["foo.rs"],
}`)
fizzBuzz := ctx.ModuleForTests("fizz-buzz", "linux_glibc_x86_64").Output("fizz-buzz")
- fizzBuzzDynamic := ctx.ModuleForTests("fizz-buzz-dynamic", "linux_glibc_x86_64").Output("fizz-buzz-dynamic")
- // Do not compile binary modules with the --test flag.
- flags := fizzBuzzDynamic.Args["rustcFlags"]
+ flags := fizzBuzz.Args["rustcFlags"]
if strings.Contains(flags, "--test") {
t.Errorf("extra --test flag, rustcFlags: %#v", flags)
}
- if !strings.Contains(flags, "prefer-dynamic") {
- t.Errorf("missing prefer-dynamic flag, rustcFlags: %#v", flags)
- }
+}
- flags = fizzBuzz.Args["rustcFlags"]
- if strings.Contains(flags, "--test") {
- t.Errorf("extra --test flag, rustcFlags: %#v", flags)
- }
- if strings.Contains(flags, "prefer-dynamic") {
- t.Errorf("unexpected prefer-dynamic flag, rustcFlags: %#v", flags)
+func TestLinkObjects(t *testing.T) {
+ ctx := testRust(t, `
+ rust_binary {
+ name: "fizz-buzz",
+ srcs: ["foo.rs"],
+ shared_libs: ["libfoo"],
+ }
+ cc_library {
+ name: "libfoo",
+ }`)
+
+ fizzBuzz := ctx.ModuleForTests("fizz-buzz", "android_arm64_armv8-a").Output("fizz-buzz")
+ linkFlags := fizzBuzz.Args["linkFlags"]
+ if !strings.Contains(linkFlags, "/libfoo.so") {
+ t.Errorf("missing shared dependency 'libfoo.so' in linkFlags: %#v", linkFlags)
}
}
diff --git a/rust/bindgen.go b/rust/bindgen.go
new file mode 100644
index 000000000..9b09e616e
--- /dev/null
+++ b/rust/bindgen.go
@@ -0,0 +1,206 @@
+// Copyright 2020 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package rust
+
+import (
+ "strings"
+
+ "github.com/google/blueprint"
+ "github.com/google/blueprint/proptools"
+
+ "android/soong/android"
+ ccConfig "android/soong/cc/config"
+)
+
+var (
+ defaultBindgenFlags = []string{""}
+
+ // bindgen should specify its own Clang revision so updating Clang isn't potentially blocked on bindgen failures.
+ bindgenClangVersion = "clang-r383902c"
+ bindgenLibClangSoGit = "11git"
+
+ //TODO(b/160803703) Use a prebuilt bindgen instead of the built bindgen.
+ _ = pctx.SourcePathVariable("bindgenCmd", "out/host/${config.HostPrebuiltTag}/bin/bindgen")
+ _ = pctx.SourcePathVariable("bindgenClang",
+ "${ccConfig.ClangBase}/${config.HostPrebuiltTag}/"+bindgenClangVersion+"/bin/clang")
+ _ = pctx.SourcePathVariable("bindgenLibClang",
+ "${ccConfig.ClangBase}/${config.HostPrebuiltTag}/"+bindgenClangVersion+"/lib64/libclang.so."+bindgenLibClangSoGit)
+
+ //TODO(ivanlozano) Switch this to RuleBuilder
+ bindgen = pctx.AndroidStaticRule("bindgen",
+ blueprint.RuleParams{
+ Command: "CLANG_PATH=$bindgenClang LIBCLANG_PATH=$bindgenLibClang RUSTFMT=${config.RustBin}/rustfmt " +
+ "$cmd $flags $in -o $out -- -MD -MF $out.d $cflags",
+ CommandDeps: []string{"$cmd"},
+ Deps: blueprint.DepsGCC,
+ Depfile: "$out.d",
+ },
+ "cmd", "flags", "cflags")
+)
+
+func init() {
+ android.RegisterModuleType("rust_bindgen", RustBindgenFactory)
+ android.RegisterModuleType("rust_bindgen_host", RustBindgenHostFactory)
+}
+
+var _ SourceProvider = (*bindgenDecorator)(nil)
+
+type BindgenProperties struct {
+ // The wrapper header file
+ Wrapper_src *string `android:"path,arch_variant"`
+
+ // list of bindgen-specific flags and options
+ Bindgen_flags []string `android:"arch_variant"`
+
+ // list of clang flags required to correctly interpret the headers.
+ Cflags []string `android:"arch_variant"`
+
+ // list of directories relative to the Blueprints file that will
+ // be added to the include path using -I
+ Local_include_dirs []string `android:"arch_variant,variant_prepend"`
+
+ // list of static libraries that provide headers for this binding.
+ Static_libs []string `android:"arch_variant,variant_prepend"`
+
+ // list of shared libraries that provide headers for this binding.
+ Shared_libs []string `android:"arch_variant"`
+
+ // module name of a custom binary/script which should be used instead of the 'bindgen' binary. This custom
+ // binary must expect arguments in a similar fashion to bindgen, e.g.
+ //
+ // "my_bindgen [flags] wrapper_header.h -o [output_path] -- [clang flags]"
+ Custom_bindgen string `android:"path"`
+
+ //TODO(b/161141999) Add support for headers from cc_library_header modules.
+}
+
+type bindgenDecorator struct {
+ *BaseSourceProvider
+
+ Properties BindgenProperties
+}
+
+func (b *bindgenDecorator) GenerateSource(ctx android.ModuleContext, deps PathDeps) android.Path {
+ ccToolchain := ccConfig.FindToolchain(ctx.Os(), ctx.Arch())
+
+ var cflags []string
+ var implicits android.Paths
+
+ implicits = append(implicits, deps.depIncludePaths...)
+ implicits = append(implicits, deps.depSystemIncludePaths...)
+
+ // Default clang flags
+ cflags = append(cflags, "${ccConfig.CommonClangGlobalCflags}")
+ if ctx.Device() {
+ cflags = append(cflags, "${ccConfig.DeviceClangGlobalCflags}")
+ }
+
+ // Toolchain clang flags
+ cflags = append(cflags, "-target "+ccToolchain.ClangTriple())
+ cflags = append(cflags, strings.ReplaceAll(ccToolchain.ToolchainClangCflags(), "${config.", "${ccConfig."))
+
+ // Dependency clang flags and include paths
+ cflags = append(cflags, deps.depClangFlags...)
+ for _, include := range deps.depIncludePaths {
+ cflags = append(cflags, "-I"+include.String())
+ }
+ for _, include := range deps.depSystemIncludePaths {
+ cflags = append(cflags, "-isystem "+include.String())
+ }
+
+ esc := proptools.NinjaAndShellEscapeList
+
+ // Module defined clang flags and include paths
+ cflags = append(cflags, esc(b.Properties.Cflags)...)
+ for _, include := range b.Properties.Local_include_dirs {
+ cflags = append(cflags, "-I"+android.PathForModuleSrc(ctx, include).String())
+ implicits = append(implicits, android.PathForModuleSrc(ctx, include))
+ }
+
+ bindgenFlags := defaultBindgenFlags
+ bindgenFlags = append(bindgenFlags, esc(b.Properties.Bindgen_flags)...)
+
+ wrapperFile := android.OptionalPathForModuleSrc(ctx, b.Properties.Wrapper_src)
+ if !wrapperFile.Valid() {
+ ctx.PropertyErrorf("wrapper_src", "invalid path to wrapper source")
+ }
+
+ outputFile := android.PathForModuleOut(ctx, b.BaseSourceProvider.getStem(ctx)+".rs")
+
+ var cmd, cmdDesc string
+ if b.Properties.Custom_bindgen != "" {
+ cmd = ctx.GetDirectDepWithTag(b.Properties.Custom_bindgen, customBindgenDepTag).(*Module).HostToolPath().String()
+ cmdDesc = b.Properties.Custom_bindgen
+ } else {
+ cmd = "$bindgenCmd"
+ cmdDesc = "bindgen"
+ }
+
+ ctx.Build(pctx, android.BuildParams{
+ Rule: bindgen,
+ Description: strings.Join([]string{cmdDesc, wrapperFile.Path().Rel()}, " "),
+ Output: outputFile,
+ Input: wrapperFile.Path(),
+ Implicits: implicits,
+ Args: map[string]string{
+ "cmd": cmd,
+ "flags": strings.Join(bindgenFlags, " "),
+ "cflags": strings.Join(cflags, " "),
+ },
+ })
+
+ b.BaseSourceProvider.OutputFile = outputFile
+ return outputFile
+}
+
+func (b *bindgenDecorator) SourceProviderProps() []interface{} {
+ return append(b.BaseSourceProvider.SourceProviderProps(),
+ &b.Properties)
+}
+
+// rust_bindgen generates Rust FFI bindings to C libraries using bindgen given a wrapper header as the primary input.
+// Bindgen has a number of flags to control the generated source, and additional flags can be passed to clang to ensure
+// the header and generated source is appropriately handled.
+func RustBindgenFactory() android.Module {
+ module, _ := NewRustBindgen(android.HostAndDeviceSupported)
+ return module.Init()
+}
+
+func RustBindgenHostFactory() android.Module {
+ module, _ := NewRustBindgen(android.HostSupported)
+ return module.Init()
+}
+
+func NewRustBindgen(hod android.HostOrDeviceSupported) (*Module, *bindgenDecorator) {
+ bindgen := &bindgenDecorator{
+ BaseSourceProvider: NewSourceProvider(),
+ Properties: BindgenProperties{},
+ }
+
+ module := NewSourceProviderModule(hod, bindgen, false)
+
+ return module, bindgen
+}
+
+func (b *bindgenDecorator) SourceProviderDeps(ctx DepsContext, deps Deps) Deps {
+ deps = b.BaseSourceProvider.SourceProviderDeps(ctx, deps)
+ if ctx.toolchain().Bionic() {
+ deps = bionicDeps(deps)
+ }
+
+ deps.SharedLibs = append(deps.SharedLibs, b.Properties.Shared_libs...)
+ deps.StaticLibs = append(deps.StaticLibs, b.Properties.Static_libs...)
+ return deps
+}
diff --git a/rust/bindgen_test.go b/rust/bindgen_test.go
new file mode 100644
index 000000000..191da9b11
--- /dev/null
+++ b/rust/bindgen_test.go
@@ -0,0 +1,84 @@
+// Copyright 2020 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package rust
+
+import (
+ "strings"
+ "testing"
+)
+
+func TestRustBindgen(t *testing.T) {
+ ctx := testRust(t, `
+ rust_bindgen {
+ name: "libbindgen",
+ wrapper_src: "src/any.h",
+ crate_name: "bindgen",
+ stem: "libbindgen",
+ source_stem: "bindings",
+ bindgen_flags: ["--bindgen-flag.*"],
+ cflags: ["--clang-flag()"],
+ shared_libs: ["libfoo_shared"],
+ static_libs: ["libfoo_static"],
+ }
+ cc_library_shared {
+ name: "libfoo_shared",
+ export_include_dirs: ["shared_include"],
+ }
+ cc_library_static {
+ name: "libfoo_static",
+ export_include_dirs: ["static_include"],
+ }
+ `)
+ libbindgen := ctx.ModuleForTests("libbindgen", "android_arm64_armv8-a").Output("bindings.rs")
+ // Ensure that the flags are present and escaped
+ if !strings.Contains(libbindgen.Args["flags"], "'--bindgen-flag.*'") {
+ t.Errorf("missing bindgen flags in rust_bindgen rule: flags %#v", libbindgen.Args["flags"])
+ }
+ if !strings.Contains(libbindgen.Args["cflags"], "'--clang-flag()'") {
+ t.Errorf("missing clang cflags in rust_bindgen rule: cflags %#v", libbindgen.Args["cflags"])
+ }
+ if !strings.Contains(libbindgen.Args["cflags"], "-Ishared_include") {
+ t.Errorf("missing shared_libs exported includes in rust_bindgen rule: cflags %#v", libbindgen.Args["cflags"])
+ }
+ if !strings.Contains(libbindgen.Args["cflags"], "-Istatic_include") {
+ t.Errorf("missing static_libs exported includes in rust_bindgen rule: cflags %#v", libbindgen.Args["cflags"])
+ }
+}
+
+func TestRustBindgenCustomBindgen(t *testing.T) {
+ ctx := testRust(t, `
+ rust_bindgen {
+ name: "libbindgen",
+ wrapper_src: "src/any.h",
+ crate_name: "bindgen",
+ stem: "libbindgen",
+ source_stem: "bindings",
+ custom_bindgen: "my_bindgen"
+ }
+ rust_binary_host {
+ name: "my_bindgen",
+ srcs: ["foo.rs"],
+ }
+ `)
+
+ libbindgen := ctx.ModuleForTests("libbindgen", "android_arm64_armv8-a").Output("bindings.rs")
+
+ // The rule description should contain the custom binary name rather than bindgen, so checking the description
+ // should be sufficient.
+ if !strings.Contains(libbindgen.Description, "my_bindgen") {
+ t.Errorf("Custom bindgen binary %s not used for libbindgen: rule description %#v", "my_bindgen",
+ libbindgen.Description)
+ }
+}
diff --git a/rust/builder.go b/rust/builder.go
index 7f94bb514..45cd268e9 100644
--- a/rust/builder.go
+++ b/rust/builder.go
@@ -28,7 +28,7 @@ var (
_ = pctx.SourcePathVariable("rustcCmd", "${config.RustBin}/rustc")
rustc = pctx.AndroidStaticRule("rustc",
blueprint.RuleParams{
- Command: "$rustcCmd " +
+ Command: "$envVars $rustcCmd " +
"-C linker=${config.RustLinker} " +
"-C link-args=\"${crtBegin} ${config.RustLinkerArgs} ${linkFlags} ${crtEnd}\" " +
"--emit link -o $out --emit dep-info=$out.d $in ${libFlags} $rustcFlags",
@@ -37,19 +37,19 @@ var (
Deps: blueprint.DepsGCC,
Depfile: "$out.d",
},
- "rustcFlags", "linkFlags", "libFlags", "crtBegin", "crtEnd")
+ "rustcFlags", "linkFlags", "libFlags", "crtBegin", "crtEnd", "envVars")
_ = pctx.SourcePathVariable("clippyCmd", "${config.RustBin}/clippy-driver")
clippyDriver = pctx.AndroidStaticRule("clippy",
blueprint.RuleParams{
- Command: "$clippyCmd " +
+ Command: "$envVars $clippyCmd " +
// Because clippy-driver uses rustc as backend, we need to have some output even during the linting.
// Use the metadata output as it has the smallest footprint.
"--emit metadata -o $out $in ${libFlags} " +
"$rustcFlags $clippyFlags",
CommandDeps: []string{"$clippyCmd"},
},
- "rustcFlags", "libFlags", "clippyFlags")
+ "rustcFlags", "libFlags", "clippyFlags", "envVars")
zip = pctx.AndroidStaticRule("zip",
blueprint.RuleParams{
@@ -58,6 +58,14 @@ var (
Rspfile: "$out.rsp",
RspfileContent: "$in",
})
+
+ cp = pctx.AndroidStaticRule("cp",
+ blueprint.RuleParams{
+ Command: "cp `cat $outDir.rsp` $outDir",
+ Rspfile: "${outDir}.rsp",
+ RspfileContent: "$in",
+ },
+ "outDir")
)
type buildOutput struct {
@@ -116,6 +124,7 @@ func transformSrctoCrate(ctx ModuleContext, main android.Path, deps PathDeps, fl
var inputs android.Paths
var implicits android.Paths
+ var envVars []string
var output buildOutput
var libFlags, rustcFlags, linkFlags []string
var implicitOutputs android.WritablePaths
@@ -166,7 +175,7 @@ func transformSrctoCrate(ctx ModuleContext, main android.Path, deps PathDeps, fl
implicits = append(implicits, rustLibsToPaths(deps.ProcMacros)...)
implicits = append(implicits, deps.StaticLibs...)
implicits = append(implicits, deps.SharedLibs...)
- implicits = append(implicits, deps.SrcDeps...)
+
if deps.CrtBegin.Valid() {
implicits = append(implicits, deps.CrtBegin.Path(), deps.CrtEnd.Path())
}
@@ -190,6 +199,32 @@ func transformSrctoCrate(ctx ModuleContext, main android.Path, deps PathDeps, fl
output.coverageFile = gcnoFile
}
+ if len(deps.SrcDeps) > 0 {
+ genSubDir := "out/"
+ moduleGenDir := android.PathForModuleOut(ctx, genSubDir)
+ var outputs android.WritablePaths
+
+ for _, genSrc := range deps.SrcDeps {
+ if android.SuffixInList(outputs.Strings(), genSubDir+genSrc.Base()) {
+ ctx.PropertyErrorf("srcs",
+ "multiple source providers generate the same filename output: "+genSrc.Base())
+ }
+ outputs = append(outputs, android.PathForModuleOut(ctx, genSubDir+genSrc.Base()))
+ }
+
+ ctx.Build(pctx, android.BuildParams{
+ Rule: cp,
+ Description: "cp " + moduleGenDir.Rel(),
+ Outputs: outputs,
+ Inputs: deps.SrcDeps,
+ Args: map[string]string{
+ "outDir": moduleGenDir.String(),
+ },
+ })
+ implicits = append(implicits, outputs.Paths()...)
+ envVars = append(envVars, "OUT_DIR=$$PWD/"+moduleGenDir.String())
+ }
+
if flags.Clippy {
clippyFile := android.PathForModuleOut(ctx, outputFile.Base()+".clippy")
ctx.Build(pctx, android.BuildParams{
@@ -203,6 +238,7 @@ func transformSrctoCrate(ctx ModuleContext, main android.Path, deps PathDeps, fl
"rustcFlags": strings.Join(rustcFlags, " "),
"libFlags": strings.Join(libFlags, " "),
"clippyFlags": strings.Join(flags.ClippyFlags, " "),
+ "envVars": strings.Join(envVars, " "),
},
})
// Declare the clippy build as an implicit dependency of the original crate.
@@ -222,6 +258,7 @@ func transformSrctoCrate(ctx ModuleContext, main android.Path, deps PathDeps, fl
"libFlags": strings.Join(libFlags, " "),
"crtBegin": deps.CrtBegin.String(),
"crtEnd": deps.CrtEnd.String(),
+ "envVars": strings.Join(envVars, " "),
},
})
diff --git a/rust/builder_test.go b/rust/builder_test.go
new file mode 100644
index 000000000..5c11cb7b5
--- /dev/null
+++ b/rust/builder_test.go
@@ -0,0 +1,42 @@
+// Copyright 2020 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package rust
+
+import "testing"
+
+func TestSourceProviderCollision(t *testing.T) {
+ testRustError(t, "multiple source providers generate the same filename output: bindings.rs", `
+ rust_binary {
+ name: "source_collider",
+ srcs: [
+ "foo.rs",
+ ":libbindings1",
+ ":libbindings2",
+ ],
+ }
+ rust_bindgen {
+ name: "libbindings1",
+ source_stem: "bindings",
+ crate_name: "bindings1",
+ wrapper_src: "src/any.h",
+ }
+ rust_bindgen {
+ name: "libbindings2",
+ source_stem: "bindings",
+ crate_name: "bindings2",
+ wrapper_src: "src/any.h",
+ }
+ `)
+}
diff --git a/rust/clippy.go b/rust/clippy.go
index e1f567d99..6f0ed7ff1 100644
--- a/rust/clippy.go
+++ b/rust/clippy.go
@@ -19,8 +19,14 @@ import (
)
type ClippyProperties struct {
- // whether to run clippy.
- Clippy *bool
+ // name of the lint set that should be used to validate this module.
+ //
+ // Possible values are "default" (for using a sensible set of lints
+ // depending on the module's location), "android" (for the strictest
+ // lint set that applies to all Android platform code), "vendor" (for a
+ // relaxed set) and "none" (to disable the execution of clippy). The
+ // default value is "default". See also the `lints` property.
+ Clippy_lints *string
}
type clippy struct {
@@ -32,10 +38,10 @@ func (c *clippy) props() []interface{} {
}
func (c *clippy) flags(ctx ModuleContext, flags Flags, deps PathDeps) (Flags, PathDeps) {
- if c.Properties.Clippy != nil && !*c.Properties.Clippy {
- return flags, deps
+ enabled, lints, err := config.ClippyLintsForDir(ctx.ModuleDir(), c.Properties.Clippy_lints)
+ if err != nil {
+ ctx.PropertyErrorf("clippy_lints", err.Error())
}
- enabled, lints := config.ClippyLintsForDir(ctx.ModuleDir())
flags.Clippy = enabled
flags.ClippyFlags = append(flags.ClippyFlags, lints)
return flags, deps
diff --git a/rust/clippy_test.go b/rust/clippy_test.go
index 314417362..7815aab9d 100644
--- a/rust/clippy_test.go
+++ b/rust/clippy_test.go
@@ -16,31 +16,77 @@ package rust
import (
"testing"
+
+ "android/soong/android"
)
func TestClippy(t *testing.T) {
- ctx := testRust(t, `
+
+ bp := `
+ // foo uses the default value of clippy_lints
rust_library {
name: "libfoo",
srcs: ["foo.rs"],
crate_name: "foo",
}
+ // bar forces the use of the "android" lint set
+ rust_library {
+ name: "libbar",
+ srcs: ["foo.rs"],
+ crate_name: "bar",
+ clippy_lints: "android",
+ }
+ // foobar explicitly disable clippy
rust_library {
name: "libfoobar",
srcs: ["foo.rs"],
crate_name: "foobar",
- clippy: false,
- }`)
+ clippy_lints: "none",
+ }`
+
+ bp = bp + GatherRequiredDepsForTest()
- ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_dylib").Output("libfoo.dylib.so")
- fooClippy := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_dylib").MaybeRule("clippy")
- if fooClippy.Rule.String() != "android/soong/rust.clippy" {
- t.Errorf("Clippy output (default) for libfoo was not generated: %+v", fooClippy)
+ fs := map[string][]byte{
+ // Reuse the same blueprint file for subdirectories.
+ "external/Android.bp": []byte(bp),
+ "hardware/Android.bp": []byte(bp),
}
- ctx.ModuleForTests("libfoobar", "android_arm64_armv8-a_dylib").Output("libfoobar.dylib.so")
- foobarClippy := ctx.ModuleForTests("libfoobar", "android_arm64_armv8-a_dylib").MaybeRule("clippy")
- if foobarClippy.Rule != nil {
- t.Errorf("Clippy output for libfoobar is not empty")
+ var clippyLintTests = []struct {
+ modulePath string
+ fooFlags string
+ }{
+ {"", "${config.ClippyDefaultLints}"},
+ {"external/", ""},
+ {"hardware/", "${config.ClippyVendorLints}"},
+ }
+
+ for _, tc := range clippyLintTests {
+ t.Run("path="+tc.modulePath, func(t *testing.T) {
+
+ config := android.TestArchConfig(buildDir, nil, bp, fs)
+ ctx := CreateTestContext()
+ ctx.Register(config)
+ _, errs := ctx.ParseFileList(".", []string{tc.modulePath + "Android.bp"})
+ android.FailIfErrored(t, errs)
+ _, errs = ctx.PrepareBuildActions(config)
+ android.FailIfErrored(t, errs)
+
+ r := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_dylib").MaybeRule("clippy")
+ if r.Args["clippyFlags"] != tc.fooFlags {
+ t.Errorf("Incorrect flags for libfoo: %q, want %q", r.Args["clippyFlags"], tc.fooFlags)
+ }
+
+ r = ctx.ModuleForTests("libbar", "android_arm64_armv8-a_dylib").MaybeRule("clippy")
+ if r.Args["clippyFlags"] != "${config.ClippyDefaultLints}" {
+ t.Errorf("Incorrect flags for libbar: %q, want %q", r.Args["clippyFlags"], "${config.ClippyDefaultLints}")
+ }
+
+ r = ctx.ModuleForTests("libfoobar", "android_arm64_armv8-a_dylib").MaybeRule("clippy")
+ if r.Rule != nil {
+ t.Errorf("libfoobar is setup to use clippy when explicitly disabled: clippyFlags=%q", r.Args["clippyFlags"])
+ }
+
+ })
}
}
diff --git a/rust/compiler.go b/rust/compiler.go
index c20179bd0..2600f4d0f 100644
--- a/rust/compiler.go
+++ b/rust/compiler.go
@@ -24,7 +24,7 @@ import (
"android/soong/rust/config"
)
-func getEdition(compiler *baseCompiler) string {
+func (compiler *baseCompiler) edition() string {
return proptools.StringDefault(compiler.Properties.Edition, config.DefaultEdition)
}
@@ -32,6 +32,10 @@ func (compiler *baseCompiler) setNoStdlibs() {
compiler.Properties.No_stdlibs = proptools.BoolPtr(true)
}
+func (compiler *baseCompiler) disableLints() {
+ compiler.Properties.Lints = proptools.StringPtr("none")
+}
+
func NewBaseCompiler(dir, dir64 string, location installLocation) *baseCompiler {
return &baseCompiler{
Properties: BaseCompilerProperties{},
@@ -46,14 +50,22 @@ type installLocation int
const (
InstallInSystem installLocation = 0
InstallInData = iota
+
+ incorrectSourcesError = "srcs can only contain one path for a rust file and source providers prefixed by \":\""
)
type BaseCompilerProperties struct {
// path to the source file that is the main entry point of the program (e.g. main.rs or lib.rs)
Srcs []string `android:"path,arch_variant"`
- // whether to suppress the standard lint flags - default to false
- No_lint *bool
+ // name of the lint set that should be used to validate this module.
+ //
+ // Possible values are "default" (for using a sensible set of lints
+ // depending on the module's location), "android" (for the strictest
+ // lint set that applies to all Android platform code), "vendor" (for
+ // a relaxed set) and "none" (for ignoring all lint warnings and
+ // errors). The default value is "default".
+ Lints *string
// flags to pass to rustc
Flags []string `android:"path,arch_variant"`
@@ -79,7 +91,10 @@ type BaseCompilerProperties struct {
// list of C static library dependencies
Static_libs []string `android:"arch_variant"`
- // crate name, required for libraries. This must be the expected extern crate name used in source
+ // crate name, required for modules which produce Rust libraries: rust_library, rust_ffi and SourceProvider
+ // modules which create library variants (rust_bindgen). This must be the expected extern crate name used in
+ // source, and is required to conform to an enforced format matching library output files (if the output file is
+ // lib<someName><suffix>, the crate_name property must be <someName>).
Crate_name string `android:"arch_variant"`
// list of features to enable for this crate
@@ -118,10 +133,22 @@ type baseCompiler struct {
distFile android.OptionalPath
}
+func (compiler *baseCompiler) Disabled() bool {
+ return false
+}
+
+func (compiler *baseCompiler) SetDisabled() {
+ panic("baseCompiler does not implement SetDisabled()")
+}
+
func (compiler *baseCompiler) coverageOutputZipPath() android.OptionalPath {
panic("baseCompiler does not implement coverageOutputZipPath()")
}
+func (compiler *baseCompiler) static() bool {
+ return false
+}
+
var _ compiler = (*baseCompiler)(nil)
func (compiler *baseCompiler) inData() bool {
@@ -142,12 +169,14 @@ func (compiler *baseCompiler) featuresToFlags(features []string) []string {
func (compiler *baseCompiler) compilerFlags(ctx ModuleContext, flags Flags) Flags {
- if !Bool(compiler.Properties.No_lint) {
- flags.RustFlags = append(flags.RustFlags, config.RustcLintsForDir(ctx.ModuleDir()))
+ lintFlags, err := config.RustcLintsForDir(ctx.ModuleDir(), compiler.Properties.Lints)
+ if err != nil {
+ ctx.PropertyErrorf("lints", err.Error())
}
+ flags.RustFlags = append(flags.RustFlags, lintFlags)
flags.RustFlags = append(flags.RustFlags, compiler.Properties.Flags...)
flags.RustFlags = append(flags.RustFlags, compiler.featuresToFlags(compiler.Properties.Features)...)
- flags.RustFlags = append(flags.RustFlags, "--edition="+getEdition(compiler))
+ flags.RustFlags = append(flags.RustFlags, "--edition="+compiler.edition())
flags.LinkFlags = append(flags.LinkFlags, compiler.Properties.Ld_flags...)
flags.GlobalRustFlags = append(flags.GlobalRustFlags, config.GlobalRustFlags...)
flags.GlobalRustFlags = append(flags.GlobalRustFlags, ctx.toolchain().ToolchainRustFlags())
@@ -191,13 +220,21 @@ func (compiler *baseCompiler) compilerDeps(ctx DepsContext, deps Deps) Deps {
stdlib = stdlib + "_" + ctx.toolchain().RustTriple()
}
- deps.Rustlibs = append(deps.Rustlibs, stdlib)
+ // For devices, we always link stdlibs in as dylibs except for ffi static libraries.
+ // (rustc does not support linking libstd as a dylib for ffi static libraries)
+ if ctx.Host() {
+ deps.Rustlibs = append(deps.Rustlibs, stdlib)
+ } else if ctx.RustModule().compiler.static() {
+ deps.Rlibs = append(deps.Rlibs, stdlib)
+ } else {
+ deps.Dylibs = append(deps.Dylibs, stdlib)
+ }
}
}
return deps
}
-func (compiler *baseCompiler) bionicDeps(ctx DepsContext, deps Deps) Deps {
+func bionicDeps(deps Deps) Deps {
deps.SharedLibs = append(deps.SharedLibs, "liblog")
deps.SharedLibs = append(deps.SharedLibs, "libc")
deps.SharedLibs = append(deps.SharedLibs, "libm")
@@ -253,6 +290,7 @@ func (compiler *baseCompiler) relativeInstallPath() string {
return String(compiler.Properties.Relative_install_path)
}
+// Returns the Path for the main source file along with Paths for generated source files from modules listed in srcs.
func srcPathFromModuleSrcs(ctx ModuleContext, srcs []string) (android.Path, android.Paths) {
// The srcs can contain strings with prefix ":".
// They are dependent modules of this module, with android.SourceDepTag.
@@ -266,11 +304,11 @@ func srcPathFromModuleSrcs(ctx ModuleContext, srcs []string) (android.Path, andr
}
}
if numSrcs != 1 {
- ctx.PropertyErrorf("srcs", "srcs can only contain one path for a rust file")
+ ctx.PropertyErrorf("srcs", incorrectSourcesError)
}
if srcIndex != 0 {
ctx.PropertyErrorf("srcs", "main source file must be the first in srcs")
}
paths := android.PathsForModuleSrc(ctx, srcs)
- return paths[srcIndex], paths
+ return paths[srcIndex], paths[1:]
}
diff --git a/rust/compiler_test.go b/rust/compiler_test.go
index 58ca52a0c..56a8ef8ac 100644
--- a/rust/compiler_test.go
+++ b/rust/compiler_test.go
@@ -17,6 +17,8 @@ package rust
import (
"strings"
"testing"
+
+ "android/soong/android"
)
// Test that feature flags are being correctly generated.
@@ -43,7 +45,7 @@ func TestFeaturesToFlags(t *testing.T) {
// Test that we reject multiple source files.
func TestEnforceSingleSourceFile(t *testing.T) {
- singleSrcError := "srcs can only contain one path for a rust file"
+ singleSrcError := "srcs can only contain one path for a rust file and source providers prefixed by \":\""
// Test libraries
testRustError(t, singleSrcError, `
@@ -104,3 +106,101 @@ func TestInstallDir(t *testing.T) {
t.Fatalf("unexpected install path for binary: %#v", install_path_bin)
}
}
+
+func TestLints(t *testing.T) {
+
+ bp := `
+ // foo uses the default value of lints
+ rust_library {
+ name: "libfoo",
+ srcs: ["foo.rs"],
+ crate_name: "foo",
+ }
+ // bar forces the use of the "android" lint set
+ rust_library {
+ name: "libbar",
+ srcs: ["foo.rs"],
+ crate_name: "bar",
+ lints: "android",
+ }
+ // foobar explicitly disable all lints
+ rust_library {
+ name: "libfoobar",
+ srcs: ["foo.rs"],
+ crate_name: "foobar",
+ lints: "none",
+ }`
+
+ bp = bp + GatherRequiredDepsForTest()
+
+ fs := map[string][]byte{
+ // Reuse the same blueprint file for subdirectories.
+ "external/Android.bp": []byte(bp),
+ "hardware/Android.bp": []byte(bp),
+ }
+
+ var lintTests = []struct {
+ modulePath string
+ fooFlags string
+ }{
+ {"", "${config.RustDefaultLints}"},
+ {"external/", "${config.RustAllowAllLints}"},
+ {"hardware/", "${config.RustVendorLints}"},
+ }
+
+ for _, tc := range lintTests {
+ t.Run("path="+tc.modulePath, func(t *testing.T) {
+
+ config := android.TestArchConfig(buildDir, nil, bp, fs)
+ ctx := CreateTestContext()
+ ctx.Register(config)
+ _, errs := ctx.ParseFileList(".", []string{tc.modulePath + "Android.bp"})
+ android.FailIfErrored(t, errs)
+ _, errs = ctx.PrepareBuildActions(config)
+ android.FailIfErrored(t, errs)
+
+ r := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_dylib").MaybeRule("rustc")
+ if !strings.Contains(r.Args["rustcFlags"], tc.fooFlags) {
+ t.Errorf("Incorrect flags for libfoo: %q, want %q", r.Args["rustcFlags"], tc.fooFlags)
+ }
+
+ r = ctx.ModuleForTests("libbar", "android_arm64_armv8-a_dylib").MaybeRule("rustc")
+ if !strings.Contains(r.Args["rustcFlags"], "${config.RustDefaultLints}") {
+ t.Errorf("Incorrect flags for libbar: %q, want %q", r.Args["rustcFlags"], "${config.RustDefaultLints}")
+ }
+
+ r = ctx.ModuleForTests("libfoobar", "android_arm64_armv8-a_dylib").MaybeRule("rustc")
+ if !strings.Contains(r.Args["rustcFlags"], "${config.RustAllowAllLints}") {
+ t.Errorf("Incorrect flags for libfoobar: %q, want %q", r.Args["rustcFlags"], "${config.RustAllowAllLints}")
+ }
+
+ })
+ }
+}
+
+// Test that devices are linking the stdlib dynamically
+func TestStdDeviceLinkage(t *testing.T) {
+ ctx := testRust(t, `
+ rust_binary {
+ name: "fizz",
+ srcs: ["foo.rs"],
+ }
+ rust_library {
+ name: "libfoo",
+ srcs: ["foo.rs"],
+ crate_name: "foo",
+ }`)
+ fizz := ctx.ModuleForTests("fizz", "android_arm64_armv8-a").Module().(*Module)
+ fooRlib := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_rlib").Module().(*Module)
+ fooDylib := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_dylib").Module().(*Module)
+
+ if !android.InList("libstd", fizz.Properties.AndroidMkDylibs) {
+ t.Errorf("libstd is not linked dynamically for device binaries")
+ }
+ if !android.InList("libstd", fooRlib.Properties.AndroidMkDylibs) {
+ t.Errorf("libstd is not linked dynamically for rlibs")
+ }
+ if !android.InList("libstd", fooDylib.Properties.AndroidMkDylibs) {
+ t.Errorf("libstd is not linked dynamically for dylibs")
+ }
+}
diff --git a/rust/config/allowed_list.go b/rust/config/allowed_list.go
index 0204cd2e7..62d469e4f 100644
--- a/rust/config/allowed_list.go
+++ b/rust/config/allowed_list.go
@@ -6,7 +6,11 @@ var (
"external/rust",
"external/crosvm",
"external/adhd",
+ "frameworks/native/libs/binder/rust",
"prebuilts/rust",
+ "system/extras/profcollectd",
+ "system/security",
+ "system/tools/aidl",
}
RustModuleTypes = []string{
diff --git a/rust/config/global.go b/rust/config/global.go
index 2020f461d..97de6761b 100644
--- a/rust/config/global.go
+++ b/rust/config/global.go
@@ -24,7 +24,7 @@ import (
var pctx = android.NewPackageContext("android/soong/rust/config")
var (
- RustDefaultVersion = "1.44.0"
+ RustDefaultVersion = "1.45.2"
RustDefaultBase = "prebuilts/rust/"
DefaultEdition = "2018"
Stdlibs = []string{
diff --git a/rust/config/lints.go b/rust/config/lints.go
index 529d0942f..06bb668d1 100644
--- a/rust/config/lints.go
+++ b/rust/config/lints.go
@@ -15,6 +15,7 @@
package config
import (
+ "fmt"
"strings"
"android/soong/android"
@@ -24,18 +25,21 @@ import (
// The Android build system tries to avoid reporting warnings during the build.
// Therefore, by default, we upgrade warnings to denials. For some of these
// lints, an allow exception is setup, using the variables below.
-// There are different default lints depending on the repository location (see
-// DefaultLocalClippyChecks).
+//
// The lints are split into two categories. The first one contains the built-in
// lints (https://doc.rust-lang.org/rustc/lints/index.html). The second is
// specific to Clippy lints (https://rust-lang.github.io/rust-clippy/master/).
//
-// When developing a module, it is possible to use the `no_lint` property to
-// disable the built-in lints configuration. It is also possible to set
-// `clippy` to false to disable the clippy verification. Expect some
-// questioning during review if you enable one of these options. For external/
-// code, if you need to use them, it is likely a bug. Otherwise, it may be
-// useful to add an exception (that is, move a lint from deny to allow).
+// For both categories, there are 3 levels of linting possible:
+// - "android", for the strictest lints that applies to all Android platform code.
+// - "vendor", for relaxed rules.
+// - "none", to disable the linting.
+// There is a fourth option ("default") which automatically selects the linting level
+// based on the module's location. See defaultLintSetForPath.
+//
+// When developing a module, you may set `lints = "none"` and `clippy_lints =
+// "none"` to disable all the linting. Expect some questioning during code review
+// if you enable one of these options.
var (
// Default Rust lints that applies to Google-authored modules.
defaultRustcLints = []string{
@@ -102,13 +106,6 @@ func init() {
pctx.StaticVariable("RustAllowAllLints", strings.Join(allowAllLints, " "))
}
-type PathBasedClippyConfig struct {
- PathPrefix string
- RustcConfig string
- ClippyEnabled bool
- ClippyConfig string
-}
-
const noLint = ""
const rustcDefault = "${config.RustDefaultLints}"
const rustcVendor = "${config.RustVendorLints}"
@@ -116,35 +113,78 @@ const rustcAllowAll = "${config.RustAllowAllLints}"
const clippyDefault = "${config.ClippyDefaultLints}"
const clippyVendor = "${config.ClippyVendorLints}"
-// This is a map of local path prefixes to a set of parameters for the linting:
-// - a string for the lints to apply to rustc.
-// - a boolean to indicate if clippy should be executed.
-// - a string for the lints to apply to clippy.
-// The first entry matching will be used.
-var DefaultLocalClippyChecks = []PathBasedClippyConfig{
- {"external/", rustcAllowAll, false, noLint},
- {"hardware/", rustcVendor, true, clippyVendor},
- {"prebuilts/", rustcAllowAll, false, noLint},
- {"vendor/google", rustcDefault, true, clippyDefault},
- {"vendor/", rustcVendor, true, clippyVendor},
+// lintConfig defines a set of lints and clippy configuration.
+type lintConfig struct {
+ rustcConfig string // for the lints to apply to rustc.
+ clippyEnabled bool // to indicate if clippy should be executed.
+ clippyConfig string // for the lints to apply to clippy.
+}
+
+const (
+ androidLints = "android"
+ vendorLints = "vendor"
+ noneLints = "none"
+)
+
+// lintSets defines the categories of linting for Android and their mapping to lintConfigs.
+var lintSets = map[string]lintConfig{
+ androidLints: {rustcDefault, true, clippyDefault},
+ vendorLints: {rustcVendor, true, clippyVendor},
+ noneLints: {rustcAllowAll, false, noLint},
+}
+
+type pathLintSet struct {
+ prefix string
+ set string
+}
+
+// This is a map of local path prefixes to a lint set. The first entry
+// matching will be used. If no entry matches, androidLints ("android") will be
+// used.
+var defaultLintSetForPath = []pathLintSet{
+ {"external", noneLints},
+ {"hardware", vendorLints},
+ {"prebuilts", noneLints},
+ {"vendor/google", androidLints},
+ {"vendor", vendorLints},
}
// ClippyLintsForDir returns a boolean if Clippy should be executed and if so, the lints to be used.
-func ClippyLintsForDir(dir string) (bool, string) {
- for _, pathCheck := range DefaultLocalClippyChecks {
- if strings.HasPrefix(dir, pathCheck.PathPrefix) {
- return pathCheck.ClippyEnabled, pathCheck.ClippyConfig
+func ClippyLintsForDir(dir string, clippyLintsProperty *string) (bool, string, error) {
+ if clippyLintsProperty != nil {
+ set, ok := lintSets[*clippyLintsProperty]
+ if ok {
+ return set.clippyEnabled, set.clippyConfig, nil
+ }
+ if *clippyLintsProperty != "default" {
+ return false, "", fmt.Errorf("unknown value for `clippy_lints`: %v, valid options are: default, android, vendor or none", *clippyLintsProperty)
+ }
+ }
+ for _, p := range defaultLintSetForPath {
+ if strings.HasPrefix(dir, p.prefix) {
+ setConfig := lintSets[p.set]
+ return setConfig.clippyEnabled, setConfig.clippyConfig, nil
}
}
- return true, clippyDefault
+ return true, clippyDefault, nil
}
// RustcLintsForDir returns the standard lints to be used for a repository.
-func RustcLintsForDir(dir string) string {
- for _, pathCheck := range DefaultLocalClippyChecks {
- if strings.HasPrefix(dir, pathCheck.PathPrefix) {
- return pathCheck.RustcConfig
+func RustcLintsForDir(dir string, lintProperty *string) (string, error) {
+ if lintProperty != nil {
+ set, ok := lintSets[*lintProperty]
+ if ok {
+ return set.rustcConfig, nil
+ }
+ if *lintProperty != "default" {
+ return "", fmt.Errorf("unknown value for `lints`: %v, valid options are: default, android, vendor or none", *lintProperty)
+ }
+
+ }
+ for _, p := range defaultLintSetForPath {
+ if strings.HasPrefix(dir, p.prefix) {
+ return lintSets[p.set].rustcConfig, nil
}
}
- return rustcDefault
+ return rustcDefault, nil
}
diff --git a/rust/coverage.go b/rust/coverage.go
index 223ba4f19..26375f507 100644
--- a/rust/coverage.go
+++ b/rust/coverage.go
@@ -53,7 +53,7 @@ func (cov *coverage) flags(ctx ModuleContext, flags Flags, deps PathDeps) (Flags
flags.Coverage = true
coverage := ctx.GetDirectDepWithTag(CovLibraryName, cc.CoverageDepTag).(cc.LinkableInterface)
flags.RustFlags = append(flags.RustFlags,
- "-Z profile", "-g", "-C opt-level=0", "-C link-dead-code", "-Z no-landing-pads")
+ "-Z profile", "-g", "-C opt-level=0", "-C link-dead-code")
flags.LinkFlags = append(flags.LinkFlags,
"--coverage", "-g", coverage.OutputFile().Path().String(), "-Wl,--wrap,getenv")
deps.StaticLibs = append(deps.StaticLibs, coverage.OutputFile().Path())
diff --git a/rust/coverage_test.go b/rust/coverage_test.go
index 357c2e8b1..73673d035 100644
--- a/rust/coverage_test.go
+++ b/rust/coverage_test.go
@@ -56,7 +56,7 @@ func TestCoverageFlags(t *testing.T) {
fizzCov := ctx.ModuleForTests("fizz_cov", "android_arm64_armv8-a_cov").Rule("rustc")
buzzNoCov := ctx.ModuleForTests("buzzNoCov", "android_arm64_armv8-a").Rule("rustc")
- rustcCoverageFlags := []string{"-Z profile", " -g ", "-C opt-level=0", "-C link-dead-code", "-Z no-landing-pads"}
+ rustcCoverageFlags := []string{"-Z profile", " -g ", "-C opt-level=0", "-C link-dead-code"}
for _, flag := range rustcCoverageFlags {
missingErrorStr := "missing rustc flag '%s' for '%s' module with coverage enabled; rustcFlags: %#v"
containsErrorStr := "contains rustc flag '%s' for '%s' module with coverage disabled; rustcFlags: %#v"
diff --git a/rust/library.go b/rust/library.go
index d718eb897..450c9d429 100644
--- a/rust/library.go
+++ b/rust/library.go
@@ -69,6 +69,10 @@ type LibraryMutatedProperties struct {
VariantIsShared bool `blueprint:"mutated"`
// This variant is a static library
VariantIsStatic bool `blueprint:"mutated"`
+
+ // This variant is disabled and should not be compiled
+ // (used for SourceProvider variants that produce only source)
+ VariantIsDisabled bool `blueprint:"mutated"`
}
type libraryDecorator struct {
@@ -78,6 +82,7 @@ type libraryDecorator struct {
Properties LibraryCompilerProperties
MutatedProperties LibraryMutatedProperties
includeDirs android.Paths
+ sourceProvider SourceProvider
}
type libraryInterface interface {
@@ -171,13 +176,13 @@ func (library *libraryDecorator) setStatic() {
library.MutatedProperties.VariantIsDylib = false
}
-func (library *libraryDecorator) autoDep() autoDep {
+func (library *libraryDecorator) autoDep(ctx BaseModuleContext) autoDep {
if library.rlib() || library.static() {
return rlibAutoDep
} else if library.dylib() || library.shared() {
return dylibAutoDep
} else {
- return rlibAutoDep
+ panic("autoDep called on library" + ctx.ModuleName() + "that has no enabled variants.")
}
}
@@ -340,7 +345,7 @@ func (library *libraryDecorator) compilerDeps(ctx DepsContext, deps Deps) Deps {
deps = library.baseCompiler.compilerDeps(ctx, deps)
if ctx.toolchain().Bionic() && (library.dylib() || library.shared()) {
- deps = library.baseCompiler.bionicDeps(ctx, deps)
+ deps = bionicDeps(deps)
deps.CrtBegin = "crtbegin_so"
deps.CrtEnd = "crtend_so"
}
@@ -367,11 +372,16 @@ func (library *libraryDecorator) compilerFlags(ctx ModuleContext, flags Flags) F
func (library *libraryDecorator) compile(ctx ModuleContext, flags Flags, deps PathDeps) android.Path {
var outputFile android.WritablePath
+ var srcPath android.Path
- srcPath, paths := srcPathFromModuleSrcs(ctx, library.baseCompiler.Properties.Srcs)
- deps.SrcDeps = paths
+ if library.sourceProvider != nil {
+ srcPath = library.sourceProvider.Srcs()[0]
+ } else {
+ srcPath, _ = srcPathFromModuleSrcs(ctx, library.baseCompiler.Properties.Srcs)
+ }
flags.RustFlags = append(flags.RustFlags, deps.depFlags...)
+ flags.LinkFlags = append(flags.LinkFlags, deps.linkObjects...)
if library.dylib() {
// We need prefer-dynamic for now to avoid linking in the static stdlib. See:
@@ -418,6 +428,7 @@ func (library *libraryDecorator) compile(ctx ModuleContext, flags Flags, deps Pa
if library.rlib() || library.dylib() {
library.exportLinkDirs(deps.linkDirs...)
library.exportDepFlags(deps.depFlags...)
+ library.exportLinkObjects(deps.linkObjects...)
}
library.unstrippedOutputFile = outputFile
@@ -431,6 +442,14 @@ func (library *libraryDecorator) getStem(ctx ModuleContext) string {
return stem + String(library.baseCompiler.Properties.Suffix)
}
+func (library *libraryDecorator) Disabled() bool {
+ return library.MutatedProperties.VariantIsDisabled
+}
+
+func (library *libraryDecorator) SetDisabled() {
+ library.MutatedProperties.VariantIsDisabled = true
+}
+
var validCrateName = regexp.MustCompile("[^a-zA-Z0-9_]+")
func validateLibraryStem(ctx BaseModuleContext, filename string, crate_name string) {
@@ -455,25 +474,35 @@ func LibraryMutator(mctx android.BottomUpMutatorContext) {
if m, ok := mctx.Module().(*Module); ok && m.compiler != nil {
switch library := m.compiler.(type) {
case libraryInterface:
-
- // We only build the rust library variants here. This assumes that
- // LinkageMutator runs first and there's an empty variant
- // if rust variants are required.
- if !library.static() && !library.shared() {
- if library.buildRlib() && library.buildDylib() {
- modules := mctx.CreateLocalVariations("rlib", "dylib")
- rlib := modules[0].(*Module)
- dylib := modules[1].(*Module)
-
- rlib.compiler.(libraryInterface).setRlib()
- dylib.compiler.(libraryInterface).setDylib()
- } else if library.buildRlib() {
- modules := mctx.CreateLocalVariations("rlib")
- modules[0].(*Module).compiler.(libraryInterface).setRlib()
- } else if library.buildDylib() {
- modules := mctx.CreateLocalVariations("dylib")
- modules[0].(*Module).compiler.(libraryInterface).setDylib()
+ if library.buildRlib() && library.buildDylib() {
+ variants := []string{"rlib", "dylib"}
+ if m.sourceProvider != nil {
+ variants = append(variants, "")
}
+ modules := mctx.CreateLocalVariations(variants...)
+
+ rlib := modules[0].(*Module)
+ dylib := modules[1].(*Module)
+ rlib.compiler.(libraryInterface).setRlib()
+ dylib.compiler.(libraryInterface).setDylib()
+
+ if m.sourceProvider != nil {
+ // This library is SourceProvider generated, so the non-library-producing
+ // variant needs to disable it's compiler and skip installation.
+ sourceProvider := modules[2].(*Module)
+ sourceProvider.compiler.SetDisabled()
+ }
+ } else if library.buildRlib() {
+ modules := mctx.CreateLocalVariations("rlib")
+ modules[0].(*Module).compiler.(libraryInterface).setRlib()
+ } else if library.buildDylib() {
+ modules := mctx.CreateLocalVariations("dylib")
+ modules[0].(*Module).compiler.(libraryInterface).setDylib()
+ }
+
+ if m.sourceProvider != nil {
+ // Alias the non-library variant to the empty-string variant.
+ mctx.AliasVariation("")
}
}
}
diff --git a/rust/library_test.go b/rust/library_test.go
index 8a91cf10f..0fd9e32f9 100644
--- a/rust/library_test.go
+++ b/rust/library_test.go
@@ -144,6 +144,22 @@ func TestSharedLibrary(t *testing.T) {
}
}
+func TestStaticLibraryLinkage(t *testing.T) {
+ ctx := testRust(t, `
+ rust_ffi_static {
+ name: "libfoo",
+ srcs: ["foo.rs"],
+ crate_name: "foo",
+ }`)
+
+ libfoo := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_static")
+
+ if !android.InList("libstd", libfoo.Module().(*Module).Properties.AndroidMkRlibs) {
+ t.Errorf("Static libstd rlib expected to be a dependency of Rust static libraries. Rlib deps are: %#v",
+ libfoo.Module().(*Module).Properties.AndroidMkDylibs)
+ }
+}
+
// Test that variants pull in the right type of rustlib autodep
func TestAutoDeps(t *testing.T) {
diff --git a/rust/prebuilt.go b/rust/prebuilt.go
index 3b4f40a55..3d081c113 100644
--- a/rust/prebuilt.go
+++ b/rust/prebuilt.go
@@ -96,7 +96,9 @@ func (prebuilt *prebuiltLibraryDecorator) compile(ctx ModuleContext, flags Flags
prebuilt.exportLinkDirs(android.PathsForModuleSrc(ctx, prebuilt.Properties.Link_dirs).Strings()...)
srcPath, paths := srcPathFromModuleSrcs(ctx, prebuilt.prebuiltSrcs())
- deps.SrcDeps = paths
+ if len(paths) > 0 {
+ ctx.PropertyErrorf("srcs", "prebuilt libraries can only have one entry in srcs (the prebuilt path)")
+ }
prebuilt.unstrippedOutputFile = srcPath
diff --git a/rust/proc_macro.go b/rust/proc_macro.go
index 49dbd8dc2..748879cc8 100644
--- a/rust/proc_macro.go
+++ b/rust/proc_macro.go
@@ -65,8 +65,7 @@ func (procMacro *procMacroDecorator) compile(ctx ModuleContext, flags Flags, dep
fileName := procMacro.getStem(ctx) + ctx.toolchain().ProcMacroSuffix()
outputFile := android.PathForModuleOut(ctx, fileName)
- srcPath, paths := srcPathFromModuleSrcs(ctx, procMacro.baseCompiler.Properties.Srcs)
- deps.SrcDeps = paths
+ srcPath, _ := srcPathFromModuleSrcs(ctx, procMacro.baseCompiler.Properties.Srcs)
procMacro.unstrippedOutputFile = outputFile
@@ -81,6 +80,6 @@ func (procMacro *procMacroDecorator) getStem(ctx ModuleContext) string {
return stem + String(procMacro.baseCompiler.Properties.Suffix)
}
-func (procMacro *procMacroDecorator) autoDep() autoDep {
+func (procMacro *procMacroDecorator) autoDep(ctx BaseModuleContext) autoDep {
return rlibAutoDep
}
diff --git a/rust/project_json.go b/rust/project_json.go
index a50e73a95..831047938 100644
--- a/rust/project_json.go
+++ b/rust/project_json.go
@@ -75,24 +75,23 @@ func mergeDependencies(ctx android.SingletonContext, project *rustProjectJson,
knownCrates map[string]crateInfo, module android.Module,
crate *rustProjectCrate, deps map[string]int) {
- //TODO(tweek): The stdlib dependencies do not appear here. We need to manually add them.
ctx.VisitDirectDeps(module, func(child android.Module) {
- childId, childName, ok := appendLibraryAndDeps(ctx, project, knownCrates, child)
+ childId, childCrateName, ok := appendLibraryAndDeps(ctx, project, knownCrates, child)
if !ok {
return
}
- if _, ok = deps[childName]; ok {
+ if _, ok = deps[ctx.ModuleName(child)]; ok {
return
}
- crate.Deps = append(crate.Deps, rustProjectDep{Crate: childId, Name: childName})
- deps[childName] = childId
+ crate.Deps = append(crate.Deps, rustProjectDep{Crate: childId, Name: childCrateName})
+ deps[ctx.ModuleName(child)] = childId
})
}
// appendLibraryAndDeps creates a rustProjectCrate for the module argument and
// appends it to the rustProjectJson struct. It visits the dependencies of the
// module depth-first. If the current module is already in knownCrates, its
-// its dependencies are merged. Returns a tuple (id, crate_name, ok).
+// dependencies are merged. Returns a tuple (id, crate_name, ok).
func appendLibraryAndDeps(ctx android.SingletonContext, project *rustProjectJson,
knownCrates map[string]crateInfo, module android.Module) (int, string, bool) {
rModule, ok := module.(*Module)
@@ -106,23 +105,28 @@ func appendLibraryAndDeps(ctx android.SingletonContext, project *rustProjectJson
if !ok {
return 0, "", false
}
+ moduleName := ctx.ModuleName(module)
crateName := rModule.CrateName()
- if cInfo, ok := knownCrates[crateName]; ok {
+ if cInfo, ok := knownCrates[moduleName]; ok {
// We have seen this crate already; merge any new dependencies.
crate := project.Crates[cInfo.ID]
mergeDependencies(ctx, project, knownCrates, module, &crate, cInfo.Deps)
+ project.Crates[cInfo.ID] = crate
return cInfo.ID, crateName, true
}
crate := rustProjectCrate{Deps: make([]rustProjectDep, 0), Cfgs: make([]string, 0)}
- src := rustLib.baseCompiler.Properties.Srcs[0]
- crate.RootModule = path.Join(ctx.ModuleDir(rModule), src)
- crate.Edition = getEdition(rustLib.baseCompiler)
+ srcs := rustLib.baseCompiler.Properties.Srcs
+ if len(srcs) == 0 {
+ return 0, "", false
+ }
+ crate.RootModule = path.Join(ctx.ModuleDir(rModule), srcs[0])
+ crate.Edition = rustLib.baseCompiler.edition()
deps := make(map[string]int)
mergeDependencies(ctx, project, knownCrates, module, &crate, deps)
id := len(project.Crates)
- knownCrates[crateName] = crateInfo{ID: id, Deps: deps}
+ knownCrates[moduleName] = crateInfo{ID: id, Deps: deps}
project.Crates = append(project.Crates, crate)
// rust-analyzer requires that all crates belong to at least one root:
// https://github.com/rust-analyzer/rust-analyzer/issues/4735.
diff --git a/rust/project_json_test.go b/rust/project_json_test.go
index 6786e72c7..85219404a 100644
--- a/rust/project_json_test.go
+++ b/rust/project_json_test.go
@@ -15,6 +15,7 @@
package rust
import (
+ "encoding/json"
"io/ioutil"
"path/filepath"
"testing"
@@ -23,20 +24,12 @@ import (
"android/soong/cc"
)
-func TestProjectJson(t *testing.T) {
- bp := `rust_library {
- name: "liba",
- srcs: ["src/lib.rs"],
- crate_name: "a"
- }` + GatherRequiredDepsForTest()
- env := map[string]string{"SOONG_GEN_RUST_PROJECT": "1"}
- fs := map[string][]byte{
- "foo.rs": nil,
- "src/lib.rs": nil,
- }
-
+// testProjectJson run the generation of rust-project.json. It returns the raw
+// content of the generated file.
+func testProjectJson(t *testing.T, bp string, fs map[string][]byte) []byte {
cc.GatherRequiredFilesForTest(fs)
+ env := map[string]string{"SOONG_GEN_RUST_PROJECT": "1"}
config := android.TestArchConfig(buildDir, env, bp, fs)
ctx := CreateTestContext()
ctx.Register(config)
@@ -48,8 +41,131 @@ func TestProjectJson(t *testing.T) {
// The JSON file is generated via WriteFileToOutputDir. Therefore, it
// won't appear in the Output of the TestingSingleton. Manually verify
// it exists.
- _, err := ioutil.ReadFile(filepath.Join(buildDir, "rust-project.json"))
+ content, err := ioutil.ReadFile(filepath.Join(buildDir, rustProjectJsonFileName))
if err != nil {
t.Errorf("rust-project.json has not been generated")
}
+ return content
+}
+
+// validateJsonCrates validates that content follows the basic structure of
+// rust-project.json. It returns the crates attribute if the validation
+// succeeded.
+// It uses an empty interface instead of relying on a defined structure to
+// avoid a strong dependency on our implementation.
+func validateJsonCrates(t *testing.T, rawContent []byte) []interface{} {
+ var content interface{}
+ err := json.Unmarshal(rawContent, &content)
+ if err != nil {
+ t.Errorf("Unable to parse the rust-project.json as JSON: %v", err)
+ }
+ root, ok := content.(map[string]interface{})
+ if !ok {
+ t.Errorf("Unexpected JSON format: %v", content)
+ }
+ if _, ok = root["crates"]; !ok {
+ t.Errorf("No crates attribute in rust-project.json: %v", root)
+ }
+ crates, ok := root["crates"].([]interface{})
+ if !ok {
+ t.Errorf("Unexpected crates format: %v", root["crates"])
+ }
+ return crates
+}
+
+func TestProjectJsonDep(t *testing.T) {
+ bp := `
+ rust_library {
+ name: "liba",
+ srcs: ["a/src/lib.rs"],
+ crate_name: "a"
+ }
+ rust_library {
+ name: "libb",
+ srcs: ["b/src/lib.rs"],
+ crate_name: "b",
+ rlibs: ["liba"],
+ }
+ ` + GatherRequiredDepsForTest()
+ fs := map[string][]byte{
+ "a/src/lib.rs": nil,
+ "b/src/lib.rs": nil,
+ }
+ jsonContent := testProjectJson(t, bp, fs)
+ validateJsonCrates(t, jsonContent)
+}
+
+func TestProjectJsonBindGen(t *testing.T) {
+ bp := `
+ rust_library {
+ name: "liba",
+ srcs: ["src/lib.rs"],
+ rlibs: ["libbindings"],
+ crate_name: "a"
+ }
+ rust_bindgen {
+ name: "libbindings",
+ crate_name: "bindings",
+ source_stem: "bindings",
+ host_supported: true,
+ wrapper_src: "src/any.h",
+ }
+ ` + GatherRequiredDepsForTest()
+ fs := map[string][]byte{
+ "src/lib.rs": nil,
+ }
+ jsonContent := testProjectJson(t, bp, fs)
+ validateJsonCrates(t, jsonContent)
+}
+
+func TestProjectJsonMultiVersion(t *testing.T) {
+ bp := `
+ rust_library {
+ name: "liba1",
+ srcs: ["a1/src/lib.rs"],
+ crate_name: "a"
+ }
+ rust_library {
+ name: "liba2",
+ srcs: ["a2/src/lib.rs"],
+ crate_name: "a",
+ }
+ rust_library {
+ name: "libb",
+ srcs: ["b/src/lib.rs"],
+ crate_name: "b",
+ rustlibs: ["liba1", "liba2"],
+ }
+ ` + GatherRequiredDepsForTest()
+ fs := map[string][]byte{
+ "a1/src/lib.rs": nil,
+ "a2/src/lib.rs": nil,
+ "b/src/lib.rs": nil,
+ }
+ jsonContent := testProjectJson(t, bp, fs)
+ crates := validateJsonCrates(t, jsonContent)
+ for _, crate := range crates {
+ c := crate.(map[string]interface{})
+ if c["root_module"] == "b/src/lib.rs" {
+ deps, ok := c["deps"].([]interface{})
+ if !ok {
+ t.Errorf("Unexpected format for deps: %v", c["deps"])
+ }
+ aCount := 0
+ for _, dep := range deps {
+ d, ok := dep.(map[string]interface{})
+ if !ok {
+ t.Errorf("Unexpected format for dep: %v", dep)
+ }
+ if d["name"] == "a" {
+ aCount++
+ }
+ }
+ if aCount != 2 {
+ t.Errorf("Unexpected number of liba dependencies want %v, got %v: %v", 2, aCount, deps)
+ }
+ return
+ }
+ }
+ t.Errorf("libb crate has not been found: %v", crates)
}
diff --git a/rust/rust.go b/rust/rust.go
index 7a98c6468..68dc5a08b 100644
--- a/rust/rust.go
+++ b/rust/rust.go
@@ -42,6 +42,7 @@ func init() {
ctx.BottomUp("rust_begin", BeginMutator).Parallel()
})
pctx.Import("android/soong/rust/config")
+ pctx.ImportAs("ccConfig", "android/soong/cc/config")
}
type Flags struct {
@@ -61,9 +62,11 @@ type BaseProperties struct {
AndroidMkProcMacroLibs []string
AndroidMkSharedLibs []string
AndroidMkStaticLibs []string
- SubName string `blueprint:"mutated"`
- PreventInstall bool
- HideFromMake bool
+
+ SubName string `blueprint:"mutated"`
+
+ PreventInstall bool
+ HideFromMake bool
}
type Module struct {
@@ -79,8 +82,27 @@ type Module struct {
coverage *coverage
clippy *clippy
cachedToolchain config.Toolchain
- subAndroidMkOnce map[subAndroidMkProvider]bool
- outputFile android.OptionalPath
+ sourceProvider SourceProvider
+ subAndroidMkOnce map[SubAndroidMkProvider]bool
+
+ outputFile android.OptionalPath
+ generatedFile android.OptionalPath
+}
+
+func (mod *Module) OutputFiles(tag string) (android.Paths, error) {
+ switch tag {
+ case "":
+ if mod.sourceProvider != nil && (mod.compiler == nil || mod.compiler.Disabled()) {
+ return mod.sourceProvider.Srcs(), nil
+ } else {
+ if mod.outputFile.Valid() {
+ return android.Paths{mod.outputFile.Path()}, nil
+ }
+ return android.Paths{}, nil
+ }
+ default:
+ return nil, fmt.Errorf("unsupported module reference tag %q", tag)
+ }
}
var _ android.ImageInterface = (*Module)(nil)
@@ -120,12 +142,8 @@ func (mod *Module) SelectedStl() string {
func (mod *Module) NonCcVariants() bool {
if mod.compiler != nil {
- if library, ok := mod.compiler.(libraryInterface); ok {
- if library.buildRlib() || library.buildDylib() {
- return true
- } else {
- return false
- }
+ if _, ok := mod.compiler.(libraryInterface); ok {
+ return false
}
}
panic(fmt.Errorf("NonCcVariants called on non-library module: %q", mod.BaseModuleName()))
@@ -141,16 +159,16 @@ func (mod *Module) Static() bool {
return library.static()
}
}
- panic(fmt.Errorf("Static called on non-library module: %q", mod.BaseModuleName()))
+ return false
}
func (mod *Module) Shared() bool {
if mod.compiler != nil {
if library, ok := mod.compiler.(libraryInterface); ok {
- return library.static()
+ return library.shared()
}
}
- panic(fmt.Errorf("Shared called on non-library module: %q", mod.BaseModuleName()))
+ return false
}
func (mod *Module) Toc() android.OptionalPath {
@@ -226,15 +244,21 @@ type Deps struct {
}
type PathDeps struct {
- DyLibs RustLibraries
- RLibs RustLibraries
- SharedLibs android.Paths
- StaticLibs android.Paths
- ProcMacros RustLibraries
- linkDirs []string
- depFlags []string
+ DyLibs RustLibraries
+ RLibs RustLibraries
+ SharedLibs android.Paths
+ StaticLibs android.Paths
+ ProcMacros RustLibraries
+ linkDirs []string
+ depFlags []string
+ linkObjects []string
//ReexportedDeps android.Paths
+ // Used by bindgen modules which call clang
+ depClangFlags []string
+ depIncludePaths android.Paths
+ depSystemIncludePaths android.Paths
+
coverageFiles android.Paths
CrtBegin android.OptionalPath
@@ -263,18 +287,26 @@ type compiler interface {
relativeInstallPath() string
nativeCoverage() bool
+
+ Disabled() bool
+ SetDisabled()
+
+ static() bool
}
type exportedFlagsProducer interface {
exportedLinkDirs() []string
exportedDepFlags() []string
+ exportedLinkObjects() []string
exportLinkDirs(...string)
exportDepFlags(...string)
+ exportLinkObjects(...string)
}
type flagExporter struct {
- depFlags []string
- linkDirs []string
+ depFlags []string
+ linkDirs []string
+ linkObjects []string
}
func (flagExporter *flagExporter) exportedLinkDirs() []string {
@@ -285,6 +317,10 @@ func (flagExporter *flagExporter) exportedDepFlags() []string {
return flagExporter.depFlags
}
+func (flagExporter *flagExporter) exportedLinkObjects() []string {
+ return flagExporter.linkObjects
+}
+
func (flagExporter *flagExporter) exportLinkDirs(dirs ...string) {
flagExporter.linkDirs = android.FirstUniqueStrings(append(flagExporter.linkDirs, dirs...))
}
@@ -293,12 +329,17 @@ func (flagExporter *flagExporter) exportDepFlags(flags ...string) {
flagExporter.depFlags = android.FirstUniqueStrings(append(flagExporter.depFlags, flags...))
}
+func (flagExporter *flagExporter) exportLinkObjects(flags ...string) {
+ flagExporter.linkObjects = android.FirstUniqueStrings(append(flagExporter.linkObjects, flags...))
+}
+
var _ exportedFlagsProducer = (*flagExporter)(nil)
func NewFlagExporter() *flagExporter {
return &flagExporter{
- depFlags: []string{},
- linkDirs: []string{},
+ depFlags: []string{},
+ linkDirs: []string{},
+ linkObjects: []string{},
}
}
@@ -348,6 +389,7 @@ func DefaultsFactory(props ...interface{}) android.Module {
&LibraryCompilerProperties{},
&ProcMacroCompilerProperties{},
&PrebuiltProperties{},
+ &SourceProviderProperties{},
&TestProperties{},
&cc.CoverageProperties{},
&ClippyProperties{},
@@ -372,7 +414,9 @@ func (mod *Module) CcLibrary() bool {
func (mod *Module) CcLibraryInterface() bool {
if mod.compiler != nil {
- if _, ok := mod.compiler.(libraryInterface); ok {
+ // use build{Static,Shared}() instead of {static,shared}() here because this might be called before
+ // VariantIs{Static,Shared} is set.
+ if lib, ok := mod.compiler.(libraryInterface); ok && (lib.buildShared() || lib.buildStatic()) {
return true
}
}
@@ -507,6 +551,9 @@ func (mod *Module) Init() android.Module {
if mod.clippy != nil {
mod.AddProperties(mod.clippy.props()...)
}
+ if mod.sourceProvider != nil {
+ mod.AddProperties(mod.sourceProvider.SourceProviderProps()...)
+ }
android.InitAndroidArchModule(mod, mod.hod, mod.multilib)
@@ -639,10 +686,19 @@ func (mod *Module) GenerateAndroidBuildActions(actx android.ModuleContext) {
flags, deps = mod.clippy.flags(ctx, flags, deps)
}
- if mod.compiler != nil {
+ // SourceProvider needs to call GenerateSource() before compiler calls compile() so it can provide the source.
+ // TODO(b/162588681) This shouldn't have to run for every variant.
+ if mod.sourceProvider != nil {
+ generatedFile := mod.sourceProvider.GenerateSource(ctx, deps)
+ mod.generatedFile = android.OptionalPathForPath(generatedFile)
+ mod.sourceProvider.setSubName(ctx.ModuleSubDir())
+ }
+
+ if mod.compiler != nil && !mod.compiler.Disabled() {
outputFile := mod.compiler.compile(ctx, flags, deps)
+
mod.outputFile = android.OptionalPathForPath(outputFile)
- if !mod.Properties.PreventInstall {
+ if mod.outputFile.Valid() && !mod.Properties.PreventInstall {
mod.compiler.install(ctx, mod.outputFile.Path())
}
}
@@ -654,6 +710,9 @@ func (mod *Module) deps(ctx DepsContext) Deps {
if mod.compiler != nil {
deps = mod.compiler.compilerDeps(ctx, deps)
}
+ if mod.sourceProvider != nil {
+ deps = mod.sourceProvider.SourceProviderDeps(ctx, deps)
+ }
if mod.coverage != nil {
deps = mod.coverage.deps(ctx, deps)
@@ -678,10 +737,11 @@ type dependencyTag struct {
}
var (
- rlibDepTag = dependencyTag{name: "rlibTag", library: true}
- dylibDepTag = dependencyTag{name: "dylib", library: true}
- procMacroDepTag = dependencyTag{name: "procMacro", proc_macro: true}
- testPerSrcDepTag = dependencyTag{name: "rust_unit_tests"}
+ customBindgenDepTag = dependencyTag{name: "customBindgenTag"}
+ rlibDepTag = dependencyTag{name: "rlibTag", library: true}
+ dylibDepTag = dependencyTag{name: "dylib", library: true}
+ procMacroDepTag = dependencyTag{name: "procMacro", proc_macro: true}
+ testPerSrcDepTag = dependencyTag{name: "rust_unit_tests"}
)
type autoDep struct {
@@ -695,7 +755,7 @@ var (
)
type autoDeppable interface {
- autoDep() autoDep
+ autoDep(ctx BaseModuleContext) autoDep
}
func (mod *Module) begin(ctx BaseModuleContext) {
@@ -712,18 +772,15 @@ func (mod *Module) depsToPaths(ctx android.ModuleContext) PathDeps {
directProcMacroDeps := []*Module{}
directSharedLibDeps := [](cc.LinkableInterface){}
directStaticLibDeps := [](cc.LinkableInterface){}
+ directSrcProvidersDeps := []*Module{}
+ directSrcDeps := [](android.SourceFileProducer){}
ctx.VisitDirectDeps(func(dep android.Module) {
depName := ctx.OtherModuleName(dep)
depTag := ctx.OtherModuleDependencyTag(dep)
- if rustDep, ok := dep.(*Module); ok {
+ if rustDep, ok := dep.(*Module); ok && !rustDep.CcLibraryInterface() {
//Handle Rust Modules
- linkFile := rustDep.outputFile
- if !linkFile.Valid() {
- ctx.ModuleErrorf("Invalid output file when adding dep %q to %q", depName, ctx.ModuleName())
- }
-
switch depTag {
case dylibDepTag:
dylib, ok := rustDep.compiler.(libraryInterface)
@@ -745,24 +802,47 @@ func (mod *Module) depsToPaths(ctx android.ModuleContext) PathDeps {
case procMacroDepTag:
directProcMacroDeps = append(directProcMacroDeps, rustDep)
mod.Properties.AndroidMkProcMacroLibs = append(mod.Properties.AndroidMkProcMacroLibs, depName)
+ case android.SourceDepTag:
+ // Since these deps are added in path_properties.go via AddDependencies, we need to ensure the correct
+ // OS/Arch variant is used.
+ var helper string
+ if ctx.Host() {
+ helper = "missing 'host_supported'?"
+ } else {
+ helper = "device module defined?"
+ }
+
+ if dep.Target().Os != ctx.Os() {
+ ctx.ModuleErrorf("OS mismatch on dependency %q (%s)", dep.Name(), helper)
+ return
+ } else if dep.Target().Arch.ArchType != ctx.Arch().ArchType {
+ ctx.ModuleErrorf("Arch mismatch on dependency %q (%s)", dep.Name(), helper)
+ return
+ }
+ directSrcProvidersDeps = append(directSrcProvidersDeps, rustDep)
}
- //Append the dependencies exportedDirs
- if lib, ok := rustDep.compiler.(exportedFlagsProducer); ok {
+ //Append the dependencies exportedDirs, except for proc-macros which target a different arch/OS
+ if lib, ok := rustDep.compiler.(exportedFlagsProducer); ok && depTag != procMacroDepTag {
depPaths.linkDirs = append(depPaths.linkDirs, lib.exportedLinkDirs()...)
depPaths.depFlags = append(depPaths.depFlags, lib.exportedDepFlags()...)
+ depPaths.linkObjects = append(depPaths.linkObjects, lib.exportedLinkObjects()...)
}
if depTag == dylibDepTag || depTag == rlibDepTag || depTag == procMacroDepTag {
+ linkFile := rustDep.outputFile
+ if !linkFile.Valid() {
+ ctx.ModuleErrorf("Invalid output file when adding dep %q to %q",
+ depName, ctx.ModuleName())
+ return
+ }
linkDir := linkPathFromFilePath(linkFile.Path())
if lib, ok := mod.compiler.(exportedFlagsProducer); ok {
lib.exportLinkDirs(linkDir)
}
}
- }
-
- if ccDep, ok := dep.(cc.LinkableInterface); ok {
+ } else if ccDep, ok := dep.(cc.LinkableInterface); ok {
//Handle C dependencies
if _, ok := ccDep.(*Module); !ok {
if ccDep.Module().Target().Os != ctx.Os() {
@@ -774,42 +854,55 @@ func (mod *Module) depsToPaths(ctx android.ModuleContext) PathDeps {
return
}
}
+ linkObject := ccDep.OutputFile()
+ linkPath := linkPathFromFilePath(linkObject.Path())
- linkFile := ccDep.OutputFile()
- linkPath := linkPathFromFilePath(linkFile.Path())
- libName := libNameFromFilePath(linkFile.Path())
- depFlag := "-l" + libName
-
- if !linkFile.Valid() {
+ if !linkObject.Valid() {
ctx.ModuleErrorf("Invalid output file when adding dep %q to %q", depName, ctx.ModuleName())
}
exportDep := false
- switch depTag {
- case cc.StaticDepTag:
- depFlag = "-lstatic=" + libName
+ switch {
+ case cc.IsStaticDepTag(depTag):
depPaths.linkDirs = append(depPaths.linkDirs, linkPath)
- depPaths.depFlags = append(depPaths.depFlags, depFlag)
+ depPaths.linkObjects = append(depPaths.linkObjects, linkObject.String())
+ depPaths.depIncludePaths = append(depPaths.depIncludePaths, ccDep.IncludeDirs()...)
+ if mod, ok := ccDep.(*cc.Module); ok {
+ depPaths.depSystemIncludePaths = append(depPaths.depSystemIncludePaths, mod.ExportedSystemIncludeDirs()...)
+ depPaths.depClangFlags = append(depPaths.depClangFlags, mod.ExportedFlags()...)
+ }
depPaths.coverageFiles = append(depPaths.coverageFiles, ccDep.CoverageFiles()...)
directStaticLibDeps = append(directStaticLibDeps, ccDep)
mod.Properties.AndroidMkStaticLibs = append(mod.Properties.AndroidMkStaticLibs, depName)
- case cc.SharedDepTag:
- depFlag = "-ldylib=" + libName
+ case cc.IsSharedDepTag(depTag):
depPaths.linkDirs = append(depPaths.linkDirs, linkPath)
- depPaths.depFlags = append(depPaths.depFlags, depFlag)
+ depPaths.linkObjects = append(depPaths.linkObjects, linkObject.String())
+ depPaths.depIncludePaths = append(depPaths.depIncludePaths, ccDep.IncludeDirs()...)
+ if mod, ok := ccDep.(*cc.Module); ok {
+ depPaths.depSystemIncludePaths = append(depPaths.depSystemIncludePaths, mod.ExportedSystemIncludeDirs()...)
+ depPaths.depClangFlags = append(depPaths.depClangFlags, mod.ExportedFlags()...)
+ }
directSharedLibDeps = append(directSharedLibDeps, ccDep)
mod.Properties.AndroidMkSharedLibs = append(mod.Properties.AndroidMkSharedLibs, depName)
exportDep = true
- case cc.CrtBeginDepTag:
- depPaths.CrtBegin = linkFile
- case cc.CrtEndDepTag:
- depPaths.CrtEnd = linkFile
+ case depTag == cc.CrtBeginDepTag:
+ depPaths.CrtBegin = linkObject
+ case depTag == cc.CrtEndDepTag:
+ depPaths.CrtEnd = linkObject
}
// Make sure these dependencies are propagated
if lib, ok := mod.compiler.(exportedFlagsProducer); ok && exportDep {
lib.exportLinkDirs(linkPath)
- lib.exportDepFlags(depFlag)
+ lib.exportLinkObjects(linkObject.String())
+ }
+ }
+
+ if srcDep, ok := dep.(android.SourceFileProducer); ok {
+ switch depTag {
+ case android.SourceDepTag:
+ // These are usually genrules which don't have per-target variants.
+ directSrcDeps = append(directSrcDeps, srcDep)
}
}
})
@@ -837,16 +930,29 @@ func (mod *Module) depsToPaths(ctx android.ModuleContext) PathDeps {
sharedLibDepFiles = append(sharedLibDepFiles, dep.OutputFile().Path())
}
+ var srcProviderDepFiles android.Paths
+ for _, dep := range directSrcProvidersDeps {
+ srcs, _ := dep.OutputFiles("")
+ srcProviderDepFiles = append(srcProviderDepFiles, srcs...)
+ }
+ for _, dep := range directSrcDeps {
+ srcs := dep.Srcs()
+ srcProviderDepFiles = append(srcProviderDepFiles, srcs...)
+ }
+
depPaths.RLibs = append(depPaths.RLibs, rlibDepFiles...)
depPaths.DyLibs = append(depPaths.DyLibs, dylibDepFiles...)
depPaths.SharedLibs = append(depPaths.SharedLibs, sharedLibDepFiles...)
depPaths.StaticLibs = append(depPaths.StaticLibs, staticLibDepFiles...)
depPaths.ProcMacros = append(depPaths.ProcMacros, procMacroDepFiles...)
+ depPaths.SrcDeps = append(depPaths.SrcDeps, srcProviderDepFiles...)
// Dedup exported flags from dependencies
depPaths.linkDirs = android.FirstUniqueStrings(depPaths.linkDirs)
depPaths.depFlags = android.FirstUniqueStrings(depPaths.depFlags)
- depPaths.SrcDeps = android.FirstUniquePaths(depPaths.SrcDeps)
+ depPaths.depClangFlags = android.FirstUniqueStrings(depPaths.depClangFlags)
+ depPaths.depIncludePaths = android.FirstUniquePaths(depPaths.depIncludePaths)
+ depPaths.depSystemIncludePaths = android.FirstUniquePaths(depPaths.depSystemIncludePaths)
return depPaths
}
@@ -862,14 +968,6 @@ func linkPathFromFilePath(filepath android.Path) string {
return strings.Split(filepath.String(), filepath.Base())[0]
}
-func libNameFromFilePath(filepath android.Path) string {
- libName := strings.TrimSuffix(filepath.Base(), filepath.Ext())
- if strings.HasPrefix(libName, "lib") {
- libName = libName[3:]
- }
- return libName
-}
-
func (mod *Module) DepsMutator(actx android.BottomUpMutatorContext) {
ctx := &depsContext{
BottomUpMutatorContext: actx,
@@ -887,38 +985,43 @@ func (mod *Module) DepsMutator(actx android.BottomUpMutatorContext) {
}
actx.AddVariationDependencies(
append(commonDepVariations, []blueprint.Variation{
- {Mutator: "rust_libraries", Variation: "rlib"},
- {Mutator: "link", Variation: ""}}...),
+ {Mutator: "rust_libraries", Variation: "rlib"}}...),
rlibDepTag, deps.Rlibs...)
actx.AddVariationDependencies(
append(commonDepVariations, []blueprint.Variation{
- {Mutator: "rust_libraries", Variation: "dylib"},
- {Mutator: "link", Variation: ""}}...),
+ {Mutator: "rust_libraries", Variation: "dylib"}}...),
dylibDepTag, deps.Dylibs...)
- if deps.Rustlibs != nil {
- autoDep := mod.compiler.(autoDeppable).autoDep()
+ if deps.Rustlibs != nil && !mod.compiler.Disabled() {
+ autoDep := mod.compiler.(autoDeppable).autoDep(ctx)
actx.AddVariationDependencies(
append(commonDepVariations, []blueprint.Variation{
- {Mutator: "rust_libraries", Variation: autoDep.variation},
- {Mutator: "link", Variation: ""}}...),
+ {Mutator: "rust_libraries", Variation: autoDep.variation}}...),
autoDep.depTag, deps.Rustlibs...)
}
actx.AddVariationDependencies(append(commonDepVariations,
blueprint.Variation{Mutator: "link", Variation: "shared"}),
- cc.SharedDepTag, deps.SharedLibs...)
+ cc.SharedDepTag(), deps.SharedLibs...)
actx.AddVariationDependencies(append(commonDepVariations,
blueprint.Variation{Mutator: "link", Variation: "static"}),
- cc.StaticDepTag, deps.StaticLibs...)
+ cc.StaticDepTag(), deps.StaticLibs...)
+ crtVariations := append(cc.GetCrtVariations(ctx, mod), commonDepVariations...)
if deps.CrtBegin != "" {
- actx.AddVariationDependencies(commonDepVariations, cc.CrtBeginDepTag, deps.CrtBegin)
+ actx.AddVariationDependencies(crtVariations, cc.CrtBeginDepTag, deps.CrtBegin)
}
if deps.CrtEnd != "" {
- actx.AddVariationDependencies(commonDepVariations, cc.CrtEndDepTag, deps.CrtEnd)
+ actx.AddVariationDependencies(crtVariations, cc.CrtEndDepTag, deps.CrtEnd)
}
+ if mod.sourceProvider != nil {
+ if bindgen, ok := mod.sourceProvider.(*bindgenDecorator); ok &&
+ bindgen.Properties.Custom_bindgen != "" {
+ actx.AddFarVariationDependencies(ctx.Config().BuildOSTarget.Variations(), customBindgenDepTag,
+ bindgen.Properties.Custom_bindgen)
+ }
+ }
// proc_macros are compiler plugins, and so we need the host arch variant as a dependendcy.
actx.AddFarVariationDependencies(ctx.Config().BuildOSTarget.Variations(), procMacroDepTag, deps.ProcMacros...)
}
@@ -947,14 +1050,20 @@ func (mod *Module) Name() string {
return name
}
+func (mod *Module) disableClippy() {
+ if mod.clippy != nil {
+ mod.clippy.Properties.Clippy_lints = proptools.StringPtr("none")
+ }
+}
+
var _ android.HostToolProvider = (*Module)(nil)
func (mod *Module) HostToolPath() android.OptionalPath {
if !mod.Host() {
return android.OptionalPath{}
}
- if _, ok := mod.compiler.(*binaryDecorator); ok {
- return mod.outputFile
+ if binary, ok := mod.compiler.(*binaryDecorator); ok {
+ return android.OptionalPathForPath(binary.baseCompiler.path)
}
return android.OptionalPath{}
}
@@ -963,3 +1072,5 @@ var Bool = proptools.Bool
var BoolDefault = proptools.BoolDefault
var String = proptools.String
var StringPtr = proptools.StringPtr
+
+var _ android.OutputFileProducer = (*Module)(nil)
diff --git a/rust/rust_test.go b/rust/rust_test.go
index e80392589..f1a08a805 100644
--- a/rust/rust_test.go
+++ b/rust/rust_test.go
@@ -132,25 +132,6 @@ func testRustError(t *testing.T, pattern string, bp string) {
t.Fatalf("missing expected error %q (0 errors are returned)", pattern)
}
-// Test that we can extract the lib name from a lib path.
-func TestLibNameFromFilePath(t *testing.T) {
- libBarPath := android.PathForTesting("out/soong/.intermediates/external/libbar/libbar/linux_glibc_x86_64_shared/libbar.so.so")
- libLibPath := android.PathForTesting("out/soong/.intermediates/external/libbar/libbar/linux_glibc_x86_64_shared/liblib.dylib.so")
-
- libBarName := libNameFromFilePath(libBarPath)
- libLibName := libNameFromFilePath(libLibPath)
-
- expectedResult := "bar.so"
- if libBarName != expectedResult {
- t.Errorf("libNameFromFilePath returned the wrong name; expected '%#v', got '%#v'", expectedResult, libBarName)
- }
-
- expectedResult = "lib.dylib"
- if libLibName != expectedResult {
- t.Errorf("libNameFromFilePath returned the wrong name; expected '%#v', got '%#v'", expectedResult, libLibPath)
- }
-}
-
// Test that we can extract the link path from a lib path.
func TestLinkPathFromFilePath(t *testing.T) {
barPath := android.PathForTesting("out/soong/.intermediates/external/libbar/libbar/linux_glibc_x86_64_shared/libbar.so")
@@ -182,7 +163,7 @@ func TestDepsTracking(t *testing.T) {
}
rust_library_host_rlib {
name: "librlib",
- srcs: ["foo.rs", ":my_generator"],
+ srcs: ["foo.rs"],
crate_name: "rlib",
}
rust_proc_macro {
@@ -190,38 +171,17 @@ func TestDepsTracking(t *testing.T) {
srcs: ["foo.rs"],
crate_name: "pm",
}
- genrule {
- name: "my_generator",
- tools: ["any_rust_binary"],
- cmd: "$(location) -o $(out) $(in)",
- srcs: ["src/any.h"],
- out: ["src/any.rs"],
- }
rust_binary_host {
- name: "fizz-buzz-dep",
+ name: "fizz-buzz",
dylibs: ["libdylib"],
rlibs: ["librlib"],
proc_macros: ["libpm"],
static_libs: ["libstatic"],
shared_libs: ["libshared"],
- srcs: [
- "foo.rs",
- ":my_generator",
- ],
+ srcs: ["foo.rs"],
}
`)
- module := ctx.ModuleForTests("fizz-buzz-dep", "linux_glibc_x86_64").Module().(*Module)
- rlibmodule := ctx.ModuleForTests("librlib", "linux_glibc_x86_64_rlib").Module().(*Module)
-
- srcs := module.compiler.(*binaryDecorator).baseCompiler.Properties.Srcs
- if len(srcs) != 2 || !android.InList(":my_generator", srcs) {
- t.Errorf("missing module dependency in fizz-buzz)")
- }
-
- srcs = rlibmodule.compiler.(*libraryDecorator).baseCompiler.Properties.Srcs
- if len(srcs) != 2 || !android.InList(":my_generator", srcs) {
- t.Errorf("missing module dependency in rlib")
- }
+ module := ctx.ModuleForTests("fizz-buzz", "linux_glibc_x86_64").Module().(*Module)
// Since dependencies are added to AndroidMk* properties, we can check these to see if they've been picked up.
if !android.InList("libdylib", module.Properties.AndroidMkDylibs) {
@@ -245,6 +205,114 @@ func TestDepsTracking(t *testing.T) {
}
}
+func TestSourceProviderDeps(t *testing.T) {
+ ctx := testRust(t, `
+ rust_binary {
+ name: "fizz-buzz-dep",
+ srcs: [
+ "foo.rs",
+ ":my_generator",
+ ":libbindings",
+ ],
+ rlibs: ["libbindings"],
+ }
+ rust_proc_macro {
+ name: "libprocmacro",
+ srcs: [
+ "foo.rs",
+ ":my_generator",
+ ":libbindings",
+ ],
+ rlibs: ["libbindings"],
+ crate_name: "procmacro",
+ }
+ rust_library {
+ name: "libfoo",
+ srcs: [
+ "foo.rs",
+ ":my_generator",
+ ":libbindings",
+ ],
+ rlibs: ["libbindings"],
+ crate_name: "foo",
+ }
+ genrule {
+ name: "my_generator",
+ tools: ["any_rust_binary"],
+ cmd: "$(location) -o $(out) $(in)",
+ srcs: ["src/any.h"],
+ out: ["src/any.rs"],
+ }
+ rust_bindgen {
+ name: "libbindings",
+ crate_name: "bindings",
+ source_stem: "bindings",
+ host_supported: true,
+ wrapper_src: "src/any.h",
+ }
+ `)
+
+ libfoo := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_rlib").Rule("rustc")
+ if !android.SuffixInList(libfoo.Implicits.Strings(), "/out/bindings.rs") {
+ t.Errorf("rust_bindgen generated source not included as implicit input for libfoo; Implicits %#v", libfoo.Implicits.Strings())
+ }
+ if !android.SuffixInList(libfoo.Implicits.Strings(), "/out/any.rs") {
+ t.Errorf("genrule generated source not included as implicit input for libfoo; Implicits %#v", libfoo.Implicits.Strings())
+ }
+
+ fizzBuzz := ctx.ModuleForTests("fizz-buzz-dep", "android_arm64_armv8-a").Rule("rustc")
+ if !android.SuffixInList(fizzBuzz.Implicits.Strings(), "/out/bindings.rs") {
+ t.Errorf("rust_bindgen generated source not included as implicit input for fizz-buzz-dep; Implicits %#v", libfoo.Implicits.Strings())
+ }
+ if !android.SuffixInList(fizzBuzz.Implicits.Strings(), "/out/any.rs") {
+ t.Errorf("genrule generated source not included as implicit input for fizz-buzz-dep; Implicits %#v", libfoo.Implicits.Strings())
+ }
+
+ libprocmacro := ctx.ModuleForTests("libprocmacro", "linux_glibc_x86_64").Rule("rustc")
+ if !android.SuffixInList(libprocmacro.Implicits.Strings(), "/out/bindings.rs") {
+ t.Errorf("rust_bindgen generated source not included as implicit input for libprocmacro; Implicits %#v", libfoo.Implicits.Strings())
+ }
+ if !android.SuffixInList(libprocmacro.Implicits.Strings(), "/out/any.rs") {
+ t.Errorf("genrule generated source not included as implicit input for libprocmacro; Implicits %#v", libfoo.Implicits.Strings())
+ }
+
+ // Check that our bindings are picked up as crate dependencies as well
+ libfooMod := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_dylib").Module().(*Module)
+ if !android.InList("libbindings", libfooMod.Properties.AndroidMkRlibs) {
+ t.Errorf("bindgen dependency not detected as a rlib dependency (dependency missing from AndroidMkRlibs)")
+ }
+ fizzBuzzMod := ctx.ModuleForTests("fizz-buzz-dep", "android_arm64_armv8-a").Module().(*Module)
+ if !android.InList("libbindings", fizzBuzzMod.Properties.AndroidMkRlibs) {
+ t.Errorf("bindgen dependency not detected as a rlib dependency (dependency missing from AndroidMkRlibs)")
+ }
+ libprocmacroMod := ctx.ModuleForTests("libprocmacro", "linux_glibc_x86_64").Module().(*Module)
+ if !android.InList("libbindings", libprocmacroMod.Properties.AndroidMkRlibs) {
+ t.Errorf("bindgen dependency not detected as a rlib dependency (dependency missing from AndroidMkRlibs)")
+ }
+
+}
+
+func TestSourceProviderTargetMismatch(t *testing.T) {
+ // This might error while building the dependency tree or when calling depsToPaths() depending on the lunched
+ // target, which results in two different errors. So don't check the error, just confirm there is one.
+ testRustError(t, ".*", `
+ rust_proc_macro {
+ name: "libprocmacro",
+ srcs: [
+ "foo.rs",
+ ":libbindings",
+ ],
+ crate_name: "procmacro",
+ }
+ rust_bindgen {
+ name: "libbindings",
+ crate_name: "bindings",
+ source_stem: "bindings",
+ wrapper_src: "src/any.h",
+ }
+ `)
+}
+
// Test to make sure proc_macros use host variants when building device modules.
func TestProcMacroDeviceDeps(t *testing.T) {
ctx := testRust(t, `
diff --git a/rust/source_provider.go b/rust/source_provider.go
new file mode 100644
index 000000000..e168718e4
--- /dev/null
+++ b/rust/source_provider.go
@@ -0,0 +1,97 @@
+// Copyright 2020 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package rust
+
+import (
+ "android/soong/android"
+)
+
+type SourceProviderProperties struct {
+ // filename for the generated source file (<source_stem>.rs). This field is required.
+ // The inherited "stem" property sets the output filename for the generated library variants only.
+ Source_stem *string `android:"arch_variant"`
+
+ // crate name, used for the library variant of this source provider. See additional details in rust_library.
+ Crate_name string `android:"arch_variant"`
+}
+
+type BaseSourceProvider struct {
+ Properties SourceProviderProperties
+
+ OutputFile android.Path
+ subAndroidMkOnce map[SubAndroidMkProvider]bool
+ subName string
+}
+
+var _ SourceProvider = (*BaseSourceProvider)(nil)
+
+type SourceProvider interface {
+ GenerateSource(ctx android.ModuleContext, deps PathDeps) android.Path
+ Srcs() android.Paths
+ SourceProviderProps() []interface{}
+ SourceProviderDeps(ctx DepsContext, deps Deps) Deps
+ setSubName(subName string)
+}
+
+func (sp *BaseSourceProvider) Srcs() android.Paths {
+ return android.Paths{sp.OutputFile}
+}
+
+func (sp *BaseSourceProvider) GenerateSource(ctx android.ModuleContext, deps PathDeps) android.Path {
+ panic("BaseSourceProviderModule does not implement GenerateSource()")
+}
+
+func (sp *BaseSourceProvider) SourceProviderProps() []interface{} {
+ return []interface{}{&sp.Properties}
+}
+
+func NewSourceProvider() *BaseSourceProvider {
+ return &BaseSourceProvider{
+ Properties: SourceProviderProperties{},
+ }
+}
+
+func NewSourceProviderModule(hod android.HostOrDeviceSupported, sourceProvider SourceProvider, enableLints bool) *Module {
+ _, library := NewRustLibrary(hod)
+ library.BuildOnlyRust()
+ library.sourceProvider = sourceProvider
+
+ module := newModule(hod, android.MultilibBoth)
+ module.sourceProvider = sourceProvider
+ module.compiler = library
+
+ if !enableLints {
+ library.disableLints()
+ module.disableClippy()
+ }
+
+ return module
+}
+
+func (sp *BaseSourceProvider) getStem(ctx android.ModuleContext) string {
+ if String(sp.Properties.Source_stem) == "" {
+ ctx.PropertyErrorf("source_stem",
+ "source_stem property is undefined but required for rust_bindgen modules")
+ }
+ return String(sp.Properties.Source_stem)
+}
+
+func (sp *BaseSourceProvider) SourceProviderDeps(ctx DepsContext, deps Deps) Deps {
+ return deps
+}
+
+func (sp *BaseSourceProvider) setSubName(subName string) {
+ sp.subName = subName
+}
diff --git a/rust/source_provider_test.go b/rust/source_provider_test.go
new file mode 100644
index 000000000..6e68ae62c
--- /dev/null
+++ b/rust/source_provider_test.go
@@ -0,0 +1,31 @@
+// Copyright 2020 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package rust
+
+import (
+ "testing"
+)
+
+var stemRequiredError = "source_stem property is undefined but required for rust_bindgen modules"
+
+func TestSourceProviderRequiredFields(t *testing.T) {
+ testRustError(t, stemRequiredError, `
+ rust_bindgen {
+ name: "libbindgen",
+ wrapper_src: "src/any.h",
+ crate_name: "bindgen",
+ }
+ `)
+}
diff --git a/rust/test.go b/rust/test.go
index e27a70cac..19802e392 100644
--- a/rust/test.go
+++ b/rust/test.go
@@ -41,6 +41,9 @@ type TestProperties struct {
// doesn't exist next to the Android.bp, this attribute doesn't need to be set to true
// explicitly.
Auto_gen_config *bool
+
+ // if set, build with the standard Rust test harness. Defaults to true.
+ Test_harness *bool
}
// A test module is a binary module with extra --test compiler flag
@@ -56,6 +59,10 @@ func (test *testDecorator) nativeCoverage() bool {
return true
}
+func (test *testDecorator) testHarness() bool {
+ return BoolDefault(test.Properties.Test_harness, true)
+}
+
func NewRustTest(hod android.HostOrDeviceSupported) (*Module, *testDecorator) {
// Build both 32 and 64 targets for device tests.
// Cannot build both for host tests yet if the test depends on
@@ -101,11 +108,13 @@ func (test *testDecorator) install(ctx ModuleContext, file android.Path) {
func (test *testDecorator) compilerFlags(ctx ModuleContext, flags Flags) Flags {
flags = test.binaryDecorator.compilerFlags(ctx, flags)
- flags.RustFlags = append(flags.RustFlags, "--test")
+ if test.testHarness() {
+ flags.RustFlags = append(flags.RustFlags, "--test")
+ }
return flags
}
-func (test *testDecorator) autoDep() autoDep {
+func (test *testDecorator) autoDep(ctx BaseModuleContext) autoDep {
return rlibAutoDep
}
diff --git a/rust/testing.go b/rust/testing.go
index 430b40bfd..80e414871 100644
--- a/rust/testing.go
+++ b/rust/testing.go
@@ -44,7 +44,28 @@ func GatherRequiredDepsForTest() string {
},
host_supported: true,
}
-
+ rust_prebuilt_library {
+ name: "libstd_x86_64-apple-darwin",
+ crate_name: "std",
+ rlib: {
+ srcs: ["libstd.rlib"],
+ },
+ dylib: {
+ srcs: ["libstd.so"],
+ },
+ host_supported: true,
+ }
+ rust_prebuilt_library {
+ name: "libtest_x86_64-apple-darwin",
+ crate_name: "test",
+ rlib: {
+ srcs: ["libtest.rlib"],
+ },
+ dylib: {
+ srcs: ["libtest.so"],
+ },
+ host_supported: true,
+ }
//////////////////////////////
// Device module requirements
@@ -77,10 +98,13 @@ func GatherRequiredDepsForTest() string {
func CreateTestContext() *android.TestContext {
ctx := android.NewTestArchContext()
+ android.RegisterPrebuiltMutators(ctx)
+ ctx.PreArchMutators(android.RegisterDefaultsPreArchMutators)
cc.RegisterRequiredBuildComponentsForTest(ctx)
ctx.RegisterModuleType("genrule", genrule.GenRuleFactory)
ctx.RegisterModuleType("rust_binary", RustBinaryFactory)
ctx.RegisterModuleType("rust_binary_host", RustBinaryHostFactory)
+ ctx.RegisterModuleType("rust_bindgen", RustBindgenFactory)
ctx.RegisterModuleType("rust_test", RustTestFactory)
ctx.RegisterModuleType("rust_test_host", RustTestHostFactory)
ctx.RegisterModuleType("rust_library", RustLibraryFactory)
diff --git a/scripts/build-aml-prebuilts.sh b/scripts/build-aml-prebuilts.sh
index c60eaa1f6..ef5565de3 100755
--- a/scripts/build-aml-prebuilts.sh
+++ b/scripts/build-aml-prebuilts.sh
@@ -84,6 +84,8 @@ cat > ${SOONG_VARS}.new << EOF
"CrossHostArch": "x86_64",
"Aml_abis": true,
+ "Allow_missing_dependencies": ${SOONG_ALLOW_MISSING_DEPENDENCIES:-false},
+ "Unbundled_build": ${TARGET_BUILD_UNBUNDLED:-false},
"UseGoma": ${USE_GOMA}
}
EOF
diff --git a/scripts/build-mainline-modules.sh b/scripts/build-mainline-modules.sh
index 1bc78e6ba..c5ec8d19c 100755
--- a/scripts/build-mainline-modules.sh
+++ b/scripts/build-mainline-modules.sh
@@ -24,7 +24,7 @@ MODULES_SDK_AND_EXPORTS=(
i18n-module-test-exports
i18n-module-sdk
platform-mainline-sdk
- platform-mainline-host-exports
+ platform-mainline-test-exports
)
# List of libraries installed on the platform that are needed for ART chroot
@@ -52,6 +52,13 @@ echo_and_run() {
"$@"
}
+lib_dir() {
+ case $1 in
+ (aosp_arm|aosp_x86) echo "lib";;
+ (aosp_arm64|aosp_x86_64) echo "lib64";;
+ esac
+}
+
OUT_DIR=$(source build/envsetup.sh > /dev/null; TARGET_PRODUCT= get_build_var OUT_DIR)
DIST_DIR=$(source build/envsetup.sh > /dev/null; TARGET_PRODUCT= get_build_var DIST_DIR)
@@ -69,7 +76,8 @@ for product in "${PRODUCTS[@]}"; do
echo_and_run cp ${PWD}/${PRODUCT_OUT}/system/apex/${module}.apex ${DIST_DIR}/${TARGET_ARCH}/
done
for library in "${PLATFORM_LIBRARIES[@]}"; do
- echo_and_run cp ${PWD}/${PRODUCT_OUT}/system/lib/${library}.so ${DIST_DIR}/${TARGET_ARCH}/
+ libdir=$(lib_dir $product)
+ echo_and_run cp ${PWD}/${PRODUCT_OUT}/system/${libdir}/${library}.so ${DIST_DIR}/${TARGET_ARCH}/
done
done
diff --git a/sdk/cc_sdk_test.go b/sdk/cc_sdk_test.go
index 935d348ae..84b905c9d 100644
--- a/sdk/cc_sdk_test.go
+++ b/sdk/cc_sdk_test.go
@@ -39,6 +39,20 @@ func testSdkWithCc(t *testing.T, bp string) *testSdkResult {
// Contains tests for SDK members provided by the cc package.
+func TestSingleDeviceOsAssumption(t *testing.T) {
+ // Mock a module with DeviceSupported() == true.
+ s := &sdk{}
+ android.InitAndroidArchModule(s, android.DeviceSupported, android.MultilibCommon)
+
+ osTypes := s.getPossibleOsTypes()
+ if len(osTypes) != 1 {
+ // The snapshot generation assumes there is a single device OS. If more are
+ // added it might need to disable them by default, like it does for host
+ // OS'es.
+ t.Errorf("expected a single device OS, got %v", osTypes)
+ }
+}
+
func TestSdkIsCompileMultilibBoth(t *testing.T) {
result := testSdkWithCc(t, `
sdk {
@@ -73,12 +87,14 @@ func TestSdkCompileMultilibOverride(t *testing.T) {
result := testSdkWithCc(t, `
sdk {
name: "mysdk",
+ host_supported: true,
native_shared_libs: ["sdkmember"],
compile_multilib: "64",
}
cc_library_shared {
name: "sdkmember",
+ host_supported: true,
srcs: ["Test.cpp"],
stl: "none",
compile_multilib: "64",
@@ -86,8 +102,72 @@ func TestSdkCompileMultilibOverride(t *testing.T) {
`)
result.CheckSnapshot("mysdk", "",
+ checkAndroidBpContents(`
+// This is auto-generated. DO NOT EDIT.
+
+cc_prebuilt_library_shared {
+ name: "mysdk_sdkmember@current",
+ sdk_member_name: "sdkmember",
+ host_supported: true,
+ installable: false,
+ stl: "none",
+ compile_multilib: "64",
+ target: {
+ host: {
+ enabled: false,
+ },
+ android_arm64: {
+ srcs: ["android/arm64/lib/sdkmember.so"],
+ },
+ linux_glibc: {
+ enabled: true,
+ },
+ linux_glibc_x86_64: {
+ srcs: ["linux_glibc/x86_64/lib/sdkmember.so"],
+ },
+ },
+}
+
+cc_prebuilt_library_shared {
+ name: "sdkmember",
+ prefer: false,
+ host_supported: true,
+ stl: "none",
+ compile_multilib: "64",
+ target: {
+ host: {
+ enabled: false,
+ },
+ android_arm64: {
+ srcs: ["android/arm64/lib/sdkmember.so"],
+ },
+ linux_glibc: {
+ enabled: true,
+ },
+ linux_glibc_x86_64: {
+ srcs: ["linux_glibc/x86_64/lib/sdkmember.so"],
+ },
+ },
+}
+
+sdk_snapshot {
+ name: "mysdk@current",
+ host_supported: true,
+ native_shared_libs: ["mysdk_sdkmember@current"],
+ compile_multilib: "64",
+ target: {
+ host: {
+ enabled: false,
+ },
+ linux_glibc: {
+ enabled: true,
+ },
+ },
+}
+`),
checkAllCopyRules(`
-.intermediates/sdkmember/android_arm64_armv8-a_shared/sdkmember.so -> arm64/lib/sdkmember.so
+.intermediates/sdkmember/android_arm64_armv8-a_shared/sdkmember.so -> android/arm64/lib/sdkmember.so
+.intermediates/sdkmember/linux_glibc_x86_64_shared/sdkmember.so -> linux_glibc/x86_64/lib/sdkmember.so
`))
}
@@ -185,11 +265,11 @@ func TestBasicSdkWithCc(t *testing.T) {
}
`)
- sdkMemberV1 := result.ModuleForTests("sdkmember_mysdk_1", "android_arm64_armv8-a_shared_myapex").Rule("toc").Output
- sdkMemberV2 := result.ModuleForTests("sdkmember_mysdk_2", "android_arm64_armv8-a_shared_myapex2").Rule("toc").Output
+ sdkMemberV1 := result.ModuleForTests("sdkmember_mysdk_1", "android_arm64_armv8-a_shared_apex10000_mysdk_1").Rule("toc").Output
+ sdkMemberV2 := result.ModuleForTests("sdkmember_mysdk_2", "android_arm64_armv8-a_shared_apex10000_mysdk_2").Rule("toc").Output
- cpplibForMyApex := result.ModuleForTests("mycpplib", "android_arm64_armv8-a_shared_myapex")
- cpplibForMyApex2 := result.ModuleForTests("mycpplib", "android_arm64_armv8-a_shared_myapex2")
+ cpplibForMyApex := result.ModuleForTests("mycpplib", "android_arm64_armv8-a_shared_apex10000_mysdk_1")
+ cpplibForMyApex2 := result.ModuleForTests("mycpplib", "android_arm64_armv8-a_shared_apex10000_mysdk_2")
// Depending on the uses_sdks value, different libs are linked
ensureListContains(t, pathsToStrings(cpplibForMyApex.Rule("ld").Implicits), sdkMemberV1.String())
@@ -260,6 +340,9 @@ func TestSnapshotWithObject(t *testing.T) {
cc_object {
name: "crtobj",
stl: "none",
+ sanitize: {
+ never: true,
+ },
}
`)
@@ -271,6 +354,10 @@ cc_prebuilt_object {
name: "mysdk_crtobj@current",
sdk_member_name: "crtobj",
stl: "none",
+ compile_multilib: "both",
+ sanitize: {
+ never: true,
+ },
arch: {
arm64: {
srcs: ["arm64/lib/crtobj.o"],
@@ -285,6 +372,10 @@ cc_prebuilt_object {
name: "crtobj",
prefer: false,
stl: "none",
+ compile_multilib: "both",
+ sanitize: {
+ never: true,
+ },
arch: {
arm64: {
srcs: ["arm64/lib/crtobj.o"],
@@ -378,6 +469,7 @@ cc_prebuilt_library_shared {
sdk_member_name: "mynativelib",
installable: false,
stl: "none",
+ compile_multilib: "both",
export_include_dirs: ["include/include"],
arch: {
arm64: {
@@ -394,6 +486,7 @@ cc_prebuilt_library_shared {
name: "mynativelib",
prefer: false,
stl: "none",
+ compile_multilib: "both",
export_include_dirs: ["include/include"],
arch: {
arm64: {
@@ -523,7 +616,11 @@ cc_prebuilt_binary {
installable: false,
stl: "none",
target: {
+ host: {
+ enabled: false,
+ },
linux_glibc: {
+ enabled: true,
compile_multilib: "both",
},
linux_glibc_x86_64: {
@@ -533,6 +630,7 @@ cc_prebuilt_binary {
srcs: ["linux_glibc/x86/bin/mynativebinary"],
},
windows: {
+ enabled: true,
compile_multilib: "64",
},
windows_x86_64: {
@@ -548,7 +646,11 @@ cc_prebuilt_binary {
host_supported: true,
stl: "none",
target: {
+ host: {
+ enabled: false,
+ },
linux_glibc: {
+ enabled: true,
compile_multilib: "both",
},
linux_glibc_x86_64: {
@@ -558,6 +660,7 @@ cc_prebuilt_binary {
srcs: ["linux_glibc/x86/bin/mynativebinary"],
},
windows: {
+ enabled: true,
compile_multilib: "64",
},
windows_x86_64: {
@@ -572,7 +675,14 @@ module_exports_snapshot {
host_supported: true,
native_binaries: ["myexports_mynativebinary@current"],
target: {
+ host: {
+ enabled: false,
+ },
+ linux_glibc: {
+ enabled: true,
+ },
windows: {
+ enabled: true,
compile_multilib: "64",
},
},
@@ -586,6 +696,162 @@ module_exports_snapshot {
)
}
+func TestSnapshotWithSingleHostOsType(t *testing.T) {
+ ctx, config := testSdkContext(`
+ cc_defaults {
+ name: "mydefaults",
+ device_supported: false,
+ host_supported: true,
+ compile_multilib: "64",
+ target: {
+ host: {
+ enabled: false,
+ },
+ linux_bionic: {
+ enabled: true,
+ },
+ },
+ }
+
+ module_exports {
+ name: "myexports",
+ defaults: ["mydefaults"],
+ native_shared_libs: ["mynativelib"],
+ native_binaries: ["mynativebinary"],
+ compile_multilib: "64", // The built-in default in sdk.go overrides mydefaults.
+ }
+
+ cc_library {
+ name: "mynativelib",
+ defaults: ["mydefaults"],
+ srcs: [
+ "Test.cpp",
+ ],
+ stl: "none",
+ }
+
+ cc_binary {
+ name: "mynativebinary",
+ defaults: ["mydefaults"],
+ srcs: [
+ "Test.cpp",
+ ],
+ stl: "none",
+ }
+ `, ccTestFs, []android.OsType{android.LinuxBionic})
+
+ result := runTests(t, ctx, config)
+
+ result.CheckSnapshot("myexports", "",
+ checkAndroidBpContents(`
+// This is auto-generated. DO NOT EDIT.
+
+cc_prebuilt_binary {
+ name: "myexports_mynativebinary@current",
+ sdk_member_name: "mynativebinary",
+ device_supported: false,
+ host_supported: true,
+ installable: false,
+ stl: "none",
+ compile_multilib: "64",
+ target: {
+ host: {
+ enabled: false,
+ },
+ linux_bionic: {
+ enabled: true,
+ },
+ linux_bionic_x86_64: {
+ srcs: ["x86_64/bin/mynativebinary"],
+ },
+ },
+}
+
+cc_prebuilt_binary {
+ name: "mynativebinary",
+ prefer: false,
+ device_supported: false,
+ host_supported: true,
+ stl: "none",
+ compile_multilib: "64",
+ target: {
+ host: {
+ enabled: false,
+ },
+ linux_bionic: {
+ enabled: true,
+ },
+ linux_bionic_x86_64: {
+ srcs: ["x86_64/bin/mynativebinary"],
+ },
+ },
+}
+
+cc_prebuilt_library_shared {
+ name: "myexports_mynativelib@current",
+ sdk_member_name: "mynativelib",
+ device_supported: false,
+ host_supported: true,
+ installable: false,
+ stl: "none",
+ compile_multilib: "64",
+ target: {
+ host: {
+ enabled: false,
+ },
+ linux_bionic: {
+ enabled: true,
+ },
+ linux_bionic_x86_64: {
+ srcs: ["x86_64/lib/mynativelib.so"],
+ },
+ },
+}
+
+cc_prebuilt_library_shared {
+ name: "mynativelib",
+ prefer: false,
+ device_supported: false,
+ host_supported: true,
+ stl: "none",
+ compile_multilib: "64",
+ target: {
+ host: {
+ enabled: false,
+ },
+ linux_bionic: {
+ enabled: true,
+ },
+ linux_bionic_x86_64: {
+ srcs: ["x86_64/lib/mynativelib.so"],
+ },
+ },
+}
+
+module_exports_snapshot {
+ name: "myexports@current",
+ device_supported: false,
+ host_supported: true,
+ native_binaries: ["myexports_mynativebinary@current"],
+ native_shared_libs: ["myexports_mynativelib@current"],
+ compile_multilib: "64",
+ target: {
+ host: {
+ enabled: false,
+ },
+ linux_bionic: {
+ enabled: true,
+ },
+ },
+}
+`),
+ checkAllCopyRules(`
+.intermediates/mynativebinary/linux_bionic_x86_64/mynativebinary -> x86_64/bin/mynativebinary
+.intermediates/mynativelib/linux_bionic_x86_64_shared/mynativelib.so -> x86_64/lib/mynativelib.so
+`),
+ )
+}
+
// Test that we support the necessary flags for the linker binary, which is
// special in several ways.
func TestSnapshotWithCcStaticNocrtBinary(t *testing.T) {
@@ -621,14 +887,20 @@ cc_prebuilt_binary {
host_supported: true,
installable: false,
stl: "none",
+ compile_multilib: "both",
static_executable: true,
nocrt: true,
- compile_multilib: "both",
- arch: {
- x86_64: {
+ target: {
+ host: {
+ enabled: false,
+ },
+ linux_glibc: {
+ enabled: true,
+ },
+ linux_glibc_x86_64: {
srcs: ["x86_64/bin/linker"],
},
- x86: {
+ linux_glibc_x86: {
srcs: ["x86/bin/linker"],
},
},
@@ -640,14 +912,20 @@ cc_prebuilt_binary {
device_supported: false,
host_supported: true,
stl: "none",
+ compile_multilib: "both",
static_executable: true,
nocrt: true,
- compile_multilib: "both",
- arch: {
- x86_64: {
+ target: {
+ host: {
+ enabled: false,
+ },
+ linux_glibc: {
+ enabled: true,
+ },
+ linux_glibc_x86_64: {
srcs: ["x86_64/bin/linker"],
},
- x86: {
+ linux_glibc_x86: {
srcs: ["x86/bin/linker"],
},
},
@@ -658,6 +936,14 @@ module_exports_snapshot {
device_supported: false,
host_supported: true,
native_binaries: ["mymodule_exports_linker@current"],
+ target: {
+ host: {
+ enabled: false,
+ },
+ linux_glibc: {
+ enabled: true,
+ },
+ },
}
`),
checkAllCopyRules(`
@@ -702,6 +988,7 @@ cc_prebuilt_library_shared {
],
installable: false,
stl: "none",
+ compile_multilib: "both",
export_include_dirs: ["include/include"],
arch: {
arm64: {
@@ -723,6 +1010,7 @@ cc_prebuilt_library_shared {
"apex2",
],
stl: "none",
+ compile_multilib: "both",
export_include_dirs: ["include/include"],
arch: {
arm64: {
@@ -824,6 +1112,7 @@ cc_prebuilt_library_shared {
sdk_member_name: "mynativelib",
installable: false,
stl: "none",
+ compile_multilib: "both",
shared_libs: [
"mysdk_myothernativelib@current",
"libc",
@@ -842,6 +1131,7 @@ cc_prebuilt_library_shared {
name: "mynativelib",
prefer: false,
stl: "none",
+ compile_multilib: "both",
shared_libs: [
"myothernativelib",
"libc",
@@ -861,6 +1151,7 @@ cc_prebuilt_library_shared {
sdk_member_name: "myothernativelib",
installable: false,
stl: "none",
+ compile_multilib: "both",
system_shared_libs: ["libm"],
arch: {
arm64: {
@@ -876,6 +1167,7 @@ cc_prebuilt_library_shared {
name: "myothernativelib",
prefer: false,
stl: "none",
+ compile_multilib: "both",
system_shared_libs: ["libm"],
arch: {
arm64: {
@@ -892,6 +1184,7 @@ cc_prebuilt_library_shared {
sdk_member_name: "mysystemnativelib",
installable: false,
stl: "none",
+ compile_multilib: "both",
arch: {
arm64: {
srcs: ["arm64/lib/mysystemnativelib.so"],
@@ -906,6 +1199,7 @@ cc_prebuilt_library_shared {
name: "mysystemnativelib",
prefer: false,
stl: "none",
+ compile_multilib: "both",
arch: {
arm64: {
srcs: ["arm64/lib/mysystemnativelib.so"],
@@ -974,13 +1268,20 @@ cc_prebuilt_library_shared {
installable: false,
sdk_version: "minimum",
stl: "none",
+ compile_multilib: "both",
export_include_dirs: ["include/include"],
- arch: {
- x86_64: {
+ target: {
+ host: {
+ enabled: false,
+ },
+ linux_glibc: {
+ enabled: true,
+ },
+ linux_glibc_x86_64: {
srcs: ["x86_64/lib/mynativelib.so"],
export_include_dirs: ["x86_64/include_gen/mynativelib"],
},
- x86: {
+ linux_glibc_x86: {
srcs: ["x86/lib/mynativelib.so"],
export_include_dirs: ["x86/include_gen/mynativelib"],
},
@@ -994,13 +1295,20 @@ cc_prebuilt_library_shared {
host_supported: true,
sdk_version: "minimum",
stl: "none",
+ compile_multilib: "both",
export_include_dirs: ["include/include"],
- arch: {
- x86_64: {
+ target: {
+ host: {
+ enabled: false,
+ },
+ linux_glibc: {
+ enabled: true,
+ },
+ linux_glibc_x86_64: {
srcs: ["x86_64/lib/mynativelib.so"],
export_include_dirs: ["x86_64/include_gen/mynativelib"],
},
- x86: {
+ linux_glibc_x86: {
srcs: ["x86/lib/mynativelib.so"],
export_include_dirs: ["x86/include_gen/mynativelib"],
},
@@ -1012,6 +1320,14 @@ sdk_snapshot {
device_supported: false,
host_supported: true,
native_shared_libs: ["mysdk_mynativelib@current"],
+ target: {
+ host: {
+ enabled: false,
+ },
+ linux_glibc: {
+ enabled: true,
+ },
+ },
}
`),
checkAllCopyRules(`
@@ -1070,12 +1386,23 @@ cc_prebuilt_library_shared {
installable: false,
stl: "none",
target: {
+ host: {
+ enabled: false,
+ },
+ linux_glibc: {
+ enabled: true,
+ compile_multilib: "both",
+ },
linux_glibc_x86_64: {
srcs: ["linux_glibc/x86_64/lib/mynativelib.so"],
},
linux_glibc_x86: {
srcs: ["linux_glibc/x86/lib/mynativelib.so"],
},
+ windows: {
+ enabled: true,
+ compile_multilib: "64",
+ },
windows_x86_64: {
srcs: ["windows/x86_64/lib/mynativelib.dll"],
},
@@ -1089,12 +1416,23 @@ cc_prebuilt_library_shared {
host_supported: true,
stl: "none",
target: {
+ host: {
+ enabled: false,
+ },
+ linux_glibc: {
+ enabled: true,
+ compile_multilib: "both",
+ },
linux_glibc_x86_64: {
srcs: ["linux_glibc/x86_64/lib/mynativelib.so"],
},
linux_glibc_x86: {
srcs: ["linux_glibc/x86/lib/mynativelib.so"],
},
+ windows: {
+ enabled: true,
+ compile_multilib: "64",
+ },
windows_x86_64: {
srcs: ["windows/x86_64/lib/mynativelib.dll"],
},
@@ -1107,7 +1445,14 @@ sdk_snapshot {
host_supported: true,
native_shared_libs: ["mysdk_mynativelib@current"],
target: {
+ host: {
+ enabled: false,
+ },
+ linux_glibc: {
+ enabled: true,
+ },
windows: {
+ enabled: true,
compile_multilib: "64",
},
},
@@ -1151,6 +1496,7 @@ cc_prebuilt_library_static {
sdk_member_name: "mynativelib",
installable: false,
stl: "none",
+ compile_multilib: "both",
export_include_dirs: ["include/include"],
arch: {
arm64: {
@@ -1168,6 +1514,7 @@ cc_prebuilt_library_static {
name: "mynativelib",
prefer: false,
stl: "none",
+ compile_multilib: "both",
export_include_dirs: ["include/include"],
arch: {
arm64: {
@@ -1236,13 +1583,20 @@ cc_prebuilt_library_static {
host_supported: true,
installable: false,
stl: "none",
+ compile_multilib: "both",
export_include_dirs: ["include/include"],
- arch: {
- x86_64: {
+ target: {
+ host: {
+ enabled: false,
+ },
+ linux_glibc: {
+ enabled: true,
+ },
+ linux_glibc_x86_64: {
srcs: ["x86_64/lib/mynativelib.a"],
export_include_dirs: ["x86_64/include_gen/mynativelib"],
},
- x86: {
+ linux_glibc_x86: {
srcs: ["x86/lib/mynativelib.a"],
export_include_dirs: ["x86/include_gen/mynativelib"],
},
@@ -1255,13 +1609,20 @@ cc_prebuilt_library_static {
device_supported: false,
host_supported: true,
stl: "none",
+ compile_multilib: "both",
export_include_dirs: ["include/include"],
- arch: {
- x86_64: {
+ target: {
+ host: {
+ enabled: false,
+ },
+ linux_glibc: {
+ enabled: true,
+ },
+ linux_glibc_x86_64: {
srcs: ["x86_64/lib/mynativelib.a"],
export_include_dirs: ["x86_64/include_gen/mynativelib"],
},
- x86: {
+ linux_glibc_x86: {
srcs: ["x86/lib/mynativelib.a"],
export_include_dirs: ["x86/include_gen/mynativelib"],
},
@@ -1273,6 +1634,14 @@ module_exports_snapshot {
device_supported: false,
host_supported: true,
native_static_libs: ["myexports_mynativelib@current"],
+ target: {
+ host: {
+ enabled: false,
+ },
+ linux_glibc: {
+ enabled: true,
+ },
+ },
}
`),
checkAllCopyRules(`
@@ -1315,6 +1684,7 @@ cc_prebuilt_library {
sdk_member_name: "mynativelib",
installable: false,
stl: "none",
+ compile_multilib: "both",
export_include_dirs: ["include/include"],
arch: {
arm64: {
@@ -1340,6 +1710,7 @@ cc_prebuilt_library {
name: "mynativelib",
prefer: false,
stl: "none",
+ compile_multilib: "both",
export_include_dirs: ["include/include"],
arch: {
arm64: {
@@ -1416,9 +1787,16 @@ cc_prebuilt_library_static {
host_supported: true,
installable: false,
stl: "none",
+ compile_multilib: "64",
export_include_dirs: ["include/include"],
- arch: {
- x86_64: {
+ target: {
+ host: {
+ enabled: false,
+ },
+ linux_glibc: {
+ enabled: true,
+ },
+ linux_glibc_x86_64: {
srcs: ["x86_64/lib/mynativelib.a"],
export_include_dirs: ["x86_64/include_gen/mynativelib"],
},
@@ -1431,9 +1809,16 @@ cc_prebuilt_library_static {
device_supported: false,
host_supported: true,
stl: "none",
+ compile_multilib: "64",
export_include_dirs: ["include/include"],
- arch: {
- x86_64: {
+ target: {
+ host: {
+ enabled: false,
+ },
+ linux_glibc: {
+ enabled: true,
+ },
+ linux_glibc_x86_64: {
srcs: ["x86_64/lib/mynativelib.a"],
export_include_dirs: ["x86_64/include_gen/mynativelib"],
},
@@ -1445,9 +1830,13 @@ module_exports_snapshot {
device_supported: false,
host_supported: true,
native_static_libs: ["myexports_mynativelib@current"],
+ compile_multilib: "64",
target: {
+ host: {
+ enabled: false,
+ },
linux_glibc: {
- compile_multilib: "64",
+ enabled: true,
},
},
}`),
@@ -1483,6 +1872,7 @@ cc_prebuilt_library_headers {
name: "mysdk_mynativeheaders@current",
sdk_member_name: "mynativeheaders",
stl: "none",
+ compile_multilib: "both",
export_include_dirs: ["include/include"],
}
@@ -1490,6 +1880,7 @@ cc_prebuilt_library_headers {
name: "mynativeheaders",
prefer: false,
stl: "none",
+ compile_multilib: "both",
export_include_dirs: ["include/include"],
}
@@ -1532,7 +1923,16 @@ cc_prebuilt_library_headers {
device_supported: false,
host_supported: true,
stl: "none",
+ compile_multilib: "both",
export_include_dirs: ["include/include"],
+ target: {
+ host: {
+ enabled: false,
+ },
+ linux_glibc: {
+ enabled: true,
+ },
+ },
}
cc_prebuilt_library_headers {
@@ -1541,7 +1941,16 @@ cc_prebuilt_library_headers {
device_supported: false,
host_supported: true,
stl: "none",
+ compile_multilib: "both",
export_include_dirs: ["include/include"],
+ target: {
+ host: {
+ enabled: false,
+ },
+ linux_glibc: {
+ enabled: true,
+ },
+ },
}
sdk_snapshot {
@@ -1549,6 +1958,14 @@ sdk_snapshot {
device_supported: false,
host_supported: true,
native_header_libs: ["mysdk_mynativeheaders@current"],
+ target: {
+ host: {
+ enabled: false,
+ },
+ linux_glibc: {
+ enabled: true,
+ },
+ },
}
`),
checkAllCopyRules(`
@@ -1590,12 +2007,17 @@ cc_prebuilt_library_headers {
sdk_member_name: "mynativeheaders",
host_supported: true,
stl: "none",
+ compile_multilib: "both",
export_system_include_dirs: ["common_os/include/include"],
target: {
+ host: {
+ enabled: false,
+ },
android: {
export_include_dirs: ["android/include/include-android"],
},
linux_glibc: {
+ enabled: true,
export_include_dirs: ["linux_glibc/include/include-host"],
},
},
@@ -1606,12 +2028,17 @@ cc_prebuilt_library_headers {
prefer: false,
host_supported: true,
stl: "none",
+ compile_multilib: "both",
export_system_include_dirs: ["common_os/include/include"],
target: {
+ host: {
+ enabled: false,
+ },
android: {
export_include_dirs: ["android/include/include-android"],
},
linux_glibc: {
+ enabled: true,
export_include_dirs: ["linux_glibc/include/include-host"],
},
},
@@ -1621,6 +2048,14 @@ sdk_snapshot {
name: "mysdk@current",
host_supported: true,
native_header_libs: ["mysdk_mynativeheaders@current"],
+ target: {
+ host: {
+ enabled: false,
+ },
+ linux_glibc: {
+ enabled: true,
+ },
+ },
}
`),
checkAllCopyRules(`
@@ -1662,6 +2097,7 @@ cc_prebuilt_library_shared {
name: "mysdk_sslnil@current",
sdk_member_name: "sslnil",
installable: false,
+ compile_multilib: "both",
arch: {
arm64: {
srcs: ["arm64/lib/sslnil.so"],
@@ -1675,6 +2111,7 @@ cc_prebuilt_library_shared {
cc_prebuilt_library_shared {
name: "sslnil",
prefer: false,
+ compile_multilib: "both",
arch: {
arm64: {
srcs: ["arm64/lib/sslnil.so"],
@@ -1689,6 +2126,7 @@ cc_prebuilt_library_shared {
name: "mysdk_sslempty@current",
sdk_member_name: "sslempty",
installable: false,
+ compile_multilib: "both",
system_shared_libs: [],
arch: {
arm64: {
@@ -1703,6 +2141,7 @@ cc_prebuilt_library_shared {
cc_prebuilt_library_shared {
name: "sslempty",
prefer: false,
+ compile_multilib: "both",
system_shared_libs: [],
arch: {
arm64: {
@@ -1718,6 +2157,7 @@ cc_prebuilt_library_shared {
name: "mysdk_sslnonempty@current",
sdk_member_name: "sslnonempty",
installable: false,
+ compile_multilib: "both",
system_shared_libs: ["mysdk_sslnil@current"],
arch: {
arm64: {
@@ -1732,6 +2172,7 @@ cc_prebuilt_library_shared {
cc_prebuilt_library_shared {
name: "sslnonempty",
prefer: false,
+ compile_multilib: "both",
system_shared_libs: ["sslnil"],
arch: {
arm64: {
@@ -1780,7 +2221,11 @@ cc_prebuilt_library_shared {
sdk_member_name: "sslvariants",
host_supported: true,
installable: false,
+ compile_multilib: "both",
target: {
+ host: {
+ enabled: false,
+ },
android: {
system_shared_libs: [],
},
@@ -1790,6 +2235,9 @@ cc_prebuilt_library_shared {
android_arm: {
srcs: ["android/arm/lib/sslvariants.so"],
},
+ linux_glibc: {
+ enabled: true,
+ },
linux_glibc_x86_64: {
srcs: ["linux_glibc/x86_64/lib/sslvariants.so"],
},
@@ -1803,7 +2251,11 @@ cc_prebuilt_library_shared {
name: "sslvariants",
prefer: false,
host_supported: true,
+ compile_multilib: "both",
target: {
+ host: {
+ enabled: false,
+ },
android: {
system_shared_libs: [],
},
@@ -1813,6 +2265,9 @@ cc_prebuilt_library_shared {
android_arm: {
srcs: ["android/arm/lib/sslvariants.so"],
},
+ linux_glibc: {
+ enabled: true,
+ },
linux_glibc_x86_64: {
srcs: ["linux_glibc/x86_64/lib/sslvariants.so"],
},
@@ -1826,6 +2281,14 @@ sdk_snapshot {
name: "mysdk@current",
host_supported: true,
native_shared_libs: ["mysdk_sslvariants@current"],
+ target: {
+ host: {
+ enabled: false,
+ },
+ linux_glibc: {
+ enabled: true,
+ },
+ },
}
`))
}
@@ -1859,6 +2322,7 @@ cc_prebuilt_library_shared {
name: "mysdk_stubslib@current",
sdk_member_name: "stubslib",
installable: false,
+ compile_multilib: "both",
stubs: {
versions: ["3"],
},
@@ -1875,6 +2339,7 @@ cc_prebuilt_library_shared {
cc_prebuilt_library_shared {
name: "stubslib",
prefer: false,
+ compile_multilib: "both",
stubs: {
versions: ["3"],
},
@@ -1928,16 +2393,23 @@ cc_prebuilt_library_shared {
sdk_member_name: "stubslib",
host_supported: true,
installable: false,
+ compile_multilib: "both",
stubs: {
versions: ["3"],
},
target: {
+ host: {
+ enabled: false,
+ },
android_arm64: {
srcs: ["android/arm64/lib/stubslib.so"],
},
android_arm: {
srcs: ["android/arm/lib/stubslib.so"],
},
+ linux_glibc: {
+ enabled: true,
+ },
linux_glibc_x86_64: {
srcs: ["linux_glibc/x86_64/lib/stubslib.so"],
},
@@ -1951,16 +2423,23 @@ cc_prebuilt_library_shared {
name: "stubslib",
prefer: false,
host_supported: true,
+ compile_multilib: "both",
stubs: {
versions: ["3"],
},
target: {
+ host: {
+ enabled: false,
+ },
android_arm64: {
srcs: ["android/arm64/lib/stubslib.so"],
},
android_arm: {
srcs: ["android/arm/lib/stubslib.so"],
},
+ linux_glibc: {
+ enabled: true,
+ },
linux_glibc_x86_64: {
srcs: ["linux_glibc/x86_64/lib/stubslib.so"],
},
@@ -1974,6 +2453,14 @@ sdk_snapshot {
name: "mysdk@current",
host_supported: true,
native_shared_libs: ["mysdk_stubslib@current"],
+ target: {
+ host: {
+ enabled: false,
+ },
+ linux_glibc: {
+ enabled: true,
+ },
+ },
}
`))
}
@@ -2003,13 +2490,20 @@ cc_prebuilt_library_shared {
host_supported: true,
installable: false,
unique_host_soname: true,
+ compile_multilib: "both",
target: {
+ host: {
+ enabled: false,
+ },
android_arm64: {
srcs: ["android/arm64/lib/mylib.so"],
},
android_arm: {
srcs: ["android/arm/lib/mylib.so"],
},
+ linux_glibc: {
+ enabled: true,
+ },
linux_glibc_x86_64: {
srcs: ["linux_glibc/x86_64/lib/mylib-host.so"],
},
@@ -2024,13 +2518,20 @@ cc_prebuilt_library_shared {
prefer: false,
host_supported: true,
unique_host_soname: true,
+ compile_multilib: "both",
target: {
+ host: {
+ enabled: false,
+ },
android_arm64: {
srcs: ["android/arm64/lib/mylib.so"],
},
android_arm: {
srcs: ["android/arm/lib/mylib.so"],
},
+ linux_glibc: {
+ enabled: true,
+ },
linux_glibc_x86_64: {
srcs: ["linux_glibc/x86_64/lib/mylib-host.so"],
},
@@ -2044,6 +2545,14 @@ sdk_snapshot {
name: "mysdk@current",
host_supported: true,
native_shared_libs: ["mysdk_mylib@current"],
+ target: {
+ host: {
+ enabled: false,
+ },
+ linux_glibc: {
+ enabled: true,
+ },
+ },
}
`),
checkAllCopyRules(`
diff --git a/sdk/java_sdk_test.go b/sdk/java_sdk_test.go
index aee04a163..5911c718d 100644
--- a/sdk/java_sdk_test.go
+++ b/sdk/java_sdk_test.go
@@ -51,10 +51,10 @@ java_system_modules_import {
name: "core-current-stubs-system-modules",
}
java_system_modules_import {
- name: "legacy-core-platform-api-stubs-system-modules",
+ name: "stable-core-platform-api-stubs-system-modules",
}
java_import {
- name: "legacy.core.platform.api.stubs",
+ name: "stable.core.platform.api.stubs",
}
java_import {
name: "android_stubs_current",
@@ -204,11 +204,11 @@ func TestBasicSdkWithJavaLibrary(t *testing.T) {
}
`)
- sdkMemberV1 := result.ctx.ModuleForTests("sdkmember_mysdk_1", "android_common_myapex").Rule("combineJar").Output
- sdkMemberV2 := result.ctx.ModuleForTests("sdkmember_mysdk_2", "android_common_myapex2").Rule("combineJar").Output
+ sdkMemberV1 := result.ctx.ModuleForTests("sdkmember_mysdk_1", "android_common").Rule("combineJar").Output
+ sdkMemberV2 := result.ctx.ModuleForTests("sdkmember_mysdk_2", "android_common").Rule("combineJar").Output
- javalibForMyApex := result.ctx.ModuleForTests("myjavalib", "android_common_myapex")
- javalibForMyApex2 := result.ctx.ModuleForTests("myjavalib", "android_common_myapex2")
+ javalibForMyApex := result.ctx.ModuleForTests("myjavalib", "android_common_apex10000_mysdk_1")
+ javalibForMyApex2 := result.ctx.ModuleForTests("myjavalib", "android_common_apex10000_mysdk_2")
// Depending on the uses_sdks value, different libs are linked
ensureListContains(t, pathsToStrings(javalibForMyApex.Rule("javac").Implicits), sdkMemberV1.String())
@@ -1424,8 +1424,8 @@ sdk_snapshot {
.intermediates/myjavalib.stubs.source.system/android_common/myjavalib.stubs.source.system_api.txt -> sdk_library/system/myjavalib.txt
.intermediates/myjavalib.stubs.source.system/android_common/myjavalib.stubs.source.system_removed.txt -> sdk_library/system/myjavalib-removed.txt
.intermediates/myjavalib.stubs.module_lib/android_common/javac/myjavalib.stubs.module_lib.jar -> sdk_library/module-lib/myjavalib-stubs.jar
-.intermediates/myjavalib.api.module_lib/android_common/myjavalib.api.module_lib_api.txt -> sdk_library/module-lib/myjavalib.txt
-.intermediates/myjavalib.api.module_lib/android_common/myjavalib.api.module_lib_removed.txt -> sdk_library/module-lib/myjavalib-removed.txt
+.intermediates/myjavalib.stubs.source.module_lib/android_common/myjavalib.stubs.source.module_lib_api.txt -> sdk_library/module-lib/myjavalib.txt
+.intermediates/myjavalib.stubs.source.module_lib/android_common/myjavalib.stubs.source.module_lib_removed.txt -> sdk_library/module-lib/myjavalib-removed.txt
`),
checkMergeZips(
".intermediates/mysdk/common_os/tmp/sdk_library/public/myjavalib_stub_sources.zip",
diff --git a/sdk/sdk.go b/sdk/sdk.go
index 3e760080e..759102028 100644
--- a/sdk/sdk.go
+++ b/sdk/sdk.go
@@ -406,13 +406,17 @@ func memberInterVersionMutator(mctx android.BottomUpMutatorContext) {
// Step 4: transitively ripple down the SDK requirements from the root modules like APEX to its
// descendants
func sdkDepsMutator(mctx android.TopDownMutatorContext) {
- if m, ok := mctx.Module().(android.SdkAware); ok {
+ if parent, ok := mctx.Module().(interface {
+ android.DepIsInSameApex
+ android.RequiredSdks
+ }); ok {
// Module types for Mainline modules (e.g. APEX) are expected to implement RequiredSdks()
// by reading its own properties like `uses_sdks`.
- requiredSdks := m.RequiredSdks()
+ requiredSdks := parent.RequiredSdks()
if len(requiredSdks) > 0 {
mctx.VisitDirectDeps(func(m android.Module) {
- if dep, ok := m.(android.SdkAware); ok {
+ // Only propagate required sdks from the apex onto its contents.
+ if dep, ok := m.(android.SdkAware); ok && parent.DepIsInSameApex(mctx, dep) {
dep.BuildWithSdks(requiredSdks)
}
})
@@ -423,15 +427,28 @@ func sdkDepsMutator(mctx android.TopDownMutatorContext) {
// Step 5: if libfoo.mysdk.11 is in the context where version 11 of mysdk is requested, the
// versioned module is used instead of the un-versioned (in-development) module libfoo
func sdkDepsReplaceMutator(mctx android.BottomUpMutatorContext) {
- if m, ok := mctx.Module().(android.SdkAware); ok && m.IsInAnySdk() {
- if sdk := m.ContainingSdk(); !sdk.Unversioned() {
- if m.RequiredSdks().Contains(sdk) {
- // Note that this replacement is done only for the modules that have the same
- // variations as the current module. Since current module is already mutated for
- // apex references in other APEXes are not affected by this replacement.
- memberName := m.MemberName()
- mctx.ReplaceDependencies(memberName)
- }
+ if versionedSdkMember, ok := mctx.Module().(android.SdkAware); ok && versionedSdkMember.IsInAnySdk() {
+ if sdk := versionedSdkMember.ContainingSdk(); !sdk.Unversioned() {
+ // Only replace dependencies to <sdkmember> with <sdkmember@required-version>
+ // if the depending module requires it. e.g.
+ // foo -> sdkmember
+ // will be transformed to:
+ // foo -> sdkmember@1
+ // if and only if foo is a member of an APEX that requires version 1 of the
+ // sdk containing sdkmember.
+ memberName := versionedSdkMember.MemberName()
+
+ // Replace dependencies on sdkmember with a dependency on the current module which
+ // is a versioned prebuilt of the sdkmember if required.
+ mctx.ReplaceDependenciesIf(memberName, func(from blueprint.Module, tag blueprint.DependencyTag, to blueprint.Module) bool {
+ // from - foo
+ // to - sdkmember
+ replace := false
+ if parent, ok := from.(android.RequiredSdks); ok {
+ replace = parent.RequiredSdks().Contains(sdk)
+ }
+ return replace
+ })
}
}
}
diff --git a/sdk/testing.go b/sdk/testing.go
index 34ea8f0cc..b53558d9f 100644
--- a/sdk/testing.go
+++ b/sdk/testing.go
@@ -97,6 +97,11 @@ func testSdkContext(bp string, fs map[string][]byte, extraOsTypes []android.OsTy
ctx.PreArchMutators(android.RegisterVisibilityRuleChecker)
ctx.PreArchMutators(android.RegisterDefaultsPreArchMutators)
ctx.PreArchMutators(android.RegisterComponentsMutator)
+
+ android.RegisterPrebuiltMutators(ctx)
+
+ // Register these after the prebuilt mutators have been registered to match what
+ // happens at runtime.
ctx.PreArchMutators(android.RegisterVisibilityRuleGatherer)
ctx.PostDepsMutators(android.RegisterVisibilityRuleEnforcer)
diff --git a/sdk/update.go b/sdk/update.go
index cf2500826..537ab13cb 100644
--- a/sdk/update.go
+++ b/sdk/update.go
@@ -43,7 +43,7 @@ var (
zipFiles = pctx.AndroidStaticRule("SnapshotZipFiles",
blueprint.RuleParams{
- Command: `${config.SoongZipCmd} -C $basedir -l $out.rsp -o $out`,
+ Command: `${config.SoongZipCmd} -C $basedir -r $out.rsp -o $out`,
CommandDeps: []string{
"${config.SoongZipCmd}",
},
@@ -262,7 +262,7 @@ func (s *sdk) buildSnapshot(ctx android.ModuleContext, sdkVariants []*sdk) andro
memberCtx := &memberContext{ctx, builder, memberType, member.name}
prebuiltModule := memberType.AddPrebuiltModule(memberCtx, member)
- s.createMemberSnapshot(memberCtx, member, prebuiltModule)
+ s.createMemberSnapshot(memberCtx, member, prebuiltModule.(*bpModule))
}
// Create a transformer that will transform an unversioned module into a versioned module.
@@ -323,19 +323,62 @@ func (s *sdk) buildSnapshot(ctx android.ModuleContext, sdkVariants []*sdk) andro
// Add properties common to all os types.
s.addMemberPropertiesToPropertySet(builder, snapshotModule, commonDynamicMemberProperties)
- // Iterate over the os types in a fixed order.
+ // Optimize other per-variant properties, besides the dynamic member lists.
+ type variantProperties struct {
+ Compile_multilib string `android:"arch_variant"`
+ }
+ var variantPropertiesContainers []propertiesContainer
+ variantToProperties := make(map[*sdk]*variantProperties)
+ for _, sdkVariant := range sdkVariants {
+ props := &variantProperties{
+ Compile_multilib: sdkVariant.multilibUsages.String(),
+ }
+ variantPropertiesContainers = append(variantPropertiesContainers, &dynamicMemberPropertiesContainer{sdkVariant, props})
+ variantToProperties[sdkVariant] = props
+ }
+ commonVariantProperties := variantProperties{}
+ extractor = newCommonValueExtractor(commonVariantProperties)
+ extractCommonProperties(ctx, extractor, &commonVariantProperties, variantPropertiesContainers)
+ if commonVariantProperties.Compile_multilib != "" && commonVariantProperties.Compile_multilib != "both" {
+ // Compile_multilib defaults to both so only needs to be set when it's
+ // specified and not both.
+ snapshotModule.AddProperty("compile_multilib", commonVariantProperties.Compile_multilib)
+ }
+
targetPropertySet := snapshotModule.AddPropertySet("target")
+
+ // If host is supported and any member is host OS dependent then disable host
+ // by default, so that we can enable each host OS variant explicitly. This
+ // avoids problems with implicitly enabled OS variants when the snapshot is
+ // used, which might be different from this run (e.g. different build OS).
+ hasHostOsDependentMember := false
+ if s.HostSupported() {
+ for _, memberRef := range memberRefs {
+ if memberRef.memberType.IsHostOsDependent() {
+ hasHostOsDependentMember = true
+ break
+ }
+ }
+ if hasHostOsDependentMember {
+ hostPropertySet := targetPropertySet.AddPropertySet("host")
+ hostPropertySet.AddProperty("enabled", false)
+ }
+ }
+
+ // Iterate over the os types in a fixed order.
for _, osType := range s.getPossibleOsTypes() {
if sdkVariant, ok := osTypeToMemberProperties[osType]; ok {
osPropertySet := targetPropertySet.AddPropertySet(sdkVariant.Target().Os.Name)
- // Compile_multilib defaults to both and must always be set to both on the
- // device and so only needs to be set when targeted at the host and is neither
- // unspecified or both.
- multilib := sdkVariant.multilibUsages
- if (osType.Class == android.Host || osType.Class == android.HostCross) &&
- multilib != multilibNone && multilib != multilibBoth {
- osPropertySet.AddProperty("compile_multilib", multilib.String())
+ // Enable the variant explicitly when we've disabled it by default on host.
+ if hasHostOsDependentMember &&
+ (osType.Class == android.Host || osType.Class == android.HostCross) {
+ osPropertySet.AddProperty("enabled", true)
+ }
+
+ variantProps := variantToProperties[sdkVariant]
+ if variantProps.Compile_multilib != "" && variantProps.Compile_multilib != "both" {
+ osPropertySet.AddProperty("compile_multilib", variantProps.Compile_multilib)
}
s.addMemberPropertiesToPropertySet(builder, osPropertySet, sdkVariant.dynamicMemberTypeListProperties)
@@ -794,6 +837,17 @@ func (s *snapshotBuilder) isInternalMember(memberName string) bool {
return !ok
}
+// Add the properties from the given SdkMemberProperties to the blueprint
+// property set. This handles common properties in SdkMemberPropertiesBase and
+// calls the member-specific AddToPropertySet for the rest.
+func addSdkMemberPropertiesToSet(ctx *memberContext, memberProperties android.SdkMemberProperties, targetPropertySet android.BpPropertySet) {
+ if memberProperties.Base().Compile_multilib != "" {
+ targetPropertySet.AddProperty("compile_multilib", memberProperties.Base().Compile_multilib)
+ }
+
+ memberProperties.AddToPropertySet(ctx, targetPropertySet)
+}
+
type sdkMemberRef struct {
memberType android.SdkMemberType
variant android.SdkAware
@@ -964,9 +1018,12 @@ func (osInfo *osTypeSpecificInfo) addToPropertySet(ctx *memberContext, bpModule
var osPropertySet android.BpPropertySet
var archPropertySet android.BpPropertySet
var archOsPrefix string
- if osInfo.Properties.Base().Os_count == 1 {
- // There is only one os type present in the variants so don't bother
- // with adding target specific properties.
+ if osInfo.Properties.Base().Os_count == 1 &&
+ (osInfo.osType.Class == android.Device || !ctx.memberType.IsHostOsDependent()) {
+ // There is only one OS type present in the variants and it shouldn't have a
+ // variant-specific target. The latter is the case if it's either for device
+ // where there is only one OS (android), or for host and the member type
+ // isn't host OS dependent.
// Create a structure that looks like:
// module_type {
@@ -1003,13 +1060,19 @@ func (osInfo *osTypeSpecificInfo) addToPropertySet(ctx *memberContext, bpModule
osPropertySet = targetPropertySet.AddPropertySet(osType.Name)
archPropertySet = targetPropertySet
+ // Enable the variant explicitly when we've disabled it by default on host.
+ if ctx.memberType.IsHostOsDependent() &&
+ (osType.Class == android.Host || osType.Class == android.HostCross) {
+ osPropertySet.AddProperty("enabled", true)
+ }
+
// Arch specific properties need to be added to an os and arch specific
// section prefixed with <os>_.
archOsPrefix = osType.Name + "_"
}
// Add the os specific but arch independent properties to the module.
- osInfo.Properties.AddToPropertySet(ctx, osPropertySet)
+ addSdkMemberPropertiesToSet(ctx, osInfo.Properties, osPropertySet)
// Add arch (and possibly os) specific sections for each set of arch (and possibly
// os) specific properties.
@@ -1111,11 +1174,11 @@ func (archInfo *archTypeSpecificInfo) optimizeProperties(ctx *memberContext, com
func (archInfo *archTypeSpecificInfo) addToPropertySet(ctx *memberContext, archPropertySet android.BpPropertySet, archOsPrefix string) {
archTypeName := archInfo.archType.Name
archTypePropertySet := archPropertySet.AddPropertySet(archOsPrefix + archTypeName)
- archInfo.Properties.AddToPropertySet(ctx, archTypePropertySet)
+ addSdkMemberPropertiesToSet(ctx, archInfo.Properties, archTypePropertySet)
for _, linkInfo := range archInfo.linkInfos {
linkPropertySet := archTypePropertySet.AddPropertySet(linkInfo.linkType)
- linkInfo.Properties.AddToPropertySet(ctx, linkPropertySet)
+ addSdkMemberPropertiesToSet(ctx, linkInfo.Properties, linkPropertySet)
}
}
@@ -1173,7 +1236,7 @@ func (m *memberContext) Name() string {
return m.name
}
-func (s *sdk) createMemberSnapshot(ctx *memberContext, member *sdkMember, bpModule android.BpModule) {
+func (s *sdk) createMemberSnapshot(ctx *memberContext, member *sdkMember, bpModule *bpModule) {
memberType := member.memberType
@@ -1221,12 +1284,24 @@ func (s *sdk) createMemberSnapshot(ctx *memberContext, member *sdkMember, bpModu
extractCommonProperties(ctx.sdkMemberContext, commonValueExtractor, commonProperties, osSpecificPropertiesContainers)
// Add the common properties to the module.
- commonProperties.AddToPropertySet(ctx, bpModule)
+ addSdkMemberPropertiesToSet(ctx, commonProperties, bpModule)
// Create a target property set into which target specific properties can be
// added.
targetPropertySet := bpModule.AddPropertySet("target")
+ // If the member is host OS dependent and has host_supported then disable by
+ // default and enable each host OS variant explicitly. This avoids problems
+ // with implicitly enabled OS variants when the snapshot is used, which might
+ // be different from this run (e.g. different build OS).
+ if ctx.memberType.IsHostOsDependent() {
+ hostSupported := bpModule.getValue("host_supported") == true // Missing means false.
+ if hostSupported {
+ hostPropertySet := targetPropertySet.AddPropertySet("host")
+ hostPropertySet.AddProperty("enabled", false)
+ }
+ }
+
// Iterate over the os types in a fixed order.
for _, osType := range s.getPossibleOsTypes() {
osInfo := osTypeToInfo[osType]
diff --git a/sh/Android.bp b/sh/Android.bp
index 0f40c5f68..e5ffeefb4 100644
--- a/sh/Android.bp
+++ b/sh/Android.bp
@@ -5,6 +5,7 @@ bootstrap_go_package {
"blueprint",
"soong",
"soong-android",
+ "soong-cc",
"soong-tradefed",
],
srcs: [
diff --git a/sh/sh_binary.go b/sh/sh_binary.go
index f28b2b685..f3f4a4aa7 100644
--- a/sh/sh_binary.go
+++ b/sh/sh_binary.go
@@ -17,11 +17,14 @@ package sh
import (
"fmt"
"path/filepath"
+ "sort"
"strings"
+ "github.com/google/blueprint"
"github.com/google/blueprint/proptools"
"android/soong/android"
+ "android/soong/cc"
"android/soong/tradefed"
)
@@ -61,6 +64,12 @@ type shBinaryProperties struct {
// install symlinks to the binary
Symlinks []string `android:"arch_variant"`
+
+ // Make this module available when building for ramdisk.
+ Ramdisk_available *bool
+
+ // Make this module available when building for recovery.
+ Recovery_available *bool
}
type TestProperties struct {
@@ -88,6 +97,20 @@ type TestProperties struct {
// doesn't exist next to the Android.bp, this attribute doesn't need to be set to true
// explicitly.
Auto_gen_config *bool
+
+ // list of binary modules that should be installed alongside the test
+ Data_bins []string `android:"path,arch_variant"`
+
+ // list of library modules that should be installed alongside the test
+ Data_libs []string `android:"path,arch_variant"`
+
+ // list of device binary modules that should be installed alongside the test.
+ // Only available for host sh_test modules.
+ Data_device_bins []string `android:"path,arch_variant"`
+
+ // list of device library modules that should be installed alongside the test.
+ // Only available for host sh_test modules.
+ Data_device_libs []string `android:"path,arch_variant"`
}
type ShBinary struct {
@@ -111,6 +134,8 @@ type ShTest struct {
data android.Paths
testConfig android.Path
+
+ dataModules map[string]android.Path
}
func (s *ShBinary) HostToolPath() android.OptionalPath {
@@ -139,6 +164,29 @@ func (s *ShBinary) Symlinks() []string {
return s.properties.Symlinks
}
+var _ android.ImageInterface = (*ShBinary)(nil)
+
+func (s *ShBinary) ImageMutatorBegin(ctx android.BaseModuleContext) {}
+
+func (s *ShBinary) CoreVariantNeeded(ctx android.BaseModuleContext) bool {
+ return !s.ModuleBase.InstallInRecovery() && !s.ModuleBase.InstallInRamdisk()
+}
+
+func (s *ShBinary) RamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
+ return proptools.Bool(s.properties.Ramdisk_available) || s.ModuleBase.InstallInRamdisk()
+}
+
+func (s *ShBinary) RecoveryVariantNeeded(ctx android.BaseModuleContext) bool {
+ return proptools.Bool(s.properties.Recovery_available) || s.ModuleBase.InstallInRecovery()
+}
+
+func (s *ShBinary) ExtraImageVariations(ctx android.BaseModuleContext) []string {
+ return nil
+}
+
+func (s *ShBinary) SetImageVariation(ctx android.BaseModuleContext, variation string, module android.Module) {
+}
+
func (s *ShBinary) generateAndroidBuildActions(ctx android.ModuleContext) {
s.sourceFilePath = android.PathForModuleSrc(ctx, proptools.String(s.properties.Src))
filename := proptools.String(s.properties.Filename)
@@ -192,6 +240,50 @@ func (s *ShBinary) customAndroidMkEntries(entries *android.AndroidMkEntries) {
}
}
+type dependencyTag struct {
+ blueprint.BaseDependencyTag
+ name string
+}
+
+var (
+ shTestDataBinsTag = dependencyTag{name: "dataBins"}
+ shTestDataLibsTag = dependencyTag{name: "dataLibs"}
+ shTestDataDeviceBinsTag = dependencyTag{name: "dataDeviceBins"}
+ shTestDataDeviceLibsTag = dependencyTag{name: "dataDeviceLibs"}
+)
+
+var sharedLibVariations = []blueprint.Variation{{Mutator: "link", Variation: "shared"}}
+
+func (s *ShTest) DepsMutator(ctx android.BottomUpMutatorContext) {
+ s.ShBinary.DepsMutator(ctx)
+
+ ctx.AddFarVariationDependencies(ctx.Target().Variations(), shTestDataBinsTag, s.testProperties.Data_bins...)
+ ctx.AddFarVariationDependencies(append(ctx.Target().Variations(), sharedLibVariations...),
+ shTestDataLibsTag, s.testProperties.Data_libs...)
+ if ctx.Target().Os.Class == android.Host && len(ctx.Config().Targets[android.Android]) > 0 {
+ deviceVariations := ctx.Config().Targets[android.Android][0].Variations()
+ ctx.AddFarVariationDependencies(deviceVariations, shTestDataDeviceBinsTag, s.testProperties.Data_device_bins...)
+ ctx.AddFarVariationDependencies(append(deviceVariations, sharedLibVariations...),
+ shTestDataDeviceLibsTag, s.testProperties.Data_device_libs...)
+ } else if ctx.Target().Os.Class != android.Host {
+ if len(s.testProperties.Data_device_bins) > 0 {
+ ctx.PropertyErrorf("data_device_bins", "only available for host modules")
+ }
+ if len(s.testProperties.Data_device_libs) > 0 {
+ ctx.PropertyErrorf("data_device_libs", "only available for host modules")
+ }
+ }
+}
+
+func (s *ShTest) addToDataModules(ctx android.ModuleContext, relPath string, path android.Path) {
+ if _, exists := s.dataModules[relPath]; exists {
+ ctx.ModuleErrorf("data modules have a conflicting installation path, %v - %s, %s",
+ relPath, s.dataModules[relPath].String(), path.String())
+ return
+ }
+ s.dataModules[relPath] = path
+}
+
func (s *ShTest) GenerateAndroidBuildActions(ctx android.ModuleContext) {
s.ShBinary.generateAndroidBuildActions(ctx)
testDir := "nativetest"
@@ -223,6 +315,50 @@ func (s *ShTest) GenerateAndroidBuildActions(ctx android.ModuleContext) {
}
s.testConfig = tradefed.AutoGenShellTestConfig(ctx, s.testProperties.Test_config,
s.testProperties.Test_config_template, s.testProperties.Test_suites, configs, s.testProperties.Auto_gen_config, s.outputFilePath.Base())
+
+ s.dataModules = make(map[string]android.Path)
+ ctx.VisitDirectDeps(func(dep android.Module) {
+ depTag := ctx.OtherModuleDependencyTag(dep)
+ switch depTag {
+ case shTestDataBinsTag, shTestDataDeviceBinsTag:
+ if cc, isCc := dep.(*cc.Module); isCc {
+ s.addToDataModules(ctx, cc.OutputFile().Path().Base(), cc.OutputFile().Path())
+ return
+ }
+ property := "data_bins"
+ if depTag == shTestDataDeviceBinsTag {
+ property = "data_device_bins"
+ }
+ ctx.PropertyErrorf(property, "%q of type %q is not supported", dep.Name(), ctx.OtherModuleType(dep))
+ case shTestDataLibsTag, shTestDataDeviceLibsTag:
+ if cc, isCc := dep.(*cc.Module); isCc {
+ // Copy to an intermediate output directory to append "lib[64]" to the path,
+ // so that it's compatible with the default rpath values.
+ var relPath string
+ if cc.Arch().ArchType.Multilib == "lib64" {
+ relPath = filepath.Join("lib64", cc.OutputFile().Path().Base())
+ } else {
+ relPath = filepath.Join("lib", cc.OutputFile().Path().Base())
+ }
+ if _, exist := s.dataModules[relPath]; exist {
+ return
+ }
+ relocatedLib := android.PathForModuleOut(ctx, "relocated", relPath)
+ ctx.Build(pctx, android.BuildParams{
+ Rule: android.Cp,
+ Input: cc.OutputFile().Path(),
+ Output: relocatedLib,
+ })
+ s.addToDataModules(ctx, relPath, relocatedLib)
+ return
+ }
+ property := "data_libs"
+ if depTag == shTestDataDeviceBinsTag {
+ property = "data_device_libs"
+ }
+ ctx.PropertyErrorf(property, "%q of type %q is not supported", dep.Name(), ctx.OtherModuleType(dep))
+ }
+ })
}
func (s *ShTest) InstallInData() bool {
@@ -251,6 +387,15 @@ func (s *ShTest) AndroidMkEntries() []android.AndroidMkEntries {
path = strings.TrimSuffix(path, rel)
entries.AddStrings("LOCAL_TEST_DATA", path+":"+rel)
}
+ relPaths := make([]string, 0)
+ for relPath, _ := range s.dataModules {
+ relPaths = append(relPaths, relPath)
+ }
+ sort.Strings(relPaths)
+ for _, relPath := range relPaths {
+ dir := strings.TrimSuffix(s.dataModules[relPath].String(), relPath)
+ entries.AddStrings("LOCAL_TEST_DATA", dir+":"+relPath)
+ }
},
},
}}
diff --git a/sh/sh_binary_test.go b/sh/sh_binary_test.go
index 3bfe6110a..0aa607b6f 100644
--- a/sh/sh_binary_test.go
+++ b/sh/sh_binary_test.go
@@ -3,10 +3,12 @@ package sh
import (
"io/ioutil"
"os"
+ "path/filepath"
"reflect"
"testing"
"android/soong/android"
+ "android/soong/cc"
)
var buildDir string
@@ -46,6 +48,9 @@ func testShBinary(t *testing.T, bp string) (*android.TestContext, android.Config
ctx := android.NewTestArchContext()
ctx.RegisterModuleType("sh_test", ShTestFactory)
ctx.RegisterModuleType("sh_test_host", ShTestHostFactory)
+
+ cc.RegisterRequiredBuildComponentsForTest(ctx)
+
ctx.Register(config)
_, errs := ctx.ParseFileList(".", []string{"Android.bp"})
android.FailIfErrored(t, errs)
@@ -105,6 +110,65 @@ func TestShTest(t *testing.T) {
}
}
+func TestShTest_dataModules(t *testing.T) {
+ ctx, config := testShBinary(t, `
+ sh_test {
+ name: "foo",
+ src: "test.sh",
+ host_supported: true,
+ data_bins: ["bar"],
+ data_libs: ["libbar"],
+ }
+
+ cc_binary {
+ name: "bar",
+ host_supported: true,
+ shared_libs: ["libbar"],
+ no_libcrt: true,
+ nocrt: true,
+ system_shared_libs: [],
+ stl: "none",
+ }
+
+ cc_library {
+ name: "libbar",
+ host_supported: true,
+ no_libcrt: true,
+ nocrt: true,
+ system_shared_libs: [],
+ stl: "none",
+ }
+ `)
+
+ buildOS := android.BuildOs.String()
+ arches := []string{"android_arm64_armv8-a", buildOS + "_x86_64"}
+ for _, arch := range arches {
+ variant := ctx.ModuleForTests("foo", arch)
+
+ libExt := ".so"
+ if arch == "darwin_x86_64" {
+ libExt = ".dylib"
+ }
+ relocated := variant.Output("relocated/lib64/libbar" + libExt)
+ expectedInput := filepath.Join(buildDir, ".intermediates/libbar/"+arch+"_shared/libbar"+libExt)
+ if relocated.Input.String() != expectedInput {
+ t.Errorf("Unexpected relocation input, expected: %q, actual: %q",
+ expectedInput, relocated.Input.String())
+ }
+
+ mod := variant.Module().(*ShTest)
+ entries := android.AndroidMkEntriesForTest(t, config, "", mod)[0]
+ expectedData := []string{
+ filepath.Join(buildDir, ".intermediates/bar", arch, ":bar"),
+ filepath.Join(buildDir, ".intermediates/foo", arch, "relocated/:lib64/libbar"+libExt),
+ }
+ actualData := entries.EntryMap["LOCAL_TEST_DATA"]
+ if !reflect.DeepEqual(expectedData, actualData) {
+ t.Errorf("Unexpected test data, expected: %q, actual: %q", expectedData, actualData)
+ }
+ }
+}
+
func TestShTestHost(t *testing.T) {
ctx, _ := testShBinary(t, `
sh_test_host {
@@ -124,3 +188,53 @@ func TestShTestHost(t *testing.T) {
t.Errorf("host bit is not set for a sh_test_host module.")
}
}
+
+func TestShTestHost_dataDeviceModules(t *testing.T) {
+ ctx, config := testShBinary(t, `
+ sh_test_host {
+ name: "foo",
+ src: "test.sh",
+ data_device_bins: ["bar"],
+ data_device_libs: ["libbar"],
+ }
+
+ cc_binary {
+ name: "bar",
+ shared_libs: ["libbar"],
+ no_libcrt: true,
+ nocrt: true,
+ system_shared_libs: [],
+ stl: "none",
+ }
+
+ cc_library {
+ name: "libbar",
+ no_libcrt: true,
+ nocrt: true,
+ system_shared_libs: [],
+ stl: "none",
+ }
+ `)
+
+ buildOS := android.BuildOs.String()
+ variant := ctx.ModuleForTests("foo", buildOS+"_x86_64")
+
+ relocated := variant.Output("relocated/lib64/libbar.so")
+ expectedInput := filepath.Join(buildDir, ".intermediates/libbar/android_arm64_armv8-a_shared/libbar.so")
+ if relocated.Input.String() != expectedInput {
+ t.Errorf("Unexpected relocation input, expected: %q, actual: %q",
+ expectedInput, relocated.Input.String())
+ }
+
+ mod := variant.Module().(*ShTest)
+ entries := android.AndroidMkEntriesForTest(t, config, "", mod)[0]
+ expectedData := []string{
+ filepath.Join(buildDir, ".intermediates/bar/android_arm64_armv8-a/:bar"),
+ // libbar has been relocated, and so has a variant that matches the host arch.
+ filepath.Join(buildDir, ".intermediates/foo/"+buildOS+"_x86_64/relocated/:lib64/libbar.so"),
+ }
+ actualData := entries.EntryMap["LOCAL_TEST_DATA"]
+ if !reflect.DeepEqual(expectedData, actualData) {
+ t.Errorf("Unexpected test data, expected: %q, actual: %q", expectedData, actualData)
+ }
+}
diff --git a/sysprop/sysprop_test.go b/sysprop/sysprop_test.go
index 850338675..711129c84 100644
--- a/sysprop/sysprop_test.go
+++ b/sysprop/sysprop_test.go
@@ -67,6 +67,8 @@ func testContext(config android.Config) *android.TestContext {
ctx.BottomUp("sysprop_deps", syspropDepsMutator).Parallel()
})
+ android.RegisterPrebuiltMutators(ctx)
+
cc.RegisterRequiredBuildComponentsForTest(ctx)
ctx.PreDepsMutators(func(ctx android.RegisterMutatorsContext) {
ctx.BottomUp("sysprop_java", java.SyspropMutator).Parallel()
diff --git a/third_party/zip/android.go b/third_party/zip/android.go
index 8d387ccb1..f8e45c56d 100644
--- a/third_party/zip/android.go
+++ b/third_party/zip/android.go
@@ -43,6 +43,15 @@ func (w *Writer) CopyFrom(orig *File, newName string) error {
offset: uint64(w.cw.count),
}
w.dir = append(w.dir, h)
+ if !fh.isZip64() {
+ // Some writers will generate 64 bit sizes and set 32 bit fields to
+ // uint32max even if the actual size fits in 32 bit. So we should
+ // make sure CompressedSize contains the correct value in such
+ // cases. With out the two lines below we would be writing invalid(-1)
+ // sizes in such case.
+ fh.CompressedSize = uint32(fh.CompressedSize64)
+ fh.UncompressedSize = uint32(fh.UncompressedSize64)
+ }
if err := writeHeader(w.cw, fh); err != nil {
return err
diff --git a/third_party/zip/zip_test.go b/third_party/zip/zip_test.go
index 73736606e..559c91402 100644
--- a/third_party/zip/zip_test.go
+++ b/third_party/zip/zip_test.go
@@ -219,7 +219,7 @@ func TestRLEBuffer(t *testing.T) {
}
}
-// fakeHash32 is a dummy Hash32 that always returns 0.
+// fakeHash32 is a fake Hash32 that always returns 0.
type fakeHash32 struct {
hash.Hash32
}
diff --git a/tradefed/autogen.go b/tradefed/autogen.go
index 1cb874d7f..798fc40fc 100644
--- a/tradefed/autogen.go
+++ b/tradefed/autogen.go
@@ -239,6 +239,21 @@ func AutoGenRustTestConfig(ctx android.ModuleContext, testConfigProp *string,
return path
}
+func AutoGenRobolectricTestConfig(ctx android.ModuleContext, testConfigProp *string, testConfigTemplateProp *string,
+ testSuites []string, autoGenConfig *bool) android.Path {
+ path, autogenPath := testConfigPath(ctx, testConfigProp, testSuites, autoGenConfig, testConfigTemplateProp)
+ if autogenPath != nil {
+ templatePath := getTestConfigTemplate(ctx, testConfigTemplateProp)
+ if templatePath.Valid() {
+ autogenTemplate(ctx, autogenPath, templatePath.String(), nil)
+ } else {
+ autogenTemplate(ctx, autogenPath, "${RobolectricTestConfigTemplate}", nil)
+ }
+ return autogenPath
+ }
+ return path
+}
+
var autogenInstrumentationTest = pctx.StaticRule("autogenInstrumentationTest", blueprint.RuleParams{
Command: "${AutoGenTestConfigScript} $out $in ${EmptyTestConfig} $template ${extraConfigs}",
CommandDeps: []string{
diff --git a/tradefed/config.go b/tradefed/config.go
index 34195c364..f7e834988 100644
--- a/tradefed/config.go
+++ b/tradefed/config.go
@@ -33,6 +33,7 @@ func init() {
pctx.SourcePathVariable("PythonBinaryHostTestConfigTemplate", "build/make/core/python_binary_host_test_config_template.xml")
pctx.SourcePathVariable("RustDeviceTestConfigTemplate", "build/make/core/rust_device_test_config_template.xml")
pctx.SourcePathVariable("RustHostTestConfigTemplate", "build/make/core/rust_host_test_config_template.xml")
+ pctx.SourcePathVariable("RobolectricTestConfigTemplate", "build/make/core/robolectric_test_config_template.xml")
pctx.SourcePathVariable("ShellTestConfigTemplate", "build/make/core/shell_test_config_template.xml")
pctx.SourcePathVariable("EmptyTestConfig", "build/make/core/empty_test_config.xml")
diff --git a/ui/build/config.go b/ui/build/config.go
index ba477e61a..e9a8fc910 100644
--- a/ui/build/config.go
+++ b/ui/build/config.go
@@ -15,6 +15,7 @@
package build
import (
+ "fmt"
"os"
"path/filepath"
"runtime"
@@ -23,6 +24,9 @@ import (
"time"
"android/soong/shared"
+ "github.com/golang/protobuf/proto"
+
+ smpb "android/soong/ui/metrics/metrics_proto"
)
type Config struct{ *configImpl }
@@ -53,8 +57,6 @@ type configImpl struct {
// Autodetected
totalRAM uint64
- pdkBuild bool
-
brokenDupRules bool
brokenUsesNetwork bool
brokenNinjaEnvVars []string
@@ -96,7 +98,7 @@ func NewConfig(ctx Context, args ...string) Config {
environ: OsEnvironment(),
}
- // Sane default matching ninja
+ // Default matching ninja
ret.parallel = runtime.NumCPU() + 2
ret.keepGoing = 1
@@ -260,12 +262,14 @@ func NewConfig(ctx Context, args ...string) Config {
ret.environ.Set("BUILD_DATETIME_FILE", buildDateTimeFile)
if ret.UseRBE() {
- for k, v := range getRBEVars(ctx, tmpDir) {
+ for k, v := range getRBEVars(ctx, Config{ret}) {
ret.environ.Set(k, v)
}
}
- return Config{ret}
+ c := Config{ret}
+ storeConfigMetrics(ctx, c)
+ return c
}
// NewBuildActionConfig returns a build configuration based on the build action. The arguments are
@@ -274,6 +278,20 @@ func NewBuildActionConfig(action BuildAction, dir string, ctx Context, args ...s
return NewConfig(ctx, getConfigArgs(action, dir, ctx, args)...)
}
+// storeConfigMetrics selects a set of configuration information and store in
+// the metrics system for further analysis.
+func storeConfigMetrics(ctx Context, config Config) {
+ if ctx.Metrics == nil {
+ return
+ }
+
+ b := &smpb.BuildConfig{
+ UseGoma: proto.Bool(config.UseGoma()),
+ UseRbe: proto.Bool(config.UseRBE()),
+ }
+ ctx.Metrics.BuildConfig(b)
+}
+
// getConfigArgs processes the command arguments based on the build action and creates a set of new
// arguments to be accepted by Config.
func getConfigArgs(action BuildAction, dir string, ctx Context, args []string) []string {
@@ -808,13 +826,73 @@ func (c *configImpl) StartRBE() bool {
return true
}
-func (c *configImpl) RBEStatsOutputDir() string {
+func (c *configImpl) logDir() string {
+ if c.Dist() {
+ return filepath.Join(c.DistDir(), "logs")
+ }
+ return c.OutDir()
+}
+
+func (c *configImpl) rbeStatsOutputDir() string {
for _, f := range []string{"RBE_output_dir", "FLAG_output_dir"} {
if v, ok := c.environ.Get(f); ok {
return v
}
}
- return ""
+ return c.logDir()
+}
+
+func (c *configImpl) rbeLogPath() string {
+ for _, f := range []string{"RBE_log_path", "FLAG_log_path"} {
+ if v, ok := c.environ.Get(f); ok {
+ return v
+ }
+ }
+ return fmt.Sprintf("text://%v/reproxy_log.txt", c.logDir())
+}
+
+func (c *configImpl) rbeExecRoot() string {
+ for _, f := range []string{"RBE_exec_root", "FLAG_exec_root"} {
+ if v, ok := c.environ.Get(f); ok {
+ return v
+ }
+ }
+ wd, err := os.Getwd()
+ if err != nil {
+ return ""
+ }
+ return wd
+}
+
+func (c *configImpl) rbeDir() string {
+ if v, ok := c.environ.Get("RBE_DIR"); ok {
+ return v
+ }
+ return "prebuilts/remoteexecution-client/live/"
+}
+
+func (c *configImpl) rbeReproxy() string {
+ for _, f := range []string{"RBE_re_proxy", "FLAG_re_proxy"} {
+ if v, ok := c.environ.Get(f); ok {
+ return v
+ }
+ }
+ return filepath.Join(c.rbeDir(), "reproxy")
+}
+
+func (c *configImpl) rbeAuth() (string, string) {
+ credFlags := []string{"use_application_default_credentials", "use_gce_credentials", "credential_file"}
+ for _, cf := range credFlags {
+ for _, f := range []string{"RBE_" + cf, "FLAG_" + cf} {
+ if v, ok := c.environ.Get(f); ok {
+ v = strings.TrimSpace(v)
+ if v != "" && v != "false" && v != "0" {
+ return "RBE_" + cf, v
+ }
+ }
+ }
+ }
+ return "RBE_use_application_default_credentials", "true"
}
func (c *configImpl) UseRemoteBuild() bool {
@@ -968,14 +1046,6 @@ func (c *configImpl) TargetDeviceDir() string {
return c.targetDeviceDir
}
-func (c *configImpl) SetPdkBuild(pdk bool) {
- c.pdkBuild = pdk
-}
-
-func (c *configImpl) IsPdkBuild() bool {
- return c.pdkBuild
-}
-
func (c *configImpl) BuildDateTime() string {
return c.buildDateTime
}
diff --git a/ui/build/dumpvars.go b/ui/build/dumpvars.go
index e22985675..999af0796 100644
--- a/ui/build/dumpvars.go
+++ b/ui/build/dumpvars.go
@@ -161,8 +161,6 @@ var BannerVars = []string{
"BUILD_ID",
"OUT_DIR",
"AUX_OS_VARIANT_LIST",
- "TARGET_BUILD_PDK",
- "PDK_FUSION_PLATFORM_ZIP",
"PRODUCT_SOONG_NAMESPACES",
}
@@ -281,7 +279,6 @@ func runMakeProductConfig(ctx Context, config Config) {
config.SetTargetDevice(make_vars["TARGET_DEVICE"])
config.SetTargetDeviceDir(make_vars["TARGET_DEVICE_DIR"])
- config.SetPdkBuild(make_vars["TARGET_BUILD_PDK"] == "true")
config.SetBuildBrokenDupRules(make_vars["BUILD_BROKEN_DUP_RULES"] == "true")
config.SetBuildBrokenUsesNetwork(make_vars["BUILD_BROKEN_USES_NETWORK"] == "true")
config.SetBuildBrokenNinjaUsesEnvVars(strings.Fields(make_vars["BUILD_BROKEN_NINJA_USES_ENV_VARS"]))
diff --git a/ui/build/kati.go b/ui/build/kati.go
index 1cd5fea32..f6d3a5741 100644
--- a/ui/build/kati.go
+++ b/ui/build/kati.go
@@ -134,14 +134,10 @@ func runKatiBuild(ctx Context, config Config) {
args := []string{
"--writable", config.OutDir() + "/",
+ "--werror_implicit_rules",
"-f", "build/make/core/main.mk",
}
- // PDK builds still uses a few implicit rules
- if !config.IsPdkBuild() {
- args = append(args, "--werror_implicit_rules")
- }
-
if !config.BuildBrokenDupRules() {
args = append(args, "--werror_overriding_commands")
}
diff --git a/ui/build/paths/config.go b/ui/build/paths/config.go
index 571740133..81c500d2b 100644
--- a/ui/build/paths/config.go
+++ b/ui/build/paths/config.go
@@ -88,7 +88,6 @@ var Configuration = map[string]PathConfig{
"javap": Allowed,
"lsof": Allowed,
"openssl": Allowed,
- "patch": Allowed,
"pstree": Allowed,
"rsync": Allowed,
"sh": Allowed,
diff --git a/ui/build/rbe.go b/ui/build/rbe.go
index fd3b7abb5..67bcebb75 100644
--- a/ui/build/rbe.go
+++ b/ui/build/rbe.go
@@ -37,10 +37,8 @@ const (
func rbeCommand(ctx Context, config Config, rbeCmd string) string {
var cmdPath string
- if rbeDir, ok := config.Environment().Get("RBE_DIR"); ok {
+ if rbeDir := config.rbeDir(); rbeDir != "" {
cmdPath = filepath.Join(rbeDir, rbeCmd)
- } else if home, ok := config.Environment().Get("HOME"); ok {
- cmdPath = filepath.Join(home, "rbe", rbeCmd)
} else {
ctx.Fatalf("rbe command path not found")
}
@@ -52,9 +50,21 @@ func rbeCommand(ctx Context, config Config, rbeCmd string) string {
return cmdPath
}
-func getRBEVars(ctx Context, tmpDir string) map[string]string {
+func getRBEVars(ctx Context, config Config) map[string]string {
rand.Seed(time.Now().UnixNano())
- return map[string]string{"RBE_server_address": fmt.Sprintf("unix://%v/reproxy_%v.sock", tmpDir, rand.Intn(1000))}
+ vars := map[string]string{
+ "RBE_log_path": config.rbeLogPath(),
+ "RBE_log_dir": config.logDir(),
+ "RBE_re_proxy": config.rbeReproxy(),
+ "RBE_exec_root": config.rbeExecRoot(),
+ "RBE_output_dir": config.rbeStatsOutputDir(),
+ }
+ if config.StartRBE() {
+ vars["RBE_server_address"] = fmt.Sprintf("unix://%v/reproxy_%v.sock", absPath(ctx, config.TempDir()), rand.Intn(1000))
+ }
+ k, v := config.rbeAuth()
+ vars[k] = v
+ return vars
}
func startRBE(ctx Context, config Config) {
@@ -102,7 +112,7 @@ func DumpRBEMetrics(ctx Context, config Config, filename string) {
return
}
- outputDir := config.RBEStatsOutputDir()
+ outputDir := config.rbeStatsOutputDir()
if outputDir == "" {
ctx.Fatal("RBE output dir variable not defined. Aborting metrics dumping.")
}
@@ -111,7 +121,20 @@ func DumpRBEMetrics(ctx Context, config Config, filename string) {
// Stop the proxy first in order to generate the RBE metrics protobuf file.
stopRBE(ctx, config)
+ if metricsFile == filename {
+ return
+ }
if _, err := copyFile(metricsFile, filename); err != nil {
ctx.Fatalf("failed to copy %q to %q: %v\n", metricsFile, filename, err)
}
}
+
+// PrintGomaDeprecation prints a PSA on the deprecation of Goma if it is set for the build.
+func PrintGomaDeprecation(ctx Context, config Config) {
+ if config.UseGoma() {
+ fmt.Fprintln(ctx.Writer, "")
+ fmt.Fprintln(ctx.Writer, "Goma for Android is being deprecated and replaced with RBE.")
+ fmt.Fprintln(ctx.Writer, "See go/goma_android_deprecation for more details.")
+ fmt.Fprintln(ctx.Writer, "")
+ }
+}
diff --git a/ui/build/rbe_test.go b/ui/build/rbe_test.go
index 2c4995b1d..8ff96bcbb 100644
--- a/ui/build/rbe_test.go
+++ b/ui/build/rbe_test.go
@@ -83,24 +83,13 @@ func TestDumpRBEMetrics(t *testing.T) {
func TestDumpRBEMetricsErrors(t *testing.T) {
ctx := testContext()
tests := []struct {
- description string
- rbeOutputDirDefined bool
- bootstrapProgram string
- expectedErr string
+ description string
+ bootstrapProgram string
+ expectedErr string
}{{
- description: "output_dir not defined",
- bootstrapProgram: rbeBootstrapProgram,
- expectedErr: "RBE output dir variable not defined",
- }, {
- description: "stopRBE failed",
- rbeOutputDirDefined: true,
- bootstrapProgram: "#!/bin/bash\nexit 1",
- expectedErr: "shutdown failed",
- }, {
- description: "failed to copy metrics file",
- rbeOutputDirDefined: true,
- bootstrapProgram: "#!/bin/bash",
- expectedErr: "failed to copy",
+ description: "stopRBE failed",
+ bootstrapProgram: "#!/bin/bash\nexit 1\n",
+ expectedErr: "shutdown failed",
}}
for _, tt := range tests {
@@ -124,10 +113,6 @@ func TestDumpRBEMetricsErrors(t *testing.T) {
env.Set("OUT_DIR", tmpDir)
env.Set("RBE_DIR", tmpDir)
- if tt.rbeOutputDirDefined {
- env.Set("RBE_output_dir", t.TempDir())
- }
-
config := Config{&configImpl{
environ: env,
}}
@@ -139,4 +124,4 @@ func TestDumpRBEMetricsErrors(t *testing.T) {
}
}
-var rbeBootstrapProgram = fmt.Sprintf("#!/bin/bash\necho 1 > $RBE_output_dir/%s", rbeMetricsPBFilename)
+var rbeBootstrapProgram = fmt.Sprintf("#!/bin/bash\necho 1 > $RBE_output_dir/%s\n", rbeMetricsPBFilename)
diff --git a/ui/build/upload.go b/ui/build/upload.go
index 1cc2e940c..a9346e0c5 100644
--- a/ui/build/upload.go
+++ b/ui/build/upload.go
@@ -44,7 +44,7 @@ var (
// environment variable. The metrics files are copied to a temporary directory
// and the uploader is then executed in the background to allow the user to continue
// working.
-func UploadMetrics(ctx Context, config Config, forceDumbOutput bool, buildStarted time.Time, files ...string) {
+func UploadMetrics(ctx Context, config Config, simpleOutput bool, buildStarted time.Time, files ...string) {
ctx.BeginTrace(metrics.RunSetupTool, "upload_metrics")
defer ctx.EndTrace()
@@ -105,7 +105,7 @@ func UploadMetrics(ctx Context, config Config, forceDumbOutput bool, buildStarte
// Start the uploader in the background as it takes several milliseconds to start the uploader
// and prepare the metrics for upload. This affects small commands like "lunch".
cmd := Command(ctx, config, "upload metrics", uploader, "--upload-metrics", pbFile)
- if forceDumbOutput {
+ if simpleOutput {
cmd.RunOrFatal()
} else {
cmd.RunAndStreamOrFatal()
diff --git a/ui/metrics/metrics.go b/ui/metrics/metrics.go
index 2b5c4c3f6..f5552a3af 100644
--- a/ui/metrics/metrics.go
+++ b/ui/metrics/metrics.go
@@ -17,6 +17,7 @@ package metrics
import (
"io/ioutil"
"os"
+ "runtime"
"time"
"github.com/golang/protobuf/proto"
@@ -65,6 +66,10 @@ func (m *Metrics) SetTimeMetrics(perf soong_metrics_proto.PerfInfo) {
}
}
+func (m *Metrics) BuildConfig(b *soong_metrics_proto.BuildConfig) {
+ m.metrics.BuildConfig = b
+}
+
func (m *Metrics) SetMetadataMetrics(metadata map[string]string) {
for k, v := range metadata {
switch k {
@@ -98,8 +103,6 @@ func (m *Metrics) SetMetadataMetrics(metadata map[string]string) {
m.metrics.HostArch = m.getArch(v)
case "HOST_2ND_ARCH":
m.metrics.Host_2NdArch = m.getArch(v)
- case "HOST_OS":
- m.metrics.HostOs = proto.String(v)
case "HOST_OS_EXTRA":
m.metrics.HostOsExtra = proto.String(v)
case "HOST_CROSS_OS":
@@ -137,6 +140,7 @@ func (m *Metrics) SetBuildDateTime(buildTimestamp time.Time) {
// exports the output to the file at outputPath
func (m *Metrics) Dump(outputPath string) (err error) {
+ m.metrics.HostOs = proto.String(runtime.GOOS)
return writeMessageToFile(&m.metrics, outputPath)
}
diff --git a/ui/metrics/metrics_proto/metrics.pb.go b/ui/metrics/metrics_proto/metrics.pb.go
index a39d1a83a..d7c53ec2b 100644
--- a/ui/metrics/metrics_proto/metrics.pb.go
+++ b/ui/metrics/metrics_proto/metrics.pb.go
@@ -152,7 +152,7 @@ func (x *ModuleTypeInfo_BuildSystem) UnmarshalJSON(data []byte) error {
}
func (ModuleTypeInfo_BuildSystem) EnumDescriptor() ([]byte, []int) {
- return fileDescriptor_6039342a2ba47b72, []int{2, 0}
+ return fileDescriptor_6039342a2ba47b72, []int{3, 0}
}
type MetricsBase struct {
@@ -199,6 +199,7 @@ type MetricsBase struct {
// The metrics for the whole build
Total *PerfInfo `protobuf:"bytes,21,opt,name=total" json:"total,omitempty"`
SoongBuildMetrics *SoongBuildMetrics `protobuf:"bytes,22,opt,name=soong_build_metrics,json=soongBuildMetrics" json:"soong_build_metrics,omitempty"`
+ BuildConfig *BuildConfig `protobuf:"bytes,23,opt,name=build_config,json=buildConfig" json:"build_config,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
@@ -388,6 +389,60 @@ func (m *MetricsBase) GetSoongBuildMetrics() *SoongBuildMetrics {
return nil
}
+func (m *MetricsBase) GetBuildConfig() *BuildConfig {
+ if m != nil {
+ return m.BuildConfig
+ }
+ return nil
+}
+
+type BuildConfig struct {
+ UseGoma *bool `protobuf:"varint,1,opt,name=use_goma,json=useGoma" json:"use_goma,omitempty"`
+ UseRbe *bool `protobuf:"varint,2,opt,name=use_rbe,json=useRbe" json:"use_rbe,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
+}
+
+func (m *BuildConfig) Reset() { *m = BuildConfig{} }
+func (m *BuildConfig) String() string { return proto.CompactTextString(m) }
+func (*BuildConfig) ProtoMessage() {}
+func (*BuildConfig) Descriptor() ([]byte, []int) {
+ return fileDescriptor_6039342a2ba47b72, []int{1}
+}
+
+func (m *BuildConfig) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_BuildConfig.Unmarshal(m, b)
+}
+func (m *BuildConfig) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_BuildConfig.Marshal(b, m, deterministic)
+}
+func (m *BuildConfig) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_BuildConfig.Merge(m, src)
+}
+func (m *BuildConfig) XXX_Size() int {
+ return xxx_messageInfo_BuildConfig.Size(m)
+}
+func (m *BuildConfig) XXX_DiscardUnknown() {
+ xxx_messageInfo_BuildConfig.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_BuildConfig proto.InternalMessageInfo
+
+func (m *BuildConfig) GetUseGoma() bool {
+ if m != nil && m.UseGoma != nil {
+ return *m.UseGoma
+ }
+ return false
+}
+
+func (m *BuildConfig) GetUseRbe() bool {
+ if m != nil && m.UseRbe != nil {
+ return *m.UseRbe
+ }
+ return false
+}
+
type PerfInfo struct {
// The description for the phase/action/part while the tool running.
Desc *string `protobuf:"bytes,1,opt,name=desc" json:"desc,omitempty"`
@@ -410,7 +465,7 @@ func (m *PerfInfo) Reset() { *m = PerfInfo{} }
func (m *PerfInfo) String() string { return proto.CompactTextString(m) }
func (*PerfInfo) ProtoMessage() {}
func (*PerfInfo) Descriptor() ([]byte, []int) {
- return fileDescriptor_6039342a2ba47b72, []int{1}
+ return fileDescriptor_6039342a2ba47b72, []int{2}
}
func (m *PerfInfo) XXX_Unmarshal(b []byte) error {
@@ -482,7 +537,7 @@ func (m *ModuleTypeInfo) Reset() { *m = ModuleTypeInfo{} }
func (m *ModuleTypeInfo) String() string { return proto.CompactTextString(m) }
func (*ModuleTypeInfo) ProtoMessage() {}
func (*ModuleTypeInfo) Descriptor() ([]byte, []int) {
- return fileDescriptor_6039342a2ba47b72, []int{2}
+ return fileDescriptor_6039342a2ba47b72, []int{3}
}
func (m *ModuleTypeInfo) XXX_Unmarshal(b []byte) error {
@@ -540,7 +595,7 @@ func (m *CriticalUserJourneyMetrics) Reset() { *m = CriticalUserJourneyM
func (m *CriticalUserJourneyMetrics) String() string { return proto.CompactTextString(m) }
func (*CriticalUserJourneyMetrics) ProtoMessage() {}
func (*CriticalUserJourneyMetrics) Descriptor() ([]byte, []int) {
- return fileDescriptor_6039342a2ba47b72, []int{3}
+ return fileDescriptor_6039342a2ba47b72, []int{4}
}
func (m *CriticalUserJourneyMetrics) XXX_Unmarshal(b []byte) error {
@@ -587,7 +642,7 @@ func (m *CriticalUserJourneysMetrics) Reset() { *m = CriticalUserJourney
func (m *CriticalUserJourneysMetrics) String() string { return proto.CompactTextString(m) }
func (*CriticalUserJourneysMetrics) ProtoMessage() {}
func (*CriticalUserJourneysMetrics) Descriptor() ([]byte, []int) {
- return fileDescriptor_6039342a2ba47b72, []int{4}
+ return fileDescriptor_6039342a2ba47b72, []int{5}
}
func (m *CriticalUserJourneysMetrics) XXX_Unmarshal(b []byte) error {
@@ -635,7 +690,7 @@ func (m *SoongBuildMetrics) Reset() { *m = SoongBuildMetrics{} }
func (m *SoongBuildMetrics) String() string { return proto.CompactTextString(m) }
func (*SoongBuildMetrics) ProtoMessage() {}
func (*SoongBuildMetrics) Descriptor() ([]byte, []int) {
- return fileDescriptor_6039342a2ba47b72, []int{5}
+ return fileDescriptor_6039342a2ba47b72, []int{6}
}
func (m *SoongBuildMetrics) XXX_Unmarshal(b []byte) error {
@@ -696,6 +751,7 @@ func init() {
proto.RegisterEnum("soong_build_metrics.MetricsBase_Arch", MetricsBase_Arch_name, MetricsBase_Arch_value)
proto.RegisterEnum("soong_build_metrics.ModuleTypeInfo_BuildSystem", ModuleTypeInfo_BuildSystem_name, ModuleTypeInfo_BuildSystem_value)
proto.RegisterType((*MetricsBase)(nil), "soong_build_metrics.MetricsBase")
+ proto.RegisterType((*BuildConfig)(nil), "soong_build_metrics.BuildConfig")
proto.RegisterType((*PerfInfo)(nil), "soong_build_metrics.PerfInfo")
proto.RegisterType((*ModuleTypeInfo)(nil), "soong_build_metrics.ModuleTypeInfo")
proto.RegisterType((*CriticalUserJourneyMetrics)(nil), "soong_build_metrics.CriticalUserJourneyMetrics")
@@ -703,69 +759,74 @@ func init() {
proto.RegisterType((*SoongBuildMetrics)(nil), "soong_build_metrics.SoongBuildMetrics")
}
-func init() { proto.RegisterFile("metrics.proto", fileDescriptor_6039342a2ba47b72) }
+func init() {
+ proto.RegisterFile("metrics.proto", fileDescriptor_6039342a2ba47b72)
+}
var fileDescriptor_6039342a2ba47b72 = []byte{
- // 962 bytes of a gzipped FileDescriptorProto
- 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x56, 0xef, 0x4e, 0xdc, 0x46,
- 0x10, 0x8f, 0xe1, 0xe0, 0xce, 0x63, 0xee, 0x30, 0x0b, 0x69, 0x9c, 0x44, 0xa8, 0x27, 0xab, 0x89,
- 0x50, 0xd5, 0x90, 0x88, 0x46, 0x28, 0x42, 0x51, 0x25, 0x38, 0x50, 0x9a, 0x22, 0xb8, 0xc8, 0xfc,
- 0x69, 0xd4, 0x7e, 0x58, 0x2d, 0xf6, 0x12, 0x9c, 0xda, 0x5e, 0x6b, 0x77, 0x1d, 0x41, 0xde, 0xa1,
- 0x0f, 0xd4, 0xcf, 0x7d, 0x96, 0xbe, 0x47, 0xb5, 0xb3, 0xf6, 0x61, 0xda, 0x8b, 0x40, 0xf9, 0x66,
- 0xcf, 0xef, 0xcf, 0xce, 0xac, 0x67, 0xe6, 0x0e, 0xfa, 0x39, 0xd7, 0x32, 0x8d, 0xd5, 0x7a, 0x29,
- 0x85, 0x16, 0x64, 0x59, 0x09, 0x51, 0x7c, 0xa0, 0x67, 0x55, 0x9a, 0x25, 0xb4, 0x86, 0xc2, 0xbf,
- 0x00, 0xbc, 0x03, 0xfb, 0xbc, 0xc3, 0x14, 0x27, 0x2f, 0x60, 0xc5, 0x12, 0x12, 0xa6, 0x39, 0xd5,
- 0x69, 0xce, 0x95, 0x66, 0x79, 0x19, 0x38, 0x43, 0x67, 0x6d, 0x36, 0x22, 0x88, 0xed, 0x32, 0xcd,
- 0x8f, 0x1b, 0x84, 0x3c, 0x84, 0x9e, 0x55, 0xa4, 0x49, 0x30, 0x33, 0x74, 0xd6, 0xdc, 0xa8, 0x8b,
- 0xef, 0x6f, 0x13, 0xb2, 0x05, 0x0f, 0xcb, 0x8c, 0xe9, 0x73, 0x21, 0x73, 0xfa, 0x89, 0x4b, 0x95,
- 0x8a, 0x82, 0xc6, 0x22, 0xe1, 0x05, 0xcb, 0x79, 0x30, 0x8b, 0xdc, 0x07, 0x0d, 0xe1, 0xd4, 0xe2,
- 0xa3, 0x1a, 0x26, 0x4f, 0x60, 0xa0, 0x99, 0xfc, 0xc0, 0x35, 0x2d, 0xa5, 0x48, 0xaa, 0x58, 0x07,
- 0x1d, 0x14, 0xf4, 0x6d, 0xf4, 0x9d, 0x0d, 0x92, 0x04, 0x56, 0x6a, 0x9a, 0x4d, 0xe2, 0x13, 0x93,
- 0x29, 0x2b, 0x74, 0x30, 0x37, 0x74, 0xd6, 0x06, 0x1b, 0xcf, 0xd6, 0xa7, 0xd4, 0xbc, 0xde, 0xaa,
- 0x77, 0x7d, 0xc7, 0x20, 0xa7, 0x56, 0xb4, 0x35, 0xbb, 0x77, 0xf8, 0x26, 0x22, 0xd6, 0xaf, 0x0d,
- 0x90, 0x31, 0x78, 0xf5, 0x29, 0x4c, 0xc6, 0x17, 0xc1, 0x3c, 0x9a, 0x3f, 0xb9, 0xd5, 0x7c, 0x5b,
- 0xc6, 0x17, 0x5b, 0xdd, 0x93, 0xc3, 0xfd, 0xc3, 0xf1, 0xaf, 0x87, 0x11, 0x58, 0x0b, 0x13, 0x24,
- 0xeb, 0xb0, 0xdc, 0x32, 0x9c, 0x64, 0xdd, 0xc5, 0x12, 0x97, 0xae, 0x89, 0x4d, 0x02, 0x3f, 0x40,
- 0x9d, 0x16, 0x8d, 0xcb, 0x6a, 0x42, 0xef, 0x21, 0xdd, 0xb7, 0xc8, 0xa8, 0xac, 0x1a, 0xf6, 0x3e,
- 0xb8, 0x17, 0x42, 0xd5, 0xc9, 0xba, 0x5f, 0x95, 0x6c, 0xcf, 0x18, 0x60, 0xaa, 0x11, 0xf4, 0xd1,
- 0x6c, 0xa3, 0x48, 0xac, 0x21, 0x7c, 0x95, 0xa1, 0x67, 0x4c, 0x36, 0x8a, 0x04, 0x3d, 0x1f, 0x40,
- 0x17, 0x3d, 0x85, 0x0a, 0x3c, 0xac, 0x61, 0xde, 0xbc, 0x8e, 0x15, 0x09, 0xeb, 0xc3, 0x84, 0xa2,
- 0xfc, 0x52, 0x4b, 0x16, 0x2c, 0x20, 0xec, 0x59, 0x78, 0xcf, 0x84, 0x26, 0x9c, 0x58, 0x0a, 0xa5,
- 0x8c, 0x45, 0xff, 0x9a, 0x33, 0x32, 0xb1, 0xb1, 0x22, 0x4f, 0x61, 0xb1, 0xc5, 0xc1, 0xb4, 0x07,
- 0xb6, 0x7d, 0x26, 0x2c, 0x4c, 0xe4, 0x19, 0x2c, 0xb7, 0x78, 0x93, 0x12, 0x17, 0xed, 0xc5, 0x4e,
- 0xb8, 0xad, 0xbc, 0x45, 0xa5, 0x69, 0x92, 0xca, 0xc0, 0xb7, 0x79, 0x8b, 0x4a, 0xef, 0xa6, 0x92,
- 0xfc, 0x04, 0x9e, 0xe2, 0xba, 0x2a, 0xa9, 0x16, 0x22, 0x53, 0xc1, 0xd2, 0x70, 0x76, 0xcd, 0xdb,
- 0x58, 0x9d, 0x7a, 0x45, 0xef, 0xb8, 0x3c, 0x7f, 0x5b, 0x9c, 0x8b, 0x08, 0x50, 0x71, 0x6c, 0x04,
- 0x64, 0x0b, 0xdc, 0x3f, 0x98, 0x4e, 0xa9, 0xac, 0x0a, 0x15, 0x90, 0xbb, 0xa8, 0x7b, 0x86, 0x1f,
- 0x55, 0x85, 0x22, 0xaf, 0x01, 0x2c, 0x13, 0xc5, 0xcb, 0x77, 0x11, 0xbb, 0x88, 0x36, 0xea, 0x22,
- 0x2d, 0x3e, 0x32, 0xab, 0x5e, 0xb9, 0x93, 0x1a, 0x05, 0xa8, 0xfe, 0x11, 0xe6, 0xb4, 0xd0, 0x2c,
- 0x0b, 0xee, 0x0f, 0x9d, 0xdb, 0x85, 0x96, 0x4b, 0x4e, 0x61, 0xda, 0x2a, 0x0a, 0xbe, 0x41, 0x8b,
- 0xa7, 0x53, 0x2d, 0x8e, 0x4c, 0x0c, 0x47, 0xb2, 0xee, 0xb0, 0x68, 0x49, 0xfd, 0x37, 0x14, 0xbe,
- 0x80, 0x85, 0x1b, 0x53, 0xdb, 0x83, 0xce, 0xc9, 0xd1, 0x5e, 0xe4, 0xdf, 0x23, 0x7d, 0x70, 0xcd,
- 0xd3, 0xee, 0xde, 0xce, 0xc9, 0x1b, 0xdf, 0x21, 0x5d, 0x30, 0x93, 0xee, 0xcf, 0x84, 0xaf, 0xa1,
- 0x83, 0xdf, 0xd5, 0x83, 0xa6, 0x4f, 0xfd, 0x7b, 0x06, 0xdd, 0x8e, 0x0e, 0x7c, 0x87, 0xb8, 0x30,
- 0xb7, 0x1d, 0x1d, 0x6c, 0xbe, 0xf4, 0x67, 0x4c, 0xec, 0xfd, 0xab, 0x4d, 0x7f, 0x96, 0x00, 0xcc,
- 0xbf, 0x7f, 0xb5, 0x49, 0x37, 0x5f, 0xfa, 0x9d, 0xf0, 0x4f, 0x07, 0x7a, 0x4d, 0x6d, 0x84, 0x40,
- 0x27, 0xe1, 0x2a, 0xc6, 0x45, 0xe9, 0x46, 0xf8, 0x6c, 0x62, 0xb8, 0xea, 0xec, 0x5a, 0xc4, 0x67,
- 0xb2, 0x0a, 0xa0, 0x34, 0x93, 0x1a, 0x77, 0x2b, 0x2e, 0xc1, 0x4e, 0xe4, 0x62, 0xc4, 0xac, 0x54,
- 0xf2, 0x18, 0x5c, 0xc9, 0x59, 0x66, 0xd1, 0x0e, 0xa2, 0x3d, 0x13, 0x40, 0x70, 0x15, 0x20, 0xe7,
- 0xb9, 0x90, 0x57, 0xb4, 0x52, 0x1c, 0x57, 0x5c, 0x27, 0x72, 0x6d, 0xe4, 0x44, 0xf1, 0xf0, 0x1f,
- 0x07, 0x06, 0x07, 0x22, 0xa9, 0x32, 0x7e, 0x7c, 0x55, 0x72, 0xcc, 0xea, 0x77, 0x58, 0xb0, 0x17,
- 0xa9, 0xae, 0x94, 0xe6, 0x39, 0x66, 0x37, 0xd8, 0x78, 0x3e, 0x7d, 0x76, 0x6f, 0x48, 0xed, 0x66,
- 0x3c, 0x42, 0x59, 0x6b, 0x8a, 0xcf, 0xae, 0xa3, 0xe4, 0x5b, 0xf0, 0x72, 0xd4, 0x50, 0x7d, 0x55,
- 0x36, 0x55, 0x42, 0x3e, 0xb1, 0x21, 0xdf, 0xc1, 0xa0, 0xa8, 0x72, 0x2a, 0xce, 0xa9, 0x0d, 0x2a,
- 0xac, 0xb7, 0x1f, 0x2d, 0x14, 0x55, 0x3e, 0x3e, 0xb7, 0xe7, 0xa9, 0xf0, 0x39, 0x78, 0xad, 0xb3,
- 0x6e, 0x7e, 0x0b, 0x17, 0xe6, 0x8e, 0xc6, 0xe3, 0x43, 0xf3, 0xd1, 0x7a, 0xd0, 0x39, 0xd8, 0xde,
- 0xdf, 0xf3, 0x67, 0xc2, 0x0c, 0x1e, 0x8d, 0x64, 0xaa, 0xd3, 0x98, 0x65, 0x27, 0x8a, 0xcb, 0x5f,
- 0x44, 0x25, 0x0b, 0x7e, 0x55, 0x77, 0xc1, 0xe4, 0xd2, 0x9d, 0xd6, 0xa5, 0x6f, 0x41, 0xb7, 0xe9,
- 0xb2, 0x19, 0xec, 0xb2, 0xe1, 0x6d, 0xdb, 0x2b, 0x6a, 0x04, 0xe1, 0x19, 0x3c, 0x9e, 0x72, 0x9a,
- 0x6a, 0x8e, 0x1b, 0x41, 0x27, 0xae, 0x3e, 0xaa, 0xc0, 0xc1, 0xc9, 0x99, 0x7e, 0xb3, 0x5f, 0xce,
- 0x36, 0x42, 0x71, 0xf8, 0xb7, 0x03, 0x4b, 0xff, 0x6b, 0x71, 0x12, 0x40, 0xb7, 0xb9, 0x37, 0x07,
- 0xef, 0xad, 0x79, 0x25, 0x8f, 0xa0, 0x57, 0xff, 0x06, 0xd8, 0x82, 0xfa, 0xd1, 0xe4, 0x9d, 0x7c,
- 0x0f, 0x4b, 0x38, 0x66, 0x94, 0x65, 0x99, 0x88, 0x69, 0x2c, 0xaa, 0x42, 0xd7, 0x7d, 0xb6, 0x88,
- 0xc0, 0xb6, 0x89, 0x8f, 0x4c, 0x98, 0xac, 0x81, 0xdf, 0xe6, 0xaa, 0xf4, 0x73, 0xd3, 0x74, 0x83,
- 0x6b, 0xea, 0x51, 0xfa, 0x99, 0x9b, 0xa5, 0x9b, 0xb3, 0x4b, 0x7a, 0xc1, 0x59, 0x69, 0x69, 0xb6,
- 0xfb, 0xbc, 0x9c, 0x5d, 0xfe, 0xcc, 0x59, 0x69, 0x38, 0x3b, 0xf7, 0x7f, 0xab, 0xe7, 0xba, 0xae,
- 0x9b, 0xe2, 0xff, 0x8e, 0x7f, 0x03, 0x00, 0x00, 0xff, 0xff, 0x4d, 0x2a, 0x36, 0xe3, 0x87, 0x08,
- 0x00, 0x00,
+ // 1021 bytes of a gzipped FileDescriptorProto
+ 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x56, 0xef, 0x6e, 0xdb, 0x36,
+ 0x10, 0xaf, 0x12, 0x27, 0xb6, 0x4e, 0xb1, 0xab, 0x30, 0xed, 0xa2, 0xb6, 0x08, 0x66, 0x18, 0x6b,
+ 0x11, 0x0c, 0x6b, 0x5a, 0x64, 0x45, 0x50, 0x04, 0xc5, 0x00, 0xc7, 0x09, 0xb2, 0x2e, 0x48, 0x5c,
+ 0x30, 0x7f, 0x56, 0x6c, 0x1f, 0x04, 0x5a, 0xa2, 0x13, 0x75, 0x96, 0x28, 0x90, 0x54, 0x91, 0xf4,
+ 0x1d, 0xf6, 0x54, 0x7b, 0x96, 0xbd, 0xc6, 0x30, 0xf0, 0x28, 0xd9, 0xca, 0xe6, 0xad, 0x41, 0xbf,
+ 0x89, 0xf7, 0xfb, 0xc3, 0x3b, 0xf2, 0x78, 0x36, 0xb4, 0x53, 0xae, 0x65, 0x12, 0xa9, 0xad, 0x5c,
+ 0x0a, 0x2d, 0xc8, 0x9a, 0x12, 0x22, 0xbb, 0x0c, 0x47, 0x45, 0x32, 0x89, 0xc3, 0x12, 0xea, 0xfd,
+ 0x05, 0xe0, 0x1d, 0xdb, 0xef, 0x3d, 0xa6, 0x38, 0x79, 0x09, 0x0f, 0x2c, 0x21, 0x66, 0x9a, 0x87,
+ 0x3a, 0x49, 0xb9, 0xd2, 0x2c, 0xcd, 0x03, 0xa7, 0xeb, 0x6c, 0x2e, 0x52, 0x82, 0xd8, 0x3e, 0xd3,
+ 0xfc, 0xac, 0x42, 0xc8, 0x23, 0x68, 0x59, 0x45, 0x12, 0x07, 0x0b, 0x5d, 0x67, 0xd3, 0xa5, 0x4d,
+ 0x5c, 0xbf, 0x8d, 0xc9, 0x2e, 0x3c, 0xca, 0x27, 0x4c, 0x8f, 0x85, 0x4c, 0xc3, 0x8f, 0x5c, 0xaa,
+ 0x44, 0x64, 0x61, 0x24, 0x62, 0x9e, 0xb1, 0x94, 0x07, 0x8b, 0xc8, 0x5d, 0xaf, 0x08, 0x17, 0x16,
+ 0x1f, 0x94, 0x30, 0x79, 0x0a, 0x1d, 0xcd, 0xe4, 0x25, 0xd7, 0x61, 0x2e, 0x45, 0x5c, 0x44, 0x3a,
+ 0x68, 0xa0, 0xa0, 0x6d, 0xa3, 0xef, 0x6c, 0x90, 0xc4, 0xf0, 0xa0, 0xa4, 0xd9, 0x24, 0x3e, 0x32,
+ 0x99, 0xb0, 0x4c, 0x07, 0x4b, 0x5d, 0x67, 0xb3, 0xb3, 0xfd, 0x7c, 0x6b, 0x4e, 0xcd, 0x5b, 0xb5,
+ 0x7a, 0xb7, 0xf6, 0x0c, 0x72, 0x61, 0x45, 0xbb, 0x8b, 0x07, 0x27, 0x87, 0x94, 0x58, 0xbf, 0x3a,
+ 0x40, 0x86, 0xe0, 0x95, 0xbb, 0x30, 0x19, 0x5d, 0x05, 0xcb, 0x68, 0xfe, 0xf4, 0xb3, 0xe6, 0x7d,
+ 0x19, 0x5d, 0xed, 0x36, 0xcf, 0x4f, 0x8e, 0x4e, 0x86, 0x3f, 0x9f, 0x50, 0xb0, 0x16, 0x26, 0x48,
+ 0xb6, 0x60, 0xad, 0x66, 0x38, 0xcd, 0xba, 0x89, 0x25, 0xae, 0xce, 0x88, 0x55, 0x02, 0xdf, 0x41,
+ 0x99, 0x56, 0x18, 0xe5, 0xc5, 0x94, 0xde, 0x42, 0xba, 0x6f, 0x91, 0x41, 0x5e, 0x54, 0xec, 0x23,
+ 0x70, 0xaf, 0x84, 0x2a, 0x93, 0x75, 0xbf, 0x28, 0xd9, 0x96, 0x31, 0xc0, 0x54, 0x29, 0xb4, 0xd1,
+ 0x6c, 0x3b, 0x8b, 0xad, 0x21, 0x7c, 0x91, 0xa1, 0x67, 0x4c, 0xb6, 0xb3, 0x18, 0x3d, 0xd7, 0xa1,
+ 0x89, 0x9e, 0x42, 0x05, 0x1e, 0xd6, 0xb0, 0x6c, 0x96, 0x43, 0x45, 0x7a, 0xe5, 0x66, 0x42, 0x85,
+ 0xfc, 0x5a, 0x4b, 0x16, 0xac, 0x20, 0xec, 0x59, 0xf8, 0xc0, 0x84, 0xa6, 0x9c, 0x48, 0x0a, 0xa5,
+ 0x8c, 0x45, 0x7b, 0xc6, 0x19, 0x98, 0xd8, 0x50, 0x91, 0x67, 0x70, 0xbf, 0xc6, 0xc1, 0xb4, 0x3b,
+ 0xb6, 0x7d, 0xa6, 0x2c, 0x4c, 0xe4, 0x39, 0xac, 0xd5, 0x78, 0xd3, 0x12, 0xef, 0xdb, 0x83, 0x9d,
+ 0x72, 0x6b, 0x79, 0x8b, 0x42, 0x87, 0x71, 0x22, 0x03, 0xdf, 0xe6, 0x2d, 0x0a, 0xbd, 0x9f, 0x48,
+ 0xf2, 0x03, 0x78, 0x8a, 0xeb, 0x22, 0x0f, 0xb5, 0x10, 0x13, 0x15, 0xac, 0x76, 0x17, 0x37, 0xbd,
+ 0xed, 0x8d, 0xb9, 0x47, 0xf4, 0x8e, 0xcb, 0xf1, 0xdb, 0x6c, 0x2c, 0x28, 0xa0, 0xe2, 0xcc, 0x08,
+ 0xc8, 0x2e, 0xb8, 0xbf, 0x31, 0x9d, 0x84, 0xb2, 0xc8, 0x54, 0x40, 0xee, 0xa2, 0x6e, 0x19, 0x3e,
+ 0x2d, 0x32, 0x45, 0xde, 0x00, 0x58, 0x26, 0x8a, 0xd7, 0xee, 0x22, 0x76, 0x11, 0xad, 0xd4, 0x59,
+ 0x92, 0x7d, 0x60, 0x56, 0xfd, 0xe0, 0x4e, 0x6a, 0x14, 0xa0, 0xfa, 0x7b, 0x58, 0xd2, 0x42, 0xb3,
+ 0x49, 0xf0, 0xb0, 0xeb, 0x7c, 0x5e, 0x68, 0xb9, 0xe4, 0x02, 0xe6, 0x8d, 0xa2, 0xe0, 0x2b, 0xb4,
+ 0x78, 0x36, 0xd7, 0xe2, 0xd4, 0xc4, 0xf0, 0x49, 0x96, 0x1d, 0x46, 0x57, 0xd5, 0x3f, 0x43, 0x64,
+ 0x00, 0x2b, 0x56, 0x15, 0x89, 0x6c, 0x9c, 0x5c, 0x06, 0xeb, 0x68, 0xd8, 0x9d, 0x6b, 0x88, 0xc2,
+ 0x01, 0xf2, 0xa8, 0x37, 0x9a, 0x2d, 0x7a, 0x2f, 0x61, 0xe5, 0xd6, 0xd3, 0x6f, 0x41, 0xe3, 0xfc,
+ 0xf4, 0x80, 0xfa, 0xf7, 0x48, 0x1b, 0x5c, 0xf3, 0xb5, 0x7f, 0xb0, 0x77, 0x7e, 0xe8, 0x3b, 0xa4,
+ 0x09, 0x66, 0x5c, 0xf8, 0x0b, 0xbd, 0x37, 0xd0, 0xc0, 0xe6, 0xf0, 0xa0, 0x6a, 0x76, 0xff, 0x9e,
+ 0x41, 0xfb, 0xf4, 0xd8, 0x77, 0x88, 0x0b, 0x4b, 0x7d, 0x7a, 0xbc, 0xf3, 0xca, 0x5f, 0x30, 0xb1,
+ 0xf7, 0xaf, 0x77, 0xfc, 0x45, 0x02, 0xb0, 0xfc, 0xfe, 0xf5, 0x4e, 0xb8, 0xf3, 0xca, 0x6f, 0xf4,
+ 0xfa, 0xe0, 0xd5, 0x72, 0x31, 0xd3, 0xb4, 0x50, 0x3c, 0xbc, 0x14, 0x29, 0xc3, 0x99, 0xdb, 0xa2,
+ 0xcd, 0x42, 0xf1, 0x43, 0x91, 0x32, 0xd3, 0x7c, 0x06, 0x92, 0x23, 0x8e, 0x73, 0xb6, 0x45, 0x97,
+ 0x0b, 0xc5, 0xe9, 0x88, 0xf7, 0x7e, 0x77, 0xa0, 0x55, 0x9d, 0x31, 0x21, 0xd0, 0x88, 0xb9, 0x8a,
+ 0x50, 0xec, 0x52, 0xfc, 0x36, 0x31, 0x1c, 0xb9, 0x76, 0x3c, 0xe3, 0x37, 0xd9, 0x00, 0x50, 0x9a,
+ 0x49, 0x8d, 0x33, 0x1e, 0x87, 0x71, 0x83, 0xba, 0x18, 0x31, 0xa3, 0x9d, 0x3c, 0x01, 0x57, 0x72,
+ 0x36, 0xb1, 0x68, 0x03, 0xd1, 0x96, 0x09, 0x20, 0xb8, 0x01, 0x90, 0xf2, 0x54, 0xc8, 0x9b, 0xb0,
+ 0x50, 0x1c, 0x47, 0x6d, 0x83, 0xba, 0x36, 0x72, 0xae, 0x78, 0xef, 0x4f, 0x07, 0x3a, 0xc7, 0x22,
+ 0x2e, 0x26, 0xfc, 0xec, 0x26, 0xe7, 0x98, 0xd5, 0xaf, 0xd5, 0xd5, 0xa8, 0x1b, 0xa5, 0x79, 0x8a,
+ 0xd9, 0x75, 0xb6, 0x5f, 0xcc, 0x9f, 0x21, 0xb7, 0xa4, 0xf6, 0xa6, 0x4e, 0x51, 0x56, 0x9b, 0x26,
+ 0xa3, 0x59, 0x94, 0x7c, 0x0d, 0x5e, 0x8a, 0x9a, 0x50, 0xdf, 0xe4, 0x55, 0x95, 0x90, 0x4e, 0x6d,
+ 0xc8, 0x37, 0xd0, 0xc9, 0x8a, 0x34, 0x14, 0xe3, 0xd0, 0x06, 0x15, 0xd6, 0xdb, 0xa6, 0x2b, 0x59,
+ 0x91, 0x0e, 0xc7, 0x76, 0x3f, 0xd5, 0x7b, 0x51, 0xde, 0x44, 0xe9, 0x7a, 0xeb, 0x3a, 0x5d, 0x58,
+ 0x3a, 0x1d, 0x0e, 0x4f, 0xcc, 0xbd, 0xb7, 0xa0, 0x71, 0xdc, 0x3f, 0x3a, 0xf0, 0x17, 0x7a, 0x13,
+ 0x78, 0x3c, 0x90, 0x89, 0x4e, 0x22, 0x36, 0x39, 0x57, 0x5c, 0xfe, 0x24, 0x0a, 0x99, 0xf1, 0x9b,
+ 0xaa, 0x1b, 0xab, 0x43, 0x77, 0x6a, 0x87, 0xbe, 0x0b, 0xcd, 0xaa, 0xdb, 0x17, 0xfe, 0xa7, 0x39,
+ 0x6b, 0x53, 0x94, 0x56, 0x82, 0xde, 0x08, 0x9e, 0xcc, 0xd9, 0x4d, 0xcd, 0x9a, 0xbf, 0x11, 0x15,
+ 0x1f, 0x54, 0xe0, 0xe0, 0x0b, 0x9e, 0x7f, 0xb2, 0xff, 0x9d, 0x2d, 0x45, 0x71, 0xef, 0x0f, 0x07,
+ 0x56, 0xff, 0xf5, 0xd4, 0x48, 0x00, 0xcd, 0xea, 0xdc, 0x1c, 0x3c, 0xb7, 0x6a, 0x49, 0x1e, 0x43,
+ 0xab, 0xfc, 0x2d, 0xb2, 0x05, 0xb5, 0xe9, 0x74, 0x4d, 0xbe, 0x85, 0x55, 0x7c, 0xee, 0x21, 0x9b,
+ 0x4c, 0x44, 0x14, 0x46, 0xa2, 0xc8, 0x74, 0xd9, 0x67, 0xf7, 0x11, 0xe8, 0x9b, 0xf8, 0xc0, 0x84,
+ 0xc9, 0x26, 0xf8, 0x75, 0xae, 0x4a, 0x3e, 0x55, 0x4d, 0xd7, 0x99, 0x51, 0x4f, 0x93, 0x4f, 0xdc,
+ 0x0c, 0xff, 0x94, 0x5d, 0x87, 0x57, 0x9c, 0xe5, 0x96, 0x66, 0xbb, 0xcf, 0x4b, 0xd9, 0xf5, 0x8f,
+ 0x9c, 0xe5, 0x86, 0xb3, 0xf7, 0xf0, 0x97, 0x72, 0xbe, 0x94, 0x75, 0x87, 0xf8, 0xff, 0xe7, 0xef,
+ 0x00, 0x00, 0x00, 0xff, 0xff, 0x0a, 0x03, 0x26, 0x59, 0x0f, 0x09, 0x00, 0x00,
}
diff --git a/ui/metrics/metrics_proto/metrics.proto b/ui/metrics/metrics_proto/metrics.proto
index 50810ebdf..6559ba334 100644
--- a/ui/metrics/metrics_proto/metrics.proto
+++ b/ui/metrics/metrics_proto/metrics.proto
@@ -94,6 +94,14 @@ message MetricsBase {
optional PerfInfo total = 21;
optional SoongBuildMetrics soong_build_metrics = 22;
+
+ optional BuildConfig build_config = 23;
+}
+
+message BuildConfig {
+ optional bool use_goma = 1;
+
+ optional bool use_rbe = 2;
}
message PerfInfo {
@@ -159,4 +167,4 @@ message SoongBuildMetrics {
// The approximate maximum size of the heap in soong_build in bytes.
optional uint64 max_heap_size = 5;
-} \ No newline at end of file
+}
diff --git a/ui/terminal/Android.bp b/ui/terminal/Android.bp
index b533b0d30..aa6e35d2b 100644
--- a/ui/terminal/Android.bp
+++ b/ui/terminal/Android.bp
@@ -17,7 +17,7 @@ bootstrap_go_package {
pkgPath: "android/soong/ui/terminal",
deps: ["soong-ui-status"],
srcs: [
- "dumb_status.go",
+ "simple_status.go",
"format.go",
"smart_status.go",
"status.go",
diff --git a/ui/terminal/dumb_status.go b/ui/terminal/simple_status.go
index 201770fac..4e8c56804 100644
--- a/ui/terminal/dumb_status.go
+++ b/ui/terminal/simple_status.go
@@ -21,31 +21,31 @@ import (
"android/soong/ui/status"
)
-type dumbStatusOutput struct {
+type simpleStatusOutput struct {
writer io.Writer
formatter formatter
}
-// NewDumbStatusOutput returns a StatusOutput that represents the
+// NewSimpleStatusOutput returns a StatusOutput that represents the
// current build status similarly to Ninja's built-in terminal
// output.
-func NewDumbStatusOutput(w io.Writer, formatter formatter) status.StatusOutput {
- return &dumbStatusOutput{
+func NewSimpleStatusOutput(w io.Writer, formatter formatter) status.StatusOutput {
+ return &simpleStatusOutput{
writer: w,
formatter: formatter,
}
}
-func (s *dumbStatusOutput) Message(level status.MsgLevel, message string) {
+func (s *simpleStatusOutput) Message(level status.MsgLevel, message string) {
if level >= status.StatusLvl {
fmt.Fprintln(s.writer, s.formatter.message(level, message))
}
}
-func (s *dumbStatusOutput) StartAction(action *status.Action, counts status.Counts) {
+func (s *simpleStatusOutput) StartAction(action *status.Action, counts status.Counts) {
}
-func (s *dumbStatusOutput) FinishAction(result status.ActionResult, counts status.Counts) {
+func (s *simpleStatusOutput) FinishAction(result status.ActionResult, counts status.Counts) {
str := result.Description
if str == "" {
str = result.Command
@@ -63,9 +63,9 @@ func (s *dumbStatusOutput) FinishAction(result status.ActionResult, counts statu
}
}
-func (s *dumbStatusOutput) Flush() {}
+func (s *simpleStatusOutput) Flush() {}
-func (s *dumbStatusOutput) Write(p []byte) (int, error) {
+func (s *simpleStatusOutput) Write(p []byte) (int, error) {
fmt.Fprint(s.writer, string(p))
return len(p), nil
}
diff --git a/ui/terminal/status.go b/ui/terminal/status.go
index 60dfc7025..d8e739211 100644
--- a/ui/terminal/status.go
+++ b/ui/terminal/status.go
@@ -26,12 +26,12 @@ import (
//
// statusFormat takes nearly all the same options as NINJA_STATUS.
// %c is currently unsupported.
-func NewStatusOutput(w io.Writer, statusFormat string, forceDumbOutput, quietBuild bool) status.StatusOutput {
+func NewStatusOutput(w io.Writer, statusFormat string, forceSimpleOutput, quietBuild bool) status.StatusOutput {
formatter := newFormatter(statusFormat, quietBuild)
- if !forceDumbOutput && isSmartTerminal(w) {
+ if !forceSimpleOutput && isSmartTerminal(w) {
return NewSmartStatusOutput(w, formatter)
} else {
- return NewDumbStatusOutput(w, formatter)
+ return NewSimpleStatusOutput(w, formatter)
}
}
diff --git a/ui/terminal/status_test.go b/ui/terminal/status_test.go
index 9f6082988..aa69dff53 100644
--- a/ui/terminal/status_test.go
+++ b/ui/terminal/status_test.go
@@ -26,64 +26,64 @@ import (
func TestStatusOutput(t *testing.T) {
tests := []struct {
- name string
- calls func(stat status.StatusOutput)
- smart string
- dumb string
+ name string
+ calls func(stat status.StatusOutput)
+ smart string
+ simple string
}{
{
- name: "two actions",
- calls: twoActions,
- smart: "\r\x1b[1m[ 0% 0/2] action1\x1b[0m\x1b[K\r\x1b[1m[ 50% 1/2] action1\x1b[0m\x1b[K\r\x1b[1m[ 50% 1/2] action2\x1b[0m\x1b[K\r\x1b[1m[100% 2/2] action2\x1b[0m\x1b[K\n",
- dumb: "[ 50% 1/2] action1\n[100% 2/2] action2\n",
+ name: "two actions",
+ calls: twoActions,
+ smart: "\r\x1b[1m[ 0% 0/2] action1\x1b[0m\x1b[K\r\x1b[1m[ 50% 1/2] action1\x1b[0m\x1b[K\r\x1b[1m[ 50% 1/2] action2\x1b[0m\x1b[K\r\x1b[1m[100% 2/2] action2\x1b[0m\x1b[K\n",
+ simple: "[ 50% 1/2] action1\n[100% 2/2] action2\n",
},
{
- name: "two parallel actions",
- calls: twoParallelActions,
- smart: "\r\x1b[1m[ 0% 0/2] action1\x1b[0m\x1b[K\r\x1b[1m[ 0% 0/2] action2\x1b[0m\x1b[K\r\x1b[1m[ 50% 1/2] action1\x1b[0m\x1b[K\r\x1b[1m[100% 2/2] action2\x1b[0m\x1b[K\n",
- dumb: "[ 50% 1/2] action1\n[100% 2/2] action2\n",
+ name: "two parallel actions",
+ calls: twoParallelActions,
+ smart: "\r\x1b[1m[ 0% 0/2] action1\x1b[0m\x1b[K\r\x1b[1m[ 0% 0/2] action2\x1b[0m\x1b[K\r\x1b[1m[ 50% 1/2] action1\x1b[0m\x1b[K\r\x1b[1m[100% 2/2] action2\x1b[0m\x1b[K\n",
+ simple: "[ 50% 1/2] action1\n[100% 2/2] action2\n",
},
{
- name: "action with output",
- calls: actionsWithOutput,
- smart: "\r\x1b[1m[ 0% 0/3] action1\x1b[0m\x1b[K\r\x1b[1m[ 33% 1/3] action1\x1b[0m\x1b[K\r\x1b[1m[ 33% 1/3] action2\x1b[0m\x1b[K\r\x1b[1m[ 66% 2/3] action2\x1b[0m\x1b[K\noutput1\noutput2\n\r\x1b[1m[ 66% 2/3] action3\x1b[0m\x1b[K\r\x1b[1m[100% 3/3] action3\x1b[0m\x1b[K\n",
- dumb: "[ 33% 1/3] action1\n[ 66% 2/3] action2\noutput1\noutput2\n[100% 3/3] action3\n",
+ name: "action with output",
+ calls: actionsWithOutput,
+ smart: "\r\x1b[1m[ 0% 0/3] action1\x1b[0m\x1b[K\r\x1b[1m[ 33% 1/3] action1\x1b[0m\x1b[K\r\x1b[1m[ 33% 1/3] action2\x1b[0m\x1b[K\r\x1b[1m[ 66% 2/3] action2\x1b[0m\x1b[K\noutput1\noutput2\n\r\x1b[1m[ 66% 2/3] action3\x1b[0m\x1b[K\r\x1b[1m[100% 3/3] action3\x1b[0m\x1b[K\n",
+ simple: "[ 33% 1/3] action1\n[ 66% 2/3] action2\noutput1\noutput2\n[100% 3/3] action3\n",
},
{
- name: "action with output without newline",
- calls: actionsWithOutputWithoutNewline,
- smart: "\r\x1b[1m[ 0% 0/3] action1\x1b[0m\x1b[K\r\x1b[1m[ 33% 1/3] action1\x1b[0m\x1b[K\r\x1b[1m[ 33% 1/3] action2\x1b[0m\x1b[K\r\x1b[1m[ 66% 2/3] action2\x1b[0m\x1b[K\noutput1\noutput2\n\r\x1b[1m[ 66% 2/3] action3\x1b[0m\x1b[K\r\x1b[1m[100% 3/3] action3\x1b[0m\x1b[K\n",
- dumb: "[ 33% 1/3] action1\n[ 66% 2/3] action2\noutput1\noutput2\n[100% 3/3] action3\n",
+ name: "action with output without newline",
+ calls: actionsWithOutputWithoutNewline,
+ smart: "\r\x1b[1m[ 0% 0/3] action1\x1b[0m\x1b[K\r\x1b[1m[ 33% 1/3] action1\x1b[0m\x1b[K\r\x1b[1m[ 33% 1/3] action2\x1b[0m\x1b[K\r\x1b[1m[ 66% 2/3] action2\x1b[0m\x1b[K\noutput1\noutput2\n\r\x1b[1m[ 66% 2/3] action3\x1b[0m\x1b[K\r\x1b[1m[100% 3/3] action3\x1b[0m\x1b[K\n",
+ simple: "[ 33% 1/3] action1\n[ 66% 2/3] action2\noutput1\noutput2\n[100% 3/3] action3\n",
},
{
- name: "action with error",
- calls: actionsWithError,
- smart: "\r\x1b[1m[ 0% 0/3] action1\x1b[0m\x1b[K\r\x1b[1m[ 33% 1/3] action1\x1b[0m\x1b[K\r\x1b[1m[ 33% 1/3] action2\x1b[0m\x1b[K\r\x1b[1m[ 66% 2/3] action2\x1b[0m\x1b[K\nFAILED: f1 f2\ntouch f1 f2\nerror1\nerror2\n\r\x1b[1m[ 66% 2/3] action3\x1b[0m\x1b[K\r\x1b[1m[100% 3/3] action3\x1b[0m\x1b[K\n",
- dumb: "[ 33% 1/3] action1\n[ 66% 2/3] action2\nFAILED: f1 f2\ntouch f1 f2\nerror1\nerror2\n[100% 3/3] action3\n",
+ name: "action with error",
+ calls: actionsWithError,
+ smart: "\r\x1b[1m[ 0% 0/3] action1\x1b[0m\x1b[K\r\x1b[1m[ 33% 1/3] action1\x1b[0m\x1b[K\r\x1b[1m[ 33% 1/3] action2\x1b[0m\x1b[K\r\x1b[1m[ 66% 2/3] action2\x1b[0m\x1b[K\nFAILED: f1 f2\ntouch f1 f2\nerror1\nerror2\n\r\x1b[1m[ 66% 2/3] action3\x1b[0m\x1b[K\r\x1b[1m[100% 3/3] action3\x1b[0m\x1b[K\n",
+ simple: "[ 33% 1/3] action1\n[ 66% 2/3] action2\nFAILED: f1 f2\ntouch f1 f2\nerror1\nerror2\n[100% 3/3] action3\n",
},
{
- name: "action with empty description",
- calls: actionWithEmptyDescription,
- smart: "\r\x1b[1m[ 0% 0/1] command1\x1b[0m\x1b[K\r\x1b[1m[100% 1/1] command1\x1b[0m\x1b[K\n",
- dumb: "[100% 1/1] command1\n",
+ name: "action with empty description",
+ calls: actionWithEmptyDescription,
+ smart: "\r\x1b[1m[ 0% 0/1] command1\x1b[0m\x1b[K\r\x1b[1m[100% 1/1] command1\x1b[0m\x1b[K\n",
+ simple: "[100% 1/1] command1\n",
},
{
- name: "messages",
- calls: actionsWithMessages,
- smart: "\r\x1b[1m[ 0% 0/2] action1\x1b[0m\x1b[K\r\x1b[1m[ 50% 1/2] action1\x1b[0m\x1b[K\r\x1b[1mstatus\x1b[0m\x1b[K\r\x1b[Kprint\nFAILED: error\n\r\x1b[1m[ 50% 1/2] action2\x1b[0m\x1b[K\r\x1b[1m[100% 2/2] action2\x1b[0m\x1b[K\n",
- dumb: "[ 50% 1/2] action1\nstatus\nprint\nFAILED: error\n[100% 2/2] action2\n",
+ name: "messages",
+ calls: actionsWithMessages,
+ smart: "\r\x1b[1m[ 0% 0/2] action1\x1b[0m\x1b[K\r\x1b[1m[ 50% 1/2] action1\x1b[0m\x1b[K\r\x1b[1mstatus\x1b[0m\x1b[K\r\x1b[Kprint\nFAILED: error\n\r\x1b[1m[ 50% 1/2] action2\x1b[0m\x1b[K\r\x1b[1m[100% 2/2] action2\x1b[0m\x1b[K\n",
+ simple: "[ 50% 1/2] action1\nstatus\nprint\nFAILED: error\n[100% 2/2] action2\n",
},
{
- name: "action with long description",
- calls: actionWithLongDescription,
- smart: "\r\x1b[1m[ 0% 0/2] action with very long descrip\x1b[0m\x1b[K\r\x1b[1m[ 50% 1/2] action with very long descrip\x1b[0m\x1b[K\n",
- dumb: "[ 50% 1/2] action with very long description to test eliding\n",
+ name: "action with long description",
+ calls: actionWithLongDescription,
+ smart: "\r\x1b[1m[ 0% 0/2] action with very long descrip\x1b[0m\x1b[K\r\x1b[1m[ 50% 1/2] action with very long descrip\x1b[0m\x1b[K\n",
+ simple: "[ 50% 1/2] action with very long description to test eliding\n",
},
{
- name: "action with output with ansi codes",
- calls: actionWithOuptutWithAnsiCodes,
- smart: "\r\x1b[1m[ 0% 0/1] action1\x1b[0m\x1b[K\r\x1b[1m[100% 1/1] action1\x1b[0m\x1b[K\n\x1b[31mcolor\x1b[0m\n",
- dumb: "[100% 1/1] action1\ncolor\n",
+ name: "action with output with ansi codes",
+ calls: actionWithOuptutWithAnsiCodes,
+ smart: "\r\x1b[1m[ 0% 0/1] action1\x1b[0m\x1b[K\r\x1b[1m[100% 1/1] action1\x1b[0m\x1b[K\n\x1b[31mcolor\x1b[0m\n",
+ simple: "[100% 1/1] action1\ncolor\n",
},
}
@@ -103,24 +103,24 @@ func TestStatusOutput(t *testing.T) {
}
})
- t.Run("dumb", func(t *testing.T) {
- dumb := &bytes.Buffer{}
- stat := NewStatusOutput(dumb, "", false, false)
+ t.Run("simple", func(t *testing.T) {
+ simple := &bytes.Buffer{}
+ stat := NewStatusOutput(simple, "", false, false)
tt.calls(stat)
stat.Flush()
- if g, w := dumb.String(), tt.dumb; g != w {
+ if g, w := simple.String(), tt.simple; g != w {
t.Errorf("want:\n%q\ngot:\n%q", w, g)
}
})
- t.Run("force dumb", func(t *testing.T) {
+ t.Run("force simple", func(t *testing.T) {
smart := &fakeSmartTerminal{termWidth: 40}
stat := NewStatusOutput(smart, "", true, false)
tt.calls(stat)
stat.Flush()
- if g, w := smart.String(), tt.dumb; g != w {
+ if g, w := smart.String(), tt.simple; g != w {
t.Errorf("want:\n%q\ngot:\n%q", w, g)
}
})
diff --git a/zip/cmd/main.go b/zip/cmd/main.go
index fba2e4b1e..d603586e6 100644
--- a/zip/cmd/main.go
+++ b/zip/cmd/main.go
@@ -62,6 +62,15 @@ func (listFiles) Set(s string) error {
return nil
}
+type rspFiles struct{}
+
+func (rspFiles) String() string { return `""` }
+
+func (rspFiles) Set(s string) error {
+ fileArgsBuilder.RspFile(s)
+ return nil
+}
+
type dir struct{}
func (dir) String() string { return `""` }
@@ -143,7 +152,8 @@ func main() {
traceFile := flags.String("trace", "", "write trace to file")
flags.Var(&rootPrefix{}, "P", "path prefix within the zip at which to place files")
- flags.Var(&listFiles{}, "l", "file containing list of .class files")
+ flags.Var(&listFiles{}, "l", "file containing list of files to zip")
+ flags.Var(&rspFiles{}, "r", "file containing list of files to zip with Ninja rsp file escaping")
flags.Var(&dir{}, "D", "directory to include in zip")
flags.Var(&file{}, "f", "file to include in zip")
flags.Var(&nonDeflatedFiles, "s", "file path to be stored within the zip without compression")
diff --git a/zip/zip.go b/zip/zip.go
index 3c710a782..e27432cbb 100644
--- a/zip/zip.go
+++ b/zip/zip.go
@@ -150,6 +150,30 @@ func (b *FileArgsBuilder) List(name string) *FileArgsBuilder {
return b
}
+func (b *FileArgsBuilder) RspFile(name string) *FileArgsBuilder {
+ if b.err != nil {
+ return b
+ }
+
+ f, err := b.fs.Open(name)
+ if err != nil {
+ b.err = err
+ return b
+ }
+ defer f.Close()
+
+ list, err := ioutil.ReadAll(f)
+ if err != nil {
+ b.err = err
+ return b
+ }
+
+ arg := b.state
+ arg.SourceFiles = ReadRespFile(list)
+ b.fileArgs = append(b.fileArgs, arg)
+ return b
+}
+
func (b *FileArgsBuilder) Error() error {
if b == nil {
return nil
diff --git a/zip/zip_test.go b/zip/zip_test.go
index 9705d6c49..302a749a3 100644
--- a/zip/zip_test.go
+++ b/zip/zip_test.go
@@ -49,6 +49,9 @@ var mockFs = pathtools.MockFs(map[string][]byte{
"l_nl": []byte("a/a/a\na/a/b\nc\n"),
"l_sp": []byte("a/a/a a/a/b c"),
"l2": []byte("missing\n"),
+ "rsp": []byte("'a/a/a'\na/a/b\n'@'\n'foo'\\''bar'"),
+ "@ -> c": nil,
+ "foo'bar -> c": nil,
"manifest.txt": fileCustomManifest,
})
@@ -247,6 +250,19 @@ func TestZip(t *testing.T) {
},
},
{
+ name: "rsp",
+ args: fileArgsBuilder().
+ RspFile("rsp"),
+ compressionLevel: 9,
+
+ files: []zip.FileHeader{
+ fh("a/a/a", fileA, zip.Deflate),
+ fh("a/a/b", fileB, zip.Deflate),
+ fh("@", fileC, zip.Deflate),
+ fh("foo'bar", fileC, zip.Deflate),
+ },
+ },
+ {
name: "prefix in zip",
args: fileArgsBuilder().
PathPrefixInZip("foo").
@@ -568,6 +584,11 @@ func TestReadRespFile(t *testing.T) {
in: `./cmd "\""-C`,
out: []string{"./cmd", `"-C`},
},
+ {
+ name: "ninja rsp file",
+ in: "'a'\nb\n'@'\n'foo'\\''bar'\n'foo\"bar'",
+ out: []string{"a", "b", "@", "foo'bar", `foo"bar`},
+ },
}
for _, testCase := range testCases {