Merge "No clang-analyzer-* checks by default for generated files"
diff --git a/OWNERS b/OWNERS
index f15bd32..f0ccd82 100644
--- a/OWNERS
+++ b/OWNERS
@@ -3,13 +3,18 @@
# AMER
ahumesky@google.com
+alexmarquez@google.com
asmundak@google.com
ccross@android.com
cparsons@google.com
dwillemsen@google.com
eakammer@google.com
+jobredeaux@google.com
joeo@google.com
+lamontjones@google.com
spandandas@google.com
+weiwli@google.com
+yudiliu@google.com
yuntaoxu@google.com
# APAC
diff --git a/README.md b/README.md
index 10ddd73..e92349e 100644
--- a/README.md
+++ b/README.md
@@ -451,15 +451,10 @@
The values of the variables can be set from a product's `BoardConfig.mk` file:
```
-SOONG_CONFIG_NAMESPACES += acme
-SOONG_CONFIG_acme += \
- board \
- feature \
- width \
-
-SOONG_CONFIG_acme_board := soc_a
-SOONG_CONFIG_acme_feature := true
-SOONG_CONFIG_acme_width := 200
+$(call add_soong_config_namespace, acme)
+$(call add_soong_config_var_value, acme, board, soc_a)
+$(call add_soong_config_var_value, acme, feature, true)
+$(call add_soong_config_var_value, acme, width, 200)
```
The `acme_cc_defaults` module type can be used anywhere after the definition in
diff --git a/android/androidmk.go b/android/androidmk.go
index f032f1b..9853d2c 100644
--- a/android/androidmk.go
+++ b/android/androidmk.go
@@ -571,7 +571,7 @@
if host {
makeOs := amod.Os().String()
- if amod.Os() == Linux || amod.Os() == LinuxBionic {
+ if amod.Os() == Linux || amod.Os() == LinuxBionic || amod.Os() == LinuxMusl {
makeOs = "linux"
}
a.SetString("LOCAL_MODULE_HOST_OS", makeOs)
diff --git a/android/bazel.go b/android/bazel.go
index fa19e52..b01bd70 100644
--- a/android/bazel.go
+++ b/android/bazel.go
@@ -137,12 +137,14 @@
// build/bazel explicitly.
"build/bazel":/* recursive = */ false,
"build/bazel/examples/android_app":/* recursive = */ true,
+ "build/bazel/examples/java":/* recursive = */ true,
"build/bazel/bazel_skylib":/* recursive = */ true,
"build/bazel/rules":/* recursive = */ true,
"build/bazel/rules_cc":/* recursive = */ true,
"build/bazel/tests":/* recursive = */ true,
"build/bazel/platforms":/* recursive = */ true,
"build/bazel/product_variables":/* recursive = */ true,
+ "build/bazel_common_rules":/* recursive = */ true,
"build/pesto":/* recursive = */ true,
// external/bazelbuild-rules_android/... is needed by mixed builds, otherwise mixed builds analysis fails
diff --git a/android/bazel_handler.go b/android/bazel_handler.go
index 312f009..9c922dd 100644
--- a/android/bazel_handler.go
+++ b/android/bazel_handler.go
@@ -106,7 +106,7 @@
bazelPath string
outputBase string
workspaceDir string
- buildDir string
+ soongOutDir string
metricsDir string
}
@@ -254,7 +254,7 @@
func bazelPathsFromConfig(c *config) (*bazelPaths, error) {
p := bazelPaths{
- buildDir: c.buildDir,
+ soongOutDir: c.soongOutDir,
}
missingEnvVars := []string{}
if len(c.Getenv("BAZEL_HOME")) > 1 {
@@ -353,7 +353,16 @@
// the invocation returned an error code.
func (r *builtinBazelRunner) issueBazelCommand(paths *bazelPaths, runName bazel.RunName, command bazelCommand,
extraFlags ...string) (string, string, error) {
- cmdFlags := []string{"--output_base=" + absolutePath(paths.outputBase), command.command}
+ cmdFlags := []string{
+ // --noautodetect_server_javabase has the practical consequence of preventing Bazel from
+ // attempting to download rules_java, which is incompatible with
+ // --experimental_repository_disable_download set further below.
+ // rules_java is also not needed until mixed builds start building java targets.
+ // TODO(b/197958133): Once rules_java is pulled into AOSP, remove this flag.
+ "--noautodetect_server_javabase",
+ "--output_base=" + absolutePath(paths.outputBase),
+ command.command,
+ }
cmdFlags = append(cmdFlags, command.expression)
cmdFlags = append(cmdFlags, "--profile="+shared.BazelMetricsFilename(paths, runName))
@@ -382,7 +391,7 @@
bazelCmd.Env = append(os.Environ(),
"HOME="+paths.homeDir,
pwdPrefix(),
- "BUILD_DIR="+absolutePath(paths.buildDir),
+ "BUILD_DIR="+absolutePath(paths.soongOutDir),
// Make OUT_DIR absolute here so tools/bazel.sh uses the correct
// OUT_DIR at <root>/out, instead of <root>/out/soong/workspace/out.
"OUT_DIR="+absolutePath(paths.outDir()),
@@ -599,24 +608,24 @@
// Returns a path containing build-related metadata required for interfacing
// with Bazel. Example: out/soong/bazel.
func (p *bazelPaths) intermediatesDir() string {
- return filepath.Join(p.buildDir, "bazel")
+ return filepath.Join(p.soongOutDir, "bazel")
}
// 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, bazel.SoongInjectionDirName)
+ return filepath.Join(p.soongOutDir, bazel.SoongInjectionDirName)
}
// Returns the path of the synthetic Bazel workspace that contains a symlink
// forest composed the whole source tree and BUILD files generated by bp2build.
func (p *bazelPaths) syntheticWorkspaceDir() string {
- return filepath.Join(p.buildDir, "workspace")
+ return filepath.Join(p.soongOutDir, "workspace")
}
// Returns the path to the top level out dir ($OUT_DIR).
func (p *bazelPaths) outDir() string {
- return filepath.Dir(p.buildDir)
+ return filepath.Dir(p.soongOutDir)
}
// Issues commands to Bazel to receive results for all cquery requests
diff --git a/android/bazel_handler_test.go b/android/bazel_handler_test.go
index f1fabec..557faea 100644
--- a/android/bazel_handler_test.go
+++ b/android/bazel_handler_test.go
@@ -101,7 +101,7 @@
func testBazelContext(t *testing.T, bazelCommandResults map[bazelCommand]string) (*bazelContext, string) {
t.Helper()
p := bazelPaths{
- buildDir: t.TempDir(),
+ soongOutDir: t.TempDir(),
outputBase: "outputbase",
workspaceDir: "workspace_dir",
}
@@ -114,5 +114,5 @@
bazelRunner: runner,
paths: &p,
requests: map[cqueryKey]bool{},
- }, p.buildDir
+ }, p.soongOutDir
}
diff --git a/android/bazel_paths.go b/android/bazel_paths.go
index c09d218..a4bd2ef 100644
--- a/android/bazel_paths.go
+++ b/android/bazel_paths.go
@@ -414,7 +414,7 @@
}
outputPath := OutputPath{basePath{"", ""},
- ctx.Config().buildDir,
+ ctx.Config().soongOutDir,
ctx.Config().BazelContext.OutputBase()}
return BazelOutPath{
diff --git a/android/config.go b/android/config.go
index 35403b8..b69963f 100644
--- a/android/config.go
+++ b/android/config.go
@@ -67,12 +67,12 @@
}
// BuildDir returns the build output directory for the configuration.
-func (c Config) BuildDir() string {
- return c.buildDir
+func (c Config) SoongOutDir() string {
+ return c.soongOutDir
}
-func (c Config) NinjaBuildDir() string {
- return c.buildDir
+func (c Config) OutDir() string {
+ return c.soongOutDir
}
func (c Config) DebugCompilation() bool {
@@ -122,7 +122,7 @@
deviceConfig *deviceConfig
- buildDir string // the path of the build output directory
+ soongOutDir string // the path of the build output directory
moduleListFile string // the path to the file which lists blueprint files to parse.
env map[string]string
@@ -283,11 +283,11 @@
// NullConfig returns a mostly empty Config for use by standalone tools like dexpreopt_gen that
// use the android package.
-func NullConfig(buildDir string) Config {
+func NullConfig(soongOutDir string) Config {
return Config{
config: &config{
- buildDir: buildDir,
- fs: pathtools.OsFs,
+ soongOutDir: soongOutDir,
+ fs: pathtools.OsFs,
},
}
}
@@ -319,7 +319,7 @@
ShippingApiLevel: stringPtr("30"),
},
- buildDir: buildDir,
+ soongOutDir: buildDir,
captureBuild: true,
env: envCopy,
@@ -397,7 +397,7 @@
// multiple runs in the same program execution is carried over (such as Bazel
// context or environment deps).
func ConfigForAdditionalRun(c Config) (Config, error) {
- newConfig, err := NewConfig(c.buildDir, c.moduleListFile, c.env)
+ newConfig, err := NewConfig(c.soongOutDir, c.moduleListFile, c.env)
if err != nil {
return Config{}, err
}
@@ -408,14 +408,14 @@
// NewConfig creates a new Config object. The srcDir argument specifies the path
// to the root source directory. It also loads the config file, if found.
-func NewConfig(buildDir string, moduleListFile string, availableEnv map[string]string) (Config, error) {
+func NewConfig(soongOutDir string, moduleListFile string, availableEnv map[string]string) (Config, error) {
// Make a config with default options.
config := &config{
- ProductVariablesFileName: filepath.Join(buildDir, productVariablesFileName),
+ ProductVariablesFileName: filepath.Join(soongOutDir, productVariablesFileName),
env: availableEnv,
- buildDir: buildDir,
+ soongOutDir: soongOutDir,
multilibConflicts: make(map[ArchType]bool),
moduleListFile: moduleListFile,
@@ -428,7 +428,7 @@
// Soundness check of the build and source directories. This won't catch strange
// configurations with symlinks, but at least checks the obvious case.
- absBuildDir, err := filepath.Abs(buildDir)
+ absBuildDir, err := filepath.Abs(soongOutDir)
if err != nil {
return Config{}, err
}
@@ -448,7 +448,7 @@
return Config{}, err
}
- KatiEnabledMarkerFile := filepath.Join(buildDir, ".soong.kati_enabled")
+ KatiEnabledMarkerFile := filepath.Join(soongOutDir, ".soong.kati_enabled")
if _, err := os.Stat(absolutePath(KatiEnabledMarkerFile)); err == nil {
config.katiEnabled = true
}
@@ -556,7 +556,7 @@
// BlueprintToolLocation returns the directory containing build system tools
// from Blueprint, like soong_zip and merge_zips.
func (c *config) BlueprintToolLocation() string {
- return filepath.Join(c.buildDir, "host", c.PrebuiltOS(), "bin")
+ return filepath.Join(c.soongOutDir, "host", c.PrebuiltOS(), "bin")
}
var _ bootstrap.ConfigBlueprintToolLocation = (*config)(nil)
@@ -1665,8 +1665,9 @@
return ConfiguredJarList{apexes, jars}
}
-// Filter keeps the entries if a jar appears in the given list of jars to keep; returns a new list.
-func (l *ConfiguredJarList) Filter(jarsToKeep []string) ConfiguredJarList {
+// Filter keeps the entries if a jar appears in the given list of jars to keep. Returns a new list
+// and any remaining jars that are not on this list.
+func (l *ConfiguredJarList) Filter(jarsToKeep []string) (ConfiguredJarList, []string) {
var apexes []string
var jars []string
@@ -1677,7 +1678,7 @@
}
}
- return ConfiguredJarList{apexes, jars}
+ return ConfiguredJarList{apexes, jars}, RemoveListFromList(jarsToKeep, jars)
}
// CopyOfJars returns a copy of the list of strings containing jar module name
diff --git a/android/fixture.go b/android/fixture.go
index fd051a7..728f031 100644
--- a/android/fixture.go
+++ b/android/fixture.go
@@ -834,7 +834,7 @@
func (r *TestResult) NormalizePathForTesting(path Path) string {
pathContext := PathContextForTesting(r.Config)
pathAsString := path.String()
- if rel, isRel := MaybeRel(pathContext, r.Config.BuildDir(), pathAsString); isRel {
+ if rel, isRel := MaybeRel(pathContext, r.Config.SoongOutDir(), pathAsString); isRel {
return rel
}
return pathAsString
diff --git a/android/module.go b/android/module.go
index b571f15..cc03418 100644
--- a/android/module.go
+++ b/android/module.go
@@ -986,10 +986,13 @@
// Device is built by default. Host and HostCross are not supported.
DeviceSupported = deviceSupported | deviceDefault
- // Device is built by default. Host and HostCross are supported.
+ // By default, _only_ device variant is built. Device variant can be disabled with `device_supported: false`
+ // Host and HostCross are disabled by default and can be enabled with `host_supported: true`
HostAndDeviceSupported = hostSupported | hostCrossSupported | deviceSupported | deviceDefault
// Host, HostCross, and Device are built by default.
+ // Building Device can be disabled with `device_supported: false`
+ // Building Host and HostCross can be disabled with `host_supported: false`
HostAndDeviceDefault = hostSupported | hostCrossSupported | hostDefault |
deviceSupported | deviceDefault
diff --git a/android/paths.go b/android/paths.go
index 71caaab..a733558 100644
--- a/android/paths.go
+++ b/android/paths.go
@@ -186,13 +186,13 @@
// A standard build has the following structure:
// ../top/
// out/ - make install files go here.
- // out/soong - this is the buildDir passed to NewTestConfig()
+ // out/soong - this is the soongOutDir passed to NewTestConfig()
// ... - the source files
//
// This function converts a path so that it appears relative to the ../top/ directory, i.e.
- // * Make install paths, which have the pattern "buildDir/../<path>" are converted into the top
+ // * Make install paths, which have the pattern "soongOutDir/../<path>" are converted into the top
// relative path "out/<path>"
- // * Soong install paths and other writable paths, which have the pattern "buildDir/<path>" are
+ // * Soong install paths and other writable paths, which have the pattern "soongOutDir/<path>" are
// converted into the top relative path "out/soong/<path>".
// * Source paths are already relative to the top.
// * Phony paths are not relative to anything.
@@ -211,7 +211,7 @@
Path
// return the path to the build directory.
- getBuildDir() string
+ getSoongOutDir() string
// the writablePath method doesn't directly do anything,
// but it allows a struct to distinguish between whether or not it implements the WritablePath interface
@@ -992,7 +992,7 @@
}
// absolute path already checked by validateSafePath
- if strings.HasPrefix(ret.String(), ctx.Config().buildDir) {
+ if strings.HasPrefix(ret.String(), ctx.Config().soongOutDir) {
return ret, fmt.Errorf("source path %q is in output", ret.String())
}
@@ -1008,7 +1008,7 @@
}
// absolute path already checked by validatePath
- if strings.HasPrefix(ret.String(), ctx.Config().buildDir) {
+ if strings.HasPrefix(ret.String(), ctx.Config().soongOutDir) {
return ret, fmt.Errorf("source path %q is in output", ret.String())
}
@@ -1151,7 +1151,7 @@
basePath
// The soong build directory, i.e. Config.BuildDir()
- buildDir string
+ soongOutDir string
fullPath string
}
@@ -1167,8 +1167,8 @@
return p
}
-func (p OutputPath) getBuildDir() string {
- return p.buildDir
+func (p OutputPath) getSoongOutDir() string {
+ return p.soongOutDir
}
func (p OutputPath) RelativeToTop() Path {
@@ -1176,8 +1176,8 @@
}
func (p OutputPath) outputPathRelativeToTop() OutputPath {
- p.fullPath = StringPathRelativeToTop(p.buildDir, p.fullPath)
- p.buildDir = OutSoongDir
+ p.fullPath = StringPathRelativeToTop(p.soongOutDir, p.fullPath)
+ p.soongOutDir = OutSoongDir
return p
}
@@ -1218,12 +1218,12 @@
if err != nil {
reportPathError(ctx, err)
}
- fullPath := filepath.Join(ctx.Config().buildDir, path)
+ fullPath := filepath.Join(ctx.Config().soongOutDir, path)
path = fullPath[len(fullPath)-len(path):]
- return OutputPath{basePath{path, ""}, ctx.Config().buildDir, fullPath}
+ return OutputPath{basePath{path, ""}, ctx.Config().soongOutDir, fullPath}
}
-// PathsForOutput returns Paths rooted from buildDir
+// PathsForOutput returns Paths rooted from soongOutDir
func PathsForOutput(ctx PathContext, paths []string) WritablePaths {
ret := make(WritablePaths, len(paths))
for i, path := range paths {
@@ -1545,7 +1545,7 @@
basePath
// The soong build directory, i.e. Config.BuildDir()
- buildDir string
+ soongOutDir string
// partitionDir is the part of the InstallPath that is automatically determined according to the context.
// For example, it is host/<os>-<arch> for host modules, and target/product/<device>/<partition> for device modules.
@@ -1565,12 +1565,12 @@
func (p InstallPath) RelativeToTop() Path {
ensureTestOnly()
- p.buildDir = OutSoongDir
+ p.soongOutDir = OutSoongDir
return p
}
-func (p InstallPath) getBuildDir() string {
- return p.buildDir
+func (p InstallPath) getSoongOutDir() string {
+ return p.soongOutDir
}
func (p InstallPath) ReplaceExtension(ctx PathContext, ext string) OutputPath {
@@ -1585,9 +1585,9 @@
func (p InstallPath) String() string {
if p.makePath {
// Make path starts with out/ instead of out/soong.
- return filepath.Join(p.buildDir, "../", p.path)
+ return filepath.Join(p.soongOutDir, "../", p.path)
} else {
- return filepath.Join(p.buildDir, p.path)
+ return filepath.Join(p.soongOutDir, p.path)
}
}
@@ -1596,9 +1596,9 @@
// The ./soong is dropped if the install path is for Make.
func (p InstallPath) PartitionDir() string {
if p.makePath {
- return filepath.Join(p.buildDir, "../", p.partitionDir)
+ return filepath.Join(p.soongOutDir, "../", p.partitionDir)
} else {
- return filepath.Join(p.buildDir, p.partitionDir)
+ return filepath.Join(p.soongOutDir, p.partitionDir)
}
}
@@ -1694,7 +1694,7 @@
base := InstallPath{
basePath: basePath{partionPath, ""},
- buildDir: ctx.Config().buildDir,
+ soongOutDir: ctx.Config().soongOutDir,
partitionDir: partionPath,
makePath: false,
}
@@ -1705,7 +1705,7 @@
func pathForNdkOrSdkInstall(ctx PathContext, prefix string, paths []string) InstallPath {
base := InstallPath{
basePath: basePath{prefix, ""},
- buildDir: ctx.Config().buildDir,
+ soongOutDir: ctx.Config().soongOutDir,
partitionDir: prefix,
makePath: false,
}
@@ -1851,7 +1851,7 @@
func (p PhonyPath) writablePath() {}
-func (p PhonyPath) getBuildDir() string {
+func (p PhonyPath) getSoongOutDir() string {
// A phone path cannot contain any / so cannot be relative to the build directory.
return ""
}
diff --git a/android/singleton.go b/android/singleton.go
index bb6614d..7ff96c9 100644
--- a/android/singleton.go
+++ b/android/singleton.go
@@ -54,10 +54,10 @@
RequireNinjaVersion(major, minor, micro int)
- // SetNinjaBuildDir sets the value of the top-level "builddir" Ninja variable
+ // SetOutDir sets the value of the top-level "builddir" Ninja variable
// that controls where Ninja stores its build log files. This value can be
// set at most one time for a single build, later calls are ignored.
- SetNinjaBuildDir(pctx PackageContext, value string)
+ SetOutDir(pctx PackageContext, value string)
// Eval takes a string with embedded ninja variables, and returns a string
// with all of the variables recursively expanded. Any variables references
@@ -180,8 +180,8 @@
addPhony(s.Config(), name, deps...)
}
-func (s *singletonContextAdaptor) SetNinjaBuildDir(pctx PackageContext, value string) {
- s.SingletonContext.SetNinjaBuildDir(pctx.PackageContext, value)
+func (s *singletonContextAdaptor) SetOutDir(pctx PackageContext, value string) {
+ s.SingletonContext.SetOutDir(pctx.PackageContext, value)
}
func (s *singletonContextAdaptor) Eval(pctx PackageContext, ninjaStr string) (string, error) {
diff --git a/android/soong_config_modules.go b/android/soong_config_modules.go
index 289e910..17f6d66 100644
--- a/android/soong_config_modules.go
+++ b/android/soong_config_modules.go
@@ -122,15 +122,10 @@
// }
//
// If an acme BoardConfig.mk file contained:
-//
-// SOONG_CONFIG_NAMESPACES += acme
-// SOONG_CONFIG_acme += \
-// board \
-// feature \
-//
-// SOONG_CONFIG_acme_board := soc_a
-// SOONG_CONFIG_acme_feature := true
-// SOONG_CONFIG_acme_width := 200
+// $(call add_sonng_config_namespace, acme)
+// $(call add_soong_config_var_value, acme, board, soc_a)
+// $(call add_soong_config_var_value, acme, feature, true)
+// $(call add_soong_config_var_value, acme, width, 200)
//
// Then libacme_foo would build with cflags "-DGENERIC -DSOC_A -DFEATURE -DWIDTH=200".
//
diff --git a/android/test_asserts.go b/android/test_asserts.go
index edeb408..064f656 100644
--- a/android/test_asserts.go
+++ b/android/test_asserts.go
@@ -77,14 +77,14 @@
// StringPathRelativeToTop on the actual string path.
func AssertStringPathRelativeToTopEquals(t *testing.T, message string, config Config, expected string, actual string) {
t.Helper()
- AssertStringEquals(t, message, expected, StringPathRelativeToTop(config.buildDir, actual))
+ AssertStringEquals(t, message, expected, StringPathRelativeToTop(config.soongOutDir, actual))
}
// AssertStringPathsRelativeToTopEquals checks if the expected value is equal to the result of
// calling StringPathsRelativeToTop on the actual string paths.
func AssertStringPathsRelativeToTopEquals(t *testing.T, message string, config Config, expected []string, actual []string) {
t.Helper()
- AssertDeepEquals(t, message, expected, StringPathsRelativeToTop(config.buildDir, actual))
+ AssertDeepEquals(t, message, expected, StringPathsRelativeToTop(config.soongOutDir, actual))
}
// AssertErrorMessageEquals checks if the error is not nil and has the expected message. If it does
diff --git a/android/testing.go b/android/testing.go
index 6ba8e3c..e25e5c5 100644
--- a/android/testing.go
+++ b/android/testing.go
@@ -664,15 +664,15 @@
// containing at most one instance of the temporary build directory at the start of the path while
// this assumes that there can be any number at any position.
func normalizeStringRelativeToTop(config Config, s string) string {
- // The buildDir usually looks something like: /tmp/testFoo2345/001
+ // The soongOutDir usually looks something like: /tmp/testFoo2345/001
//
- // Replace any usage of the buildDir with out/soong, e.g. replace "/tmp/testFoo2345/001" with
+ // Replace any usage of the soongOutDir with out/soong, e.g. replace "/tmp/testFoo2345/001" with
// "out/soong".
- outSoongDir := filepath.Clean(config.buildDir)
+ outSoongDir := filepath.Clean(config.soongOutDir)
re := regexp.MustCompile(`\Q` + outSoongDir + `\E\b`)
s = re.ReplaceAllString(s, "out/soong")
- // Replace any usage of the buildDir/.. with out, e.g. replace "/tmp/testFoo2345" with
+ // Replace any usage of the soongOutDir/.. with out, e.g. replace "/tmp/testFoo2345" with
// "out". This must come after the previous replacement otherwise this would replace
// "/tmp/testFoo2345/001" with "out/001" instead of "out/soong".
outDir := filepath.Dir(outSoongDir)
@@ -991,7 +991,7 @@
}
p := path.String()
if w, ok := path.(WritablePath); ok {
- rel, err := filepath.Rel(w.getBuildDir(), p)
+ rel, err := filepath.Rel(w.getSoongOutDir(), p)
if err != nil {
panic(err)
}
diff --git a/android/writedocs.go b/android/writedocs.go
index 67b9aa3..c380a3d 100644
--- a/android/writedocs.go
+++ b/android/writedocs.go
@@ -34,12 +34,12 @@
type docsSingleton struct{}
func primaryBuilderPath(ctx SingletonContext) Path {
- buildDir := absolutePath(ctx.Config().BuildDir())
+ soongOutDir := absolutePath(ctx.Config().SoongOutDir())
binary := absolutePath(os.Args[0])
- primaryBuilder, err := filepath.Rel(buildDir, binary)
+ primaryBuilder, err := filepath.Rel(soongOutDir, binary)
if err != nil {
ctx.Errorf("path to primary builder %q is not in build dir %q (%q)",
- os.Args[0], ctx.Config().BuildDir(), err)
+ os.Args[0], ctx.Config().SoongOutDir(), err)
}
return PathForOutput(ctx, primaryBuilder)
diff --git a/apex/androidmk.go b/apex/androidmk.go
index ebf0833..2f10904 100644
--- a/apex/androidmk.go
+++ b/apex/androidmk.go
@@ -212,7 +212,7 @@
}
if host {
makeOs := fi.module.Target().Os.String()
- if fi.module.Target().Os == android.Linux || fi.module.Target().Os == android.LinuxBionic {
+ if fi.module.Target().Os == android.Linux || fi.module.Target().Os == android.LinuxBionic || fi.module.Target().Os == android.LinuxMusl {
makeOs = "linux"
}
fmt.Fprintln(w, "LOCAL_MODULE_HOST_OS :=", makeOs)
diff --git a/apex/apex.go b/apex/apex.go
index e1fca67..6bafcae 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -117,9 +117,6 @@
// List of platform_compat_config files that are embedded inside this APEX bundle.
Compat_configs []string
- // List of BPF programs inside this APEX bundle.
- Bpfs []string
-
// List of filesystem images that are embedded inside this APEX bundle.
Filesystems []string
@@ -297,6 +294,9 @@
// List of runtime resource overlays (RROs) that are embedded inside this APEX.
Rros []string
+ // List of BPF programs inside this APEX bundle.
+ Bpfs []string
+
// Names of modules to be overridden. Listed modules can only be other binaries (in Make or
// Soong). This does not completely prevent installation of the overridden binaries, but if
// both binaries would be installed by default (in PRODUCT_PACKAGES) the other binary will
@@ -780,7 +780,6 @@
ctx.AddFarVariationDependencies(commonVariation, bcpfTag, a.properties.Bootclasspath_fragments...)
ctx.AddFarVariationDependencies(commonVariation, sscpfTag, a.properties.Systemserverclasspath_fragments...)
ctx.AddFarVariationDependencies(commonVariation, javaLibTag, a.properties.Java_libs...)
- ctx.AddFarVariationDependencies(commonVariation, bpfTag, a.properties.Bpfs...)
ctx.AddFarVariationDependencies(commonVariation, fsTag, a.properties.Filesystems...)
ctx.AddFarVariationDependencies(commonVariation, compatConfigTag, a.properties.Compat_configs...)
@@ -813,6 +812,7 @@
commonVariation := ctx.Config().AndroidCommonTarget.Variations()
ctx.AddFarVariationDependencies(commonVariation, androidAppTag, a.overridableProperties.Apps...)
+ ctx.AddFarVariationDependencies(commonVariation, bpfTag, a.overridableProperties.Bpfs...)
ctx.AddFarVariationDependencies(commonVariation, rroTag, a.overridableProperties.Rros...)
// Dependencies for signing
diff --git a/apex/apex_test.go b/apex/apex_test.go
index f07bf63..e0bf5e5 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -1874,6 +1874,45 @@
expectNoLink("libx", "shared_apex10000", "libz", "shared")
}
+func TestApexMinSdkVersion_crtobjectInVendorApex(t *testing.T) {
+ ctx := testApex(t, `
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ native_shared_libs: ["mylib"],
+ updatable: false,
+ vendor: true,
+ min_sdk_version: "29",
+ }
+
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+
+ cc_library {
+ name: "mylib",
+ vendor_available: true,
+ system_shared_libs: [],
+ stl: "none",
+ apex_available: [ "myapex" ],
+ min_sdk_version: "29",
+ }
+ `)
+
+ vendorVariant := "android_vendor.29_arm64_armv8-a"
+
+ // First check that the correct variant of crtbegin_so is used.
+ ldRule := ctx.ModuleForTests("mylib", vendorVariant+"_shared_apex29").Rule("ld")
+ crtBegin := names(ldRule.Args["crtBegin"])
+ ensureListContains(t, crtBegin, "out/soong/.intermediates/"+cc.DefaultCcCommonTestModulesDir+"crtbegin_so/"+vendorVariant+"_apex29/crtbegin_so.o")
+
+ // Ensure that the crtbegin_so used by the APEX is targeting 29
+ cflags := ctx.ModuleForTests("crtbegin_so", vendorVariant+"_apex29").Rule("cc").Args["cFlags"]
+ android.AssertStringDoesContain(t, "cflags", cflags, "-target aarch64-linux-android29")
+}
+
func TestPlatformUsesLatestStubsFromApexes(t *testing.T) {
ctx := testApex(t, `
apex {
@@ -4891,7 +4930,7 @@
}
}
if !foundLibfooJar {
- t.Errorf("Rule for libfoo.jar missing in dex_bootjars singleton outputs %q", android.StringPathsRelativeToTop(ctx.Config().BuildDir(), s.AllOutputs()))
+ t.Errorf("Rule for libfoo.jar missing in dex_bootjars singleton outputs %q", android.StringPathsRelativeToTop(ctx.Config().SoongOutDir(), s.AllOutputs()))
}
}
@@ -6034,6 +6073,7 @@
name: "myapex",
key: "myapex.key",
apps: ["app"],
+ bpfs: ["bpf"],
overrides: ["oldapex"],
updatable: false,
}
@@ -6042,6 +6082,7 @@
name: "override_myapex",
base: "myapex",
apps: ["override_app"],
+ bpfs: ["override_bpf"],
overrides: ["unknownapex"],
logging_parent: "com.foo.bar",
package_name: "test.overridden.package",
@@ -6080,6 +6121,16 @@
base: "app",
package_name: "bar",
}
+
+ bpf {
+ name: "bpf",
+ srcs: ["bpf.c"],
+ }
+
+ bpf {
+ name: "override_bpf",
+ srcs: ["override_bpf.c"],
+ }
`, withManifestPackageNameOverrides([]string{"myapex:com.android.myapex"}))
originalVariant := ctx.ModuleForTests("myapex", "android_common_myapex_image").Module().(android.OverridableModule)
@@ -6098,6 +6149,9 @@
ensureNotContains(t, copyCmds, "image.apex/app/app/app.apk")
ensureContains(t, copyCmds, "image.apex/app/override_app/override_app.apk")
+ ensureNotContains(t, copyCmds, "image.apex/etc/bpf/bpf.o")
+ ensureContains(t, copyCmds, "image.apex/etc/bpf/override_bpf.o")
+
apexBundle := module.Module().(*apexBundle)
name := apexBundle.Name()
if name != "override_myapex" {
@@ -6120,10 +6174,12 @@
data.Custom(&builder, name, "TARGET_", "", data)
androidMk := builder.String()
ensureContains(t, androidMk, "LOCAL_MODULE := override_app.override_myapex")
+ ensureContains(t, androidMk, "LOCAL_MODULE := override_bpf.o.override_myapex")
ensureContains(t, androidMk, "LOCAL_MODULE := apex_manifest.pb.override_myapex")
ensureContains(t, androidMk, "LOCAL_MODULE_STEM := override_myapex.apex")
ensureContains(t, androidMk, "LOCAL_OVERRIDES_MODULES := unknownapex myapex")
ensureNotContains(t, androidMk, "LOCAL_MODULE := app.myapex")
+ ensureNotContains(t, androidMk, "LOCAL_MODULE := bpf.myapex")
ensureNotContains(t, androidMk, "LOCAL_MODULE := override_app.myapex")
ensureNotContains(t, androidMk, "LOCAL_MODULE := apex_manifest.pb.myapex")
ensureNotContains(t, androidMk, "LOCAL_MODULE_STEM := myapex.apex")
diff --git a/apex/classpath_element_test.go b/apex/classpath_element_test.go
index e2d8465..60f18bd 100644
--- a/apex/classpath_element_test.go
+++ b/apex/classpath_element_test.go
@@ -159,11 +159,6 @@
],
}
- bootclasspath_fragment {
- name: "non-apex-fragment",
- contents: ["othersdklibrary"],
- }
-
apex {
name: "otherapex",
key: "otherapex.key",
@@ -213,7 +208,6 @@
myFragment := result.Module("mybootclasspath-fragment", "android_common_apex10000")
myBar := result.Module("bar", "android_common_apex10000")
- nonApexFragment := result.Module("non-apex-fragment", "android_common")
other := result.Module("othersdklibrary", "android_common_apex10000")
otherApexLibrary := result.Module("otherapexlibrary", "android_common_apex10000")
@@ -253,15 +247,6 @@
assertElementsEquals(t, "elements", expectedElements, elements)
})
- // Verify that CreateClasspathElements detects when a fragment does not have an associated apex.
- t.Run("non apex fragment", func(t *testing.T) {
- ctx := newCtx()
- elements := java.CreateClasspathElements(ctx, []android.Module{}, []android.Module{nonApexFragment})
- android.FailIfNoMatchingErrors(t, "fragment non-apex-fragment{.*} is not part of an apex", ctx.errs)
- expectedElements := java.ClasspathElements{}
- assertElementsEquals(t, "elements", expectedElements, elements)
- })
-
// Verify that CreateClasspathElements detects when an apex has multiple fragments.
t.Run("multiple fragments for same apex", func(t *testing.T) {
ctx := newCtx()
diff --git a/apex/platform_bootclasspath_test.go b/apex/platform_bootclasspath_test.go
index e0421f6..513ddc0 100644
--- a/apex/platform_bootclasspath_test.go
+++ b/apex/platform_bootclasspath_test.go
@@ -543,3 +543,140 @@
"out/soong/target/product/test_device/system/etc/classpaths",
)
}
+
+func TestBootJarNotInApex(t *testing.T) {
+ android.GroupFixturePreparers(
+ prepareForTestWithPlatformBootclasspath,
+ PrepareForTestWithApexBuildComponents,
+ prepareForTestWithMyapex,
+ java.FixtureConfigureApexBootJars("myapex:foo"),
+ ).ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(
+ `dependency "foo" of "myplatform-bootclasspath" missing variant`)).
+ RunTestWithBp(t, `
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ updatable: false,
+ }
+
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+
+ java_library {
+ name: "foo",
+ srcs: ["b.java"],
+ installable: true,
+ apex_available: [
+ "myapex",
+ ],
+ }
+
+ bootclasspath_fragment {
+ name: "not-in-apex-fragment",
+ contents: [
+ "foo",
+ ],
+ }
+
+ platform_bootclasspath {
+ name: "myplatform-bootclasspath",
+ }
+ `)
+}
+
+func TestBootFragmentNotInApex(t *testing.T) {
+ android.GroupFixturePreparers(
+ prepareForTestWithPlatformBootclasspath,
+ PrepareForTestWithApexBuildComponents,
+ prepareForTestWithMyapex,
+ java.FixtureConfigureApexBootJars("myapex:foo"),
+ ).ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(
+ `library foo.*have no corresponding fragment.*`)).RunTestWithBp(t, `
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ java_libs: ["foo"],
+ updatable: false,
+ }
+
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+
+ java_library {
+ name: "foo",
+ srcs: ["b.java"],
+ installable: true,
+ apex_available: ["myapex"],
+ permitted_packages: ["foo"],
+ }
+
+ bootclasspath_fragment {
+ name: "not-in-apex-fragment",
+ contents: ["foo"],
+ }
+
+ platform_bootclasspath {
+ name: "myplatform-bootclasspath",
+ }
+ `)
+}
+
+func TestNonBootJarInFragment(t *testing.T) {
+ android.GroupFixturePreparers(
+ prepareForTestWithPlatformBootclasspath,
+ PrepareForTestWithApexBuildComponents,
+ prepareForTestWithMyapex,
+ java.FixtureConfigureApexBootJars("myapex:foo"),
+ ).ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(
+ `in contents must also be declared in PRODUCT_APEX_BOOT_JARS`)).
+ RunTestWithBp(t, `
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ bootclasspath_fragments: ["apex-fragment"],
+ updatable: false,
+ }
+
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+
+ java_library {
+ name: "foo",
+ srcs: ["b.java"],
+ installable: true,
+ apex_available: ["myapex"],
+ permitted_packages: ["foo"],
+ }
+
+ java_library {
+ name: "bar",
+ srcs: ["b.java"],
+ installable: true,
+ apex_available: ["myapex"],
+ permitted_packages: ["bar"],
+ }
+
+ bootclasspath_fragment {
+ name: "apex-fragment",
+ contents: ["foo", "bar"],
+ apex_available:[ "myapex" ],
+ }
+
+ platform_bootclasspath {
+ name: "myplatform-bootclasspath",
+ fragments: [{
+ apex: "myapex",
+ module:"apex-fragment",
+ }],
+ }
+ `)
+}
diff --git a/apex/systemserver_classpath_fragment_test.go b/apex/systemserver_classpath_fragment_test.go
index a64c6f4..a8d5931 100644
--- a/apex/systemserver_classpath_fragment_test.go
+++ b/apex/systemserver_classpath_fragment_test.go
@@ -130,3 +130,54 @@
`mysystemserverclasspathfragment`,
})
}
+
+func TestSystemServerClasspathFragmentWithContentNotInMake(t *testing.T) {
+ android.GroupFixturePreparers(
+ prepareForTestWithSystemserverclasspathFragment,
+ prepareForTestWithMyapex,
+ dexpreopt.FixtureSetApexSystemServerJars("myapex:foo"),
+ ).
+ ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(
+ `in contents must also be declared in PRODUCT_UPDATABLE_SYSTEM_SERVER_JARS`)).
+ RunTestWithBp(t, `
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ systemserverclasspath_fragments: [
+ "mysystemserverclasspathfragment",
+ ],
+ updatable: false,
+ }
+
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+
+ java_library {
+ name: "foo",
+ srcs: ["b.java"],
+ installable: true,
+ apex_available: ["myapex"],
+ }
+
+ java_library {
+ name: "bar",
+ srcs: ["b.java"],
+ installable: true,
+ apex_available: ["myapex"],
+ }
+
+ systemserverclasspath_fragment {
+ name: "mysystemserverclasspathfragment",
+ contents: [
+ "foo",
+ "bar",
+ ],
+ apex_available: [
+ "myapex",
+ ],
+ }
+ `)
+}
diff --git a/bp2build/Android.bp b/bp2build/Android.bp
index 78e3a74..b1ccc96 100644
--- a/bp2build/Android.bp
+++ b/bp2build/Android.bp
@@ -42,6 +42,7 @@
"performance_test.go",
"prebuilt_etc_conversion_test.go",
"python_binary_conversion_test.go",
+ "python_library_conversion_test.go",
"sh_conversion_test.go",
"testing.go",
],
diff --git a/bp2build/build_conversion.go b/bp2build/build_conversion.go
index a64d474..f652a35 100644
--- a/bp2build/build_conversion.go
+++ b/bp2build/build_conversion.go
@@ -14,14 +14,20 @@
package bp2build
+/*
+For shareable/common functionality for conversion from soong-module to build files
+for queryview/bp2build
+*/
+
import (
- "android/soong/android"
- "android/soong/bazel"
"fmt"
"reflect"
"sort"
"strings"
+ "android/soong/android"
+ "android/soong/bazel"
+
"github.com/google/blueprint"
"github.com/google/blueprint/proptools"
)
diff --git a/bp2build/cc_library_conversion_test.go b/bp2build/cc_library_conversion_test.go
index bff192f..c840016 100644
--- a/bp2build/cc_library_conversion_test.go
+++ b/bp2build/cc_library_conversion_test.go
@@ -15,10 +15,10 @@
package bp2build
import (
+ "testing"
+
"android/soong/android"
"android/soong/cc"
- "strings"
- "testing"
)
const (
@@ -54,59 +54,6 @@
ctx.RegisterModuleType("cc_library_headers", cc.LibraryHeaderFactory)
}
-func runBp2BuildTestCase(t *testing.T, registerModuleTypes func(ctx android.RegistrationContext), tc bp2buildTestCase) {
- t.Helper()
- dir := "."
- filesystem := make(map[string][]byte)
- toParse := []string{
- "Android.bp",
- }
- for f, content := range tc.filesystem {
- if strings.HasSuffix(f, "Android.bp") {
- toParse = append(toParse, f)
- }
- filesystem[f] = []byte(content)
- }
- config := android.TestConfig(buildDir, nil, tc.blueprint, filesystem)
- ctx := android.NewTestContext(config)
-
- registerModuleTypes(ctx)
- ctx.RegisterModuleType(tc.moduleTypeUnderTest, tc.moduleTypeUnderTestFactory)
- ctx.RegisterBp2BuildConfig(bp2buildConfig)
- ctx.RegisterBp2BuildMutator(tc.moduleTypeUnderTest, tc.moduleTypeUnderTestBp2BuildMutator)
- ctx.RegisterForBazelConversion()
-
- _, errs := ctx.ParseFileList(dir, toParse)
- if errored(t, tc.description, errs) {
- return
- }
- _, errs = ctx.ResolveDependencies(config)
- if errored(t, tc.description, errs) {
- return
- }
-
- checkDir := dir
- if tc.dir != "" {
- checkDir = tc.dir
- }
- codegenCtx := NewCodegenContext(config, *ctx.Context, Bp2Build)
- bazelTargets := generateBazelTargetsForDir(codegenCtx, checkDir)
- if actualCount, expectedCount := len(bazelTargets), len(tc.expectedBazelTargets); actualCount != expectedCount {
- t.Errorf("%s: Expected %d bazel target, got %d", tc.description, expectedCount, actualCount)
- } else {
- for i, target := range bazelTargets {
- if w, g := tc.expectedBazelTargets[i], target.content; w != g {
- t.Errorf(
- "%s: Expected generated Bazel target to be '%s', got '%s'",
- tc.description,
- w,
- g,
- )
- }
- }
- }
-}
-
func TestCcLibrarySimple(t *testing.T) {
runCcLibraryTestCase(t, bp2buildTestCase{
description: "cc_library - simple example",
diff --git a/bp2build/cc_library_headers_conversion_test.go b/bp2build/cc_library_headers_conversion_test.go
index 712d0bd..ea2c10a 100644
--- a/bp2build/cc_library_headers_conversion_test.go
+++ b/bp2build/cc_library_headers_conversion_test.go
@@ -40,17 +40,6 @@
}`
)
-type bp2buildTestCase struct {
- description string
- moduleTypeUnderTest string
- moduleTypeUnderTestFactory android.ModuleFactory
- moduleTypeUnderTestBp2BuildMutator func(android.TopDownMutatorContext)
- blueprint string
- expectedBazelTargets []string
- filesystem map[string]string
- dir string
-}
-
func TestCcLibraryHeadersLoadStatement(t *testing.T) {
testCases := []struct {
bazelTargets BazelTargets
diff --git a/bp2build/python_binary_conversion_test.go b/bp2build/python_binary_conversion_test.go
index 7bedf71..6f6fc11 100644
--- a/bp2build/python_binary_conversion_test.go
+++ b/bp2build/python_binary_conversion_test.go
@@ -7,13 +7,15 @@
"android/soong/python"
)
-func runPythonTestCase(t *testing.T, tc bp2buildTestCase) {
- t.Helper()
- runBp2BuildTestCase(t, func(ctx android.RegistrationContext) {}, tc)
+func runBp2BuildTestCaseWithLibs(t *testing.T, tc bp2buildTestCase) {
+ runBp2BuildTestCase(t, func(ctx android.RegistrationContext) {
+ ctx.RegisterModuleType("python_library", python.PythonLibraryFactory)
+ ctx.RegisterModuleType("python_library_host", python.PythonLibraryHostFactory)
+ }, tc)
}
func TestPythonBinaryHostSimple(t *testing.T) {
- runPythonTestCase(t, bp2buildTestCase{
+ runBp2BuildTestCaseWithLibs(t, bp2buildTestCase{
description: "simple python_binary_host converts to a native py_binary",
moduleTypeUnderTest: "python_binary_host",
moduleTypeUnderTestFactory: python.PythonBinaryHostFactory,
@@ -31,12 +33,18 @@
srcs: ["**/*.py"],
exclude_srcs: ["b/e.py"],
data: ["files/data.txt",],
+ libs: ["bar"],
bazel_module: { bp2build_available: true },
}
-`,
+ python_library_host {
+ name: "bar",
+ srcs: ["b/e.py"],
+ bazel_module: { bp2build_available: true },
+ }`,
expectedBazelTargets: []string{`py_binary(
name = "foo",
data = ["files/data.txt"],
+ deps = [":bar"],
main = "a.py",
srcs = [
"a.py",
@@ -49,7 +57,7 @@
}
func TestPythonBinaryHostPy2(t *testing.T) {
- runPythonTestCase(t, bp2buildTestCase{
+ runBp2BuildTestCaseSimple(t, bp2buildTestCase{
description: "py2 python_binary_host",
moduleTypeUnderTest: "python_binary_host",
moduleTypeUnderTestFactory: python.PythonBinaryHostFactory,
@@ -79,7 +87,7 @@
}
func TestPythonBinaryHostPy3(t *testing.T) {
- runPythonTestCase(t, bp2buildTestCase{
+ runBp2BuildTestCaseSimple(t, bp2buildTestCase{
description: "py3 python_binary_host",
moduleTypeUnderTest: "python_binary_host",
moduleTypeUnderTestFactory: python.PythonBinaryHostFactory,
diff --git a/bp2build/python_library_conversion_test.go b/bp2build/python_library_conversion_test.go
new file mode 100644
index 0000000..b6f45e5
--- /dev/null
+++ b/bp2build/python_library_conversion_test.go
@@ -0,0 +1,156 @@
+package bp2build
+
+import (
+ "fmt"
+ "testing"
+
+ "android/soong/android"
+ "android/soong/python"
+)
+
+// TODO(alexmarquez): Should be lifted into a generic Bp2Build file
+type PythonLibBp2Build func(ctx android.TopDownMutatorContext)
+
+func TestPythonLibrary(t *testing.T) {
+ testPythonLib(t, "python_library",
+ python.PythonLibraryFactory, python.PythonLibraryBp2Build,
+ func(ctx android.RegistrationContext) {})
+}
+
+func TestPythonLibraryHost(t *testing.T) {
+ testPythonLib(t, "python_library_host",
+ python.PythonLibraryHostFactory, python.PythonLibraryHostBp2Build,
+ func(ctx android.RegistrationContext) {
+ ctx.RegisterModuleType("python_library", python.PythonLibraryFactory)
+ })
+}
+
+func testPythonLib(t *testing.T, modType string,
+ factory android.ModuleFactory, mutator PythonLibBp2Build,
+ registration func(ctx android.RegistrationContext)) {
+ t.Helper()
+ // Simple
+ runBp2BuildTestCase(t, registration, bp2buildTestCase{
+ description: fmt.Sprintf("simple %s converts to a native py_library", modType),
+ moduleTypeUnderTest: modType,
+ moduleTypeUnderTestFactory: factory,
+ moduleTypeUnderTestBp2BuildMutator: mutator,
+ filesystem: map[string]string{
+ "a.py": "",
+ "b/c.py": "",
+ "b/d.py": "",
+ "b/e.py": "",
+ "files/data.txt": "",
+ },
+ blueprint: fmt.Sprintf(`%s {
+ name: "foo",
+ srcs: ["**/*.py"],
+ exclude_srcs: ["b/e.py"],
+ data: ["files/data.txt",],
+ libs: ["bar"],
+ bazel_module: { bp2build_available: true },
+}
+ python_library {
+ name: "bar",
+ srcs: ["b/e.py"],
+ bazel_module: { bp2build_available: false },
+ }`, modType),
+ expectedBazelTargets: []string{`py_library(
+ name = "foo",
+ data = ["files/data.txt"],
+ deps = [":bar"],
+ srcs = [
+ "a.py",
+ "b/c.py",
+ "b/d.py",
+ ],
+ srcs_version = "PY3",
+)`,
+ },
+ })
+
+ // PY2
+ runBp2BuildTestCaseSimple(t, bp2buildTestCase{
+ description: fmt.Sprintf("py2 %s converts to a native py_library", modType),
+ moduleTypeUnderTest: modType,
+ moduleTypeUnderTestFactory: factory,
+ moduleTypeUnderTestBp2BuildMutator: mutator,
+ blueprint: fmt.Sprintf(`%s {
+ name: "foo",
+ srcs: ["a.py"],
+ version: {
+ py2: {
+ enabled: true,
+ },
+ py3: {
+ enabled: false,
+ },
+ },
+
+ bazel_module: { bp2build_available: true },
+}`, modType),
+ expectedBazelTargets: []string{`py_library(
+ name = "foo",
+ srcs = ["a.py"],
+ srcs_version = "PY2",
+)`,
+ },
+ })
+
+ // PY3
+ runBp2BuildTestCaseSimple(t, bp2buildTestCase{
+ description: fmt.Sprintf("py3 %s converts to a native py_library", modType),
+ moduleTypeUnderTest: modType,
+ moduleTypeUnderTestFactory: factory,
+ moduleTypeUnderTestBp2BuildMutator: mutator,
+ blueprint: fmt.Sprintf(`%s {
+ name: "foo",
+ srcs: ["a.py"],
+ version: {
+ py2: {
+ enabled: false,
+ },
+ py3: {
+ enabled: true,
+ },
+ },
+
+ bazel_module: { bp2build_available: true },
+}`, modType),
+ expectedBazelTargets: []string{`py_library(
+ name = "foo",
+ srcs = ["a.py"],
+ srcs_version = "PY3",
+)`,
+ },
+ })
+
+ // Both
+ runBp2BuildTestCaseSimple(t, bp2buildTestCase{
+ description: fmt.Sprintf("py2&3 %s converts to a native py_library", modType),
+ moduleTypeUnderTest: modType,
+ moduleTypeUnderTestFactory: factory,
+ moduleTypeUnderTestBp2BuildMutator: mutator,
+ blueprint: fmt.Sprintf(`%s {
+ name: "foo",
+ srcs: ["a.py"],
+ version: {
+ py2: {
+ enabled: true,
+ },
+ py3: {
+ enabled: true,
+ },
+ },
+
+ bazel_module: { bp2build_available: true },
+}`, modType),
+ expectedBazelTargets: []string{
+ // srcs_version is PY2ANDPY3 by default.
+ `py_library(
+ name = "foo",
+ srcs = ["a.py"],
+)`,
+ },
+ })
+}
diff --git a/bp2build/testing.go b/bp2build/testing.go
index 266b817..a549a93 100644
--- a/bp2build/testing.go
+++ b/bp2build/testing.go
@@ -1,6 +1,26 @@
+// Copyright 2021 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
+/*
+For shareable/common bp2build testing functionality and dumping ground for
+specific-but-shared functionality among tests in package
+*/
+
import (
+ "strings"
"testing"
"android/soong/android"
@@ -16,6 +36,87 @@
buildDir string
)
+func errored(t *testing.T, desc string, errs []error) bool {
+ t.Helper()
+ if len(errs) > 0 {
+ for _, err := range errs {
+ t.Errorf("%s: %s", desc, err)
+ }
+ return true
+ }
+ return false
+}
+
+func runBp2BuildTestCaseSimple(t *testing.T, tc bp2buildTestCase) {
+ t.Helper()
+ runBp2BuildTestCase(t, func(ctx android.RegistrationContext) {}, tc)
+}
+
+type bp2buildTestCase struct {
+ description string
+ moduleTypeUnderTest string
+ moduleTypeUnderTestFactory android.ModuleFactory
+ moduleTypeUnderTestBp2BuildMutator func(android.TopDownMutatorContext)
+ blueprint string
+ expectedBazelTargets []string
+ filesystem map[string]string
+ dir string
+}
+
+func runBp2BuildTestCase(t *testing.T, registerModuleTypes func(ctx android.RegistrationContext), tc bp2buildTestCase) {
+ t.Helper()
+ dir := "."
+ filesystem := make(map[string][]byte)
+ toParse := []string{
+ "Android.bp",
+ }
+ for f, content := range tc.filesystem {
+ if strings.HasSuffix(f, "Android.bp") {
+ toParse = append(toParse, f)
+ }
+ filesystem[f] = []byte(content)
+ }
+ config := android.TestConfig(buildDir, nil, tc.blueprint, filesystem)
+ ctx := android.NewTestContext(config)
+
+ registerModuleTypes(ctx)
+ ctx.RegisterModuleType(tc.moduleTypeUnderTest, tc.moduleTypeUnderTestFactory)
+ ctx.RegisterBp2BuildConfig(bp2buildConfig)
+ ctx.RegisterBp2BuildMutator(tc.moduleTypeUnderTest, tc.moduleTypeUnderTestBp2BuildMutator)
+ ctx.RegisterForBazelConversion()
+
+ _, errs := ctx.ParseFileList(dir, toParse)
+ if errored(t, tc.description, errs) {
+ return
+ }
+ _, errs = ctx.ResolveDependencies(config)
+ if errored(t, tc.description, errs) {
+ return
+ }
+
+ checkDir := dir
+ if tc.dir != "" {
+ checkDir = tc.dir
+ }
+ codegenCtx := NewCodegenContext(config, *ctx.Context, Bp2Build)
+ bazelTargets := generateBazelTargetsForDir(codegenCtx, checkDir)
+ if actualCount, expectedCount := len(bazelTargets), len(tc.expectedBazelTargets); actualCount != expectedCount {
+ t.Errorf("%s: Expected %d bazel target, got %d; %v",
+ tc.description, expectedCount, actualCount, bazelTargets)
+ } else {
+ for i, target := range bazelTargets {
+ if w, g := tc.expectedBazelTargets[i], target.content; w != g {
+ t.Errorf(
+ "%s: Expected generated Bazel target to be '%s', got '%s'",
+ tc.description,
+ w,
+ g,
+ )
+ }
+ }
+ }
+}
+
type nestedProps struct {
Nested_prop string
}
@@ -44,17 +145,6 @@
props customProps
}
-func errored(t *testing.T, desc string, errs []error) bool {
- t.Helper()
- if len(errs) > 0 {
- for _, err := range errs {
- t.Errorf("%s: %s", desc, err)
- }
- return true
- }
- return false
-}
-
// OutputFiles is needed because some instances of this module use dist with a
// tag property which requires the module implements OutputFileProducer.
func (m *customModule) OutputFiles(tag string) (android.Paths, error) {
diff --git a/cc/androidmk.go b/cc/androidmk.go
index e95d5a7..cd52363 100644
--- a/cc/androidmk.go
+++ b/cc/androidmk.go
@@ -294,6 +294,9 @@
if library.buildStubs() {
entries.SetBool("LOCAL_NO_NOTICE_FILE", true)
}
+ if library.apiListCoverageXmlPath.String() != "" {
+ entries.SetString("SOONG_CC_API_XML", "$(SOONG_CC_API_XML) "+library.apiListCoverageXmlPath.String())
+ }
})
}
// If a library providing a stub is included in an APEX, the private APIs of the library
diff --git a/cc/binary.go b/cc/binary.go
index 763d2b9..b423c50 100644
--- a/cc/binary.go
+++ b/cc/binary.go
@@ -156,6 +156,10 @@
}
}
+ if binary.static() {
+ deps.StaticLibs = append(deps.StaticLibs, deps.SystemSharedLibs...)
+ }
+
if ctx.toolchain().Bionic() {
if binary.static() {
if ctx.selectedStl() == "libc++_static" {
@@ -208,7 +212,7 @@
func (binary *binaryDecorator) linkerInit(ctx BaseModuleContext) {
binary.baseLinker.linkerInit(ctx)
- if !ctx.toolchain().Bionic() {
+ if !ctx.toolchain().Bionic() && !ctx.toolchain().Musl() {
if ctx.Os() == android.Linux {
// Unless explicitly specified otherwise, host static binaries are built with -static
// if HostStaticBinaries is true for the product configuration.
diff --git a/cc/cc.go b/cc/cc.go
index 243f0a5..9c1f559 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -975,16 +975,17 @@
return String(c.Properties.Min_sdk_version)
}
-func (c *Module) SplitPerApiLevel() bool {
- if !c.canUseSdk() {
- return false
- }
+func (c *Module) isCrt() bool {
if linker, ok := c.linker.(*objectLinker); ok {
return linker.isCrt()
}
return false
}
+func (c *Module) SplitPerApiLevel() bool {
+ return c.canUseSdk() && c.isCrt()
+}
+
func (c *Module) AlwaysSdk() bool {
return c.Properties.AlwaysSdk || Bool(c.Properties.Sdk_variant_only)
}
@@ -1446,12 +1447,20 @@
// create versioned variants for. For example, if min_sdk_version is 16, then sdk variant of
// the crt object has local variants of 16, 17, ..., up to the latest version. sdk_version
// and min_sdk_version properties of the variants are set to the corresponding version
- // numbers. However, the platform (non-sdk) variant of the crt object is left untouched.
- // min_sdk_version: 16 doesn't actually mean that the platform variant has to support such
- // an old version. Since the variant is for the platform, it's preferred to target the
- // latest version.
- if ctx.mod.SplitPerApiLevel() && !ctx.isSdkVariant() {
- ver = strconv.Itoa(android.FutureApiLevelInt)
+ // numbers. However, the non-sdk variant (for apex or platform) of the crt object is left
+ // untouched. min_sdk_version: 16 doesn't actually mean that the non-sdk variant has to
+ // support such an old version. The version is set to the later version in case when the
+ // non-sdk variant is for the platform, or the min_sdk_version of the containing APEX if
+ // it's for an APEX.
+ if ctx.mod.isCrt() && !ctx.isSdkVariant() {
+ if ctx.isForPlatform() {
+ ver = strconv.Itoa(android.FutureApiLevelInt)
+ } else { // for apex
+ ver = ctx.apexSdkVersion().String()
+ if ver == "" { // in case when min_sdk_version was not set by the APEX
+ ver = ctx.sdkVersion()
+ }
+ }
}
// Also make sure that minSdkVersion is not greater than sdkVersion, if they are both numbers
diff --git a/cc/cmakelists.go b/cc/cmakelists.go
index 04536fc..ad130ba 100644
--- a/cc/cmakelists.go
+++ b/cc/cmakelists.go
@@ -316,7 +316,7 @@
if strings.HasPrefix(parameter, "--sysroot") {
return systemRoot
}
- if strings.HasPrefix(parameter, "-fsanitize-blacklist") {
+ if strings.HasPrefix(parameter, "-fsanitize-ignorelist") {
return relativeFilePathFlag
}
if strings.HasPrefix(parameter, "-fprofile-sample-use") {
diff --git a/cc/config/x86_linux_host.go b/cc/config/x86_linux_host.go
index e7fcfed..ac5d5f7 100644
--- a/cc/config/x86_linux_host.go
+++ b/cc/config/x86_linux_host.go
@@ -45,6 +45,7 @@
linuxMuslCflags = []string{
"-D_LIBCPP_HAS_MUSL_LIBC",
+ "-DANDROID_HOST_MUSL",
"-nostdlibinc",
}
@@ -106,7 +107,7 @@
"util",
}, "-l")
- muslCrtBeginStaticBinary, muslCrtEndStaticBinary = []string{"libc_musl_crtbegin_static"}, []string{"crtend_android"}
+ muslCrtBeginStaticBinary, muslCrtEndStaticBinary = []string{"libc_musl_crtbegin_static"}, []string{"libc_musl_crtend"}
muslCrtBeginSharedBinary, muslCrtEndSharedBinary = []string{"libc_musl_crtbegin_dynamic", "musl_linker_script"}, []string{"libc_musl_crtend"}
muslCrtBeginSharedLibrary, muslCrtEndSharedLibrary = []string{"libc_musl_crtbegin_so"}, []string{"libc_musl_crtend_so"}
diff --git a/cc/coverage.go b/cc/coverage.go
index baf4226..8dd2db1 100644
--- a/cc/coverage.go
+++ b/cc/coverage.go
@@ -244,3 +244,19 @@
m[1].(Coverage).EnableCoverageIfNeeded()
}
}
+
+func parseSymbolFileForAPICoverage(ctx ModuleContext, symbolFile string) android.ModuleOutPath {
+ apiLevelsJson := android.GetApiLevelsJson(ctx)
+ symbolFilePath := android.PathForModuleSrc(ctx, symbolFile)
+ outputFile := ctx.baseModuleName() + ".xml"
+ parsedApiCoveragePath := android.PathForModuleOut(ctx, outputFile)
+ rule := android.NewRuleBuilder(pctx, ctx)
+ rule.Command().
+ BuiltTool("ndk_api_coverage_parser").
+ Input(symbolFilePath).
+ Output(parsedApiCoveragePath).
+ Implicit(apiLevelsJson).
+ FlagWithArg("--api-map ", apiLevelsJson.String())
+ rule.Build("native_library_api_list", "Generate native API list based on symbol files for coverage measurement")
+ return parsedApiCoveragePath
+}
diff --git a/cc/fuzz.go b/cc/fuzz.go
index fbef12b..83f0037 100644
--- a/cc/fuzz.go
+++ b/cc/fuzz.go
@@ -123,7 +123,7 @@
// that should be installed in the fuzz target output directories. This function
// returns true, unless:
// - The module is not an installable shared library, or
-// - The module is a header, stub, or vendor-linked library, or
+// - The module is a header or stub, or
// - The module is a prebuilt and its source is available, or
// - The module is a versioned member of an SDK snapshot.
func isValidSharedDependency(dependency android.Module) bool {
@@ -141,11 +141,6 @@
return false
}
- if linkable.UseVndk() {
- // Discard vendor linked libraries.
- return false
- }
-
if lib := moduleLibraryInterface(dependency); lib != nil && lib.buildStubs() && linkable.CcLibrary() {
// Discard stubs libs (only CCLibrary variants). Prebuilt libraries should not
// be excluded on the basis of they're not CCLibrary()'s.
diff --git a/cc/library.go b/cc/library.go
index 1526f81..196116b 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -536,6 +536,8 @@
*baseInstaller
collectedSnapshotHeaders android.Paths
+
+ apiListCoverageXmlPath android.ModuleOutPath
}
type ccLibraryBazelHandler struct {
@@ -951,6 +953,12 @@
objs := compileStubLibrary(ctx, flags, nativeAbiResult.stubSrc)
library.versionScriptPath = android.OptionalPathForPath(
nativeAbiResult.versionScript)
+
+ // Parse symbol file to get API list for coverage
+ if library.stubsVersion() == "current" && ctx.PrimaryArch() {
+ library.apiListCoverageXmlPath = parseSymbolFileForAPICoverage(ctx, symbolFile)
+ }
+
return objs
}
diff --git a/cc/linker.go b/cc/linker.go
index 7c710d7..8671dec 100644
--- a/cc/linker.go
+++ b/cc/linker.go
@@ -95,6 +95,9 @@
// vendor variants and this module uses VNDK.
Runtime_libs []string `android:"arch_variant"`
+ // list of runtime libs that should not be installed along with this module.
+ Exclude_runtime_libs []string `android:"arch_variant"`
+
Target struct {
Vendor, Product struct {
// list of shared libs that only should be used to build vendor or
@@ -121,8 +124,8 @@
// product variant of the C/C++ module.
Exclude_header_libs []string
- // list of runtime libs that should not be installed along with
- // vendor or variant of the C/C++ module.
+ // list of runtime libs that should not be installed along with the
+ // vendor or product variant of the C/C++ module.
Exclude_runtime_libs []string
// version script for vendor or product variant
@@ -148,6 +151,10 @@
// list of header libs that should not be used to build the recovery variant
// of the C/C++ module.
Exclude_header_libs []string
+
+ // list of runtime libs that should not be installed along with the
+ // recovery variant of the C/C++ module.
+ Exclude_runtime_libs []string
}
Ramdisk struct {
// list of static libs that only should be used to build the recovery
@@ -161,6 +168,10 @@
// list of static libs that should not be used to build
// the ramdisk variant of the C/C++ module.
Exclude_static_libs []string
+
+ // list of runtime libs that should not be installed along with the
+ // ramdisk variant of the C/C++ module.
+ Exclude_runtime_libs []string
}
Vendor_ramdisk struct {
// list of shared libs that should not be used to build
@@ -170,6 +181,10 @@
// list of static libs that should not be used to build
// the vendor ramdisk variant of the C/C++ module.
Exclude_static_libs []string
+
+ // list of runtime libs that should not be installed along with the
+ // vendor ramdisk variant of the C/C++ module.
+ Exclude_runtime_libs []string
}
Platform struct {
// list of shared libs that should be use to build the platform variant
@@ -191,7 +206,7 @@
// the C/C++ module.
Exclude_shared_libs []string
- // list of static libs that should not be used to build the apex ramdisk
+ // list of static libs that should not be used to build the apex
// variant of the C/C++ module.
Exclude_static_libs []string
}
@@ -275,6 +290,7 @@
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)
+ deps.RuntimeLibs = removeListFromList(deps.RuntimeLibs, linker.Properties.Exclude_runtime_libs)
// Record the libraries that need to be excluded when building for APEX. Unlike other
// target.*.exclude_* properties, SharedLibs and StaticLibs are not modified here because
@@ -325,6 +341,7 @@
deps.ReexportHeaderLibHeaders = removeListFromList(deps.ReexportHeaderLibHeaders, linker.Properties.Target.Recovery.Exclude_header_libs)
deps.ReexportStaticLibHeaders = removeListFromList(deps.ReexportStaticLibHeaders, linker.Properties.Target.Recovery.Exclude_static_libs)
deps.WholeStaticLibs = removeListFromList(deps.WholeStaticLibs, linker.Properties.Target.Recovery.Exclude_static_libs)
+ deps.RuntimeLibs = removeListFromList(deps.RuntimeLibs, linker.Properties.Target.Recovery.Exclude_runtime_libs)
}
if ctx.inRamdisk() {
@@ -334,6 +351,7 @@
deps.StaticLibs = removeListFromList(deps.StaticLibs, linker.Properties.Target.Ramdisk.Exclude_static_libs)
deps.ReexportStaticLibHeaders = removeListFromList(deps.ReexportStaticLibHeaders, linker.Properties.Target.Ramdisk.Exclude_static_libs)
deps.WholeStaticLibs = removeListFromList(deps.WholeStaticLibs, linker.Properties.Target.Ramdisk.Exclude_static_libs)
+ deps.RuntimeLibs = removeListFromList(deps.RuntimeLibs, linker.Properties.Target.Ramdisk.Exclude_runtime_libs)
}
if ctx.inVendorRamdisk() {
@@ -342,6 +360,7 @@
deps.StaticLibs = removeListFromList(deps.StaticLibs, linker.Properties.Target.Vendor_ramdisk.Exclude_static_libs)
deps.ReexportStaticLibHeaders = removeListFromList(deps.ReexportStaticLibHeaders, linker.Properties.Target.Vendor_ramdisk.Exclude_static_libs)
deps.WholeStaticLibs = removeListFromList(deps.WholeStaticLibs, linker.Properties.Target.Vendor_ramdisk.Exclude_static_libs)
+ deps.RuntimeLibs = removeListFromList(deps.RuntimeLibs, linker.Properties.Target.Vendor_ramdisk.Exclude_runtime_libs)
}
if !ctx.useSdk() {
diff --git a/cc/ndk_api_coverage_parser/__init__.py b/cc/ndk_api_coverage_parser/__init__.py
index 7817c78..8b9cd66 100755
--- a/cc/ndk_api_coverage_parser/__init__.py
+++ b/cc/ndk_api_coverage_parser/__init__.py
@@ -21,7 +21,12 @@
import sys
from xml.etree.ElementTree import Element, SubElement, tostring
-from symbolfile import ALL_ARCHITECTURES, FUTURE_API_LEVEL, MultiplyDefinedSymbolError, SymbolFileParser
+from symbolfile import (
+ ALL_ARCHITECTURES,
+ FUTURE_API_LEVEL,
+ MultiplyDefinedSymbolError,
+ SymbolFileParser,
+)
ROOT_ELEMENT_TAG = 'ndk-library'
@@ -63,6 +68,7 @@
class XmlGenerator(object):
"""Output generator that writes parsed symbol file to a xml file."""
+
def __init__(self, output_file):
self.output_file = output_file
@@ -74,10 +80,14 @@
continue
version_attributes = parse_tags(version.tags)
_, _, postfix = version.name.partition('_')
- is_platform = postfix == 'PRIVATE' or postfix == 'PLATFORM'
+ is_platform = postfix in ('PRIVATE' , 'PLATFORM')
is_deprecated = postfix == 'DEPRECATED'
- version_attributes.update({PLATFORM_ATTRIBUTE_KEY: str(is_platform)})
- version_attributes.update({DEPRECATED_ATTRIBUTE_KEY: str(is_deprecated)})
+ version_attributes.update(
+ {PLATFORM_ATTRIBUTE_KEY: str(is_platform)}
+ )
+ version_attributes.update(
+ {DEPRECATED_ATTRIBUTE_KEY: str(is_deprecated)}
+ )
for symbol in version.symbols:
if VARIABLE_TAG in symbol.tags:
continue
@@ -103,13 +113,20 @@
"""Parses and returns command line arguments."""
parser = argparse.ArgumentParser()
- parser.add_argument('symbol_file', type=os.path.realpath, help='Path to symbol file.')
parser.add_argument(
- 'output_file', type=os.path.realpath,
- help='The output parsed api coverage file.')
+ 'symbol_file', type=os.path.realpath, help='Path to symbol file.'
+ )
parser.add_argument(
- '--api-map', type=os.path.realpath, required=True,
- help='Path to the API level map JSON file.')
+ 'output_file',
+ type=os.path.realpath,
+ help='The output parsed api coverage file.',
+ )
+ parser.add_argument(
+ '--api-map',
+ type=os.path.realpath,
+ required=True,
+ help='Path to the API level map JSON file.',
+ )
return parser.parse_args()
@@ -122,13 +139,15 @@
with open(args.symbol_file) as symbol_file:
try:
- versions = SymbolFileParser(symbol_file, api_map, "", FUTURE_API_LEVEL,
- True, True).parse()
+ versions = SymbolFileParser(
+ symbol_file, api_map, "", FUTURE_API_LEVEL, True, True
+ ).parse()
except MultiplyDefinedSymbolError as ex:
sys.exit('{}: error: {}'.format(args.symbol_file, ex))
generator = XmlGenerator(args.output_file)
generator.write(versions)
+
if __name__ == '__main__':
main()
diff --git a/cc/ndk_api_coverage_parser/test_ndk_api_coverage_parser.py b/cc/ndk_api_coverage_parser/test_ndk_api_coverage_parser.py
index 3ec14c1..141059c 100644
--- a/cc/ndk_api_coverage_parser/test_ndk_api_coverage_parser.py
+++ b/cc/ndk_api_coverage_parser/test_ndk_api_coverage_parser.py
@@ -50,10 +50,12 @@
return False
return all(etree_equal(c1, c2) for c1, c2 in zip(elem1, elem2))
-
+# pylint: disable=line-too-long
class ApiCoverageSymbolFileParserTest(unittest.TestCase):
def test_parse(self):
- input_file = io.StringIO(textwrap.dedent(u"""\
+ input_file = io.StringIO(
+ textwrap.dedent(
+ u"""\
LIBLOG { # introduced-arm64=24 introduced-x86=24 introduced-x86_64=24
global:
android_name_to_log_id; # apex llndk introduced=23
@@ -64,22 +66,28 @@
local:
*;
};
-
+
LIBLOG_PLATFORM {
android_fdtrack; # llndk
android_net; # introduced=23
};
-
+
LIBLOG_FOO { # var
android_var;
};
- """))
- parser = SymbolFileParser(input_file, {}, "", FUTURE_API_LEVEL, True, True)
+ """
+ )
+ )
+ parser = SymbolFileParser(
+ input_file, {}, "", FUTURE_API_LEVEL, True, True
+ )
generator = nparser.XmlGenerator(io.StringIO())
result = generator.convertToXml(parser.parse())
- expected = fromstring('<ndk-library><symbol apex="True" arch="" introduced="23" introduced-arm64="24" introduced-x86="24" introduced-x86_64="24" is_deprecated="False" is_platform="False" llndk="True" name="android_name_to_log_id" /><symbol arch="arm" introduced-arm64="24" introduced-x86="24" introduced-x86_64="24" is_deprecated="False" is_platform="False" llndk="True" name="android_log_id_to_name" /><symbol arch="" introduced-arm64="24" introduced-x86="23" introduced-x86_64="24" is_deprecated="False" is_platform="False" name="__android_log_assert" /><symbol arch="" introduced-arm64="24" introduced-x86="24" introduced-x86_64="24" is_deprecated="False" is_platform="False" name="__android_log_buf_write" /><symbol arch="" is_deprecated="False" is_platform="True" llndk="True" name="android_fdtrack" /><symbol arch="" introduced="23" is_deprecated="False" is_platform="True" name="android_net" /></ndk-library>')
+ expected = fromstring(
+ '<ndk-library><symbol apex="True" arch="" introduced="23" introduced-arm64="24" introduced-x86="24" introduced-x86_64="24" is_deprecated="False" is_platform="False" llndk="True" name="android_name_to_log_id" /><symbol arch="arm" introduced-arm64="24" introduced-x86="24" introduced-x86_64="24" is_deprecated="False" is_platform="False" llndk="True" name="android_log_id_to_name" /><symbol arch="" introduced-arm64="24" introduced-x86="23" introduced-x86_64="24" is_deprecated="False" is_platform="False" name="__android_log_assert" /><symbol arch="" introduced-arm64="24" introduced-x86="24" introduced-x86_64="24" is_deprecated="False" is_platform="False" name="__android_log_buf_write" /><symbol arch="" is_deprecated="False" is_platform="True" llndk="True" name="android_fdtrack" /><symbol arch="" introduced="23" is_deprecated="False" is_platform="True" name="android_net" /></ndk-library>'
+ )
self.assertTrue(etree_equal(expected, result))
-
+# pylint: enable=line-too-long
def main():
suite = unittest.TestLoader().loadTestsFromName(__name__)
diff --git a/cc/ndk_library.go b/cc/ndk_library.go
index 63e8261..51cdddf 100644
--- a/cc/ndk_library.go
+++ b/cc/ndk_library.go
@@ -29,7 +29,6 @@
func init() {
pctx.HostBinToolVariable("ndkStubGenerator", "ndkstubgen")
- pctx.HostBinToolVariable("ndk_api_coverage_parser", "ndk_api_coverage_parser")
pctx.HostBinToolVariable("abidiff", "abidiff")
pctx.HostBinToolVariable("abitidy", "abitidy")
pctx.HostBinToolVariable("abidw", "abidw")
@@ -43,12 +42,6 @@
CommandDeps: []string{"$ndkStubGenerator"},
}, "arch", "apiLevel", "apiMap", "flags")
- parseNdkApiRule = pctx.AndroidStaticRule("parseNdkApiRule",
- blueprint.RuleParams{
- Command: "$ndk_api_coverage_parser $in $out --api-map $apiMap",
- CommandDeps: []string{"$ndk_api_coverage_parser"},
- }, "apiMap")
-
abidw = pctx.AndroidStaticRule("abidw",
blueprint.RuleParams{
Command: "$abidw --type-id-style hash --no-corpus-path " +
@@ -276,24 +269,6 @@
android.Paths{src}, nil, nil)
}
-func parseSymbolFileForCoverage(ctx ModuleContext, symbolFile string) android.ModuleOutPath {
- apiLevelsJson := android.GetApiLevelsJson(ctx)
- symbolFilePath := android.PathForModuleSrc(ctx, symbolFile)
- outputFileName := strings.Split(symbolFilePath.Base(), ".")[0]
- parsedApiCoveragePath := android.PathForModuleOut(ctx, outputFileName+".xml")
- ctx.Build(pctx, android.BuildParams{
- Rule: parseNdkApiRule,
- Description: "parse ndk api symbol file for api coverage: " + symbolFilePath.Rel(),
- Outputs: []android.WritablePath{parsedApiCoveragePath},
- Input: symbolFilePath,
- Implicits: []android.Path{apiLevelsJson},
- Args: map[string]string{
- "apiMap": apiLevelsJson.String(),
- },
- })
- return parsedApiCoveragePath
-}
-
func (this *stubDecorator) findImplementationLibrary(ctx ModuleContext) android.Path {
dep := ctx.GetDirectDepWithTag(strings.TrimSuffix(ctx.ModuleName(), ndkLibrarySuffix),
stubImplementation)
@@ -454,7 +429,7 @@
}
}
if c.apiLevel.IsCurrent() && ctx.PrimaryArch() {
- c.parsedCoverageXmlPath = parseSymbolFileForCoverage(ctx, symbolFile)
+ c.parsedCoverageXmlPath = parseSymbolFileForAPICoverage(ctx, symbolFile)
}
return objs
}
diff --git a/cc/object_test.go b/cc/object_test.go
index 0e5508a..259a892 100644
--- a/cc/object_test.go
+++ b/cc/object_test.go
@@ -15,8 +15,9 @@
package cc
import (
- "android/soong/android"
"testing"
+
+ "android/soong/android"
)
func TestMinSdkVersionsOfCrtObjects(t *testing.T) {
@@ -27,24 +28,23 @@
crt: true,
stl: "none",
min_sdk_version: "28",
-
+ vendor_available: true,
}`)
- 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 + " "
+ variants := []struct {
+ variant string
+ num string
+ }{
+ {"android_arm64_armv8-a", "10000"},
+ {"android_arm64_armv8-a_sdk_28", "28"},
+ {"android_arm64_armv8-a_sdk_29", "29"},
+ {"android_arm64_armv8-a_sdk_30", "30"},
+ {"android_arm64_armv8-a_sdk_current", "10000"},
+ {"android_vendor.29_arm64_armv8-a", "29"},
+ }
+ for _, v := range variants {
+ cflags := ctx.ModuleForTests("crt_foo", v.variant).Rule("cc").Args["cFlags"]
+ expected := "-target aarch64-linux-android" + v.num + " "
android.AssertStringDoesContain(t, "cflag", cflags, expected)
}
}
diff --git a/cc/sanitize.go b/cc/sanitize.go
index dd15ae1..f6a9d5b 100644
--- a/cc/sanitize.go
+++ b/cc/sanitize.go
@@ -41,7 +41,6 @@
hwasanCflags = []string{"-fno-omit-frame-pointer", "-Wno-frame-larger-than=",
"-fsanitize-hwaddress-abi=platform",
- "-fno-experimental-new-pass-manager",
// The following improves debug location information
// availability at the cost of its accuracy. It increases
// the likelihood of a stack variable's frame offset
@@ -57,7 +56,7 @@
}
cfiCflags = []string{"-flto", "-fsanitize-cfi-cross-dso",
- "-fsanitize-blacklist=external/compiler-rt/lib/cfi/cfi_blocklist.txt"}
+ "-fsanitize-ignorelist=external/compiler-rt/lib/cfi/cfi_blocklist.txt"}
// -flto and -fvisibility are required by clang when -fsanitize=cfi is
// used, but have no effect on assembly files
cfiAsflags = []string{"-flto", "-fvisibility=default"}
@@ -65,7 +64,7 @@
"-Wl,-plugin-opt,O1"}
cfiExportsMapPath = "build/soong/cc/config/cfi_exports.map"
- intOverflowCflags = []string{"-fsanitize-blacklist=build/soong/cc/config/integer_overflow_blocklist.txt"}
+ intOverflowCflags = []string{"-fsanitize-ignorelist=build/soong/cc/config/integer_overflow_blocklist.txt"}
minimalRuntimeFlags = []string{"-fsanitize-minimal-runtime", "-fno-sanitize-trap=integer,undefined",
"-fno-sanitize-recover=integer,undefined"}
@@ -261,7 +260,7 @@
// the first one
Recover []string
- // value to pass to -fsanitize-blacklist
+ // value to pass to -fsanitize-ignorelist
Blocklist *string
}
@@ -757,7 +756,7 @@
blocklist := android.OptionalPathForModuleSrc(ctx, sanitize.Properties.Sanitize.Blocklist)
if blocklist.Valid() {
- flags.Local.CFlags = append(flags.Local.CFlags, "-fsanitize-blacklist="+blocklist.String())
+ flags.Local.CFlags = append(flags.Local.CFlags, "-fsanitize-ignorelist="+blocklist.String())
flags.CFlagsDeps = append(flags.CFlagsDeps, blocklist.Path())
}
diff --git a/cc/testing.go b/cc/testing.go
index 071f1ec..d0dca6b 100644
--- a/cc/testing.go
+++ b/cc/testing.go
@@ -375,26 +375,42 @@
cc_object {
name: "crtbegin_so",
defaults: ["crt_defaults"],
+ srcs: ["crtbegin_so.c"],
+ objs: ["crtbrand"],
}
cc_object {
name: "crtbegin_dynamic",
defaults: ["crt_defaults"],
+ srcs: ["crtbegin.c"],
+ objs: ["crtbrand"],
}
cc_object {
name: "crtbegin_static",
defaults: ["crt_defaults"],
+ srcs: ["crtbegin.c"],
+ objs: ["crtbrand"],
}
cc_object {
name: "crtend_so",
defaults: ["crt_defaults"],
+ srcs: ["crtend_so.c"],
+ objs: ["crtbrand"],
}
cc_object {
name: "crtend_android",
defaults: ["crt_defaults"],
+ srcs: ["crtend.c"],
+ objs: ["crtbrand"],
+ }
+
+ cc_object {
+ name: "crtbrand",
+ defaults: ["crt_defaults"],
+ srcs: ["crtbrand.c"],
}
cc_library {
@@ -585,6 +601,11 @@
"defaults/cc/common/libm.map.txt": nil,
"defaults/cc/common/ndk_libandroid_support": nil,
"defaults/cc/common/ndk_libc++_shared": nil,
+ "defaults/cc/common/crtbegin_so.c": nil,
+ "defaults/cc/common/crtbegin.c": nil,
+ "defaults/cc/common/crtend_so.c": nil,
+ "defaults/cc/common/crtend.c": nil,
+ "defaults/cc/common/crtbrand.c": nil,
}.AddToFixture(),
// Place the default cc test modules that are common to all platforms in a location that will not
diff --git a/cmd/soong_build/main.go b/cmd/soong_build/main.go
index 8aea037..beda184 100644
--- a/cmd/soong_build/main.go
+++ b/cmd/soong_build/main.go
@@ -25,6 +25,7 @@
"android/soong/bp2build"
"android/soong/shared"
+
"github.com/google/blueprint/bootstrap"
"github.com/google/blueprint/deptools"
"github.com/google/blueprint/pathtools"
@@ -43,6 +44,7 @@
delveListen string
delvePath string
+ moduleGraphFile string
docFile string
bazelQueryViewDir string
bp2buildMarker string
@@ -62,6 +64,7 @@
flag.StringVar(&delvePath, "delve_path", "", "Path to Delve. Only used if --delve_listen is set")
// Flags representing various modes soong_build can run in
+ flag.StringVar(&moduleGraphFile, "module_graph_file", "", "JSON module graph file to output")
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")
@@ -71,7 +74,6 @@
flag.StringVar(&globListDir, "globListDir", "", "the directory containing the glob list files")
flag.StringVar(&cmdlineArgs.BuildDir, "b", ".", "the build output directory")
flag.StringVar(&cmdlineArgs.NinjaBuildDir, "n", "", "the ninja builddir directory")
- flag.StringVar(&cmdlineArgs.DepFile, "d", "", "the dependency file to output")
flag.StringVar(&cmdlineArgs.Cpuprofile, "cpuprofile", "", "write cpu profile to file")
flag.StringVar(&cmdlineArgs.TraceFile, "trace", "", "write trace to file")
flag.StringVar(&cmdlineArgs.Memprofile, "memprofile", "", "write memory profile to file")
@@ -146,14 +148,10 @@
ninjaDeps := bootstrap.RunBlueprint(secondArgs, secondCtx.Context, secondConfig)
ninjaDeps = append(ninjaDeps, extraNinjaDeps...)
- globListFiles := writeBuildGlobsNinjaFile(secondCtx.SrcDir(), configuration.BuildDir(), secondCtx.Globs, configuration)
+ globListFiles := writeBuildGlobsNinjaFile(secondCtx.SrcDir(), configuration.SoongOutDir(), secondCtx.Globs, configuration)
ninjaDeps = append(ninjaDeps, globListFiles...)
- err = deptools.WriteDepFile(shared.JoinPath(topDir, secondArgs.DepFile), secondArgs.OutFile, ninjaDeps)
- if err != nil {
- fmt.Fprintf(os.Stderr, "Error writing depfile '%s': %s\n", secondArgs.DepFile, err)
- os.Exit(1)
- }
+ writeDepFile(secondArgs.OutFile, ninjaDeps)
}
// Run the code-generation phase to convert BazelTargetModules to BUILD files.
@@ -177,7 +175,7 @@
}
func writeMetrics(configuration android.Config) {
- metricsFile := filepath.Join(configuration.BuildDir(), "soong_build_metrics.pb")
+ metricsFile := filepath.Join(configuration.SoongOutDir(), "soong_build_metrics.pb")
err := android.WriteMetrics(configuration, metricsFile)
if err != nil {
fmt.Fprintf(os.Stderr, "error writing soong_build metrics %s: %s", metricsFile, err)
@@ -185,8 +183,8 @@
}
}
-func writeJsonModuleGraph(configuration android.Config, ctx *android.Context, path string, extraNinjaDeps []string) {
- f, err := os.Create(path)
+func writeJsonModuleGraph(ctx *android.Context, path string) {
+ f, err := os.Create(shared.JoinPath(topDir, path))
if err != nil {
fmt.Fprintf(os.Stderr, "%s", err)
os.Exit(1)
@@ -194,7 +192,6 @@
defer f.Close()
ctx.Context.PrintJSONGraph(f)
- writeFakeNinjaFile(extraNinjaDeps, configuration.BuildDir())
}
func writeBuildGlobsNinjaFile(srcDir, buildDir string, globs func() pathtools.MultipleGlobResults, config interface{}) []string {
@@ -208,6 +205,15 @@
return bootstrap.GlobFileListFiles(globDir)
}
+func writeDepFile(outputFile string, ninjaDeps []string) {
+ depFile := shared.JoinPath(topDir, outputFile+".d")
+ err := deptools.WriteDepFile(depFile, outputFile, ninjaDeps)
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "Error writing depfile '%s': %s\n", depFile, err)
+ os.Exit(1)
+ }
+}
+
// doChosenActivity runs Soong for a specific activity, like bp2build, queryview
// or the actual Soong build for the build.ninja file. Returns the top level
// output file of the specific activity.
@@ -215,10 +221,9 @@
bazelConversionRequested := bp2buildMarker != ""
mixedModeBuild := configuration.BazelContext.BazelEnabled()
generateQueryView := bazelQueryViewDir != ""
- jsonModuleFile := configuration.Getenv("SOONG_DUMP_JSON_MODULE_GRAPH")
blueprintArgs := cmdlineArgs
- prepareBuildActions := !generateQueryView && jsonModuleFile == ""
+ prepareBuildActions := !generateQueryView && moduleGraphFile == ""
if bazelConversionRequested {
// Run the alternate pipeline of bp2build mutators and singleton to convert
// Blueprint to BUILD files before everything else.
@@ -233,27 +238,24 @@
ninjaDeps := bootstrap.RunBlueprint(blueprintArgs, ctx.Context, configuration)
ninjaDeps = append(ninjaDeps, extraNinjaDeps...)
- globListFiles := writeBuildGlobsNinjaFile(ctx.SrcDir(), configuration.BuildDir(), ctx.Globs, configuration)
+ globListFiles := writeBuildGlobsNinjaFile(ctx.SrcDir(), configuration.SoongOutDir(), ctx.Globs, configuration)
ninjaDeps = append(ninjaDeps, globListFiles...)
- err := deptools.WriteDepFile(shared.JoinPath(topDir, blueprintArgs.DepFile), blueprintArgs.OutFile, ninjaDeps)
- if err != nil {
- fmt.Fprintf(os.Stderr, "Error writing depfile '%s': %s\n", blueprintArgs.DepFile, err)
- os.Exit(1)
+ // Convert the Soong module graph into Bazel BUILD files.
+ if generateQueryView {
+ runQueryView(configuration, ctx)
+ return cmdlineArgs.OutFile // TODO: This is a lie
+ } else if moduleGraphFile != "" {
+ writeJsonModuleGraph(ctx, moduleGraphFile)
+ writeDepFile(moduleGraphFile, ninjaDeps)
+ return moduleGraphFile
+ } else {
+ // The actual output (build.ninja) was written in the RunBlueprint() call
+ // above
+ writeDepFile(cmdlineArgs.OutFile, ninjaDeps)
}
}
- // Convert the Soong module graph into Bazel BUILD files.
- if generateQueryView {
- runQueryView(configuration, ctx)
- return cmdlineArgs.OutFile // TODO: This is a lie
- }
-
- if jsonModuleFile != "" {
- writeJsonModuleGraph(configuration, ctx, jsonModuleFile, extraNinjaDeps)
- return cmdlineArgs.OutFile // TODO: This is a lie
- }
-
writeMetrics(configuration)
return cmdlineArgs.OutFile
}
@@ -307,7 +309,7 @@
if shared.IsDebugging() {
// Add a non-existent file to the dependencies so that soong_build will rerun when the debugger is
// enabled even if it completed successfully.
- extraNinjaDeps = append(extraNinjaDeps, filepath.Join(configuration.BuildDir(), "always_rerun_for_delve"))
+ extraNinjaDeps = append(extraNinjaDeps, filepath.Join(configuration.SoongOutDir(), "always_rerun_for_delve"))
}
if docFile != "" {
@@ -348,29 +350,6 @@
touch(shared.JoinPath(topDir, finalOutputFile))
}
-// Workarounds to support running bp2build in a clean AOSP checkout with no
-// prior builds, and exiting early as soon as the BUILD files get generated,
-// therefore not creating build.ninja files that soong_ui and callers of
-// soong_build expects.
-//
-// These files are: build.ninja and build.ninja.d. Since Kati hasn't been
-// ran as well, and `nothing` is defined in a .mk file, there isn't a ninja
-// target called `nothing`, so we manually create it here.
-func writeFakeNinjaFile(extraNinjaDeps []string, buildDir string) {
- extraNinjaDepsString := strings.Join(extraNinjaDeps, " \\\n ")
-
- ninjaFileName := "build.ninja"
- ninjaFile := shared.JoinPath(topDir, buildDir, ninjaFileName)
- ninjaFileD := shared.JoinPath(topDir, buildDir, ninjaFileName+".d")
- // A workaround to create the 'nothing' ninja target so `m nothing` works,
- // since bp2build runs without Kati, and the 'nothing' target is declared in
- // a Makefile.
- ioutil.WriteFile(ninjaFile, []byte("build nothing: phony\n phony_output = true\n"), 0666)
- ioutil.WriteFile(ninjaFileD,
- []byte(fmt.Sprintf("%s: \\\n %s\n", ninjaFile, extraNinjaDepsString)),
- 0666)
-}
-
func touch(path string) {
f, err := os.OpenFile(path, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0666)
if err != nil {
@@ -505,7 +484,7 @@
ninjaDeps := bootstrap.RunBlueprint(blueprintArgs, bp2buildCtx.Context, configuration)
ninjaDeps = append(ninjaDeps, extraNinjaDeps...)
- globListFiles := writeBuildGlobsNinjaFile(bp2buildCtx.SrcDir(), configuration.BuildDir(), bp2buildCtx.Globs, configuration)
+ globListFiles := writeBuildGlobsNinjaFile(bp2buildCtx.SrcDir(), configuration.SoongOutDir(), bp2buildCtx.Globs, configuration)
ninjaDeps = append(ninjaDeps, globListFiles...)
// Run the code-generation phase to convert BazelTargetModules to BUILD files
@@ -513,8 +492,8 @@
codegenContext := bp2build.NewCodegenContext(configuration, *bp2buildCtx, bp2build.Bp2Build)
metrics := bp2build.Codegen(codegenContext)
- generatedRoot := shared.JoinPath(configuration.BuildDir(), "bp2build")
- workspaceRoot := shared.JoinPath(configuration.BuildDir(), "workspace")
+ generatedRoot := shared.JoinPath(configuration.SoongOutDir(), "bp2build")
+ workspaceRoot := shared.JoinPath(configuration.SoongOutDir(), "workspace")
excludes := []string{
"bazel-bin",
@@ -550,12 +529,7 @@
ninjaDeps = append(ninjaDeps, codegenContext.AdditionalNinjaDeps()...)
ninjaDeps = append(ninjaDeps, symlinkForestDeps...)
- depFile := bp2buildMarker + ".d"
- err = deptools.WriteDepFile(shared.JoinPath(topDir, depFile), bp2buildMarker, ninjaDeps)
- if err != nil {
- fmt.Fprintf(os.Stderr, "Cannot write depfile '%s': %s\n", depFile, err)
- os.Exit(1)
- }
+ writeDepFile(bp2buildMarker, ninjaDeps)
// Create an empty bp2build marker file.
touch(shared.JoinPath(topDir, bp2buildMarker))
diff --git a/dexpreopt/class_loader_context.go b/dexpreopt/class_loader_context.go
index ebb8959..1bdd040 100644
--- a/dexpreopt/class_loader_context.go
+++ b/dexpreopt/class_loader_context.go
@@ -196,6 +196,10 @@
// If the library is optional or required.
Optional bool
+ // If the library is implicitly infered by Soong (as opposed to explicitly added via `uses_libs`
+ // or `optional_uses_libs`.
+ Implicit bool
+
// On-host build path to the library dex file (used in dex2oat argument --class-loader-context).
Host android.Path
@@ -258,8 +262,9 @@
const AnySdkVersion int = android.FutureApiLevelInt
// Add class loader context for the given library to the map entry for the given SDK version.
-func (clcMap ClassLoaderContextMap) addContext(ctx android.ModuleInstallPathContext, sdkVer int, lib string,
- optional bool, hostPath, installPath android.Path, nestedClcMap ClassLoaderContextMap) error {
+func (clcMap ClassLoaderContextMap) addContext(ctx android.ModuleInstallPathContext, sdkVer int,
+ lib string, optional, implicit bool, hostPath, installPath android.Path,
+ nestedClcMap ClassLoaderContextMap) error {
// For prebuilts, library should have the same name as the source module.
lib = android.RemoveOptionalPrebuiltPrefix(lib)
@@ -308,6 +313,7 @@
clcMap[sdkVer] = append(clcMap[sdkVer], &ClassLoaderContext{
Name: lib,
Optional: optional,
+ Implicit: implicit,
Host: hostPath,
Device: devicePath,
Subcontexts: subcontexts,
@@ -320,9 +326,10 @@
// about paths). For the subset of libraries that are used in dexpreopt, their build/install paths
// are validated later before CLC is used (in validateClassLoaderContext).
func (clcMap ClassLoaderContextMap) AddContext(ctx android.ModuleInstallPathContext, sdkVer int,
- lib string, optional bool, hostPath, installPath android.Path, nestedClcMap ClassLoaderContextMap) {
+ lib string, optional, implicit bool, hostPath, installPath android.Path,
+ nestedClcMap ClassLoaderContextMap) {
- err := clcMap.addContext(ctx, sdkVer, lib, optional, hostPath, installPath, nestedClcMap)
+ err := clcMap.addContext(ctx, sdkVer, lib, optional, implicit, hostPath, installPath, nestedClcMap)
if err != nil {
ctx.ModuleErrorf(err.Error())
}
@@ -366,13 +373,15 @@
// included). This is the list of libraries that should be in the <uses-library> tags in the
// manifest. Some of them may be present in the source manifest, others are added by manifest_fixer.
// Required and optional libraries are in separate lists.
-func (clcMap ClassLoaderContextMap) UsesLibs() (required []string, optional []string) {
+func (clcMap ClassLoaderContextMap) usesLibs(implicit bool) (required []string, optional []string) {
if clcMap != nil {
clcs := clcMap[AnySdkVersion]
required = make([]string, 0, len(clcs))
optional = make([]string, 0, len(clcs))
for _, clc := range clcs {
- if clc.Optional {
+ if implicit && !clc.Implicit {
+ // Skip, this is an explicit library and we need only the implicit ones.
+ } else if clc.Optional {
optional = append(optional, clc.Name)
} else {
required = append(required, clc.Name)
@@ -382,6 +391,14 @@
return required, optional
}
+func (clcMap ClassLoaderContextMap) UsesLibs() ([]string, []string) {
+ return clcMap.usesLibs(false)
+}
+
+func (clcMap ClassLoaderContextMap) ImplicitUsesLibs() ([]string, []string) {
+ return clcMap.usesLibs(true)
+}
+
func (clcMap ClassLoaderContextMap) Dump() string {
jsonCLC := toJsonClassLoaderContext(clcMap)
bytes, err := json.MarshalIndent(jsonCLC, "", " ")
@@ -524,6 +541,8 @@
// the same as Soong representation except that SDK versions and paths are represented with strings.
type jsonClassLoaderContext struct {
Name string
+ Optional bool
+ Implicit bool
Host string
Device string
Subcontexts []*jsonClassLoaderContext
@@ -555,6 +574,8 @@
for _, clc := range jClcs {
clcs = append(clcs, &ClassLoaderContext{
Name: clc.Name,
+ Optional: clc.Optional,
+ Implicit: clc.Implicit,
Host: constructPath(ctx, clc.Host),
Device: clc.Device,
Subcontexts: fromJsonClassLoaderContextRec(ctx, clc.Subcontexts),
@@ -579,6 +600,8 @@
for i, clc := range clcs {
jClcs[i] = &jsonClassLoaderContext{
Name: clc.Name,
+ Optional: clc.Optional,
+ Implicit: clc.Implicit,
Host: clc.Host.String(),
Device: clc.Device,
Subcontexts: toJsonClassLoaderContextRec(clc.Subcontexts),
diff --git a/dexpreopt/class_loader_context_test.go b/dexpreopt/class_loader_context_test.go
index 0b7b546..d81ac2c 100644
--- a/dexpreopt/class_loader_context_test.go
+++ b/dexpreopt/class_loader_context_test.go
@@ -50,33 +50,34 @@
ctx := testContext()
optional := false
+ implicit := true
m := make(ClassLoaderContextMap)
- m.AddContext(ctx, AnySdkVersion, "a", optional, buildPath(ctx, "a"), installPath(ctx, "a"), nil)
- m.AddContext(ctx, AnySdkVersion, "b", optional, buildPath(ctx, "b"), installPath(ctx, "b"), nil)
- m.AddContext(ctx, AnySdkVersion, "c", optional, buildPath(ctx, "c"), installPath(ctx, "c"), nil)
+ m.AddContext(ctx, AnySdkVersion, "a", optional, implicit, buildPath(ctx, "a"), installPath(ctx, "a"), nil)
+ m.AddContext(ctx, AnySdkVersion, "b", optional, implicit, buildPath(ctx, "b"), installPath(ctx, "b"), nil)
+ m.AddContext(ctx, AnySdkVersion, "c", optional, implicit, buildPath(ctx, "c"), installPath(ctx, "c"), nil)
// Add some libraries with nested subcontexts.
m1 := make(ClassLoaderContextMap)
- m1.AddContext(ctx, AnySdkVersion, "a1", optional, buildPath(ctx, "a1"), installPath(ctx, "a1"), nil)
- m1.AddContext(ctx, AnySdkVersion, "b1", optional, buildPath(ctx, "b1"), installPath(ctx, "b1"), nil)
+ m1.AddContext(ctx, AnySdkVersion, "a1", optional, implicit, buildPath(ctx, "a1"), installPath(ctx, "a1"), nil)
+ m1.AddContext(ctx, AnySdkVersion, "b1", optional, implicit, buildPath(ctx, "b1"), installPath(ctx, "b1"), nil)
m2 := make(ClassLoaderContextMap)
- m2.AddContext(ctx, AnySdkVersion, "a2", optional, buildPath(ctx, "a2"), installPath(ctx, "a2"), nil)
- m2.AddContext(ctx, AnySdkVersion, "b2", optional, buildPath(ctx, "b2"), installPath(ctx, "b2"), nil)
- m2.AddContext(ctx, AnySdkVersion, "c2", optional, buildPath(ctx, "c2"), installPath(ctx, "c2"), m1)
+ m2.AddContext(ctx, AnySdkVersion, "a2", optional, implicit, buildPath(ctx, "a2"), installPath(ctx, "a2"), nil)
+ m2.AddContext(ctx, AnySdkVersion, "b2", optional, implicit, buildPath(ctx, "b2"), installPath(ctx, "b2"), nil)
+ m2.AddContext(ctx, AnySdkVersion, "c2", optional, implicit, buildPath(ctx, "c2"), installPath(ctx, "c2"), m1)
m3 := make(ClassLoaderContextMap)
- m3.AddContext(ctx, AnySdkVersion, "a3", optional, buildPath(ctx, "a3"), installPath(ctx, "a3"), nil)
- m3.AddContext(ctx, AnySdkVersion, "b3", optional, buildPath(ctx, "b3"), installPath(ctx, "b3"), nil)
+ m3.AddContext(ctx, AnySdkVersion, "a3", optional, implicit, buildPath(ctx, "a3"), installPath(ctx, "a3"), nil)
+ m3.AddContext(ctx, AnySdkVersion, "b3", optional, implicit, buildPath(ctx, "b3"), installPath(ctx, "b3"), nil)
- m.AddContext(ctx, AnySdkVersion, "d", optional, buildPath(ctx, "d"), installPath(ctx, "d"), m2)
+ m.AddContext(ctx, AnySdkVersion, "d", optional, implicit, buildPath(ctx, "d"), installPath(ctx, "d"), m2)
// When the same library is both in conditional and unconditional context, it should be removed
// from conditional context.
- m.AddContext(ctx, 42, "f", optional, buildPath(ctx, "f"), installPath(ctx, "f"), nil)
- m.AddContext(ctx, AnySdkVersion, "f", optional, buildPath(ctx, "f"), installPath(ctx, "f"), nil)
+ m.AddContext(ctx, 42, "f", optional, implicit, buildPath(ctx, "f"), installPath(ctx, "f"), nil)
+ m.AddContext(ctx, AnySdkVersion, "f", optional, implicit, buildPath(ctx, "f"), installPath(ctx, "f"), nil)
// Merge map with implicit root library that is among toplevel contexts => does nothing.
m.AddContextMap(m1, "c")
@@ -85,12 +86,12 @@
m.AddContextMap(m3, "m_g")
// Compatibility libraries with unknown install paths get default paths.
- m.AddContext(ctx, 29, AndroidHidlManager, optional, buildPath(ctx, AndroidHidlManager), nil, nil)
- m.AddContext(ctx, 29, AndroidHidlBase, optional, buildPath(ctx, AndroidHidlBase), nil, nil)
+ m.AddContext(ctx, 29, AndroidHidlManager, optional, implicit, buildPath(ctx, AndroidHidlManager), nil, nil)
+ m.AddContext(ctx, 29, AndroidHidlBase, optional, implicit, buildPath(ctx, AndroidHidlBase), nil, nil)
// Add "android.test.mock" to conditional CLC, observe that is gets removed because it is only
// needed as a compatibility library if "android.test.runner" is in CLC as well.
- m.AddContext(ctx, 30, AndroidTestMock, optional, buildPath(ctx, AndroidTestMock), nil, nil)
+ m.AddContext(ctx, 30, AndroidTestMock, optional, implicit, buildPath(ctx, AndroidTestMock), nil, nil)
valid, validationError := validateClassLoaderContext(m)
@@ -164,11 +165,12 @@
func TestCLCJson(t *testing.T) {
ctx := testContext()
optional := false
+ implicit := true
m := make(ClassLoaderContextMap)
- m.AddContext(ctx, 28, "a", optional, buildPath(ctx, "a"), installPath(ctx, "a"), nil)
- m.AddContext(ctx, 29, "b", optional, buildPath(ctx, "b"), installPath(ctx, "b"), nil)
- m.AddContext(ctx, 30, "c", optional, buildPath(ctx, "c"), installPath(ctx, "c"), nil)
- m.AddContext(ctx, AnySdkVersion, "d", optional, buildPath(ctx, "d"), installPath(ctx, "d"), nil)
+ m.AddContext(ctx, 28, "a", optional, implicit, buildPath(ctx, "a"), installPath(ctx, "a"), nil)
+ m.AddContext(ctx, 29, "b", optional, implicit, buildPath(ctx, "b"), installPath(ctx, "b"), nil)
+ m.AddContext(ctx, 30, "c", optional, implicit, buildPath(ctx, "c"), installPath(ctx, "c"), nil)
+ m.AddContext(ctx, AnySdkVersion, "d", optional, implicit, buildPath(ctx, "d"), installPath(ctx, "d"), nil)
jsonCLC := toJsonClassLoaderContext(m)
restored := fromJsonClassLoaderContext(ctx, jsonCLC)
android.AssertIntEquals(t, "The size of the maps should be the same.", len(m), len(restored))
@@ -189,12 +191,13 @@
func testCLCUnknownPath(t *testing.T, whichPath string) {
ctx := testContext()
optional := false
+ implicit := true
m := make(ClassLoaderContextMap)
if whichPath == "build" {
- m.AddContext(ctx, AnySdkVersion, "a", optional, nil, nil, nil)
+ m.AddContext(ctx, AnySdkVersion, "a", optional, implicit, nil, nil, nil)
} else {
- m.AddContext(ctx, AnySdkVersion, "a", optional, buildPath(ctx, "a"), nil, nil)
+ m.AddContext(ctx, AnySdkVersion, "a", optional, implicit, buildPath(ctx, "a"), nil, nil)
}
// The library should be added to <uses-library> tags by the manifest_fixer.
@@ -229,10 +232,11 @@
func TestCLCNestedConditional(t *testing.T) {
ctx := testContext()
optional := false
+ implicit := true
m1 := make(ClassLoaderContextMap)
- m1.AddContext(ctx, 42, "a", optional, buildPath(ctx, "a"), installPath(ctx, "a"), nil)
+ m1.AddContext(ctx, 42, "a", optional, implicit, buildPath(ctx, "a"), installPath(ctx, "a"), nil)
m := make(ClassLoaderContextMap)
- err := m.addContext(ctx, AnySdkVersion, "b", optional, buildPath(ctx, "b"), installPath(ctx, "b"), m1)
+ err := m.addContext(ctx, AnySdkVersion, "b", optional, implicit, buildPath(ctx, "b"), installPath(ctx, "b"), m1)
checkError(t, err, "nested class loader context shouldn't have conditional part")
}
@@ -241,11 +245,12 @@
func TestCLCSdkVersionOrder(t *testing.T) {
ctx := testContext()
optional := false
+ implicit := true
m := make(ClassLoaderContextMap)
- m.AddContext(ctx, 28, "a", optional, buildPath(ctx, "a"), installPath(ctx, "a"), nil)
- m.AddContext(ctx, 29, "b", optional, buildPath(ctx, "b"), installPath(ctx, "b"), nil)
- m.AddContext(ctx, 30, "c", optional, buildPath(ctx, "c"), installPath(ctx, "c"), nil)
- m.AddContext(ctx, AnySdkVersion, "d", optional, buildPath(ctx, "d"), installPath(ctx, "d"), nil)
+ m.AddContext(ctx, 28, "a", optional, implicit, buildPath(ctx, "a"), installPath(ctx, "a"), nil)
+ m.AddContext(ctx, 29, "b", optional, implicit, buildPath(ctx, "b"), installPath(ctx, "b"), nil)
+ m.AddContext(ctx, 30, "c", optional, implicit, buildPath(ctx, "c"), installPath(ctx, "c"), nil)
+ m.AddContext(ctx, AnySdkVersion, "d", optional, implicit, buildPath(ctx, "d"), installPath(ctx, "d"), nil)
valid, validationError := validateClassLoaderContext(m)
diff --git a/dexpreopt/config.go b/dexpreopt/config.go
index 7a74506..de3666a 100644
--- a/dexpreopt/config.go
+++ b/dexpreopt/config.go
@@ -159,7 +159,7 @@
}
func constructPath(ctx android.PathContext, path string) android.Path {
- buildDirPrefix := ctx.Config().BuildDir() + "/"
+ buildDirPrefix := ctx.Config().SoongOutDir() + "/"
if path == "" {
return nil
} else if strings.HasPrefix(path, buildDirPrefix) {
diff --git a/dexpreopt/dexpreopt.go b/dexpreopt/dexpreopt.go
index 4c6ae82..1401c75 100644
--- a/dexpreopt/dexpreopt.go
+++ b/dexpreopt/dexpreopt.go
@@ -430,11 +430,6 @@
}
}
- // Never enable on eng.
- if global.IsEng {
- debugInfo = false
- }
-
if debugInfo {
cmd.Flag("--generate-mini-debug-info")
} else {
diff --git a/java/android_manifest.go b/java/android_manifest.go
index 1f7234d..38065f1 100644
--- a/java/android_manifest.go
+++ b/java/android_manifest.go
@@ -71,7 +71,9 @@
args = append(args, "--use-embedded-dex")
}
- requiredUsesLibs, optionalUsesLibs := classLoaderContexts.UsesLibs()
+ // manifest_fixer should add only the implicit SDK libraries inferred by Soong, not those added
+ // explicitly via `uses_libs`/`optional_uses_libs`.
+ requiredUsesLibs, optionalUsesLibs := classLoaderContexts.ImplicitUsesLibs()
for _, usesLib := range requiredUsesLibs {
args = append(args, "--uses-library", usesLib)
}
diff --git a/java/app.go b/java/app.go
index e7661df..5104f07 100755
--- a/java/app.go
+++ b/java/app.go
@@ -1224,17 +1224,28 @@
func (u *usesLibrary) deps(ctx android.BottomUpMutatorContext, hasFrameworkLibs bool) {
if !ctx.Config().UnbundledBuild() || ctx.Config().UnbundledBuildImage() {
- ctx.AddVariationDependencies(nil, usesLibReqTag, u.usesLibraryProperties.Uses_libs...)
- ctx.AddVariationDependencies(nil, usesLibOptTag, u.presentOptionalUsesLibs(ctx)...)
+ reqTag := makeUsesLibraryDependencyTag(dexpreopt.AnySdkVersion, false, false)
+ ctx.AddVariationDependencies(nil, reqTag, u.usesLibraryProperties.Uses_libs...)
+
+ optTag := makeUsesLibraryDependencyTag(dexpreopt.AnySdkVersion, true, false)
+ ctx.AddVariationDependencies(nil, optTag, u.presentOptionalUsesLibs(ctx)...)
+
// Only add these extra dependencies if the module depends on framework libs. This avoids
// creating a cyclic dependency:
// e.g. framework-res -> org.apache.http.legacy -> ... -> framework-res.
if hasFrameworkLibs {
- // Dexpreopt needs paths to the dex jars of these libraries in order to construct
- // class loader context for dex2oat. Add them as a dependency with a special tag.
- ctx.AddVariationDependencies(nil, usesLibCompat29ReqTag, dexpreopt.CompatUsesLibs29...)
- ctx.AddVariationDependencies(nil, usesLibCompat28OptTag, dexpreopt.OptionalCompatUsesLibs28...)
- ctx.AddVariationDependencies(nil, usesLibCompat30OptTag, dexpreopt.OptionalCompatUsesLibs30...)
+ // Add implicit <uses-library> dependencies on compatibility libraries. Some of them are
+ // optional, and some required --- this depends on the most common usage of the library
+ // and may be wrong for some apps (they need explicit `uses_libs`/`optional_uses_libs`).
+
+ compat28OptTag := makeUsesLibraryDependencyTag(28, true, true)
+ ctx.AddVariationDependencies(nil, compat28OptTag, dexpreopt.OptionalCompatUsesLibs28...)
+
+ compat29ReqTag := makeUsesLibraryDependencyTag(29, false, true)
+ ctx.AddVariationDependencies(nil, compat29ReqTag, dexpreopt.CompatUsesLibs29...)
+
+ compat30OptTag := makeUsesLibraryDependencyTag(30, true, true)
+ ctx.AddVariationDependencies(nil, compat30OptTag, dexpreopt.OptionalCompatUsesLibs30...)
}
}
}
@@ -1293,7 +1304,7 @@
replaceInList(u.usesLibraryProperties.Uses_libs, dep, libName)
replaceInList(u.usesLibraryProperties.Optional_uses_libs, dep, libName)
}
- clcMap.AddContext(ctx, tag.sdkVersion, libName, tag.optional,
+ clcMap.AddContext(ctx, tag.sdkVersion, libName, tag.optional, tag.implicit,
lib.DexJarBuildPath(), lib.DexJarInstallPath(), lib.ClassLoaderContexts())
} else if ctx.Config().AllowMissingDependencies() {
ctx.AddMissingDependencies([]string{dep})
diff --git a/java/app_test.go b/java/app_test.go
index c14c65d..07439fc 100644
--- a/java/app_test.go
+++ b/java/app_test.go
@@ -1737,7 +1737,7 @@
foo := result.ModuleForTests("foo", "android_common")
- outSoongDir := result.Config.BuildDir()
+ outSoongDir := result.Config.SoongOutDir()
outputs := foo.AllOutputs()
outputMap := make(map[string]bool)
@@ -2398,14 +2398,7 @@
expectManifestFixerArgs := `--extract-native-libs=true ` +
`--uses-library qux ` +
`--uses-library quuz ` +
- `--uses-library foo ` + // TODO(b/132357300): "foo" should not be passed to manifest_fixer
- `--uses-library com.non.sdk.lib ` + // TODO(b/132357300): "com.non.sdk.lib" should not be passed to manifest_fixer
- `--uses-library runtime-library ` +
- `--uses-library runtime-required-x ` + // TODO(b/132357300): "runtime-required-x" should not be passed to manifest_fixer
- `--uses-library runtime-required-y ` + // TODO(b/132357300): "runtime-required-y" should not be passed to manifest_fixer
- `--optional-uses-library bar ` + // TODO(b/132357300): "bar" should not be passed to manifest_fixer
- `--optional-uses-library runtime-optional-x ` + // TODO(b/132357300): "runtime-optional-x" should not be passed to manifest_fixer
- `--optional-uses-library runtime-optional-y` // TODO(b/132357300): "runtime-optional-y" should not be passed to manifest_fixer
+ `--uses-library runtime-library`
android.AssertStringEquals(t, "manifest_fixer args", expectManifestFixerArgs, actualManifestFixerArgs)
// Test that all libraries are verified (library order matters).
diff --git a/java/base.go b/java/base.go
index ea5b137..86022c3 100644
--- a/java/base.go
+++ b/java/base.go
@@ -606,10 +606,8 @@
if component, ok := dep.(SdkLibraryComponentDependency); ok {
if lib := component.OptionalSdkLibraryImplementation(); lib != nil {
// Add library as optional if it's one of the optional compatibility libs.
- tag := usesLibReqTag
- if android.InList(*lib, dexpreopt.OptionalCompatUsesLibs) {
- tag = usesLibOptTag
- }
+ optional := android.InList(*lib, dexpreopt.OptionalCompatUsesLibs)
+ tag := makeUsesLibraryDependencyTag(dexpreopt.AnySdkVersion, optional, true)
ctx.AddVariationDependencies(nil, tag, *lib)
}
}
@@ -793,7 +791,7 @@
// Manually specify build directory in case it is not under the repo root.
// (javac doesn't seem to expand into symbolic links when searching for patch-module targets, so
// just adding a symlink under the root doesn't help.)
- patchPaths := []string{".", ctx.Config().BuildDir()}
+ patchPaths := []string{".", ctx.Config().SoongOutDir()}
// b/150878007
//
diff --git a/java/bootclasspath_fragment.go b/java/bootclasspath_fragment.go
index bb542c4..7577316 100644
--- a/java/bootclasspath_fragment.go
+++ b/java/bootclasspath_fragment.go
@@ -538,7 +538,7 @@
global := dexpreopt.GetGlobalConfig(ctx)
possibleUpdatableModules := gatherPossibleApexModuleNamesAndStems(ctx, b.properties.Contents, bootclasspathFragmentContentDepTag)
- jars := global.ApexBootJars.Filter(possibleUpdatableModules)
+ jars, unknown := global.ApexBootJars.Filter(possibleUpdatableModules)
// TODO(satayev): for apex_test we want to include all contents unconditionally to classpaths
// config. However, any test specific jars would not be present in ApexBootJars. Instead,
@@ -546,6 +546,12 @@
// 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 global.ApexBootJars.Len() != 0 && !android.IsModuleInVersionedSdk(ctx.Module()) {
+ unknown = android.RemoveListFromList(unknown, b.properties.Coverage.Contents)
+ _, unknown = android.RemoveFromList("core-icu4j", unknown)
+ if len(unknown) > 0 {
+ ctx.ModuleErrorf("%s in contents must also be declared in PRODUCT_APEX_BOOT_JARS", unknown)
+ }
}
return jars
}
diff --git a/java/core-libraries/Android.bp b/java/core-libraries/Android.bp
index 51d998a..b198c24 100644
--- a/java/core-libraries/Android.bp
+++ b/java/core-libraries/Android.bp
@@ -24,6 +24,10 @@
// core libraries.
//
// Don't use this directly, use "sdk_version: core_current".
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
java_library {
name: "core.current.stubs",
visibility: ["//visibility:public"],
diff --git a/java/java.go b/java/java.go
index b46324f..4c2ca9b 100644
--- a/java/java.go
+++ b/java/java.go
@@ -248,15 +248,24 @@
type usesLibraryDependencyTag struct {
dependencyTag
- sdkVersion int // SDK version in which the library appared as a standalone library.
- optional bool // If the dependency is optional or required.
+
+ // SDK version in which the library appared as a standalone library.
+ sdkVersion int
+
+ // If the dependency is optional or required.
+ optional bool
+
+ // Whether this is an implicit dependency inferred by Soong, or an explicit one added via
+ // `uses_libs`/`optional_uses_libs` properties.
+ implicit bool
}
-func makeUsesLibraryDependencyTag(sdkVersion int, optional bool) usesLibraryDependencyTag {
+func makeUsesLibraryDependencyTag(sdkVersion int, optional bool, implicit bool) usesLibraryDependencyTag {
return usesLibraryDependencyTag{
dependencyTag: dependencyTag{name: fmt.Sprintf("uses-library-%d", sdkVersion)},
sdkVersion: sdkVersion,
optional: optional,
+ implicit: implicit,
}
}
@@ -285,11 +294,6 @@
syspropPublicStubDepTag = dependencyTag{name: "sysprop public stub"}
jniInstallTag = installDependencyTag{name: "jni install"}
binaryInstallTag = installDependencyTag{name: "binary install"}
- usesLibReqTag = makeUsesLibraryDependencyTag(dexpreopt.AnySdkVersion, false)
- usesLibOptTag = makeUsesLibraryDependencyTag(dexpreopt.AnySdkVersion, true)
- usesLibCompat28OptTag = makeUsesLibraryDependencyTag(28, true)
- usesLibCompat29ReqTag = makeUsesLibraryDependencyTag(29, false)
- usesLibCompat30OptTag = makeUsesLibraryDependencyTag(30, true)
)
func IsLibDepTag(depTag blueprint.DependencyTag) bool {
@@ -1813,8 +1817,10 @@
depTag := ctx.OtherModuleDependencyTag(depModule)
if depTag == libTag {
// Ok, propagate <uses-library> through non-static library dependencies.
- } else if tag, ok := depTag.(usesLibraryDependencyTag); ok && tag.sdkVersion == dexpreopt.AnySdkVersion {
- // Ok, propagate <uses-library> through non-compatibility <uses-library> dependencies.
+ } else if tag, ok := depTag.(usesLibraryDependencyTag); ok &&
+ tag.sdkVersion == dexpreopt.AnySdkVersion && tag.implicit {
+ // Ok, propagate <uses-library> through non-compatibility implicit <uses-library>
+ // dependencies.
} else if depTag == staticLibTag {
// Propagate <uses-library> through static library dependencies, unless it is a component
// library (such as stubs). Component libraries have a dependency on their SDK library,
@@ -1832,7 +1838,7 @@
// <uses_library> and should not be added to CLC, but the transitive <uses-library> dependencies
// from its CLC should be added to the current CLC.
if sdkLib != nil {
- clcMap.AddContext(ctx, dexpreopt.AnySdkVersion, *sdkLib, false,
+ clcMap.AddContext(ctx, dexpreopt.AnySdkVersion, *sdkLib, false, true,
dep.DexJarBuildPath(), dep.DexJarInstallPath(), dep.ClassLoaderContexts())
} else {
clcMap.AddContextMap(dep.ClassLoaderContexts(), depName)
diff --git a/java/java_test.go b/java/java_test.go
index b6780c2..8bb017f 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -1183,7 +1183,7 @@
break
}
}
- if expected != android.StringPathRelativeToTop(ctx.Config().BuildDir(), got) {
+ if expected != android.StringPathRelativeToTop(ctx.Config().SoongOutDir(), got) {
t.Errorf("Unexpected patch-module flag for module %q - expected %q, but got %q", moduleName, expected, got)
}
}
diff --git a/java/systemserver_classpath_fragment.go b/java/systemserver_classpath_fragment.go
index 6c2a5b5..5311f62 100644
--- a/java/systemserver_classpath_fragment.go
+++ b/java/systemserver_classpath_fragment.go
@@ -107,7 +107,16 @@
global := dexpreopt.GetGlobalConfig(ctx)
possibleUpdatableModules := gatherPossibleApexModuleNamesAndStems(ctx, s.properties.Contents, systemServerClasspathFragmentContentDepTag)
- return global.ApexSystemServerJars.Filter(possibleUpdatableModules)
+ jars, unknown := global.ApexSystemServerJars.Filter(possibleUpdatableModules)
+ // TODO(satayev): remove geotz ssc_fragment, since geotz is not part of SSCP anymore.
+ _, unknown = android.RemoveFromList("geotz", unknown)
+
+ // For non test apexes, make sure that all contents are actually declared in make.
+ if global.ApexSystemServerJars.Len() > 0 && len(unknown) > 0 {
+ ctx.ModuleErrorf("%s in contents must also be declared in PRODUCT_UPDATABLE_SYSTEM_SERVER_JARS", unknown)
+ }
+
+ return jars
}
type systemServerClasspathFragmentContentDependencyTag struct {
diff --git a/mk2rbc/Android.bp b/mk2rbc/Android.bp
index 3ea3f7f..4fa3eb6 100644
--- a/mk2rbc/Android.bp
+++ b/mk2rbc/Android.bp
@@ -13,6 +13,10 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
blueprint_go_binary {
name: "mk2rbc",
srcs: ["cmd/mk2rbc.go"],
diff --git a/python/binary.go b/python/binary.go
index b106536..bc2768c 100644
--- a/python/binary.go
+++ b/python/binary.go
@@ -38,6 +38,7 @@
Main string
Srcs bazel.LabelListAttribute
Data bazel.LabelListAttribute
+ Deps bazel.LabelListAttribute
Python_version string
}
@@ -81,11 +82,13 @@
srcs := android.BazelLabelForModuleSrcExcludes(ctx, m.properties.Srcs, m.properties.Exclude_srcs)
data := android.BazelLabelForModuleSrc(ctx, m.properties.Data)
+ deps := android.BazelLabelForModuleDeps(ctx, m.properties.Libs)
attrs := &bazelPythonBinaryAttributes{
Main: main,
Srcs: bazel.MakeLabelListAttribute(srcs),
Data: bazel.MakeLabelListAttribute(data),
+ Deps: bazel.MakeLabelListAttribute(deps),
Python_version: python_version,
}
diff --git a/python/library.go b/python/library.go
index 9663b3c..a132216 100644
--- a/python/library.go
+++ b/python/library.go
@@ -17,11 +17,17 @@
// This file contains the module types for building Python library.
import (
+ "fmt"
+
"android/soong/android"
+ "android/soong/bazel"
+ "github.com/google/blueprint/proptools"
)
func init() {
registerPythonLibraryComponents(android.InitRegistrationContext)
+ android.RegisterBp2BuildMutator("python_library_host", PythonLibraryHostBp2Build)
+ android.RegisterBp2BuildMutator("python_library", PythonLibraryBp2Build)
}
func registerPythonLibraryComponents(ctx android.RegistrationContext) {
@@ -32,11 +38,79 @@
func PythonLibraryHostFactory() android.Module {
module := newModule(android.HostSupported, android.MultilibFirst)
+ android.InitBazelModule(module)
+
return module.init()
}
+type bazelPythonLibraryAttributes struct {
+ Srcs bazel.LabelListAttribute
+ Data bazel.LabelListAttribute
+ Deps bazel.LabelListAttribute
+ Srcs_version string
+}
+
+func PythonLibraryHostBp2Build(ctx android.TopDownMutatorContext) {
+ pythonLibBp2Build(ctx, "python_library_host")
+}
+
+func PythonLibraryBp2Build(ctx android.TopDownMutatorContext) {
+ pythonLibBp2Build(ctx, "python_library")
+}
+
+func pythonLibBp2Build(ctx android.TopDownMutatorContext, modType string) {
+ m, ok := ctx.Module().(*Module)
+ if !ok || !m.ConvertWithBp2build(ctx) {
+ return
+ }
+
+ // a Module can be something other than a `modType`
+ if ctx.ModuleType() != modType {
+ return
+ }
+
+ // TODO(b/182306917): this doesn't fully handle all nested props versioned
+ // by the python version, which would have been handled by the version split
+ // mutator. This is sufficient for very simple python_library modules under
+ // Bionic.
+ py3Enabled := proptools.BoolDefault(m.properties.Version.Py3.Enabled, true)
+ py2Enabled := proptools.BoolDefault(m.properties.Version.Py2.Enabled, false)
+ var python_version string
+ if py2Enabled && !py3Enabled {
+ python_version = "PY2"
+ } else if !py2Enabled && py3Enabled {
+ python_version = "PY3"
+ } else if !py2Enabled && !py3Enabled {
+ panic(fmt.Errorf(
+ "error for '%s' module: bp2build's %s converter doesn't understand having "+
+ "neither py2 nor py3 enabled", m.Name(), modType))
+ } else {
+ // do nothing, since python_version defaults to PY2ANDPY3
+ }
+
+ srcs := android.BazelLabelForModuleSrcExcludes(ctx, m.properties.Srcs, m.properties.Exclude_srcs)
+ data := android.BazelLabelForModuleSrc(ctx, m.properties.Data)
+ deps := android.BazelLabelForModuleDeps(ctx, m.properties.Libs)
+
+ attrs := &bazelPythonLibraryAttributes{
+ Srcs: bazel.MakeLabelListAttribute(srcs),
+ Data: bazel.MakeLabelListAttribute(data),
+ Deps: bazel.MakeLabelListAttribute(deps),
+ Srcs_version: python_version,
+ }
+
+ props := bazel.BazelTargetModuleProperties{
+ // Use the native py_library rule.
+ Rule_class: "py_library",
+ }
+
+ ctx.CreateBazelTargetModule(m.Name(), props, attrs)
+}
+
func PythonLibraryFactory() android.Module {
module := newModule(android.HostAndDeviceSupported, android.MultilibBoth)
+ android.InitBazelModule(module)
+
return module.init()
}
diff --git a/rust/config/allowed_list.go b/rust/config/allowed_list.go
index 926d2ac..63a8f04 100644
--- a/rust/config/allowed_list.go
+++ b/rust/config/allowed_list.go
@@ -13,6 +13,7 @@
"external/minijail",
"external/rust",
"external/selinux/libselinux",
+ "external/uwb",
"external/vm_tools/p9",
"frameworks/native/libs/binder/rust",
"frameworks/proto_logging/stats",
@@ -25,6 +26,7 @@
"system/extras/simpleperf",
"system/hardware/interfaces/keystore2",
"system/librustutils",
+ "system/logging/liblog",
"system/logging/rust",
"system/security",
"system/tools/aidl",
diff --git a/rust/project_json_test.go b/rust/project_json_test.go
index bdd54c5..f7b6681 100644
--- a/rust/project_json_test.go
+++ b/rust/project_json_test.go
@@ -36,7 +36,7 @@
// The JSON file is generated via WriteFileToOutputDir. Therefore, it
// won't appear in the Output of the TestingSingleton. Manually verify
// it exists.
- content, err := ioutil.ReadFile(filepath.Join(result.Config.BuildDir(), rustProjectJsonFileName))
+ content, err := ioutil.ReadFile(filepath.Join(result.Config.SoongOutDir(), rustProjectJsonFileName))
if err != nil {
t.Errorf("rust-project.json has not been generated")
}
diff --git a/scripts/construct_context.py b/scripts/construct_context.py
index f0658ba..3f601c3 100755
--- a/scripts/construct_context.py
+++ b/scripts/construct_context.py
@@ -25,57 +25,78 @@
def parse_args(args):
- """Parse commandline arguments."""
- parser = argparse.ArgumentParser()
- parser.add_argument('--target-sdk-version', default='', dest='sdk',
- help='specify target SDK version (as it appears in the manifest)')
- parser.add_argument('--host-context-for-sdk', dest='host_contexts',
- action='append', nargs=2, metavar=('sdk','context'),
- help='specify context on host for a given SDK version or "any" version')
- parser.add_argument('--target-context-for-sdk', dest='target_contexts',
- action='append', nargs=2, metavar=('sdk','context'),
- help='specify context on target for a given SDK version or "any" version')
- return parser.parse_args(args)
+ """Parse commandline arguments."""
+ parser = argparse.ArgumentParser()
+ parser.add_argument(
+ '--target-sdk-version',
+ default='',
+ dest='sdk',
+ help='specify target SDK version (as it appears in the manifest)')
+ parser.add_argument(
+ '--host-context-for-sdk',
+ dest='host_contexts',
+ action='append',
+ nargs=2,
+ metavar=('sdk', 'context'),
+ help='specify context on host for a given SDK version or "any" version')
+ parser.add_argument(
+ '--target-context-for-sdk',
+ dest='target_contexts',
+ action='append',
+ nargs=2,
+ metavar=('sdk', 'context'),
+ help='specify context on target for a given SDK version or "any" '
+ 'version'
+ )
+ return parser.parse_args(args)
+
# Special keyword that means that the context should be added to class loader
# context regardless of the target SDK version.
any_sdk = 'any'
+
# We assume that the order of context arguments passed to this script is
# correct (matches the order computed by package manager). It is possible to
# sort them here, but Soong needs to use deterministic order anyway, so it can
# as well use the correct order.
def construct_context(versioned_contexts, target_sdk):
- context = []
- for [sdk, ctx] in versioned_contexts:
- if sdk == any_sdk or compare_version_gt(sdk, target_sdk):
- context.append(ctx)
- return context
+ context = []
+ for [sdk, ctx] in versioned_contexts:
+ if sdk == any_sdk or compare_version_gt(sdk, target_sdk):
+ context.append(ctx)
+ return context
+
def construct_contexts(args):
- host_context = construct_context(args.host_contexts, args.sdk)
- target_context = construct_context(args.target_contexts, args.sdk)
- context_sep = '#'
- return ('class_loader_context_arg=--class-loader-context=PCL[]{%s} ; ' % context_sep.join(host_context) +
- 'stored_class_loader_context_arg=--stored-class-loader-context=PCL[]{%s}' % context_sep.join(target_context))
+ host_context = construct_context(args.host_contexts, args.sdk)
+ target_context = construct_context(args.target_contexts, args.sdk)
+ context_sep = '#'
+ return (
+ 'class_loader_context_arg=--class-loader-context=PCL[]{%s} ; ' %
+ context_sep.join(host_context) +
+ 'stored_class_loader_context_arg=--stored-class-loader-context=PCL[]{%s}' #pylint: disable=line-too-long
+ % context_sep.join(target_context))
+
def main():
- """Program entry point."""
- try:
- args = parse_args(sys.argv[1:])
- if not args.sdk:
- raise SystemExit('target sdk version is not set')
- if not args.host_contexts:
- args.host_contexts = []
- if not args.target_contexts:
- args.target_contexts = []
+ """Program entry point."""
+ try:
+ args = parse_args(sys.argv[1:])
+ if not args.sdk:
+ raise SystemExit('target sdk version is not set')
+ if not args.host_contexts:
+ args.host_contexts = []
+ if not args.target_contexts:
+ args.target_contexts = []
- print(construct_contexts(args))
+ print(construct_contexts(args))
- # pylint: disable=broad-except
- except Exception as err:
- print('error: ' + str(err), file=sys.stderr)
- sys.exit(-1)
+ # pylint: disable=broad-except
+ except Exception as err:
+ print('error: ' + str(err), file=sys.stderr)
+ sys.exit(-1)
+
if __name__ == '__main__':
- main()
+ main()
diff --git a/scripts/construct_context_test.py b/scripts/construct_context_test.py
index 3b05f90..2ff5ac5 100755
--- a/scripts/construct_context_test.py
+++ b/scripts/construct_context_test.py
@@ -23,53 +23,63 @@
sys.dont_write_bytecode = True
+
def construct_contexts(arglist):
- args = cc.parse_args(arglist)
- return cc.construct_contexts(args)
+ args = cc.parse_args(arglist)
+ return cc.construct_contexts(args)
+
contexts = [
- '--host-context-for-sdk', '28', 'PCL[out/zdir/z.jar]',
- '--target-context-for-sdk', '28', 'PCL[/system/z.jar]',
- '--host-context-for-sdk', '29', 'PCL[out/xdir/x.jar]#PCL[out/ydir/y.jar]',
- '--target-context-for-sdk', '29', 'PCL[/system/x.jar]#PCL[/product/y.jar]',
- '--host-context-for-sdk', 'any', 'PCL[out/adir/a.jar]#PCL[out/bdir/b.jar]',
- '--target-context-for-sdk', 'any', 'PCL[/system/a.jar]#PCL[/product/b.jar]',
+ '--host-context-for-sdk',
+ '28',
+ 'PCL[out/zdir/z.jar]',
+ '--target-context-for-sdk',
+ '28',
+ 'PCL[/system/z.jar]',
+ '--host-context-for-sdk',
+ '29',
+ 'PCL[out/xdir/x.jar]#PCL[out/ydir/y.jar]',
+ '--target-context-for-sdk',
+ '29',
+ 'PCL[/system/x.jar]#PCL[/product/y.jar]',
+ '--host-context-for-sdk',
+ 'any',
+ 'PCL[out/adir/a.jar]#PCL[out/bdir/b.jar]',
+ '--target-context-for-sdk',
+ 'any',
+ 'PCL[/system/a.jar]#PCL[/product/b.jar]',
]
+#pylint: disable=line-too-long
class ConstructContextTest(unittest.TestCase):
- def test_construct_context_28(self):
- args = ['--target-sdk-version', '28'] + contexts
- result = construct_contexts(args)
- expect = ('class_loader_context_arg=--class-loader-context=PCL[]{PCL[out/xdir/x.jar]'
- '#PCL[out/ydir/y.jar]'
- '#PCL[out/adir/a.jar]'
- '#PCL[out/bdir/b.jar]}'
- ' ; '
- 'stored_class_loader_context_arg=--stored-class-loader-context=PCL[]{PCL[/system/x.jar]'
- '#PCL[/product/y.jar]'
- '#PCL[/system/a.jar]'
- '#PCL[/product/b.jar]}')
- self.assertEqual(result, expect)
- def test_construct_context_29(self):
- args = ['--target-sdk-version', '29'] + contexts
- result = construct_contexts(args)
- expect = ('class_loader_context_arg=--class-loader-context=PCL[]{PCL[out/adir/a.jar]'
- '#PCL[out/bdir/b.jar]}'
- ' ; '
- 'stored_class_loader_context_arg=--stored-class-loader-context=PCL[]{PCL[/system/a.jar]'
- '#PCL[/product/b.jar]}')
- self.assertEqual(result, expect)
+ def test_construct_context_28(self):
+ args = ['--target-sdk-version', '28'] + contexts
+ result = construct_contexts(args)
+ expect = (
+ 'class_loader_context_arg=--class-loader-context=PCL[]{PCL[out/xdir/x.jar]#PCL[out/ydir/y.jar]#PCL[out/adir/a.jar]#PCL[out/bdir/b.jar]}'
+ ' ; '
+ 'stored_class_loader_context_arg=--stored-class-loader-context=PCL[]{PCL[/system/x.jar]#PCL[/product/y.jar]#PCL[/system/a.jar]#PCL[/product/b.jar]}')
+ self.assertEqual(result, expect)
- def test_construct_context_S(self):
- args = ['--target-sdk-version', 'S'] + contexts
- result = construct_contexts(args)
- expect = ('class_loader_context_arg=--class-loader-context=PCL[]{PCL[out/adir/a.jar]'
- '#PCL[out/bdir/b.jar]}'
- ' ; '
- 'stored_class_loader_context_arg=--stored-class-loader-context=PCL[]{PCL[/system/a.jar]'
- '#PCL[/product/b.jar]}')
- self.assertEqual(result, expect)
+ def test_construct_context_29(self):
+ args = ['--target-sdk-version', '29'] + contexts
+ result = construct_contexts(args)
+ expect = (
+ 'class_loader_context_arg=--class-loader-context=PCL[]{PCL[out/adir/a.jar]#PCL[out/bdir/b.jar]}'
+ ' ; '
+ 'stored_class_loader_context_arg=--stored-class-loader-context=PCL[]{PCL[/system/a.jar]#PCL[/product/b.jar]}')
+ self.assertEqual(result, expect)
+
+ def test_construct_context_S(self):
+ args = ['--target-sdk-version', 'S'] + contexts
+ result = construct_contexts(args)
+ expect = (
+ 'class_loader_context_arg=--class-loader-context=PCL[]{PCL[out/adir/a.jar]#PCL[out/bdir/b.jar]}'
+ ' ; '
+ 'stored_class_loader_context_arg=--stored-class-loader-context=PCL[]{PCL[/system/a.jar]#PCL[/product/b.jar]}')
+ self.assertEqual(result, expect)
+#pylint: enable=line-too-long
if __name__ == '__main__':
- unittest.main(verbosity=2)
+ unittest.main(verbosity=2)
diff --git a/scripts/conv_linker_config.py b/scripts/conv_linker_config.py
index 92f79da..e46efe4 100644
--- a/scripts/conv_linker_config.py
+++ b/scripts/conv_linker_config.py
@@ -20,178 +20,181 @@
import json
import os
-import linker_config_pb2
+import linker_config_pb2 #pylint: disable=import-error
from google.protobuf.descriptor import FieldDescriptor
from google.protobuf.json_format import ParseDict
from google.protobuf.text_format import MessageToString
def Proto(args):
- json_content = ''
- with open(args.source) as f:
- for line in f:
- if not line.lstrip().startswith('//'):
- json_content += line
- obj = json.loads(json_content, object_pairs_hook=collections.OrderedDict)
- pb = ParseDict(obj, linker_config_pb2.LinkerConfig())
- with open(args.output, 'wb') as f:
- f.write(pb.SerializeToString())
+ json_content = ''
+ with open(args.source) as f:
+ for line in f:
+ if not line.lstrip().startswith('//'):
+ json_content += line
+ obj = json.loads(json_content, object_pairs_hook=collections.OrderedDict)
+ pb = ParseDict(obj, linker_config_pb2.LinkerConfig())
+ with open(args.output, 'wb') as f:
+ f.write(pb.SerializeToString())
def Print(args):
- with open(args.source, 'rb') as f:
- pb = linker_config_pb2.LinkerConfig()
- pb.ParseFromString(f.read())
- print(MessageToString(pb))
+ with open(args.source, 'rb') as f:
+ pb = linker_config_pb2.LinkerConfig()
+ pb.ParseFromString(f.read())
+ print(MessageToString(pb))
def SystemProvide(args):
- pb = linker_config_pb2.LinkerConfig()
- with open(args.source, 'rb') as f:
- pb.ParseFromString(f.read())
- libraries = args.value.split()
+ pb = linker_config_pb2.LinkerConfig()
+ with open(args.source, 'rb') as f:
+ pb.ParseFromString(f.read())
+ libraries = args.value.split()
- def IsInLibPath(lib_name):
- lib_path = os.path.join(args.system, 'lib', lib_name)
- lib64_path = os.path.join(args.system, 'lib64', lib_name)
- return os.path.exists(lib_path) or os.path.islink(lib_path) or os.path.exists(lib64_path) or os.path.islink(lib64_path)
+ def IsInLibPath(lib_name):
+ lib_path = os.path.join(args.system, 'lib', lib_name)
+ lib64_path = os.path.join(args.system, 'lib64', lib_name)
+ return os.path.exists(lib_path) or os.path.islink(
+ lib_path) or os.path.exists(lib64_path) or os.path.islink(
+ lib64_path)
- installed_libraries = list(filter(IsInLibPath, libraries))
- for item in installed_libraries:
- if item not in getattr(pb, 'provideLibs'):
- getattr(pb, 'provideLibs').append(item)
- with open(args.output, 'wb') as f:
- f.write(pb.SerializeToString())
+ installed_libraries = [lib for lib in libraries if IsInLibPath(lib)]
+ for item in installed_libraries:
+ if item not in getattr(pb, 'provideLibs'):
+ getattr(pb, 'provideLibs').append(item)
+ with open(args.output, 'wb') as f:
+ f.write(pb.SerializeToString())
def Append(args):
- pb = linker_config_pb2.LinkerConfig()
- with open(args.source, 'rb') as f:
- pb.ParseFromString(f.read())
+ pb = linker_config_pb2.LinkerConfig()
+ with open(args.source, 'rb') as f:
+ pb.ParseFromString(f.read())
- if getattr(type(pb), args.key).DESCRIPTOR.label == FieldDescriptor.LABEL_REPEATED:
- for value in args.value.split():
- getattr(pb, args.key).append(value)
- else:
- setattr(pb, args.key, args.value)
+ if getattr(type(pb),
+ args.key).DESCRIPTOR.label == FieldDescriptor.LABEL_REPEATED:
+ for value in args.value.split():
+ getattr(pb, args.key).append(value)
+ else:
+ setattr(pb, args.key, args.value)
- with open(args.output, 'wb') as f:
- f.write(pb.SerializeToString())
+ with open(args.output, 'wb') as f:
+ f.write(pb.SerializeToString())
+
def Merge(args):
- pb = linker_config_pb2.LinkerConfig()
- for other in args.input:
- with open(other, 'rb') as f:
- pb.MergeFromString(f.read())
+ pb = linker_config_pb2.LinkerConfig()
+ for other in args.input:
+ with open(other, 'rb') as f:
+ pb.MergeFromString(f.read())
- with open(args.out, 'wb') as f:
- f.write(pb.SerializeToString())
+ with open(args.out, 'wb') as f:
+ f.write(pb.SerializeToString())
+
def GetArgParser():
- parser = argparse.ArgumentParser()
- subparsers = parser.add_subparsers()
+ parser = argparse.ArgumentParser()
+ subparsers = parser.add_subparsers()
- parser_proto = subparsers.add_parser(
- 'proto', help='Convert the input JSON configuration file into protobuf.')
- parser_proto.add_argument(
- '-s',
- '--source',
- required=True,
- type=str,
- help='Source linker configuration file in JSON.')
- parser_proto.add_argument(
- '-o',
- '--output',
- required=True,
- type=str,
- help='Target path to create protobuf file.')
- parser_proto.set_defaults(func=Proto)
+ parser_proto = subparsers.add_parser(
+ 'proto',
+ help='Convert the input JSON configuration file into protobuf.')
+ parser_proto.add_argument(
+ '-s',
+ '--source',
+ required=True,
+ type=str,
+ help='Source linker configuration file in JSON.')
+ parser_proto.add_argument(
+ '-o',
+ '--output',
+ required=True,
+ type=str,
+ help='Target path to create protobuf file.')
+ parser_proto.set_defaults(func=Proto)
- print_proto = subparsers.add_parser(
- 'print', help='Print configuration in human-readable text format.')
- print_proto.add_argument(
- '-s',
- '--source',
- required=True,
- type=str,
- help='Source linker configuration file in protobuf.')
- print_proto.set_defaults(func=Print)
+ print_proto = subparsers.add_parser(
+ 'print', help='Print configuration in human-readable text format.')
+ print_proto.add_argument(
+ '-s',
+ '--source',
+ required=True,
+ type=str,
+ help='Source linker configuration file in protobuf.')
+ print_proto.set_defaults(func=Print)
- system_provide_libs = subparsers.add_parser(
- 'systemprovide', help='Append system provide libraries into the configuration.')
- system_provide_libs.add_argument(
- '-s',
- '--source',
- required=True,
- type=str,
- help='Source linker configuration file in protobuf.')
- system_provide_libs.add_argument(
- '-o',
- '--output',
- required=True,
- type=str,
- help='Target linker configuration file to write in protobuf.')
- system_provide_libs.add_argument(
- '--value',
- required=True,
- type=str,
- help='Values of the libraries to append. If there are more than one it should be separated by empty space')
- system_provide_libs.add_argument(
- '--system',
- required=True,
- type=str,
- help='Path of the system image.')
- system_provide_libs.set_defaults(func=SystemProvide)
+ system_provide_libs = subparsers.add_parser(
+ 'systemprovide',
+ help='Append system provide libraries into the configuration.')
+ system_provide_libs.add_argument(
+ '-s',
+ '--source',
+ required=True,
+ type=str,
+ help='Source linker configuration file in protobuf.')
+ system_provide_libs.add_argument(
+ '-o',
+ '--output',
+ required=True,
+ type=str,
+ help='Target linker configuration file to write in protobuf.')
+ system_provide_libs.add_argument(
+ '--value',
+ required=True,
+ type=str,
+ help='Values of the libraries to append. If there are more than one '
+ 'it should be separated by empty space'
+ )
+ system_provide_libs.add_argument(
+ '--system', required=True, type=str, help='Path of the system image.')
+ system_provide_libs.set_defaults(func=SystemProvide)
- append = subparsers.add_parser(
- 'append', help='Append value(s) to given key.')
- append.add_argument(
- '-s',
- '--source',
- required=True,
- type=str,
- help='Source linker configuration file in protobuf.')
- append.add_argument(
- '-o',
- '--output',
- required=True,
- type=str,
- help='Target linker configuration file to write in protobuf.')
- append.add_argument(
- '--key',
- required=True,
- type=str,
- help='.')
- append.add_argument(
- '--value',
- required=True,
- type=str,
- help='Values of the libraries to append. If there are more than one it should be separated by empty space')
- append.set_defaults(func=Append)
+ append = subparsers.add_parser(
+ 'append', help='Append value(s) to given key.')
+ append.add_argument(
+ '-s',
+ '--source',
+ required=True,
+ type=str,
+ help='Source linker configuration file in protobuf.')
+ append.add_argument(
+ '-o',
+ '--output',
+ required=True,
+ type=str,
+ help='Target linker configuration file to write in protobuf.')
+ append.add_argument('--key', required=True, type=str, help='.')
+ append.add_argument(
+ '--value',
+ required=True,
+ type=str,
+ help='Values of the libraries to append. If there are more than one'
+ 'it should be separated by empty space'
+ )
+ append.set_defaults(func=Append)
- append = subparsers.add_parser(
- 'merge', help='Merge configurations')
- append.add_argument(
- '-o',
- '--out',
- required=True,
- type=str,
- help='Ouptut linker configuration file to write in protobuf.')
- append.add_argument(
- '-i',
- '--input',
- nargs='+',
- type=str,
- help='Linker configuration files to merge.')
- append.set_defaults(func=Merge)
+ append = subparsers.add_parser('merge', help='Merge configurations')
+ append.add_argument(
+ '-o',
+ '--out',
+ required=True,
+ type=str,
+ help='Output linker configuration file to write in protobuf.')
+ append.add_argument(
+ '-i',
+ '--input',
+ nargs='+',
+ type=str,
+ help='Linker configuration files to merge.')
+ append.set_defaults(func=Merge)
- return parser
+ return parser
def main():
- args = GetArgParser().parse_args()
- args.func(args)
+ args = GetArgParser().parse_args()
+ args.func(args)
if __name__ == '__main__':
- main()
+ main()
diff --git a/scripts/get_clang_version.py b/scripts/get_clang_version.py
index f6efc5f..17bc88b 100755
--- a/scripts/get_clang_version.py
+++ b/scripts/get_clang_version.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
#
# Copyright (C) 2021 The Android Open Source Project
#
diff --git a/tests/bootstrap_test.sh b/tests/bootstrap_test.sh
index 76b2ee9..610e427 100755
--- a/tests/bootstrap_test.sh
+++ b/tests/bootstrap_test.sh
@@ -607,12 +607,36 @@
function test_dump_json_module_graph() {
setup
- SOONG_DUMP_JSON_MODULE_GRAPH="$MOCK_TOP/modules.json" run_soong
- if [[ ! -r "$MOCK_TOP/modules.json" ]]; then
+ GENERATE_JSON_MODULE_GRAPH=1 run_soong
+ if [[ ! -r "out/soong//module-graph.json" ]]; then
fail "JSON file was not created"
fi
}
+function test_json_module_graph_back_and_forth_null_build() {
+ setup
+
+ run_soong
+ local ninja_mtime1=$(stat -c "%y" out/soong/build.ninja)
+
+ GENERATE_JSON_MODULE_GRAPH=1 run_soong
+ local json_mtime1=$(stat -c "%y" out/soong/module-graph.json)
+
+ run_soong
+ local ninja_mtime2=$(stat -c "%y" out/soong/build.ninja)
+ if [[ "$ninja_mtime1" != "$ninja_mtime2" ]]; then
+ fail "Output Ninja file changed after writing JSON module graph"
+ fi
+
+ GENERATE_JSON_MODULE_GRAPH=1 run_soong
+ local json_mtime2=$(stat -c "%y" out/soong/module-graph.json)
+ if [[ "$json_mtime1" != "$json_mtime2" ]]; then
+ fail "JSON module graph file changed after writing Ninja file"
+ fi
+
+}
+
+
function test_bp2build_bazel_workspace_structure {
setup
@@ -757,6 +781,7 @@
test_glob_during_bootstrapping
test_soong_build_rerun_iff_environment_changes
test_dump_json_module_graph
+test_json_module_graph_back_and_forth_null_build
test_write_to_source_tree
test_bp2build_smoke
test_bp2build_generates_marker_file
diff --git a/ui/build/config.go b/ui/build/config.go
index 956406d..6a05f4f 100644
--- a/ui/build/config.go
+++ b/ui/build/config.go
@@ -747,6 +747,10 @@
return shared.JoinPath(c.SoongOutDir(), ".bootstrap/bp2build_workspace_marker")
}
+func (c *configImpl) ModuleGraphFile() string {
+ return shared.JoinPath(c.SoongOutDir(), "module-graph.json")
+}
+
func (c *configImpl) TempDir() string {
return shared.TempDirForOutDir(c.SoongOutDir())
}
@@ -919,7 +923,7 @@
return mixedBuild
} else if c.Environment().IsEnvTrue("GENERATE_BAZEL_FILES") {
return generateBuildFiles
- } else if v, ok := c.Environment().Get("SOONG_DUMP_JSON_MODULE_GRAPH"); ok && v != "" {
+ } else if c.Environment().IsEnvTrue("GENERATE_JSON_MODULE_GRAPH") {
return generateJsonModuleGraph
} else {
return noBazel
diff --git a/ui/build/soong.go b/ui/build/soong.go
index 8ef8c74..058f819 100644
--- a/ui/build/soong.go
+++ b/ui/build/soong.go
@@ -71,17 +71,17 @@
// A tiny struct used to tell Blueprint that it's in bootstrap mode. It would
// probably be nicer to use a flag in bootstrap.Args instead.
type BlueprintConfig struct {
- buildDir string
- ninjaBuildDir string
+ soongOutDir string
+ outDir string
debugCompilation bool
}
-func (c BlueprintConfig) BuildDir() string {
- return c.buildDir
+func (c BlueprintConfig) SoongOutDir() string {
+ return c.soongOutDir
}
-func (c BlueprintConfig) NinjaBuildDir() string {
- return c.ninjaBuildDir
+func (c BlueprintConfig) OutDir() string {
+ return c.outDir
}
func (c BlueprintConfig) DebugCompilation() bool {
@@ -117,6 +117,7 @@
bootstrapGlobFile := shared.JoinPath(config.SoongOutDir(), ".bootstrap/build-globs.ninja")
bp2buildGlobFile := shared.JoinPath(config.SoongOutDir(), ".bootstrap/build-globs.bp2build.ninja")
+ moduleGraphGlobFile := shared.JoinPath(config.SoongOutDir(), ".bootstrap/build-globs.modulegraph.ninja")
// The glob .ninja files are subninja'd. However, they are generated during
// the build itself so we write an empty file so that the subninja doesn't
@@ -181,16 +182,34 @@
Outputs: []string{config.Bp2BuildMarkerFile()},
Args: bp2buildArgs,
}
+
+ moduleGraphArgs := []string{
+ "--module_graph_file", config.ModuleGraphFile(),
+ "--globListDir", "globs.modulegraph",
+ "--globFile", moduleGraphGlobFile,
+ }
+
+ moduleGraphArgs = append(moduleGraphArgs, commonArgs...)
+ moduleGraphArgs = append(moduleGraphArgs, environmentArgs(config, ".modulegraph")...)
+ moduleGraphArgs = append(moduleGraphArgs, "Android.bp")
+
+ moduleGraphInvocation := bootstrap.PrimaryBuilderInvocation{
+ Inputs: []string{"Android.bp"},
+ Outputs: []string{config.ModuleGraphFile()},
+ Args: moduleGraphArgs,
+ }
+
args.PrimaryBuilderInvocations = []bootstrap.PrimaryBuilderInvocation{
bp2buildInvocation,
mainSoongBuildInvocation,
+ moduleGraphInvocation,
}
blueprintCtx := blueprint.NewContext()
blueprintCtx.SetIgnoreUnknownModuleTypes(true)
blueprintConfig := BlueprintConfig{
- buildDir: config.SoongOutDir(),
- ninjaBuildDir: config.OutDir(),
+ soongOutDir: config.SoongOutDir(),
+ outDir: config.OutDir(),
debugCompilation: os.Getenv("SOONG_DELVE") != "",
}
@@ -307,6 +326,8 @@
if config.bazelBuildMode() == generateBuildFiles {
target = config.Bp2BuildMarkerFile()
+ } else if config.bazelBuildMode() == generateJsonModuleGraph {
+ target = config.ModuleGraphFile()
} else {
// This build generates <builddir>/build.ninja, which is used later by build/soong/ui/build/build.go#Build().
target = config.MainNinjaFile()