Merge "Add module name to sh_test install path."
diff --git a/android/arch.go b/android/arch.go
index 08c0256..9a54614 100644
--- a/android/arch.go
+++ b/android/arch.go
@@ -810,7 +810,7 @@
// Valid multilib values include:
// "both": compile for all Targets supported by the OsClass (generally x86_64 and x86, or arm64 and arm).
// "first": compile for only a single preferred Target supported by the OsClass. This is generally x86_64 or arm64,
-// but may be arm for a 32-bit only build or a build with TARGET_PREFER_32_BIT=true set.
+// but may be arm for a 32-bit only build.
// "32": compile for only a single 32-bit Target supported by the OsClass.
// "64": compile for only a single 64-bit Target supported by the OsClass.
// "common": compile a for a single Target that will work on all Targets suported by the OsClass (for example Java).
@@ -1026,6 +1026,7 @@
"Not_windows",
"Arm_on_x86",
"Arm_on_x86_64",
+ "Native_bridge",
}
for _, os := range OsTypeList {
targets = append(targets, os.Field)
@@ -1413,6 +1414,11 @@
prefix := "target.arm_on_x86_64"
m.appendProperties(ctx, genProps, targetProp, field, prefix)
}
+ if os == Android && m.Target().NativeBridge == NativeBridgeEnabled {
+ field := "Native_bridge"
+ prefix := "target.native_bridge"
+ m.appendProperties(ctx, genProps, targetProp, field, prefix)
+ }
}
}
}
diff --git a/android/arch_test.go b/android/arch_test.go
index b987d56..8525b03 100644
--- a/android/arch_test.go
+++ b/android/arch_test.go
@@ -383,3 +383,88 @@
})
}
}
+
+func TestArchMutatorNativeBridge(t *testing.T) {
+ bp := `
+ // This module is only enabled for x86.
+ module {
+ name: "foo",
+ }
+
+ // This module is enabled for x86 and arm (via native bridge).
+ module {
+ name: "bar",
+ native_bridge_supported: true,
+ }
+
+ // This module is enabled for arm (native_bridge) only.
+ module {
+ name: "baz",
+ native_bridge_supported: true,
+ enabled: false,
+ target: {
+ native_bridge: {
+ enabled: true,
+ }
+ }
+ }
+ `
+
+ testCases := []struct {
+ name string
+ config func(Config)
+ fooVariants []string
+ barVariants []string
+ bazVariants []string
+ }{
+ {
+ name: "normal",
+ config: nil,
+ fooVariants: []string{"android_x86_64_silvermont", "android_x86_silvermont"},
+ barVariants: []string{"android_x86_64_silvermont", "android_native_bridge_arm64_armv8-a", "android_x86_silvermont", "android_native_bridge_arm_armv7-a-neon"},
+ bazVariants: []string{"android_native_bridge_arm64_armv8-a", "android_native_bridge_arm_armv7-a-neon"},
+ },
+ }
+
+ enabledVariants := func(ctx *TestContext, name string) []string {
+ var ret []string
+ variants := ctx.ModuleVariantsForTests(name)
+ for _, variant := range variants {
+ m := ctx.ModuleForTests(name, variant)
+ if m.Module().Enabled() {
+ ret = append(ret, variant)
+ }
+ }
+ return ret
+ }
+
+ for _, tt := range testCases {
+ t.Run(tt.name, func(t *testing.T) {
+ config := TestArchConfigNativeBridge(buildDir, nil, bp, nil)
+
+ ctx := NewTestArchContext()
+ ctx.RegisterModuleType("module", archTestModuleFactory)
+ ctx.Register(config)
+ if tt.config != nil {
+ tt.config(config)
+ }
+
+ _, errs := ctx.ParseFileList(".", []string{"Android.bp"})
+ FailIfErrored(t, errs)
+ _, errs = ctx.PrepareBuildActions(config)
+ FailIfErrored(t, errs)
+
+ if g, w := enabledVariants(ctx, "foo"), tt.fooVariants; !reflect.DeepEqual(w, g) {
+ t.Errorf("want foo variants:\n%q\ngot:\n%q\n", w, g)
+ }
+
+ if g, w := enabledVariants(ctx, "bar"), tt.barVariants; !reflect.DeepEqual(w, g) {
+ t.Errorf("want bar variants:\n%q\ngot:\n%q\n", w, g)
+ }
+
+ if g, w := enabledVariants(ctx, "baz"), tt.bazVariants; !reflect.DeepEqual(w, g) {
+ t.Errorf("want qux variants:\n%q\ngot:\n%q\n", w, g)
+ }
+ })
+ }
+}
diff --git a/android/config.go b/android/config.go
index 59118ce..675660e 100644
--- a/android/config.go
+++ b/android/config.go
@@ -732,14 +732,6 @@
return Bool(c.productVariables.Eng)
}
-func (c *config) DevicePrefer32BitApps() bool {
- return Bool(c.productVariables.DevicePrefer32BitApps)
-}
-
-func (c *config) DevicePrefer32BitExecutables() bool {
- return Bool(c.productVariables.DevicePrefer32BitExecutables)
-}
-
func (c *config) DevicePrimaryArchType() ArchType {
return c.Targets[Android][0].Arch.ArchType
}
diff --git a/android/variable.go b/android/variable.go
index 3c08405..e025ae0 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -272,10 +272,6 @@
CoveragePaths []string `json:",omitempty"`
CoverageExcludePaths []string `json:",omitempty"`
- DevicePrefer32BitApps *bool `json:",omitempty"`
- DevicePrefer32BitExecutables *bool `json:",omitempty"`
- HostPrefer32BitExecutables *bool `json:",omitempty"`
-
SanitizeHost []string `json:",omitempty"`
SanitizeDevice []string `json:",omitempty"`
SanitizeDeviceDiag []string `json:",omitempty"`
diff --git a/apex/androidmk.go b/apex/androidmk.go
index 1b3a4ba..774b62d 100644
--- a/apex/androidmk.go
+++ b/apex/androidmk.go
@@ -180,13 +180,17 @@
}
switch fi.class {
case javaSharedLib:
- javaModule := fi.module.(java.Dependency)
// soong_java_prebuilt.mk sets LOCAL_MODULE_SUFFIX := .jar Therefore
// we need to remove the suffix from LOCAL_MODULE_STEM, otherwise
// we will have foo.jar.jar
fmt.Fprintln(w, "LOCAL_MODULE_STEM :=", strings.TrimSuffix(fi.Stem(), ".jar"))
- fmt.Fprintln(w, "LOCAL_SOONG_CLASSES_JAR :=", javaModule.ImplementationAndResourcesJars()[0].String())
- fmt.Fprintln(w, "LOCAL_SOONG_HEADER_JAR :=", javaModule.HeaderJars()[0].String())
+ if javaModule, ok := fi.module.(java.Dependency); ok {
+ fmt.Fprintln(w, "LOCAL_SOONG_CLASSES_JAR :=", javaModule.ImplementationAndResourcesJars()[0].String())
+ fmt.Fprintln(w, "LOCAL_SOONG_HEADER_JAR :=", javaModule.HeaderJars()[0].String())
+ } else {
+ fmt.Fprintln(w, "LOCAL_SOONG_CLASSES_JAR :=", fi.builtFile.String())
+ fmt.Fprintln(w, "LOCAL_SOONG_HEADER_JAR :=", fi.builtFile.String())
+ }
fmt.Fprintln(w, "LOCAL_SOONG_DEX_JAR :=", fi.builtFile.String())
fmt.Fprintln(w, "LOCAL_DEX_PREOPT := false")
fmt.Fprintln(w, "include $(BUILD_SYSTEM)/soong_java_prebuilt.mk")
diff --git a/apex/apex.go b/apex/apex.go
index 2f7b2e5..d45dd6f 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -2280,9 +2280,6 @@
module.AddProperties(&module.properties)
module.AddProperties(&module.targetProperties)
module.AddProperties(&module.overridableProperties)
- module.Prefer32(func(ctx android.BaseModuleContext, base *android.ModuleBase, class android.OsClass) bool {
- return class == android.Device && ctx.Config().DevicePrefer32BitExecutables()
- })
android.InitAndroidMultiTargetsArchModule(module, android.HostAndDeviceSupported, android.MultilibCommon)
android.InitDefaultableModule(module)
android.InitSdkAwareModule(module)
diff --git a/apex/apex_test.go b/apex/apex_test.go
index d6a5d09..7bd0374 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -329,7 +329,7 @@
// Minimal test
func TestBasicApex(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx, config := testApex(t, `
apex_defaults {
name: "myapex-defaults",
manifest: ":myapex.manifest",
@@ -484,6 +484,16 @@
apexRule := ctx.ModuleForTests("myapex", "android_common_myapex_image").Rule("apexRule")
+ // Make sure that Android.mk is created
+ ab := ctx.ModuleForTests("myapex", "android_common_myapex_image").Module().(*apexBundle)
+ data := android.AndroidMkDataForTest(t, config, "", ab)
+ var builder strings.Builder
+ data.Custom(&builder, ab.BaseModuleName(), "TARGET_", "", data)
+
+ androidMk := builder.String()
+ ensureContains(t, androidMk, "LOCAL_MODULE := mylib.myapex\n")
+ ensureNotContains(t, androidMk, "LOCAL_MODULE := mylib.com.android.myapex\n")
+
optFlags := apexRule.Args["opt_flags"]
ensureContains(t, optFlags, "--pubkey vendor/foo/devkeys/testkey.avbpubkey")
// Ensure that the NOTICE output is being packaged as an asset.
diff --git a/cc/cc.go b/cc/cc.go
index 8eabff5..770391a 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -825,15 +825,8 @@
}
c.Prefer32(func(ctx android.BaseModuleContext, base *android.ModuleBase, class android.OsClass) bool {
- switch class {
- case android.Device:
- return ctx.Config().DevicePrefer32BitExecutables()
- case android.HostCross:
- // Windows builds always prefer 32-bit
- return true
- default:
- return false
- }
+ // Windows builds always prefer 32-bit
+ return class == android.HostCross
})
android.InitAndroidArchModule(c, c.hod, c.multilib)
android.InitApexModule(c)
diff --git a/cc/config/global.go b/cc/config/global.go
index 1dd8a2d..7b651bc 100644
--- a/cc/config/global.go
+++ b/cc/config/global.go
@@ -128,8 +128,8 @@
// prebuilts/clang default settings.
ClangDefaultBase = "prebuilts/clang/host"
- ClangDefaultVersion = "clang-r383902"
- ClangDefaultShortVersion = "11.0.1"
+ ClangDefaultVersion = "clang-r383902b"
+ ClangDefaultShortVersion = "11.0.2"
// Directories with warnings from Android.bp files.
WarningAllowedProjects = []string{
diff --git a/cc/linker.go b/cc/linker.go
index 57a0c01..c9cbd9b 100644
--- a/cc/linker.go
+++ b/cc/linker.go
@@ -177,7 +177,10 @@
Version_script *string `android:"path,arch_variant"`
// list of static libs that should not be used to build this module
- Exclude_static_libs []string
+ Exclude_static_libs []string `android:"arch_variant"`
+
+ // list of shared libs that should not be used to build this module
+ Exclude_shared_libs []string `android:"arch_variant"`
}
func NewBaseLinker(sanitize *sanitize) *baseLinker {
@@ -223,6 +226,8 @@
deps.ReexportSharedLibHeaders = append(deps.ReexportSharedLibHeaders, linker.Properties.Export_shared_lib_headers...)
deps.ReexportGeneratedHeaders = append(deps.ReexportGeneratedHeaders, linker.Properties.Export_generated_headers...)
+ deps.SharedLibs = removeListFromList(deps.SharedLibs, linker.Properties.Exclude_shared_libs)
+ deps.StaticLibs = removeListFromList(deps.StaticLibs, linker.Properties.Exclude_static_libs)
deps.WholeStaticLibs = removeListFromList(deps.WholeStaticLibs, linker.Properties.Exclude_static_libs)
if Bool(linker.Properties.Use_version_lib) {
diff --git a/cc/sdk.go b/cc/sdk.go
index d05a04a..a6f94af 100644
--- a/cc/sdk.go
+++ b/cc/sdk.go
@@ -43,6 +43,7 @@
if ctx.Config().UnbundledBuild() {
modules[0].(*Module).Properties.HideFromMake = true
+ modules[0].(*Module).Properties.PreventInstall = true
} else {
modules[1].(*Module).Properties.SdkAndPlatformVariantVisibleToMake = true
modules[1].(*Module).Properties.PreventInstall = true
diff --git a/java/aar.go b/java/aar.go
index 7413c80..28e388a 100644
--- a/java/aar.go
+++ b/java/aar.go
@@ -734,6 +734,10 @@
return nil
}
+func (a *AARImport) DexJarInstallPath() android.Path {
+ return nil
+}
+
func (a *AARImport) AidlIncludeDirs() android.Paths {
return nil
}
diff --git a/java/app.go b/java/app.go
index 24dde79..7a109be 100755
--- a/java/app.go
+++ b/java/app.go
@@ -973,10 +973,6 @@
&module.overridableAppProperties,
&module.usesLibrary.usesLibraryProperties)
- module.Prefer32(func(ctx android.BaseModuleContext, base *android.ModuleBase, class android.OsClass) bool {
- return class == android.Device && ctx.Config().DevicePrefer32BitApps()
- })
-
android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon)
android.InitDefaultableModule(module)
android.InitOverridableModule(module, &module.appProperties.Overrides)
@@ -1887,16 +1883,22 @@
ctx.VisitDirectDepsWithTag(usesLibTag, func(m android.Module) {
dep := ctx.OtherModuleName(m)
if lib, ok := m.(Dependency); ok {
- if dexJar := lib.DexJarBuildPath(); dexJar != nil {
- usesLibPaths[dep] = &dexpreopt.LibraryPath{
- dexJar,
- // TODO(b/132357300): propagate actual install paths here.
- filepath.Join("/system/framework", dep+".jar"),
- }
- } else {
+ buildPath := lib.DexJarBuildPath()
+ if buildPath == nil {
ctx.ModuleErrorf("module %q in uses_libs or optional_uses_libs must"+
" produce a dex jar, does it have installable: true?", dep)
+ return
}
+
+ var devicePath string
+ installPath := lib.DexJarInstallPath()
+ if installPath == nil {
+ devicePath = filepath.Join("/system/framework", dep+".jar")
+ } else {
+ devicePath = android.InstallPathToOnDevicePath(ctx, installPath.(android.InstallPath))
+ }
+
+ usesLibPaths[dep] = &dexpreopt.LibraryPath{buildPath, devicePath}
} else if ctx.Config().AllowMissingDependencies() {
ctx.AddMissingDependencies([]string{dep})
} else {
diff --git a/java/device_host_converter.go b/java/device_host_converter.go
index 1ffb13f..877fd8a 100644
--- a/java/device_host_converter.go
+++ b/java/device_host_converter.go
@@ -154,6 +154,10 @@
return nil
}
+func (d *DeviceHostConverter) DexJarInstallPath() android.Path {
+ return nil
+}
+
func (d *DeviceHostConverter) AidlIncludeDirs() android.Paths {
return nil
}
diff --git a/java/dexpreopt.go b/java/dexpreopt.go
index 2911fd9..c33415e 100644
--- a/java/dexpreopt.go
+++ b/java/dexpreopt.go
@@ -77,10 +77,6 @@
return true
}
- if ctx.Config().UnbundledBuild() {
- return true
- }
-
if d.isTest {
return true
}
diff --git a/java/dexpreopt_bootjars.go b/java/dexpreopt_bootjars.go
index 9d93838..4120559 100644
--- a/java/dexpreopt_bootjars.go
+++ b/java/dexpreopt_bootjars.go
@@ -179,15 +179,7 @@
}
func skipDexpreoptBootJars(ctx android.PathContext) bool {
- if dexpreopt.GetGlobalConfig(ctx).DisablePreopt {
- return true
- }
-
- if ctx.Config().UnbundledBuild() {
- return true
- }
-
- return false
+ return dexpreopt.GetGlobalConfig(ctx).DisablePreopt
}
type dexpreoptBootJars struct {
@@ -340,10 +332,12 @@
bootFrameworkProfileRule(ctx, image, missingDeps)
updatableBcpPackagesRule(ctx, image, missingDeps)
- var allFiles android.Paths
+ var zipFiles android.Paths
for _, variant := range image.variants {
files := buildBootImageVariant(ctx, variant, profile, missingDeps)
- allFiles = append(allFiles, files.Paths()...)
+ if variant.target.Os == android.Android {
+ zipFiles = append(zipFiles, files.Paths()...)
+ }
}
if image.zip != nil {
@@ -351,8 +345,8 @@
rule.Command().
BuiltTool(ctx, "soong_zip").
FlagWithOutput("-o ", image.zip).
- FlagWithArg("-C ", image.dir.String()).
- FlagWithInputList("-f ", allFiles, " -f ")
+ FlagWithArg("-C ", image.dir.Join(ctx, android.Android.String()).String()).
+ FlagWithInputList("-f ", zipFiles, " -f ")
rule.Build(pctx, ctx, "zip_"+image.name, "zip "+image.name+" image")
}
diff --git a/java/dexpreopt_bootjars_test.go b/java/dexpreopt_bootjars_test.go
index e9704dc..9670c7f 100644
--- a/java/dexpreopt_bootjars_test.go
+++ b/java/dexpreopt_bootjars_test.go
@@ -118,7 +118,7 @@
ctx := android.PathContextForTesting(testConfig(nil, "", nil))
expectedInputs := []string{}
- for _, target := range dexpreoptTargets(ctx) {
+ for _, target := range ctx.Config().Targets[android.Android] {
for _, ext := range []string{".art", ".oat", ".vdex"} {
for _, jar := range []string{"foo", "bar", "baz"} {
expectedInputs = append(expectedInputs,
diff --git a/java/java.go b/java/java.go
index af68e56..5f8ad03 100644
--- a/java/java.go
+++ b/java/java.go
@@ -502,6 +502,7 @@
ResourceJars() android.Paths
ImplementationAndResourcesJars() android.Paths
DexJarBuildPath() android.Path
+ DexJarInstallPath() android.Path
AidlIncludeDirs() android.Paths
ExportedSdkLibs() []string
ExportedPlugins() (android.Paths, []string)
@@ -1749,6 +1750,10 @@
return j.dexJarFile
}
+func (j *Module) DexJarInstallPath() android.Path {
+ return j.installFile
+}
+
func (j *Module) ResourceJars() android.Paths {
if j.resourceJar == nil {
return nil
@@ -2575,6 +2580,10 @@
return nil
}
+func (j *Import) DexJarInstallPath() android.Path {
+ return nil
+}
+
func (j *Import) AidlIncludeDirs() android.Paths {
return j.exportAidlIncludeDirs
}
@@ -2754,8 +2763,10 @@
j.maybeStrippedDexJarFile = dexOutputFile
- ctx.InstallFile(android.PathForModuleInstall(ctx, "framework"),
- j.Stem()+".jar", dexOutputFile)
+ if j.IsForPlatform() {
+ ctx.InstallFile(android.PathForModuleInstall(ctx, "framework"),
+ j.Stem()+".jar", dexOutputFile)
+ }
}
func (j *DexImport) DexJarBuildPath() android.Path {
diff --git a/python/androidmk.go b/python/androidmk.go
index d293d52..247b80d 100644
--- a/python/androidmk.go
+++ b/python/androidmk.go
@@ -66,15 +66,9 @@
fmt.Fprintln(w, "LOCAL_COMPATIBILITY_SUITE :=",
strings.Join(p.binaryDecorator.binaryProperties.Test_suites, " "))
}
- // If the test config has an explicit config specified use it.
- if p.testProperties.Test_config != nil {
- fmt.Fprintln(w, "LOCAL_TEST_CONFIG :=",
- *p.testProperties.Test_config)
- } else {
- if p.testConfig != nil {
- fmt.Fprintln(w, "LOCAL_FULL_TEST_CONFIG :=",
- p.testConfig.String())
- }
+ if p.testConfig != nil {
+ fmt.Fprintln(w, "LOCAL_FULL_TEST_CONFIG :=",
+ p.testConfig.String())
}
if !BoolDefault(p.binaryProperties.Auto_gen_config, true) {
diff --git a/python/test.go b/python/test.go
index f684fd5..a669c73 100644
--- a/python/test.go
+++ b/python/test.go
@@ -29,11 +29,11 @@
type TestProperties struct {
// the name of the test configuration (for example "AndroidTest.xml") that should be
// installed with the module.
- Test_config *string `android:"arch_variant"`
+ Test_config *string `android:"path,arch_variant"`
// the name of the test configuration template (for example "AndroidTestTemplate.xml") that
// should be installed with the module.
- Test_config_template *string `android:"arch_variant"`
+ Test_config_template *string `android:"path,arch_variant"`
}
type testDecorator struct {
diff --git a/rust/Android.bp b/rust/Android.bp
index 684db0b..b06ea8e 100644
--- a/rust/Android.bp
+++ b/rust/Android.bp
@@ -16,6 +16,7 @@
"library.go",
"prebuilt.go",
"proc_macro.go",
+ "project_json.go",
"rust.go",
"test.go",
"testing.go",
@@ -25,6 +26,7 @@
"compiler_test.go",
"coverage_test.go",
"library_test.go",
+ "project_json_test.go",
"rust_test.go",
"test_test.go",
],
diff --git a/rust/library.go b/rust/library.go
index 8aa033c..2e51266 100644
--- a/rust/library.go
+++ b/rust/library.go
@@ -329,12 +329,21 @@
return deps
}
+
+func (library *libraryDecorator) sharedLibFilename(ctx ModuleContext) string {
+ return library.getStem(ctx) + ctx.toolchain().SharedLibSuffix()
+}
+
func (library *libraryDecorator) compilerFlags(ctx ModuleContext, flags Flags) Flags {
flags.RustFlags = append(flags.RustFlags, "-C metadata="+ctx.baseModuleName())
flags = library.baseCompiler.compilerFlags(ctx, flags)
if library.shared() || library.static() {
library.includeDirs = append(library.includeDirs, android.PathsForModuleSrc(ctx, library.Properties.Include_dirs)...)
}
+ if library.shared() {
+ flags.LinkFlags = append(flags.LinkFlags, "-Wl,-soname="+library.sharedLibFilename(ctx))
+ }
+
return flags
}
@@ -371,7 +380,7 @@
outputs := TransformSrctoStatic(ctx, srcPath, deps, flags, outputFile, deps.linkDirs)
library.coverageFile = outputs.coverageFile
} else if library.shared() {
- fileName := library.getStem(ctx) + ctx.toolchain().SharedLibSuffix()
+ fileName := library.sharedLibFilename(ctx)
outputFile = android.PathForModuleOut(ctx, fileName)
outputs := TransformSrctoShared(ctx, srcPath, deps, flags, outputFile, deps.linkDirs)
diff --git a/rust/library_test.go b/rust/library_test.go
index 9f9f374..37dd541 100644
--- a/rust/library_test.go
+++ b/rust/library_test.go
@@ -114,3 +114,17 @@
}`)
}
+
+func TestSharedLibraryFlags(t *testing.T) {
+ ctx := testRust(t, `
+ rust_library_host {
+ name: "libfoo",
+ srcs: ["foo.rs"],
+ crate_name: "foo",
+ }`)
+
+ libfooShared := ctx.ModuleForTests("libfoo", "linux_glibc_x86_64_shared").Output("libfoo.so")
+ if !strings.Contains(libfooShared.Args["linkFlags"], "-Wl,-soname=libfoo.so") {
+ t.Errorf("missing expected -Wl,-soname linker flag for libfoo shared lib, linkFlags: %#v", libfooShared.Args["linkFlags"])
+ }
+}
diff --git a/rust/project_json.go b/rust/project_json.go
new file mode 100644
index 0000000..909aebc
--- /dev/null
+++ b/rust/project_json.go
@@ -0,0 +1,161 @@
+// 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 rust
+
+import (
+ "encoding/json"
+ "fmt"
+ "path"
+
+ "android/soong/android"
+)
+
+// This singleton collects Rust crate definitions and generates a JSON file
+// (${OUT_DIR}/soong/rust-project.json) which can be use by external tools,
+// such as rust-analyzer. It does so when either make, mm, mma, mmm or mmma is
+// called. This singleton is enabled only if SOONG_GEN_RUST_PROJECT is set.
+// For example,
+//
+// $ SOONG_GEN_RUST_PROJECT=1 m nothing
+
+func init() {
+ android.RegisterSingletonType("rust_project_generator", rustProjectGeneratorSingleton)
+}
+
+func rustProjectGeneratorSingleton() android.Singleton {
+ return &projectGeneratorSingleton{}
+}
+
+type projectGeneratorSingleton struct{}
+
+const (
+ // Environment variables used to control the behavior of this singleton.
+ envVariableCollectRustDeps = "SOONG_GEN_RUST_PROJECT"
+ rustProjectJsonFileName = "rust-project.json"
+)
+
+// The format of rust-project.json is not yet finalized. A current description is available at:
+// https://github.com/rust-analyzer/rust-analyzer/blob/master/docs/user/manual.adoc#non-cargo-based-projects
+type rustProjectDep struct {
+ Crate int `json:"crate"`
+ Name string `json:"name"`
+}
+
+type rustProjectCrate struct {
+ RootModule string `json:"root_module"`
+ Edition string `json:"edition,omitempty"`
+ Deps []rustProjectDep `json:"deps"`
+ Cfgs []string `json:"cfgs"`
+}
+
+type rustProjectJson struct {
+ Roots []string `json:"roots"`
+ Crates []rustProjectCrate `json:"crates"`
+}
+
+// crateInfo is used during the processing to keep track of the known crates.
+type crateInfo struct {
+ ID int
+ Deps map[string]int
+}
+
+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)
+ if !ok {
+ return
+ }
+ if _, ok = deps[childName]; ok {
+ return
+ }
+ crate.Deps = append(crate.Deps, rustProjectDep{Crate: childId, Name: childName})
+ deps[childName] = 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).
+func appendLibraryAndDeps(ctx android.SingletonContext, project *rustProjectJson,
+ knownCrates map[string]crateInfo, module android.Module) (int, string, bool) {
+ rModule, ok := module.(*Module)
+ if !ok {
+ return 0, "", false
+ }
+ if rModule.compiler == nil {
+ return 0, "", false
+ }
+ rustLib, ok := rModule.compiler.(*libraryDecorator)
+ if !ok {
+ return 0, "", false
+ }
+ crateName := rModule.CrateName()
+ if cInfo, ok := knownCrates[crateName]; ok {
+ // We have seen this crate already; merge any new dependencies.
+ crate := project.Crates[cInfo.ID]
+ mergeDependencies(ctx, project, knownCrates, module, &crate, cInfo.Deps)
+ return cInfo.ID, crateName, true
+ }
+ crate := rustProjectCrate{Deps: make([]rustProjectDep, 0), Cfgs: make([]string, 0)}
+ src := rustLib.Properties.Srcs[0]
+ crate.RootModule = path.Join(ctx.ModuleDir(rModule), src)
+ crate.Edition = getEdition(rustLib.baseCompiler)
+
+ deps := make(map[string]int)
+ mergeDependencies(ctx, project, knownCrates, module, &crate, deps)
+
+ id := len(project.Crates)
+ knownCrates[crateName] = 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.
+ project.Roots = append(project.Roots, path.Dir(crate.RootModule))
+ return id, crateName, true
+}
+
+func (r *projectGeneratorSingleton) GenerateBuildActions(ctx android.SingletonContext) {
+ if !ctx.Config().IsEnvTrue(envVariableCollectRustDeps) {
+ return
+ }
+
+ project := rustProjectJson{}
+ knownCrates := make(map[string]crateInfo)
+ ctx.VisitAllModules(func(module android.Module) {
+ appendLibraryAndDeps(ctx, &project, knownCrates, module)
+ })
+
+ path := android.PathForOutput(ctx, rustProjectJsonFileName)
+ err := createJsonFile(project, path)
+ if err != nil {
+ ctx.Errorf(err.Error())
+ }
+}
+
+func createJsonFile(project rustProjectJson, rustProjectPath android.WritablePath) error {
+ buf, err := json.MarshalIndent(project, "", " ")
+ if err != nil {
+ return fmt.Errorf("JSON marshal of rustProjectJson failed: %s", err)
+ }
+ err = android.WriteFileToOutputDir(rustProjectPath, buf, 0666)
+ if err != nil {
+ return fmt.Errorf("Writing rust-project to %s failed: %s", rustProjectPath.String(), err)
+ }
+ return nil
+}
diff --git a/rust/project_json_test.go b/rust/project_json_test.go
new file mode 100644
index 0000000..6786e72
--- /dev/null
+++ b/rust/project_json_test.go
@@ -0,0 +1,55 @@
+// 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 rust
+
+import (
+ "io/ioutil"
+ "path/filepath"
+ "testing"
+
+ "android/soong/android"
+ "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,
+ }
+
+ cc.GatherRequiredFilesForTest(fs)
+
+ config := android.TestArchConfig(buildDir, env, bp, fs)
+ ctx := CreateTestContext()
+ ctx.Register(config)
+ _, errs := ctx.ParseFileList(".", []string{"Android.bp"})
+ android.FailIfErrored(t, errs)
+ _, errs = ctx.PrepareBuildActions(config)
+ android.FailIfErrored(t, errs)
+
+ // 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"))
+ if err != nil {
+ t.Errorf("rust-project.json has not been generated")
+ }
+}
diff --git a/rust/test.go b/rust/test.go
index 94568c1..10c2785 100644
--- a/rust/test.go
+++ b/rust/test.go
@@ -25,11 +25,11 @@
type TestProperties struct {
// the name of the test configuration (for example "AndroidTest.xml") that should be
// installed with the module.
- Test_config *string `android:"arch_variant"`
+ Test_config *string `android:"path,arch_variant"`
// the name of the test configuration template (for example "AndroidTestTemplate.xml") that
// should be installed with the module.
- Test_config_template *string `android:"arch_variant"`
+ Test_config_template *string `android:"path,arch_variant"`
// list of compatibility suites (for example "cts", "vts") that the module should be
// installed into.
diff --git a/rust/testing.go b/rust/testing.go
index 09008a8..f94af71 100644
--- a/rust/testing.go
+++ b/rust/testing.go
@@ -100,6 +100,7 @@
ctx.BottomUp("rust_unit_tests", TestPerSrcMutator).Parallel()
ctx.BottomUp("rust_begin", BeginMutator).Parallel()
})
+ ctx.RegisterSingletonType("rust_project_generator", rustProjectGeneratorSingleton)
return ctx
}
diff --git a/sh/sh_binary.go b/sh/sh_binary.go
index 37e8253..ae653fd 100644
--- a/sh/sh_binary.go
+++ b/sh/sh_binary.go
@@ -70,7 +70,7 @@
// the name of the test configuration (for example "AndroidTest.xml") that should be
// installed with the module.
- Test_config *string `android:"arch_variant"`
+ Test_config *string `android:"path,arch_variant"`
// list of files or filegroup modules that provide data that should be installed alongside
// the test.
@@ -234,12 +234,8 @@
entries.SetPath("LOCAL_MODULE_PATH", s.installDir.ToMakePath())
entries.AddStrings("LOCAL_COMPATIBILITY_SUITE", s.testProperties.Test_suites...)
- if s.testProperties.Test_config != nil {
- entries.SetString("LOCAL_TEST_CONFIG", proptools.String(s.testProperties.Test_config))
- } else {
- if s.testConfig != nil {
- entries.SetString("LOCAL_FULL_TEST_CONFIG", s.testConfig.String())
- }
+ if s.testConfig != nil {
+ entries.SetPath("LOCAL_FULL_TEST_CONFIG", s.testConfig)
}
for _, d := range s.data {
rel := d.Rel()
@@ -263,9 +259,6 @@
// executable binary to <partition>/bin.
func ShBinaryFactory() android.Module {
module := &ShBinary{}
- module.Prefer32(func(ctx android.BaseModuleContext, base *android.ModuleBase, class android.OsClass) bool {
- return class == android.Device && ctx.Config().DevicePrefer32BitExecutables()
- })
InitShBinaryModule(module)
android.InitAndroidArchModule(module, android.HostAndDeviceSupported, android.MultilibFirst)
return module
diff --git a/ui/build/config.go b/ui/build/config.go
index 49f506e..c4bbad7 100644
--- a/ui/build/config.go
+++ b/ui/build/config.go
@@ -592,6 +592,7 @@
c.environ.Set("TARGET_BUILD_VARIANT", variant)
c.environ.Set("TARGET_BUILD_TYPE", "release")
c.environ.Unset("TARGET_BUILD_APPS")
+ c.environ.Unset("TARGET_BUILD_UNBUNDLED")
}
// Tapas configures the environment to build one or more unbundled apps,
diff --git a/ui/build/dumpvars.go b/ui/build/dumpvars.go
index 7dc4915..e229856 100644
--- a/ui/build/dumpvars.go
+++ b/ui/build/dumpvars.go
@@ -143,6 +143,7 @@
"TARGET_BUILD_VARIANT",
"TARGET_BUILD_TYPE",
"TARGET_BUILD_APPS",
+ "TARGET_BUILD_UNBUNDLED",
"TARGET_ARCH",
"TARGET_ARCH_VARIANT",
"TARGET_CPU_VARIANT",
@@ -187,6 +188,7 @@
"TARGET_PRODUCT",
"TARGET_BUILD_VARIANT",
"TARGET_BUILD_APPS",
+ "TARGET_BUILD_UNBUNDLED",
// compiler wrappers set up by make
"CC_WRAPPER",