Merge "Move env var config loading to be within the config package."
diff --git a/android/bazel.go b/android/bazel.go
index 528c7b1..0940205 100644
--- a/android/bazel.go
+++ b/android/bazel.go
@@ -217,7 +217,6 @@
"external/bazelbuild-rules_android":/* recursive = */ true,
"external/bazel-skylib":/* recursive = */ true,
"external/guava":/* recursive = */ true,
- "external/error_prone":/* recursive = */ true,
"external/jsr305":/* recursive = */ true,
"frameworks/ex/common":/* recursive = */ true,
@@ -292,6 +291,7 @@
"external/bouncycastle": Bp2BuildDefaultTrue,
"external/brotli": Bp2BuildDefaultTrue,
"external/conscrypt": Bp2BuildDefaultTrue,
+ "external/error_prone": Bp2BuildDefaultTrue,
"external/fmtlib": Bp2BuildDefaultTrueRecursively,
"external/google-benchmark": Bp2BuildDefaultTrueRecursively,
"external/googletest": Bp2BuildDefaultTrueRecursively,
@@ -341,6 +341,7 @@
"packages/screensavers/Basic": Bp2BuildDefaultTrue,
"packages/services/Car/tests/SampleRearViewCamera": Bp2BuildDefaultTrue,
"prebuilts/clang/host/linux-x86": Bp2BuildDefaultTrueRecursively,
+ "prebuilts/tools/common/m2": Bp2BuildDefaultTrue,
"system/apex": Bp2BuildDefaultFalse, // TODO(b/207466993): flaky failures
"system/apex/proto": Bp2BuildDefaultTrueRecursively,
"system/apex/libs": Bp2BuildDefaultTrueRecursively,
@@ -469,10 +470,11 @@
"libdexfiled", // depends on unconverted modules: dexfile_operator_srcs, libartbased, libartpalette
// go deps:
- "apex-protos", // depends on soong_zip, a go binary
- "robolectric_tzdata", // depends on soong_zip, a go binary
- "host_bionic_linker_asm", // depends on extract_linker, a go binary.
- "host_bionic_linker_script", // depends on extract_linker, a go binary.
+ "apex-protos", // depends on soong_zip, a go binary
+ "robolectric_tzdata", // depends on soong_zip, a go binary
+ "robolectric-sqlite4java-native", // depends on soong_zip, a go binary
+ "host_bionic_linker_asm", // depends on extract_linker, a go binary.
+ "host_bionic_linker_script", // depends on extract_linker, a go binary.
// java deps
"bin2c_fastdeployagent", // depends on deployagent, a java binary
diff --git a/android/config.go b/android/config.go
index 4472036..10e074c 100644
--- a/android/config.go
+++ b/android/config.go
@@ -24,6 +24,7 @@
"io/ioutil"
"os"
"path/filepath"
+ "reflect"
"runtime"
"strconv"
"strings"
@@ -273,15 +274,45 @@
return fmt.Errorf("Could not create dir %s: %s", dir, err)
}
- data, err := json.MarshalIndent(&config, "", " ")
+ nonArchVariantProductVariables := []string{}
+ archVariantProductVariables := []string{}
+ p := variableProperties{}
+ t := reflect.TypeOf(p.Product_variables)
+ for i := 0; i < t.NumField(); i++ {
+ f := t.Field(i)
+ nonArchVariantProductVariables = append(nonArchVariantProductVariables, strings.ToLower(f.Name))
+ if proptools.HasTag(f, "android", "arch_variant") {
+ archVariantProductVariables = append(archVariantProductVariables, strings.ToLower(f.Name))
+ }
+ }
+
+ //TODO(b/216168792) should use common function to print Starlark code
+ nonArchVariantProductVariablesJson, err := json.MarshalIndent(&nonArchVariantProductVariables, "", " ")
+ if err != nil {
+ return fmt.Errorf("cannot marshal product variable data: %s", err.Error())
+ }
+
+ //TODO(b/216168792) should use common function to print Starlark code
+ archVariantProductVariablesJson, err := json.MarshalIndent(&archVariantProductVariables, "", " ")
+ if err != nil {
+ return fmt.Errorf("cannot marshal arch variant product variable data: %s", err.Error())
+ }
+
+ configJson, err := json.MarshalIndent(&config, "", " ")
if err != nil {
return fmt.Errorf("cannot marshal config data: %s", err.Error())
}
bzl := []string{
bazel.GeneratedBazelFileWarning,
- fmt.Sprintf(`_product_vars = json.decode("""%s""")`, data),
- "product_vars = _product_vars\n",
+ fmt.Sprintf(`_product_vars = json.decode("""%s""")`, configJson),
+ fmt.Sprintf(`_product_var_constraints = %s`, nonArchVariantProductVariablesJson),
+ fmt.Sprintf(`_arch_variant_product_var_constraints = %s`, archVariantProductVariablesJson),
+ "\n", `
+product_vars = _product_vars
+product_var_constraints = _product_var_constraints
+arch_variant_product_var_constraints = _arch_variant_product_var_constraints
+`,
}
err = ioutil.WriteFile(filepath.Join(dir, "product_variables.bzl"), []byte(strings.Join(bzl, "\n")), 0644)
if err != nil {
diff --git a/android/module.go b/android/module.go
index 3c8c777..666732f 100644
--- a/android/module.go
+++ b/android/module.go
@@ -267,7 +267,7 @@
//
// The Modules passed to the visit function should not be retained outside of the visit function, they may be
// invalidated by future mutators.
- WalkDeps(visit func(Module, Module) bool)
+ WalkDeps(visit func(child, parent Module) bool)
// WalkDepsBlueprint calls visit for each transitive dependency, traversing the dependency
// tree in top down order. visit may be called multiple times for the same (child, parent)
@@ -2620,7 +2620,7 @@
}
if aModule == nil {
- b.ModuleErrorf("module %q not an android module", b.OtherModuleName(module))
+ b.ModuleErrorf("module %q (%#v) not an android module", b.OtherModuleName(module), tag)
return nil
}
@@ -2742,8 +2742,8 @@
func (b *baseModuleContext) VisitDirectDepsWithTag(tag blueprint.DependencyTag, visit func(Module)) {
b.bp.VisitDirectDeps(func(module blueprint.Module) {
- if aModule := b.validateAndroidModule(module, b.bp.OtherModuleDependencyTag(module), b.strictVisitDeps); aModule != nil {
- if b.bp.OtherModuleDependencyTag(aModule) == tag {
+ if b.bp.OtherModuleDependencyTag(module) == tag {
+ if aModule := b.validateAndroidModule(module, b.bp.OtherModuleDependencyTag(module), b.strictVisitDeps); aModule != nil {
visit(aModule)
}
}
diff --git a/androidmk/androidmk/androidmk_test.go b/androidmk/androidmk/androidmk_test.go
index 3c36197..abdbf53 100644
--- a/androidmk/androidmk/androidmk_test.go
+++ b/androidmk/androidmk/androidmk_test.go
@@ -699,7 +699,7 @@
expected: `
android_library {
srcs: ["test.java"],
- resource_dirs: ["res"],
+
jacoco: {
include_filter: ["foo.*"],
},
@@ -1458,7 +1458,7 @@
runtime_resource_overlay {
name: "foo",
product_specific: true,
- resource_dirs: ["res"],
+
sdk_version: "current",
theme: "FooTheme",
@@ -1604,6 +1604,22 @@
}
`,
},
+ {
+ desc: "Drop default resource and asset dirs from bp",
+ in: `
+include $(CLEAR_VARS)
+LOCAL_MODULE := foo
+LOCAL_ASSET_DIR := $(LOCAL_PATH)/assets
+LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
+include $(BUILD_PACKAGE)
+`,
+ expected: `
+android_app {
+ name: "foo",
+
+}
+`,
+ },
}
func TestEndToEnd(t *testing.T) {
diff --git a/bp2build/java_import_conversion_test.go b/bp2build/java_import_conversion_test.go
new file mode 100644
index 0000000..2f7211c
--- /dev/null
+++ b/bp2build/java_import_conversion_test.go
@@ -0,0 +1,52 @@
+// Copyright 2022 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 bp2build
+
+import (
+ "android/soong/android"
+ "android/soong/java"
+
+ "testing"
+)
+
+func runJavaImportTestCase(t *testing.T, tc bp2buildTestCase) {
+ t.Helper()
+ runBp2BuildTestCase(t, registerJavaImportModuleTypes, tc)
+}
+
+func registerJavaImportModuleTypes(ctx android.RegistrationContext) {
+}
+
+func TestMinimalJavaImport(t *testing.T) {
+ runJavaImportTestCase(t, bp2buildTestCase{
+ description: "Java import - simple example",
+ moduleTypeUnderTest: "java_import",
+ moduleTypeUnderTestFactory: java.ImportFactory,
+ filesystem: map[string]string{
+ "import.jar": "",
+ },
+ blueprint: `
+java_import {
+ name: "example_import",
+ jars: ["import.jar"],
+ bazel_module: { bp2build_available: true },
+}
+`,
+ expectedBazelTargets: []string{
+ makeBazelTarget("java_import", "example_import", attrNameToString{
+ "jars": `["import.jar"]`,
+ }),
+ }})
+}
diff --git a/bpf/bpf.go b/bpf/bpf.go
index 187b4db..a4999e5 100644
--- a/bpf/bpf.go
+++ b/bpf/bpf.go
@@ -23,6 +23,7 @@
_ "android/soong/cc/config"
"github.com/google/blueprint"
+ "github.com/google/blueprint/proptools"
)
func init() {
@@ -41,6 +42,14 @@
CommandDeps: []string{"$ccCmd"},
},
"ccCmd", "cFlags")
+
+ stripRule = pctx.AndroidStaticRule("stripRule",
+ blueprint.RuleParams{
+ Command: `$stripCmd --strip-unneeded --remove-section=.rel.BTF ` +
+ `--remove-section=.rel.BTF.ext --remove-section=.BTF.ext $in -o $out`,
+ CommandDeps: []string{"$stripCmd"},
+ },
+ "stripCmd")
)
func registerBpfBuildComponents(ctx android.RegistrationContext) {
@@ -64,6 +73,8 @@
Cflags []string
Include_dirs []string
Sub_dir string
+ // If set to true, generate BTF debug info for maps & programs
+ Btf *bool
}
type bpf struct {
@@ -99,10 +110,14 @@
cflags = append(cflags, bpf.properties.Cflags...)
+ if proptools.Bool(bpf.properties.Btf) {
+ cflags = append(cflags, "-g")
+ }
+
srcs := android.PathsForModuleSrc(ctx, bpf.properties.Srcs)
for _, src := range srcs {
- obj := android.ObjPathWithExt(ctx, "", src, "o")
+ obj := android.ObjPathWithExt(ctx, "unstripped", src, "o")
ctx.Build(pctx, android.BuildParams{
Rule: ccRule,
@@ -114,7 +129,21 @@
},
})
- bpf.objs = append(bpf.objs, obj.WithoutRel())
+ if proptools.Bool(bpf.properties.Btf) {
+ objStripped := android.ObjPathWithExt(ctx, "", src, "o")
+ ctx.Build(pctx, android.BuildParams{
+ Rule: stripRule,
+ Input: obj,
+ Output: objStripped,
+ Args: map[string]string{
+ "stripCmd": "${config.ClangBin}/llvm-strip",
+ },
+ })
+ bpf.objs = append(bpf.objs, objStripped.WithoutRel())
+ } else {
+ bpf.objs = append(bpf.objs, obj.WithoutRel())
+ }
+
}
}
diff --git a/bpfix/bpfix/bpfix.go b/bpfix/bpfix/bpfix.go
index a9a0b1f..4f7d88c 100644
--- a/bpfix/bpfix/bpfix.go
+++ b/bpfix/bpfix/bpfix.go
@@ -158,6 +158,10 @@
Name: "formatFlagProperties",
Fix: runPatchListMod(formatFlagProperties),
},
+ {
+ Name: "removeResourcesAndAssetsIfDefault",
+ Fix: removeResourceAndAssetsIfDefault,
+ },
}
// for fix that only need to run once
@@ -886,6 +890,24 @@
return nil
}
+func removeResourceAndAssetsIfDefault(f *Fixer) error {
+ for _, def := range f.tree.Defs {
+ mod, ok := def.(*parser.Module)
+ if !ok {
+ continue
+ }
+ resourceDirList, resourceDirFound := getLiteralListPropertyValue(mod, "resource_dirs")
+ if resourceDirFound && len(resourceDirList) == 1 && resourceDirList[0] == "res" {
+ removeProperty(mod, "resource_dirs")
+ }
+ assetDirList, assetDirFound := getLiteralListPropertyValue(mod, "asset_dirs")
+ if assetDirFound && len(assetDirList) == 1 && assetDirList[0] == "assets" {
+ removeProperty(mod, "asset_dirs")
+ }
+ }
+ return nil
+}
+
// Converts the default source list property, 'srcs', to a single source property with a given name.
// "LOCAL_MODULE" reference is also resolved during the conversion process.
func convertToSingleSource(mod *parser.Module, srcPropertyName string) {
diff --git a/bpfix/bpfix/bpfix_test.go b/bpfix/bpfix/bpfix_test.go
index 1941837..17b3c24 100644
--- a/bpfix/bpfix/bpfix_test.go
+++ b/bpfix/bpfix/bpfix_test.go
@@ -19,11 +19,10 @@
import (
"bytes"
"fmt"
+ "reflect"
"strings"
"testing"
- "reflect"
-
"github.com/google/blueprint/parser"
"github.com/google/blueprint/pathtools"
)
@@ -2063,3 +2062,124 @@
})
}
}
+
+func TestRemoveResourceAndAssetsIfDefault(t *testing.T) {
+ tests := []struct {
+ name string
+ in string
+ out string
+ }{
+ {
+ name: "resource_dirs default",
+ in: `
+ android_app {
+ name: "foo",
+ resource_dirs: ["res"],
+ }
+ `,
+ out: `
+ android_app {
+ name: "foo",
+
+ }
+ `,
+ },
+ {
+ name: "resource_dirs not default",
+ in: `
+ android_app {
+ name: "foo",
+ resource_dirs: ["reso"],
+ }
+ `,
+ out: `
+ android_app {
+ name: "foo",
+ resource_dirs: ["reso"],
+ }
+ `,
+ },
+ {
+ name: "resource_dirs includes not default",
+ in: `
+ android_app {
+ name: "foo",
+ resource_dirs: ["res", "reso"],
+ }
+ `,
+ out: `
+ android_app {
+ name: "foo",
+ resource_dirs: ["res", "reso"],
+ }
+ `,
+ }, {
+ name: "asset_dirs default",
+ in: `
+ android_app {
+ name: "foo",
+ asset_dirs: ["assets"],
+ }
+ `,
+ out: `
+ android_app {
+ name: "foo",
+
+ }
+ `,
+ },
+ {
+ name: "asset_dirs not default",
+ in: `
+ android_app {
+ name: "foo",
+ asset_dirs: ["assety"],
+ }
+ `,
+ out: `
+ android_app {
+ name: "foo",
+ asset_dirs: ["assety"],
+ }
+ `,
+ },
+ {
+ name: "asset_dirs includes not default",
+ in: `
+ android_app {
+ name: "foo",
+ asset_dirs: ["assets", "assety"],
+ }
+ `,
+ out: `
+ android_app {
+ name: "foo",
+ asset_dirs: ["assets", "assety"],
+ }
+ `,
+ },
+ {
+ name: "resource_dirs and asset_dirs both default",
+ in: `
+ android_app {
+ name: "foo",
+ asset_dirs: ["assets"],
+ resource_dirs: ["res"],
+ }
+ `,
+ out: `
+ android_app {
+ name: "foo",
+
+ }
+ `,
+ },
+ }
+ for _, test := range tests {
+ t.Run(test.name, func(t *testing.T) {
+ runPassOnce(t, test.in, test.out, func(fixer *Fixer) error {
+ return removeResourceAndAssetsIfDefault(fixer)
+ })
+ })
+ }
+}
diff --git a/cc/Android.bp b/cc/Android.bp
index cf45630..9103a48 100644
--- a/cc/Android.bp
+++ b/cc/Android.bp
@@ -88,6 +88,7 @@
"stub_library.go",
],
testSrcs: [
+ "afdo_test.go",
"cc_test.go",
"compiler_test.go",
"gen_test.go",
diff --git a/cc/OWNERS b/cc/OWNERS
index 811d881..a438b15 100644
--- a/cc/OWNERS
+++ b/cc/OWNERS
@@ -1,4 +1,4 @@
per-file ndk_*.go = danalbert@google.com
per-file tidy.go = srhines@google.com, chh@google.com
-per-file afdo.go,lto.go,pgo.go = srhines@google.com, pirama@google.com, yikong@google.com
-
+per-file afdo.go,afdo_test.go,lto.go,pgo.go = srhines@google.com, pirama@google.com, yikong@google.com
+per-file coverage.go = pirama@google.com, srhines@google.com, allenhair@google.com
diff --git a/cc/afdo_test.go b/cc/afdo_test.go
new file mode 100644
index 0000000..5515464
--- /dev/null
+++ b/cc/afdo_test.go
@@ -0,0 +1,70 @@
+// Copyright 2022 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 cc
+
+import (
+ "testing"
+
+ "android/soong/android"
+ "github.com/google/blueprint"
+)
+
+func TestAfdoDeps(t *testing.T) {
+ bp := `
+ cc_library {
+ name: "libTest",
+ srcs: ["foo.c"],
+ static_libs: ["libFoo"],
+ afdo: true,
+ }
+
+ cc_library {
+ name: "libFoo",
+ static_libs: ["libBar"],
+ }
+
+ cc_library {
+ name: "libBar",
+ }
+ `
+ prepareForAfdoTest := android.FixtureAddTextFile("toolchain/pgo-profiles/sampling/libTest.afdo", "TEST")
+
+ result := android.GroupFixturePreparers(
+ prepareForCcTest,
+ prepareForAfdoTest,
+ ).RunTestWithBp(t, bp)
+
+ libTest := result.ModuleForTests("libTest", "android_arm64_armv8-a_shared").Module()
+ libFoo := result.ModuleForTests("libFoo", "android_arm64_armv8-a_static_afdo-libTest").Module()
+ libBar := result.ModuleForTests("libBar", "android_arm64_armv8-a_static_afdo-libTest").Module()
+
+ hasDep := func(m android.Module, wantDep android.Module) bool {
+ var found bool
+ result.VisitDirectDeps(m, func(dep blueprint.Module) {
+ if dep == wantDep {
+ found = true
+ }
+ })
+ return found
+ }
+
+ if !hasDep(libTest, libFoo) {
+ t.Errorf("libTest missing dependency on afdo variant of libFoo")
+ }
+
+ if !hasDep(libFoo, libBar) {
+ t.Errorf("libTest missing dependency on afdo variant of libBar")
+ }
+}
diff --git a/cc/coverage.go b/cc/coverage.go
index 8dd2db1..f2b5425 100644
--- a/cc/coverage.go
+++ b/cc/coverage.go
@@ -98,6 +98,9 @@
} else if clangCoverage {
flags.Local.CommonFlags = append(flags.Local.CommonFlags, profileInstrFlag,
"-fcoverage-mapping", "-Wno-pass-failed", "-D__ANDROID_CLANG_COVERAGE__")
+ // Override -Wframe-larger-than. We can expect frame size increase after
+ // coverage instrumentation.
+ flags.Local.CFlags = append(flags.Local.CFlags, "-Wno-frame-larger-than=")
}
}
diff --git a/cc/pgo.go b/cc/pgo.go
index cd017c4..aa0feae 100644
--- a/cc/pgo.go
+++ b/cc/pgo.go
@@ -208,6 +208,10 @@
ctx.ModuleErrorf("Instrumentation PGO specification is missing benchmark property")
}
+ if isSampling {
+ ctx.ModuleErrorf("Sampling PGO is deprecated, use AFDO instead")
+ }
+
if isSampling && isInstrumentation {
ctx.PropertyErrorf("pgo", "Exactly one of \"instrumentation\" and \"sampling\" properties must be set")
}
diff --git a/cc/sanitize.go b/cc/sanitize.go
index a054c91..6c68822 100644
--- a/cc/sanitize.go
+++ b/cc/sanitize.go
@@ -42,7 +42,6 @@
"-fno-omit-frame-pointer",
"-Wno-frame-larger-than=",
"-fsanitize-hwaddress-abi=platform",
- "-mllvm", "-hwasan-use-after-scope=1",
}
// ThinLTO performs codegen during link time, thus these flags need to
diff --git a/cc/tidy.go b/cc/tidy.go
index 97418fe..1f5f56d 100644
--- a/cc/tidy.go
+++ b/cc/tidy.go
@@ -156,6 +156,9 @@
// Too many existing functions trigger this rule, and fixing it requires large code
// refactoring. The cost of maintaining this tidy rule outweighs the benefit it brings.
tidyChecks = tidyChecks + ",-bugprone-easily-swappable-parameters"
+ // http://b/216364337 - TODO: Follow-up after compiler update to
+ // disable or fix individual instances.
+ tidyChecks = tidyChecks + ",-cert-err33-c"
flags.TidyFlags = append(flags.TidyFlags, tidyChecks)
if ctx.Config().IsEnvTrue("WITH_TIDY") {
diff --git a/cmd/soong_build/main.go b/cmd/soong_build/main.go
index f07eafa..b3a6ee0 100644
--- a/cmd/soong_build/main.go
+++ b/cmd/soong_build/main.go
@@ -48,6 +48,7 @@
delvePath string
moduleGraphFile string
+ moduleActionsFile string
docFile string
bazelQueryViewDir string
bp2buildMarker string
@@ -76,6 +77,7 @@
// Flags representing various modes soong_build can run in
flag.StringVar(&moduleGraphFile, "module_graph_file", "", "JSON module graph file to output")
+ flag.StringVar(&moduleActionsFile, "module_actions_file", "", "JSON file to output inputs/outputs of actions of modules")
flag.StringVar(&docFile, "soong_docs", "", "build documentation file to output")
flag.StringVar(&bazelQueryViewDir, "bazel_queryview_dir", "", "path to the bazel queryview directory relative to --top")
flag.StringVar(&bp2buildMarker, "bp2build_marker", "", "If set, run bp2build, touch the specified marker file then exit")
@@ -176,15 +178,17 @@
}
}
-func writeJsonModuleGraph(ctx *android.Context, path string) {
- f, err := os.Create(shared.JoinPath(topDir, path))
- if err != nil {
- fmt.Fprintf(os.Stderr, "%s", err)
+func writeJsonModuleGraphAndActions(ctx *android.Context, graphPath string, actionsPath string) {
+ graphFile, graphErr := os.Create(shared.JoinPath(topDir, graphPath))
+ actionsFile, actionsErr := os.Create(shared.JoinPath(topDir, actionsPath))
+ if graphErr != nil || actionsErr != nil {
+ fmt.Fprintf(os.Stderr, "Graph err: %s, actions err: %s", graphErr, actionsErr)
os.Exit(1)
}
- defer f.Close()
- ctx.Context.PrintJSONGraph(f)
+ defer graphFile.Close()
+ defer actionsFile.Close()
+ ctx.Context.PrintJSONGraphAndActions(graphFile, actionsFile)
}
func writeBuildGlobsNinjaFile(srcDir, buildDir string, globs func() pathtools.MultipleGlobResults, config interface{}) []string {
@@ -254,7 +258,7 @@
writeDepFile(queryviewMarkerFile, ninjaDeps)
return queryviewMarkerFile
} else if generateModuleGraphFile {
- writeJsonModuleGraph(ctx, moduleGraphFile)
+ writeJsonModuleGraphAndActions(ctx, moduleGraphFile, moduleActionsFile)
writeDepFile(moduleGraphFile, ninjaDeps)
return moduleGraphFile
} else if generateDocFile {
diff --git a/cmd/soong_ui/main.go b/cmd/soong_ui/main.go
index e3ccb6c..13b20f4 100644
--- a/cmd/soong_ui/main.go
+++ b/cmd/soong_ui/main.go
@@ -61,7 +61,7 @@
}
// list of supported commands (flags) supported by soong ui
-var commands []command = []command{
+var commands = []command{
{
flag: "--make-mode",
description: "build the modules by the target name (i.e. soong_docs)",
@@ -523,7 +523,11 @@
}
// command not found
- return nil, nil, fmt.Errorf("Command not found: %q", args)
+ flags := make([]string, len(commands))
+ for i, c := range commands {
+ flags[i] = c.flag
+ }
+ return nil, nil, fmt.Errorf("Command not found: %q\nDid you mean one of these: %q", args, flags)
}
// For Bazel support, this moves files and directories from e.g. out/dist/$f to DIST_DIR/$f if necessary.
diff --git a/docs/OWNERS b/docs/OWNERS
index d143317..2d71271 100644
--- a/docs/OWNERS
+++ b/docs/OWNERS
@@ -1 +1,3 @@
per-file map_files.md = danalbert@google.com, enh@google.com, jiyong@google.com
+per-file native_code_coverage.md = pirama@google.com, srhines@google.com, allenhair@google.com
+per-file tidy.md = chh@google.com, srhines@google.com
diff --git a/docs/native_code_coverage.md b/docs/native_code_coverage.md
new file mode 100644
index 0000000..fabbfa0
--- /dev/null
+++ b/docs/native_code_coverage.md
@@ -0,0 +1,241 @@
+## Native Code Coverage for Android
+
+## Scope
+
+These instructions are for Android developers to collect and inspect code
+coverage for C++ and Rust code on the Android platform.
+
+## Building with Native Code Coverage Instrumentation
+
+Identify the paths where native code-coverage instrumentation should be enabled
+and set up the following environment variables.
+
+```
+ export CLANG_COVERAGE=true
+ export NATIVE_COVERAGE_PATHS="<paths-to-instrument-for-coverage>"
+```
+
+`NATIVE_COVERAGE_PATHS` should be a list of paths. Any Android.bp module defined
+under these paths is instrumented for code-coverage. E.g:
+
+```
+export NATIVE_COVERAGE_PATHS="external/libcxx system/core/adb"
+```
+
+### Additional Notes
+
+- Native Code coverage is not supported for host modules or `Android.mk`
+ modules.
+- `NATIVE_COVERAGE_PATHS="*"` enables coverage instrumentation for all paths.
+- Set `native_coverage: false` blueprint property to always disable code
+ coverage instrumentation for a module. This is useful if this module has
+ issues when building or running with coverage.
+- `NATIVE_COVERAGE_EXCLUDE_PATHS` can be set to exclude subdirs under
+ `NATIVE_COVERAGE_PATHS` from coverage instrumentation. E.g.
+ `NATIVE_COVERAGE_PATHS=frameworks/native
+ NATIVE_COVERAGE_PATHS=frameworks/native/vulkan` will instrument all native
+ code under `frameworks/native` except`frameworks/native/vulkan`.
+
+## Running Tests
+
+### Collecting Profiles
+
+When an instrumented program is run, the profiles are stored to the path and
+name specified in the `LLVM_PROFILE_FILE` environment variable. On Android
+coverage builds it is set to `/data/misc/trace/clang-%p-%20m.profraw`.
+
+* `%`p is replaced by the pid of the process
+* `%m` by the hash of the library/binary
+* The `20` in`%20m` creates a pool of 20 profraw files and "online" profile
+ merging is used to merge coverage to profiles onto this pool.
+
+Reference:`LLVM_PROFILE_FILE` can include additional specifiers as described
+[here](https://clang.llvm.org/docs/SourceBasedCodeCoverage.html#running-the-instrumented-program).
+
+For this and following steps, use the `acov-llvm.py` script:
+`$ANDROID_BUILD_TOP/development/scripts/acov-llvm.py`.
+
+There may be profiles in `/data/misc/trace` collected before the test is run.
+Clear this data before running the test.
+
+```
+ # Clear any coverage that's already written to /data/misc/trace
+ # and reset coverage for all daemons.
+ <host>$ acov-llvm.py clean-device
+
+ # Run the test. The exact command depends on the nature of the test.
+ <device>$ /data/local/tmp/$MY_TEST
+```
+
+For tests that exercise a daemon/service running in another process, write out
+the coverage for those processes as well.
+
+```
+ # Flush coverage of all daemons/processes running on the device.
+ <host>$ acov-llvm.py flush
+
+ # Flush coverage for a particular daemon, say adbd.
+ <host>$ acov-llvm.py flush adbd
+```
+
+## Viewing Coverage Data (acov-llvm.py)
+
+To post-process and view coverage information we use the `acov-llvm.py report`
+command. It invokes two LLVM utilities `llvm-profdata` and `llvm-cov`. An
+advanced user can manually invoke these utilities for fine-grained control. This
+is discussed [below](#viewing-coverage-data-manual).
+
+To generate coverage report need the following parameters. These are dependent
+on the test/module:
+
+1. One or more binaries and shared libraries from which coverage was collected.
+ E.g.:
+
+ 1. ART mainline module contains a few libraries such as `libart.so`,
+ `libart-compiler.so`.
+ 2. Bionic tests exercise code in `libc.so` and `libm.so`.
+
+ We need the *unstripped* copies of these binaries. Source information
+ included in the debuginfo is used to process the coverage data.
+
+2. One or more source directories under `$ANDROID_BUILD_TOP` for which coverage
+ needs to be reported.
+
+Invoke the report subcommand of acov-llvm.py to produce a html coverage summary:
+
+```
+ $ acov-llvm.py report \
+ -s <one-or-more-source-paths-in-$ANDROID_BUILD_TOP \
+ -b <one-or-more-(unstripped)-binaries-in-$OUT>
+```
+
+E.g.:
+
+```
+ $ acov-llvm.py report \
+ -s bionic \
+ -b \
+ $OUT/symbols/apex/com.android.runtime/lib/bionic/libc.so \
+ $OUT/symbols/apex/com.android.runtime/lib/bionic/libm.so
+```
+
+The script will produce a report in a temporary directory under
+`$ANDROID_BUILD_TOP`. It'll produce a log as below:
+
+```
+ generating coverage report in covreport-xxxxxx
+```
+
+A html report would be generated under `covreport-xxxxxx/html`.
+
+## Viewing Coverage Data (manual)
+
+`acov-llvm.py report` does a few operations under the hood which we can also
+manually invoke for flexibility.
+
+### Post-processing Coverage Files
+
+Fetch coverage files from the device and post-process them to a `.profdata` file
+as follows:
+
+```
+ # Fetch the coverage data from the device.
+ <host>$ cd coverage_data
+ <host>$ adb pull /data/misc/trace/ $TRACE_DIR_HOST
+
+ # Convert from .profraw format to the .profdata format.
+ <host>$ llvm-profdata merge --output=$MY_TEST.profdata \
+ $TRACE_DIR_HOST/clang-*.profraw
+```
+
+For added specificity, restrict the above command to just the <PID>s of the
+daemon or test processes of interest.
+
+```
+ <host>$ llvm-profdata merge --output=$MY_TEST.profdata \
+ $MY_TEST.profraw \
+ trace/clang-<pid1>.profraw trace/clang-<pid2>.profraw ...
+```
+
+### Generating Coverage report
+
+Documentation on Clang source-instrumentation-based coverage is available
+[here](https://clang.llvm.org/docs/SourceBasedCodeCoverage.html#creating-coverage-reports).
+The `llvm-cov` utility is used to show coverage from a `.profdata` file. The
+documentation for commonly used `llvm-cov` command-line arguments is available
+[here](https://llvm.org/docs/CommandGuide/llvm-cov.html#llvm-cov-report). (Try
+`llvm-cov show --help` for a complete list).
+
+#### `show` subcommand
+
+The `show` command displays the function and line coverage for each source file
+in the binary.
+
+```
+ <host>$ llvm-cov show \
+ --show-region-summary=false
+ --format=html --output-dir=coverage-html \
+ --instr-profile=$MY_TEST.profdata \
+ $MY_BIN \
+```
+
+* In the above command, `$MY_BIN` should be the unstripped binary (i.e. with
+ debuginfo) since `llvm-cov` reads some debuginfo to process the coverage
+ data.
+
+ E.g.:
+
+ ~~~
+ ```
+ <host>$ llvm-cov report \
+ --instr-profile=adbd.profdata \
+ $LOCATION_OF_UNSTRIPPED_ADBD/adbd \
+ --show-region-summary=false
+ ```
+ ~~~
+
+* The `-ignore-filename-regex=<regex>` option can be used to ignore files that
+ are not of interest. E.g: `-ignore-filename-regex="external/*"`
+
+* Use the `--object=<BIN>` argument to specify additional binaries and shared
+ libraries whose coverage is included in this profdata. See the earlier
+ [section](#viewing-coverage-data-acov-llvm-py) for examples where more than
+ one binary may need to be used.
+
+ E.g., the following command is used for `bionic-unit-tests`, which tests
+ both `libc.so` and `libm.so`:
+
+ ~~~
+ ```
+ <host>$ llvm-cov report \
+ --instr-profile=bionic.profdata \
+ $OUT/.../libc.so \
+ --object=$OUT/.../libm.so
+ ```
+ ~~~
+
+* `llvm-cov` also takes positional SOURCES argument to consider/display only
+ particular paths of interest. E.g:
+
+ ~~~
+ ```
+ <host>$ llvm-cov report \
+ --instr-profile=adbd.profdata \
+ $LOCATION_OF_ADBD/adbd \
+ --show-region-summary=false \
+ /proc/self/cwd/system/core/adb
+ ```
+ ~~~
+
+Note that the paths for the sources need to be prepended with
+'`/proc/self/cwd/`'. This is because Android C/C++ compilations run with
+`PWD=/proc/self/cwd` and consequently the source names are recorded with that
+prefix. Alternatively, the
+[`--path-equivalence`](https://llvm.org/docs/CommandGuide/llvm-cov.html#cmdoption-llvm-cov-show-path-equivalence)
+option to `llvm-cov` can be used.
+
+#### `report` subcommand
+
+The [`report`](https://llvm.org/docs/CommandGuide/llvm-cov.html#llvm-cov-report)
+subcommand summarizes the percentage of covered lines to the console. It takes
+options similar to the `show` subcommand.
diff --git a/docs/tidy.md b/docs/tidy.md
new file mode 100644
index 0000000..3140198
--- /dev/null
+++ b/docs/tidy.md
@@ -0,0 +1,244 @@
+# Clang-Tidy Rules and Checks
+
+Android C/C++ source files can be checked by clang-tidy for issues like
+coding style, error-prone/performance patterns, and static flow analysis.
+See the official
+[clang-tidy document](https://clang.llvm.org/extra/clang-tidy)
+and list of
+[clang-tidy checks](https://clang.llvm.org/extra/clang-tidy/checks/list.html).
+
+## Global defaults for Android builds
+
+The simplest way to enable clang-tidy checks is
+to set environment variable `WITH_TIDY`.
+```
+$ WITH_TIDY=1 make
+```
+
+This will turn on the global default to run clang-tidy for every required
+C/C++ source file compilation. The global default clang-tidy checks
+do not include time-consuming static analyzer checks. To enable those
+checks, set the `CLANG_ANALYZER_CHECKS` variable.
+```
+$ WITH_TIDY=1 CLANG_ANALYZER_CHECKS=1 make
+```
+
+The default global clang-tidy checks and flags are defined in
+[build/soong/cc/config/tidy.go](https://android.googlesource.com/platform/build/soong/+/refs/heads/master/cc/config/tidy.go).
+
+
+## Module clang-tidy properties
+
+The global default can be overwritten by module properties in Android.bp.
+
+### `tidy` and `tidy_checks`
+
+For example, in
+[system/bpf/Android.bp](https://android.googlesource.com/platform/system/bpf/+/refs/heads/master/Android.bp),
+clang-tidy is enabled explicitly and with a different check list:
+```
+cc_defaults {
+ name: "bpf_defaults",
+ // snipped
+ tidy: true,
+ tidy_checks: [
+ "android-*",
+ "cert-*",
+ "-cert-err34-c",
+ "clang-analyzer-security*",
+ // Disabling due to many unavoidable warnings from POSIX API usage.
+ "-google-runtime-int",
+ ],
+}
+```
+That means in normal builds, even without `WITH_TIDY=1`,
+the modules that use `bpf_defaults` will run clang-tidy
+over C/C++ source files with the given `tidy_checks`.
+Note that `clang-analyzer-security*` is included in `tidy_checks`
+but not all `clang-analyzer-*` checks. Check `cert-err34-c` is
+disabled, although `cert-*` is selected.
+
+Some modules might want to disable clang-tidy even when
+environment variable `WITH_TIDY=1` is set.
+Examples can be found in
+[system/netd/tests/Android.bp](https://android.googlesource.com/platform/system/netd/+/refs/heads/master/tests/Android.bp)
+```
+cc_test {
+ name: "netd_integration_test",
+ // snipped
+ defaults: ["netd_defaults"],
+ tidy: false, // cuts test build time by almost 1 minute
+```
+and in
+[bionic/tests/Android.bp](https://android.googlesource.com/platform/bionic/+/refs/heads/master/tests/Android.bp).
+```
+cc_test_library {
+ name: "fortify_disabled_for_tidy",
+ // snipped
+ srcs: ["clang_fortify_tests.cpp"],
+ tidy: false,
+}
+```
+
+### `tidy_checks_as_errors`
+
+The global tidy checks are enabled as warnings.
+If a C/C++ module wants to be free of certain clang-tidy warnings,
+it can chose those checks to be treated as errors.
+For example
+[system/core/libsysutils/Android.bp](https://android.googlesource.com/platform/system/core/+/refs/heads/master/libsysutils/Android.bp)
+has enabled clang-tidy explicitly, selected its own tidy checks,
+and set three groups of tidy checks as errors:
+```
+cc_library {
+ name: "libsysutils",
+ // snipped
+ tidy: true,
+ tidy_checks: [
+ "-*",
+ "cert-*",
+ "clang-analyzer-security*",
+ "android-*",
+ ],
+ tidy_checks_as_errors: [
+ "cert-*",
+ "clang-analyzer-security*",
+ "android-*",
+ ],
+ // snipped
+}
+```
+
+### `tidy_flags` and `tidy_disabled_srcs`
+
+Extra clang-tidy flags can be passed with the `tidy_flags` property.
+
+Some Android modules use the `tidy_flags` to pass "-warnings-as-errors="
+to clang-tidy. This usage should now be replaced with the
+`tidy_checks_as_errors` property.
+
+Some other tidy flags examples are `-format-style=` and `-header-filter=`
+For example, in
+[art/odrefresh/Android.bp](https://android.googlesource.com/platform/art/+/refs/heads/master/odrefresh/Android.bp),
+we found
+```
+cc_defaults {
+ name: "odrefresh-defaults",
+ srcs: [
+ "odrefresh.cc",
+ "odr_common.cc",
+ "odr_compilation_log.cc",
+ "odr_fs_utils.cc",
+ "odr_metrics.cc",
+ "odr_metrics_record.cc",
+ ],
+ // snipped
+ generated_sources: [
+ "apex-info-list-tinyxml",
+ "art-apex-cache-info",
+ "art-odrefresh-operator-srcs",
+ ],
+ // snipped
+ tidy: true,
+ tidy_disabled_srcs: [":art-apex-cache-info"],
+ tidy_flags: [
+ "-format-style=file",
+ "-header-filter=(art/odrefresh/|system/apex/)",
+ ],
+}
+```
+That means all modules with the `odrefresh-defaults` will
+have clang-tidy enabled, but not for generated source
+files in `art-apex-cache-info`.
+The clang-tidy is called with extra flags to specify the
+format-style and header-filter.
+
+Note that the globally set default for header-filter is to
+include only the module directory. So, the default clang-tidy
+warnings for `art/odrefresh` modules will include source files
+under that directory. Now `odrefresh-defaults` is interested
+in seeing warnings from both `art/odrefresh/` and `system/apex/`
+and it redefines `-header-filter` in its `tidy_flags`.
+
+
+## Phony tidy-* targets
+
+### The tidy-*directory* targets
+
+Setting `WITH_TIDY=1` is easy to enable clang-tidy globally for any build.
+However, it adds extra compilation time.
+
+For developers focusing on just one directory, they only want to compile
+their files with clang-tidy and wish to build other Android components as
+fast as possible. Changing the `WITH_TIDY=1` variable setting is also expensive
+since the build.ninja file will be regenerated due to any such variable change.
+
+To manually select only some directories or modules to compile with clang-tidy,
+do not set the `WITH_TIDY=1` variable, but use the special `tidy-<directory>`
+phony target. For example, a person working on `system/libbase` can build
+Android quickly with
+```
+unset WITH_TIDY # Optional, not if you haven't set WITH_TIDY
+make droid tidy-system-libbase
+```
+
+For any directory `d1/d2/d3`, a phony target tidy-d1-d2-d3 is generated
+if there is any C/C++ source file under `d1/d2/d3`.
+
+Note that with `make droid tidy-system-libbase`, some C/C++ files
+that are not needed by the `droid` target will be passed to clang-tidy
+if they are under `system/libbase`. This is like a `checkbuild`
+under `system/libbase` to include all modules, but only C/C++
+files of those modules are compiled with clang-tidy.
+
+### The tidy-soong target
+
+A special `tidy-soong` target is defined to include all C/C++
+source files in *all* directories. This phony target is sometimes
+used to test if all source files compile with a new clang-tidy release.
+
+### The tidy-*_subset targets
+
+A *subset* of each tidy-* phony target is defined to reduce test time.
+Since any Android module, a C/C++ library or binary, can be built
+for many different *variants*, one C/C++ source file is usually
+compiled multiple times with different compilation flags.
+Many of such *variant* flags have little or no effect on clang-tidy
+checks. To reduce clang-tidy check time, a *subset* target like
+`tidy-soong_subset` or `tidy-system-libbase_subset` is generated
+to include only a subset, the first variant, of each module in
+the directory.
+
+Hence, for C/C++ source code quality, instead of a long
+"make checkbuild", we can use "make tidy-soong_subset".
+
+
+## Limit clang-tidy runtime
+
+Some Android modules have large files that take a long time to compile
+with clang-tidy, with or without the clang-analyzer checks.
+To limit clang-tidy time, an environment variable can be set as
+```base
+WITH_TIDY=1 TIDY_TIMEOUT=90 make
+```
+This 90-second limit is actually the default time limit
+in several Android continuous builds where `WITH_TIDY=1` and
+`CLANG_ANALYZER_CHECKS=1` are set.
+
+## Capabilities for Android.bp and Android.mk
+
+Some of the previously mentioned features are defined only
+for modules in Android.bp files, not for Android.mk modules yet.
+
+* The global `WITH_TIDY=1` variable will enable clang-tidy for all C/C++
+ modules in Android.bp or Android.mk files.
+
+* The global `TIDY_TIMEOUT` variable is recognized by Android prebuilt
+ clang-tidy, so it should work for any clang-tidy invocation.
+
+* The clang-tidy module level properties are defined for Android.bp modules.
+ For Android.mk modules, old `LOCAL_TIDY`, `LOCAL_TIDY_CHECKS`,
+ `LOCAL_TIDY_FLAGS` work similarly, but it would be better to convert
+ those modules to use Android.bp files.
+
+* The `tidy-*` phony targets are only generated for Android.bp modules.
diff --git a/java/bootclasspath_fragment.go b/java/bootclasspath_fragment.go
index fee51d7..4794180 100644
--- a/java/bootclasspath_fragment.go
+++ b/java/bootclasspath_fragment.go
@@ -669,6 +669,8 @@
// This is an exception to support end-to-end test for SdkExtensions, until such support exists.
if android.InList("test_framework-sdkextensions", possibleUpdatableModules) {
jars = jars.Append("com.android.sdkext", "test_framework-sdkextensions")
+ } else if android.InList("AddNewActivity", possibleUpdatableModules) {
+ jars = jars.Append("test_com.android.cts.frameworkresapkplits", "AddNewActivity")
} else if android.InList("test_framework-apexd", possibleUpdatableModules) {
jars = jars.Append("com.android.apex.test_package", "test_framework-apexd")
} else if global.ApexBootJars.Len() != 0 && !android.IsModuleInVersionedSdk(ctx.Module()) {
diff --git a/java/config/config.go b/java/config/config.go
index 30c6f91..ea2f934 100644
--- a/java/config/config.go
+++ b/java/config/config.go
@@ -60,7 +60,7 @@
const (
JavaVmFlags = `-XX:OnError="cat hs_err_pid%p.log" -XX:CICompilerCount=6 -XX:+UseDynamicNumberOfGCThreads`
- JavacVmFlags = `-J-XX:OnError="cat hs_err_pid%p.log" -J-XX:CICompilerCount=6 -J-XX:+UseDynamicNumberOfGCThreads`
+ JavacVmFlags = `-J-XX:OnError="cat hs_err_pid%p.log" -J-XX:CICompilerCount=6 -J-XX:+UseDynamicNumberOfGCThreads -J-XX:+TieredCompilation -J-XX:TieredStopAtLevel=1`
)
func init() {
diff --git a/java/droidstubs.go b/java/droidstubs.go
index 5a84e05..7ad316f 100644
--- a/java/droidstubs.go
+++ b/java/droidstubs.go
@@ -19,7 +19,6 @@
"path/filepath"
"strings"
- "github.com/google/blueprint"
"github.com/google/blueprint/proptools"
"android/soong/android"
@@ -807,8 +806,7 @@
properties PrebuiltStubsSourcesProperties
- stubsSrcJar android.Path
- jsonDataActions []blueprint.JSONDataAction
+ stubsSrcJar android.Path
}
func (p *PrebuiltStubsSources) OutputFiles(tag string) (android.Paths, error) {
@@ -824,13 +822,6 @@
return d.stubsSrcJar
}
-// AddJSONData is a temporary solution for droidstubs module to put action
-// related data into the module json graph.
-func (p *PrebuiltStubsSources) AddJSONData(d *map[string]interface{}) {
- p.ModuleBase.AddJSONData(d)
- (*d)["Actions"] = blueprint.FormatJSONDataActions(p.jsonDataActions)
-}
-
func (p *PrebuiltStubsSources) GenerateAndroidBuildActions(ctx android.ModuleContext) {
if len(p.properties.Srcs) != 1 {
ctx.PropertyErrorf("srcs", "must only specify one directory path or srcjar, contains %d paths", len(p.properties.Srcs))
@@ -838,12 +829,9 @@
}
src := p.properties.Srcs[0]
- var jsonDataAction blueprint.JSONDataAction
if filepath.Ext(src) == ".srcjar" {
// This is a srcjar. We can use it directly.
p.stubsSrcJar = android.PathForModuleSrc(ctx, src)
- jsonDataAction.Inputs = []string{src}
- jsonDataAction.Outputs = []string{src}
} else {
outPath := android.PathForModuleOut(ctx, ctx.ModuleName()+"-"+"stubs.srcjar")
@@ -867,10 +855,7 @@
rule.Restat()
rule.Build("zip src", "Create srcjar from prebuilt source")
p.stubsSrcJar = outPath
- jsonDataAction.Inputs = srcPaths.Strings()
- jsonDataAction.Outputs = []string{outPath.String()}
}
- p.jsonDataActions = []blueprint.JSONDataAction{jsonDataAction}
}
func (p *PrebuiltStubsSources) Prebuilt() *android.Prebuilt {
diff --git a/java/droidstubs_test.go b/java/droidstubs_test.go
index 82ebba7..10d99f3 100644
--- a/java/droidstubs_test.go
+++ b/java/droidstubs_test.go
@@ -21,8 +21,6 @@
"strings"
"testing"
- "github.com/google/blueprint"
-
"android/soong/android"
)
@@ -234,27 +232,6 @@
checkSystemModulesUseByDroidstubs(t, ctx, "stubs-prebuilt-system-modules", "prebuilt-jar.jar")
}
-func TestAddJSONData(t *testing.T) {
- prebuiltStubsSources := PrebuiltStubsSources{}
- prebuiltStubsSources.jsonDataActions = []blueprint.JSONDataAction{
- blueprint.JSONDataAction{
- Inputs: []string{},
- Outputs: []string{},
- },
- }
- jsonData := map[string]interface{}{}
- prebuiltStubsSources.AddJSONData(&jsonData)
- expectedOut := []map[string]interface{}{
- map[string]interface{}{
- "Inputs": []string{},
- "Outputs": []string{},
- },
- }
- if !reflect.DeepEqual(jsonData["Actions"], expectedOut) {
- t.Errorf("The JSON action data %#v isn't as expected %#v.", jsonData["Actions"], expectedOut)
- }
-}
-
func checkSystemModulesUseByDroidstubs(t *testing.T, ctx *android.TestContext, moduleName string, systemJar string) {
metalavaRule := ctx.ModuleForTests(moduleName, "android_common").Rule("metalava")
var systemJars []string
diff --git a/java/java.go b/java/java.go
index e3e9721..ca4b3cf 100644
--- a/java/java.go
+++ b/java/java.go
@@ -325,6 +325,7 @@
var (
dataNativeBinsTag = dependencyTag{name: "dataNativeBins"}
+ dataDeviceBinsTag = dependencyTag{name: "dataDeviceBins"}
staticLibTag = dependencyTag{name: "staticlib"}
libTag = dependencyTag{name: "javalib", runtimeLinked: true}
java9LibTag = dependencyTag{name: "java9lib", runtimeLinked: true}
@@ -831,6 +832,9 @@
type hostTestProperties struct {
// list of native binary modules that should be installed alongside the test
Data_native_bins []string `android:"arch_variant"`
+
+ // list of device binary modules that should be installed alongside the test
+ Data_device_bins []string `android:"arch_variant"`
}
type testHelperLibraryProperties struct {
@@ -904,6 +908,11 @@
}
}
+ if len(j.testHostProperties.Data_device_bins) > 0 {
+ deviceVariations := ctx.Config().AndroidFirstDeviceTarget.Variations()
+ ctx.AddFarVariationDependencies(deviceVariations, dataDeviceBinsTag, j.testHostProperties.Data_device_bins...)
+ }
+
if len(j.testProperties.Jni_libs) > 0 {
for _, target := range ctx.MultiTargets() {
sharedLibVariations := append(target.Variations(), blueprint.Variation{Mutator: "link", Variation: "shared"})
@@ -918,14 +927,35 @@
j.extraResources = append(j.extraResources, p)
}
+func (j *TestHost) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ var configs []tradefed.Config
+ if len(j.testHostProperties.Data_device_bins) > 0 {
+ // add Tradefed configuration to push device bins to device for testing
+ remoteDir := filepath.Join("/data/local/tests/unrestricted/", j.Name())
+ options := []tradefed.Option{{Name: "cleanup", Value: "true"}}
+ for _, bin := range j.testHostProperties.Data_device_bins {
+ fullPath := filepath.Join(remoteDir, bin)
+ options = append(options, tradefed.Option{Name: "push-file", Key: bin, Value: fullPath})
+ }
+ configs = append(configs, tradefed.Object{"target_preparer", "com.android.tradefed.targetprep.PushFilePreparer", options})
+ }
+
+ j.Test.generateAndroidBuildActionsWithConfig(ctx, configs)
+}
+
func (j *Test) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ j.generateAndroidBuildActionsWithConfig(ctx, nil)
+}
+
+func (j *Test) generateAndroidBuildActionsWithConfig(ctx android.ModuleContext, configs []tradefed.Config) {
if j.testProperties.Test_options.Unit_test == nil && ctx.Host() {
// TODO(b/): Clean temporary heuristic to avoid unexpected onboarding.
defaultUnitTest := !inList("tradefed", j.properties.Libs) && !inList("cts", j.testProperties.Test_suites)
j.testProperties.Test_options.Unit_test = proptools.BoolPtr(defaultUnitTest)
}
+
j.testConfig = tradefed.AutoGenJavaTestConfig(ctx, j.testProperties.Test_config, j.testProperties.Test_config_template,
- j.testProperties.Test_suites, j.testProperties.Auto_gen_config, j.testProperties.Test_options.Unit_test)
+ j.testProperties.Test_suites, configs, j.testProperties.Auto_gen_config, j.testProperties.Test_options.Unit_test)
j.data = android.PathsForModuleSrc(ctx, j.testProperties.Data)
@@ -935,6 +965,10 @@
j.data = append(j.data, android.OutputFileForModule(ctx, dep, ""))
})
+ ctx.VisitDirectDepsWithTag(dataDeviceBinsTag, func(dep android.Module) {
+ j.data = append(j.data, android.OutputFileForModule(ctx, dep, ""))
+ })
+
ctx.VisitDirectDepsWithTag(jniLibTag, func(dep android.Module) {
sharedLibInfo := ctx.OtherModuleProvider(dep, cc.SharedLibraryInfoProvider).(cc.SharedLibraryInfo)
if sharedLibInfo.SharedLibrary != nil {
@@ -967,7 +1001,7 @@
func (j *JavaTestImport) GenerateAndroidBuildActions(ctx android.ModuleContext) {
j.testConfig = tradefed.AutoGenJavaTestConfig(ctx, j.prebuiltTestProperties.Test_config, nil,
- j.prebuiltTestProperties.Test_suites, nil, nil)
+ j.prebuiltTestProperties.Test_suites, nil, nil, nil)
j.Import.GenerateAndroidBuildActions(ctx)
}
@@ -1294,6 +1328,7 @@
android.ModuleBase
android.DefaultableModuleBase
android.ApexModuleBase
+ android.BazelModuleBase
prebuilt android.Prebuilt
android.SdkBase
@@ -1649,6 +1684,7 @@
android.InitPrebuiltModule(module, &module.properties.Jars)
android.InitApexModule(module)
android.InitSdkAwareModule(module)
+ android.InitBazelModule(module)
InitJavaModule(module, android.HostAndDeviceSupported)
return module
}
@@ -2067,3 +2103,21 @@
// Create the BazelTargetModule.
ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: m.Name()}, attrs)
}
+
+type bazelJavaImportAttributes struct {
+ Jars bazel.LabelListAttribute
+}
+
+// java_import bp2Build converter.
+func (i *Import) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
+ //TODO(b/209577426): Support multiple arch variants
+ jars := bazel.MakeLabelListAttribute(android.BazelLabelForModuleSrcExcludes(ctx, i.properties.Jars, []string(nil)))
+
+ attrs := &bazelJavaImportAttributes{
+ Jars: jars,
+ }
+ props := bazel.BazelTargetModuleProperties{Rule_class: "java_import"}
+
+ ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: android.RemoveOptionalPrebuiltPrefix(i.Name())}, attrs)
+
+}
diff --git a/java/java_test.go b/java/java_test.go
index 3a51981..21c76b6 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -1460,3 +1460,64 @@
t.Errorf("expected errorprone to contain %q, got %q", expectedSubstring, javac.Args["javacFlags"])
}
}
+
+func TestDataDeviceBinsBuildsDeviceBinary(t *testing.T) {
+ bp := `
+ java_test_host {
+ name: "foo",
+ srcs: ["test.java"],
+ data_device_bins: ["bar"],
+ }
+
+ cc_binary {
+ name: "bar",
+ }
+ `
+
+ ctx := android.GroupFixturePreparers(
+ PrepareForIntegrationTestWithJava,
+ ).RunTestWithBp(t, bp)
+
+ buildOS := ctx.Config.BuildOS.String()
+ fooVariant := ctx.ModuleForTests("foo", buildOS+"_common")
+ barVariant := ctx.ModuleForTests("bar", "android_arm64_armv8-a")
+ fooMod := fooVariant.Module().(*TestHost)
+
+ relocated := barVariant.Output("bar")
+ expectedInput := "out/soong/.intermediates/bar/android_arm64_armv8-a/unstripped/bar"
+ android.AssertPathRelativeToTopEquals(t, "relocation input", expectedInput, relocated.Input)
+
+ entries := android.AndroidMkEntriesForTest(t, ctx.TestContext, fooMod)[0]
+ expectedData := []string{
+ "out/soong/.intermediates/bar/android_arm64_armv8-a/bar:bar",
+ }
+ actualData := entries.EntryMap["LOCAL_COMPATIBILITY_SUPPORT_FILES"]
+ android.AssertStringPathsRelativeToTopEquals(t, "LOCAL_TEST_DATA", ctx.Config, expectedData, actualData)
+}
+
+func TestDataDeviceBinsAutogenTradefedConfig(t *testing.T) {
+ bp := `
+ java_test_host {
+ name: "foo",
+ srcs: ["test.java"],
+ data_device_bins: ["bar"],
+ }
+
+ cc_binary {
+ name: "bar",
+ }
+ `
+
+ ctx := android.GroupFixturePreparers(
+ PrepareForIntegrationTestWithJava,
+ ).RunTestWithBp(t, bp)
+
+ buildOS := ctx.Config.BuildOS.String()
+ fooModule := ctx.ModuleForTests("foo", buildOS+"_common")
+ expectedAutogenConfig := `<option name="push-file" key="bar" value="/data/local/tests/unrestricted/foo/bar" />`
+
+ autogen := fooModule.Rule("autogen")
+ if !strings.Contains(autogen.Args["extraConfigs"], expectedAutogenConfig) {
+ t.Errorf("foo extraConfigs %v does not contain %q", autogen.Args["extraConfigs"], expectedAutogenConfig)
+ }
+}
diff --git a/licenses/Android.bp b/licenses/Android.bp
index 5b764dc..8db001f 100644
--- a/licenses/Android.bp
+++ b/licenses/Android.bp
@@ -18,6 +18,11 @@
default_applicable_licenses: ["Android-Apache-2.0"],
}
+filegroup {
+ name: "Apache-2.0-License-Text",
+ srcs: ["LICENSE"],
+}
+
license {
name: "Android-Apache-2.0",
package_name: "Android",
diff --git a/mk2rbc/mk2rbc_test.go b/mk2rbc/mk2rbc_test.go
index d62882d..c4f7da3 100644
--- a/mk2rbc/mk2rbc_test.go
+++ b/mk2rbc/mk2rbc_test.go
@@ -1048,8 +1048,8 @@
cfg = rblf.cfg(handle)
g["MY_PATH"] = "foo"
_entry = {
- "vendor/foo1/cfg.mk": ("_cfg", _cfg_init),
- "vendor/bar/baz/cfg.mk": ("_cfg1", _cfg1_init),
+ "vendor/foo1/cfg.mk": ("vendor/foo1/cfg", _cfg_init),
+ "vendor/bar/baz/cfg.mk": ("vendor/bar/baz/cfg", _cfg1_init),
}.get("vendor/%s/cfg.mk" % g["MY_PATH"])
(_varmod, _varmod_init) = _entry if _entry else (None, None)
if not _varmod_init:
@@ -1073,7 +1073,7 @@
g["MY_PATH"] = "foo"
#RBC# include_top vendor/foo1
_entry = {
- "vendor/foo1/cfg.mk": ("_cfg", _cfg_init),
+ "vendor/foo1/cfg.mk": ("vendor/foo1/cfg", _cfg_init),
}.get("%s/cfg.mk" % g["MY_PATH"])
(_varmod, _varmod_init) = _entry if _entry else (None, None)
if not _varmod_init:
@@ -1099,7 +1099,7 @@
g["MY_PATH"] = "foo"
#RBC# include_top vendor/foo1
_entry = {
- "vendor/foo1/cfg.mk": ("_cfg", _cfg_init),
+ "vendor/foo1/cfg.mk": ("vendor/foo1/cfg", _cfg_init),
}.get("%s/cfg.mk" % g["MY_PATH"])
(_varmod, _varmod_init) = _entry if _entry else (None, None)
if not _varmod_init:
@@ -1107,7 +1107,7 @@
rblf.inherit(handle, _varmod, _varmod_init)
#RBC# include_top vendor/foo1
_entry = {
- "vendor/foo1/cfg.mk": ("_cfg", _cfg_init),
+ "vendor/foo1/cfg.mk": ("vendor/foo1/cfg", _cfg_init),
}.get("%s/cfg.mk" % g["MY_PATH"])
(_varmod, _varmod_init) = _entry if _entry else (None, None)
if not _varmod_init:
@@ -1137,7 +1137,7 @@
def init(g, handle):
cfg = rblf.cfg(handle)
_entry = {
- "foo/font.mk": ("_font", _font_init),
+ "foo/font.mk": ("foo/font", _font_init),
}.get("%s/font.mk" % g.get("MY_VAR", ""))
(_varmod, _varmod_init) = _entry if _entry else (None, None)
if not _varmod_init:
@@ -1146,7 +1146,7 @@
#RBC# include_top foo
# There's some space and even this comment between the include_top and the inherit-product
_entry = {
- "foo/font.mk": ("_font", _font_init),
+ "foo/font.mk": ("foo/font", _font_init),
}.get("%s/font.mk" % g.get("MY_VAR", ""))
(_varmod, _varmod_init) = _entry if _entry else (None, None)
if not _varmod_init:
diff --git a/mk2rbc/node.go b/mk2rbc/node.go
index 333a8da..4f7c4f0 100644
--- a/mk2rbc/node.go
+++ b/mk2rbc/node.go
@@ -54,6 +54,10 @@
return im.moduleLocalName + "_init"
}
+func (mi moduleInfo) name() string {
+ return fmt.Sprintf("%q", MakePath2ModuleName(mi.originalPath))
+}
+
type inheritedModule interface {
name() string
entryName() string
@@ -67,10 +71,6 @@
loadAlways bool
}
-func (im inheritedStaticModule) name() string {
- return fmt.Sprintf("%q", MakePath2ModuleName(im.originalPath))
-}
-
func (im inheritedStaticModule) emitSelect(_ *generationContext) {
}
@@ -102,7 +102,7 @@
gctx.indentLevel++
for _, mi := range i.candidateModules {
gctx.newLine()
- gctx.writef(`"%s": (%q, %s),`, mi.originalPath, mi.moduleLocalName, mi.entryName())
+ gctx.writef(`"%s": (%s, %s),`, mi.originalPath, mi.name(), mi.entryName())
}
gctx.indentLevel--
gctx.newLine()
diff --git a/rust/binary.go b/rust/binary.go
index db91ccb..0dc320e 100644
--- a/rust/binary.go
+++ b/rust/binary.go
@@ -92,14 +92,23 @@
func (binary *binaryDecorator) compilerDeps(ctx DepsContext, deps Deps) Deps {
deps = binary.baseCompiler.compilerDeps(ctx, deps)
+ static := Bool(binary.Properties.Static_executable)
if ctx.toolchain().Bionic() {
- deps = bionicDeps(ctx, deps, Bool(binary.Properties.Static_executable))
- if Bool(binary.Properties.Static_executable) {
- deps.CrtBegin = "crtbegin_static"
+ deps = bionicDeps(ctx, deps, static)
+ if static {
+ deps.CrtBegin = []string{"crtbegin_static"}
} else {
- deps.CrtBegin = "crtbegin_dynamic"
+ deps.CrtBegin = []string{"crtbegin_dynamic"}
}
- deps.CrtEnd = "crtend_android"
+ deps.CrtEnd = []string{"crtend_android"}
+ } else if ctx.Os() == android.LinuxMusl {
+ deps = muslDeps(ctx, deps, static)
+ if static {
+ deps.CrtBegin = []string{"libc_musl_crtbegin_static"}
+ } else {
+ deps.CrtBegin = []string{"libc_musl_crtbegin_dynamic", "musl_linker_script"}
+ }
+ deps.CrtEnd = []string{"libc_musl_crtend"}
}
return deps
diff --git a/rust/bindgen.go b/rust/bindgen.go
index ef5702b..f4c337d 100644
--- a/rust/bindgen.go
+++ b/rust/bindgen.go
@@ -288,6 +288,8 @@
deps = b.BaseSourceProvider.SourceProviderDeps(ctx, deps)
if ctx.toolchain().Bionic() {
deps = bionicDeps(ctx, deps, false)
+ } else if ctx.Os() == android.LinuxMusl {
+ deps = muslDeps(ctx, deps, false)
}
deps.SharedLibs = append(deps.SharedLibs, b.ClangProperties.Shared_libs...)
diff --git a/rust/builder.go b/rust/builder.go
index e66a6f0..00035b9 100644
--- a/rust/builder.go
+++ b/rust/builder.go
@@ -247,9 +247,8 @@
implicits = append(implicits, deps.srcProviderFiles...)
implicits = append(implicits, deps.AfdoProfiles...)
- if deps.CrtBegin.Valid() {
- implicits = append(implicits, deps.CrtBegin.Path(), deps.CrtEnd.Path())
- }
+ implicits = append(implicits, deps.CrtBegin...)
+ implicits = append(implicits, deps.CrtEnd...)
if len(deps.SrcDeps) > 0 {
moduleGenDir := ctx.RustModule().compiler.CargoOutDir()
@@ -319,8 +318,8 @@
"rustcFlags": strings.Join(rustcFlags, " "),
"linkFlags": strings.Join(linkFlags, " "),
"libFlags": strings.Join(libFlags, " "),
- "crtBegin": deps.CrtBegin.String(),
- "crtEnd": deps.CrtEnd.String(),
+ "crtBegin": strings.Join(deps.CrtBegin.Strings(), " "),
+ "crtEnd": strings.Join(deps.CrtEnd.Strings(), " "),
"envVars": strings.Join(envVars, " "),
},
})
diff --git a/rust/compiler.go b/rust/compiler.go
index 3040e5d..c5d40f4 100644
--- a/rust/compiler.go
+++ b/rust/compiler.go
@@ -364,7 +364,7 @@
if !Bool(compiler.Properties.No_stdlibs) {
for _, stdlib := range config.Stdlibs {
// If we're building for the build host, use the prebuilt stdlibs
- if ctx.Target().Os == ctx.Config().BuildOS {
+ if ctx.Target().Os == android.Linux || ctx.Target().Os == android.Darwin {
stdlib = "prebuilt_" + stdlib
}
deps.Stdlibs = append(deps.Stdlibs, stdlib)
@@ -394,6 +394,20 @@
return deps
}
+func muslDeps(ctx DepsContext, deps Deps, static bool) Deps {
+ muslLibs := []string{"libc_musl"}
+ if static {
+ deps.StaticLibs = append(deps.StaticLibs, muslLibs...)
+ } else {
+ deps.SharedLibs = append(deps.SharedLibs, muslLibs...)
+ }
+ if libRuntimeBuiltins := config.BuiltinsRuntimeLibrary(ctx.toolchain()); libRuntimeBuiltins != "" {
+ deps.StaticLibs = append(deps.StaticLibs, libRuntimeBuiltins)
+ }
+
+ return deps
+}
+
func (compiler *baseCompiler) crateName() string {
return compiler.Properties.Crate_name
}
diff --git a/rust/config/allowed_list.go b/rust/config/allowed_list.go
index f318507..0962168 100644
--- a/rust/config/allowed_list.go
+++ b/rust/config/allowed_list.go
@@ -19,6 +19,7 @@
"frameworks/native/libs/binder/rust",
"frameworks/proto_logging/stats",
"hardware/interfaces/security",
+ "hardware/interfaces/uwb",
"packages/modules/Bluetooth",
"packages/modules/DnsResolver",
"packages/modules/Uwb",
diff --git a/rust/config/x86_linux_host.go b/rust/config/x86_linux_host.go
index c10afd8..7608349 100644
--- a/rust/config/x86_linux_host.go
+++ b/rust/config/x86_linux_host.go
@@ -22,12 +22,29 @@
var (
LinuxRustFlags = []string{}
+ LinuxMuslRustFlags = []string{
+ // disable rustc's builtin fallbacks for crt objects
+ "-C link_self_contained=no",
+ // force rustc to use a dynamic musl libc
+ "-C target-feature=-crt-static",
+ "-Z link-native-libraries=no",
+ }
LinuxRustLinkFlags = []string{
"-B${cc_config.ClangBin}",
"-fuse-ld=lld",
"-Wl,--undefined-version",
+ }
+ LinuxRustGlibcLinkFlags = []string{
"--sysroot ${cc_config.LinuxGccRoot}/sysroot",
}
+ LinuxRustMuslLinkFlags = []string{
+ "--sysroot /dev/null",
+ "-nodefaultlibs",
+ "-nostdlib",
+ "-Wl,--no-dynamic-linker",
+ // for unwind
+ "-lgcc", "-lgcc_eh",
+ }
linuxX86Rustflags = []string{}
linuxX86Linkflags = []string{}
linuxX8664Rustflags = []string{}
@@ -35,15 +52,17 @@
)
func init() {
- registerToolchainFactory(android.Linux, android.X86_64, linuxX8664ToolchainFactory)
- registerToolchainFactory(android.Linux, android.X86, linuxX86ToolchainFactory)
+ registerToolchainFactory(android.Linux, android.X86_64, linuxGlibcX8664ToolchainFactory)
+ registerToolchainFactory(android.Linux, android.X86, linuxGlibcX86ToolchainFactory)
- // TODO: musl rust support
- registerToolchainFactory(android.LinuxMusl, android.X86_64, linuxX8664ToolchainFactory)
- registerToolchainFactory(android.LinuxMusl, android.X86, linuxX86ToolchainFactory)
+ registerToolchainFactory(android.LinuxMusl, android.X86_64, linuxMuslX8664ToolchainFactory)
+ registerToolchainFactory(android.LinuxMusl, android.X86, linuxMuslX86ToolchainFactory)
pctx.StaticVariable("LinuxToolchainRustFlags", strings.Join(LinuxRustFlags, " "))
+ pctx.StaticVariable("LinuxMuslToolchainRustFlags", strings.Join(LinuxMuslRustFlags, " "))
pctx.StaticVariable("LinuxToolchainLinkFlags", strings.Join(LinuxRustLinkFlags, " "))
+ pctx.StaticVariable("LinuxGlibcToolchainLinkFlags", strings.Join(LinuxRustGlibcLinkFlags, " "))
+ pctx.StaticVariable("LinuxMuslToolchainLinkFlags", strings.Join(LinuxRustMuslLinkFlags, " "))
pctx.StaticVariable("LinuxToolchainX86RustFlags", strings.Join(linuxX86Rustflags, " "))
pctx.StaticVariable("LinuxToolchainX86LinkFlags", strings.Join(linuxX86Linkflags, " "))
pctx.StaticVariable("LinuxToolchainX8664RustFlags", strings.Join(linuxX8664Rustflags, " "))
@@ -51,19 +70,9 @@
}
-type toolchainLinux struct {
- toolchainRustFlags string
- toolchainLinkFlags string
-}
-
-type toolchainLinuxX86 struct {
- toolchain32Bit
- toolchainLinux
-}
-
+// Base 64-bit linux rust toolchain
type toolchainLinuxX8664 struct {
toolchain64Bit
- toolchainLinux
}
func (toolchainLinuxX8664) Supported() bool {
@@ -78,10 +87,6 @@
return "x86_64"
}
-func (t *toolchainLinuxX8664) RustTriple() string {
- return "x86_64-unknown-linux-gnu"
-}
-
func (t *toolchainLinuxX8664) ToolchainLinkFlags() string {
// Prepend the lld flags from cc_config so we stay in sync with cc
return "${cc_config.LinuxLldflags} ${cc_config.LinuxX8664Lldflags} " +
@@ -92,8 +97,49 @@
return "${config.LinuxToolchainRustFlags} ${config.LinuxToolchainX8664RustFlags}"
}
-func linuxX8664ToolchainFactory(arch android.Arch) Toolchain {
- return toolchainLinuxX8664Singleton
+// Specialization of the 64-bit linux rust toolchain for glibc. Adds the gnu rust triple and
+// sysroot linker flags.
+type toolchainLinuxGlibcX8664 struct {
+ toolchainLinuxX8664
+}
+
+func (t *toolchainLinuxX8664) RustTriple() string {
+ return "x86_64-unknown-linux-gnu"
+}
+
+func (t *toolchainLinuxGlibcX8664) ToolchainLinkFlags() string {
+ return t.toolchainLinuxX8664.ToolchainLinkFlags() + " " + "${config.LinuxGlibcToolchainLinkFlags}"
+}
+
+func linuxGlibcX8664ToolchainFactory(arch android.Arch) Toolchain {
+ return toolchainLinuxGlibcX8664Singleton
+}
+
+// Specialization of the 64-bit linux rust toolchain for musl. Adds the musl rust triple and
+// linker flags to avoid using the host sysroot.
+type toolchainLinuxMuslX8664 struct {
+ toolchainLinuxX8664
+}
+
+func (t *toolchainLinuxMuslX8664) RustTriple() string {
+ return "x86_64-unknown-linux-musl"
+}
+
+func (t *toolchainLinuxMuslX8664) ToolchainLinkFlags() string {
+ return t.toolchainLinuxX8664.ToolchainLinkFlags() + " " + "${config.LinuxMuslToolchainLinkFlags}"
+}
+
+func (t *toolchainLinuxMuslX8664) ToolchainRustFlags() string {
+ return t.toolchainLinuxX8664.ToolchainRustFlags() + " " + "${config.LinuxMuslToolchainRustFlags}"
+}
+
+func linuxMuslX8664ToolchainFactory(arch android.Arch) Toolchain {
+ return toolchainLinuxMuslX8664Singleton
+}
+
+// Base 32-bit linux rust toolchain
+type toolchainLinuxX86 struct {
+ toolchain32Bit
}
func (toolchainLinuxX86) Supported() bool {
@@ -116,10 +162,6 @@
return "x86_64"
}
-func (t *toolchainLinuxX86) RustTriple() string {
- return "i686-unknown-linux-gnu"
-}
-
func (t *toolchainLinuxX86) ToolchainLinkFlags() string {
// Prepend the lld flags from cc_config so we stay in sync with cc
return "${cc_config.LinuxLldflags} ${cc_config.LinuxX86Lldflags} " +
@@ -130,9 +172,47 @@
return "${config.LinuxToolchainRustFlags} ${config.LinuxToolchainX86RustFlags}"
}
-func linuxX86ToolchainFactory(arch android.Arch) Toolchain {
- return toolchainLinuxX86Singleton
+// Specialization of the 32-bit linux rust toolchain for glibc. Adds the gnu rust triple and
+// sysroot linker flags.
+type toolchainLinuxGlibcX86 struct {
+ toolchainLinuxX86
}
-var toolchainLinuxX8664Singleton Toolchain = &toolchainLinuxX8664{}
-var toolchainLinuxX86Singleton Toolchain = &toolchainLinuxX86{}
+func (t *toolchainLinuxGlibcX86) RustTriple() string {
+ return "i686-unknown-linux-gnu"
+}
+
+func (t *toolchainLinuxGlibcX86) ToolchainLinkFlags() string {
+ return t.toolchainLinuxX86.ToolchainLinkFlags() + " " + "${config.LinuxGlibcToolchainLinkFlags}"
+}
+
+func linuxGlibcX86ToolchainFactory(arch android.Arch) Toolchain {
+ return toolchainLinuxGlibcX86Singleton
+}
+
+// Specialization of the 32-bit linux rust toolchain for musl. Adds the musl rust triple and
+// linker flags to avoid using the host sysroot.
+type toolchainLinuxMuslX86 struct {
+ toolchainLinuxX86
+}
+
+func (t *toolchainLinuxMuslX86) RustTriple() string {
+ return "i686-unknown-linux-musl"
+}
+
+func (t *toolchainLinuxMuslX86) ToolchainLinkFlags() string {
+ return t.toolchainLinuxX86.ToolchainLinkFlags() + " " + "${config.LinuxMuslToolchainLinkFlags}"
+}
+
+func (t *toolchainLinuxMuslX86) ToolchainRustFlags() string {
+ return t.toolchainLinuxX86.ToolchainRustFlags() + " " + "${config.LinuxMuslToolchainRustFlags}"
+}
+
+func linuxMuslX86ToolchainFactory(arch android.Arch) Toolchain {
+ return toolchainLinuxMuslX86Singleton
+}
+
+var toolchainLinuxGlibcX8664Singleton Toolchain = &toolchainLinuxGlibcX8664{}
+var toolchainLinuxGlibcX86Singleton Toolchain = &toolchainLinuxGlibcX86{}
+var toolchainLinuxMuslX8664Singleton Toolchain = &toolchainLinuxMuslX8664{}
+var toolchainLinuxMuslX86Singleton Toolchain = &toolchainLinuxMuslX86{}
diff --git a/rust/coverage.go b/rust/coverage.go
index 8fdfa23..050b811 100644
--- a/rust/coverage.go
+++ b/rust/coverage.go
@@ -57,18 +57,7 @@
flags.RustFlags = append(flags.RustFlags,
"-Z instrument-coverage", "-g")
flags.LinkFlags = append(flags.LinkFlags,
- profileInstrFlag, "-g", coverage.OutputFile().Path().String(), "-Wl,--wrap,open",
- // Upstream LLVM change 6d2d3bd0a6 made
- // -z,start-stop-gc the default. It drops metadata
- // sections like __llvm_prf_data unless they are marked
- // SHF_GNU_RETAIN. https://reviews.llvm.org/D97448
- // marks generated sections, including __llvm_prf_data
- // as SHF_GNU_RETAIN. However this change is not in
- // the Rust toolchain. Since we link Rust libs with
- // new lld, we should use nostart-stop-gc until the
- // Rust toolchain updates past D97448.
- "-Wl,-z,nostart-stop-gc",
- )
+ profileInstrFlag, "-g", coverage.OutputFile().Path().String(), "-Wl,--wrap,open")
deps.StaticLibs = append(deps.StaticLibs, coverage.OutputFile().Path())
}
diff --git a/rust/library.go b/rust/library.go
index bb2e83f..baac3f0 100644
--- a/rust/library.go
+++ b/rust/library.go
@@ -426,10 +426,16 @@
func (library *libraryDecorator) compilerDeps(ctx DepsContext, deps Deps) Deps {
deps = library.baseCompiler.compilerDeps(ctx, deps)
- if ctx.toolchain().Bionic() && (library.dylib() || library.shared()) {
- deps = bionicDeps(ctx, deps, false)
- deps.CrtBegin = "crtbegin_so"
- deps.CrtEnd = "crtend_so"
+ if library.dylib() || library.shared() {
+ if ctx.toolchain().Bionic() {
+ deps = bionicDeps(ctx, deps, false)
+ deps.CrtBegin = []string{"crtbegin_so"}
+ deps.CrtEnd = []string{"crtend_so"}
+ } else if ctx.Os() == android.LinuxMusl {
+ deps = muslDeps(ctx, deps, false)
+ deps.CrtBegin = []string{"libc_musl_crtbegin_so"}
+ deps.CrtEnd = []string{"libc_musl_crtend_so"}
+ }
}
return deps
diff --git a/rust/rust.go b/rust/rust.go
index 0f7b768..018d1dd 100644
--- a/rust/rust.go
+++ b/rust/rust.go
@@ -394,7 +394,7 @@
DataLibs []string
DataBins []string
- CrtBegin, CrtEnd string
+ CrtBegin, CrtEnd []string
}
type PathDeps struct {
@@ -421,8 +421,8 @@
depGeneratedHeaders android.Paths
depSystemIncludePaths android.Paths
- CrtBegin android.OptionalPath
- CrtEnd android.OptionalPath
+ CrtBegin android.Paths
+ CrtEnd android.Paths
// Paths to generated source files
SrcDeps android.Paths
@@ -1224,9 +1224,9 @@
depPaths.depSystemIncludePaths = append(depPaths.depSystemIncludePaths, exportedInfo.SystemIncludeDirs...)
depPaths.depGeneratedHeaders = append(depPaths.depGeneratedHeaders, exportedInfo.GeneratedHeaders...)
case depTag == cc.CrtBeginDepTag:
- depPaths.CrtBegin = linkObject
+ depPaths.CrtBegin = append(depPaths.CrtBegin, linkObject.Path())
case depTag == cc.CrtEndDepTag:
- depPaths.CrtEnd = linkObject
+ depPaths.CrtEnd = append(depPaths.CrtEnd, linkObject.Path())
}
// Make sure these dependencies are propagated
@@ -1234,6 +1234,13 @@
lib.exportLinkDirs(linkPath)
lib.exportLinkObjects(linkObject.String())
}
+ } else {
+ switch {
+ case depTag == cc.CrtBeginDepTag:
+ depPaths.CrtBegin = append(depPaths.CrtBegin, android.OutputFileForModule(ctx, dep, ""))
+ case depTag == cc.CrtEndDepTag:
+ depPaths.CrtEnd = append(depPaths.CrtEnd, android.OutputFileForModule(ctx, dep, ""))
+ }
}
if srcDep, ok := dep.(android.SourceFileProducer); ok {
@@ -1432,13 +1439,13 @@
actx.AddVariationDependencies(nil, cc.HeaderDepTag(), deps.HeaderLibs...)
crtVariations := cc.GetCrtVariations(ctx, mod)
- if deps.CrtBegin != "" {
+ for _, crt := range deps.CrtBegin {
actx.AddVariationDependencies(crtVariations, cc.CrtBeginDepTag,
- cc.RewriteSnapshotLib(deps.CrtBegin, cc.GetSnapshot(mod, &snapshotInfo, actx).Objects))
+ cc.RewriteSnapshotLib(crt, cc.GetSnapshot(mod, &snapshotInfo, actx).Objects))
}
- if deps.CrtEnd != "" {
+ for _, crt := range deps.CrtEnd {
actx.AddVariationDependencies(crtVariations, cc.CrtEndDepTag,
- cc.RewriteSnapshotLib(deps.CrtEnd, cc.GetSnapshot(mod, &snapshotInfo, actx).Objects))
+ cc.RewriteSnapshotLib(crt, cc.GetSnapshot(mod, &snapshotInfo, actx).Objects))
}
if mod.sourceProvider != nil {
diff --git a/sh/sh_binary_test.go b/sh/sh_binary_test.go
index 28b6fb9..7fe1d85 100644
--- a/sh/sh_binary_test.go
+++ b/sh/sh_binary_test.go
@@ -4,6 +4,7 @@
"os"
"path/filepath"
"strconv"
+ "strings"
"testing"
"android/soong/android"
@@ -215,3 +216,40 @@
actualData := entries.EntryMap["LOCAL_TEST_DATA"]
android.AssertStringPathsRelativeToTopEquals(t, "LOCAL_TEST_DATA", config, expectedData, actualData)
}
+
+func TestShTestHost_dataDeviceModulesAutogenTradefedConfig(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 := config.BuildOS.String()
+ fooModule := ctx.ModuleForTests("foo", buildOS+"_x86_64")
+
+ expectedBinAutogenConfig := `<option name="push-file" key="bar" value="/data/local/tests/unrestricted/foo/bar" />`
+ autogen := fooModule.Rule("autogen")
+ if !strings.Contains(autogen.Args["extraConfigs"], expectedBinAutogenConfig) {
+ t.Errorf("foo extraConfings %v does not contain %q", autogen.Args["extraConfigs"], expectedBinAutogenConfig)
+ }
+}
diff --git a/tradefed/autogen.go b/tradefed/autogen.go
index da55829..c2429ab 100644
--- a/tradefed/autogen.go
+++ b/tradefed/autogen.go
@@ -188,20 +188,20 @@
}
func AutoGenJavaTestConfig(ctx android.ModuleContext, testConfigProp *string, testConfigTemplateProp *string,
- testSuites []string, autoGenConfig *bool, unitTest *bool) android.Path {
+ testSuites []string, config []Config, autoGenConfig *bool, unitTest *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, "")
+ autogenTemplate(ctx, autogenPath, templatePath.String(), config, "")
} else {
if ctx.Device() {
- autogenTemplate(ctx, autogenPath, "${JavaTestConfigTemplate}", nil, "")
+ autogenTemplate(ctx, autogenPath, "${JavaTestConfigTemplate}", config, "")
} else {
if Bool(unitTest) {
- autogenTemplate(ctx, autogenPath, "${JavaHostUnitTestConfigTemplate}", nil, "")
+ autogenTemplate(ctx, autogenPath, "${JavaHostUnitTestConfigTemplate}", config, "")
} else {
- autogenTemplate(ctx, autogenPath, "${JavaHostTestConfigTemplate}", nil, "")
+ autogenTemplate(ctx, autogenPath, "${JavaHostTestConfigTemplate}", config, "")
}
}
}
diff --git a/ui/build/config.go b/ui/build/config.go
index a731932..d1714a4 100644
--- a/ui/build/config.go
+++ b/ui/build/config.go
@@ -868,6 +868,10 @@
return shared.JoinPath(c.SoongOutDir(), "module-graph.json")
}
+func (c *configImpl) ModuleActionsFile() string {
+ return shared.JoinPath(c.SoongOutDir(), "module-actions.json")
+}
+
func (c *configImpl) TempDir() string {
return shared.TempDirForOutDir(c.SoongOutDir())
}
diff --git a/ui/build/soong.go b/ui/build/soong.go
index 8133762..117a2a5 100644
--- a/ui/build/soong.go
+++ b/ui/build/soong.go
@@ -284,6 +284,7 @@
config.ModuleGraphFile(),
[]string{
"--module_graph_file", config.ModuleGraphFile(),
+ "--module_actions_file", config.ModuleActionsFile(),
},
fmt.Sprintf("generating the Soong module graph at %s", config.ModuleGraphFile()),
)