Merge "VNDK snapshot may provide LLNDK stub libraries"
diff --git a/android/bazel.go b/android/bazel.go
index cb3abff..2d4755f 100644
--- a/android/bazel.go
+++ b/android/bazel.go
@@ -231,7 +231,8 @@
"libpropertyinfoparser", // cparsons@, cc_library_static, wrong include paths
"libarm-optimized-routines-string", // jingwen@, cc_library_static, OK for bp2build but b/186615213 (asflags not handled in bp2build), version script assignment of 'LIBC' to symbol 'memcmp' failed: symbol not defined (also for memrchr, strnlen)
"fmtlib_ndk", // http://b/187040371, cc_library_static, OK for bp2build but format-inl.h:11:10: fatal error: 'cassert' file not found for mixed builds
- }
+ "libc_nomalloc", // cc_library_static, OK for bp2build but ld.lld: error: undefined symbol: pthread_mutex_lock (and others)
+ }
// Used for quicker lookups
bp2buildModuleDoNotConvert = map[string]bool{}
diff --git a/android/bazel_handler.go b/android/bazel_handler.go
index 63145bf..a1206dc 100644
--- a/android/bazel_handler.go
+++ b/android/bazel_handler.go
@@ -567,7 +567,7 @@
// Returns the path where the contents of the @soong_injection repository live.
// It is used by Soong to tell Bazel things it cannot over the command line.
func (p *bazelPaths) injectedFilesDir() string {
- return filepath.Join(p.buildDir, "soong_injection")
+ return filepath.Join(p.buildDir, bazel.SoongInjectionDirName)
}
// Returns the path of the synthetic Bazel workspace that contains a symlink
diff --git a/android/config.go b/android/config.go
index 79917ad..4847182 100644
--- a/android/config.go
+++ b/android/config.go
@@ -35,6 +35,7 @@
"github.com/google/blueprint/proptools"
"android/soong/android/soongconfig"
+ "android/soong/bazel"
"android/soong/remoteexec"
)
@@ -169,7 +170,7 @@
// loadFromConfigFile loads and decodes configuration options from a JSON file
// in the current working directory.
-func loadFromConfigFile(configurable jsonConfigurable, filename string) error {
+func loadFromConfigFile(configurable *productVariables, filename string) error {
// Try to open the file
configFileReader, err := os.Open(filename)
defer configFileReader.Close()
@@ -194,13 +195,20 @@
}
}
- // No error
- return nil
+ if Bool(configurable.GcovCoverage) && Bool(configurable.ClangCoverage) {
+ return fmt.Errorf("GcovCoverage and ClangCoverage cannot both be set")
+ }
+
+ configurable.Native_coverage = proptools.BoolPtr(
+ Bool(configurable.GcovCoverage) ||
+ Bool(configurable.ClangCoverage))
+
+ return saveToBazelConfigFile(configurable, filepath.Dir(filename))
}
// atomically writes the config file in case two copies of soong_build are running simultaneously
// (for example, docs generation and ninja manifest generation)
-func saveToConfigFile(config jsonConfigurable, filename string) error {
+func saveToConfigFile(config *productVariables, filename string) error {
data, err := json.MarshalIndent(&config, "", " ")
if err != nil {
return fmt.Errorf("cannot marshal config data: %s", err.Error())
@@ -229,6 +237,35 @@
return nil
}
+func saveToBazelConfigFile(config *productVariables, outDir string) error {
+ dir := filepath.Join(outDir, bazel.SoongInjectionDirName, "product_config")
+ err := createDirIfNonexistent(dir, os.ModePerm)
+ if err != nil {
+ return fmt.Errorf("Could not create dir %s: %s", dir, err)
+ }
+
+ data, 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",
+ }
+ err = ioutil.WriteFile(filepath.Join(dir, "product_variables.bzl"), []byte(strings.Join(bzl, "\n")), 0644)
+ if err != nil {
+ return fmt.Errorf("Could not write .bzl config file %s", err)
+ }
+ err = ioutil.WriteFile(filepath.Join(dir, "BUILD"), []byte(bazel.GeneratedBazelFileWarning), 0644)
+ if err != nil {
+ return fmt.Errorf("Could not write BUILD config file %s", err)
+ }
+
+ return nil
+}
+
// NullConfig returns a mostly empty Config for use by standalone tools like dexpreopt_gen that
// use the android package.
func NullConfig(buildDir string) Config {
@@ -448,14 +485,6 @@
config.AndroidFirstDeviceTarget = firstTarget(config.Targets[Android], "lib64", "lib32")[0]
}
- if Bool(config.productVariables.GcovCoverage) && Bool(config.productVariables.ClangCoverage) {
- return Config{}, fmt.Errorf("GcovCoverage and ClangCoverage cannot both be set")
- }
-
- config.productVariables.Native_coverage = proptools.BoolPtr(
- Bool(config.productVariables.GcovCoverage) ||
- Bool(config.productVariables.ClangCoverage))
-
config.BazelContext, err = NewBazelContext(config)
config.bp2buildPackageConfig = bp2buildDefaultConfig
config.bp2buildModuleTypeConfig = make(map[string]bool)
diff --git a/android/paths.go b/android/paths.go
index fb75117..88d625a 100644
--- a/android/paths.go
+++ b/android/paths.go
@@ -1990,6 +1990,10 @@
func CreateOutputDirIfNonexistent(path WritablePath, perm os.FileMode) error {
dir := absolutePath(path.String())
+ return createDirIfNonexistent(dir, perm)
+}
+
+func createDirIfNonexistent(dir string, perm os.FileMode) error {
if _, err := os.Stat(dir); os.IsNotExist(err) {
return os.MkdirAll(dir, os.ModePerm)
} else {
diff --git a/android/variable.go b/android/variable.go
index e830845..672576a 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -282,7 +282,7 @@
NativeCoverageExcludePaths []string `json:",omitempty"`
// Set by NewConfig
- Native_coverage *bool
+ Native_coverage *bool `json:",omitempty"`
SanitizeHost []string `json:",omitempty"`
SanitizeDevice []string `json:",omitempty"`
diff --git a/apex/apex.go b/apex/apex.go
index 790f2e8..da4f472 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -2153,7 +2153,10 @@
// Get the dexBootJar from the bootclasspath_fragment as that is responsible for performing the
// hidden API encpding.
- dexBootJar := bootclasspathFragmentInfo.DexBootJarPathForContentModule(javaModule)
+ dexBootJar, err := bootclasspathFragmentInfo.DexBootJarPathForContentModule(javaModule)
+ if err != nil {
+ ctx.ModuleErrorf("%s", err)
+ }
// Create an apexFile as for a normal java module but with the dex boot jar provided by the
// bootclasspath_fragment.
diff --git a/apex/bootclasspath_fragment_test.go b/apex/bootclasspath_fragment_test.go
index 7f5e15c..9a8c7d0 100644
--- a/apex/bootclasspath_fragment_test.go
+++ b/apex/bootclasspath_fragment_test.go
@@ -512,7 +512,10 @@
checkFragmentExportedDexJar := func(name string, expectedDexJar string) {
module := result.Module(name, "android_common_apex10000")
- dexJar := info.DexBootJarPathForContentModule(module)
+ dexJar, err := info.DexBootJarPathForContentModule(module)
+ if err != nil {
+ t.Error(err)
+ }
android.AssertPathRelativeToTopEquals(t, name+" dex", expectedDexJar, dexJar)
expectedCopyCommand := fmt.Sprintf("&& cp -f %s out/soong/.intermediates/myapex/android_common_myapex_image/image.apex/javalib/%s.jar", expectedDexJar, name)
diff --git a/bazel/constants.go b/bazel/constants.go
index 15c75cf..6beb496 100644
--- a/bazel/constants.go
+++ b/bazel/constants.go
@@ -18,6 +18,10 @@
// Run bazel as a ninja executer
BazelNinjaExecRunName = RunName("bazel-ninja-exec")
+
+ SoongInjectionDirName = "soong_injection"
+
+ GeneratedBazelFileWarning = "# GENERATED FOR BAZEL FROM SOONG. DO NOT EDIT"
)
// String returns the name of the run.
diff --git a/bp2build/bp2build.go b/bp2build/bp2build.go
index 59c5acd..ee36982 100644
--- a/bp2build/bp2build.go
+++ b/bp2build/bp2build.go
@@ -16,6 +16,7 @@
import (
"android/soong/android"
+ "android/soong/bazel"
"fmt"
"os"
)
@@ -32,7 +33,7 @@
bp2buildFiles := CreateBazelFiles(nil, buildToTargets, ctx.mode)
writeFiles(ctx, bp2buildDir, bp2buildFiles)
- soongInjectionDir := android.PathForOutput(ctx, "soong_injection")
+ soongInjectionDir := android.PathForOutput(ctx, bazel.SoongInjectionDirName)
writeFiles(ctx, soongInjectionDir, CreateSoongInjectionFiles())
return metrics
diff --git a/java/base.go b/java/base.go
index 0d2f1ac..f7989b8 100644
--- a/java/base.go
+++ b/java/base.go
@@ -1217,12 +1217,6 @@
return
}
- // Initialize the hiddenapi structure.
- j.initHiddenAPI(ctx, dexOutputFile, j.implementationJarFile, j.dexProperties.Uncompress_dex)
-
- // Encode hidden API flags in dex file.
- dexOutputFile = j.hiddenAPIEncodeDex(ctx, dexOutputFile)
-
// merge dex jar with resources if necessary
if j.resourceJar != nil {
jars := android.Paths{dexOutputFile, j.resourceJar}
@@ -1238,6 +1232,12 @@
}
}
+ // Initialize the hiddenapi structure.
+ j.initHiddenAPI(ctx, dexOutputFile, j.implementationJarFile, j.dexProperties.Uncompress_dex)
+
+ // Encode hidden API flags in dex file, if needed.
+ dexOutputFile = j.hiddenAPIEncodeDex(ctx, dexOutputFile)
+
j.dexJarFile = dexOutputFile
// Dexpreopting
diff --git a/java/bootclasspath_fragment.go b/java/bootclasspath_fragment.go
index 5d8a8e5..6b395fb 100644
--- a/java/bootclasspath_fragment.go
+++ b/java/bootclasspath_fragment.go
@@ -273,6 +273,10 @@
// Will be nil if the BootclasspathFragmentApexContentInfo has not been provided for a specific module. That can occur
// when SkipDexpreoptBootJars(ctx) returns true.
imageConfig *bootImageConfig
+
+ // Map from the name of the context module (as returned by Name()) to the hidden API encoded dex
+ // jar path.
+ contentModuleDexJarPaths map[string]android.Path
}
func (i BootclasspathFragmentApexContentInfo) Modules() android.ConfiguredJarList {
@@ -299,10 +303,14 @@
// DexBootJarPathForContentModule returns the path to the dex boot jar for specified module.
//
// The dex boot jar is one which has had hidden API encoding performed on it.
-func (i BootclasspathFragmentApexContentInfo) DexBootJarPathForContentModule(module android.Module) android.Path {
- j := module.(UsesLibraryDependency)
- dexJar := j.DexJarBuildPath()
- return dexJar
+func (i BootclasspathFragmentApexContentInfo) DexBootJarPathForContentModule(module android.Module) (android.Path, error) {
+ name := module.Name()
+ if dexJar, ok := i.contentModuleDexJarPaths[name]; ok {
+ return dexJar, nil
+ } else {
+ return nil, fmt.Errorf("unknown bootclasspath_fragment content module %s, expected one of %s",
+ name, strings.Join(android.SortedStringKeys(i.contentModuleDexJarPaths), ", "))
+ }
}
func (b *BootclasspathFragmentModule) DepIsInSameApex(ctx android.BaseModuleContext, dep android.Module) bool {
@@ -380,6 +388,28 @@
// Perform hidden API processing.
b.generateHiddenAPIBuildActions(ctx, contents)
+ // Verify that the image_name specified on a bootclasspath_fragment is valid even if this is a
+ // prebuilt which will not use the image config.
+ imageConfig := b.getImageConfig(ctx)
+
+ // A prebuilt fragment cannot contribute to the apex.
+ if !android.IsModulePrebuilt(ctx.Module()) {
+ // Provide the apex content info.
+ b.provideApexContentInfo(ctx, imageConfig, contents)
+ }
+}
+
+// provideApexContentInfo creates, initializes and stores the apex content info for use by other
+// modules.
+func (b *BootclasspathFragmentModule) provideApexContentInfo(ctx android.ModuleContext, imageConfig *bootImageConfig, contents []android.Module) {
+ // Construct the apex content info from the config.
+ info := BootclasspathFragmentApexContentInfo{
+ imageConfig: imageConfig,
+ }
+
+ // Populate the apex content info with paths to the dex jars.
+ b.populateApexContentInfoDexJars(ctx, &info, contents)
+
if !SkipDexpreoptBootJars(ctx) {
// Force the GlobalSoongConfig to be created and cached for use by the dex_bootjars
// GenerateSingletonBuildActions method as it cannot create it for itself.
@@ -387,11 +417,20 @@
// Only generate the boot image if the configuration does not skip it.
b.generateBootImageBuildActions(ctx, contents)
+ }
- // Make the boot image info available for other modules
- ctx.SetProvider(BootclasspathFragmentApexContentInfoProvider, BootclasspathFragmentApexContentInfo{
- imageConfig: b.getImageConfig(ctx),
- })
+ // Make the apex content info available for other modules.
+ ctx.SetProvider(BootclasspathFragmentApexContentInfoProvider, info)
+}
+
+// populateApexContentInfoDexJars adds paths to the dex jars provided by this fragment to the
+// apex content info.
+func (b *BootclasspathFragmentModule) populateApexContentInfoDexJars(ctx android.ModuleContext, info *BootclasspathFragmentApexContentInfo, contents []android.Module) {
+ info.contentModuleDexJarPaths = map[string]android.Path{}
+ for _, m := range contents {
+ j := m.(UsesLibraryDependency)
+ dexJar := j.DexJarBuildPath()
+ info.contentModuleDexJarPaths[m.Name()] = dexJar
}
}
diff --git a/java/dexpreopt_test.go b/java/dexpreopt_test.go
index f065534..b25dece 100644
--- a/java/dexpreopt_test.go
+++ b/java/dexpreopt_test.go
@@ -173,6 +173,11 @@
}
func TestDex2oatToolDeps(t *testing.T) {
+ if android.BuildOs != android.Linux {
+ // The host binary paths checked below are build OS dependent.
+ t.Skipf("Unsupported build OS %s", android.BuildOs)
+ }
+
preparers := android.GroupFixturePreparers(
cc.PrepareForTestWithCcDefaultModules,
PrepareForTestWithJavaDefaultModulesWithoutFakeDex2oatd,
diff --git a/java/hiddenapi.go b/java/hiddenapi.go
index 1e83824..c9e3c29 100644
--- a/java/hiddenapi.go
+++ b/java/hiddenapi.go
@@ -235,7 +235,7 @@
echo "--output-dex=$tmpDir/dex-output/$$(basename $${INPUT_DEX})";
done | xargs ${config.HiddenAPI} encode --api-flags=$flagsCsv $hiddenapiFlags &&
${config.SoongZipCmd} $soongZipFlags -o $tmpDir/dex.jar -C $tmpDir/dex-output -f "$tmpDir/dex-output/classes*.dex" &&
- ${config.MergeZipsCmd} -D -zipToNotStrip $tmpDir/dex.jar -stripFile "classes*.dex" -stripFile "**/*.uau" $out $tmpDir/dex.jar $in`,
+ ${config.MergeZipsCmd} -j -D -zipToNotStrip $tmpDir/dex.jar -stripFile "classes*.dex" -stripFile "**/*.uau" $out $tmpDir/dex.jar $in`,
CommandDeps: []string{
"${config.HiddenAPI}",
"${config.SoongZipCmd}",
diff --git a/tests/lib.sh b/tests/lib.sh
index e561a3d..35ccea9 100644
--- a/tests/lib.sh
+++ b/tests/lib.sh
@@ -114,6 +114,7 @@
symlink_directory prebuilts/jdk
symlink_file WORKSPACE
+ symlink_file BUILD
symlink_file tools/bazel
}