Merge "Respect `required` property of apex modules"
diff --git a/Android.bp b/Android.bp
index b5ddaa4..0e8d86d 100644
--- a/Android.bp
+++ b/Android.bp
@@ -127,3 +127,7 @@
srcs: ["cc/config/global.go"],
out: ["clang-prebuilts-version.txt"],
}
+
+dexpreopt_systemserver_check {
+ name: "dexpreopt_systemserver_check",
+}
diff --git a/README.md b/README.md
index a67c393..b820fd1 100644
--- a/README.md
+++ b/README.md
@@ -561,27 +561,41 @@
## Developing for Soong
-To load Soong code in a Go-aware IDE, create a directory outside your android tree and then:
-```bash
-apt install bindfs
-export GOPATH=<path to the directory you created>
-build/soong/scripts/setup_go_workspace_for_soong.sh
-```
+To load the code of Soong in IntelliJ:
-This will bind mount the Soong source directories into the directory in the layout expected by
-the IDE.
-
+* File -> Open, open the `build/soong` directory. It will be opened as a new
+ project.
+* File -> Settings, then Languages & Frameworks -> Go -> GOROOT, then set it to
+ `prebuilts/go/linux-x86`
+* File -> Project Structure, then, Project Settings -> Modules, then Add
+ Content Root, then add the `build/blueprint` directory.
+* Optional: also add the `external/golang-protobuf` directory. In practice,
+ IntelliJ seems to work well enough without this, too.
### Running Soong in a debugger
-To run the soong_build process in a debugger, install `dlv` and then start the build with
-`SOONG_DELVE=<listen addr>` in the environment.
+To make `soong_build` wait for a debugger connection, install `dlv` and then
+start the build with `SOONG_DELVE=<listen addr>` in the environment.
For example:
```bash
-SOONG_DELVE=:1234 m nothing
+SOONG_DELVE=:5006 m nothing
```
-and then in another terminal:
+
+To make `soong_ui` wait for a debugger connection, use the `SOONG_UI_DELVE`
+variable:
+
```
-dlv connect :1234
+SOONG_UI_DELVE=:5006 m nothing
+```
+
+
+setting or unsetting `SOONG_DELVE` causes a recompilation of `soong_build`. This
+is because in order to debug the binary, it needs to be built with debug
+symbols.
+
+To test the debugger connection, run this command:
+
+```
+dlv connect :5006
```
If you see an error:
@@ -596,6 +610,21 @@
sudo sysctl -w kernel.yama.ptrace_scope=0
```
+To connect to the process using IntelliJ:
+
+* Run -> Edit Configurations...
+* Choose "Go Remote" on the left
+* Click on the "+" buttion on the top-left
+* Give it a nice name and set "Host" to localhost and "Port" to the port in the
+ environment variable
+
+Debugging works far worse than debugging Java, but is sometimes useful.
+
+Sometimes the `dlv` process hangs on connection. A symptom of this is `dlv`
+spinning a core or two. In that case, `kill -9` `dlv` and try again.
+Anecdotally, it _feels_ like waiting a minute after the start of `soong_build`
+helps.
+
## Contact
Email android-building@googlegroups.com (external) for any questions, or see
diff --git a/android/androidmk.go b/android/androidmk.go
index f48c06b..b6b04a6 100644
--- a/android/androidmk.go
+++ b/android/androidmk.go
@@ -478,8 +478,9 @@
func (a *AndroidMkEntries) fillInEntries(ctx fillInEntriesContext, mod blueprint.Module) {
a.EntryMap = make(map[string][]string)
- amod := mod.(Module).base()
- name := amod.BaseModuleName()
+ amod := mod.(Module)
+ base := amod.base()
+ name := base.BaseModuleName()
if a.OverrideName != "" {
name = a.OverrideName
}
@@ -487,9 +488,9 @@
if a.Include == "" {
a.Include = "$(BUILD_PREBUILT)"
}
- a.Required = append(a.Required, mod.(Module).RequiredModuleNames()...)
- a.Host_required = append(a.Host_required, mod.(Module).HostRequiredModuleNames()...)
- a.Target_required = append(a.Target_required, mod.(Module).TargetRequiredModuleNames()...)
+ a.Required = append(a.Required, amod.RequiredModuleNames()...)
+ a.Host_required = append(a.Host_required, amod.HostRequiredModuleNames()...)
+ a.Target_required = append(a.Target_required, amod.TargetRequiredModuleNames()...)
for _, distString := range a.GetDistForGoals(mod) {
fmt.Fprintf(&a.header, distString)
@@ -500,14 +501,14 @@
// Collect make variable assignment entries.
a.SetString("LOCAL_PATH", ctx.ModuleDir(mod))
a.SetString("LOCAL_MODULE", name+a.SubName)
- a.AddStrings("LOCAL_LICENSE_KINDS", amod.commonProperties.Effective_license_kinds...)
- a.AddStrings("LOCAL_LICENSE_CONDITIONS", amod.commonProperties.Effective_license_conditions...)
- a.AddStrings("LOCAL_NOTICE_FILE", amod.commonProperties.Effective_license_text.Strings()...)
+ a.AddStrings("LOCAL_LICENSE_KINDS", base.commonProperties.Effective_license_kinds...)
+ a.AddStrings("LOCAL_LICENSE_CONDITIONS", base.commonProperties.Effective_license_conditions...)
+ a.AddStrings("LOCAL_NOTICE_FILE", base.commonProperties.Effective_license_text.Strings()...)
// TODO(b/151177513): Does this code need to set LOCAL_MODULE_IS_CONTAINER ?
- if amod.commonProperties.Effective_package_name != nil {
- a.SetString("LOCAL_LICENSE_PACKAGE_NAME", *amod.commonProperties.Effective_package_name)
- } else if len(amod.commonProperties.Effective_licenses) > 0 {
- a.SetString("LOCAL_LICENSE_PACKAGE_NAME", strings.Join(amod.commonProperties.Effective_licenses, " "))
+ if base.commonProperties.Effective_package_name != nil {
+ a.SetString("LOCAL_LICENSE_PACKAGE_NAME", *base.commonProperties.Effective_package_name)
+ } else if len(base.commonProperties.Effective_licenses) > 0 {
+ a.SetString("LOCAL_LICENSE_PACKAGE_NAME", strings.Join(base.commonProperties.Effective_licenses, " "))
}
a.SetString("LOCAL_MODULE_CLASS", a.Class)
a.SetString("LOCAL_PREBUILT_MODULE_FILE", a.OutputFile.String())
@@ -515,31 +516,41 @@
a.AddStrings("LOCAL_HOST_REQUIRED_MODULES", a.Host_required...)
a.AddStrings("LOCAL_TARGET_REQUIRED_MODULES", a.Target_required...)
+ // If the install rule was generated by Soong tell Make about it.
+ if amod.InstallBypassMake() && len(base.katiInstalls) > 0 {
+ // Assume the primary install file is last since it probably needs to depend on any other
+ // installed files. If that is not the case we can add a method to specify the primary
+ // installed file.
+ a.SetPath("LOCAL_SOONG_INSTALLED_MODULE", base.katiInstalls[len(base.katiInstalls)-1].to)
+ a.SetString("LOCAL_SOONG_INSTALL_PAIRS", base.katiInstalls.BuiltInstalled())
+ a.SetPaths("LOCAL_SOONG_INSTALL_SYMLINKS", base.katiSymlinks.InstallPaths().Paths())
+ }
+
if am, ok := mod.(ApexModule); ok {
a.SetBoolIfTrue("LOCAL_NOT_AVAILABLE_FOR_PLATFORM", am.NotAvailableForPlatform())
}
- archStr := amod.Arch().ArchType.String()
+ archStr := base.Arch().ArchType.String()
host := false
- switch amod.Os().Class {
+ switch base.Os().Class {
case Host:
- if amod.Target().HostCross {
+ if base.Target().HostCross {
// Make cannot identify LOCAL_MODULE_HOST_CROSS_ARCH:= common.
- if amod.Arch().ArchType != Common {
+ if base.Arch().ArchType != Common {
a.SetString("LOCAL_MODULE_HOST_CROSS_ARCH", archStr)
}
} else {
// Make cannot identify LOCAL_MODULE_HOST_ARCH:= common.
- if amod.Arch().ArchType != Common {
+ if base.Arch().ArchType != Common {
a.SetString("LOCAL_MODULE_HOST_ARCH", archStr)
}
}
host = true
case Device:
// Make cannot identify LOCAL_MODULE_TARGET_ARCH:= common.
- if amod.Arch().ArchType != Common {
- if amod.Target().NativeBridge {
- hostArchStr := amod.Target().NativeBridgeHostArchName
+ if base.Arch().ArchType != Common {
+ if base.Target().NativeBridge {
+ hostArchStr := base.Target().NativeBridgeHostArchName
if hostArchStr != "" {
a.SetString("LOCAL_MODULE_TARGET_ARCH", hostArchStr)
}
@@ -548,31 +559,31 @@
}
}
- if !amod.InRamdisk() && !amod.InVendorRamdisk() {
- a.AddPaths("LOCAL_FULL_INIT_RC", amod.initRcPaths)
+ if !base.InRamdisk() && !base.InVendorRamdisk() {
+ a.AddPaths("LOCAL_FULL_INIT_RC", base.initRcPaths)
}
- if len(amod.vintfFragmentsPaths) > 0 {
- a.AddPaths("LOCAL_FULL_VINTF_FRAGMENTS", amod.vintfFragmentsPaths)
+ if len(base.vintfFragmentsPaths) > 0 {
+ a.AddPaths("LOCAL_FULL_VINTF_FRAGMENTS", base.vintfFragmentsPaths)
}
- a.SetBoolIfTrue("LOCAL_PROPRIETARY_MODULE", Bool(amod.commonProperties.Proprietary))
- if Bool(amod.commonProperties.Vendor) || Bool(amod.commonProperties.Soc_specific) {
+ a.SetBoolIfTrue("LOCAL_PROPRIETARY_MODULE", Bool(base.commonProperties.Proprietary))
+ if Bool(base.commonProperties.Vendor) || Bool(base.commonProperties.Soc_specific) {
a.SetString("LOCAL_VENDOR_MODULE", "true")
}
- a.SetBoolIfTrue("LOCAL_ODM_MODULE", Bool(amod.commonProperties.Device_specific))
- a.SetBoolIfTrue("LOCAL_PRODUCT_MODULE", Bool(amod.commonProperties.Product_specific))
- a.SetBoolIfTrue("LOCAL_SYSTEM_EXT_MODULE", Bool(amod.commonProperties.System_ext_specific))
- if amod.commonProperties.Owner != nil {
- a.SetString("LOCAL_MODULE_OWNER", *amod.commonProperties.Owner)
+ a.SetBoolIfTrue("LOCAL_ODM_MODULE", Bool(base.commonProperties.Device_specific))
+ a.SetBoolIfTrue("LOCAL_PRODUCT_MODULE", Bool(base.commonProperties.Product_specific))
+ a.SetBoolIfTrue("LOCAL_SYSTEM_EXT_MODULE", Bool(base.commonProperties.System_ext_specific))
+ if base.commonProperties.Owner != nil {
+ a.SetString("LOCAL_MODULE_OWNER", *base.commonProperties.Owner)
}
}
- if len(amod.noticeFiles) > 0 {
- a.SetString("LOCAL_NOTICE_FILE", strings.Join(amod.noticeFiles.Strings(), " "))
+ if len(base.noticeFiles) > 0 {
+ a.SetString("LOCAL_NOTICE_FILE", strings.Join(base.noticeFiles.Strings(), " "))
}
if host {
- makeOs := amod.Os().String()
- if amod.Os() == Linux || amod.Os() == LinuxBionic || amod.Os() == LinuxMusl {
+ makeOs := base.Os().String()
+ if base.Os() == Linux || base.Os() == LinuxBionic || base.Os() == LinuxMusl {
makeOs = "linux"
}
a.SetString("LOCAL_MODULE_HOST_OS", makeOs)
@@ -580,10 +591,10 @@
}
prefix := ""
- if amod.ArchSpecific() {
- switch amod.Os().Class {
+ if base.ArchSpecific() {
+ switch base.Os().Class {
case Host:
- if amod.Target().HostCross {
+ if base.Target().HostCross {
prefix = "HOST_CROSS_"
} else {
prefix = "HOST_"
@@ -593,7 +604,7 @@
}
- if amod.Arch().ArchType != ctx.Config().Targets[amod.Os()][0].Arch.ArchType {
+ if base.Arch().ArchType != ctx.Config().Targets[base.Os()][0].Arch.ArchType {
prefix = "2ND_" + prefix
}
}
@@ -910,6 +921,11 @@
return true
}
+ // Only expose the primary Darwin target, as Make does not understand Darwin+Arm64
+ if module.Os() == Darwin && module.Target().HostCross {
+ return true
+ }
+
return !module.Enabled() ||
module.commonProperties.HideFromMake ||
// Make does not understand LinuxBionic
diff --git a/android/api_levels.go b/android/api_levels.go
index 93583bc..c1b3ba2 100644
--- a/android/api_levels.go
+++ b/android/api_levels.go
@@ -177,6 +177,10 @@
// libandroid_support.
var FirstNonLibAndroidSupportVersion = uncheckedFinalApiLevel(21)
+// LastWithoutModuleLibCoreSystemModules is the last API level where prebuilts/sdk does not contain
+// a core-for-system-modules.jar for the module-lib API scope.
+var LastWithoutModuleLibCoreSystemModules = uncheckedFinalApiLevel(31)
+
// If the `raw` input is the codename of an API level has been finalized, this
// function returns the API level number associated with that API level. If the
// input is *not* a finalized codename, the input is returned unmodified.
@@ -236,6 +240,27 @@
return apiLevel, nil
}
+// ApiLevelForTest returns an ApiLevel constructed from the supplied raw string.
+//
+// This only supports "current" and numeric levels, code names are not supported.
+func ApiLevelForTest(raw string) ApiLevel {
+ if raw == "" {
+ panic("API level string must be non-empty")
+ }
+
+ if raw == "current" {
+ return FutureApiLevel
+ }
+
+ asInt, err := strconv.Atoi(raw)
+ if err != nil {
+ panic(fmt.Errorf("%q could not be parsed as an integer and is not a recognized codename", raw))
+ }
+
+ apiLevel := uncheckedFinalApiLevel(asInt)
+ return apiLevel
+}
+
// Converts an API level string `raw` into an ApiLevel in the same method as
// `ApiLevelFromUser`, but the input is assumed to have no errors and any errors
// will panic instead of returning an error.
diff --git a/android/arch.go b/android/arch.go
index 5e3e920..3bf54b7 100644
--- a/android/arch.go
+++ b/android/arch.go
@@ -308,7 +308,7 @@
// LinuxMusl is the OS for the Linux kernel plus the musl runtime.
LinuxMusl = newOsType("linux_musl", Host, false, X86, X86_64)
// Darwin is the OS for MacOS/Darwin host machines.
- Darwin = newOsType("darwin", Host, false, X86_64)
+ Darwin = newOsType("darwin", Host, false, Arm64, X86_64)
// LinuxBionic is the OS for the Linux kernel plus the Bionic libc runtime, but without the
// rest of Android.
LinuxBionic = newOsType("linux_bionic", Host, false, Arm64, X86_64)
@@ -696,6 +696,11 @@
for i, m := range modules {
addTargetProperties(m, targets[i], multiTargets, i == 0)
m.base().setArchProperties(mctx)
+
+ // Install support doesn't understand Darwin+Arm64
+ if os == Darwin && targets[i].HostCross {
+ m.base().commonProperties.SkipInstall = true
+ }
}
}
diff --git a/android/bazel.go b/android/bazel.go
index 5dda655..cf27cb4 100644
--- a/android/bazel.go
+++ b/android/bazel.go
@@ -60,8 +60,8 @@
HasHandcraftedLabel() bool
HandcraftedLabel() string
GetBazelLabel(ctx BazelConversionPathContext, module blueprint.Module) string
- ConvertWithBp2build(ctx BazelConversionPathContext) bool
- convertWithBp2build(ctx BazelConversionPathContext, module blueprint.Module) bool
+ ConvertWithBp2build(ctx BazelConversionContext) bool
+ convertWithBp2build(ctx BazelConversionContext, module blueprint.Module) bool
GetBazelBuildFileContents(c Config, path, name string) (string, error)
}
@@ -249,8 +249,8 @@
"build_tools_source_properties",
// //external/libcap/...
- "libcap", // http://b/198595332, depends on _makenames, a cc_binary
- "cap_names.h", // http://b/198596102, depends on _makenames, a cc_binary
+ "cap_names.h", // http://b/196105070 host toolchain misconfigurations for mixed builds
+ "libcap", // http://b/196105070 host toolchain misconfigurations for mixed builds
"libminijail", // depends on unconverted modules: libcap
"getcap", // depends on unconverted modules: libcap
@@ -377,7 +377,7 @@
}
// ConvertedToBazel returns whether this module has been converted (with bp2build or manually) to Bazel.
-func convertedToBazel(ctx BazelConversionPathContext, module blueprint.Module) bool {
+func convertedToBazel(ctx BazelConversionContext, module blueprint.Module) bool {
b, ok := module.(Bazelable)
if !ok {
return false
@@ -386,11 +386,11 @@
}
// ConvertWithBp2build returns whether the given BazelModuleBase should be converted with bp2build.
-func (b *BazelModuleBase) ConvertWithBp2build(ctx BazelConversionPathContext) bool {
+func (b *BazelModuleBase) ConvertWithBp2build(ctx BazelConversionContext) bool {
return b.convertWithBp2build(ctx, ctx.Module())
}
-func (b *BazelModuleBase) convertWithBp2build(ctx BazelConversionPathContext, module blueprint.Module) bool {
+func (b *BazelModuleBase) convertWithBp2build(ctx BazelConversionContext, module blueprint.Module) bool {
if bp2buildModuleDoNotConvert[module.Name()] {
return false
}
diff --git a/android/bazel_paths.go b/android/bazel_paths.go
index 9957369..729c73c 100644
--- a/android/bazel_paths.go
+++ b/android/bazel_paths.go
@@ -68,24 +68,36 @@
// cannot be resolved,the function will panic. This is often due to the dependency not being added
// via an AddDependency* method.
-// A subset of the ModuleContext methods which are sufficient to resolve references to paths/deps in
-// order to form a Bazel-compatible label for conversion.
-type BazelConversionPathContext interface {
- EarlyModulePathContext
+// A minimal context interface to check if a module should be converted by bp2build,
+// with functions containing information to match against allowlists and denylists.
+// If a module is deemed to be convertible by bp2build, then it should rely on a
+// BazelConversionPathContext for more functions for dep/path features.
+type BazelConversionContext interface {
+ Config() Config
- GetDirectDep(name string) (blueprint.Module, blueprint.DependencyTag)
- ModuleFromName(name string) (blueprint.Module, bool)
Module() Module
OtherModuleType(m blueprint.Module) string
OtherModuleName(m blueprint.Module) string
OtherModuleDir(m blueprint.Module) string
+}
+
+// A subset of the ModuleContext methods which are sufficient to resolve references to paths/deps in
+// order to form a Bazel-compatible label for conversion.
+type BazelConversionPathContext interface {
+ EarlyModulePathContext
+ BazelConversionContext
+
+ ModuleErrorf(fmt string, args ...interface{})
+ PropertyErrorf(property, fmt string, args ...interface{})
+ GetDirectDep(name string) (blueprint.Module, blueprint.DependencyTag)
+ ModuleFromName(name string) (blueprint.Module, bool)
AddUnconvertedBp2buildDep(string)
}
// BazelLabelForModuleDeps expects a list of reference to other modules, ("<module>"
// or ":<module>") and returns a Bazel-compatible label which corresponds to dependencies on the
// module within the given ctx.
-func BazelLabelForModuleDeps(ctx TopDownMutatorContext, modules []string) bazel.LabelList {
+func BazelLabelForModuleDeps(ctx BazelConversionPathContext, modules []string) bazel.LabelList {
return BazelLabelForModuleDepsWithFn(ctx, modules, BazelModuleLabel)
}
@@ -95,15 +107,15 @@
// list which corresponds to dependencies on the module within the given ctx, and the excluded
// dependencies. Prebuilt dependencies will be appended with _alwayslink so they can be handled as
// whole static libraries.
-func BazelLabelForModuleDepsExcludes(ctx TopDownMutatorContext, modules, excludes []string) bazel.LabelList {
+func BazelLabelForModuleDepsExcludes(ctx BazelConversionPathContext, modules, excludes []string) bazel.LabelList {
return BazelLabelForModuleDepsExcludesWithFn(ctx, modules, excludes, BazelModuleLabel)
}
// BazelLabelForModuleDepsWithFn expects a list of reference to other modules, ("<module>"
// or ":<module>") and applies moduleToLabelFn to determine and return a Bazel-compatible label
// which corresponds to dependencies on the module within the given ctx.
-func BazelLabelForModuleDepsWithFn(ctx TopDownMutatorContext, modules []string,
- moduleToLabelFn func(TopDownMutatorContext, blueprint.Module) string) bazel.LabelList {
+func BazelLabelForModuleDepsWithFn(ctx BazelConversionPathContext, modules []string,
+ moduleToLabelFn func(BazelConversionPathContext, blueprint.Module) string) bazel.LabelList {
var labels bazel.LabelList
// In some cases, a nil string list is different than an explicitly empty list.
if len(modules) == 0 && modules != nil {
@@ -131,8 +143,8 @@
// to other modules, ("<module>" or ":<module>"). It applies moduleToLabelFn to determine and return a
// Bazel-compatible label list which corresponds to dependencies on the module within the given ctx, and
// the excluded dependencies.
-func BazelLabelForModuleDepsExcludesWithFn(ctx TopDownMutatorContext, modules, excludes []string,
- moduleToLabelFn func(TopDownMutatorContext, blueprint.Module) string) bazel.LabelList {
+func BazelLabelForModuleDepsExcludesWithFn(ctx BazelConversionPathContext, modules, excludes []string,
+ moduleToLabelFn func(BazelConversionPathContext, blueprint.Module) string) bazel.LabelList {
moduleLabels := BazelLabelForModuleDepsWithFn(ctx, RemoveListFromList(modules, excludes), moduleToLabelFn)
if len(excludes) == 0 {
return moduleLabels
@@ -144,11 +156,11 @@
}
}
-func BazelLabelForModuleSrcSingle(ctx TopDownMutatorContext, path string) bazel.Label {
+func BazelLabelForModuleSrcSingle(ctx BazelConversionPathContext, path string) bazel.Label {
return BazelLabelForModuleSrcExcludes(ctx, []string{path}, []string(nil)).Includes[0]
}
-func BazelLabelForModuleDepSingle(ctx TopDownMutatorContext, path string) bazel.Label {
+func BazelLabelForModuleDepSingle(ctx BazelConversionPathContext, path string) bazel.Label {
return BazelLabelForModuleDepsExcludes(ctx, []string{path}, []string(nil)).Includes[0]
}
@@ -158,7 +170,7 @@
// relative if within the same package).
// Properties must have been annotated with struct tag `android:"path"` so that dependencies modules
// will have already been handled by the path_deps mutator.
-func BazelLabelForModuleSrc(ctx TopDownMutatorContext, paths []string) bazel.LabelList {
+func BazelLabelForModuleSrc(ctx BazelConversionPathContext, paths []string) bazel.LabelList {
return BazelLabelForModuleSrcExcludes(ctx, paths, []string(nil))
}
@@ -168,7 +180,7 @@
// (absolute if in a different package or relative if within the same package).
// Properties must have been annotated with struct tag `android:"path"` so that dependencies modules
// will have already been handled by the path_deps mutator.
-func BazelLabelForModuleSrcExcludes(ctx TopDownMutatorContext, paths, excludes []string) bazel.LabelList {
+func BazelLabelForModuleSrcExcludes(ctx BazelConversionPathContext, paths, excludes []string) bazel.LabelList {
excludeLabels := expandSrcsForBazel(ctx, excludes, []string(nil))
excluded := make([]string, 0, len(excludeLabels.Includes))
for _, e := range excludeLabels.Includes {
@@ -288,7 +300,7 @@
// Properties passed as the paths or excludes argument must have been annotated with struct tag
// `android:"path"` so that dependencies on other modules will have already been handled by the
// path_deps mutator.
-func expandSrcsForBazel(ctx TopDownMutatorContext, paths, expandedExcludes []string) bazel.LabelList {
+func expandSrcsForBazel(ctx BazelConversionPathContext, paths, expandedExcludes []string) bazel.LabelList {
if paths == nil {
return bazel.LabelList{}
}
@@ -336,8 +348,8 @@
// getOtherModuleLabel returns a bazel.Label for the given dependency/tag combination for the
// module. The label will be relative to the current directory if appropriate. The dependency must
// already be resolved by either deps mutator or path deps mutator.
-func getOtherModuleLabel(ctx TopDownMutatorContext, dep, tag string,
- labelFromModule func(TopDownMutatorContext, blueprint.Module) string) bazel.Label {
+func getOtherModuleLabel(ctx BazelConversionPathContext, dep, tag string,
+ labelFromModule func(BazelConversionPathContext, blueprint.Module) string) bazel.Label {
m, _ := ctx.ModuleFromName(dep)
if m == nil {
panic(fmt.Errorf("No module named %q found, but was a direct dep of %q", dep, ctx.Module().Name()))
@@ -359,7 +371,7 @@
}
}
-func BazelModuleLabel(ctx TopDownMutatorContext, module blueprint.Module) string {
+func BazelModuleLabel(ctx BazelConversionPathContext, module blueprint.Module) string {
// TODO(b/165114590): Convert tag (":name{.tag}") to corresponding Bazel implicit output targets.
if !convertedToBazel(ctx, module) {
return bp2buildModuleLabel(ctx, module)
@@ -370,11 +382,17 @@
func bazelShortLabel(label string) string {
i := strings.Index(label, ":")
+ if i == -1 {
+ panic(fmt.Errorf("Could not find the ':' character in '%s', expected a fully qualified label.", label))
+ }
return label[i:]
}
func bazelPackage(label string) string {
i := strings.Index(label, ":")
+ if i == -1 {
+ panic(fmt.Errorf("Could not find the ':' character in '%s', expected a fully qualified label.", label))
+ }
return label[0:i]
}
@@ -382,7 +400,7 @@
return bazelPackage(label1) == bazelPackage(label2)
}
-func bp2buildModuleLabel(ctx BazelConversionPathContext, module blueprint.Module) string {
+func bp2buildModuleLabel(ctx BazelConversionContext, module blueprint.Module) string {
moduleName := ctx.OtherModuleName(module)
moduleDir := ctx.OtherModuleDir(module)
return fmt.Sprintf("//%s:%s", moduleDir, moduleName)
diff --git a/android/config.go b/android/config.go
index 6060bce..78d43c6 100644
--- a/android/config.go
+++ b/android/config.go
@@ -355,14 +355,14 @@
config.bp2buildModuleTypeConfig = map[string]bool{}
+ determineBuildOS(config)
+
return Config{config}
}
func modifyTestConfigToSupportArchMutator(testConfig Config) {
config := testConfig.config
- determineBuildOS(config)
-
config.Targets = map[OsType][]Target{
Android: []Target{
{Android, Arch{ArchType: Arm64, ArchVariant: "armv8-a", Abi: []string{"arm64-v8a"}}, NativeBridgeDisabled, "", "", false},
@@ -568,15 +568,17 @@
}
func (c *config) HostToolPath(ctx PathContext, tool string) Path {
- return PathForOutput(ctx, "host", c.PrebuiltOS(), "bin", tool)
+ path := pathForInstall(ctx, ctx.Config().BuildOS, ctx.Config().BuildArch, "bin", false, tool)
+ return path
}
-func (c *config) HostJNIToolPath(ctx PathContext, path string) Path {
+func (c *config) HostJNIToolPath(ctx PathContext, lib string) Path {
ext := ".so"
if runtime.GOOS == "darwin" {
ext = ".dylib"
}
- return PathForOutput(ctx, "host", c.PrebuiltOS(), "lib64", path+ext)
+ path := pathForInstall(ctx, ctx.Config().BuildOS, ctx.Config().BuildArch, "lib64", false, lib+ext)
+ return path
}
func (c *config) HostJavaToolPath(ctx PathContext, path string) Path {
diff --git a/android/licenses.go b/android/licenses.go
index bcd85f9..e9e271b 100644
--- a/android/licenses.go
+++ b/android/licenses.go
@@ -308,3 +308,12 @@
}
var LicenseInfoProvider = blueprint.NewProvider(LicenseInfo{})
+
+func init() {
+ RegisterMakeVarsProvider(pctx, licensesMakeVarsProvider)
+}
+
+func licensesMakeVarsProvider(ctx MakeVarsContext) {
+ ctx.Strict("BUILD_LICENSE_METADATA",
+ ctx.Config().HostToolPath(ctx, "build_license_metadata").String())
+}
diff --git a/android/makevars.go b/android/makevars.go
index 40c0ccd..20db65a 100644
--- a/android/makevars.go
+++ b/android/makevars.go
@@ -17,6 +17,8 @@
import (
"bytes"
"fmt"
+ "path/filepath"
+ "runtime"
"sort"
"strings"
@@ -222,6 +224,9 @@
lateOutFile := absolutePath(PathForOutput(ctx,
"late"+proptools.String(ctx.Config().productVariables.Make_suffix)+".mk").String())
+ installsFile := absolutePath(PathForOutput(ctx,
+ "installs"+proptools.String(ctx.Config().productVariables.Make_suffix)+".mk").String())
+
if ctx.Failed() {
return
}
@@ -229,6 +234,8 @@
var vars []makeVarsVariable
var dists []dist
var phonies []phony
+ var katiInstalls []katiInstall
+ var katiSymlinks []katiInstall
providers := append([]makeVarsProvider(nil), makeVarsInitProviders...)
providers = append(providers, *ctx.Config().Get(singletonMakeVarsProvidersKey).(*[]makeVarsProvider)...)
@@ -258,6 +265,11 @@
phonies = append(phonies, mctx.phonies...)
dists = append(dists, mctx.dists...)
}
+
+ if m.ExportedToMake() {
+ katiInstalls = append(katiInstalls, m.base().katiInstalls...)
+ katiSymlinks = append(katiSymlinks, m.base().katiSymlinks...)
+ }
})
if ctx.Failed() {
@@ -297,6 +309,10 @@
ctx.Errorf(err.Error())
}
+ installsBytes := s.writeInstalls(katiInstalls, katiSymlinks)
+ if err := pathtools.WriteFileIfChanged(installsFile, installsBytes, 0666); err != nil {
+ ctx.Errorf(err.Error())
+ }
}
func (s *makeVarsSingleton) writeVars(vars []makeVarsVariable) []byte {
@@ -405,6 +421,84 @@
return buf.Bytes()
}
+// writeInstalls writes the list of install rules generated by Soong to a makefile. The rules
+// are exported to Make instead of written directly to the ninja file so that main.mk can add
+// the dependencies from the `required` property that are hard to resolve in Soong.
+func (s *makeVarsSingleton) writeInstalls(installs, symlinks []katiInstall) []byte {
+ buf := &bytes.Buffer{}
+
+ fmt.Fprint(buf, `# Autogenerated file
+
+# Values written by Soong to generate install rules that can be amended by Kati.
+
+
+`)
+
+ preserveSymlinksFlag := "-d"
+ if runtime.GOOS == "darwin" {
+ preserveSymlinksFlag = "-R"
+ }
+
+ for _, install := range installs {
+ // Write a rule for each install request in the form:
+ // to: from [ deps ] [ | order only deps ]
+ // cp -f -d $< $@ [ && chmod +x $@ ]
+ fmt.Fprintf(buf, "%s: %s", install.to.String(), install.from.String())
+ for _, dep := range install.implicitDeps {
+ fmt.Fprintf(buf, " %s", dep.String())
+ }
+ if len(install.orderOnlyDeps) > 0 {
+ fmt.Fprintf(buf, " |")
+ }
+ for _, dep := range install.orderOnlyDeps {
+ fmt.Fprintf(buf, " %s", dep.String())
+ }
+ fmt.Fprintln(buf)
+
+ fmt.Fprintf(buf, "\trm -f $@ && cp -f %s $< $@", preserveSymlinksFlag)
+ if install.executable {
+ fmt.Fprintf(buf, " && chmod +x $@")
+ }
+ fmt.Fprintln(buf)
+ fmt.Fprintln(buf)
+ }
+
+ for _, symlink := range symlinks {
+ fmt.Fprintf(buf, "%s:", symlink.to.String())
+ for _, dep := range symlink.implicitDeps {
+ fmt.Fprintf(buf, " %s", dep.String())
+ }
+ if symlink.from != nil || len(symlink.orderOnlyDeps) > 0 {
+ fmt.Fprintf(buf, " |")
+ }
+ if symlink.from != nil {
+ fmt.Fprintf(buf, " %s", symlink.from.String())
+ }
+ for _, dep := range symlink.orderOnlyDeps {
+ fmt.Fprintf(buf, " %s", dep.String())
+ }
+ fmt.Fprintln(buf)
+
+ fromStr := ""
+ if symlink.from != nil {
+ rel, err := filepath.Rel(filepath.Dir(symlink.to.String()), symlink.from.String())
+ if err != nil {
+ panic(fmt.Errorf("failed to find relative path for symlink from %q to %q: %w",
+ symlink.from.String(), symlink.to.String(), err))
+ }
+ fromStr = rel
+ } else {
+ fromStr = symlink.absFrom
+ }
+
+ fmt.Fprintf(buf, "\trm -f $@ && ln -sfn %s $@", fromStr)
+ fmt.Fprintln(buf)
+ fmt.Fprintln(buf)
+ }
+
+ return buf.Bytes()
+}
+
func (c *makeVarsContext) DeviceConfig() DeviceConfig {
return DeviceConfig{c.Config().deviceConfig}
}
diff --git a/android/module.go b/android/module.go
index d98998d..3447f2b 100644
--- a/android/module.go
+++ b/android/module.go
@@ -1194,7 +1194,10 @@
packagingSpecs []PackagingSpec
packagingSpecsDepSet *packagingSpecsDepSet
noticeFiles Paths
- phonies map[string]Paths
+ // katiInstalls tracks the install rules that were created by Soong but are being exported
+ // to Make to convert to ninja rules so that Make can add additional dependencies.
+ katiInstalls katiInstalls
+ katiSymlinks katiInstalls
// The files to copy to the dist as explicitly specified in the .bp file.
distFiles TaggedDistFiles
@@ -1768,8 +1771,14 @@
ctx.VisitAllModuleVariants(func(module Module) {
a := module.base()
allInstalledFiles = append(allInstalledFiles, a.installFiles...)
- allCheckbuildFiles = append(allCheckbuildFiles, a.checkbuildFiles...)
- allTidyFiles = append(allTidyFiles, a.tidyFiles...)
+ // A module's -{checkbuild,tidy} phony targets should
+ // not be created if the module is not exported to make.
+ // Those could depend on the build target and fail to compile
+ // for the current build target.
+ if !ctx.Config().KatiEnabled() || !shouldSkipAndroidMkProcessing(a) {
+ allCheckbuildFiles = append(allCheckbuildFiles, a.checkbuildFiles...)
+ allTidyFiles = append(allTidyFiles, a.tidyFiles...)
+ }
})
var deps Paths
@@ -2010,9 +2019,8 @@
m.checkbuildFiles = append(m.checkbuildFiles, ctx.checkbuildFiles...)
m.tidyFiles = append(m.tidyFiles, ctx.tidyFiles...)
m.packagingSpecs = append(m.packagingSpecs, ctx.packagingSpecs...)
- for k, v := range ctx.phonies {
- m.phonies[k] = append(m.phonies[k], v...)
- }
+ m.katiInstalls = append(m.katiInstalls, ctx.katiInstalls...)
+ m.katiSymlinks = append(m.katiSymlinks, ctx.katiSymlinks...)
} else if ctx.Config().AllowMissingDependencies() {
// If the module is not enabled it will not create any build rules, nothing will call
// ctx.GetMissingDependencies(), and blueprint will consider the missing dependencies to be unhandled
@@ -2211,12 +2219,52 @@
module Module
phonies map[string]Paths
+ katiInstalls []katiInstall
+ katiSymlinks []katiInstall
+
// For tests
buildParams []BuildParams
ruleParams map[blueprint.Rule]blueprint.RuleParams
variables map[string]string
}
+// katiInstall stores a request from Soong to Make to create an install rule.
+type katiInstall struct {
+ from Path
+ to InstallPath
+ implicitDeps Paths
+ orderOnlyDeps Paths
+ executable bool
+
+ absFrom string
+}
+
+type katiInstalls []katiInstall
+
+// BuiltInstalled returns the katiInstalls in the form used by $(call copy-many-files) in Make, a
+// space separated list of from:to tuples.
+func (installs katiInstalls) BuiltInstalled() string {
+ sb := strings.Builder{}
+ for i, install := range installs {
+ if i != 0 {
+ sb.WriteRune(' ')
+ }
+ sb.WriteString(install.from.String())
+ sb.WriteRune(':')
+ sb.WriteString(install.to.String())
+ }
+ return sb.String()
+}
+
+// InstallPaths returns the install path of each entry.
+func (installs katiInstalls) InstallPaths() InstallPaths {
+ paths := make(InstallPaths, 0, len(installs))
+ for _, install := range installs {
+ paths = append(paths, install.to)
+ }
+ return paths
+}
+
func (m *moduleContext) ninjaError(params BuildParams, err error) (PackageContext, BuildParams) {
return pctx, BuildParams{
Rule: ErrorRule,
@@ -2848,20 +2896,33 @@
orderOnlyDeps = deps
}
- rule := Cp
- if executable {
- rule = CpExecutable
- }
+ if m.Config().KatiEnabled() && m.InstallBypassMake() {
+ // When creating the install rule in Soong but embedding in Make, write the rule to a
+ // makefile instead of directly to the ninja file so that main.mk can add the
+ // dependencies from the `required` property that are hard to resolve in Soong.
+ m.katiInstalls = append(m.katiInstalls, katiInstall{
+ from: srcPath,
+ to: fullInstallPath,
+ implicitDeps: implicitDeps,
+ orderOnlyDeps: orderOnlyDeps,
+ executable: executable,
+ })
+ } else {
+ rule := Cp
+ if executable {
+ rule = CpExecutable
+ }
- m.Build(pctx, BuildParams{
- Rule: rule,
- Description: "install " + fullInstallPath.Base(),
- Output: fullInstallPath,
- Input: srcPath,
- Implicits: implicitDeps,
- OrderOnly: orderOnlyDeps,
- Default: !m.Config().KatiEnabled(),
- })
+ m.Build(pctx, BuildParams{
+ Rule: rule,
+ Description: "install " + fullInstallPath.Base(),
+ Output: fullInstallPath,
+ Input: srcPath,
+ Implicits: implicitDeps,
+ OrderOnly: orderOnlyDeps,
+ Default: !m.Config().KatiEnabled(),
+ })
+ }
m.installFiles = append(m.installFiles, fullInstallPath)
}
@@ -2883,16 +2944,26 @@
}
if !m.skipInstall() {
- m.Build(pctx, BuildParams{
- Rule: Symlink,
- Description: "install symlink " + fullInstallPath.Base(),
- Output: fullInstallPath,
- Input: srcPath,
- Default: !m.Config().KatiEnabled(),
- Args: map[string]string{
- "fromPath": relPath,
- },
- })
+ if m.Config().KatiEnabled() && m.InstallBypassMake() {
+ // When creating the symlink rule in Soong but embedding in Make, write the rule to a
+ // makefile instead of directly to the ninja file so that main.mk can add the
+ // dependencies from the `required` property that are hard to resolve in Soong.
+ m.katiSymlinks = append(m.katiSymlinks, katiInstall{
+ from: srcPath,
+ to: fullInstallPath,
+ })
+ } else {
+ m.Build(pctx, BuildParams{
+ Rule: Symlink,
+ Description: "install symlink " + fullInstallPath.Base(),
+ Output: fullInstallPath,
+ Input: srcPath,
+ Default: !m.Config().KatiEnabled(),
+ Args: map[string]string{
+ "fromPath": relPath,
+ },
+ })
+ }
m.installFiles = append(m.installFiles, fullInstallPath)
m.checkbuildFiles = append(m.checkbuildFiles, srcPath)
@@ -2915,15 +2986,25 @@
m.module.base().hooks.runInstallHooks(m, nil, fullInstallPath, true)
if !m.skipInstall() {
- m.Build(pctx, BuildParams{
- Rule: Symlink,
- Description: "install symlink " + fullInstallPath.Base() + " -> " + absPath,
- Output: fullInstallPath,
- Default: !m.Config().KatiEnabled(),
- Args: map[string]string{
- "fromPath": absPath,
- },
- })
+ if m.Config().KatiEnabled() && m.InstallBypassMake() {
+ // When creating the symlink rule in Soong but embedding in Make, write the rule to a
+ // makefile instead of directly to the ninja file so that main.mk can add the
+ // dependencies from the `required` property that are hard to resolve in Soong.
+ m.katiSymlinks = append(m.katiSymlinks, katiInstall{
+ absFrom: absPath,
+ to: fullInstallPath,
+ })
+ } else {
+ m.Build(pctx, BuildParams{
+ Rule: Symlink,
+ Description: "install symlink " + fullInstallPath.Base() + " -> " + absPath,
+ Output: fullInstallPath,
+ Default: !m.Config().KatiEnabled(),
+ Args: map[string]string{
+ "fromPath": absPath,
+ },
+ })
+ }
m.installFiles = append(m.installFiles, fullInstallPath)
}
diff --git a/android/neverallow.go b/android/neverallow.go
index 9098a71..04366d3 100644
--- a/android/neverallow.go
+++ b/android/neverallow.go
@@ -27,7 +27,7 @@
// "neverallow" rules for the build system.
//
// This allows things which aren't related to the build system and are enforced
-// for sanity, in progress code refactors, or policy to be expressed in a
+// against assumptions, in progress code refactors, or policy to be expressed in a
// straightforward away disjoint from implementations and tests which should
// work regardless of these restrictions.
//
diff --git a/android/paths.go b/android/paths.go
index 2e378ba..69ab5f7 100644
--- a/android/paths.go
+++ b/android/paths.go
@@ -462,6 +462,13 @@
return ret
}
+// PathForGoBinary returns the path to the installed location of a bootstrap_go_binary module.
+func PathForGoBinary(ctx PathContext, goBinary bootstrap.GoBinaryTool) Path {
+ goBinaryInstallDir := pathForInstall(ctx, ctx.Config().BuildOS, ctx.Config().BuildArch, "bin", false)
+ rel := Rel(ctx, goBinaryInstallDir.String(), goBinary.InstallPath())
+ return goBinaryInstallDir.Join(ctx, rel)
+}
+
// Expands Paths to a SourceFileProducer or OutputFileProducer module dependency referenced via ":name" or ":name{.tag}" syntax.
// If the dependency is not found, a missingErrorDependency is returned.
// If the module dependency is not a SourceFileProducer or OutputFileProducer, appropriate errors will be returned.
@@ -482,11 +489,8 @@
} else if tag != "" {
return nil, fmt.Errorf("path dependency %q is not an output file producing module", path)
} else if goBinary, ok := module.(bootstrap.GoBinaryTool); ok {
- if rel, err := filepath.Rel(PathForOutput(ctx).String(), goBinary.InstallPath()); err == nil {
- return Paths{PathForOutput(ctx, rel).WithoutRel()}, nil
- } else {
- return nil, fmt.Errorf("cannot find output path for %q: %w", goBinary.InstallPath(), err)
- }
+ goBinaryPath := PathForGoBinary(ctx, goBinary)
+ return Paths{goBinaryPath}, nil
} else if srcProducer, ok := module.(SourceFileProducer); ok {
return srcProducer.Srcs(), nil
} else {
@@ -1571,6 +1575,8 @@
// For example, it is host/<os>-<arch> for host modules, and target/product/<device>/<partition> for device modules.
partitionDir string
+ partition string
+
// makePath indicates whether this path is for Soong (false) or Make (true).
makePath bool
}
@@ -1716,6 +1722,7 @@
basePath: basePath{partionPath, ""},
soongOutDir: ctx.Config().soongOutDir,
partitionDir: partionPath,
+ partition: partition,
makePath: false,
}
@@ -1741,8 +1748,7 @@
}
func InstallPathToOnDevicePath(ctx PathContext, path InstallPath) string {
- rel := Rel(ctx, PathForOutput(ctx, "target", "product", ctx.Config().DeviceName()).String(), path.String())
-
+ rel := Rel(ctx, strings.TrimSuffix(path.PartitionDir(), path.partition), path.String())
return "/" + rel
}
diff --git a/android/rule_builder.go b/android/rule_builder.go
index c9a9ddd..1c6b1c0 100644
--- a/android/rule_builder.go
+++ b/android/rule_builder.go
@@ -833,10 +833,11 @@
func sboxPathForToolRel(ctx BuilderContext, path Path) string {
// Errors will be handled in RuleBuilder.Build where we have a context to report them
- relOut, isRelOut, _ := maybeRelErr(PathForOutput(ctx, "host", ctx.Config().PrebuiltOS()).String(), path.String())
- if isRelOut {
- // The tool is in the output directory, it will be copied to __SBOX_OUT_DIR__/tools/out
- return filepath.Join(sboxToolsSubDir, "out", relOut)
+ toolDir := pathForInstall(ctx, ctx.Config().BuildOS, ctx.Config().BuildArch, "", false)
+ relOutSoong, isRelOutSoong, _ := maybeRelErr(toolDir.String(), path.String())
+ if isRelOutSoong {
+ // The tool is in the Soong output directory, it will be copied to __SBOX_OUT_DIR__/tools/out
+ return filepath.Join(sboxToolsSubDir, "out", relOutSoong)
}
// The tool is in the source directory, it will be copied to __SBOX_OUT_DIR__/tools/src
return filepath.Join(sboxToolsSubDir, "src", path.String())
diff --git a/android/sdk_version.go b/android/sdk_version.go
index c6c75a3..1813e7e 100644
--- a/android/sdk_version.go
+++ b/android/sdk_version.go
@@ -157,7 +157,7 @@
return ctx.Config().AlwaysUsePrebuiltSdks()
} else if !s.ApiLevel.IsPreview() {
// validation check
- if s.Kind != SdkPublic && s.Kind != SdkSystem && s.Kind != SdkTest && s.Kind != SdkModule {
+ if s.Kind != SdkPublic && s.Kind != SdkSystem && s.Kind != SdkTest && s.Kind != SdkModule && s.Kind != SdkSystemServer {
panic(fmt.Errorf("prebuilt SDK is not not available for SdkKind=%q", s.Kind))
return false
}
diff --git a/android/variable.go b/android/variable.go
index baa6dfa..e943640 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -498,7 +498,7 @@
// ProductVariableProperties returns a ProductConfigProperties containing only the properties which
// have been set for the module in the given context.
-func ProductVariableProperties(ctx BaseMutatorContext) ProductConfigProperties {
+func ProductVariableProperties(ctx BazelConversionPathContext) ProductConfigProperties {
module := ctx.Module()
moduleBase := module.base()
diff --git a/apex/apex.go b/apex/apex.go
index 1f06187..33188cb 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -178,6 +178,10 @@
// used in tests.
Test_only_force_compression *bool
+ // Put extra tags (signer=<value>) to apexkeys.txt, so that release tools can sign this apex
+ // with the tool to sign payload contents.
+ Custom_sign_tool *string
+
// Canonical name of this APEX bundle. Used to determine the path to the
// activated APEX on device (i.e. /apex/<apexVariationName>), and used for the
// apex mutator variations. For override_apex modules, this is the name of the
@@ -1454,12 +1458,7 @@
func apexFileForGoBinary(ctx android.BaseModuleContext, depName string, gb bootstrap.GoBinaryTool) apexFile {
dirInApex := "bin"
- s, err := filepath.Rel(android.PathForOutput(ctx).String(), gb.InstallPath())
- if err != nil {
- ctx.ModuleErrorf("Unable to use compiled binary at %s", gb.InstallPath())
- return apexFile{}
- }
- fileToCopy := android.PathForOutput(ctx, s)
+ fileToCopy := android.PathForGoBinary(ctx, gb)
// NB: Since go binaries are static we don't need the module for anything here, which is
// good since the go tool is a blueprint.Module not an android.Module like we would
// normally use.
diff --git a/apex/apex_test.go b/apex/apex_test.go
index e7c63b9..59ea206 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -7683,6 +7683,28 @@
name: "myapex",
key: "myapex.key",
updatable: false,
+ custom_sign_tool: "sign_myapex",
+ }
+
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+ `)
+
+ apexKeysText := ctx.SingletonForTests("apex_keys_text")
+ content := apexKeysText.MaybeDescription("apexkeys.txt").BuildParams.Args["content"]
+ ensureContains(t, content, `name="myapex.apex" public_key="vendor/foo/devkeys/testkey.avbpubkey" private_key="vendor/foo/devkeys/testkey.pem" container_certificate="vendor/foo/devkeys/test.x509.pem" container_private_key="vendor/foo/devkeys/test.pk8" partition="system_ext" sign_tool="sign_myapex"`)
+}
+
+func TestApexKeysTxtOverrides(t *testing.T) {
+ ctx := testApex(t, `
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ updatable: false,
+ custom_sign_tool: "sign_myapex",
}
apex_key {
diff --git a/apex/builder.go b/apex/builder.go
index 772f789..e22d694 100644
--- a/apex/builder.go
+++ b/apex/builder.go
@@ -106,7 +106,7 @@
Description: "convert ${in}=>${out}",
})
- // TODO(b/113233103): make sure that file_contexts is sane, i.e., validate
+ // TODO(b/113233103): make sure that file_contexts is as expected, i.e., validate
// against the binary policy using sefcontext_compiler -p <policy>.
// TODO(b/114327326): automate the generation of file_contexts
@@ -524,7 +524,7 @@
}
unsignedOutputFile := android.PathForModuleOut(ctx, a.Name()+suffix+".unsigned")
- outHostBinDir := android.PathForOutput(ctx, "host", ctx.Config().PrebuiltOS(), "bin").String()
+ outHostBinDir := ctx.Config().HostToolPath(ctx, "").String()
prebuiltSdkToolsBinDir := filepath.Join("prebuilts", "sdk", "tools", runtime.GOOS, "bin")
// Figure out if need to compress apex.
diff --git a/apex/key.go b/apex/key.go
index e2695d7..259060f 100644
--- a/apex/key.go
+++ b/apex/key.go
@@ -123,13 +123,18 @@
containerCertificate string
containerPrivateKey string
partition string
+ signTool string
}
toString := func(e apexKeyEntry) string {
- format := "name=%q public_key=%q private_key=%q container_certificate=%q container_private_key=%q partition=%q\n"
+ signTool := ""
+ if e.signTool != "" {
+ signTool = fmt.Sprintf(" sign_tool=%q", e.signTool)
+ }
+ format := "name=%q public_key=%q private_key=%q container_certificate=%q container_private_key=%q partition=%q%s\n"
if e.presigned {
- return fmt.Sprintf(format, e.name, "PRESIGNED", "PRESIGNED", "PRESIGNED", "PRESIGNED", e.partition)
+ return fmt.Sprintf(format, e.name, "PRESIGNED", "PRESIGNED", "PRESIGNED", "PRESIGNED", e.partition, signTool)
} else {
- return fmt.Sprintf(format, e.name, e.publicKey, e.privateKey, e.containerCertificate, e.containerPrivateKey, e.partition)
+ return fmt.Sprintf(format, e.name, e.publicKey, e.privateKey, e.containerCertificate, e.containerPrivateKey, e.partition, signTool)
}
}
@@ -145,6 +150,7 @@
containerCertificate: pem.String(),
containerPrivateKey: key.String(),
partition: m.PartitionTag(ctx.DeviceConfig()),
+ signTool: proptools.String(m.properties.Custom_sign_tool),
}
}
})
diff --git a/bazel/aquery.go b/bazel/aquery.go
index 0dedcf4..6d96b1c 100644
--- a/bazel/aquery.go
+++ b/bazel/aquery.go
@@ -245,9 +245,9 @@
out := outputPaths[0]
outDir := proptools.ShellEscapeIncludingSpaces(filepath.Dir(out))
out = proptools.ShellEscapeIncludingSpaces(out)
- in := proptools.ShellEscapeIncludingSpaces(inputPaths[0])
- // Use hard links, because some soong actions expect real files (for example, `cp -d`).
- buildStatement.Command = fmt.Sprintf("mkdir -p %[1]s && rm -f %[2]s && ln -f %[3]s %[2]s", outDir, out, in)
+ in := filepath.Join("$PWD", proptools.ShellEscapeIncludingSpaces(inputPaths[0]))
+ // Use absolute paths, because some soong actions don't play well with relative paths (for example, `cp -d`).
+ buildStatement.Command = fmt.Sprintf("mkdir -p %[1]s && rm -f %[2]s && ln -sf %[3]s %[2]s", outDir, out, in)
buildStatement.SymlinkPaths = outputPaths[:]
} else if len(actionEntry.Arguments) < 1 {
return nil, fmt.Errorf("received action with no command: [%v]", buildStatement)
diff --git a/bazel/aquery_test.go b/bazel/aquery_test.go
index 88066c8..69f1115 100644
--- a/bazel/aquery_test.go
+++ b/bazel/aquery_test.go
@@ -859,7 +859,7 @@
BuildStatement{
Command: "mkdir -p one/symlink_subdir && " +
"rm -f one/symlink_subdir/symlink && " +
- "ln -f one/file_subdir/file one/symlink_subdir/symlink",
+ "ln -sf $PWD/one/file_subdir/file one/symlink_subdir/symlink",
InputPaths: []string{"one/file_subdir/file"},
OutputPaths: []string{"one/symlink_subdir/symlink"},
SymlinkPaths: []string{"one/symlink_subdir/symlink"},
@@ -923,14 +923,14 @@
BuildStatement{
Command: "mkdir -p 'one/symlink subdir' && " +
"rm -f 'one/symlink subdir/symlink' && " +
- "ln -f 'one/file subdir/file' 'one/symlink subdir/symlink'",
+ "ln -sf $PWD/'one/file subdir/file' 'one/symlink subdir/symlink'",
InputPaths: []string{"one/file subdir/file"},
OutputPaths: []string{"one/symlink subdir/symlink"},
SymlinkPaths: []string{"one/symlink subdir/symlink"},
Mnemonic: "SolibSymlink",
},
}
- assertBuildStatements(t, actual, expectedBuildStatements)
+ assertBuildStatements(t, expectedBuildStatements, actual)
}
func TestSymlinkMultipleInputs(t *testing.T) {
diff --git a/bazel/configurability.go b/bazel/configurability.go
index e9641e7..f05c8e5 100644
--- a/bazel/configurability.go
+++ b/bazel/configurability.go
@@ -39,6 +39,7 @@
osArchAndroidArm64 = "android_arm64"
osArchAndroidX86 = "android_x86"
osArchAndroidX86_64 = "android_x86_64"
+ osArchDarwinArm64 = "darwin_arm64"
osArchDarwinX86_64 = "darwin_x86_64"
osArchLinuxX86 = "linux_glibc_x86"
osArchLinuxX86_64 = "linux_glibc_x86_64"
@@ -96,6 +97,7 @@
osArchAndroidArm64: "//build/bazel/platforms/os_arch:android_arm64",
osArchAndroidX86: "//build/bazel/platforms/os_arch:android_x86",
osArchAndroidX86_64: "//build/bazel/platforms/os_arch:android_x86_64",
+ osArchDarwinArm64: "//build/bazel/platforms/os_arch:darwin_arm64",
osArchDarwinX86_64: "//build/bazel/platforms/os_arch:darwin_x86_64",
osArchLinuxX86: "//build/bazel/platforms/os_arch:linux_glibc_x86",
osArchLinuxX86_64: "//build/bazel/platforms/os_arch:linux_glibc_x86_64",
diff --git a/bazel/properties.go b/bazel/properties.go
index 6a06c1b..facbedd 100644
--- a/bazel/properties.go
+++ b/bazel/properties.go
@@ -534,9 +534,13 @@
lla.ConfigurableValues[axis][config] = SubtractBazelLabelList(val, lla.Value)
}
- // Now that the Value list is finalized for this axis, compare it with the original
- // list, and put the difference into the default condition for the axis.
- lla.ConfigurableValues[axis][ConditionsDefaultConfigKey] = SubtractBazelLabelList(baseLabels, lla.Value)
+ // Now that the Value list is finalized for this axis, compare it with
+ // the original list, and union the difference with the default
+ // condition for the axis.
+ difference := SubtractBazelLabelList(baseLabels, lla.Value)
+ existingDefaults := lla.ConfigurableValues[axis][ConditionsDefaultConfigKey]
+ existingDefaults.Append(difference)
+ lla.ConfigurableValues[axis][ConditionsDefaultConfigKey] = FirstUniqueBazelLabelList(existingDefaults)
// if everything ends up without includes, just delete the axis
if !lla.ConfigurableValues[axis].HasConfigurableValues() {
diff --git a/bazel/properties_test.go b/bazel/properties_test.go
index f53fdc1..7a7d6f3 100644
--- a/bazel/properties_test.go
+++ b/bazel/properties_test.go
@@ -236,8 +236,9 @@
),
ConfigurableValues: configurableLabelLists{
ArchConfigurationAxis: labelListSelectValues{
- "arm": makeLabelList([]string{}, []string{"arm_exclude"}),
- "x86": makeLabelList([]string{"x86_include"}, []string{}),
+ "arm": makeLabelList([]string{}, []string{"arm_exclude"}),
+ "x86": makeLabelList([]string{"x86_include"}, []string{}),
+ ConditionsDefaultConfigKey: makeLabelList([]string{"default_include"}, []string{}),
},
OsConfigurationAxis: labelListSelectValues{
"android": makeLabelList([]string{}, []string{"android_exclude"}),
@@ -246,7 +247,13 @@
OsArchConfigurationAxis: labelListSelectValues{
"linux_x86": makeLabelList([]string{"linux_x86_include"}, []string{}),
},
- ProductVariableConfigurationAxis("a"): labelListSelectValues{
+ ProductVariableConfigurationAxis("product_with_defaults"): labelListSelectValues{
+ "a": makeLabelList([]string{}, []string{"not_in_value"}),
+ "b": makeLabelList([]string{"b_val"}, []string{}),
+ "c": makeLabelList([]string{"c_val"}, []string{}),
+ ConditionsDefaultConfigKey: makeLabelList([]string{"c_val", "default", "default2"}, []string{}),
+ },
+ ProductVariableConfigurationAxis("product_only_with_excludes"): labelListSelectValues{
"a": makeLabelList([]string{}, []string{"not_in_value"}),
},
},
@@ -254,25 +261,31 @@
attr.ResolveExcludes()
- expectedBaseIncludes := []Label{Label{Label: "all_include"}}
+ expectedBaseIncludes := []Label{{Label: "all_include"}}
if !reflect.DeepEqual(expectedBaseIncludes, attr.Value.Includes) {
t.Errorf("Expected Value includes %q, got %q", attr.Value.Includes, expectedBaseIncludes)
}
var nilLabels []Label
expectedConfiguredIncludes := map[ConfigurationAxis]map[string][]Label{
- ArchConfigurationAxis: map[string][]Label{
- "arm": nilLabels,
- "x86": makeLabels("arm_exclude", "x86_include"),
- "conditions_default": makeLabels("arm_exclude"),
+ ArchConfigurationAxis: {
+ "arm": nilLabels,
+ "x86": makeLabels("arm_exclude", "x86_include"),
+ ConditionsDefaultConfigKey: makeLabels("arm_exclude", "default_include"),
},
- OsConfigurationAxis: map[string][]Label{
- "android": nilLabels,
- "linux": makeLabels("android_exclude", "linux_include"),
- "conditions_default": makeLabels("android_exclude"),
+ OsConfigurationAxis: {
+ "android": nilLabels,
+ "linux": makeLabels("android_exclude", "linux_include"),
+ ConditionsDefaultConfigKey: makeLabels("android_exclude"),
},
- OsArchConfigurationAxis: map[string][]Label{
- "linux_x86": makeLabels("linux_x86_include"),
- "conditions_default": nilLabels,
+ OsArchConfigurationAxis: {
+ "linux_x86": makeLabels("linux_x86_include"),
+ ConditionsDefaultConfigKey: nilLabels,
+ },
+ ProductVariableConfigurationAxis("product_with_defaults"): {
+ "a": nilLabels,
+ "b": makeLabels("b_val"),
+ "c": makeLabels("c_val"),
+ ConditionsDefaultConfigKey: makeLabels("c_val", "default", "default2"),
},
}
for _, axis := range attr.SortedConfigurationAxes() {
@@ -288,7 +301,7 @@
for config, value := range gotForAxis {
if expected, ok := expectedForAxis[config]; ok {
if !reflect.DeepEqual(expected, value.Includes) {
- t.Errorf("For %s, expected: %#v, got %#v", axis, expected, value.Includes)
+ t.Errorf("For %s,\nexpected: %#v\ngot %#v", axis, expected, value.Includes)
}
} else {
t.Errorf("Got unexpected config %q for %s", config, axis)
diff --git a/bootstrap.bash b/bootstrap.bash
index 4db8539..726692a 100755
--- a/bootstrap.bash
+++ b/bootstrap.bash
@@ -15,9 +15,9 @@
# limitations under the License.
echo '==== ERROR: bootstrap.bash & ./soong are obsolete ====' >&2
-echo 'Use `m --skip-make` with a standalone OUT_DIR instead.' >&2
+echo 'Use `m --soong-only` with a standalone OUT_DIR instead.' >&2
echo 'Without envsetup.sh, use:' >&2
-echo ' build/soong/soong_ui.bash --make-mode --skip-make' >&2
+echo ' build/soong/soong_ui.bash --make-mode --soong-only' >&2
echo '======================================================' >&2
exit 1
diff --git a/bp2build/cc_prebuilt_library_shared_test.go b/bp2build/cc_prebuilt_library_shared_test.go
new file mode 100644
index 0000000..97545c8
--- /dev/null
+++ b/bp2build/cc_prebuilt_library_shared_test.go
@@ -0,0 +1,65 @@
+package bp2build
+
+import (
+ "testing"
+
+ "android/soong/cc"
+)
+
+func TestSharedPrebuiltLibrary(t *testing.T) {
+ runBp2BuildTestCaseSimple(t,
+ bp2buildTestCase{
+ description: "prebuilt library shared simple",
+ moduleTypeUnderTest: "cc_prebuilt_library_shared",
+ moduleTypeUnderTestFactory: cc.PrebuiltSharedLibraryFactory,
+ moduleTypeUnderTestBp2BuildMutator: cc.PrebuiltLibrarySharedBp2Build,
+ filesystem: map[string]string{
+ "libf.so": "",
+ },
+ blueprint: `
+cc_prebuilt_library_shared {
+ name: "libtest",
+ srcs: ["libf.so"],
+ bazel_module: { bp2build_available: true },
+}`,
+ expectedBazelTargets: []string{
+ `prebuilt_library_shared(
+ name = "libtest",
+ shared_library = "libf.so",
+)`,
+ },
+ })
+}
+
+func TestSharedPrebuiltLibraryWithArchVariance(t *testing.T) {
+ runBp2BuildTestCaseSimple(t,
+ bp2buildTestCase{
+ description: "prebuilt library shared with arch variance",
+ moduleTypeUnderTest: "cc_prebuilt_library_shared",
+ moduleTypeUnderTestFactory: cc.PrebuiltSharedLibraryFactory,
+ moduleTypeUnderTestBp2BuildMutator: cc.PrebuiltLibrarySharedBp2Build,
+ filesystem: map[string]string{
+ "libf.so": "",
+ "libg.so": "",
+ },
+ blueprint: `
+cc_prebuilt_library_shared {
+ name: "libtest",
+ arch: {
+ arm64: { srcs: ["libf.so"], },
+ arm: { srcs: ["libg.so"], },
+ },
+ bazel_module: { bp2build_available: true },
+}`,
+ expectedBazelTargets: []string{
+ `prebuilt_library_shared(
+ name = "libtest",
+ shared_library = select({
+ "//build/bazel/platforms/arch:arm": "libg.so",
+ "//build/bazel/platforms/arch:arm64": "libf.so",
+ "//conditions:default": None,
+ }),
+)`,
+ },
+ })
+}
diff --git a/cc/bp2build.go b/cc/bp2build.go
index e20f7c3..1b13854 100644
--- a/cc/bp2build.go
+++ b/cc/bp2build.go
@@ -50,7 +50,7 @@
System_dynamic_deps bazel.LabelListAttribute
}
-func groupSrcsByExtension(ctx android.TopDownMutatorContext, srcs bazel.LabelListAttribute) bazel.PartitionToLabelListAttribute {
+func groupSrcsByExtension(ctx android.BazelConversionPathContext, srcs bazel.LabelListAttribute) bazel.PartitionToLabelListAttribute {
// Check that a module is a filegroup type named <label>.
isFilegroupNamed := func(m android.Module, fullLabel string) bool {
if ctx.OtherModuleType(m) != "filegroup" {
@@ -93,7 +93,7 @@
}
// bp2BuildParseLibProps returns the attributes for a variant of a cc_library.
-func bp2BuildParseLibProps(ctx android.TopDownMutatorContext, module *Module, isStatic bool) staticOrSharedAttributes {
+func bp2BuildParseLibProps(ctx android.BazelConversionPathContext, module *Module, isStatic bool) staticOrSharedAttributes {
lib, ok := module.compiler.(*libraryDecorator)
if !ok {
return staticOrSharedAttributes{}
@@ -102,12 +102,12 @@
}
// bp2buildParseSharedProps returns the attributes for the shared variant of a cc_library.
-func bp2BuildParseSharedProps(ctx android.TopDownMutatorContext, module *Module) staticOrSharedAttributes {
+func bp2BuildParseSharedProps(ctx android.BazelConversionPathContext, module *Module) staticOrSharedAttributes {
return bp2BuildParseLibProps(ctx, module, false)
}
// bp2buildParseStaticProps returns the attributes for the static variant of a cc_library.
-func bp2BuildParseStaticProps(ctx android.TopDownMutatorContext, module *Module) staticOrSharedAttributes {
+func bp2BuildParseStaticProps(ctx android.BazelConversionPathContext, module *Module) staticOrSharedAttributes {
return bp2BuildParseLibProps(ctx, module, true)
}
@@ -116,9 +116,9 @@
implementation bazel.LabelList
}
-type bazelLabelForDepsFn func(android.TopDownMutatorContext, []string) bazel.LabelList
+type bazelLabelForDepsFn func(android.BazelConversionPathContext, []string) bazel.LabelList
-func maybePartitionExportedAndImplementationsDeps(ctx android.TopDownMutatorContext, exportsDeps bool, allDeps, exportedDeps []string, fn bazelLabelForDepsFn) depsPartition {
+func maybePartitionExportedAndImplementationsDeps(ctx android.BazelConversionPathContext, exportsDeps bool, allDeps, exportedDeps []string, fn bazelLabelForDepsFn) depsPartition {
if !exportsDeps {
return depsPartition{
implementation: fn(ctx, allDeps),
@@ -133,9 +133,9 @@
}
}
-type bazelLabelForDepsExcludesFn func(android.TopDownMutatorContext, []string, []string) bazel.LabelList
+type bazelLabelForDepsExcludesFn func(android.BazelConversionPathContext, []string, []string) bazel.LabelList
-func maybePartitionExportedAndImplementationsDepsExcludes(ctx android.TopDownMutatorContext, exportsDeps bool, allDeps, excludes, exportedDeps []string, fn bazelLabelForDepsExcludesFn) depsPartition {
+func maybePartitionExportedAndImplementationsDepsExcludes(ctx android.BazelConversionPathContext, exportsDeps bool, allDeps, excludes, exportedDeps []string, fn bazelLabelForDepsExcludesFn) depsPartition {
if !exportsDeps {
return depsPartition{
implementation: fn(ctx, allDeps, excludes),
@@ -149,7 +149,7 @@
}
}
-func bp2buildParseStaticOrSharedProps(ctx android.TopDownMutatorContext, module *Module, lib *libraryDecorator, isStatic bool) staticOrSharedAttributes {
+func bp2buildParseStaticOrSharedProps(ctx android.BazelConversionPathContext, module *Module, lib *libraryDecorator, isStatic bool) staticOrSharedAttributes {
attrs := staticOrSharedAttributes{}
setAttrs := func(axis bazel.ConfigurationAxis, config string, props StaticOrSharedProperties) {
@@ -204,7 +204,7 @@
}
// NOTE: Used outside of Soong repo project, in the clangprebuilts.go bootstrap_go_package
-func Bp2BuildParsePrebuiltLibraryProps(ctx android.TopDownMutatorContext, module *Module) prebuiltAttributes {
+func Bp2BuildParsePrebuiltLibraryProps(ctx android.BazelConversionPathContext, module *Module) prebuiltAttributes {
var srcLabelAttribute bazel.LabelAttribute
for axis, configToProps := range module.GetArchVariantProperties(ctx, &prebuiltLinkerProperties{}) {
@@ -269,7 +269,7 @@
return result
}
-func (ca *compilerAttributes) bp2buildForAxisAndConfig(ctx android.TopDownMutatorContext, axis bazel.ConfigurationAxis, config string, props *BaseCompilerProperties) {
+func (ca *compilerAttributes) bp2buildForAxisAndConfig(ctx android.BazelConversionPathContext, axis bazel.ConfigurationAxis, config string, props *BaseCompilerProperties) {
// If there's arch specific srcs or exclude_srcs, generate a select entry for it.
// TODO(b/186153868): do this for OS specific srcs and exclude_srcs too.
if srcsList, ok := parseSrcs(ctx, props); ok {
@@ -295,7 +295,7 @@
ca.rtti.SetSelectValue(axis, config, props.Rtti)
}
-func (ca *compilerAttributes) convertStlProps(ctx android.TopDownMutatorContext, module *Module) {
+func (ca *compilerAttributes) convertStlProps(ctx android.ArchVariantContext, module *Module) {
stlPropsByArch := module.GetArchVariantProperties(ctx, &StlProperties{})
for _, configToProps := range stlPropsByArch {
for _, props := range configToProps {
@@ -313,7 +313,7 @@
}
}
-func (ca *compilerAttributes) convertProductVariables(ctx android.TopDownMutatorContext, productVariableProps android.ProductConfigProperties) {
+func (ca *compilerAttributes) convertProductVariables(ctx android.BazelConversionPathContext, productVariableProps android.ProductConfigProperties) {
productVarPropNameToAttribute := map[string]*bazel.StringListAttribute{
"Cflags": &ca.copts,
"Asflags": &ca.asFlags,
@@ -333,7 +333,7 @@
}
}
-func (ca *compilerAttributes) finalize(ctx android.TopDownMutatorContext, implementationHdrs bazel.LabelListAttribute) {
+func (ca *compilerAttributes) finalize(ctx android.BazelConversionPathContext, implementationHdrs bazel.LabelListAttribute) {
ca.srcs.ResolveExcludes()
partitionedSrcs := groupSrcsByExtension(ctx, ca.srcs)
@@ -355,7 +355,7 @@
}
// Parse srcs from an arch or OS's props value.
-func parseSrcs(ctx android.TopDownMutatorContext, props *BaseCompilerProperties) (bazel.LabelList, bool) {
+func parseSrcs(ctx android.BazelConversionPathContext, props *BaseCompilerProperties) (bazel.LabelList, bool) {
anySrcs := false
// Add srcs-like dependencies such as generated files.
// First create a LabelList containing these dependencies, then merge the values with srcs.
@@ -392,7 +392,7 @@
}
// bp2BuildParseCompilerProps returns copts, srcs and hdrs and other attributes.
-func bp2BuildParseBaseProps(ctx android.TopDownMutatorContext, module *Module) baseAttributes {
+func bp2BuildParseBaseProps(ctx android.BazelConversionPathContext, module *Module) baseAttributes {
archVariantCompilerProps := module.GetArchVariantProperties(ctx, &BaseCompilerProperties{})
archVariantLinkerProps := module.GetArchVariantProperties(ctx, &BaseLinkerProperties{})
@@ -475,7 +475,7 @@
features bazel.StringListAttribute
}
-func (la *linkerAttributes) bp2buildForAxisAndConfig(ctx android.TopDownMutatorContext, isBinary bool, axis bazel.ConfigurationAxis, config string, props *BaseLinkerProperties) {
+func (la *linkerAttributes) bp2buildForAxisAndConfig(ctx android.BazelConversionPathContext, isBinary bool, axis bazel.ConfigurationAxis, config string, props *BaseLinkerProperties) {
// Use a single variable to capture usage of nocrt in arch variants, so there's only 1 error message for this module
var axisFeatures []string
@@ -548,7 +548,7 @@
}
}
-func (la *linkerAttributes) convertStripProps(ctx android.TopDownMutatorContext, module *Module) {
+func (la *linkerAttributes) convertStripProps(ctx android.BazelConversionPathContext, module *Module) {
for axis, configToProps := range module.GetArchVariantProperties(ctx, &StripProperties{}) {
for config, props := range configToProps {
if stripProperties, ok := props.(*StripProperties); ok {
@@ -562,7 +562,7 @@
}
}
-func (la *linkerAttributes) convertProductVariables(ctx android.TopDownMutatorContext, productVariableProps android.ProductConfigProperties) {
+func (la *linkerAttributes) convertProductVariables(ctx android.BazelConversionPathContext, productVariableProps android.ProductConfigProperties) {
type productVarDep struct {
// the name of the corresponding excludes field, if one exists
@@ -570,14 +570,14 @@
// reference to the bazel attribute that should be set for the given product variable config
attribute *bazel.LabelListAttribute
- depResolutionFunc func(ctx android.TopDownMutatorContext, modules, excludes []string) bazel.LabelList
+ depResolutionFunc func(ctx android.BazelConversionPathContext, modules, excludes []string) bazel.LabelList
}
productVarToDepFields := map[string]productVarDep{
// product variables do not support exclude_shared_libs
- "Shared_libs": productVarDep{attribute: &la.implementationDynamicDeps, depResolutionFunc: bazelLabelForSharedDepsExcludes},
- "Static_libs": productVarDep{"Exclude_static_libs", &la.implementationDeps, bazelLabelForStaticDepsExcludes},
- "Whole_static_libs": productVarDep{"Exclude_static_libs", &la.wholeArchiveDeps, bazelLabelForWholeDepsExcludes},
+ "Shared_libs": {attribute: &la.implementationDynamicDeps, depResolutionFunc: bazelLabelForSharedDepsExcludes},
+ "Static_libs": {"Exclude_static_libs", &la.implementationDeps, bazelLabelForStaticDepsExcludes},
+ "Whole_static_libs": {"Exclude_static_libs", &la.wholeArchiveDeps, bazelLabelForWholeDepsExcludes},
}
for name, dep := range productVarToDepFields {
@@ -655,14 +655,14 @@
SystemIncludes bazel.StringListAttribute
}
-func bp2BuildParseExportedIncludes(ctx android.TopDownMutatorContext, module *Module) BazelIncludes {
+func bp2BuildParseExportedIncludes(ctx android.BazelConversionPathContext, module *Module) BazelIncludes {
libraryDecorator := module.linker.(*libraryDecorator)
return bp2BuildParseExportedIncludesHelper(ctx, module, libraryDecorator)
}
// Bp2buildParseExportedIncludesForPrebuiltLibrary returns a BazelIncludes with Bazel-ified values
// to export includes from the underlying module's properties.
-func Bp2BuildParseExportedIncludesForPrebuiltLibrary(ctx android.TopDownMutatorContext, module *Module) BazelIncludes {
+func Bp2BuildParseExportedIncludesForPrebuiltLibrary(ctx android.BazelConversionPathContext, module *Module) BazelIncludes {
prebuiltLibraryLinker := module.linker.(*prebuiltLibraryLinker)
libraryDecorator := prebuiltLibraryLinker.libraryDecorator
return bp2BuildParseExportedIncludesHelper(ctx, module, libraryDecorator)
@@ -670,7 +670,7 @@
// bp2BuildParseExportedIncludes creates a string list attribute contains the
// exported included directories of a module.
-func bp2BuildParseExportedIncludesHelper(ctx android.TopDownMutatorContext, module *Module, libraryDecorator *libraryDecorator) BazelIncludes {
+func bp2BuildParseExportedIncludesHelper(ctx android.BazelConversionPathContext, module *Module, libraryDecorator *libraryDecorator) BazelIncludes {
exported := BazelIncludes{}
for axis, configToProps := range module.GetArchVariantProperties(ctx, &FlagExporterProperties{}) {
for config, props := range configToProps {
@@ -690,7 +690,7 @@
return exported
}
-func bazelLabelForStaticModule(ctx android.TopDownMutatorContext, m blueprint.Module) string {
+func bazelLabelForStaticModule(ctx android.BazelConversionPathContext, m blueprint.Module) string {
label := android.BazelModuleLabel(ctx, m)
if aModule, ok := m.(android.Module); ok {
if ctx.OtherModuleType(aModule) == "cc_library" && !android.GenerateCcLibraryStaticOnly(m.Name()) {
@@ -700,13 +700,13 @@
return label
}
-func bazelLabelForSharedModule(ctx android.TopDownMutatorContext, m blueprint.Module) string {
+func bazelLabelForSharedModule(ctx android.BazelConversionPathContext, m blueprint.Module) string {
// cc_library, at it's root name, propagates the shared library, which depends on the static
// library.
return android.BazelModuleLabel(ctx, m)
}
-func bazelLabelForStaticWholeModuleDeps(ctx android.TopDownMutatorContext, m blueprint.Module) string {
+func bazelLabelForStaticWholeModuleDeps(ctx android.BazelConversionPathContext, m blueprint.Module) string {
label := bazelLabelForStaticModule(ctx, m)
if aModule, ok := m.(android.Module); ok {
if android.IsModulePrebuilt(aModule) {
@@ -716,33 +716,33 @@
return label
}
-func bazelLabelForWholeDeps(ctx android.TopDownMutatorContext, modules []string) bazel.LabelList {
+func bazelLabelForWholeDeps(ctx android.BazelConversionPathContext, modules []string) bazel.LabelList {
return android.BazelLabelForModuleDepsWithFn(ctx, modules, bazelLabelForStaticWholeModuleDeps)
}
-func bazelLabelForWholeDepsExcludes(ctx android.TopDownMutatorContext, modules, excludes []string) bazel.LabelList {
+func bazelLabelForWholeDepsExcludes(ctx android.BazelConversionPathContext, modules, excludes []string) bazel.LabelList {
return android.BazelLabelForModuleDepsExcludesWithFn(ctx, modules, excludes, bazelLabelForStaticWholeModuleDeps)
}
-func bazelLabelForStaticDepsExcludes(ctx android.TopDownMutatorContext, modules, excludes []string) bazel.LabelList {
+func bazelLabelForStaticDepsExcludes(ctx android.BazelConversionPathContext, modules, excludes []string) bazel.LabelList {
return android.BazelLabelForModuleDepsExcludesWithFn(ctx, modules, excludes, bazelLabelForStaticModule)
}
-func bazelLabelForStaticDeps(ctx android.TopDownMutatorContext, modules []string) bazel.LabelList {
+func bazelLabelForStaticDeps(ctx android.BazelConversionPathContext, modules []string) bazel.LabelList {
return android.BazelLabelForModuleDepsWithFn(ctx, modules, bazelLabelForStaticModule)
}
-func bazelLabelForSharedDeps(ctx android.TopDownMutatorContext, modules []string) bazel.LabelList {
+func bazelLabelForSharedDeps(ctx android.BazelConversionPathContext, modules []string) bazel.LabelList {
return android.BazelLabelForModuleDepsWithFn(ctx, modules, bazelLabelForSharedModule)
}
-func bazelLabelForHeaderDeps(ctx android.TopDownMutatorContext, modules []string) bazel.LabelList {
+func bazelLabelForHeaderDeps(ctx android.BazelConversionPathContext, modules []string) bazel.LabelList {
// This is not elegant, but bp2build's shared library targets only propagate
// their header information as part of the normal C++ provider.
return bazelLabelForSharedDeps(ctx, modules)
}
-func bazelLabelForSharedDepsExcludes(ctx android.TopDownMutatorContext, modules, excludes []string) bazel.LabelList {
+func bazelLabelForSharedDepsExcludes(ctx android.BazelConversionPathContext, modules, excludes []string) bazel.LabelList {
return android.BazelLabelForModuleDepsExcludesWithFn(ctx, modules, excludes, bazelLabelForSharedModule)
}
@@ -750,7 +750,7 @@
Linkshared *bool
}
-func bp2buildBinaryLinkerProps(ctx android.TopDownMutatorContext, m *Module) binaryLinkerAttrs {
+func bp2buildBinaryLinkerProps(ctx android.BazelConversionPathContext, m *Module) binaryLinkerAttrs {
attrs := binaryLinkerAttrs{}
archVariantProps := m.GetArchVariantProperties(ctx, &BinaryLinkerProperties{})
for axis, configToProps := range archVariantProps {
diff --git a/cc/cc.go b/cc/cc.go
index 1c65549..32652c1 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -325,7 +325,7 @@
SnapshotStaticLibs []string `blueprint:"mutated"`
SnapshotRuntimeLibs []string `blueprint:"mutated"`
- Installable *bool
+ Installable *bool `android:"arch_variant"`
// Set by factories of module types that can only be referenced from variants compiled against
// the SDK.
@@ -1865,7 +1865,7 @@
}
func (c *Module) maybeInstall(ctx ModuleContext, apexInfo android.ApexInfo) {
- if !proptools.BoolDefault(c.Properties.Installable, true) {
+ if !proptools.BoolDefault(c.Installable(), true) {
// If the module has been specifically configure to not be installed then
// hide from make as otherwise it will break when running inside make
// as the output path to install will not be specified. Not all uninstallable
@@ -3260,6 +3260,11 @@
}
func (c *Module) Installable() *bool {
+ if c.library != nil {
+ if i := c.library.installable(); i != nil {
+ return i
+ }
+ }
return c.Properties.Installable
}
diff --git a/cc/config/Android.bp b/cc/config/Android.bp
index 3e8ee48..7b7ee28 100644
--- a/cc/config/Android.bp
+++ b/cc/config/Android.bp
@@ -24,7 +24,7 @@
"x86_device.go",
"x86_64_device.go",
- "x86_darwin_host.go",
+ "darwin_host.go",
"x86_linux_host.go",
"x86_linux_bionic_host.go",
"x86_windows_host.go",
diff --git a/cc/config/x86_darwin_host.go b/cc/config/darwin_host.go
similarity index 81%
rename from cc/config/x86_darwin_host.go
rename to cc/config/darwin_host.go
index ad82b94..318acb4 100644
--- a/cc/config/x86_darwin_host.go
+++ b/cc/config/darwin_host.go
@@ -53,9 +53,6 @@
}
darwinSupportedSdkVersions = []string{
- "10.13",
- "10.14",
- "10.15",
"11",
}
@@ -174,19 +171,43 @@
toolchain64Bit
}
-func (t *toolchainDarwin) Name() string {
+type toolchainDarwinX86 struct {
+ toolchainDarwin
+}
+
+type toolchainDarwinArm struct {
+ toolchainDarwin
+}
+
+func (t *toolchainDarwinArm) Name() string {
+ return "arm64"
+}
+
+func (t *toolchainDarwinX86) Name() string {
return "x86_64"
}
-func (t *toolchainDarwin) GccRoot() string {
+func (t *toolchainDarwinArm) GccRoot() string {
+ panic("unimplemented")
+}
+
+func (t *toolchainDarwinArm) GccTriple() string {
+ panic("unimplemented")
+}
+
+func (t *toolchainDarwinArm) GccVersion() string {
+ panic("unimplemented")
+}
+
+func (t *toolchainDarwinX86) GccRoot() string {
return "${config.DarwinGccRoot}"
}
-func (t *toolchainDarwin) GccTriple() string {
+func (t *toolchainDarwinX86) GccTriple() string {
return "${config.DarwinGccTriple}"
}
-func (t *toolchainDarwin) GccVersion() string {
+func (t *toolchainDarwinX86) GccVersion() string {
return darwinGccVersion
}
@@ -194,7 +215,11 @@
return ""
}
-func (t *toolchainDarwin) ClangTriple() string {
+func (t *toolchainDarwinArm) ClangTriple() string {
+ return "aarch64-apple-darwin"
+}
+
+func (t *toolchainDarwinX86) ClangTriple() string {
return "x86_64-apple-darwin"
}
@@ -230,12 +255,18 @@
return "${config.MacToolPath}"
}
-var toolchainDarwinSingleton Toolchain = &toolchainDarwin{}
+var toolchainDarwinArmSingleton Toolchain = &toolchainDarwinArm{}
+var toolchainDarwinX86Singleton Toolchain = &toolchainDarwinX86{}
-func darwinToolchainFactory(arch android.Arch) Toolchain {
- return toolchainDarwinSingleton
+func darwinArmToolchainFactory(arch android.Arch) Toolchain {
+ return toolchainDarwinArmSingleton
+}
+
+func darwinX86ToolchainFactory(arch android.Arch) Toolchain {
+ return toolchainDarwinX86Singleton
}
func init() {
- registerToolchainFactory(android.Darwin, android.X86_64, darwinToolchainFactory)
+ registerToolchainFactory(android.Darwin, android.Arm64, darwinArmToolchainFactory)
+ registerToolchainFactory(android.Darwin, android.X86_64, darwinX86ToolchainFactory)
}
diff --git a/cc/fuzz.go b/cc/fuzz.go
index 40f16f3..e987fe4 100644
--- a/cc/fuzz.go
+++ b/cc/fuzz.go
@@ -123,7 +123,7 @@
}
// Discard installable:false libraries because they are expected to be absent
// in runtime.
- if !proptools.BoolDefault(ccLibrary.Properties.Installable, true) {
+ if !proptools.BoolDefault(ccLibrary.Installable(), true) {
return false
}
}
diff --git a/cc/library.go b/cc/library.go
index 16cf481..c3f7305 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -159,6 +159,8 @@
Export_static_lib_headers []string `android:"arch_variant"`
Apex_available []string `android:"arch_variant"`
+
+ Installable *bool `android:"arch_variant"`
}
type LibraryMutatedProperties struct {
@@ -1048,6 +1050,8 @@
availableFor(string) bool
getAPIListCoverageXMLPath() android.ModuleOutPath
+
+ installable() *bool
}
type versionedInterface interface {
@@ -1972,6 +1976,15 @@
return android.CheckAvailableForApex(what, list)
}
+func (library *libraryDecorator) installable() *bool {
+ if library.static() {
+ return library.StaticProperties.Static.Installable
+ } else if library.shared() {
+ return library.SharedProperties.Shared.Installable
+ }
+ return nil
+}
+
func (library *libraryDecorator) makeUninstallable(mod *Module) {
if library.static() && library.buildStatic() && !library.buildStubs() {
// If we're asked to make a static library uninstallable we don't do
diff --git a/cc/lto.go b/cc/lto.go
index 99598a9..6d55579 100644
--- a/cc/lto.go
+++ b/cc/lto.go
@@ -137,9 +137,8 @@
func (lto *lto) DefaultThinLTO(ctx BaseModuleContext) bool {
host := ctx.Host()
- test := ctx.testBinary()
vndk := ctx.isVndk() // b/169217596
- return GlobalThinLTO(ctx) && !lto.Never() && !host && !test && !vndk
+ return GlobalThinLTO(ctx) && !lto.Never() && !host && !vndk
}
func (lto *lto) FullLTO() bool {
diff --git a/cc/ndk_sysroot.go b/cc/ndk_sysroot.go
index 2726b1a..fd458d9 100644
--- a/cc/ndk_sysroot.go
+++ b/cc/ndk_sysroot.go
@@ -33,7 +33,7 @@
// Component 3: Stub Libraries
// The shared libraries in the NDK are not the actual shared libraries they
// refer to (to prevent people from accidentally loading them), but stub
-// libraries with dummy implementations of everything for use at build time
+// libraries with placeholder implementations of everything for use at build time
// only.
//
// Since we don't actually need to know anything about the stub libraries aside
diff --git a/cc/prebuilt.go b/cc/prebuilt.go
index 4a2c451..3401e36 100644
--- a/cc/prebuilt.go
+++ b/cc/prebuilt.go
@@ -18,6 +18,7 @@
"path/filepath"
"android/soong/android"
+ "android/soong/bazel"
)
func init() {
@@ -31,6 +32,8 @@
ctx.RegisterModuleType("cc_prebuilt_test_library_shared", PrebuiltSharedTestLibraryFactory)
ctx.RegisterModuleType("cc_prebuilt_object", prebuiltObjectFactory)
ctx.RegisterModuleType("cc_prebuilt_binary", prebuiltBinaryFactory)
+
+ android.RegisterBp2BuildMutator("cc_prebuilt_library_shared", PrebuiltLibrarySharedBp2Build)
}
type prebuiltLinkerInterface interface {
@@ -309,6 +312,42 @@
return module, library
}
+type bazelPrebuiltLibrarySharedAttributes struct {
+ Shared_library bazel.LabelAttribute
+}
+
+func PrebuiltLibrarySharedBp2Build(ctx android.TopDownMutatorContext) {
+ module, ok := ctx.Module().(*Module)
+ if !ok {
+ // Not a cc module
+ return
+ }
+ if !module.ConvertWithBp2build(ctx) {
+ return
+ }
+ if ctx.ModuleType() != "cc_prebuilt_library_shared" {
+ return
+ }
+
+ prebuiltLibrarySharedBp2BuildInternal(ctx, module)
+}
+
+func prebuiltLibrarySharedBp2BuildInternal(ctx android.TopDownMutatorContext, module *Module) {
+ prebuiltAttrs := Bp2BuildParsePrebuiltLibraryProps(ctx, module)
+
+ attrs := &bazelPrebuiltLibrarySharedAttributes{
+ Shared_library: prebuiltAttrs.Src,
+ }
+
+ props := bazel.BazelTargetModuleProperties{
+ Rule_class: "prebuilt_library_shared",
+ Bzl_load_location: "//build/bazel/rules:prebuilt_library_shared.bzl",
+ }
+
+ name := android.RemoveOptionalPrebuiltPrefix(module.Name())
+ ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: name}, attrs)
+}
+
type prebuiltObjectProperties struct {
Srcs []string `android:"path,arch_variant"`
}
diff --git a/cc/sanitize.go b/cc/sanitize.go
index f6a9d5b..c7e8411 100644
--- a/cc/sanitize.go
+++ b/cc/sanitize.go
@@ -39,8 +39,15 @@
}
asanLdflags = []string{"-Wl,-u,__asan_preinit"}
- hwasanCflags = []string{"-fno-omit-frame-pointer", "-Wno-frame-larger-than=",
+ hwasanCflags = []string{
+ "-fno-omit-frame-pointer",
+ "-Wno-frame-larger-than=",
"-fsanitize-hwaddress-abi=platform",
+ }
+
+ // ThinLTO performs codegen during link time, thus these flags need to
+ // passed to both CFLAGS and LDFLAGS.
+ hwasanCommonflags = []string{
// The following improves debug location information
// availability at the cost of its accuracy. It increases
// the likelihood of a stack variable's frame offset
@@ -48,11 +55,11 @@
// for the quality of hwasan reports. The downside is a
// higher number of "optimized out" stack variables.
// b/112437883.
- "-mllvm", "-instcombine-lower-dbg-declare=0",
+ "-instcombine-lower-dbg-declare=0",
// TODO(b/159343917): HWASan and GlobalISel don't play nicely, and
// GlobalISel is the default at -O0 on aarch64.
- "-mllvm", "--aarch64-enable-global-isel-at-O=-1",
- "-mllvm", "-fast-isel=false",
+ "--aarch64-enable-global-isel-at-O=-1",
+ "-fast-isel=false",
}
cfiCflags = []string{"-flto", "-fsanitize-cfi-cross-dso",
@@ -629,6 +636,14 @@
if Bool(sanitize.Properties.Sanitize.Hwaddress) {
flags.Local.CFlags = append(flags.Local.CFlags, hwasanCflags...)
+
+ for _, flag := range hwasanCommonflags {
+ flags.Local.CFlags = append(flags.Local.CFlags, "-mllvm", flag)
+ }
+ for _, flag := range hwasanCommonflags {
+ flags.Local.LdFlags = append(flags.Local.LdFlags, "-Wl,-mllvm,"+flag)
+ }
+
if Bool(sanitize.Properties.Sanitize.Writeonly) {
flags.Local.CFlags = append(flags.Local.CFlags, "-mllvm", "-hwasan-instrument-reads=0")
}
diff --git a/compliance/build_license_metadata/Android.bp b/compliance/build_license_metadata/Android.bp
new file mode 100644
index 0000000..5000346
--- /dev/null
+++ b/compliance/build_license_metadata/Android.bp
@@ -0,0 +1,29 @@
+// 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+blueprint_go_binary {
+ name: "build_license_metadata",
+ srcs: [
+ "build_license_metadata.go",
+ ],
+ deps: [
+ "license_metadata_proto",
+ "golang-protobuf-proto",
+ "golang-protobuf-encoding-prototext",
+ ],
+}
diff --git a/compliance/build_license_metadata/build_license_metadata.go b/compliance/build_license_metadata/build_license_metadata.go
new file mode 100644
index 0000000..ba3cc3e
--- /dev/null
+++ b/compliance/build_license_metadata/build_license_metadata.go
@@ -0,0 +1,174 @@
+// 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 main
+
+import (
+ "flag"
+ "fmt"
+ "io/ioutil"
+ "os"
+ "path/filepath"
+ "strings"
+
+ "google.golang.org/protobuf/encoding/prototext"
+ "google.golang.org/protobuf/proto"
+
+ "android/soong/compliance/license_metadata_proto"
+)
+
+var (
+ packageName = flag.String("p", "", "license package name")
+ moduleType = newMultiString("mt", "module type")
+ moduleClass = newMultiString("mc", "module class")
+ kinds = newMultiString("k", "license kinds")
+ conditions = newMultiString("c", "license conditions")
+ notices = newMultiString("n", "license notice file")
+ deps = newMultiString("d", "license metadata file dependency")
+ sources = newMultiString("s", "source (input) dependency")
+ built = newMultiString("t", "built targets")
+ installed = newMultiString("i", "installed targets")
+ roots = newMultiString("r", "root directory of project")
+ installedMap = newMultiString("m", "map dependent targets to their installed names")
+ isContainer = flag.Bool("is_container", false, "preserved dependent target name when given")
+ outFile = flag.String("o", "", "output file")
+)
+
+func newMultiString(name, usage string) *multiString {
+ var f multiString
+ flag.Var(&f, name, usage)
+ return &f
+}
+
+type multiString []string
+
+func (ms *multiString) String() string { return strings.Join(*ms, ", ") }
+func (ms *multiString) Set(s string) error { *ms = append(*ms, s); return nil }
+
+func main() {
+ flag.Parse()
+
+ metadata := license_metadata_proto.LicenseMetadata{}
+ metadata.PackageName = proto.String(*packageName)
+ metadata.ModuleTypes = *moduleType
+ metadata.ModuleClasses = *moduleClass
+ metadata.IsContainer = proto.Bool(*isContainer)
+ metadata.Projects = findGitRoots(*roots)
+ metadata.LicenseKinds = *kinds
+ metadata.LicenseConditions = *conditions
+ metadata.LicenseTexts = *notices
+ metadata.Built = *built
+ metadata.Installed = *installed
+ metadata.InstallMap = convertInstalledMap(*installedMap)
+ metadata.Sources = *sources
+ metadata.Deps = convertDependencies(*deps)
+
+ err := writeMetadata(*outFile, &metadata)
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "error: %s\n", err.Error())
+ os.Exit(2)
+ }
+}
+
+func findGitRoots(dirs []string) []string {
+ ret := make([]string, len(dirs))
+ for i, dir := range dirs {
+ ret[i] = findGitRoot(dir)
+ }
+ return ret
+}
+
+// findGitRoot finds the directory at or above dir that contains a ".git" directory. This isn't
+// guaranteed to exist, for example during remote execution, when sandboxed, when building from
+// infrastructure that doesn't use git, or when the .git directory has been removed to save space,
+// but it should be good enough for local builds. If no .git directory is found the original value
+// is returned.
+func findGitRoot(dir string) string {
+ orig := dir
+ for dir != "" && dir != "." && dir != "/" {
+ _, err := os.Stat(filepath.Join(dir, ".git"))
+ if err == nil {
+ // Found dir/.git, return dir.
+ return dir
+ } else if !os.IsNotExist(err) {
+ // Error finding .git, return original input.
+ return orig
+ }
+ dir, _ = filepath.Split(dir)
+ dir = strings.TrimSuffix(dir, "/")
+ }
+ return orig
+}
+
+// convertInstalledMap converts a list of colon-separated from:to pairs into InstallMap proto
+// messages.
+func convertInstalledMap(installMaps []string) []*license_metadata_proto.InstallMap {
+ var ret []*license_metadata_proto.InstallMap
+
+ for _, installMap := range installMaps {
+ components := strings.Split(installMap, ":")
+ if len(components) != 2 {
+ panic(fmt.Errorf("install map entry %q contains %d colons, expected 1", len(components)-1))
+ }
+ ret = append(ret, &license_metadata_proto.InstallMap{
+ FromPath: proto.String(components[0]),
+ ContainerPath: proto.String(components[1]),
+ })
+ }
+
+ return ret
+}
+
+// convertDependencies converts a colon-separated tuple of dependency:annotation:annotation...
+// into AnnotatedDependency proto messages.
+func convertDependencies(deps []string) []*license_metadata_proto.AnnotatedDependency {
+ var ret []*license_metadata_proto.AnnotatedDependency
+
+ for _, d := range deps {
+ components := strings.Split(d, ":")
+ dep := components[0]
+ components = components[1:]
+ ad := &license_metadata_proto.AnnotatedDependency{
+ File: proto.String(dep),
+ Annotations: make([]string, 0, len(components)),
+ }
+ for _, ann := range components {
+ if len(ann) == 0 {
+ continue
+ }
+ ad.Annotations = append(ad.Annotations, ann)
+ }
+ ret = append(ret, ad)
+ }
+
+ return ret
+}
+
+func writeMetadata(file string, metadata *license_metadata_proto.LicenseMetadata) error {
+ buf, err := prototext.MarshalOptions{Multiline: true}.Marshal(metadata)
+ if err != nil {
+ return fmt.Errorf("error marshalling textproto: %w", err)
+ }
+
+ if file != "" {
+ err = ioutil.WriteFile(file, buf, 0666)
+ if err != nil {
+ return fmt.Errorf("error writing textproto %q: %w", file, err)
+ }
+ } else {
+ _, _ = os.Stdout.Write(buf)
+ }
+
+ return nil
+}
diff --git a/compliance/license_metadata_proto/Android.bp b/compliance/license_metadata_proto/Android.bp
new file mode 100644
index 0000000..3c041e4
--- /dev/null
+++ b/compliance/license_metadata_proto/Android.bp
@@ -0,0 +1,27 @@
+// 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+bootstrap_go_package {
+ name: "license_metadata_proto",
+ pkgPath: "android/soong/compliance/license_metadata_proto",
+ srcs: ["license_metadata.pb.go"],
+ deps: [
+ "golang-protobuf-reflect-protoreflect",
+ "golang-protobuf-runtime-protoimpl",
+ ],
+}
diff --git a/compliance/license_metadata_proto/license_metadata.pb.go b/compliance/license_metadata_proto/license_metadata.pb.go
new file mode 100644
index 0000000..44dbc78
--- /dev/null
+++ b/compliance/license_metadata_proto/license_metadata.pb.go
@@ -0,0 +1,451 @@
+// 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.
+
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// versions:
+// protoc-gen-go v1.27.1
+// protoc v3.19.0
+// source: license_metadata.proto
+
+package license_metadata_proto
+
+import (
+ protoreflect "google.golang.org/protobuf/reflect/protoreflect"
+ protoimpl "google.golang.org/protobuf/runtime/protoimpl"
+ reflect "reflect"
+ sync "sync"
+)
+
+const (
+ // Verify that this generated code is sufficiently up-to-date.
+ _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
+ // Verify that runtime/protoimpl is sufficiently up-to-date.
+ _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
+)
+
+type LicenseMetadata struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ // package_name identifies the source package. License texts are named relative to the package name.
+ PackageName *string `protobuf:"bytes,1,opt,name=package_name,json=packageName" json:"package_name,omitempty"`
+ ModuleTypes []string `protobuf:"bytes,2,rep,name=module_types,json=moduleTypes" json:"module_types,omitempty"`
+ ModuleClasses []string `protobuf:"bytes,3,rep,name=module_classes,json=moduleClasses" json:"module_classes,omitempty"`
+ // projects identifies the git project(s) containing the associated source code.
+ Projects []string `protobuf:"bytes,4,rep,name=projects" json:"projects,omitempty"`
+ // license_kinds lists the kinds of licenses. e.g. SPDX-license-identifier-Apache-2.0 or legacy_notice.
+ LicenseKinds []string `protobuf:"bytes,5,rep,name=license_kinds,json=licenseKinds" json:"license_kinds,omitempty"`
+ // license_conditions lists the conditions that apply to the license kinds. e.g. notice or restricted.
+ LicenseConditions []string `protobuf:"bytes,6,rep,name=license_conditions,json=licenseConditions" json:"license_conditions,omitempty"`
+ // license_texts lists the filenames of the associated license text(s).
+ LicenseTexts []string `protobuf:"bytes,7,rep,name=license_texts,json=licenseTexts" json:"license_texts,omitempty"`
+ // is_container is true for target types that merely aggregate. e.g. .img or .zip files.
+ IsContainer *bool `protobuf:"varint,8,opt,name=is_container,json=isContainer" json:"is_container,omitempty"`
+ // built lists the built targets.
+ Built []string `protobuf:"bytes,9,rep,name=built" json:"built,omitempty"`
+ // installed lists the installed targets.
+ Installed []string `protobuf:"bytes,10,rep,name=installed" json:"installed,omitempty"`
+ // installMap identifies the substitutions to make to path names when moving into installed location.
+ InstallMap []*InstallMap `protobuf:"bytes,11,rep,name=install_map,json=installMap" json:"install_map,omitempty"`
+ // sources lists the targets depended on.
+ Sources []string `protobuf:"bytes,12,rep,name=sources" json:"sources,omitempty"`
+ // deps lists the license metadata files depended on.
+ Deps []*AnnotatedDependency `protobuf:"bytes,13,rep,name=deps" json:"deps,omitempty"`
+}
+
+func (x *LicenseMetadata) Reset() {
+ *x = LicenseMetadata{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_license_metadata_proto_msgTypes[0]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *LicenseMetadata) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*LicenseMetadata) ProtoMessage() {}
+
+func (x *LicenseMetadata) ProtoReflect() protoreflect.Message {
+ mi := &file_license_metadata_proto_msgTypes[0]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use LicenseMetadata.ProtoReflect.Descriptor instead.
+func (*LicenseMetadata) Descriptor() ([]byte, []int) {
+ return file_license_metadata_proto_rawDescGZIP(), []int{0}
+}
+
+func (x *LicenseMetadata) GetPackageName() string {
+ if x != nil && x.PackageName != nil {
+ return *x.PackageName
+ }
+ return ""
+}
+
+func (x *LicenseMetadata) GetModuleTypes() []string {
+ if x != nil {
+ return x.ModuleTypes
+ }
+ return nil
+}
+
+func (x *LicenseMetadata) GetModuleClasses() []string {
+ if x != nil {
+ return x.ModuleClasses
+ }
+ return nil
+}
+
+func (x *LicenseMetadata) GetProjects() []string {
+ if x != nil {
+ return x.Projects
+ }
+ return nil
+}
+
+func (x *LicenseMetadata) GetLicenseKinds() []string {
+ if x != nil {
+ return x.LicenseKinds
+ }
+ return nil
+}
+
+func (x *LicenseMetadata) GetLicenseConditions() []string {
+ if x != nil {
+ return x.LicenseConditions
+ }
+ return nil
+}
+
+func (x *LicenseMetadata) GetLicenseTexts() []string {
+ if x != nil {
+ return x.LicenseTexts
+ }
+ return nil
+}
+
+func (x *LicenseMetadata) GetIsContainer() bool {
+ if x != nil && x.IsContainer != nil {
+ return *x.IsContainer
+ }
+ return false
+}
+
+func (x *LicenseMetadata) GetBuilt() []string {
+ if x != nil {
+ return x.Built
+ }
+ return nil
+}
+
+func (x *LicenseMetadata) GetInstalled() []string {
+ if x != nil {
+ return x.Installed
+ }
+ return nil
+}
+
+func (x *LicenseMetadata) GetInstallMap() []*InstallMap {
+ if x != nil {
+ return x.InstallMap
+ }
+ return nil
+}
+
+func (x *LicenseMetadata) GetSources() []string {
+ if x != nil {
+ return x.Sources
+ }
+ return nil
+}
+
+func (x *LicenseMetadata) GetDeps() []*AnnotatedDependency {
+ if x != nil {
+ return x.Deps
+ }
+ return nil
+}
+
+// InstallMap messages describe the mapping from an input filesystem file to the path to the file
+// in a container.
+type InstallMap struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ // The input path on the filesystem.
+ FromPath *string `protobuf:"bytes,1,opt,name=from_path,json=fromPath" json:"from_path,omitempty"`
+ // The path to the file inside the container or installed location.
+ ContainerPath *string `protobuf:"bytes,2,opt,name=container_path,json=containerPath" json:"container_path,omitempty"`
+}
+
+func (x *InstallMap) Reset() {
+ *x = InstallMap{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_license_metadata_proto_msgTypes[1]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *InstallMap) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*InstallMap) ProtoMessage() {}
+
+func (x *InstallMap) ProtoReflect() protoreflect.Message {
+ mi := &file_license_metadata_proto_msgTypes[1]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use InstallMap.ProtoReflect.Descriptor instead.
+func (*InstallMap) Descriptor() ([]byte, []int) {
+ return file_license_metadata_proto_rawDescGZIP(), []int{1}
+}
+
+func (x *InstallMap) GetFromPath() string {
+ if x != nil && x.FromPath != nil {
+ return *x.FromPath
+ }
+ return ""
+}
+
+func (x *InstallMap) GetContainerPath() string {
+ if x != nil && x.ContainerPath != nil {
+ return *x.ContainerPath
+ }
+ return ""
+}
+
+// AnnotateDepencency messages describe edges in the build graph.
+type AnnotatedDependency struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ // The path to the dependency license metadata file.
+ File *string `protobuf:"bytes,1,opt,name=file" json:"file,omitempty"`
+ // The annotations attached to the dependency.
+ Annotations []string `protobuf:"bytes,2,rep,name=annotations" json:"annotations,omitempty"`
+}
+
+func (x *AnnotatedDependency) Reset() {
+ *x = AnnotatedDependency{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_license_metadata_proto_msgTypes[2]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *AnnotatedDependency) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*AnnotatedDependency) ProtoMessage() {}
+
+func (x *AnnotatedDependency) ProtoReflect() protoreflect.Message {
+ mi := &file_license_metadata_proto_msgTypes[2]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use AnnotatedDependency.ProtoReflect.Descriptor instead.
+func (*AnnotatedDependency) Descriptor() ([]byte, []int) {
+ return file_license_metadata_proto_rawDescGZIP(), []int{2}
+}
+
+func (x *AnnotatedDependency) GetFile() string {
+ if x != nil && x.File != nil {
+ return *x.File
+ }
+ return ""
+}
+
+func (x *AnnotatedDependency) GetAnnotations() []string {
+ if x != nil {
+ return x.Annotations
+ }
+ return nil
+}
+
+var File_license_metadata_proto protoreflect.FileDescriptor
+
+var file_license_metadata_proto_rawDesc = []byte{
+ 0x0a, 0x16, 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61,
+ 0x74, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x16, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f,
+ 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61,
+ 0x22, 0x8a, 0x04, 0x0a, 0x0f, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61,
+ 0x64, 0x61, 0x74, 0x61, 0x12, 0x21, 0x0a, 0x0c, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x5f,
+ 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x61, 0x63, 0x6b,
+ 0x61, 0x67, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x6d, 0x6f, 0x64, 0x75, 0x6c,
+ 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0b, 0x6d,
+ 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x54, 0x79, 0x70, 0x65, 0x73, 0x12, 0x25, 0x0a, 0x0e, 0x6d, 0x6f,
+ 0x64, 0x75, 0x6c, 0x65, 0x5f, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03,
+ 0x28, 0x09, 0x52, 0x0d, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x65,
+ 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x18, 0x04, 0x20,
+ 0x03, 0x28, 0x09, 0x52, 0x08, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x12, 0x23, 0x0a,
+ 0x0d, 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x5f, 0x6b, 0x69, 0x6e, 0x64, 0x73, 0x18, 0x05,
+ 0x20, 0x03, 0x28, 0x09, 0x52, 0x0c, 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x4b, 0x69, 0x6e,
+ 0x64, 0x73, 0x12, 0x2d, 0x0a, 0x12, 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x5f, 0x63, 0x6f,
+ 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x09, 0x52, 0x11,
+ 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e,
+ 0x73, 0x12, 0x23, 0x0a, 0x0d, 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x5f, 0x74, 0x65, 0x78,
+ 0x74, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0c, 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73,
+ 0x65, 0x54, 0x65, 0x78, 0x74, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x69, 0x73, 0x5f, 0x63, 0x6f, 0x6e,
+ 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x69, 0x73,
+ 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x12, 0x14, 0x0a, 0x05, 0x62, 0x75, 0x69,
+ 0x6c, 0x74, 0x18, 0x09, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x62, 0x75, 0x69, 0x6c, 0x74, 0x12,
+ 0x1c, 0x0a, 0x09, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x18, 0x0a, 0x20, 0x03,
+ 0x28, 0x09, 0x52, 0x09, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x12, 0x43, 0x0a,
+ 0x0b, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x5f, 0x6d, 0x61, 0x70, 0x18, 0x0b, 0x20, 0x03,
+ 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6c, 0x69, 0x63, 0x65, 0x6e,
+ 0x73, 0x65, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x49, 0x6e, 0x73, 0x74,
+ 0x61, 0x6c, 0x6c, 0x4d, 0x61, 0x70, 0x52, 0x0a, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x4d,
+ 0x61, 0x70, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x18, 0x0c, 0x20,
+ 0x03, 0x28, 0x09, 0x52, 0x07, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, 0x3f, 0x0a, 0x04,
+ 0x64, 0x65, 0x70, 0x73, 0x18, 0x0d, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x62, 0x75, 0x69,
+ 0x6c, 0x64, 0x5f, 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64,
+ 0x61, 0x74, 0x61, 0x2e, 0x41, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x65, 0x64, 0x44, 0x65, 0x70,
+ 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x79, 0x52, 0x04, 0x64, 0x65, 0x70, 0x73, 0x22, 0x50, 0x0a,
+ 0x0a, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x4d, 0x61, 0x70, 0x12, 0x1b, 0x0a, 0x09, 0x66,
+ 0x72, 0x6f, 0x6d, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08,
+ 0x66, 0x72, 0x6f, 0x6d, 0x50, 0x61, 0x74, 0x68, 0x12, 0x25, 0x0a, 0x0e, 0x63, 0x6f, 0x6e, 0x74,
+ 0x61, 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09,
+ 0x52, 0x0d, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x50, 0x61, 0x74, 0x68, 0x22,
+ 0x4b, 0x0a, 0x13, 0x41, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x65, 0x64, 0x44, 0x65, 0x70, 0x65,
+ 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x79, 0x12, 0x12, 0x0a, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x01,
+ 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x61, 0x6e,
+ 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52,
+ 0x0b, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x42, 0x31, 0x5a, 0x2f,
+ 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x2f, 0x63, 0x6f,
+ 0x6d, 0x70, 0x6c, 0x69, 0x61, 0x6e, 0x63, 0x65, 0x2f, 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65,
+ 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+}
+
+var (
+ file_license_metadata_proto_rawDescOnce sync.Once
+ file_license_metadata_proto_rawDescData = file_license_metadata_proto_rawDesc
+)
+
+func file_license_metadata_proto_rawDescGZIP() []byte {
+ file_license_metadata_proto_rawDescOnce.Do(func() {
+ file_license_metadata_proto_rawDescData = protoimpl.X.CompressGZIP(file_license_metadata_proto_rawDescData)
+ })
+ return file_license_metadata_proto_rawDescData
+}
+
+var file_license_metadata_proto_msgTypes = make([]protoimpl.MessageInfo, 3)
+var file_license_metadata_proto_goTypes = []interface{}{
+ (*LicenseMetadata)(nil), // 0: build_license_metadata.LicenseMetadata
+ (*InstallMap)(nil), // 1: build_license_metadata.InstallMap
+ (*AnnotatedDependency)(nil), // 2: build_license_metadata.AnnotatedDependency
+}
+var file_license_metadata_proto_depIdxs = []int32{
+ 1, // 0: build_license_metadata.LicenseMetadata.install_map:type_name -> build_license_metadata.InstallMap
+ 2, // 1: build_license_metadata.LicenseMetadata.deps:type_name -> build_license_metadata.AnnotatedDependency
+ 2, // [2:2] is the sub-list for method output_type
+ 2, // [2:2] is the sub-list for method input_type
+ 2, // [2:2] is the sub-list for extension type_name
+ 2, // [2:2] is the sub-list for extension extendee
+ 0, // [0:2] is the sub-list for field type_name
+}
+
+func init() { file_license_metadata_proto_init() }
+func file_license_metadata_proto_init() {
+ if File_license_metadata_proto != nil {
+ return
+ }
+ if !protoimpl.UnsafeEnabled {
+ file_license_metadata_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*LicenseMetadata); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_license_metadata_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*InstallMap); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_license_metadata_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*AnnotatedDependency); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ }
+ type x struct{}
+ out := protoimpl.TypeBuilder{
+ File: protoimpl.DescBuilder{
+ GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
+ RawDescriptor: file_license_metadata_proto_rawDesc,
+ NumEnums: 0,
+ NumMessages: 3,
+ NumExtensions: 0,
+ NumServices: 0,
+ },
+ GoTypes: file_license_metadata_proto_goTypes,
+ DependencyIndexes: file_license_metadata_proto_depIdxs,
+ MessageInfos: file_license_metadata_proto_msgTypes,
+ }.Build()
+ File_license_metadata_proto = out.File
+ file_license_metadata_proto_rawDesc = nil
+ file_license_metadata_proto_goTypes = nil
+ file_license_metadata_proto_depIdxs = nil
+}
diff --git a/compliance/license_metadata_proto/license_metadata.proto b/compliance/license_metadata_proto/license_metadata.proto
new file mode 100644
index 0000000..1b4f34f
--- /dev/null
+++ b/compliance/license_metadata_proto/license_metadata.proto
@@ -0,0 +1,76 @@
+// 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.
+
+syntax = "proto2";
+
+package build_license_metadata;
+option go_package = "android/soong/compliance/license_metadata_proto";
+
+message LicenseMetadata {
+ // package_name identifies the source package. License texts are named relative to the package name.
+ optional string package_name = 1;
+
+ repeated string module_types = 2;
+
+ repeated string module_classes = 3;
+
+ // projects identifies the git project(s) containing the associated source code.
+ repeated string projects = 4;
+
+ // license_kinds lists the kinds of licenses. e.g. SPDX-license-identifier-Apache-2.0 or legacy_notice.
+ repeated string license_kinds = 5;
+
+ // license_conditions lists the conditions that apply to the license kinds. e.g. notice or restricted.
+ repeated string license_conditions = 6;
+
+ // license_texts lists the filenames of the associated license text(s).
+ repeated string license_texts = 7;
+
+ // is_container is true for target types that merely aggregate. e.g. .img or .zip files.
+ optional bool is_container = 8;
+
+ // built lists the built targets.
+ repeated string built = 9;
+
+ // installed lists the installed targets.
+ repeated string installed = 10;
+
+ // installMap identifies the substitutions to make to path names when moving into installed location.
+ repeated InstallMap install_map = 11;
+
+ // sources lists the targets depended on.
+ repeated string sources = 12;
+
+ // deps lists the license metadata files depended on.
+ repeated AnnotatedDependency deps = 13;
+}
+
+// InstallMap messages describe the mapping from an input filesystem file to the path to the file
+// in a container.
+message InstallMap {
+ // The input path on the filesystem.
+ optional string from_path = 1;
+
+ // The path to the file inside the container or installed location.
+ optional string container_path = 2;
+}
+
+// AnnotateDepencency messages describe edges in the build graph.
+message AnnotatedDependency {
+ // The path to the dependency license metadata file.
+ optional string file = 1;
+
+ // The annotations attached to the dependency.
+ repeated string annotations = 2;
+}
diff --git a/dexpreopt/dexpreopt.go b/dexpreopt/dexpreopt.go
index 965b755..3145315 100644
--- a/dexpreopt/dexpreopt.go
+++ b/dexpreopt/dexpreopt.go
@@ -204,6 +204,17 @@
return fmt.Sprintf("/system/framework/%s.jar", lib)
}
+// Returns the location to the odex file for the dex file at `path`.
+func ToOdexPath(path string, arch android.ArchType) string {
+ if strings.HasPrefix(path, "/apex/") {
+ return filepath.Join("/system/framework/oat", arch.String(),
+ strings.ReplaceAll(path[1:], "/", "@")+"@classes.odex")
+ }
+
+ return filepath.Join(filepath.Dir(path), "oat", arch.String(),
+ pathtools.ReplaceExtension(filepath.Base(path), "odex"))
+}
+
func dexpreoptCommand(ctx android.PathContext, globalSoong *GlobalSoongConfig, global *GlobalConfig,
module *ModuleConfig, rule *android.RuleBuilder, archIdx int, profile android.WritablePath,
appImage bool, generateDM bool) {
@@ -218,23 +229,8 @@
base = "package.apk"
}
- toOdexPath := func(path string) string {
- if global.ApexSystemServerJars.ContainsJar(module.Name) {
- return filepath.Join(
- "/system/framework/oat",
- arch.String(),
- strings.ReplaceAll(path[1:], "/", "@")+"@classes.odex")
- }
-
- return filepath.Join(
- filepath.Dir(path),
- "oat",
- arch.String(),
- pathtools.ReplaceExtension(filepath.Base(path), "odex"))
- }
-
odexPath := module.BuildPath.InSameDir(ctx, "oat", arch.String(), pathtools.ReplaceExtension(base, "odex"))
- odexInstallPath := toOdexPath(module.DexLocation)
+ odexInstallPath := ToOdexPath(module.DexLocation, arch)
if odexOnSystemOther(module, global) {
odexInstallPath = filepath.Join(SystemOtherPartition, odexInstallPath)
}
diff --git a/genrule/genrule.go b/genrule/genrule.go
index b9c2b10..c9bf958 100644
--- a/genrule/genrule.go
+++ b/genrule/genrule.go
@@ -336,14 +336,9 @@
}
case bootstrap.GoBinaryTool:
// A GoBinaryTool provides the install path to a tool, which will be copied.
- if s, err := filepath.Rel(android.PathForOutput(ctx).String(), t.InstallPath()); err == nil {
- toolPath := android.PathForOutput(ctx, s)
- tools = append(tools, toolPath)
- addLocationLabel(tag.label, toolLocation{android.Paths{toolPath}})
- } else {
- ctx.ModuleErrorf("cannot find path for %q: %v", tool, err)
- return
- }
+ p := android.PathForGoBinary(ctx, t)
+ tools = append(tools, p)
+ addLocationLabel(tag.label, toolLocation{android.Paths{p}})
default:
ctx.ModuleErrorf("%q is not a host tool provider", tool)
return
diff --git a/java/Android.bp b/java/Android.bp
index 9ffa123..8835b44 100644
--- a/java/Android.bp
+++ b/java/Android.bp
@@ -40,6 +40,7 @@
"dex.go",
"dexpreopt.go",
"dexpreopt_bootjars.go",
+ "dexpreopt_check.go",
"dexpreopt_config.go",
"droiddoc.go",
"droidstubs.go",
@@ -92,6 +93,7 @@
"platform_bootclasspath_test.go",
"platform_compat_config_test.go",
"plugin_test.go",
+ "prebuilt_apis_test.go",
"rro_test.go",
"sdk_test.go",
"sdk_library_test.go",
diff --git a/java/bootclasspath_fragment.go b/java/bootclasspath_fragment.go
index 8f18790..bfa6838 100644
--- a/java/bootclasspath_fragment.go
+++ b/java/bootclasspath_fragment.go
@@ -616,6 +616,8 @@
// This is an exception to support end-to-end test for SdkExtensions, until such support exists.
if android.InList("test_framework-sdkextensions", possibleUpdatableModules) {
jars = jars.Append("com.android.sdkext", "test_framework-sdkextensions")
+ } else if android.InList("test_framework-apexd", possibleUpdatableModules) {
+ jars = jars.Append("com.android.apex.test_package", "test_framework-apexd")
} else if global.ApexBootJars.Len() != 0 && !android.IsModuleInVersionedSdk(ctx.Module()) {
unknown = android.RemoveListFromList(unknown, b.properties.Coverage.Contents)
_, unknown = android.RemoveFromList("core-icu4j", unknown)
diff --git a/java/core-libraries/Android.bp b/java/core-libraries/Android.bp
index b198c24..cf39746 100644
--- a/java/core-libraries/Android.bp
+++ b/java/core-libraries/Android.bp
@@ -28,6 +28,11 @@
default_applicable_licenses: ["Android-Apache-2.0"],
}
+dist_targets = [
+ "sdk",
+ "win_sdk",
+]
+
java_library {
name: "core.current.stubs",
visibility: ["//visibility:public"],
@@ -40,15 +45,16 @@
system_modules: "none",
dist: {
- targets: [
- "sdk",
- "win_sdk",
- ],
+ targets: dist_targets,
},
}
// Distributed with the SDK for turning into system modules to compile apps
// against.
+//
+// Also, produces dist files that are used by the
+// prebuilts/sdk/update_prebuilts.py script to update the prebuilts/sdk
+// directory.
java_library {
name: "core-current-stubs-for-system-modules",
visibility: ["//development/sdk"],
@@ -65,18 +71,22 @@
],
sdk_version: "none",
system_modules: "none",
- dist: {
- dest: "core-for-system-modules.jar",
- targets: [
- "sdk",
- "win_sdk",
- ],
- },
+ dists: [
+ {
+ // Legacy dist location for the public file.
+ dest: "core-for-system-modules.jar",
+ targets: dist_targets,
+ },
+ {
+ dest: "system-modules/public/core-for-system-modules.jar",
+ targets: dist_targets,
+ },
+ ],
}
// Used when compiling higher-level code against core.current.stubs.
java_system_modules {
- name: "core-current-stubs-system-modules",
+ name: "core-public-stubs-system-modules",
visibility: ["//visibility:public"],
libs: [
"core-current-stubs-for-system-modules",
@@ -103,10 +113,13 @@
visibility: ["//visibility:private"],
}
-// Used when compiling higher-level code with sdk_version "module_current"
-java_system_modules {
- name: "core-module-lib-stubs-system-modules",
- libs: [
+// Produces a dist file that is used by the
+// prebuilts/sdk/update_prebuilts.py script to update the prebuilts/sdk
+// directory.
+java_library {
+ name: "core-module-lib-stubs-for-system-modules",
+ visibility: ["//visibility:private"],
+ static_libs: [
"core.module_lib.stubs",
// This one is not on device but it's needed when javac compiles code
// containing lambdas.
@@ -117,6 +130,20 @@
// See http://b/123891440.
"core-generated-annotation-stubs",
],
+ sdk_version: "none",
+ system_modules: "none",
+ dist: {
+ dest: "system-modules/module-lib/core-for-system-modules.jar",
+ targets: dist_targets,
+ },
+}
+
+// Used when compiling higher-level code with sdk_version "module_current"
+java_system_modules {
+ name: "core-module-lib-stubs-system-modules",
+ libs: [
+ "core-module-lib-stubs-for-system-modules",
+ ],
visibility: ["//visibility:public"],
}
diff --git a/java/dexpreopt_check.go b/java/dexpreopt_check.go
new file mode 100644
index 0000000..565901d
--- /dev/null
+++ b/java/dexpreopt_check.go
@@ -0,0 +1,96 @@
+// 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 java
+
+import (
+ "strings"
+
+ "android/soong/android"
+ "android/soong/dexpreopt"
+
+ "github.com/google/blueprint/pathtools"
+)
+
+func init() {
+ RegisterDexpreoptCheckBuildComponents(android.InitRegistrationContext)
+}
+
+func RegisterDexpreoptCheckBuildComponents(ctx android.RegistrationContext) {
+ ctx.RegisterSingletonModuleType("dexpreopt_systemserver_check", dexpreoptSystemserverCheckFactory)
+}
+
+// A build-time check to verify if all compilation artifacts of system server jars are installed
+// into the system image. When the check fails, it means that dexpreopting is not working for some
+// system server jars and needs to be fixed.
+// This singleton module generates a list of the paths to the artifacts based on
+// PRODUCT_SYSTEM_SERVER_JARS and PRODUCT_APEX_SYSTEM_SERVER_JARS, and passes it to Make via a
+// variable. Make will then do the actual check.
+// Currently, it only checks artifacts of modules defined in Soong. Artifacts of modules defined in
+// Makefile are generated by a script generated by dexpreopt_gen, and their existence is unknown to
+// Make and Ninja.
+type dexpreoptSystemserverCheck struct {
+ android.SingletonModuleBase
+
+ // Mapping from the module name to the install paths to the compilation artifacts.
+ artifactsByModuleName map[string][]string
+
+ // The install paths to the compilation artifacts.
+ artifacts []string
+}
+
+func dexpreoptSystemserverCheckFactory() android.SingletonModule {
+ m := &dexpreoptSystemserverCheck{}
+ m.artifactsByModuleName = make(map[string][]string)
+ android.InitAndroidArchModule(m, android.DeviceSupported, android.MultilibCommon)
+ return m
+}
+
+func getInstallPath(ctx android.ModuleContext, location string) android.InstallPath {
+ return android.PathForModuleInPartitionInstall(
+ ctx, "", strings.TrimPrefix(location, "/")).ToMakePath()
+}
+
+func (m *dexpreoptSystemserverCheck) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ global := dexpreopt.GetGlobalConfig(ctx)
+ targets := ctx.Config().Targets[android.Android]
+
+ // The check should be skipped on unbundled builds because system server jars are not preopted on
+ // unbundled builds since the artifacts are installed into the system image, not the APEXes.
+ if global.DisablePreopt || len(targets) == 0 || ctx.Config().UnbundledBuild() {
+ return
+ }
+
+ systemServerJars := dexpreopt.AllSystemServerJars(ctx, global)
+ for _, jar := range systemServerJars.CopyOfJars() {
+ dexLocation := dexpreopt.GetSystemServerDexLocation(global, jar)
+ odexLocation := dexpreopt.ToOdexPath(dexLocation, targets[0].Arch.ArchType)
+ odexPath := getInstallPath(ctx, odexLocation)
+ vdexPath := getInstallPath(ctx, pathtools.ReplaceExtension(odexLocation, "vdex"))
+ m.artifactsByModuleName[jar] = []string{odexPath.String(), vdexPath.String()}
+ }
+}
+
+func (m *dexpreoptSystemserverCheck) GenerateSingletonBuildActions(ctx android.SingletonContext) {
+ // Only keep modules defined in Soong.
+ ctx.VisitAllModules(func(module android.Module) {
+ if artifacts, ok := m.artifactsByModuleName[module.Name()]; ok {
+ m.artifacts = append(m.artifacts, artifacts...)
+ }
+ })
+}
+
+func (m *dexpreoptSystemserverCheck) MakeVars(ctx android.MakeVarsContext) {
+ ctx.Strict("DEXPREOPT_SYSTEMSERVER_ARTIFACTS", strings.Join(m.artifacts, " "))
+}
diff --git a/java/droidstubs.go b/java/droidstubs.go
index 0c66ccf..7ad316f 100644
--- a/java/droidstubs.go
+++ b/java/droidstubs.go
@@ -16,6 +16,7 @@
import (
"fmt"
+ "path/filepath"
"strings"
"github.com/google/blueprint/proptools"
@@ -805,7 +806,7 @@
properties PrebuiltStubsSourcesProperties
- stubsSrcJar android.ModuleOutPath
+ stubsSrcJar android.Path
}
func (p *PrebuiltStubsSources) OutputFiles(tag string) (android.Paths, error) {
@@ -822,35 +823,39 @@
}
func (p *PrebuiltStubsSources) GenerateAndroidBuildActions(ctx android.ModuleContext) {
- p.stubsSrcJar = android.PathForModuleOut(ctx, ctx.ModuleName()+"-"+"stubs.srcjar")
-
if len(p.properties.Srcs) != 1 {
- ctx.PropertyErrorf("srcs", "must only specify one directory path, contains %d paths", len(p.properties.Srcs))
+ ctx.PropertyErrorf("srcs", "must only specify one directory path or srcjar, contains %d paths", len(p.properties.Srcs))
return
}
- localSrcDir := p.properties.Srcs[0]
- // Although PathForModuleSrc can return nil if either the path doesn't exist or
- // the path components are invalid it won't in this case because no components
- // are specified and the module directory must exist in order to get this far.
- srcDir := android.PathForModuleSrc(ctx).(android.SourcePath).Join(ctx, localSrcDir)
+ src := p.properties.Srcs[0]
+ if filepath.Ext(src) == ".srcjar" {
+ // This is a srcjar. We can use it directly.
+ p.stubsSrcJar = android.PathForModuleSrc(ctx, src)
+ } else {
+ outPath := android.PathForModuleOut(ctx, ctx.ModuleName()+"-"+"stubs.srcjar")
- // Glob the contents of the directory just in case the directory does not exist.
- srcGlob := localSrcDir + "/**/*"
- srcPaths := android.PathsForModuleSrc(ctx, []string{srcGlob})
+ // This is a directory. Glob the contents just in case the directory does not exist.
+ srcGlob := src + "/**/*"
+ srcPaths := android.PathsForModuleSrc(ctx, []string{srcGlob})
- rule := android.NewRuleBuilder(pctx, ctx)
- rule.Command().
- BuiltTool("soong_zip").
- Flag("-write_if_changed").
- Flag("-jar").
- FlagWithOutput("-o ", p.stubsSrcJar).
- FlagWithArg("-C ", srcDir.String()).
- FlagWithRspFileInputList("-r ", p.stubsSrcJar.ReplaceExtension(ctx, "rsp"), srcPaths)
+ // Although PathForModuleSrc can return nil if either the path doesn't exist or
+ // the path components are invalid it won't in this case because no components
+ // are specified and the module directory must exist in order to get this far.
+ srcDir := android.PathForModuleSrc(ctx).(android.SourcePath).Join(ctx, src)
- rule.Restat()
-
- rule.Build("zip src", "Create srcjar from prebuilt source")
+ rule := android.NewRuleBuilder(pctx, ctx)
+ rule.Command().
+ BuiltTool("soong_zip").
+ Flag("-write_if_changed").
+ Flag("-jar").
+ FlagWithOutput("-o ", outPath).
+ FlagWithArg("-C ", srcDir.String()).
+ FlagWithRspFileInputList("-r ", outPath.ReplaceExtension(ctx, "rsp"), srcPaths)
+ rule.Restat()
+ rule.Build("zip src", "Create srcjar from prebuilt source")
+ p.stubsSrcJar = outPath
+ }
}
func (p *PrebuiltStubsSources) Prebuilt() *android.Prebuilt {
diff --git a/java/prebuilt_apis.go b/java/prebuilt_apis.go
index c33e6c2..c67e2bd 100644
--- a/java/prebuilt_apis.go
+++ b/java/prebuilt_apis.go
@@ -167,30 +167,24 @@
localPath := strings.TrimPrefix(f, mydir)
module, apiver, scope := parseJarPath(localPath)
createImport(mctx, module, scope, apiver, localPath, sdkVersion, compileDex)
+
+ if module == "core-for-system-modules" {
+ createSystemModules(mctx, apiver, scope)
+ }
}
}
-func createSystemModules(mctx android.LoadHookContext, apiver string) {
+func createSystemModules(mctx android.LoadHookContext, apiver string, scope string) {
props := struct {
Name *string
Libs []string
}{}
- props.Name = proptools.StringPtr(prebuiltApiModuleName(mctx, "system_modules", "public", apiver))
- props.Libs = append(props.Libs, prebuiltApiModuleName(mctx, "core-for-system-modules", "public", apiver))
+ props.Name = proptools.StringPtr(prebuiltApiModuleName(mctx, "system_modules", scope, apiver))
+ props.Libs = append(props.Libs, prebuiltApiModuleName(mctx, "core-for-system-modules", scope, apiver))
mctx.CreateModule(systemModulesImportFactory, &props)
}
-func prebuiltSdkSystemModules(mctx android.LoadHookContext, p *prebuiltApis) {
- for _, apiver := range p.properties.Api_dirs {
- jar := android.ExistentPathForSource(mctx,
- mctx.ModuleDir(), apiver, "public", "core-for-system-modules.jar")
- if jar.Valid() {
- createSystemModules(mctx, apiver)
- }
- }
-}
-
func prebuiltApiFiles(mctx android.LoadHookContext, p *prebuiltApis) {
mydir := mctx.ModuleDir() + "/"
// <apiver>/<scope>/api/<module>.txt
@@ -273,7 +267,6 @@
if p, ok := mctx.Module().(*prebuiltApis); ok {
prebuiltApiFiles(mctx, p)
prebuiltSdkStubs(mctx, p)
- prebuiltSdkSystemModules(mctx, p)
}
}
diff --git a/java/prebuilt_apis_test.go b/java/prebuilt_apis_test.go
new file mode 100644
index 0000000..79f4225
--- /dev/null
+++ b/java/prebuilt_apis_test.go
@@ -0,0 +1,56 @@
+// 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 java
+
+import (
+ "sort"
+ "strings"
+ "testing"
+
+ "android/soong/android"
+ "github.com/google/blueprint"
+)
+
+func TestPrebuiltApis_SystemModulesCreation(t *testing.T) {
+ result := android.GroupFixturePreparers(
+ prepareForJavaTest,
+ FixtureWithPrebuiltApis(map[string][]string{
+ "31": {},
+ "32": {},
+ "current": {},
+ }),
+ ).RunTest(t)
+
+ sdkSystemModules := []string{}
+ result.VisitAllModules(func(module blueprint.Module) {
+ name := android.RemoveOptionalPrebuiltPrefix(module.Name())
+ if strings.HasPrefix(name, "sdk_") && strings.HasSuffix(name, "_system_modules") {
+ sdkSystemModules = append(sdkSystemModules, name)
+ }
+ })
+ sort.Strings(sdkSystemModules)
+ expected := []string{
+ // 31 only has public system modules.
+ "sdk_public_31_system_modules",
+
+ // 32 and current both have public and module-lib system modules.
+ "sdk_public_32_system_modules",
+ "sdk_module-lib_32_system_modules",
+ "sdk_public_current_system_modules",
+ "sdk_module-lib_current_system_modules",
+ }
+ sort.Strings(expected)
+ android.AssertArrayString(t, "sdk system modules", expected, sdkSystemModules)
+}
diff --git a/java/proto.go b/java/proto.go
index 2fa22b6..ab913d8 100644
--- a/java/proto.go
+++ b/java/proto.go
@@ -102,6 +102,9 @@
if String(p.Proto.Plugin) == "" {
var typeToPlugin string
switch String(p.Proto.Type) {
+ case "stream":
+ flags.proto.OutTypeFlag = "--javastream_out"
+ typeToPlugin = "javastream"
case "micro":
flags.proto.OutTypeFlag = "--javamicro_out"
typeToPlugin = "javamicro"
diff --git a/java/robolectric.go b/java/robolectric.go
index a3603ad..16af546 100644
--- a/java/robolectric.go
+++ b/java/robolectric.go
@@ -212,13 +212,7 @@
installDeps = append(installDeps, installedData)
}
- installed := ctx.InstallFile(installPath, ctx.ModuleName()+".jar", r.combinedJar, installDeps...)
-
- if r.ExportedToMake() {
- // Soong handles installation here, but Make is usually what creates the phony rule that atest
- // uses to build the module. Create it here for now.
- ctx.Phony(ctx.ModuleName(), installed)
- }
+ r.installFile = ctx.InstallFile(installPath, ctx.ModuleName()+".jar", r.combinedJar, installDeps...)
}
func generateRoboTestConfig(ctx android.ModuleContext, outputFile android.WritablePath,
@@ -282,6 +276,10 @@
func (r *robolectricTest) AndroidMkEntries() []android.AndroidMkEntries {
entriesList := r.Library.AndroidMkEntries()
entries := &entriesList[0]
+ entries.ExtraEntries = append(entries.ExtraEntries,
+ func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
+ entries.SetBool("LOCAL_UNINSTALLABLE_MODULE", true)
+ })
entries.ExtraFooters = []android.AndroidMkExtraFootersFunc{
func(w io.Writer, name, prefix, moduleDir string) {
diff --git a/java/sdk.go b/java/sdk.go
index 80f2d6a..e6bf220 100644
--- a/java/sdk.go
+++ b/java/sdk.go
@@ -60,6 +60,30 @@
}
}
+// systemModuleKind returns the kind of system modules to use for the supplied combination of sdk
+// kind and API level.
+func systemModuleKind(sdkKind android.SdkKind, apiLevel android.ApiLevel) android.SdkKind {
+ systemModuleKind := sdkKind
+ if apiLevel.LessThanOrEqualTo(android.LastWithoutModuleLibCoreSystemModules) {
+ // API levels less than or equal to 31 did not provide a core-for-system-modules.jar
+ // specifically for the module-lib API. So, always use the public system modules for them.
+ systemModuleKind = android.SdkPublic
+ } else if systemModuleKind == android.SdkCore {
+ // Core is by definition what is included in the system module for the public API so should
+ // just use its system modules.
+ systemModuleKind = android.SdkPublic
+ } else if systemModuleKind == android.SdkSystem || systemModuleKind == android.SdkTest {
+ // The core system and test APIs are currently the same as the public API so they should use
+ // its system modules.
+ systemModuleKind = android.SdkPublic
+ } else if systemModuleKind == android.SdkSystemServer {
+ // The core system server API is the same as the core module-lib API.
+ systemModuleKind = android.SdkModule
+ }
+
+ return systemModuleKind
+}
+
func decodeSdkDep(ctx android.EarlyModuleContext, sdkContext android.SdkContext) sdkDep {
sdkVersion := sdkContext.SdkVersion(ctx)
if !sdkVersion.Valid() {
@@ -105,7 +129,8 @@
var systemModules string
if defaultJavaLanguageVersion(ctx, sdkVersion).usesJavaModules() {
- systemModules = "sdk_public_" + sdkVersion.ApiLevel.String() + "_system_modules"
+ systemModuleKind := systemModuleKind(sdkVersion.Kind, sdkVersion.ApiLevel)
+ systemModules = fmt.Sprintf("sdk_%s_%s_system_modules", systemModuleKind, sdkVersion.ApiLevel)
}
return sdkDep{
@@ -116,13 +141,15 @@
}
}
- toModule := func(modules []string, res string, aidl android.Path) sdkDep {
+ toModule := func(module string, aidl android.Path) sdkDep {
+ // Select the kind of system modules needed for the sdk version.
+ systemModulesKind := systemModuleKind(sdkVersion.Kind, android.FutureApiLevel)
return sdkDep{
useModule: true,
- bootclasspath: append(modules, config.DefaultLambdaStubsLibrary),
- systemModules: "core-current-stubs-system-modules",
- java9Classpath: modules,
- frameworkResModule: res,
+ bootclasspath: []string{module, config.DefaultLambdaStubsLibrary},
+ systemModules: fmt.Sprintf("core-%s-stubs-system-modules", systemModulesKind),
+ java9Classpath: []string{module},
+ frameworkResModule: "framework-res",
aidl: android.OptionalPathForPath(aidl),
}
}
@@ -161,38 +188,24 @@
noFrameworksLibs: true,
}
case android.SdkPublic:
- return toModule([]string{"android_stubs_current"}, "framework-res", sdkFrameworkAidlPath(ctx))
+ return toModule("android_stubs_current", sdkFrameworkAidlPath(ctx))
case android.SdkSystem:
- return toModule([]string{"android_system_stubs_current"}, "framework-res", sdkFrameworkAidlPath(ctx))
+ return toModule("android_system_stubs_current", sdkFrameworkAidlPath(ctx))
case android.SdkTest:
- return toModule([]string{"android_test_stubs_current"}, "framework-res", sdkFrameworkAidlPath(ctx))
+ return toModule("android_test_stubs_current", sdkFrameworkAidlPath(ctx))
case android.SdkCore:
return sdkDep{
useModule: true,
bootclasspath: []string{"core.current.stubs", config.DefaultLambdaStubsLibrary},
- systemModules: "core-current-stubs-system-modules",
+ systemModules: "core-public-stubs-system-modules",
noFrameworksLibs: true,
}
case android.SdkModule:
// TODO(146757305): provide .apk and .aidl that have more APIs for modules
- return sdkDep{
- useModule: true,
- bootclasspath: []string{"android_module_lib_stubs_current", config.DefaultLambdaStubsLibrary},
- systemModules: "core-module-lib-stubs-system-modules",
- java9Classpath: []string{"android_module_lib_stubs_current"},
- frameworkResModule: "framework-res",
- aidl: android.OptionalPathForPath(nonUpdatableFrameworkAidlPath(ctx)),
- }
+ return toModule("android_module_lib_stubs_current", nonUpdatableFrameworkAidlPath(ctx))
case android.SdkSystemServer:
// TODO(146757305): provide .apk and .aidl that have more APIs for modules
- return sdkDep{
- useModule: true,
- bootclasspath: []string{"android_system_server_stubs_current", config.DefaultLambdaStubsLibrary},
- systemModules: "core-module-lib-stubs-system-modules",
- java9Classpath: []string{"android_system_server_stubs_current"},
- frameworkResModule: "framework-res",
- aidl: android.OptionalPathForPath(sdkFrameworkAidlPath(ctx)),
- }
+ return toModule("android_system_server_stubs_current", sdkFrameworkAidlPath(ctx))
default:
panic(fmt.Errorf("invalid sdk %q", sdkVersion.Raw))
}
diff --git a/java/sdk_library.go b/java/sdk_library.go
index 273efec..d7f14d6 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -361,13 +361,14 @@
// The sdk_version to use for building the stubs.
//
// If not specified then it will use an sdk_version determined as follows:
+ //
// 1) If the sdk_version specified on the java_sdk_library is none then this
- // will be none. This is used for java_sdk_library instances that are used
- // to create stubs that contribute to the core_current sdk version.
- // 2) Otherwise, it is assumed that this library extends but does not contribute
- // directly to a specific sdk_version and so this uses the sdk_version appropriate
- // for the api scope. e.g. public will use sdk_version: current, system will use
- // sdk_version: system_current, etc.
+ // will be none. This is used for java_sdk_library instances that are used
+ // to create stubs that contribute to the core_current sdk version.
+ // 2) Otherwise, it is assumed that this library extends but does not
+ // contribute directly to a specific sdk_version and so this uses the
+ // sdk_version appropriate for the api scope. e.g. public will use
+ // sdk_version: current, system will use sdk_version: system_current, etc.
//
// This does not affect the sdk_version used for either generating the stubs source
// or the API file. They both have to use the same sdk_version as is used for
diff --git a/java/sdk_test.go b/java/sdk_test.go
index 6d62130..9e8ba6e 100644
--- a/java/sdk_test.go
+++ b/java/sdk_test.go
@@ -25,27 +25,36 @@
"android/soong/java/config"
)
+type classpathTestCase struct {
+ name string
+ unbundled bool
+ moduleType string
+ host android.OsClass
+ properties string
+
+ // for java 8
+ bootclasspath []string
+ java8classpath []string
+
+ // for java 9
+ system string
+ java9classpath []string
+
+ forces8 bool // if set, javac will always be called with java 8 arguments
+
+ aidl string
+
+ // Indicates how this test case is affected by the setting of Always_use_prebuilt_sdks.
+ //
+ // If this is nil then the test case is unaffected by the setting of Always_use_prebuilt_sdks.
+ // Otherwise, the test case can only be used when
+ // Always_use_prebuilt_sdks=*forAlwaysUsePrebuiltSdks.
+ forAlwaysUsePrebuiltSdks *bool
+}
+
func TestClasspath(t *testing.T) {
const frameworkAidl = "-I" + defaultJavaDir + "/framework/aidl"
- var classpathTestcases = []struct {
- name string
- unbundled bool
- moduleType string
- host android.OsClass
- properties string
-
- // for java 8
- bootclasspath []string
- java8classpath []string
-
- // for java 9
- system string
- java9classpath []string
-
- forces8 bool // if set, javac will always be called with java 8 arguments
-
- aidl string
- }{
+ var classpathTestcases = []classpathTestCase{
{
name: "default",
bootclasspath: config.StableCorePlatformBootclasspathLibraries,
@@ -91,25 +100,52 @@
aidl: "-pprebuilts/sdk/30/public/framework.aidl",
},
{
+ // Test case only applies when Always_use_prebuilt_sdks=false (the default).
+ forAlwaysUsePrebuiltSdks: proptools.BoolPtr(false),
name: "current",
properties: `sdk_version: "current",`,
bootclasspath: []string{"android_stubs_current", "core-lambda-stubs"},
- system: "core-current-stubs-system-modules",
+ system: "core-public-stubs-system-modules",
java9classpath: []string{"android_stubs_current"},
aidl: "-pout/soong/framework.aidl",
},
{
+ // Test case only applies when Always_use_prebuilt_sdks=true.
+ forAlwaysUsePrebuiltSdks: proptools.BoolPtr(true),
+
+ name: "current",
+ properties: `sdk_version: "current",`,
+ bootclasspath: []string{`""`},
+ system: "sdk_public_current_system_modules",
+ java8classpath: []string{"prebuilts/sdk/current/public/android.jar", "prebuilts/sdk/tools/core-lambda-stubs.jar"},
+ java9classpath: []string{"prebuilts/sdk/current/public/android.jar", "prebuilts/sdk/tools/core-lambda-stubs.jar"},
+ aidl: "-pprebuilts/sdk/current/public/framework.aidl",
+ },
+ {
+ // Test case only applies when Always_use_prebuilt_sdks=false (the default).
+ forAlwaysUsePrebuiltSdks: proptools.BoolPtr(false),
name: "system_current",
properties: `sdk_version: "system_current",`,
bootclasspath: []string{"android_system_stubs_current", "core-lambda-stubs"},
- system: "core-current-stubs-system-modules",
+ system: "core-public-stubs-system-modules",
java9classpath: []string{"android_system_stubs_current"},
aidl: "-pout/soong/framework.aidl",
},
{
+ // Test case only applies when Always_use_prebuilt_sdks=true.
+ forAlwaysUsePrebuiltSdks: proptools.BoolPtr(true),
+ name: "system_current",
+ properties: `sdk_version: "system_current",`,
+ bootclasspath: []string{`""`},
+ system: "sdk_public_current_system_modules",
+ java8classpath: []string{"prebuilts/sdk/current/system/android.jar", "prebuilts/sdk/tools/core-lambda-stubs.jar"},
+ java9classpath: []string{"prebuilts/sdk/current/system/android.jar", "prebuilts/sdk/tools/core-lambda-stubs.jar"},
+ aidl: "-pprebuilts/sdk/current/public/framework.aidl",
+ },
+ {
name: "system_29",
properties: `sdk_version: "system_29",`,
bootclasspath: []string{`""`},
@@ -118,7 +154,6 @@
aidl: "-pprebuilts/sdk/29/public/framework.aidl",
},
{
-
name: "system_30",
properties: `sdk_version: "system_30",`,
bootclasspath: []string{`""`},
@@ -128,20 +163,57 @@
aidl: "-pprebuilts/sdk/30/public/framework.aidl",
},
{
+ // Test case only applies when Always_use_prebuilt_sdks=false (the default).
+ forAlwaysUsePrebuiltSdks: proptools.BoolPtr(false),
name: "test_current",
properties: `sdk_version: "test_current",`,
bootclasspath: []string{"android_test_stubs_current", "core-lambda-stubs"},
- system: "core-current-stubs-system-modules",
+ system: "core-public-stubs-system-modules",
java9classpath: []string{"android_test_stubs_current"},
aidl: "-pout/soong/framework.aidl",
},
{
+ // Test case only applies when Always_use_prebuilt_sdks=true.
+ forAlwaysUsePrebuiltSdks: proptools.BoolPtr(true),
+
+ name: "test_current",
+ properties: `sdk_version: "test_current",`,
+ bootclasspath: []string{`""`},
+ system: "sdk_public_current_system_modules",
+ java8classpath: []string{"prebuilts/sdk/current/test/android.jar", "prebuilts/sdk/tools/core-lambda-stubs.jar"},
+ java9classpath: []string{"prebuilts/sdk/current/test/android.jar", "prebuilts/sdk/tools/core-lambda-stubs.jar"},
+ aidl: "-pprebuilts/sdk/current/public/framework.aidl",
+ },
+ {
+ name: "test_30",
+ properties: `sdk_version: "test_30",`,
+ bootclasspath: []string{`""`},
+ system: "sdk_public_30_system_modules",
+ java8classpath: []string{"prebuilts/sdk/30/test/android.jar", "prebuilts/sdk/tools/core-lambda-stubs.jar"},
+ java9classpath: []string{"prebuilts/sdk/30/test/android.jar", "prebuilts/sdk/tools/core-lambda-stubs.jar"},
+ aidl: "-pprebuilts/sdk/30/public/framework.aidl",
+ },
+ {
+ // Test case only applies when Always_use_prebuilt_sdks=false (the default).
+ forAlwaysUsePrebuiltSdks: proptools.BoolPtr(false),
name: "core_current",
properties: `sdk_version: "core_current",`,
bootclasspath: []string{"core.current.stubs", "core-lambda-stubs"},
- system: "core-current-stubs-system-modules",
+ system: "core-public-stubs-system-modules",
+ },
+ {
+ // Test case only applies when Always_use_prebuilt_sdks=true.
+ forAlwaysUsePrebuiltSdks: proptools.BoolPtr(true),
+
+ name: "core_current",
+ properties: `sdk_version: "core_current",`,
+ bootclasspath: []string{`""`},
+ system: "sdk_public_current_system_modules",
+ java8classpath: []string{"prebuilts/sdk/current/core/android.jar", "prebuilts/sdk/tools/core-lambda-stubs.jar"},
+ java9classpath: []string{"prebuilts/sdk/current/core/android.jar", "prebuilts/sdk/tools/core-lambda-stubs.jar"},
+ aidl: "-pprebuilts/sdk/current/public/framework.aidl",
},
{
@@ -214,8 +286,10 @@
java9classpath: []string{"prebuilts/sdk/current/public/android.jar", "prebuilts/sdk/tools/core-lambda-stubs.jar"},
aidl: "-pprebuilts/sdk/current/public/framework.aidl",
},
-
{
+ // Test case only applies when Always_use_prebuilt_sdks=false (the default).
+ forAlwaysUsePrebuiltSdks: proptools.BoolPtr(false),
+
name: "module_current",
properties: `sdk_version: "module_current",`,
bootclasspath: []string{"android_module_lib_stubs_current", "core-lambda-stubs"},
@@ -224,6 +298,48 @@
aidl: "-pout/soong/framework_non_updatable.aidl",
},
{
+ // Test case only applies when Always_use_prebuilt_sdks=true.
+ forAlwaysUsePrebuiltSdks: proptools.BoolPtr(true),
+
+ name: "module_current",
+ properties: `sdk_version: "module_current",`,
+ bootclasspath: []string{`""`},
+ system: "sdk_module-lib_current_system_modules",
+ java8classpath: []string{"prebuilts/sdk/current/module-lib/android.jar", "prebuilts/sdk/tools/core-lambda-stubs.jar"},
+ java9classpath: []string{"prebuilts/sdk/current/module-lib/android.jar", "prebuilts/sdk/tools/core-lambda-stubs.jar"},
+ aidl: "-pprebuilts/sdk/current/public/framework.aidl",
+ },
+ {
+ name: "module_30",
+ properties: `sdk_version: "module_30",`,
+ bootclasspath: []string{`""`},
+ system: "sdk_public_30_system_modules",
+ java8classpath: []string{"prebuilts/sdk/30/module-lib/android.jar", "prebuilts/sdk/tools/core-lambda-stubs.jar"},
+ java9classpath: []string{"prebuilts/sdk/30/module-lib/android.jar", "prebuilts/sdk/tools/core-lambda-stubs.jar"},
+ aidl: "-pprebuilts/sdk/30/public/framework.aidl",
+ },
+ {
+ name: "module_31",
+ properties: `sdk_version: "module_31",`,
+ bootclasspath: []string{`""`},
+ system: "sdk_public_31_system_modules",
+ java8classpath: []string{"prebuilts/sdk/31/module-lib/android.jar", "prebuilts/sdk/tools/core-lambda-stubs.jar"},
+ java9classpath: []string{"prebuilts/sdk/31/module-lib/android.jar", "prebuilts/sdk/tools/core-lambda-stubs.jar"},
+ aidl: "-pprebuilts/sdk/31/public/framework.aidl",
+ },
+ {
+ name: "module_32",
+ properties: `sdk_version: "module_32",`,
+ bootclasspath: []string{`""`},
+ system: "sdk_module-lib_32_system_modules",
+ java8classpath: []string{"prebuilts/sdk/32/module-lib/android.jar", "prebuilts/sdk/tools/core-lambda-stubs.jar"},
+ java9classpath: []string{"prebuilts/sdk/32/module-lib/android.jar", "prebuilts/sdk/tools/core-lambda-stubs.jar"},
+ aidl: "-pprebuilts/sdk/32/public/framework.aidl",
+ },
+ {
+ // Test case only applies when Always_use_prebuilt_sdks=false (the default).
+ forAlwaysUsePrebuiltSdks: proptools.BoolPtr(false),
+
name: "system_server_current",
properties: `sdk_version: "system_server_current",`,
bootclasspath: []string{"android_system_server_stubs_current", "core-lambda-stubs"},
@@ -231,9 +347,62 @@
java9classpath: []string{"android_system_server_stubs_current"},
aidl: "-pout/soong/framework.aidl",
},
+ {
+ // Test case only applies when Always_use_prebuilt_sdks=true.
+ forAlwaysUsePrebuiltSdks: proptools.BoolPtr(true),
+
+ name: "system_server_current",
+ properties: `sdk_version: "system_server_current",`,
+ bootclasspath: []string{`""`},
+ system: "sdk_module-lib_current_system_modules",
+ java8classpath: []string{"prebuilts/sdk/current/system-server/android.jar", "prebuilts/sdk/tools/core-lambda-stubs.jar"},
+ java9classpath: []string{"prebuilts/sdk/current/system-server/android.jar", "prebuilts/sdk/tools/core-lambda-stubs.jar"},
+ aidl: "-pprebuilts/sdk/current/public/framework.aidl",
+ },
+ {
+ name: "system_server_30",
+ properties: `sdk_version: "system_server_30",`,
+ bootclasspath: []string{`""`},
+ system: "sdk_public_30_system_modules",
+ java8classpath: []string{"prebuilts/sdk/30/system-server/android.jar", "prebuilts/sdk/tools/core-lambda-stubs.jar"},
+ java9classpath: []string{"prebuilts/sdk/30/system-server/android.jar", "prebuilts/sdk/tools/core-lambda-stubs.jar"},
+ aidl: "-pprebuilts/sdk/30/public/framework.aidl",
+ },
+ {
+ name: "system_server_31",
+ properties: `sdk_version: "system_server_31",`,
+ bootclasspath: []string{`""`},
+ system: "sdk_public_31_system_modules",
+ java8classpath: []string{"prebuilts/sdk/31/system-server/android.jar", "prebuilts/sdk/tools/core-lambda-stubs.jar"},
+ java9classpath: []string{"prebuilts/sdk/31/system-server/android.jar", "prebuilts/sdk/tools/core-lambda-stubs.jar"},
+ aidl: "-pprebuilts/sdk/31/public/framework.aidl",
+ },
+ {
+ name: "system_server_32",
+ properties: `sdk_version: "system_server_32",`,
+ bootclasspath: []string{`""`},
+ system: "sdk_module-lib_32_system_modules",
+ java8classpath: []string{"prebuilts/sdk/32/system-server/android.jar", "prebuilts/sdk/tools/core-lambda-stubs.jar"},
+ java9classpath: []string{"prebuilts/sdk/32/system-server/android.jar", "prebuilts/sdk/tools/core-lambda-stubs.jar"},
+ aidl: "-pprebuilts/sdk/32/public/framework.aidl",
+ },
}
+ t.Run("basic", func(t *testing.T) {
+ testClasspathTestCases(t, classpathTestcases, false)
+ })
+
+ t.Run("Always_use_prebuilt_sdks=true", func(t *testing.T) {
+ testClasspathTestCases(t, classpathTestcases, true)
+ })
+}
+
+func testClasspathTestCases(t *testing.T, classpathTestcases []classpathTestCase, alwaysUsePrebuiltSdks bool) {
for _, testcase := range classpathTestcases {
+ if testcase.forAlwaysUsePrebuiltSdks != nil && *testcase.forAlwaysUsePrebuiltSdks != alwaysUsePrebuiltSdks {
+ continue
+ }
+
t.Run(testcase.name, func(t *testing.T) {
moduleType := "java_library"
if testcase.moduleType != "" {
@@ -299,7 +468,9 @@
system = "--system=none"
} else if testcase.system != "" {
dir := ""
- if strings.HasPrefix(testcase.system, "sdk_public_") {
+ // If the system modules name starts with sdk_ then it is a prebuilt module and so comes
+ // from the prebuilt directory.
+ if strings.HasPrefix(testcase.system, "sdk_") {
dir = "prebuilts/sdk"
} else {
dir = defaultJavaDir
@@ -351,11 +522,20 @@
android.AssertPathsRelativeToTopEquals(t, "implicits", deps, javac.Implicits)
}
+ preparer := android.NullFixturePreparer
+ if alwaysUsePrebuiltSdks {
+ preparer = android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ variables.Always_use_prebuilt_sdks = proptools.BoolPtr(true)
+ })
+ }
+
fixtureFactory := android.GroupFixturePreparers(
prepareForJavaTest,
FixtureWithPrebuiltApis(map[string][]string{
"29": {},
"30": {},
+ "31": {},
+ "32": {},
"current": {},
}),
android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
@@ -369,6 +549,7 @@
env["ANDROID_JAVA8_HOME"] = "jdk8"
}
}),
+ preparer,
)
// Test with legacy javac -source 1.8 -target 1.8
diff --git a/java/systemserver_classpath_fragment.go b/java/systemserver_classpath_fragment.go
index f209f4a..d75635c 100644
--- a/java/systemserver_classpath_fragment.go
+++ b/java/systemserver_classpath_fragment.go
@@ -120,9 +120,19 @@
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)
+ // This module only exists in car products.
+ // So ignore it even if it is not in PRODUCT_APEX_SYSTEM_SERVER_JARS.
+ // TODO(b/203233647): Add better mechanism to make it optional.
+ _, unknown = android.RemoveFromList("car-frameworks-service-module", unknown)
- // For non test apexes, make sure that all contents are actually declared in make.
- if global.ApexSystemServerJars.Len() > 0 && len(unknown) > 0 && !android.IsModuleInVersionedSdk(ctx.Module()) {
+ // 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 ApexSystemServerJars. Instead,
+ // we should check if we are creating a config for apex_test via ApexInfo and amend the values.
+ // This is an exception to support end-to-end test for ApexdUnitTests, until such support exists.
+ if android.InList("test_service-apexd", possibleUpdatableModules) {
+ jars = jars.Append("com.android.apex.test_package", "test_service-apexd")
+ } else if global.ApexSystemServerJars.Len() > 0 && len(unknown) > 0 && !android.IsModuleInVersionedSdk(ctx.Module()) {
+ // For non test apexes, make sure that all contents are actually declared in make.
ctx.ModuleErrorf("%s in contents must also be declared in PRODUCT_APEX_SYSTEM_SERVER_JARS", unknown)
}
diff --git a/java/testing.go b/java/testing.go
index 99d55a0..7441e44 100644
--- a/java/testing.go
+++ b/java/testing.go
@@ -159,8 +159,7 @@
`, strings.Join(android.SortedStringKeys(release2Modules), `", "`))
for release, modules := range release2Modules {
- libs := append([]string{"android", "core-for-system-modules"}, modules...)
- mockFS.Merge(prebuiltApisFilesForLibs([]string{release}, libs))
+ mockFS.Merge(prebuiltApisFilesForModules([]string{release}, modules))
}
return android.GroupFixturePreparers(
android.FixtureAddTextFile(path, bp),
@@ -168,19 +167,32 @@
)
}
-func prebuiltApisFilesForLibs(apiLevels []string, sdkLibs []string) map[string][]byte {
+func prebuiltApisFilesForModules(apiLevels []string, modules []string) map[string][]byte {
+ libs := append([]string{"android"}, modules...)
+
fs := make(map[string][]byte)
for _, level := range apiLevels {
- for _, lib := range sdkLibs {
- for _, scope := range []string{"public", "system", "module-lib", "system-server", "test"} {
- fs[fmt.Sprintf("prebuilts/sdk/%s/%s/%s.jar", level, scope, lib)] = nil
+ apiLevel := android.ApiLevelForTest(level)
+ for _, sdkKind := range []android.SdkKind{android.SdkPublic, android.SdkSystem, android.SdkModule, android.SdkSystemServer, android.SdkTest} {
+ // A core-for-system-modules file must only be created for the sdk kind that supports it.
+ if sdkKind == systemModuleKind(sdkKind, apiLevel) {
+ fs[fmt.Sprintf("prebuilts/sdk/%s/%s/core-for-system-modules.jar", level, sdkKind)] = nil
+ }
+
+ for _, lib := range libs {
+ // Create a jar file for every library.
+ fs[fmt.Sprintf("prebuilts/sdk/%s/%s/%s.jar", level, sdkKind, lib)] = nil
+
// No finalized API files for "current"
if level != "current" {
- fs[fmt.Sprintf("prebuilts/sdk/%s/%s/api/%s.txt", level, scope, lib)] = nil
- fs[fmt.Sprintf("prebuilts/sdk/%s/%s/api/%s-removed.txt", level, scope, lib)] = nil
+ fs[fmt.Sprintf("prebuilts/sdk/%s/%s/api/%s.txt", level, sdkKind, lib)] = nil
+ fs[fmt.Sprintf("prebuilts/sdk/%s/%s/api/%s-removed.txt", level, sdkKind, lib)] = nil
}
}
}
+ if level == "current" {
+ fs["prebuilts/sdk/current/core/android.jar"] = nil
+ }
fs[fmt.Sprintf("prebuilts/sdk/%s/public/framework.aidl", level)] = nil
}
return fs
@@ -332,7 +344,7 @@
}`
systemModules := []string{
- "core-current-stubs-system-modules",
+ "core-public-stubs-system-modules",
"core-module-lib-stubs-system-modules",
"legacy-core-platform-api-stubs-system-modules",
"stable-core-platform-api-stubs-system-modules",
diff --git a/mk2rbc/cmd/mk2rbc.go b/mk2rbc/cmd/mk2rbc.go
index d8e7018..b089f91 100644
--- a/mk2rbc/cmd/mk2rbc.go
+++ b/mk2rbc/cmd/mk2rbc.go
@@ -60,7 +60,7 @@
)
func init() {
- // Poor man's flag aliasing: works, but the usage string is ugly and
+ // Simplistic flag aliasing: works, but the usage string is ugly and
// both flag and its alias can be present on the command line
flagAlias := func(target string, alias string) {
if f := flag.Lookup(target); f != nil {
diff --git a/mk2rbc/mk2rbc.go b/mk2rbc/mk2rbc.go
index b377fd8..6227164 100644
--- a/mk2rbc/mk2rbc.go
+++ b/mk2rbc/mk2rbc.go
@@ -40,12 +40,15 @@
)
const (
- baseUri = "//build/make/core:product_config.rbc"
+ annotationCommentPrefix = "RBC#"
+ baseUri = "//build/make/core:product_config.rbc"
// The name of the struct exported by the product_config.rbc
// that contains the functions and variables available to
// product configuration Starlark files.
baseName = "rblf"
+ soongNsPrefix = "SOONG_CONFIG_"
+
// And here are the functions and variables:
cfnGetCfg = baseName + ".cfg"
cfnMain = baseName + ".product_configuration"
@@ -60,10 +63,14 @@
const (
// Phony makefile functions, they are eventually rewritten
// according to knownFunctions map
- addSoongNamespace = "add_soong_config_namespace"
- addSoongConfigVarValue = "add_soong_config_var_value"
- fileExistsPhony = "$file_exists"
- wildcardExistsPhony = "$wildcard_exists"
+ fileExistsPhony = "$file_exists"
+ // The following two macros are obsolete, and will we deleted once
+ // there are deleted from the makefiles:
+ soongConfigNamespaceOld = "add_soong_config_namespace"
+ soongConfigVarSetOld = "add_soong_config_var_value"
+ soongConfigAppend = "soong_config_append"
+ soongConfigAssign = "soong_config_set"
+ wildcardExistsPhony = "$wildcard_exists"
)
const (
@@ -82,8 +89,10 @@
"abspath": {baseName + ".abspath", starlarkTypeString, hiddenArgNone},
fileExistsPhony: {baseName + ".file_exists", starlarkTypeBool, hiddenArgNone},
wildcardExistsPhony: {baseName + ".file_wildcard_exists", starlarkTypeBool, hiddenArgNone},
- addSoongNamespace: {baseName + ".add_soong_config_namespace", starlarkTypeVoid, hiddenArgGlobal},
- addSoongConfigVarValue: {baseName + ".add_soong_config_var_value", starlarkTypeVoid, hiddenArgGlobal},
+ soongConfigNamespaceOld: {baseName + ".soong_config_namespace", starlarkTypeVoid, hiddenArgGlobal},
+ soongConfigVarSetOld: {baseName + ".soong_config_set", starlarkTypeVoid, hiddenArgGlobal},
+ soongConfigAssign: {baseName + ".soong_config_set", starlarkTypeVoid, hiddenArgGlobal},
+ soongConfigAppend: {baseName + ".soong_config_append", starlarkTypeVoid, hiddenArgGlobal},
"add-to-product-copy-files-if-exists": {baseName + ".copy_if_exists", starlarkTypeList, hiddenArgNone},
"addprefix": {baseName + ".addprefix", starlarkTypeList, hiddenArgNone},
"addsuffix": {baseName + ".addsuffix", starlarkTypeList, hiddenArgNone},
@@ -102,13 +111,16 @@
"is-android-codename": {"!is-android-codename", starlarkTypeBool, hiddenArgNone}, // unused by product config
"is-android-codename-in-list": {"!is-android-codename-in-list", starlarkTypeBool, hiddenArgNone}, // unused by product config
"is-board-platform": {"!is-board-platform", starlarkTypeBool, hiddenArgNone},
+ "is-board-platform2": {baseName + ".board_platform_is", starlarkTypeBool, hiddenArgGlobal},
"is-board-platform-in-list": {"!is-board-platform-in-list", starlarkTypeBool, hiddenArgNone},
+ "is-board-platform-in-list2": {baseName + ".board_platform_in", starlarkTypeBool, hiddenArgGlobal},
"is-chipset-in-board-platform": {"!is-chipset-in-board-platform", starlarkTypeUnknown, hiddenArgNone}, // unused by product config
"is-chipset-prefix-in-board-platform": {"!is-chipset-prefix-in-board-platform", starlarkTypeBool, hiddenArgNone}, // unused by product config
"is-not-board-platform": {"!is-not-board-platform", starlarkTypeBool, hiddenArgNone}, // defined but never used
"is-platform-sdk-version-at-least": {"!is-platform-sdk-version-at-least", starlarkTypeBool, hiddenArgNone}, // unused by product config
"is-product-in-list": {"!is-product-in-list", starlarkTypeBool, hiddenArgNone},
"is-vendor-board-platform": {"!is-vendor-board-platform", starlarkTypeBool, hiddenArgNone},
+ "is-vendor-board-qcom": {"!is-vendor-board-qcom", starlarkTypeBool, hiddenArgNone},
callLoadAlways: {"!inherit-product", starlarkTypeVoid, hiddenArgNone},
callLoadIf: {"!inherit-product-if-exists", starlarkTypeVoid, hiddenArgNone},
"lastword": {"!lastword", starlarkTypeString, hiddenArgNone},
@@ -399,6 +411,7 @@
outputDir string
dependentModules map[string]*moduleInfo
soongNamespaces map[string]map[string]bool
+ includeTops []string
}
func newParseContext(ss *StarlarkScript, nodes []mkparser.Node) *parseContext {
@@ -444,6 +457,7 @@
variables: make(map[string]variable),
dependentModules: make(map[string]*moduleInfo),
soongNamespaces: make(map[string]map[string]bool),
+ includeTops: []string{"vendor/google-devices"},
}
ctx.pushVarAssignments()
for _, item := range predefined {
@@ -522,7 +536,6 @@
return
}
name := a.Name.Strings[0]
- const soongNsPrefix = "SOONG_CONFIG_"
// Soong confuguration
if strings.HasPrefix(name, soongNsPrefix) {
ctx.handleSoongNsAssignment(strings.TrimPrefix(name, soongNsPrefix), a)
@@ -615,7 +628,7 @@
for _, ns := range strings.Fields(s) {
ctx.addSoongNamespace(ns)
ctx.receiver.newNode(&exprNode{&callExpr{
- name: addSoongNamespace,
+ name: soongConfigNamespaceOld,
args: []starlarkExpr{&stringLiteralExpr{ns}},
returnType: starlarkTypeVoid,
}})
@@ -665,8 +678,12 @@
ctx.errorf(asgn, "no %s variable in %s namespace, please use add_soong_config_var_value instead", varName, namespaceName)
return
}
+ fname := soongConfigVarSetOld
+ if asgn.Type == "+=" {
+ fname = soongConfigAppend
+ }
ctx.receiver.newNode(&exprNode{&callExpr{
- name: addSoongConfigVarValue,
+ name: fname,
args: []starlarkExpr{&stringLiteralExpr{namespaceName}, &stringLiteralExpr{varName}, val},
returnType: starlarkTypeVoid,
}})
@@ -799,21 +816,15 @@
pathPattern = append(pathPattern, chunk)
}
}
- if pathPattern[0] != "" {
- matchingPaths = ctx.findMatchingPaths(pathPattern)
- } else {
- // Heuristics -- if pattern starts from top, restrict it to the directories where
- // we know inherit-product uses dynamically calculated path. Restrict it even further
- // for certain path which would yield too many useless matches
- if len(varPath.chunks) == 2 && varPath.chunks[1] == "/BoardConfigVendor.mk" {
- pathPattern[0] = "vendor/google_devices"
- matchingPaths = ctx.findMatchingPaths(pathPattern)
- } else {
- for _, t := range []string{"vendor/qcom", "vendor/google_devices"} {
- pathPattern[0] = t
- matchingPaths = append(matchingPaths, ctx.findMatchingPaths(pathPattern)...)
- }
+ if pathPattern[0] == "" {
+ // If pattern starts from the top. restrict it to the directories where
+ // we know inherit-product uses dynamically calculated path.
+ for _, p := range ctx.includeTops {
+ pathPattern[0] = p
+ matchingPaths = append(matchingPaths, ctx.findMatchingPaths(pathPattern)...)
}
+ } else {
+ matchingPaths = ctx.findMatchingPaths(pathPattern)
}
// Safeguard against $(call inherit-product,$(PRODUCT_PATH))
const maxMatchingFiles = 150
@@ -1133,6 +1144,34 @@
list: &variableRefExpr{ctx.addVariable(s + "_BOARD_PLATFORMS"), true},
isNot: negate,
}, true
+
+ case "is-board-platform2", "is-board-platform-in-list2":
+ if s, ok := maybeString(xValue); !ok || s != "" {
+ return ctx.newBadExpr(directive,
+ fmt.Sprintf("the result of %s can be compared only to empty", x.name)), true
+ }
+ if len(x.args) != 1 {
+ return ctx.newBadExpr(directive, "%s requires an argument", x.name), true
+ }
+ cc := &callExpr{
+ name: x.name,
+ args: []starlarkExpr{x.args[0]},
+ returnType: starlarkTypeBool,
+ }
+ if !negate {
+ return ¬Expr{cc}, true
+ }
+ return cc, true
+ case "is-vendor-board-qcom":
+ if s, ok := maybeString(xValue); !ok || s != "" {
+ return ctx.newBadExpr(directive,
+ fmt.Sprintf("the result of %s can be compared only to empty", x.name)), true
+ }
+ return &inExpr{
+ expr: &variableRefExpr{ctx.addVariable("TARGET_BOARD_PLATFORM"), false},
+ list: &variableRefExpr{ctx.addVariable("QCOM_BOARD_PLATFORMS"), true},
+ isNot: negate,
+ }, true
default:
return ctx.newBadExpr(directive, "Unknown function in ifeq: %s", x.name), true
}
@@ -1277,6 +1316,10 @@
returnType: starlarkTypeUnknown,
}
}
+ if strings.HasPrefix(refDump, soongNsPrefix) {
+ // TODO (asmundak): if we find many, maybe handle them.
+ return ctx.newBadExpr(node, "SOONG_CONFIG_ variables cannot be referenced: %s", refDump)
+ }
if v := ctx.addVariable(refDump); v != nil {
return &variableRefExpr{v, ctx.lastAssignment(v.name()) != nil}
}
@@ -1438,6 +1481,7 @@
handled := true
switch x := node.(type) {
case *mkparser.Comment:
+ ctx.maybeHandleAnnotation(x)
ctx.insertComment("#" + x.Comment)
case *mkparser.Assignment:
ctx.handleAssignment(x)
@@ -1453,11 +1497,33 @@
handled = false
}
default:
- ctx.errorf(x, "unsupported line %s", x.Dump())
+ ctx.errorf(x, "unsupported line %s", strings.ReplaceAll(x.Dump(), "\n", "\n#"))
}
return handled
}
+// Processes annotation. An annotation is a comment that starts with #RBC# and provides
+// a conversion hint -- say, where to look for the dynamically calculated inherit/include
+// paths.
+func (ctx *parseContext) maybeHandleAnnotation(cnode *mkparser.Comment) {
+ maybeTrim := func(s, prefix string) (string, bool) {
+ if strings.HasPrefix(s, prefix) {
+ return strings.TrimSpace(strings.TrimPrefix(s, prefix)), true
+ }
+ return s, false
+ }
+ annotation, ok := maybeTrim(cnode.Comment, annotationCommentPrefix)
+ if !ok {
+ return
+ }
+ if p, ok := maybeTrim(annotation, "include_top"); ok {
+ ctx.includeTops = append(ctx.includeTops, p)
+ return
+ }
+ ctx.errorf(cnode, "unsupported annotation %s", cnode.Comment)
+
+}
+
func (ctx *parseContext) insertComment(s string) {
ctx.receiver.newNode(&commentNode{strings.TrimSpace(s)})
}
diff --git a/mk2rbc/mk2rbc_test.go b/mk2rbc/mk2rbc_test.go
index fe1fa08..511bb0f 100644
--- a/mk2rbc/mk2rbc_test.go
+++ b/mk2rbc/mk2rbc_test.go
@@ -563,6 +563,27 @@
`,
},
{
+ desc: "new is-board calls",
+ mkname: "product.mk",
+ in: `
+ifneq (,$(call is-board-platform-in-list2,msm8998 $(X))
+else ifeq (,$(call is-board-platform2,copper)
+else ifneq (,$(call is-vendor-board-qcom))
+endif
+`,
+ expected: `load("//build/make/core:product_config.rbc", "rblf")
+
+def init(g, handle):
+ cfg = rblf.cfg(handle)
+ if rblf.board_platform_in(g, "msm8998 %s" % g.get("X", "")):
+ pass
+ elif not rblf.board_platform_is(g, "copper"):
+ pass
+ elif g.get("TARGET_BOARD_PLATFORM", "") not in g["QCOM_BOARD_PLATFORMS"]:
+ pass
+`,
+ },
+ {
desc: "findstring call",
mkname: "product.mk",
in: `
@@ -681,6 +702,8 @@
$(info $(notdir foo/bar))
$(call add_soong_config_namespace,snsconfig)
$(call add_soong_config_var_value,snsconfig,imagetype,odm_image)
+$(call soong_config_set, snsconfig, foo, foo_value)
+$(call soong_config_append, snsconfig, bar, bar_value)
PRODUCT_COPY_FILES := $(call copy-files,$(wildcard foo*.mk),etc)
PRODUCT_COPY_FILES := $(call product-copy-files-by-pattern,from/%,to/%,a b c)
`,
@@ -700,8 +723,10 @@
rblf.mkinfo("product.mk", rblf.dir((_foobar).split()[-1]))
rblf.mkinfo("product.mk", rblf.abspath("foo/bar"))
rblf.mkinfo("product.mk", rblf.notdir("foo/bar"))
- rblf.add_soong_config_namespace(g, "snsconfig")
- rblf.add_soong_config_var_value(g, "snsconfig", "imagetype", "odm_image")
+ rblf.soong_config_namespace(g, "snsconfig")
+ rblf.soong_config_set(g, "snsconfig", "imagetype", "odm_image")
+ rblf.soong_config_set(g, "snsconfig", "foo", "foo_value")
+ rblf.soong_config_append(g, "snsconfig", "bar", "bar_value")
cfg["PRODUCT_COPY_FILES"] = rblf.copy_files(rblf.expand_wildcard("foo*.mk"), "etc")
cfg["PRODUCT_COPY_FILES"] = rblf.product_copy_files_by_pattern("from/%", "to/%", "a b c")
`,
@@ -784,17 +809,21 @@
in: `
SOONG_CONFIG_NAMESPACES += cvd
SOONG_CONFIG_cvd += launch_configs
-SOONG_CONFIG_cvd_launch_configs += cvd_config_auto.json
+SOONG_CONFIG_cvd_launch_configs = cvd_config_auto.json
SOONG_CONFIG_cvd += grub_config
SOONG_CONFIG_cvd_grub_config += grub.cfg
+x := $(SOONG_CONFIG_cvd_grub_config)
`,
expected: `load("//build/make/core:product_config.rbc", "rblf")
def init(g, handle):
cfg = rblf.cfg(handle)
- rblf.add_soong_config_namespace(g, "cvd")
- rblf.add_soong_config_var_value(g, "cvd", "launch_configs", "cvd_config_auto.json")
- rblf.add_soong_config_var_value(g, "cvd", "grub_config", "grub.cfg")
+ rblf.soong_config_namespace(g, "cvd")
+ rblf.soong_config_set(g, "cvd", "launch_configs", "cvd_config_auto.json")
+ rblf.soong_config_append(g, "cvd", "grub_config", "grub.cfg")
+ # MK2RBC TRANSLATION ERROR: SOONG_CONFIG_ variables cannot be referenced: SOONG_CONFIG_cvd_grub_config
+ # x := $(SOONG_CONFIG_cvd_grub_config)
+ rblf.warning("product.mk", "partially successful conversion")
`,
},
{
@@ -911,7 +940,7 @@
desc: "Dynamic inherit path",
mkname: "product.mk",
in: `
-MY_PATH=foo
+MY_PATH:=foo
$(call inherit-product,vendor/$(MY_PATH)/cfg.mk)
`,
expected: `load("//build/make/core:product_config.rbc", "rblf")
@@ -931,6 +960,47 @@
rblf.inherit(handle, _varmod, _varmod_init)
`,
},
+ {
+ desc: "Dynamic inherit with hint",
+ mkname: "product.mk",
+ in: `
+MY_PATH:=foo
+#RBC# include_top vendor/foo1
+$(call inherit-product,$(MY_PATH)/cfg.mk)
+`,
+ expected: `load("//build/make/core:product_config.rbc", "rblf")
+load("//vendor/foo1:cfg.star|init", _cfg_init = "init")
+
+def init(g, handle):
+ cfg = rblf.cfg(handle)
+ g["MY_PATH"] = "foo"
+ #RBC# include_top vendor/foo1
+ _entry = {
+ "vendor/foo1/cfg.mk": ("_cfg", _cfg_init),
+ }.get("%s/cfg.mk" % g["MY_PATH"])
+ (_varmod, _varmod_init) = _entry if _entry else (None, None)
+ if not _varmod_init:
+ rblf.mkerror("cannot")
+ rblf.inherit(handle, _varmod, _varmod_init)
+`,
+ },
+ {
+ desc: "Ignore make rules",
+ mkname: "product.mk",
+ in: `
+foo: foo.c
+ gcc -o $@ $*`,
+ expected: `# MK2RBC TRANSLATION ERROR: unsupported line rule: foo: foo.c
+#gcc -o $@ $*
+# rule: foo: foo.c
+# gcc -o $@ $*
+load("//build/make/core:product_config.rbc", "rblf")
+
+def init(g, handle):
+ cfg = rblf.cfg(handle)
+ rblf.warning("product.mk", "partially successful conversion")
+`,
+ },
}
var known_variables = []struct {
diff --git a/mk2rbc/types.go b/mk2rbc/types.go
index ebd52d8..46c6aa9 100644
--- a/mk2rbc/types.go
+++ b/mk2rbc/types.go
@@ -53,7 +53,7 @@
NewVariable(name string, varClass varClass, valueType starlarkType)
}
-// ScopeBase is a dummy implementation of the mkparser.Scope.
+// ScopeBase is a placeholder implementation of the mkparser.Scope.
// All our scopes are read-only and resolve only simple variables.
type ScopeBase struct{}
diff --git a/rust/binary.go b/rust/binary.go
index 2c3f548..7c18730 100644
--- a/rust/binary.go
+++ b/rust/binary.go
@@ -31,6 +31,11 @@
Static_executable *bool `android:"arch_variant"`
}
+type binaryInterface interface {
+ binary() bool
+ staticallyLinked() bool
+}
+
type binaryDecorator struct {
*baseCompiler
stripper Stripper
@@ -155,3 +160,11 @@
}
return binary.baseCompiler.stdLinkage(ctx)
}
+
+func (binary *binaryDecorator) binary() bool {
+ return true
+}
+
+func (binary *binaryDecorator) staticallyLinked() bool {
+ return Bool(binary.Properties.Static_executable)
+}
diff --git a/rust/config/Android.bp b/rust/config/Android.bp
index 5b121c3..7757c79 100644
--- a/rust/config/Android.bp
+++ b/rust/config/Android.bp
@@ -16,7 +16,7 @@
"lints.go",
"toolchain.go",
"allowed_list.go",
- "x86_darwin_host.go",
+ "darwin_host.go",
"x86_linux_bionic_host.go",
"x86_linux_host.go",
"x86_device.go",
diff --git a/rust/config/x86_darwin_host.go b/rust/config/darwin_host.go
similarity index 67%
rename from rust/config/x86_darwin_host.go
rename to rust/config/darwin_host.go
index 8ff0dd4..03bea82 100644
--- a/rust/config/x86_darwin_host.go
+++ b/rust/config/darwin_host.go
@@ -25,41 +25,64 @@
DarwinRustLinkFlags = []string{
"-B${cc_config.MacToolPath}",
}
+ darwinArm64Rustflags = []string{}
+ darwinArm64Linkflags = []string{}
darwinX8664Rustflags = []string{}
darwinX8664Linkflags = []string{}
)
func init() {
+ registerToolchainFactory(android.Darwin, android.Arm64, darwinArm64ToolchainFactory)
registerToolchainFactory(android.Darwin, android.X86_64, darwinX8664ToolchainFactory)
+
pctx.StaticVariable("DarwinToolchainRustFlags", strings.Join(DarwinRustFlags, " "))
pctx.StaticVariable("DarwinToolchainLinkFlags", strings.Join(DarwinRustLinkFlags, " "))
+
+ pctx.StaticVariable("DarwinToolchainArm64RustFlags", strings.Join(darwinArm64Rustflags, " "))
+ pctx.StaticVariable("DarwinToolchainArm64LinkFlags", strings.Join(darwinArm64Linkflags, " "))
pctx.StaticVariable("DarwinToolchainX8664RustFlags", strings.Join(darwinX8664Rustflags, " "))
pctx.StaticVariable("DarwinToolchainX8664LinkFlags", strings.Join(darwinX8664Linkflags, " "))
}
type toolchainDarwin struct {
+ toolchain64Bit
toolchainRustFlags string
toolchainLinkFlags string
}
-type toolchainDarwinX8664 struct {
- toolchain64Bit
+type toolchainDarwinArm64 struct {
toolchainDarwin
}
+type toolchainDarwinX8664 struct {
+ toolchainDarwin
+}
+
+func (toolchainDarwinArm64) Supported() bool {
+ return true
+}
+
func (toolchainDarwinX8664) Supported() bool {
return true
}
-func (toolchainDarwinX8664) Bionic() bool {
+func (toolchainDarwin) Bionic() bool {
return false
}
+func (t *toolchainDarwinArm64) Name() string {
+ return "arm64"
+}
+
func (t *toolchainDarwinX8664) Name() string {
return "x86_64"
}
+func (t *toolchainDarwinArm64) RustTriple() string {
+ return "aarch64-apple-darwin"
+}
+
func (t *toolchainDarwinX8664) RustTriple() string {
return "x86_64-apple-darwin"
}
@@ -76,6 +99,15 @@
return ".dylib"
}
+func (t *toolchainDarwinArm64) ToolchainLinkFlags() string {
+ // Prepend the lld flags from cc_config so we stay in sync with cc
+ return "${cc_config.DarwinLldflags} ${config.DarwinToolchainLinkFlags} ${config.DarwinToolchainArm64LinkFlags}"
+}
+
+func (t *toolchainDarwinArm64) ToolchainRustFlags() string {
+ return "${config.DarwinToolchainRustFlags} ${config.DarwinToolchainArm64RustFlags}"
+}
+
func (t *toolchainDarwinX8664) ToolchainLinkFlags() string {
// Prepend the lld flags from cc_config so we stay in sync with cc
return "${cc_config.DarwinLldflags} ${config.DarwinToolchainLinkFlags} ${config.DarwinToolchainX8664LinkFlags}"
@@ -85,8 +117,13 @@
return "${config.DarwinToolchainRustFlags} ${config.DarwinToolchainX8664RustFlags}"
}
+func darwinArm64ToolchainFactory(arch android.Arch) Toolchain {
+ return toolchainDarwinArm64Singleton
+}
+
func darwinX8664ToolchainFactory(arch android.Arch) Toolchain {
return toolchainDarwinX8664Singleton
}
+var toolchainDarwinArm64Singleton Toolchain = &toolchainDarwinArm64{}
var toolchainDarwinX8664Singleton Toolchain = &toolchainDarwinX8664{}
diff --git a/rust/rust.go b/rust/rust.go
index 13169f1..c465cb6 100644
--- a/rust/rust.go
+++ b/rust/rust.go
@@ -261,10 +261,8 @@
}
func (mod *Module) Binary() bool {
- if mod.compiler != nil {
- if _, ok := mod.compiler.(*binaryDecorator); ok {
- return true
- }
+ if binary, ok := mod.compiler.(binaryInterface); ok {
+ return binary.binary()
}
return false
}
@@ -273,7 +271,7 @@
if !mod.Binary() {
return false
}
- return Bool(mod.compiler.(*binaryDecorator).Properties.Static_executable)
+ return mod.StaticallyLinked()
}
func (mod *Module) Object() bool {
@@ -1123,7 +1121,12 @@
if cc.IsWholeStaticLib(depTag) {
// rustc will bundle static libraries when they're passed with "-lstatic=<lib>". This will fail
// if the library is not prefixed by "lib".
- if libName, ok := libNameFromFilePath(linkObject.Path()); ok {
+ if mod.Binary() {
+ // Binaries may sometimes need to link whole static libraries that don't start with 'lib'.
+ // Since binaries don't need to 'rebundle' these like libraries and only use these for the
+ // final linkage, pass the args directly to the linker to handle these cases.
+ depPaths.depLinkFlags = append(depPaths.depLinkFlags, []string{"-Wl,--whole-archive", linkObject.Path().String(), "-Wl,--no-whole-archive"}...)
+ } else if libName, ok := libNameFromFilePath(linkObject.Path()); ok {
depPaths.depFlags = append(depPaths.depFlags, "-lstatic="+libName)
} else {
ctx.ModuleErrorf("'%q' cannot be listed as a whole_static_library in Rust modules unless the output is prefixed by 'lib'", depName, ctx.ModuleName())
diff --git a/rust/sanitize.go b/rust/sanitize.go
index a4ba4bd..baa383d 100644
--- a/rust/sanitize.go
+++ b/rust/sanitize.go
@@ -311,8 +311,8 @@
func (mod *Module) StaticallyLinked() bool {
if lib, ok := mod.compiler.(libraryInterface); ok {
return lib.rlib() || lib.static()
- } else if binary, ok := mod.compiler.(*binaryDecorator); ok {
- return Bool(binary.Properties.Static_executable)
+ } else if binary, ok := mod.compiler.(binaryInterface); ok {
+ return binary.staticallyLinked()
}
return false
}
diff --git a/scripts/build-aml-prebuilts.sh b/scripts/build-aml-prebuilts.sh
index 8a5513e..1a16f7c 100755
--- a/scripts/build-aml-prebuilts.sh
+++ b/scripts/build-aml-prebuilts.sh
@@ -23,10 +23,10 @@
export OUT_DIR=${OUT_DIR:-out}
if [ -e ${OUT_DIR}/soong/.soong.kati_enabled ]; then
- # If ${OUT_DIR} has been created without --skip-make, Soong will create an
+ # If ${OUT_DIR} has been created without --soong-only, Soong will create an
# ${OUT_DIR}/soong/build.ninja that leaves out many targets which are
# expected to be supplied by the .mk files, and that might cause errors in
- # "m --skip-make" below. We therefore default to a different out dir
+ # "m --soong-only" below. We therefore default to a different out dir
# location in that case.
AML_OUT_DIR=out/aml
echo "Avoiding in-make OUT_DIR '${OUT_DIR}' - building in '${AML_OUT_DIR}' instead"
diff --git a/scripts/build-mainline-modules.sh b/scripts/build-mainline-modules.sh
index 281cb82..f183c05 100755
--- a/scripts/build-mainline-modules.sh
+++ b/scripts/build-mainline-modules.sh
@@ -99,7 +99,7 @@
export FORCE_BUILD_LLVM_COMPONENTS=true
# Create multi-archs SDKs in a different out directory. The multi-arch script
-# uses Soong in --skip-make mode which cannot use the same directory as normal
+# uses Soong in --soong-only mode which cannot use the same directory as normal
# mode with make.
export OUT_DIR=${OUT_DIR}/aml
echo_and_run build/soong/scripts/build-aml-prebuilts.sh \
diff --git a/scripts/build-ndk-prebuilts.sh b/scripts/build-ndk-prebuilts.sh
index a1fa48d..4783037 100755
--- a/scripts/build-ndk-prebuilts.sh
+++ b/scripts/build-ndk-prebuilts.sh
@@ -64,7 +64,7 @@
"MissingUsesLibraries": ${MISSING_USES_LIBRARIES}
}
EOF
-m --skip-make ${SOONG_OUT}/ndk.timestamp
+m --soong-only --skip-config ${SOONG_OUT}/ndk.timestamp
if [ -n "${DIST_DIR}" ]; then
mkdir -p ${DIST_DIR} || true
diff --git a/scripts/check_boot_jars/package_allowed_list.txt b/scripts/check_boot_jars/package_allowed_list.txt
index b1b1e7e..ed63651 100644
--- a/scripts/check_boot_jars/package_allowed_list.txt
+++ b/scripts/check_boot_jars/package_allowed_list.txt
@@ -69,6 +69,7 @@
javax\.xml\.transform\.stream
javax\.xml\.validation
javax\.xml\.xpath
+jdk\.internal
jdk\.internal\.math
jdk\.internal\.misc
jdk\.internal\.reflect
diff --git a/scripts/manifest_check.py b/scripts/manifest_check.py
index b4936b8..8bed52a 100755
--- a/scripts/manifest_check.py
+++ b/scripts/manifest_check.py
@@ -84,6 +84,13 @@
return parser.parse_args()
+C_RED = "\033[1;31m"
+C_GREEN = "\033[1;32m"
+C_BLUE = "\033[1;34m"
+C_OFF = "\033[0m"
+C_BOLD = "\033[1m"
+
+
def enforce_uses_libraries(manifest, required, optional, relax, is_apk, path):
"""Verify that the <uses-library> tags in the manifest match those provided
@@ -119,22 +126,21 @@
errmsg = ''.join([
'mismatch in the <uses-library> tags between the build system and the '
'manifest:\n',
- '\t- required libraries in build system: [%s]\n' % ', '.join(required),
- '\t vs. in the manifest: [%s]\n' %
- ', '.join(manifest_required),
- '\t- optional libraries in build system: [%s]\n' % ', '.join(optional),
- '\t vs. in the manifest: [%s]\n' %
- ', '.join(manifest_optional),
+ '\t- required libraries in build system: %s[%s]%s\n' % (C_RED, ', '.join(required), C_OFF),
+ '\t vs. in the manifest: %s[%s]%s\n' % (C_RED, ', '.join(manifest_required), C_OFF),
+ '\t- optional libraries in build system: %s[%s]%s\n' % (C_RED, ', '.join(optional), C_OFF),
+ '\t vs. in the manifest: %s[%s]%s\n' % (C_RED, ', '.join(manifest_optional), C_OFF),
'\t- tags in the manifest (%s):\n' % path,
'\t\t%s\n' % '\t\t'.join(tags),
- 'note: the following options are available:\n',
+ '%snote:%s the following options are available:\n' % (C_BLUE, C_OFF),
'\t- to temporarily disable the check on command line, rebuild with ',
- 'RELAX_USES_LIBRARY_CHECK=true (this will set compiler filter "verify" ',
- 'and disable AOT-compilation in dexpreopt)\n',
+ '%sRELAX_USES_LIBRARY_CHECK=true%s' % (C_BOLD, C_OFF),
+ ' (this will set compiler filter "verify" and disable AOT-compilation in dexpreopt)\n',
'\t- to temporarily disable the check for the whole product, set ',
- 'PRODUCT_BROKEN_VERIFY_USES_LIBRARIES := true in the product makefiles\n',
- '\t- to fix the check, make build system properties coherent with the '
- 'manifest\n', '\t- see build/make/Changes.md for details\n'
+ '%sPRODUCT_BROKEN_VERIFY_USES_LIBRARIES := true%s in the product makefiles\n' % (C_BOLD, C_OFF),
+ '\t- to fix the check, make build system properties coherent with the manifest\n',
+ '\t- for details, see %sbuild/make/Changes.md%s' % (C_GREEN, C_OFF),
+ ' and %shttps://source.android.com/devices/tech/dalvik/art-class-loader-context%s\n' % (C_GREEN, C_OFF)
])
#pylint: enable=line-too-long
@@ -380,7 +386,7 @@
# pylint: disable=broad-except
except Exception as err:
- print('error: ' + str(err), file=sys.stderr)
+ print('%serror:%s ' % (C_RED, C_OFF) + str(err), file=sys.stderr)
sys.exit(-1)
diff --git a/scripts/rbc-run b/scripts/rbc-run
index a0907cf..ecc6edd 100755
--- a/scripts/rbc-run
+++ b/scripts/rbc-run
@@ -4,12 +4,13 @@
# that will be passed to rbcrun.
[[ $# -gt 0 && -f "$1" ]] || { echo "Usage: ${0##*/} product.mk [Additional rbcrun arguments]" >&2; exit 1; }
set -eu
-declare -r output_root=${OUT_DIR:-out}
-declare -r runner="$output_root/soong/.bootstrap/bin/rbcrun"
-declare -r converter="$output_root/soong/.bootstrap/bin/mk2rbc"
-declare -r launcher=$output_root/launchers/run.rbc
-declare -r makefile=$1
+
+declare -r output_root="${OUT_DIR:-out}"
+declare -r runner="${output_root}/soong/rbcrun"
+declare -r converter="${output_root}/soong/mk2rbc"
+declare -r launcher="${output_root}/launchers/run.rbc"
+declare -r makefile="$1"
shift
-$converter -mode=write -r --outdir $output_root --launcher=$launcher $makefile
-$runner RBC_OUT="make,global" RBC_DEBUG="${RBC_DEBUG:-}" $@ $launcher
+"${converter}" -mode=write -r --outdir "${output_root}" --launcher="${launcher}" "${makefile}"
+"${runner}" RBC_OUT="make,global" RBC_DEBUG="${RBC_DEBUG:-}" $@ "${launcher}"
diff --git a/soong.bash b/soong.bash
index 8cf2ec6..db7af7c 100755
--- a/soong.bash
+++ b/soong.bash
@@ -15,8 +15,8 @@
# limitations under the License.
echo '==== ERROR: bootstrap.bash & ./soong are obsolete ====' >&2
-echo 'Use `m --skip-make` with a standalone OUT_DIR instead.' >&2
+echo 'Use `m --soong-only` with a standalone OUT_DIR instead.' >&2
echo 'Without envsetup.sh, use:' >&2
-echo ' build/soong/soong_ui.bash --make-mode --skip-make' >&2
+echo ' build/soong/soong_ui.bash --make-mode --soong-only' >&2
echo '======================================================' >&2
exit 1
diff --git a/tests/bootstrap_test.sh b/tests/bootstrap_test.sh
index a22adc5..e92a561 100755
--- a/tests/bootstrap_test.sh
+++ b/tests/bootstrap_test.sh
@@ -17,10 +17,10 @@
function test_null_build() {
setup
run_soong
- local bootstrap_mtime1=$(stat -c "%y" out/soong/.bootstrap/build.ninja)
+ local bootstrap_mtime1=$(stat -c "%y" out/soong/bootstrap.ninja)
local output_mtime1=$(stat -c "%y" out/soong/build.ninja)
run_soong
- local bootstrap_mtime2=$(stat -c "%y" out/soong/.bootstrap/build.ninja)
+ local bootstrap_mtime2=$(stat -c "%y" out/soong/bootstrap.ninja)
local output_mtime2=$(stat -c "%y" out/soong/build.ninja)
if [[ "$bootstrap_mtime1" == "$bootstrap_mtime2" ]]; then
@@ -36,12 +36,12 @@
function test_soong_build_rebuilt_if_blueprint_changes() {
setup
run_soong
- local mtime1=$(stat -c "%y" out/soong/.bootstrap/build.ninja)
+ local mtime1=$(stat -c "%y" out/soong/bootstrap.ninja)
sed -i 's/pluginGenSrcCmd/pluginGenSrcCmd2/g' build/blueprint/bootstrap/bootstrap.go
run_soong
- local mtime2=$(stat -c "%y" out/soong/.bootstrap/build.ninja)
+ local mtime2=$(stat -c "%y" out/soong/bootstrap.ninja)
if [[ "$mtime1" == "$mtime2" ]]; then
fail "Bootstrap Ninja file did not change"
@@ -541,7 +541,7 @@
function test_bp2build_smoke {
setup
run_soong bp2build
- [[ -e out/soong/.bootstrap/bp2build_workspace_marker ]] || fail "bp2build marker file not created"
+ [[ -e out/soong/bp2build_workspace_marker ]] || fail "bp2build marker file not created"
[[ -e out/soong/workspace ]] || fail "Bazel workspace not created"
}
@@ -551,7 +551,7 @@
run_soong bp2build
- if [[ ! -f "./out/soong/.bootstrap/bp2build_workspace_marker" ]]; then
+ if [[ ! -f "./out/soong/bp2build_workspace_marker" ]]; then
fail "Marker file was not generated"
fi
}
@@ -592,10 +592,10 @@
setup
run_soong bp2build
- local mtime1=$(stat -c "%y" out/soong/.bootstrap/bp2build_workspace_marker)
+ local mtime1=$(stat -c "%y" out/soong/bp2build_workspace_marker)
run_soong bp2build
- local mtime2=$(stat -c "%y" out/soong/.bootstrap/bp2build_workspace_marker)
+ local mtime2=$(stat -c "%y" out/soong/bp2build_workspace_marker)
if [[ "$mtime1" != "$mtime2" ]]; then
fail "Output Ninja file changed on null build"
@@ -626,7 +626,7 @@
function test_multiple_soong_build_modes() {
setup
run_soong json-module-graph bp2build nothing
- if [[ ! -f "out/soong/.bootstrap/bp2build_workspace_marker" ]]; then
+ if [[ ! -f "out/soong/bp2build_workspace_marker" ]]; then
fail "bp2build marker file was not generated"
fi
@@ -780,11 +780,11 @@
fail "Output Ninja file changed when switching to bp2build"
fi
- local marker_mtime1=$(stat -c "%y" out/soong/.bootstrap/bp2build_workspace_marker)
+ local marker_mtime1=$(stat -c "%y" out/soong/bp2build_workspace_marker)
run_soong
local output_mtime3=$(stat -c "%y" out/soong/build.ninja)
- local marker_mtime2=$(stat -c "%y" out/soong/.bootstrap/bp2build_workspace_marker)
+ local marker_mtime2=$(stat -c "%y" out/soong/bp2build_workspace_marker)
if [[ "$output_mtime1" != "$output_mtime3" ]]; then
fail "Output Ninja file changed when switching to regular build from bp2build"
fi
@@ -794,7 +794,7 @@
run_soong bp2build
local output_mtime4=$(stat -c "%y" out/soong/build.ninja)
- local marker_mtime3=$(stat -c "%y" out/soong/.bootstrap/bp2build_workspace_marker)
+ local marker_mtime3=$(stat -c "%y" out/soong/bp2build_workspace_marker)
if [[ "$output_mtime1" != "$output_mtime4" ]]; then
fail "Output Ninja file changed when switching back to bp2build"
fi
diff --git a/tests/bp2build_bazel_test.sh b/tests/bp2build_bazel_test.sh
index 379eb65..01b4760 100755
--- a/tests/bp2build_bazel_test.sh
+++ b/tests/bp2build_bazel_test.sh
@@ -11,10 +11,10 @@
function test_bp2build_null_build() {
setup
run_soong bp2build
- local output_mtime1=$(stat -c "%y" out/soong/.bootstrap/bp2build_workspace_marker)
+ local output_mtime1=$(stat -c "%y" out/soong/bp2build_workspace_marker)
run_soong bp2build
- local output_mtime2=$(stat -c "%y" out/soong/.bootstrap/bp2build_workspace_marker)
+ local output_mtime2=$(stat -c "%y" out/soong/bp2build_workspace_marker)
if [[ "$output_mtime1" != "$output_mtime2" ]]; then
fail "Output bp2build marker file changed on null build"
@@ -36,10 +36,10 @@
touch foo/bar/a.txt foo/bar/b.txt
run_soong bp2build
- local output_mtime1=$(stat -c "%y" out/soong/.bootstrap/bp2build_workspace_marker)
+ local output_mtime1=$(stat -c "%y" out/soong/bp2build_workspace_marker)
run_soong bp2build
- local output_mtime2=$(stat -c "%y" out/soong/.bootstrap/bp2build_workspace_marker)
+ local output_mtime2=$(stat -c "%y" out/soong/bp2build_workspace_marker)
if [[ "$output_mtime1" != "$output_mtime2" ]]; then
fail "Output bp2build marker file changed on null build"
diff --git a/tests/lib.sh b/tests/lib.sh
index e777820..e6074f8 100644
--- a/tests/lib.sh
+++ b/tests/lib.sh
@@ -105,7 +105,7 @@
}
function run_soong() {
- build/soong/soong_ui.bash --make-mode --skip-ninja --skip-make --skip-soong-tests "$@"
+ build/soong/soong_ui.bash --make-mode --skip-ninja --skip-config --soong-only --skip-soong-tests "$@"
}
function create_mock_bazel() {
@@ -125,7 +125,7 @@
}
run_ninja() {
- build/soong/soong_ui.bash --make-mode --skip-make --skip-soong-tests "$@"
+ build/soong/soong_ui.bash --make-mode --skip-config --soong-only --skip-soong-tests "$@"
}
info "Starting Soong integration test suite $(basename $0)"
diff --git a/tests/run_integration_tests.sh b/tests/run_integration_tests.sh
index 6304a11..a376e06 100755
--- a/tests/run_integration_tests.sh
+++ b/tests/run_integration_tests.sh
@@ -7,3 +7,4 @@
"$TOP/build/soong/tests/mixed_mode_test.sh"
"$TOP/build/soong/tests/bp2build_bazel_test.sh"
"$TOP/build/soong/tests/soong_test.sh"
+"$TOP/build/bazel/ci/rbc_product_config.sh" aosp_arm64-userdebug
diff --git a/third_party/zip/reader_test.go b/third_party/zip/reader_test.go
index dfaae78..11c6d6e 100644
--- a/third_party/zip/reader_test.go
+++ b/third_party/zip/reader_test.go
@@ -786,7 +786,7 @@
}
}
-// Verify the number of files is sane.
+// Verify the number of files is within expected bounds
func TestIssue10956(t *testing.T) {
data := []byte("PK\x06\x06PK\x06\a0000\x00\x00\x00\x00\x00\x00\x00\x00" +
"0000PK\x05\x06000000000000" +
diff --git a/ui/build/config.go b/ui/build/config.go
index 7837cc4..e0fa503 100644
--- a/ui/build/config.go
+++ b/ui/build/config.go
@@ -784,24 +784,21 @@
panic("Unknown GOOS")
}
}
+
func (c *configImpl) HostToolDir() string {
return filepath.Join(c.SoongOutDir(), "host", c.PrebuiltOS(), "bin")
}
func (c *configImpl) NamedGlobFile(name string) string {
- return shared.JoinPath(c.SoongOutDir(), ".bootstrap/build-globs."+name+".ninja")
+ return shared.JoinPath(c.SoongOutDir(), "globs-"+name+".ninja")
}
func (c *configImpl) UsedEnvFile(tag string) string {
return shared.JoinPath(c.SoongOutDir(), usedEnvFile+"."+tag)
}
-func (c *configImpl) MainNinjaFile() string {
- return shared.JoinPath(c.SoongOutDir(), "build.ninja")
-}
-
func (c *configImpl) Bp2BuildMarkerFile() string {
- return shared.JoinPath(c.SoongOutDir(), ".bootstrap/bp2build_workspace_marker")
+ return shared.JoinPath(c.SoongOutDir(), "bp2build_workspace_marker")
}
func (c *configImpl) SoongDocsHtml() string {
diff --git a/ui/build/dumpvars.go b/ui/build/dumpvars.go
index afec829..3f10f75 100644
--- a/ui/build/dumpvars.go
+++ b/ui/build/dumpvars.go
@@ -263,9 +263,9 @@
}, exportEnvVars...), BannerVars...)
// We need Roboleaf converter and runner in the mixed mode
- runMicrofactory(ctx, config, ".bootstrap/bin/mk2rbc", "android/soong/mk2rbc/cmd",
+ runMicrofactory(ctx, config, "mk2rbc", "android/soong/mk2rbc/cmd",
map[string]string{"android/soong": "build/soong"})
- runMicrofactory(ctx, config, ".bootstrap/bin/rbcrun", "rbcrun/cmd",
+ runMicrofactory(ctx, config, "rbcrun", "rbcrun/cmd",
map[string]string{"go.starlark.net": "external/starlark-go", "rbcrun": "build/make/tools/rbcrun"})
makeVars, err := dumpMakeVars(ctx, config, config.Arguments(), allVars, true, "")
diff --git a/ui/build/soong.go b/ui/build/soong.go
index 617d293..4ced722 100644
--- a/ui/build/soong.go
+++ b/ui/build/soong.go
@@ -15,6 +15,7 @@
package build
import (
+ "fmt"
"io/ioutil"
"os"
"path/filepath"
@@ -43,6 +44,12 @@
jsonModuleGraphTag = "modulegraph"
queryviewTag = "queryview"
soongDocsTag = "soong_docs"
+
+ // bootstrapEpoch is used to determine if an incremental build is incompatible with the current
+ // version of bootstrap and needs cleaning before continuing the build. Increment this for
+ // incompatible changes, for example when moving the location of the bpglob binary that is
+ // executed during bootstrap before the primary builder has had a chance to update the path.
+ bootstrapEpoch = 1
)
func writeEnvironmentFile(ctx Context, envFile string, envDeps map[string]string) error {
@@ -121,20 +128,31 @@
}
}
-func writeEmptyGlobFile(ctx Context, path string) {
+func writeEmptyFile(ctx Context, path string) {
err := os.MkdirAll(filepath.Dir(path), 0777)
if err != nil {
- ctx.Fatalf("Failed to create parent directories of empty ninja glob file '%s': %s", path, err)
+ ctx.Fatalf("Failed to create parent directories of empty file '%s': %s", path, err)
}
- if _, err := os.Stat(path); os.IsNotExist(err) {
+ if exists, err := fileExists(path); err != nil {
+ ctx.Fatalf("Failed to check if file '%s' exists: %s", path, err)
+ } else if !exists {
err = ioutil.WriteFile(path, nil, 0666)
if err != nil {
- ctx.Fatalf("Failed to create empty ninja glob file '%s': %s", path, err)
+ ctx.Fatalf("Failed to create empty file '%s': %s", path, err)
}
}
}
+func fileExists(path string) (bool, error) {
+ if _, err := os.Stat(path); os.IsNotExist(err) {
+ return false, nil
+ } else if err != nil {
+ return false, err
+ }
+ return true, nil
+}
+
func primaryBuilderInvocation(config Config, name string, output string, specificArgs []string) bootstrap.PrimaryBuilderInvocation {
commonArgs := make([]string, 0, 0)
@@ -166,11 +184,46 @@
}
}
+// bootstrapEpochCleanup deletes files used by bootstrap during incremental builds across
+// incompatible changes. Incompatible changes are marked by incrementing the bootstrapEpoch
+// constant. A tree is considered out of date for the current epoch of the
+// .soong.bootstrap.epoch.<epoch> file doesn't exist.
+func bootstrapEpochCleanup(ctx Context, config Config) {
+ epochFile := fmt.Sprintf(".soong.bootstrap.epoch.%d", bootstrapEpoch)
+ epochPath := filepath.Join(config.SoongOutDir(), epochFile)
+ if exists, err := fileExists(epochPath); err != nil {
+ ctx.Fatalf("failed to check if bootstrap epoch file %q exists: %q", epochPath, err)
+ } else if !exists {
+ // The tree is out of date for the current epoch, delete files used by bootstrap
+ // and force the primary builder to rerun.
+ os.Remove(filepath.Join(config.SoongOutDir(), "build.ninja"))
+ for _, globFile := range bootstrapGlobFileList(config) {
+ os.Remove(globFile)
+ }
+
+ // Mark the tree as up to date with the current epoch by writing the epoch marker file.
+ writeEmptyFile(ctx, epochPath)
+ }
+}
+
+func bootstrapGlobFileList(config Config) []string {
+ return []string{
+ config.NamedGlobFile(soongBuildTag),
+ config.NamedGlobFile(bp2buildTag),
+ config.NamedGlobFile(jsonModuleGraphTag),
+ config.NamedGlobFile(queryviewTag),
+ config.NamedGlobFile(soongDocsTag),
+ }
+}
+
func bootstrapBlueprint(ctx Context, config Config) {
ctx.BeginTrace(metrics.RunSoong, "blueprint bootstrap")
defer ctx.EndTrace()
- mainSoongBuildExtraArgs := []string{"-o", config.MainNinjaFile()}
+ // Clean up some files for incremental builds across incompatible changes.
+ bootstrapEpochCleanup(ctx, config)
+
+ mainSoongBuildExtraArgs := []string{"-o", config.SoongNinjaFile()}
if config.EmptyNinjaFile() {
mainSoongBuildExtraArgs = append(mainSoongBuildExtraArgs, "--empty-ninja-file")
}
@@ -178,7 +231,7 @@
mainSoongBuildInvocation := primaryBuilderInvocation(
config,
soongBuildTag,
- config.MainNinjaFile(),
+ config.SoongNinjaFile(),
mainSoongBuildExtraArgs)
if config.bazelBuildMode() == mixedBuild {
@@ -232,14 +285,14 @@
// The glob .ninja files are subninja'd. However, they are generated during
// the build itself so we write an empty file if the file does not exist yet
// so that the subninja doesn't fail on clean builds
- for _, globFile := range globFiles {
- writeEmptyGlobFile(ctx, globFile)
+ for _, globFile := range bootstrapGlobFileList(config) {
+ writeEmptyFile(ctx, globFile)
}
var blueprintArgs bootstrap.Args
blueprintArgs.ModuleListFile = filepath.Join(config.FileListDir(), "Android.bp.list")
- blueprintArgs.OutFile = shared.JoinPath(config.SoongOutDir(), ".bootstrap/build.ninja")
+ blueprintArgs.OutFile = shared.JoinPath(config.SoongOutDir(), "bootstrap.ninja")
blueprintArgs.EmptyNinjaFile = false
blueprintCtx := blueprint.NewContext()
@@ -261,7 +314,7 @@
}
bootstrapDeps := bootstrap.RunBlueprint(blueprintArgs, bootstrap.DoEverything, blueprintCtx, blueprintConfig)
- bootstrapDepFile := shared.JoinPath(config.SoongOutDir(), ".bootstrap/build.ninja.d")
+ bootstrapDepFile := shared.JoinPath(config.SoongOutDir(), "bootstrap.ninja.d")
err := deptools.WriteDepFile(bootstrapDepFile, blueprintArgs.OutFile, bootstrapDeps)
if err != nil {
ctx.Fatalf("Error writing depfile '%s': %s", bootstrapDepFile, err)
@@ -289,11 +342,6 @@
// unused variables were changed?
envFile := filepath.Join(config.SoongOutDir(), availableEnvFile)
- dir := filepath.Join(config.SoongOutDir(), ".bootstrap")
- if err := os.MkdirAll(dir, 0755); err != nil {
- ctx.Fatalf("Cannot mkdir " + dir)
- }
-
buildMode := config.bazelBuildMode()
integratedBp2Build := buildMode == mixedBuild
@@ -342,7 +390,7 @@
}
}()
- runMicrofactory(ctx, config, filepath.Join(config.HostToolDir(), "bpglob"), "github.com/google/blueprint/bootstrap/bpglob",
+ runMicrofactory(ctx, config, "bpglob", "github.com/google/blueprint/bootstrap/bpglob",
map[string]string{"github.com/google/blueprint": "build/blueprint"})
ninja := func(name, ninjaFile string, targets ...string) {
@@ -401,10 +449,10 @@
if config.SoongBuildInvocationNeeded() {
// This build generates <builddir>/build.ninja, which is used later by build/soong/ui/build/build.go#Build().
- targets = append(targets, config.MainNinjaFile())
+ targets = append(targets, config.SoongNinjaFile())
}
- ninja("bootstrap", ".bootstrap/build.ninja", targets...)
+ ninja("bootstrap", "bootstrap.ninja", targets...)
var soongBuildMetrics *soong_metrics_proto.SoongBuildMetrics
if shouldCollectBuildSoongMetrics(config) {
@@ -424,8 +472,7 @@
}
}
-func runMicrofactory(ctx Context, config Config, relExePath string, pkg string, mapping map[string]string) {
- name := filepath.Base(relExePath)
+func runMicrofactory(ctx Context, config Config, name string, pkg string, mapping map[string]string) {
ctx.BeginTrace(metrics.RunSoong, name)
defer ctx.EndTrace()
cfg := microfactory.Config{TrimPath: absPath(ctx, ".")}
@@ -433,7 +480,7 @@
cfg.Map(pkgPrefix, pathPrefix)
}
- exePath := filepath.Join(config.SoongOutDir(), relExePath)
+ exePath := filepath.Join(config.SoongOutDir(), name)
dir := filepath.Dir(exePath)
if err := os.MkdirAll(dir, 0777); err != nil {
ctx.Fatalf("cannot create %s: %s", dir, err)
diff --git a/ui/build/test_build.go b/ui/build/test_build.go
index f9a60b6..83007be 100644
--- a/ui/build/test_build.go
+++ b/ui/build/test_build.go
@@ -63,7 +63,6 @@
cmd.StartOrFatal()
outDir := config.OutDir()
- bootstrapDir := filepath.Join(outDir, "soong", ".bootstrap")
modulePathsDir := filepath.Join(outDir, ".module_paths")
variablesFilePath := filepath.Join(outDir, "soong", "soong.variables")
@@ -86,8 +85,7 @@
// Leaf node is not in the out directory.
continue
}
- if strings.HasPrefix(line, bootstrapDir) ||
- strings.HasPrefix(line, modulePathsDir) ||
+ if strings.HasPrefix(line, modulePathsDir) ||
line == variablesFilePath ||
line == dexpreoptConfigFilePath ||
line == buildDatetimeFilePath {