Merge "Create a synthetic Bazel workspace."
diff --git a/android/bazel.go b/android/bazel.go
index 260f1e5..1f7f7e6 100644
--- a/android/bazel.go
+++ b/android/bazel.go
@@ -134,7 +134,7 @@
"system/logging/liblog": Bp2BuildDefaultTrueRecursively,
}
- // Per-module denylist to always opt modules out.
+ // Per-module denylist to always opt modules out of both bp2build and mixed builds.
bp2buildModuleDoNotConvertList = []string{
"libBionicBenchmarksUtils", // ruperts@, cc_library_static, 'map' file not found
"libbionic_spawn_benchmark", // ruperts@, cc_library_static, depends on //system/libbase
@@ -170,6 +170,8 @@
"libc_dns", // ruperts@, cc_library_static, 'android/log.h' file not found
"libc_static_dispatch", // eakammer@, cc_library_static, 'private/bionic_asm.h' file not found
"libc_dynamic_dispatch", // eakammer@, cc_library_static, 'private/bionic_ifuncs.h' file not found
+ "note_memtag_heap_async", // jingwen@, cc_library_static, 'private/bionic_asm.h' file not found (arm64)
+ "note_memtag_heap_sync", // jingwen@, cc_library_static, 'private/bionic_asm.h' file not found (arm64)
// List of all full_cc_libraries in //bionic, with their immediate failures
"libc", // jingwen@, cc_library, depends on //external/gwp_asan
@@ -179,21 +181,39 @@
"libm", // jingwen@, cc_library, fatal error: 'freebsd-compat.h' file not found
"libseccomp_policy", // jingwen@, cc_library, fatal error: 'seccomp_policy.h' file not found
"libstdc++", // jingwen@, cc_library, depends on //external/gwp_asan
+ }
- // For mixed builds specifically
- "note_memtag_heap_async", // jingwen@, cc_library_static, OK for bp2build but features.h includes not found for mixed builds (b/185079815)
- "note_memtag_heap_sync", // jingwen@, cc_library_static, OK for bp2build but features.h includes not found for mixed builds (b/185079815)
- "libc_gdtoa", // ruperts@, cc_library_static, OK for bp2build but undefined symbol: __strtorQ for mixed builds
+ // Per-module denylist to opt modules out of mixed builds. Such modules will
+ // still be generated via bp2build.
+ mixedBuildsDisabledList = []string{
+ "libc_gdtoa", // ruperts@, cc_library_static, OK for bp2build but undefined symbol: __strtorQ for mixed builds
}
// Used for quicker lookups
bp2buildModuleDoNotConvert = map[string]bool{}
+ mixedBuildsDisabled = map[string]bool{}
)
func init() {
for _, moduleName := range bp2buildModuleDoNotConvertList {
bp2buildModuleDoNotConvert[moduleName] = true
}
+
+ for _, moduleName := range mixedBuildsDisabledList {
+ mixedBuildsDisabled[moduleName] = true
+ }
+}
+
+// MixedBuildsEnabled checks that a module is ready to be replaced by a
+// converted or handcrafted Bazel target.
+func (b *BazelModuleBase) MixedBuildsEnabled(ctx BazelConversionPathContext) bool {
+ if !ctx.Config().BazelContext.BazelEnabled() {
+ return false
+ }
+ if len(b.GetBazelLabel(ctx, ctx.Module())) == 0 {
+ return false
+ }
+ return !mixedBuildsDisabled[ctx.Module().Name()]
}
// ConvertWithBp2build returns whether the given BazelModuleBase should be converted with bp2build.
diff --git a/cc/cc.go b/cc/cc.go
index 7f69d56..9eebbae 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -1641,7 +1641,7 @@
func (c *Module) maybeGenerateBazelActions(actx android.ModuleContext) bool {
bazelModuleLabel := c.GetBazelLabel(actx, c)
bazelActionsUsed := false
- if c.bazelHandler != nil && actx.Config().BazelContext.BazelEnabled() && len(bazelModuleLabel) > 0 {
+ if c.MixedBuildsEnabled(actx) && c.bazelHandler != nil {
bazelActionsUsed = c.bazelHandler.generateBazelBuildActions(actx, bazelModuleLabel)
}
return bazelActionsUsed
diff --git a/cc/cc_test.go b/cc/cc_test.go
index 26d1f8e..db696ef 100644
--- a/cc/cc_test.go
+++ b/cc/cc_test.go
@@ -3778,59 +3778,6 @@
android.AssertStringDoesContain(t, "min sdk version", cFlags, "-target aarch64-linux-android29")
}
-func TestMinSdkVersionsOfCrtObjects(t *testing.T) {
- ctx := testCc(t, `
- cc_object {
- name: "crt_foo",
- srcs: ["foo.c"],
- crt: true,
- stl: "none",
- min_sdk_version: "28",
-
- }`)
-
- arch := "android_arm64_armv8-a"
- for _, v := range []string{"", "28", "29", "30", "current"} {
- var variant string
- if v == "" {
- variant = arch
- } else {
- variant = arch + "_sdk_" + v
- }
- cflags := ctx.ModuleForTests("crt_foo", variant).Rule("cc").Args["cFlags"]
- vNum := v
- if v == "current" || v == "" {
- vNum = "10000"
- }
- expected := "-target aarch64-linux-android" + vNum + " "
- android.AssertStringDoesContain(t, "cflag", cflags, expected)
- }
-}
-
-func TestUseCrtObjectOfCorrectVersion(t *testing.T) {
- ctx := testCc(t, `
- cc_binary {
- name: "bin",
- srcs: ["foo.c"],
- stl: "none",
- min_sdk_version: "29",
- sdk_version: "current",
- }
- `)
-
- // Sdk variant uses the crt object of the matching min_sdk_version
- variant := "android_arm64_armv8-a_sdk"
- crt := ctx.ModuleForTests("bin", variant).Rule("ld").Args["crtBegin"]
- android.AssertStringDoesContain(t, "crt dep of sdk variant", crt,
- variant+"_29/crtbegin_dynamic.o")
-
- // platform variant uses the crt object built for platform
- variant = "android_arm64_armv8-a"
- crt = ctx.ModuleForTests("bin", variant).Rule("ld").Args["crtBegin"]
- android.AssertStringDoesContain(t, "crt dep of platform variant", crt,
- variant+"/crtbegin_dynamic.o")
-}
-
type MemtagNoteType int
const (
diff --git a/cc/object_test.go b/cc/object_test.go
index f82d544..0e5508a 100644
--- a/cc/object_test.go
+++ b/cc/object_test.go
@@ -19,6 +19,60 @@
"testing"
)
+func TestMinSdkVersionsOfCrtObjects(t *testing.T) {
+ ctx := testCc(t, `
+ cc_object {
+ name: "crt_foo",
+ srcs: ["foo.c"],
+ crt: true,
+ stl: "none",
+ min_sdk_version: "28",
+
+ }`)
+
+ arch := "android_arm64_armv8-a"
+ for _, v := range []string{"", "28", "29", "30", "current"} {
+ var variant string
+ // platform variant
+ if v == "" {
+ variant = arch
+ } else {
+ variant = arch + "_sdk_" + v
+ }
+ cflags := ctx.ModuleForTests("crt_foo", variant).Rule("cc").Args["cFlags"]
+ vNum := v
+ if v == "current" || v == "" {
+ vNum = "10000"
+ }
+ expected := "-target aarch64-linux-android" + vNum + " "
+ android.AssertStringDoesContain(t, "cflag", cflags, expected)
+ }
+}
+
+func TestUseCrtObjectOfCorrectVersion(t *testing.T) {
+ ctx := testCc(t, `
+ cc_binary {
+ name: "bin",
+ srcs: ["foo.c"],
+ stl: "none",
+ min_sdk_version: "29",
+ sdk_version: "current",
+ }
+ `)
+
+ // Sdk variant uses the crt object of the matching min_sdk_version
+ variant := "android_arm64_armv8-a_sdk"
+ crt := ctx.ModuleForTests("bin", variant).Rule("ld").Args["crtBegin"]
+ android.AssertStringDoesContain(t, "crt dep of sdk variant", crt,
+ variant+"_29/crtbegin_dynamic.o")
+
+ // platform variant uses the crt object built for platform
+ variant = "android_arm64_armv8-a"
+ crt = ctx.ModuleForTests("bin", variant).Rule("ld").Args["crtBegin"]
+ android.AssertStringDoesContain(t, "crt dep of platform variant", crt,
+ variant+"/crtbegin_dynamic.o")
+}
+
func TestLinkerScript(t *testing.T) {
t.Run("script", func(t *testing.T) {
testCc(t, `
diff --git a/cmd/sbox/sbox.go b/cmd/sbox/sbox.go
index 7bd0868..f124e40 100644
--- a/cmd/sbox/sbox.go
+++ b/cmd/sbox/sbox.go
@@ -230,7 +230,7 @@
}
// Copy in any files specified by the manifest.
- err = copyFiles(command.CopyBefore, "", tempDir)
+ err = copyFiles(command.CopyBefore, "", tempDir, false)
if err != nil {
return "", err
}
@@ -255,12 +255,11 @@
return "", err
}
- commandDescription := rawCommand
-
cmd := exec.Command("bash", "-c", rawCommand)
+ buf := &bytes.Buffer{}
cmd.Stdin = os.Stdin
- cmd.Stdout = os.Stdout
- cmd.Stderr = os.Stderr
+ cmd.Stdout = buf
+ cmd.Stderr = buf
if command.GetChdir() {
cmd.Dir = tempDir
@@ -276,9 +275,29 @@
}
err = cmd.Run()
+ if err != nil {
+ // The command failed, do a best effort copy of output files out of the sandbox. This is
+ // especially useful for linters with baselines that print an error message on failure
+ // with a command to copy the output lint errors to the new baseline. Use a copy instead of
+ // a move to leave the sandbox intact for manual inspection
+ copyFiles(command.CopyAfter, tempDir, "", true)
+ }
+
+ // If the command was executed but failed with an error, print a debugging message before
+ // the command's output so it doesn't scroll the real error message off the screen.
if exit, ok := err.(*exec.ExitError); ok && !exit.Success() {
- return "", fmt.Errorf("sbox command failed with err:\n%s\n%w\n", commandDescription, err)
- } else if err != nil {
+ fmt.Fprintf(os.Stderr,
+ "The failing command was run inside an sbox sandbox in temporary directory\n"+
+ "%s\n"+
+ "The failing command line was:\n"+
+ "%s\n",
+ tempDir, rawCommand)
+ }
+
+ // Write the command's combined stdout/stderr.
+ os.Stdout.Write(buf.Bytes())
+
+ if err != nil {
return "", err
}
@@ -290,7 +309,7 @@
// build error message
errorMessage := "mismatch between declared and actual outputs\n"
- errorMessage += "in sbox command(" + commandDescription + ")\n\n"
+ errorMessage += "in sbox command(" + rawCommand + ")\n\n"
errorMessage += "in sandbox " + tempDir + ",\n"
errorMessage += fmt.Sprintf("failed to create %v files:\n", len(missingOutputErrors))
for _, missingOutputError := range missingOutputErrors {
@@ -351,12 +370,13 @@
return missingOutputErrors
}
-// copyFiles copies files in or out of the sandbox.
-func copyFiles(copies []*sbox_proto.Copy, fromDir, toDir string) error {
+// copyFiles copies files in or out of the sandbox. If allowFromNotExists is true then errors
+// caused by a from path not existing are ignored.
+func copyFiles(copies []*sbox_proto.Copy, fromDir, toDir string, allowFromNotExists bool) error {
for _, copyPair := range copies {
fromPath := joinPath(fromDir, copyPair.GetFrom())
toPath := joinPath(toDir, copyPair.GetTo())
- err := copyOneFile(fromPath, toPath, copyPair.GetExecutable())
+ err := copyOneFile(fromPath, toPath, copyPair.GetExecutable(), allowFromNotExists)
if err != nil {
return fmt.Errorf("error copying %q to %q: %w", fromPath, toPath, err)
}
@@ -364,8 +384,9 @@
return nil
}
-// copyOneFile copies a file.
-func copyOneFile(from string, to string, executable bool) error {
+// copyOneFile copies a file and its permissions. If forceExecutable is true it adds u+x to the
+// permissions. If allowFromNotExists is true it returns nil if the from path doesn't exist.
+func copyOneFile(from string, to string, forceExecutable, allowFromNotExists bool) error {
err := os.MkdirAll(filepath.Dir(to), 0777)
if err != nil {
return err
@@ -373,11 +394,14 @@
stat, err := os.Stat(from)
if err != nil {
+ if os.IsNotExist(err) && allowFromNotExists {
+ return nil
+ }
return err
}
perm := stat.Mode()
- if executable {
+ if forceExecutable {
perm = perm | 0100 // u+x
}
@@ -454,7 +478,7 @@
to := applyPathMappings(rspFile.PathMappings, from)
// Copy the file into the sandbox.
- err := copyOneFile(from, joinPath(toDir, to), false)
+ err := copyOneFile(from, joinPath(toDir, to), false, false)
if err != nil {
return err
}
diff --git a/genrule/genrule.go b/genrule/genrule.go
index e6a5ab9..3a9aecc 100644
--- a/genrule/genrule.go
+++ b/genrule/genrule.go
@@ -543,7 +543,7 @@
bazelModuleLabel := g.GetBazelLabel(ctx, g)
bazelActionsUsed := false
- if ctx.Config().BazelContext.BazelEnabled() && len(bazelModuleLabel) > 0 {
+ if g.MixedBuildsEnabled(ctx) {
bazelActionsUsed = g.generateBazelBuildActions(ctx, bazelModuleLabel)
}
if !bazelActionsUsed {
diff --git a/java/droidstubs.go b/java/droidstubs.go
index a9e2749..2676f3d 100644
--- a/java/droidstubs.go
+++ b/java/droidstubs.go
@@ -516,9 +516,6 @@
d.apiLintTimestamp = android.PathForModuleOut(ctx, "metalava", "api_lint.timestamp")
// Note this string includes a special shell quote $' ... ', which decodes the "\n"s.
- // However, because $' ... ' doesn't expand environmental variables, we can't just embed
- // $PWD, so we have to terminate $'...', use "$PWD", then start $' ... ' again,
- // which is why we have '"$PWD"$' in it.
//
// TODO: metalava also has a slightly different message hardcoded. Should we unify this
// message and metalava's one?
@@ -539,9 +536,9 @@
msg += fmt.Sprintf(``+
`2. You can update the baseline by executing the following\n`+
` command:\n`+
- ` cp \\\n`+
- ` "'"$PWD"$'/%s" \\\n`+
- ` "'"$PWD"$'/%s"\n`+
+ ` (cd $ANDROID_BUILD_TOP && cp \\\n`+
+ ` "%s" \\\n`+
+ ` "%s")\n`+
` To submit the revised baseline.txt to the main Android\n`+
` repository, you will need approval.\n`, updatedBaselineOutput, baselineFile.Path())
} else {
diff --git a/java/java.go b/java/java.go
index ee4f2eb..adb0c56 100644
--- a/java/java.go
+++ b/java/java.go
@@ -27,6 +27,7 @@
"github.com/google/blueprint/proptools"
"android/soong/android"
+ "android/soong/cc"
"android/soong/dexpreopt"
"android/soong/java/config"
"android/soong/tradefed"
@@ -708,6 +709,9 @@
// Test options.
Test_options TestOptions
+
+ // Names of modules containing JNI libraries that should be installed alongside the test.
+ Jni_libs []string
}
type hostTestProperties struct {
@@ -769,6 +773,13 @@
}
}
+ if len(j.testProperties.Jni_libs) > 0 {
+ for _, target := range ctx.MultiTargets() {
+ sharedLibVariations := append(target.Variations(), blueprint.Variation{Mutator: "link", Variation: "shared"})
+ ctx.AddFarVariationDependencies(sharedLibVariations, jniLibTag, j.testProperties.Jni_libs...)
+ }
+ }
+
j.deps(ctx)
}
@@ -793,6 +804,29 @@
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 {
+ // Copy to an intermediate output directory to append "lib[64]" to the path,
+ // so that it's compatible with the default rpath values.
+ var relPath string
+ if sharedLibInfo.Target.Arch.ArchType.Multilib == "lib64" {
+ relPath = filepath.Join("lib64", sharedLibInfo.SharedLibrary.Base())
+ } else {
+ relPath = filepath.Join("lib", sharedLibInfo.SharedLibrary.Base())
+ }
+ relocatedLib := android.PathForModuleOut(ctx, "relocated").Join(ctx, relPath)
+ ctx.Build(pctx, android.BuildParams{
+ Rule: android.Cp,
+ Input: sharedLibInfo.SharedLibrary,
+ Output: relocatedLib,
+ })
+ j.data = append(j.data, relocatedLib)
+ } else {
+ ctx.PropertyErrorf("jni_libs", "%q of type %q is not supported", dep.Name(), ctx.OtherModuleType(dep))
+ }
+ })
+
j.Library.GenerateAndroidBuildActions(ctx)
}
diff --git a/java/java_test.go b/java/java_test.go
index 0523458..e7ea4ef 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -20,6 +20,7 @@
"path/filepath"
"reflect"
"regexp"
+ "runtime"
"strconv"
"strings"
"testing"
@@ -462,6 +463,38 @@
}
}
+func TestTest(t *testing.T) {
+ ctx, _ := testJava(t, `
+ java_test_host {
+ name: "foo",
+ srcs: ["a.java"],
+ jni_libs: ["libjni"],
+ }
+
+ cc_library_shared {
+ name: "libjni",
+ host_supported: true,
+ device_supported: false,
+ stl: "none",
+ }
+ `)
+
+ buildOS := android.BuildOs.String()
+
+ foo := ctx.ModuleForTests("foo", buildOS+"_common").Module().(*TestHost)
+
+ expected := "lib64/libjni.so"
+ if runtime.GOOS == "darwin" {
+ expected = "lib64/libjni.dylib"
+ }
+
+ fooTestData := foo.data
+ if len(fooTestData) != 1 || fooTestData[0].Rel() != expected {
+ t.Errorf(`expected foo test data relative path [%q], got %q`,
+ expected, fooTestData.Strings())
+ }
+}
+
func TestHostBinaryNoJavaDebugInfoOverride(t *testing.T) {
bp := `
java_library {
diff --git a/java/sdk_library.go b/java/sdk_library.go
index e5ee397..223be5c 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -534,6 +534,11 @@
// This is not the implementation jar, it still only contains stubs.
stubsImplPath android.Paths
+ // The dex jar for the stubs.
+ //
+ // This is not the implementation jar, it still only contains stubs.
+ stubsDexJarPath android.Path
+
// The API specification file, e.g. system_current.txt.
currentApiFilePath android.OptionalPath
@@ -549,6 +554,9 @@
lib := ctx.OtherModuleProvider(dep, JavaInfoProvider).(JavaInfo)
paths.stubsHeaderPath = lib.HeaderJars
paths.stubsImplPath = lib.ImplementationJars
+
+ libDep := dep.(UsesLibraryDependency)
+ paths.stubsDexJarPath = libDep.DexJarBuildPath()
return nil
} else {
return fmt.Errorf("expected module that has JavaInfoProvider, e.g. java_library")
@@ -825,8 +833,22 @@
return PrebuiltJars(ctx, c.moduleBase.BaseModuleName(), sdkVersion)
}
+ paths := c.selectScopePaths(ctx, sdkVersion.Kind)
+ if paths == nil {
+ return nil
+ }
+
+ return paths.stubsHeaderPath
+}
+
+// selectScopePaths returns the *scopePaths appropriate for the specific kind.
+//
+// If the module does not support the specific kind then it will return the *scopePaths for the
+// closest kind which is a subset of the requested kind. e.g. if requesting android.SdkModule then
+// it will return *scopePaths for android.SdkSystem if available or android.SdkPublic of not.
+func (c *commonToSdkLibraryAndImport) selectScopePaths(ctx android.BaseModuleContext, kind android.SdkKind) *scopePaths {
var apiScope *apiScope
- switch sdkVersion.Kind {
+ switch kind {
case android.SdkSystem:
apiScope = apiScopeSystem
case android.SdkModule:
@@ -851,7 +873,17 @@
return nil
}
- return paths.stubsHeaderPath
+ return paths
+}
+
+// to satisfy SdkLibraryDependency interface
+func (c *commonToSdkLibraryAndImport) SdkApiStubDexJar(ctx android.BaseModuleContext, kind android.SdkKind) android.Path {
+ paths := c.selectScopePaths(ctx, kind)
+ if paths == nil {
+ return nil
+ }
+
+ return paths.stubsDexJarPath
}
func (c *commonToSdkLibraryAndImport) sdkComponentPropertiesForChildLibrary() interface{} {
@@ -944,6 +976,10 @@
// jars for the stubs. The latter should only be needed when generating JavaDoc as otherwise
// they are identical to the corresponding header jars.
SdkImplementationJars(ctx android.BaseModuleContext, sdkVersion android.SdkSpec) android.Paths
+
+ // SdkApiStubDexJar returns the dex jar for the stubs. It is needed by the hiddenapi processing
+ // tool which processes dex files.
+ SdkApiStubDexJar(ctx android.BaseModuleContext, kind android.SdkKind) android.Path
}
type SdkLibrary struct {
@@ -1781,6 +1817,9 @@
// List of shared java libs, common to all scopes, that this module has
// dependencies to
Libs []string
+
+ // If set to true, compile dex files for the stubs. Defaults to false.
+ Compile_dex *bool
}
type SdkLibraryImport struct {
@@ -1916,6 +1955,7 @@
Libs []string
Jars []string
Prefer *bool
+ Compile_dex *bool
}{}
props.Name = proptools.StringPtr(module.stubsLibraryModuleName(apiScope))
props.Sdk_version = scopeProperties.Sdk_version
@@ -1927,6 +1967,9 @@
// The imports are preferred if the java_sdk_library_import is preferred.
props.Prefer = proptools.BoolPtr(module.prebuilt.Prefer())
+ // The imports need to be compiled to dex if the java_sdk_library_import requests it.
+ props.Compile_dex = module.properties.Compile_dex
+
mctx.CreateModule(ImportFactory, &props, module.sdkComponentPropertiesForChildLibrary())
}
@@ -2348,6 +2391,9 @@
// otherwise.
Shared_library *bool
+ // True if the stub imports should produce dex jars.
+ Compile_dex *bool
+
// The paths to the doctag files to add to the prebuilt.
Doctag_paths android.Paths
}
@@ -2389,6 +2435,7 @@
s.Libs = sdk.properties.Libs
s.Naming_scheme = sdk.commonSdkLibraryProperties.Naming_scheme
s.Shared_library = proptools.BoolPtr(sdk.sharedLibrary())
+ s.Compile_dex = sdk.dexProperties.Compile_dex
s.Doctag_paths = sdk.doctagPaths
}
@@ -2399,6 +2446,9 @@
if s.Shared_library != nil {
propertySet.AddProperty("shared_library", *s.Shared_library)
}
+ if s.Compile_dex != nil {
+ propertySet.AddProperty("compile_dex", *s.Compile_dex)
+ }
for _, apiScope := range allApiScopes {
if properties, ok := s.Scopes[apiScope]; ok {
diff --git a/python/builder.go b/python/builder.go
index dc2d1f1..7d7239c 100644
--- a/python/builder.go
+++ b/python/builder.go
@@ -45,7 +45,7 @@
hostPar = pctx.AndroidStaticRule("hostPar",
blueprint.RuleParams{
Command: `sed -e 's/%interpreter%/$interp/g' -e 's/%main%/$main/g' $template > $stub && ` +
- `echo "#!/usr/bin/env python" >${out}.prefix &&` +
+ `echo "#!/usr/bin/env $interp" >${out}.prefix &&` +
`$mergeParCmd -p --prefix ${out}.prefix -pm $stub $out $srcsZips && ` +
`chmod +x $out && (rm -f $stub; rm -f ${out}.prefix)`,
CommandDeps: []string{"$mergeParCmd"},
diff --git a/python/scripts/stub_template_host.txt b/python/scripts/stub_template_host.txt
index a48a86f..138404b 100644
--- a/python/scripts/stub_template_host.txt
+++ b/python/scripts/stub_template_host.txt
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env '%interpreter%'
import os
import re
@@ -82,7 +82,7 @@
sys.stdout.flush()
retCode = subprocess.call(args)
- exit(retCode)
+ sys.exit(retCode)
except:
raise
finally:
diff --git a/rust/Android.bp b/rust/Android.bp
index a6c4e07..f45404f 100644
--- a/rust/Android.bp
+++ b/rust/Android.bp
@@ -21,6 +21,7 @@
"clippy.go",
"compiler.go",
"coverage.go",
+ "doc.go",
"fuzz.go",
"image.go",
"library.go",
diff --git a/rust/binary.go b/rust/binary.go
index dfe8744..ffc0413 100644
--- a/rust/binary.go
+++ b/rust/binary.go
@@ -122,7 +122,7 @@
flags.LinkFlags = append(flags.LinkFlags, deps.depLinkFlags...)
flags.LinkFlags = append(flags.LinkFlags, deps.linkObjects...)
- TransformSrcToBinary(ctx, srcPath, deps, flags, outputFile, deps.linkDirs)
+ TransformSrcToBinary(ctx, srcPath, deps, flags, outputFile)
if binary.stripper.NeedsStrip(ctx) {
strippedOutputFile := android.PathForModuleOut(ctx, "stripped", fileName)
diff --git a/rust/bindgen.go b/rust/bindgen.go
index bcc26b8..8edb7c9 100644
--- a/rust/bindgen.go
+++ b/rust/bindgen.go
@@ -29,7 +29,7 @@
defaultBindgenFlags = []string{""}
// bindgen should specify its own Clang revision so updating Clang isn't potentially blocked on bindgen failures.
- bindgenClangVersion = "clang-r412851"
+ bindgenClangVersion = "clang-r416183b"
_ = pctx.VariableFunc("bindgenClangVersion", func(ctx android.PackageVarContext) string {
if override := ctx.Config().Getenv("LLVM_BINDGEN_PREBUILTS_VERSION"); override != "" {
diff --git a/rust/builder.go b/rust/builder.go
index 208b734..1fcce38 100644
--- a/rust/builder.go
+++ b/rust/builder.go
@@ -44,6 +44,16 @@
},
"rustcFlags", "linkFlags", "libFlags", "crtBegin", "crtEnd", "envVars")
+ _ = pctx.SourcePathVariable("rustdocCmd", "${config.RustBin}/rustdoc")
+ rustdoc = pctx.AndroidStaticRule("rustdoc",
+ blueprint.RuleParams{
+ Command: "rm -rf $outDir && " +
+ "$envVars $rustdocCmd $rustdocFlags $in -o $outDir && " +
+ "touch $out",
+ CommandDeps: []string{"$rustdocCmd"},
+ },
+ "rustdocFlags", "outDir", "envVars")
+
_ = pctx.SourcePathVariable("clippyCmd", "${config.RustBin}/clippy-driver")
clippyDriver = pctx.AndroidStaticRule("clippy",
blueprint.RuleParams{
@@ -85,37 +95,37 @@
}
func TransformSrcToBinary(ctx ModuleContext, mainSrc android.Path, deps PathDeps, flags Flags,
- outputFile android.WritablePath, linkDirs []string) buildOutput {
+ outputFile android.WritablePath) buildOutput {
flags.GlobalRustFlags = append(flags.GlobalRustFlags, "-C lto")
- return transformSrctoCrate(ctx, mainSrc, deps, flags, outputFile, "bin", linkDirs)
+ return transformSrctoCrate(ctx, mainSrc, deps, flags, outputFile, "bin")
}
func TransformSrctoRlib(ctx ModuleContext, mainSrc android.Path, deps PathDeps, flags Flags,
- outputFile android.WritablePath, linkDirs []string) buildOutput {
- return transformSrctoCrate(ctx, mainSrc, deps, flags, outputFile, "rlib", linkDirs)
+ outputFile android.WritablePath) buildOutput {
+ return transformSrctoCrate(ctx, mainSrc, deps, flags, outputFile, "rlib")
}
func TransformSrctoDylib(ctx ModuleContext, mainSrc android.Path, deps PathDeps, flags Flags,
- outputFile android.WritablePath, linkDirs []string) buildOutput {
- return transformSrctoCrate(ctx, mainSrc, deps, flags, outputFile, "dylib", linkDirs)
+ outputFile android.WritablePath) buildOutput {
+ return transformSrctoCrate(ctx, mainSrc, deps, flags, outputFile, "dylib")
}
func TransformSrctoStatic(ctx ModuleContext, mainSrc android.Path, deps PathDeps, flags Flags,
- outputFile android.WritablePath, linkDirs []string) buildOutput {
+ outputFile android.WritablePath) buildOutput {
flags.GlobalRustFlags = append(flags.GlobalRustFlags, "-C lto")
- return transformSrctoCrate(ctx, mainSrc, deps, flags, outputFile, "staticlib", linkDirs)
+ return transformSrctoCrate(ctx, mainSrc, deps, flags, outputFile, "staticlib")
}
func TransformSrctoShared(ctx ModuleContext, mainSrc android.Path, deps PathDeps, flags Flags,
- outputFile android.WritablePath, linkDirs []string) buildOutput {
+ outputFile android.WritablePath) buildOutput {
flags.GlobalRustFlags = append(flags.GlobalRustFlags, "-C lto")
- return transformSrctoCrate(ctx, mainSrc, deps, flags, outputFile, "cdylib", linkDirs)
+ return transformSrctoCrate(ctx, mainSrc, deps, flags, outputFile, "cdylib")
}
func TransformSrctoProcMacro(ctx ModuleContext, mainSrc android.Path, deps PathDeps,
- flags Flags, outputFile android.WritablePath, linkDirs []string) buildOutput {
- return transformSrctoCrate(ctx, mainSrc, deps, flags, outputFile, "proc-macro", linkDirs)
+ flags Flags, outputFile android.WritablePath) buildOutput {
+ return transformSrctoCrate(ctx, mainSrc, deps, flags, outputFile, "proc-macro")
}
func rustLibsToPaths(libs RustLibraries) android.Paths {
@@ -126,26 +136,69 @@
return paths
}
+func makeLibFlags(deps PathDeps) []string {
+ var libFlags []string
+
+ // Collect library/crate flags
+ for _, lib := range deps.RLibs {
+ libFlags = append(libFlags, "--extern "+lib.CrateName+"="+lib.Path.String())
+ }
+ for _, lib := range deps.DyLibs {
+ libFlags = append(libFlags, "--extern "+lib.CrateName+"="+lib.Path.String())
+ }
+ for _, proc_macro := range deps.ProcMacros {
+ libFlags = append(libFlags, "--extern "+proc_macro.CrateName+"="+proc_macro.Path.String())
+ }
+
+ for _, path := range deps.linkDirs {
+ libFlags = append(libFlags, "-L "+path)
+ }
+
+ return libFlags
+}
+
+func rustEnvVars(ctx ModuleContext, deps PathDeps) []string {
+ var envVars []string
+
+ // libstd requires a specific environment variable to be set. This is
+ // not officially documented and may be removed in the future. See
+ // https://github.com/rust-lang/rust/blob/master/library/std/src/env.rs#L866.
+ if ctx.RustModule().CrateName() == "std" {
+ envVars = append(envVars, "STD_ENV_ARCH="+config.StdEnvArch[ctx.RustModule().Arch().ArchType])
+ }
+
+ if len(deps.SrcDeps) > 0 {
+ moduleGenDir := ctx.RustModule().compiler.CargoOutDir()
+ // We must calculate an absolute path for OUT_DIR since Rust's include! macro (which normally consumes this)
+ // assumes that paths are relative to the source file.
+ var outDirPrefix string
+ if !filepath.IsAbs(moduleGenDir.String()) {
+ // If OUT_DIR is not absolute, we use $$PWD to generate an absolute path (os.Getwd() returns '/')
+ outDirPrefix = "$$PWD/"
+ } else {
+ // If OUT_DIR is absolute, then moduleGenDir will be an absolute path, so we don't need to set this to anything.
+ outDirPrefix = ""
+ }
+ envVars = append(envVars, "OUT_DIR="+filepath.Join(outDirPrefix, moduleGenDir.String()))
+ }
+
+ return envVars
+}
+
func transformSrctoCrate(ctx ModuleContext, main android.Path, deps PathDeps, flags Flags,
- outputFile android.WritablePath, crate_type string, linkDirs []string) buildOutput {
+ outputFile android.WritablePath, crate_type string) buildOutput {
var inputs android.Paths
var implicits android.Paths
- var envVars []string
var output buildOutput
- var libFlags, rustcFlags, linkFlags []string
+ var rustcFlags, linkFlags []string
var implicitOutputs android.WritablePaths
output.outputFile = outputFile
crateName := ctx.RustModule().CrateName()
targetTriple := ctx.toolchain().RustTriple()
- // libstd requires a specific environment variable to be set. This is
- // not officially documented and may be removed in the future. See
- // https://github.com/rust-lang/rust/blob/master/library/std/src/env.rs#L866.
- if crateName == "std" {
- envVars = append(envVars, "STD_ENV_ARCH="+config.StdEnvArch[ctx.RustModule().Arch().ArchType])
- }
+ envVars := rustEnvVars(ctx, deps)
inputs = append(inputs, main)
@@ -168,20 +221,7 @@
linkFlags = append(linkFlags, flags.GlobalLinkFlags...)
linkFlags = append(linkFlags, flags.LinkFlags...)
- // Collect library/crate flags
- for _, lib := range deps.RLibs {
- libFlags = append(libFlags, "--extern "+lib.CrateName+"="+lib.Path.String())
- }
- for _, lib := range deps.DyLibs {
- libFlags = append(libFlags, "--extern "+lib.CrateName+"="+lib.Path.String())
- }
- for _, proc_macro := range deps.ProcMacros {
- libFlags = append(libFlags, "--extern "+proc_macro.CrateName+"="+proc_macro.Path.String())
- }
-
- for _, path := range linkDirs {
- libFlags = append(libFlags, "-L "+path)
- }
+ libFlags := makeLibFlags(deps)
// Collect dependencies
implicits = append(implicits, rustLibsToPaths(deps.RLibs)...)
@@ -217,18 +257,6 @@
},
})
implicits = append(implicits, outputs.Paths()...)
-
- // We must calculate an absolute path for OUT_DIR since Rust's include! macro (which normally consumes this)
- // assumes that paths are relative to the source file.
- var outDirPrefix string
- if !filepath.IsAbs(moduleGenDir.String()) {
- // If OUT_DIR is not absolute, we use $$PWD to generate an absolute path (os.Getwd() returns '/')
- outDirPrefix = "$$PWD/"
- } else {
- // If OUT_DIR is absolute, then moduleGenDir will be an absolute path, so we don't need to set this to anything.
- outDirPrefix = ""
- }
- envVars = append(envVars, "OUT_DIR="+filepath.Join(outDirPrefix, moduleGenDir.String()))
}
envVars = append(envVars, "ANDROID_RUST_VERSION="+config.RustDefaultVersion)
@@ -272,3 +300,41 @@
return output
}
+
+func Rustdoc(ctx ModuleContext, main android.Path, deps PathDeps,
+ flags Flags) android.ModuleOutPath {
+
+ rustdocFlags := append([]string{}, flags.RustdocFlags...)
+ rustdocFlags = append(rustdocFlags, "--sysroot=/dev/null")
+
+ targetTriple := ctx.toolchain().RustTriple()
+
+ // Collect rustc flags
+ if targetTriple != "" {
+ rustdocFlags = append(rustdocFlags, "--target="+targetTriple)
+ }
+
+ crateName := ctx.RustModule().CrateName()
+ if crateName != "" {
+ rustdocFlags = append(rustdocFlags, "--crate-name "+crateName)
+ }
+
+ rustdocFlags = append(rustdocFlags, makeLibFlags(deps)...)
+ docTimestampFile := android.PathForModuleOut(ctx, "rustdoc.timestamp")
+ docDir := android.PathForOutput(ctx, "rustdoc", ctx.ModuleName())
+
+ ctx.Build(pctx, android.BuildParams{
+ Rule: rustdoc,
+ Description: "rustdoc " + main.Rel(),
+ Output: docTimestampFile,
+ Input: main,
+ Implicit: ctx.RustModule().unstrippedOutputFile.Path(),
+ Args: map[string]string{
+ "rustdocFlags": strings.Join(rustdocFlags, " "),
+ "outDir": docDir.String(),
+ "envVars": strings.Join(rustEnvVars(ctx, deps), " "),
+ },
+ })
+
+ return docTimestampFile
+}
diff --git a/rust/compiler.go b/rust/compiler.go
index bc034d7..bfc23b2 100644
--- a/rust/compiler.go
+++ b/rust/compiler.go
@@ -239,7 +239,10 @@
flags.RustFlags = append(flags.RustFlags, compiler.Properties.Flags...)
flags.RustFlags = append(flags.RustFlags, compiler.cfgsToFlags()...)
flags.RustFlags = append(flags.RustFlags, compiler.featuresToFlags()...)
+ flags.RustdocFlags = append(flags.RustdocFlags, compiler.cfgsToFlags()...)
+ flags.RustdocFlags = append(flags.RustdocFlags, compiler.featuresToFlags()...)
flags.RustFlags = append(flags.RustFlags, "--edition="+compiler.edition())
+ flags.RustdocFlags = append(flags.RustdocFlags, "--edition="+compiler.edition())
flags.LinkFlags = append(flags.LinkFlags, compiler.Properties.Ld_flags...)
flags.GlobalRustFlags = append(flags.GlobalRustFlags, config.GlobalRustFlags...)
flags.GlobalRustFlags = append(flags.GlobalRustFlags, ctx.toolchain().ToolchainRustFlags())
@@ -272,6 +275,12 @@
panic(fmt.Errorf("baseCrater doesn't know how to crate things!"))
}
+func (compiler *baseCompiler) rustdoc(ctx ModuleContext, flags Flags,
+ deps PathDeps) android.OptionalPath {
+
+ return android.OptionalPath{}
+}
+
func (compiler *baseCompiler) initialize(ctx ModuleContext) {
compiler.cargoOutDir = android.PathForModuleOut(ctx, genSubDir)
}
diff --git a/rust/doc.go b/rust/doc.go
new file mode 100644
index 0000000..e7f1371
--- /dev/null
+++ b/rust/doc.go
@@ -0,0 +1,43 @@
+// Copyright 2021 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package rust
+
+import (
+ "android/soong/android"
+)
+
+func init() {
+ android.RegisterSingletonType("rustdoc", RustdocSingleton)
+}
+
+func RustdocSingleton() android.Singleton {
+ return &rustdocSingleton{}
+}
+
+type rustdocSingleton struct{}
+
+func (n *rustdocSingleton) GenerateBuildActions(ctx android.SingletonContext) {
+ ctx.VisitAllModules(func(module android.Module) {
+ if !module.Enabled() {
+ return
+ }
+
+ if m, ok := module.(*Module); ok {
+ if m.docTimestampFile.Valid() {
+ ctx.Phony("rustdoc", m.docTimestampFile.Path())
+ }
+ }
+ })
+}
diff --git a/rust/library.go b/rust/library.go
index 052fb3a..1bdf83a 100644
--- a/rust/library.go
+++ b/rust/library.go
@@ -432,14 +432,10 @@
func (library *libraryDecorator) compile(ctx ModuleContext, flags Flags, deps PathDeps) android.Path {
var outputFile android.ModuleOutPath
var fileName string
- var srcPath android.Path
+ srcPath := library.srcPath(ctx, deps)
if library.sourceProvider != nil {
- // Assume the first source from the source provider is the library entry point.
- srcPath = library.sourceProvider.Srcs()[0]
deps.srcProviderFiles = append(deps.srcProviderFiles, library.sourceProvider.Srcs()...)
- } else {
- srcPath, _ = srcPathFromModuleSrcs(ctx, library.baseCompiler.Properties.Srcs)
}
flags.RustFlags = append(flags.RustFlags, deps.depFlags...)
@@ -457,22 +453,22 @@
fileName = library.getStem(ctx) + ctx.toolchain().RlibSuffix()
outputFile = android.PathForModuleOut(ctx, fileName)
- TransformSrctoRlib(ctx, srcPath, deps, flags, outputFile, deps.linkDirs)
+ TransformSrctoRlib(ctx, srcPath, deps, flags, outputFile)
} else if library.dylib() {
fileName = library.getStem(ctx) + ctx.toolchain().DylibSuffix()
outputFile = android.PathForModuleOut(ctx, fileName)
- TransformSrctoDylib(ctx, srcPath, deps, flags, outputFile, deps.linkDirs)
+ TransformSrctoDylib(ctx, srcPath, deps, flags, outputFile)
} else if library.static() {
fileName = library.getStem(ctx) + ctx.toolchain().StaticLibSuffix()
outputFile = android.PathForModuleOut(ctx, fileName)
- TransformSrctoStatic(ctx, srcPath, deps, flags, outputFile, deps.linkDirs)
+ TransformSrctoStatic(ctx, srcPath, deps, flags, outputFile)
} else if library.shared() {
fileName = library.sharedLibFilename(ctx)
outputFile = android.PathForModuleOut(ctx, fileName)
- TransformSrctoShared(ctx, srcPath, deps, flags, outputFile, deps.linkDirs)
+ TransformSrctoShared(ctx, srcPath, deps, flags, outputFile)
}
if !library.rlib() && !library.static() && library.stripper.NeedsStrip(ctx) {
@@ -514,6 +510,31 @@
return outputFile
}
+func (library *libraryDecorator) srcPath(ctx ModuleContext, deps PathDeps) android.Path {
+ if library.sourceProvider != nil {
+ // Assume the first source from the source provider is the library entry point.
+ return library.sourceProvider.Srcs()[0]
+ } else {
+ path, _ := srcPathFromModuleSrcs(ctx, library.baseCompiler.Properties.Srcs)
+ return path
+ }
+}
+
+func (library *libraryDecorator) rustdoc(ctx ModuleContext, flags Flags,
+ deps PathDeps) android.OptionalPath {
+ // rustdoc has builtin support for documenting config specific information
+ // regardless of the actual config it was given
+ // (https://doc.rust-lang.org/rustdoc/advanced-features.html#cfgdoc-documenting-platform-specific-or-feature-specific-information),
+ // so we generate the rustdoc for only the primary module so that we have a
+ // single set of docs to refer to.
+ if ctx.Module() != ctx.PrimaryModule() {
+ return android.OptionalPath{}
+ }
+
+ return android.OptionalPathForPath(Rustdoc(ctx, library.srcPath(ctx, deps),
+ deps, flags))
+}
+
func (library *libraryDecorator) getStem(ctx ModuleContext) string {
stem := library.baseCompiler.getStemWithoutSuffix(ctx)
validateLibraryStem(ctx, stem, library.crateName())
diff --git a/rust/prebuilt.go b/rust/prebuilt.go
index 94fe1e5..49f3c0f 100644
--- a/rust/prebuilt.go
+++ b/rust/prebuilt.go
@@ -103,6 +103,12 @@
return srcPath
}
+func (prebuilt *prebuiltLibraryDecorator) rustdoc(ctx ModuleContext, flags Flags,
+ deps PathDeps) android.OptionalPath {
+
+ return android.OptionalPath{}
+}
+
func (prebuilt *prebuiltLibraryDecorator) compilerDeps(ctx DepsContext, deps Deps) Deps {
deps = prebuilt.baseCompiler.compilerDeps(ctx, deps)
return deps
diff --git a/rust/proc_macro.go b/rust/proc_macro.go
index 115045a..4eead32 100644
--- a/rust/proc_macro.go
+++ b/rust/proc_macro.go
@@ -68,7 +68,7 @@
outputFile := android.PathForModuleOut(ctx, fileName)
srcPath, _ := srcPathFromModuleSrcs(ctx, procMacro.baseCompiler.Properties.Srcs)
- TransformSrctoProcMacro(ctx, srcPath, deps, flags, outputFile, deps.linkDirs)
+ TransformSrctoProcMacro(ctx, srcPath, deps, flags, outputFile)
return outputFile
}
diff --git a/rust/rust.go b/rust/rust.go
index 9738b46..78a793d 100644
--- a/rust/rust.go
+++ b/rust/rust.go
@@ -58,6 +58,7 @@
RustFlags []string // Flags that apply to rust
LinkFlags []string // Flags that apply to linker
ClippyFlags []string // Flags that apply to clippy-driver, during the linting
+ RustdocFlags []string // Flags that apply to rustdoc
Toolchain config.Toolchain
Coverage bool
Clippy bool
@@ -124,6 +125,7 @@
// as a library. The stripped output which is used for installation can be found via
// compiler.strippedOutputFile if it exists.
unstrippedOutputFile android.OptionalPath
+ docTimestampFile android.OptionalPath
hideApexVariantFromMake bool
}
@@ -355,10 +357,12 @@
compile(ctx ModuleContext, flags Flags, deps PathDeps) android.Path
compilerDeps(ctx DepsContext, deps Deps) Deps
crateName() string
+ rustdoc(ctx ModuleContext, flags Flags, deps PathDeps) android.OptionalPath
// Output directory in which source-generated code from dependencies is
// copied. This is equivalent to Cargo's OUT_DIR variable.
CargoOutDir() android.OptionalPath
+
inData() bool
install(ctx ModuleContext)
relativeInstallPath() string
@@ -755,6 +759,8 @@
mod.unstrippedOutputFile = android.OptionalPathForPath(unstrippedOutputFile)
bloaty.MeasureSizeForPaths(ctx, mod.compiler.strippedOutputFilePath(), mod.unstrippedOutputFile)
+ mod.docTimestampFile = mod.compiler.rustdoc(ctx, flags, deps)
+
apexInfo := actx.Provider(android.ApexInfoProvider).(android.ApexInfo)
if mod.installable(apexInfo) {
mod.compiler.install(ctx)
diff --git a/sdk/java_sdk_test.go b/sdk/java_sdk_test.go
index 54916d8..6016981 100644
--- a/sdk/java_sdk_test.go
+++ b/sdk/java_sdk_test.go
@@ -1089,6 +1089,80 @@
)
}
+func TestSnapshotWithJavaSdkLibrary_CompileDex(t *testing.T) {
+ result := android.GroupFixturePreparers(prepareForSdkTestWithJavaSdkLibrary).RunTestWithBp(t, `
+ sdk {
+ name: "mysdk",
+ java_sdk_libs: ["myjavalib"],
+ }
+
+ java_sdk_library {
+ name: "myjavalib",
+ srcs: ["Test.java"],
+ sdk_version: "current",
+ shared_library: false,
+ compile_dex: true,
+ public: {
+ enabled: true,
+ },
+ system: {
+ enabled: true,
+ },
+ }
+ `)
+
+ CheckSnapshot(t, result, "mysdk", "",
+ checkUnversionedAndroidBpContents(`
+// This is auto-generated. DO NOT EDIT.
+
+java_sdk_library_import {
+ name: "myjavalib",
+ prefer: false,
+ visibility: ["//visibility:public"],
+ apex_available: ["//apex_available:platform"],
+ shared_library: false,
+ compile_dex: true,
+ public: {
+ jars: ["sdk_library/public/myjavalib-stubs.jar"],
+ stub_srcs: ["sdk_library/public/myjavalib_stub_sources"],
+ current_api: "sdk_library/public/myjavalib.txt",
+ removed_api: "sdk_library/public/myjavalib-removed.txt",
+ sdk_version: "current",
+ },
+ system: {
+ jars: ["sdk_library/system/myjavalib-stubs.jar"],
+ stub_srcs: ["sdk_library/system/myjavalib_stub_sources"],
+ current_api: "sdk_library/system/myjavalib.txt",
+ removed_api: "sdk_library/system/myjavalib-removed.txt",
+ sdk_version: "system_current",
+ },
+}
+`),
+ snapshotTestChecker(checkSnapshotWithSourcePreferred, func(t *testing.T, result *android.TestResult) {
+ ctx := android.ModuleInstallPathContextForTesting(result.Config)
+ dexJarBuildPath := func(name string, kind android.SdkKind) string {
+ dep := result.Module(name, "android_common").(java.SdkLibraryDependency)
+ path := dep.SdkApiStubDexJar(ctx, kind)
+ return path.RelativeToTop().String()
+ }
+
+ dexJarPath := dexJarBuildPath("myjavalib", android.SdkPublic)
+ android.AssertStringEquals(t, "source dex public stubs jar build path", "out/soong/.intermediates/myjavalib.stubs/android_common/dex/myjavalib.stubs.jar", dexJarPath)
+
+ dexJarPath = dexJarBuildPath("myjavalib", android.SdkSystem)
+ systemDexJar := "out/soong/.intermediates/myjavalib.stubs.system/android_common/dex/myjavalib.stubs.system.jar"
+ android.AssertStringEquals(t, "source dex system stubs jar build path", systemDexJar, dexJarPath)
+
+ // This should fall back to system as module is not available.
+ dexJarPath = dexJarBuildPath("myjavalib", android.SdkModule)
+ android.AssertStringEquals(t, "source dex module stubs jar build path", systemDexJar, dexJarPath)
+
+ dexJarPath = dexJarBuildPath(android.PrebuiltNameFromSource("myjavalib"), android.SdkPublic)
+ android.AssertStringEquals(t, "prebuilt dex public stubs jar build path", "out/soong/.intermediates/snapshot/prebuilt_myjavalib.stubs/android_common/dex/myjavalib.stubs.jar", dexJarPath)
+ }),
+ )
+}
+
func TestSnapshotWithJavaSdkLibrary_SdkVersion_None(t *testing.T) {
result := android.GroupFixturePreparers(prepareForSdkTestWithJavaSdkLibrary).RunTestWithBp(t, `
sdk {
diff --git a/tests/bootstrap_test.sh b/tests/bootstrap_test.sh
index 7cf7438..e45df06 100755
--- a/tests/bootstrap_test.sh
+++ b/tests/bootstrap_test.sh
@@ -126,7 +126,7 @@
# This test needs to start from a clean build, but setup creates an
# initialized tree that has already been built once. Clear the out
- # directory to start from scratch.
+ # directory to start from scratch (see b/185591972)
rm -rf out
mkdir -p a
diff --git a/tests/run_integration_tests.sh b/tests/run_integration_tests.sh
index db24037..76b324b 100755
--- a/tests/run_integration_tests.sh
+++ b/tests/run_integration_tests.sh
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/bin/bash -eu
TOP="$(readlink -f "$(dirname "$0")"/../../..)"
"$TOP/build/soong/tests/bootstrap_test.sh"