Merge "Defer error reporting of missing prebuilt dex jar files"
diff --git a/Android.bp b/Android.bp
index 45e661e..d6260b4 100644
--- a/Android.bp
+++ b/Android.bp
@@ -116,3 +116,13 @@
dex_bootjars {
name: "dex_bootjars",
}
+
+// Pseudo-test that's run on checkbuilds to ensure that get_clang_version can
+// parse cc/config/global.go.
+genrule {
+ name: "get_clang_version_test",
+ cmd: "$(location get_clang_version) > $(out)",
+ tools: ["get_clang_version"],
+ srcs: ["cc/config/global.go"],
+ out: ["clang-prebuilts-version.txt"],
+}
diff --git a/README.md b/README.md
index b7e93f4..10ddd73 100644
--- a/README.md
+++ b/README.md
@@ -213,8 +213,8 @@
A module name's **scope** is the smallest namespace containing it. Suppose a
source tree has `device/my` and `device/my/display` namespaces. If `libfoo`
-module is defined in `device/co/display/lib/Android.bp`, its namespace is
-`device/co/display`.
+module is defined in `device/my/display/lib/Android.bp`, its namespace is
+`device/my/display`.
The name uniqueness thus means that module's name is unique within its scope. In
other words, "//_scope_:_name_" is globally unique module reference, e.g,
diff --git a/apex/prebuilt.go b/apex/prebuilt.go
index f783172..1bb0fb5 100644
--- a/apex/prebuilt.go
+++ b/apex/prebuilt.go
@@ -376,6 +376,12 @@
}
}
+ // Ignore any modules that do not implement ApexModule as they cannot have an APEX specific
+ // variant.
+ if _, ok := child.(android.ApexModule); !ok {
+ return false
+ }
+
// Strip off the prebuilt_ prefix if present before storing content to ensure consistent
// behavior whether there is a corresponding source module present or not.
depName = android.RemoveOptionalPrebuiltPrefix(depName)
diff --git a/cc/cc.go b/cc/cc.go
index 15cb39a..0aa1014 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -571,7 +571,8 @@
sharedLibs []string
// Note nil and [] are semantically distinct. [] prevents linking against the defaults (usually
// libc, libm, etc.)
- systemSharedLibs []string
+ systemSharedLibs []string
+ defaultSharedLibs []string
}
// installer is the interface for an installer helper object. This helper is responsible for
diff --git a/cc/cc_test.go b/cc/cc_test.go
index 401fd6f..0a74e58 100644
--- a/cc/cc_test.go
+++ b/cc/cc_test.go
@@ -4046,12 +4046,12 @@
"${config.ArmToolchainClangCflags}",
"${config.ArmClangArmv7ANeonCflags}",
"${config.ArmClangGenericCflags}",
- "export_include_dirs",
- "linux_export_include_dirs",
- "android_export_include_dirs",
- "arm_export_include_dirs",
- "lib32_export_include_dirs",
"android_arm_export_include_dirs",
+ "lib32_export_include_dirs",
+ "arm_export_include_dirs",
+ "android_export_include_dirs",
+ "linux_export_include_dirs",
+ "export_include_dirs",
"android_arm_local_include_dirs",
"lib32_local_include_dirs",
"arm_local_include_dirs",
diff --git a/cc/compiler.go b/cc/compiler.go
index 78a5a5d..69ead30 100644
--- a/cc/compiler.go
+++ b/cc/compiler.go
@@ -92,7 +92,7 @@
// list of generated headers to add to the include path. These are the names
// of genrule modules.
- Generated_headers []string `android:"arch_variant"`
+ Generated_headers []string `android:"arch_variant,variant_prepend"`
// pass -frtti instead of -fno-rtti
Rtti *bool
diff --git a/cc/library.go b/cc/library.go
index 95f9b0a..4fd7c74 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -147,11 +147,12 @@
Cflags []string `android:"arch_variant"`
- Enabled *bool `android:"arch_variant"`
- Whole_static_libs []string `android:"arch_variant"`
- Static_libs []string `android:"arch_variant"`
- Shared_libs []string `android:"arch_variant"`
- System_shared_libs []string `android:"arch_variant"`
+ Enabled *bool `android:"arch_variant"`
+ Whole_static_libs []string `android:"arch_variant"`
+ Static_libs []string `android:"arch_variant"`
+ Shared_libs []string `android:"arch_variant"`
+ System_shared_libs []string `android:"arch_variant"`
+ Default_shared_libs []string `android:"arch_variant"`
Export_shared_lib_headers []string `android:"arch_variant"`
Export_static_lib_headers []string `android:"arch_variant"`
@@ -184,11 +185,11 @@
// be added to the include path (using -I) for this module and any module that links
// against this module. Directories listed in export_include_dirs do not need to be
// listed in local_include_dirs.
- Export_include_dirs []string `android:"arch_variant"`
+ Export_include_dirs []string `android:"arch_variant,variant_prepend"`
// list of directories that will be added to the system include path
// using -isystem for this module and any module that links against this module.
- Export_system_include_dirs []string `android:"arch_variant"`
+ Export_system_include_dirs []string `android:"arch_variant,variant_prepend"`
Target struct {
Vendor, Product struct {
@@ -1156,11 +1157,17 @@
if library.StaticProperties.Static.System_shared_libs != nil {
library.baseLinker.Properties.System_shared_libs = library.StaticProperties.Static.System_shared_libs
}
+ if library.StaticProperties.Static.Default_shared_libs != nil {
+ library.baseLinker.Properties.Default_shared_libs = library.StaticProperties.Static.Default_shared_libs
+ }
} else if library.shared() {
// Compare with nil because an empty list needs to be propagated.
if library.SharedProperties.Shared.System_shared_libs != nil {
library.baseLinker.Properties.System_shared_libs = library.SharedProperties.Shared.System_shared_libs
}
+ if library.SharedProperties.Shared.Default_shared_libs != nil {
+ library.baseLinker.Properties.Default_shared_libs = library.SharedProperties.Shared.Default_shared_libs
+ }
}
deps = library.baseLinker.linkerDeps(ctx, deps)
@@ -1242,6 +1249,11 @@
} else {
specifiedDeps.systemSharedLibs = append(specifiedDeps.systemSharedLibs, properties.System_shared_libs...)
}
+ if specifiedDeps.defaultSharedLibs == nil {
+ specifiedDeps.defaultSharedLibs = properties.Default_shared_libs
+ } else {
+ specifiedDeps.defaultSharedLibs = append(specifiedDeps.defaultSharedLibs, properties.Default_shared_libs...)
+ }
specifiedDeps.sharedLibs = android.FirstUniqueStrings(specifiedDeps.sharedLibs)
if len(specifiedDeps.systemSharedLibs) > 0 {
@@ -1249,6 +1261,11 @@
// retained.
specifiedDeps.systemSharedLibs = android.FirstUniqueStrings(specifiedDeps.systemSharedLibs)
}
+ if len(specifiedDeps.defaultSharedLibs) > 0 {
+ // Skip this if defaultSharedLibs is either nil or [], to ensure they are
+ // retained.
+ specifiedDeps.defaultSharedLibs = android.FirstUniqueStrings(specifiedDeps.defaultSharedLibs)
+ }
return specifiedDeps
}
diff --git a/cc/library_sdk_member.go b/cc/library_sdk_member.go
index 9010a1a..9ad2742 100644
--- a/cc/library_sdk_member.go
+++ b/cc/library_sdk_member.go
@@ -258,6 +258,12 @@
outputProperties.AddPropertyWithTag("system_shared_libs", libInfo.SystemSharedLibs, builder.SdkMemberReferencePropertyTag(false))
}
+ // SystemSharedLibs needs to be propagated if it's a list, even if it's empty,
+ // so check for non-nil instead of nonzero length.
+ if libInfo.DefaultSharedLibs != nil {
+ outputProperties.AddPropertyWithTag("default_shared_libs", libInfo.DefaultSharedLibs, builder.SdkMemberReferencePropertyTag(false))
+ }
+
// Map from property name to the include dirs to add to the prebuilt module in the snapshot.
includeDirs := make(map[string][]string)
@@ -387,6 +393,12 @@
// This field is exported as its contents may not be arch specific.
SystemSharedLibs []string `android:"arch_variant"`
+ // The set of default shared libraries. Note nil and [] are semantically
+ // distinct - see BaseLinkerProperties.Default_shared_libs.
+ //
+ // This field is exported as its contents may not be arch specific.
+ DefaultSharedLibs []string `android:"arch_variant"`
+
// The specific stubs version for the lib variant, or empty string if stubs
// are not in use.
//
@@ -462,6 +474,7 @@
}
}
p.SystemSharedLibs = specifiedDeps.systemSharedLibs
+ p.DefaultSharedLibs = specifiedDeps.defaultSharedLibs
}
p.ExportedGeneratedHeaders = exportedInfo.GeneratedHeaders
diff --git a/cc/linker.go b/cc/linker.go
index 7b16b40..13df232 100644
--- a/cc/linker.go
+++ b/cc/linker.go
@@ -45,11 +45,18 @@
// list of module-specific flags that will be used for all link steps
Ldflags []string `android:"arch_variant"`
- // list of system libraries that will be dynamically linked to
- // shared library and executable modules. If unset, generally defaults to libc,
- // libm, and libdl. Set to [] to prevent linking against the defaults.
+ // list of system libraries that will be dynamically linked to shared library and executable
+ // modules that build against bionic (device or Linux bionic modules). If unset, generally
+ // defaults to libc, libm, and libdl. Set to [] to prevent linking against the defaults.
+ // Equivalent to default_shared_libs for modules that build against bionic, and ignored on
+ // modules that do not build against bionic.
System_shared_libs []string `android:"arch_variant"`
+ // list of system libraries that will be dynamically linked to shared library and executable
+ // modules. If unset, generally defaults to libc, libm, and libdl. Set to [] to prevent
+ // linking against the defaults. Equivalent to system_shared_libs, but applies to all modules.
+ Default_shared_libs []string `android:"arch_variant"`
+
// allow the module to contain undefined symbols. By default,
// modules cannot contain undefined symbols that are not satisified by their immediate
// dependencies. Set this flag to true to remove --no-undefined from the linker flags.
@@ -231,6 +238,19 @@
linker.Properties.Ldflags = append(linker.Properties.Ldflags, flags...)
}
+// overrideDefaultSharedLibraries returns the contents of the default_shared_libs or
+// system_shared_libs properties, and records an error if both are set.
+func (linker *baseLinker) overrideDefaultSharedLibraries(ctx BaseModuleContext) []string {
+ if linker.Properties.System_shared_libs != nil && linker.Properties.Default_shared_libs != nil {
+ ctx.PropertyErrorf("system_shared_libs", "cannot be specified if default_shared_libs is also specified")
+ }
+ if ctx.toolchain().Bionic() && linker.Properties.System_shared_libs != nil {
+ // system_shared_libs is only honored when building against bionic.
+ return linker.Properties.System_shared_libs
+ }
+ return linker.Properties.Default_shared_libs
+}
+
// linkerInit initializes dynamic properties of the linker (such as runpath).
func (linker *baseLinker) linkerInit(ctx BaseModuleContext) {
if ctx.toolchain().Is64Bit() {
@@ -331,22 +351,22 @@
deps.SharedLibs = append(deps.SharedLibs, linker.Properties.Target.Platform.Shared_libs...)
}
+ deps.SystemSharedLibs = linker.overrideDefaultSharedLibraries(ctx)
+ // In Bazel conversion mode, variations have not been specified, so SystemSharedLibs may
+ // inaccuarately appear unset, which can cause issues with circular dependencies.
+ if deps.SystemSharedLibs == nil && !ctx.BazelConversionMode() {
+ // Provide a default set of shared libraries if default_shared_libs and system_shared_libs
+ // are unspecified. Note: If an empty list [] is specified, it implies that the module
+ // declines the default shared libraries.
+ deps.SystemSharedLibs = append(deps.SystemSharedLibs, ctx.toolchain().DefaultSharedLibraries()...)
+ }
+
if ctx.toolchain().Bionic() {
// libclang_rt.builtins has to be last on the command line
if !Bool(linker.Properties.No_libcrt) && !ctx.header() {
deps.LateStaticLibs = append(deps.LateStaticLibs, config.BuiltinsRuntimeLibrary(ctx.toolchain()))
}
- deps.SystemSharedLibs = linker.Properties.System_shared_libs
- // In Bazel conversion mode, variations have not been specified, so SystemSharedLibs may
- // inaccuarately appear unset, which can cause issues with circular dependencies.
- if deps.SystemSharedLibs == nil && !ctx.BazelConversionMode() {
- // Provide a default system_shared_libs if it is unspecified. Note: If an
- // empty list [] is specified, it implies that the module declines the
- // default system_shared_libs.
- deps.SystemSharedLibs = append(deps.SystemSharedLibs, ctx.toolchain().DefaultSharedLibraries()...)
- }
-
if inList("libdl", deps.SharedLibs) {
// If system_shared_libs has libc but not libdl, make sure shared_libs does not
// have libdl to avoid loading libdl before libc.
@@ -573,6 +593,11 @@
} else {
specifiedDeps.systemSharedLibs = append(specifiedDeps.systemSharedLibs, linker.Properties.System_shared_libs...)
}
+ if specifiedDeps.defaultSharedLibs == nil {
+ specifiedDeps.defaultSharedLibs = linker.Properties.Default_shared_libs
+ } else {
+ specifiedDeps.defaultSharedLibs = append(specifiedDeps.defaultSharedLibs, linker.Properties.Default_shared_libs...)
+ }
return specifiedDeps
}
diff --git a/java/base.go b/java/base.go
index 77f6fc6..6b81196 100644
--- a/java/base.go
+++ b/java/base.go
@@ -870,6 +870,7 @@
if aaptSrcJar != nil {
srcJars = append(srcJars, aaptSrcJar)
}
+ srcFiles = srcFiles.FilterOutByExt(".srcjar")
if j.properties.Jarjar_rules != nil {
j.expandJarjarRules = android.PathForModuleSrc(ctx, *j.properties.Jarjar_rules)
diff --git a/java/bootclasspath_fragment_test.go b/java/bootclasspath_fragment_test.go
index b469886..3d0e155 100644
--- a/java/bootclasspath_fragment_test.go
+++ b/java/bootclasspath_fragment_test.go
@@ -197,7 +197,7 @@
],
},
core_platform_api: {
- stub_libs: ["mycoreplatform"],
+ stub_libs: ["mycoreplatform.stubs"],
},
}
diff --git a/java/hiddenapi_modular.go b/java/hiddenapi_modular.go
index 7e10fab..c4832d2 100644
--- a/java/hiddenapi_modular.go
+++ b/java/hiddenapi_modular.go
@@ -586,6 +586,13 @@
// addStubDexJar adds a stub dex jar path provided by the specified module for the specified scope.
func (s StubDexJarsByModule) addStubDexJar(ctx android.ModuleContext, module android.Module, scope *HiddenAPIScope, stubDexJar android.Path) {
name := android.RemoveOptionalPrebuiltPrefix(module.Name())
+
+ // Each named module provides one dex jar for each scope. However, in some cases different API
+ // versions of a single classes are provided by separate modules. e.g. the core platform
+ // version of java.lang.Object is provided by the legacy.art.module.platform.api module but the
+ // public version is provided by the art.module.public.api module. In those cases it is necessary
+ // to treat all those modules as they were the same name, otherwise it will result in multiple
+ // definitions of a single class being passed to hidden API processing which will cause an error.
if name == scope.nonUpdatablePrebuiltModule || name == scope.nonUpdatableSourceModule {
// Treat all *android-non-updatable* modules as if they were part of an android-non-updatable
// java_sdk_library.
@@ -606,6 +613,14 @@
// conscrypt.module.public.api java_sdk_library which will be the case once the former has been
// migrated to a module_lib API.
name = "conscrypt.module.public.api"
+ } else if d, ok := module.(SdkLibraryComponentDependency); ok {
+ sdkLibraryName := d.SdkLibraryName()
+ if sdkLibraryName != nil {
+ // The module is a component of a java_sdk_library so use the name of the java_sdk_library.
+ // e.g. if this module is `foo.system.stubs` and is part of the `foo` java_sdk_library then
+ // use `foo` as the name.
+ name = *sdkLibraryName
+ }
}
stubDexJarsByScope := s[name]
if stubDexJarsByScope == nil {
diff --git a/java/jacoco.go b/java/jacoco.go
index 9162161..e11c2ce 100644
--- a/java/jacoco.go
+++ b/java/jacoco.go
@@ -94,7 +94,7 @@
if len(includes) > 0 {
specs += strings.Join(includes, " ")
} else {
- specs += "**/*.class"
+ specs += "'**/*.class'"
}
return specs
}
diff --git a/java/jacoco_test.go b/java/jacoco_test.go
index 91f0553..1882908 100644
--- a/java/jacoco_test.go
+++ b/java/jacoco_test.go
@@ -74,7 +74,7 @@
{
name: "implicit wildcard",
includes: []string{},
- out: "**/*.class",
+ out: "'**/*.class'",
},
{
name: "only include",
diff --git a/java/lint_defaults.txt b/java/lint_defaults.txt
index 2de05b0..75de7dc 100644
--- a/java/lint_defaults.txt
+++ b/java/lint_defaults.txt
@@ -78,3 +78,7 @@
--disable_check HardcodedDebugMode
--warning_check QueryAllPackagesPermission
+
+--warning_check CoarseFineLocation
+--warning_check IntentFilterExportedReceiver
+--warning_check RemoteViewLayout
diff --git a/java/sdk.go b/java/sdk.go
index cbd873d..d1b899e 100644
--- a/java/sdk.go
+++ b/java/sdk.go
@@ -175,10 +175,24 @@
}
case android.SdkModule:
// TODO(146757305): provide .apk and .aidl that have more APIs for modules
- return toModule([]string{"android_module_lib_stubs_current"}, "framework-res", nonUpdatableFrameworkAidlPath(ctx))
+ 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)),
+ }
case android.SdkSystemServer:
// TODO(146757305): provide .apk and .aidl that have more APIs for modules
- return toModule([]string{"android_system_server_stubs_current"}, "framework-res", sdkFrameworkAidlPath(ctx))
+ 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)),
+ }
default:
panic(fmt.Errorf("invalid sdk %q", sdkVersion.Raw))
}
diff --git a/java/sdk_library.go b/java/sdk_library.go
index 567e292..ed9aeff 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -675,10 +675,13 @@
return false
}
+ namePtr := proptools.StringPtr(c.module.BaseModuleName())
+ c.sdkLibraryComponentProperties.SdkLibraryName = namePtr
+
// Only track this sdk library if this can be used as a shared library.
if c.sharedLibrary() {
// Use the name specified in the module definition as the owner.
- c.sdkLibraryComponentProperties.SdkLibraryToImplicitlyTrack = proptools.StringPtr(c.module.BaseModuleName())
+ c.sdkLibraryComponentProperties.SdkLibraryToImplicitlyTrack = namePtr
}
return true
@@ -922,15 +925,19 @@
func (c *commonToSdkLibraryAndImport) sdkComponentPropertiesForChildLibrary() interface{} {
componentProps := &struct {
+ SdkLibraryName *string
SdkLibraryToImplicitlyTrack *string
}{}
+ namePtr := proptools.StringPtr(c.module.BaseModuleName())
+ componentProps.SdkLibraryName = namePtr
+
if c.sharedLibrary() {
// Mark the stubs library as being components of this java_sdk_library so that
// any app that includes code which depends (directly or indirectly) on the stubs
// library will have the appropriate <uses-library> invocation inserted into its
// manifest if necessary.
- componentProps.SdkLibraryToImplicitlyTrack = proptools.StringPtr(c.module.BaseModuleName())
+ componentProps.SdkLibraryToImplicitlyTrack = namePtr
}
return componentProps
@@ -949,6 +956,8 @@
// Properties related to the use of a module as an component of a java_sdk_library.
type SdkLibraryComponentProperties struct {
+ // The name of the java_sdk_library/_import module.
+ SdkLibraryName *string `blueprint:"mutated"`
// The name of the java_sdk_library/_import to add to a <uses-library> entry
// in the AndroidManifest.xml of any Android app that includes code that references
@@ -967,6 +976,11 @@
}
// to satisfy SdkLibraryComponentDependency
+func (e *EmbeddableSdkLibraryComponent) SdkLibraryName() *string {
+ return e.sdkLibraryComponentProperties.SdkLibraryName
+}
+
+// to satisfy SdkLibraryComponentDependency
func (e *EmbeddableSdkLibraryComponent) OptionalImplicitSdkLibrary() *string {
return e.sdkLibraryComponentProperties.SdkLibraryToImplicitlyTrack
}
@@ -982,6 +996,9 @@
type SdkLibraryComponentDependency interface {
UsesLibraryDependency
+ // SdkLibraryName returns the name of the java_sdk_library/_import module.
+ SdkLibraryName() *string
+
// The optional name of the sdk library that should be implicitly added to the
// AndroidManifest of an app that contains code which references the sdk library.
//
diff --git a/java/sdk_test.go b/java/sdk_test.go
index 2b18465..bb595a5 100644
--- a/java/sdk_test.go
+++ b/java/sdk_test.go
@@ -219,7 +219,7 @@
name: "module_current",
properties: `sdk_version: "module_current",`,
bootclasspath: []string{"android_module_lib_stubs_current", "core-lambda-stubs"},
- system: "core-current-stubs-system-modules",
+ system: "core-module-lib-stubs-system-modules",
java9classpath: []string{"android_module_lib_stubs_current"},
aidl: "-pout/soong/framework_non_updatable.aidl",
},
@@ -227,7 +227,7 @@
name: "system_server_current",
properties: `sdk_version: "system_server_current",`,
bootclasspath: []string{"android_system_server_stubs_current", "core-lambda-stubs"},
- system: "core-current-stubs-system-modules",
+ system: "core-module-lib-stubs-system-modules",
java9classpath: []string{"android_system_server_stubs_current"},
aidl: "-pout/soong/framework.aidl",
},
diff --git a/java/testing.go b/java/testing.go
index c3803c8..e2ff5cd 100644
--- a/java/testing.go
+++ b/java/testing.go
@@ -312,6 +312,7 @@
systemModules := []string{
"core-current-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/scripts/Android.bp b/scripts/Android.bp
index 1c02bd0..635be10 100644
--- a/scripts/Android.bp
+++ b/scripts/Android.bp
@@ -265,3 +265,19 @@
"linker_config_proto",
],
}
+
+python_binary_host {
+ name: "get_clang_version",
+ main: "get_clang_version.py",
+ srcs: [
+ "get_clang_version.py",
+ ],
+ version: {
+ py2: {
+ enabled: false,
+ },
+ py3: {
+ enabled: true,
+ },
+ },
+}
diff --git a/scripts/get_clang_version.py b/scripts/get_clang_version.py
new file mode 100755
index 0000000..622fca1
--- /dev/null
+++ b/scripts/get_clang_version.py
@@ -0,0 +1,46 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2021 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""A tool to report the current clang version used during build"""
+
+import os
+import re
+import sys
+
+
+ANDROID_BUILD_TOP = os.environ.get("ANDROID_BUILD_TOP", ".")
+
+def get_clang_prebuilts_version(global_go):
+ # TODO(b/187231324): Get clang version from the json file once it is no longer
+ # hard-coded in global.go
+ if global_go is None:
+ global_go = ANDROID_BUILD_TOP + '/build/soong/cc/config/global.go'
+ with open(global_go) as infile:
+ contents = infile.read()
+
+ regex_rev = r'\tClangDefaultVersion\s+= "clang-(?P<rev>r\d+[a-z]?\d?)"'
+ match_rev = re.search(regex_rev, contents)
+ if match_rev is None:
+ raise RuntimeError('Parsing clang info failed')
+ return match_rev.group('rev')
+
+
+def main():
+ global_go = sys.argv[1] if len(sys.argv) > 1 else None
+ print(get_clang_prebuilts_version(global_go));
+
+
+if __name__ == '__main__':
+ main()
diff --git a/scripts/get_clang_version_test.py b/scripts/get_clang_version_test.py
new file mode 100644
index 0000000..e57df6c
--- /dev/null
+++ b/scripts/get_clang_version_test.py
@@ -0,0 +1,32 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2021 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+"""Unit tests for get_clang_version.py."""
+
+import unittest
+
+import get_clang_version
+
+class GetClangVersionTest(unittest.TestCase):
+ """Unit tests for get_clang_version."""
+
+ def test_get_clang_version(self):
+ """Test parsing of clang prebuilts version."""
+ self.assertIsNotNone(get_clang_version.get_clang_prebuilts_version())
+
+
+if __name__ == '__main__':
+ unittest.main(verbosity=2)
diff --git a/sdk/cc_sdk_test.go b/sdk/cc_sdk_test.go
index 31555c0..98697dc 100644
--- a/sdk/cc_sdk_test.go
+++ b/sdk/cc_sdk_test.go
@@ -2189,7 +2189,7 @@
result := testSdkWithCc(t, `
sdk {
name: "mysdk",
- native_shared_libs: ["sslnil", "sslempty", "sslnonempty"],
+ native_shared_libs: ["sslnil", "sslempty", "sslnonempty", "dslnil", "dslempty", "dslnonempty"],
}
cc_library {
@@ -2206,6 +2206,21 @@
name: "sslnonempty",
system_shared_libs: ["sslnil"],
}
+
+ cc_library {
+ name: "dslnil",
+ host_supported: true,
+ }
+
+ cc_library {
+ name: "dslempty",
+ default_shared_libs: [],
+ }
+
+ cc_library {
+ name: "dslnonempty",
+ default_shared_libs: ["sslnil"],
+ }
`)
CheckSnapshot(t, result, "mysdk", "",
@@ -2261,13 +2276,62 @@
},
},
}
-`))
+
+cc_prebuilt_library_shared {
+ name: "dslnil",
+ prefer: false,
+ visibility: ["//visibility:public"],
+ apex_available: ["//apex_available:platform"],
+ compile_multilib: "both",
+ arch: {
+ arm64: {
+ srcs: ["arm64/lib/dslnil.so"],
+ },
+ arm: {
+ srcs: ["arm/lib/dslnil.so"],
+ },
+ },
+}
+
+cc_prebuilt_library_shared {
+ name: "dslempty",
+ prefer: false,
+ visibility: ["//visibility:public"],
+ apex_available: ["//apex_available:platform"],
+ compile_multilib: "both",
+ default_shared_libs: [],
+ arch: {
+ arm64: {
+ srcs: ["arm64/lib/dslempty.so"],
+ },
+ arm: {
+ srcs: ["arm/lib/dslempty.so"],
+ },
+ },
+}
+
+cc_prebuilt_library_shared {
+ name: "dslnonempty",
+ prefer: false,
+ visibility: ["//visibility:public"],
+ apex_available: ["//apex_available:platform"],
+ compile_multilib: "both",
+ default_shared_libs: ["sslnil"],
+ arch: {
+ arm64: {
+ srcs: ["arm64/lib/dslnonempty.so"],
+ },
+ arm: {
+ srcs: ["arm/lib/dslnonempty.so"],
+ },
+ },
+}`))
result = testSdkWithCc(t, `
sdk {
name: "mysdk",
host_supported: true,
- native_shared_libs: ["sslvariants"],
+ native_shared_libs: ["sslvariants", "dslvariants"],
}
cc_library {
@@ -2279,6 +2343,16 @@
},
},
}
+
+ cc_library {
+ name: "dslvariants",
+ host_supported: true,
+ target: {
+ android: {
+ default_shared_libs: [],
+ },
+ },
+ }
`)
CheckSnapshot(t, result, "mysdk", "",
@@ -2315,6 +2389,37 @@
},
},
}
+
+cc_prebuilt_library_shared {
+ name: "dslvariants",
+ prefer: false,
+ visibility: ["//visibility:public"],
+ apex_available: ["//apex_available:platform"],
+ host_supported: true,
+ compile_multilib: "both",
+ target: {
+ host: {
+ enabled: false,
+ },
+ android: {
+ default_shared_libs: [],
+ },
+ android_arm64: {
+ srcs: ["android/arm64/lib/dslvariants.so"],
+ },
+ android_arm: {
+ srcs: ["android/arm/lib/dslvariants.so"],
+ },
+ linux_glibc_x86_64: {
+ enabled: true,
+ srcs: ["linux_glibc/x86_64/lib/dslvariants.so"],
+ },
+ linux_glibc_x86: {
+ enabled: true,
+ srcs: ["linux_glibc/x86/lib/dslvariants.so"],
+ },
+ },
+}
`),
checkVersionedAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
@@ -2351,11 +2456,46 @@
},
}
+cc_prebuilt_library_shared {
+ name: "mysdk_dslvariants@current",
+ sdk_member_name: "dslvariants",
+ visibility: ["//visibility:public"],
+ apex_available: ["//apex_available:platform"],
+ host_supported: true,
+ installable: false,
+ compile_multilib: "both",
+ target: {
+ host: {
+ enabled: false,
+ },
+ android: {
+ default_shared_libs: [],
+ },
+ android_arm64: {
+ srcs: ["android/arm64/lib/dslvariants.so"],
+ },
+ android_arm: {
+ srcs: ["android/arm/lib/dslvariants.so"],
+ },
+ linux_glibc_x86_64: {
+ enabled: true,
+ srcs: ["linux_glibc/x86_64/lib/dslvariants.so"],
+ },
+ linux_glibc_x86: {
+ enabled: true,
+ srcs: ["linux_glibc/x86/lib/dslvariants.so"],
+ },
+ },
+}
+
sdk_snapshot {
name: "mysdk@current",
visibility: ["//visibility:public"],
host_supported: true,
- native_shared_libs: ["mysdk_sslvariants@current"],
+ native_shared_libs: [
+ "mysdk_sslvariants@current",
+ "mysdk_dslvariants@current",
+ ],
target: {
host: {
enabled: false,
diff --git a/sh/sh_binary.go b/sh/sh_binary.go
index 4805846..1647428 100644
--- a/sh/sh_binary.go
+++ b/sh/sh_binary.go
@@ -495,6 +495,10 @@
module := &ShTest{}
InitShBinaryModule(&module.ShBinary)
module.AddProperties(&module.testProperties)
+ // Default sh_test_host to unit_tests = true
+ if module.testProperties.Test_options.Unit_test == nil {
+ module.testProperties.Test_options.Unit_test = proptools.BoolPtr(true)
+ }
android.InitAndroidArchModule(module, android.HostSupported, android.MultilibFirst)
return module
diff --git a/tests/bootstrap_test.sh b/tests/bootstrap_test.sh
index 8c8dc82..1258684 100755
--- a/tests/bootstrap_test.sh
+++ b/tests/bootstrap_test.sh
@@ -486,6 +486,39 @@
fi
}
+function test_write_to_source_tree {
+ setup
+ mkdir -p a
+ cat > a/Android.bp <<EOF
+genrule {
+ name: "write_to_source_tree",
+ out: ["write_to_source_tree"],
+ cmd: "touch file_in_source_tree && touch \$(out)",
+}
+EOF
+ readonly EXPECTED_OUT=out/soong/.intermediates/a/write_to_source_tree/gen/write_to_source_tree
+ readonly ERROR_LOG=${MOCK_TOP}/out/error.log
+ readonly ERROR_MSG="Read-only file system"
+ readonly ERROR_HINT_PATTERN="BUILD_BROKEN_SRC_DIR"
+ # Test in ReadOnly source tree
+ run_ninja BUILD_BROKEN_SRC_DIR_IS_WRITABLE=false ${EXPECTED_OUT} &> /dev/null && \
+ fail "Write to source tree should not work in a ReadOnly source tree"
+
+ if grep -q "${ERROR_MSG}" ${ERROR_LOG} && grep -q "${ERROR_HINT_PATTERN}" ${ERROR_LOG} ; then
+ echo Error message and error hint found in logs >/dev/null
+ else
+ fail "Did not find Read-only error AND error hint in error.log"
+ fi
+
+ # Test in ReadWrite source tree
+ run_ninja BUILD_BROKEN_SRC_DIR_IS_WRITABLE=true ${EXPECTED_OUT} &> /dev/null || \
+ fail "Write to source tree did not succeed in a ReadWrite source tree"
+
+ if grep -q "${ERROR_MSG}\|${ERROR_HINT_PATTERN}" ${ERROR_LOG} ; then
+ fail "Found read-only error OR error hint in error.log"
+ fi
+}
+
function test_bp2build_smoke {
setup
GENERATE_BAZEL_FILES=1 run_soong
@@ -692,6 +725,7 @@
test_glob_during_bootstrapping
test_soong_build_rerun_iff_environment_changes
test_dump_json_module_graph
+test_write_to_source_tree
test_bp2build_smoke
test_bp2build_generates_fake_ninja_file
test_bp2build_null_build
diff --git a/tests/lib.sh b/tests/lib.sh
index 35ccea9..f1e1efa 100644
--- a/tests/lib.sh
+++ b/tests/lib.sh
@@ -126,6 +126,10 @@
GENERATE_BAZEL_FILES=true build/soong/soong_ui.bash --make-mode --skip-ninja --skip-make --skip-soong-tests nothing
}
+run_ninja() {
+ build/soong/soong_ui.bash --make-mode --skip-make --skip-soong-tests "$@"
+}
+
info "Starting Soong integration test suite $(basename $0)"
info "Mock top: $MOCK_TOP"
diff --git a/ui/build/build.go b/ui/build/build.go
index 1187aa2..1ed9014 100644
--- a/ui/build/build.go
+++ b/ui/build/build.go
@@ -28,16 +28,20 @@
func SetupOutDir(ctx Context, config Config) {
ensureEmptyFileExists(ctx, filepath.Join(config.OutDir(), "Android.mk"))
ensureEmptyFileExists(ctx, filepath.Join(config.OutDir(), "CleanSpec.mk"))
- if !config.SkipKati() {
- // Run soong_build with Kati for a hybrid build, e.g. running the
- // AndroidMk singleton and postinstall commands. Communicate this to
- // soong_build by writing an empty .soong.kati_enabled marker file in the
- // soong_build output directory for the soong_build primary builder to
- // know if the user wants to run Kati after.
- //
- // This does not preclude running Kati for *product configuration purposes*.
- ensureEmptyFileExists(ctx, filepath.Join(config.SoongOutDir(), ".soong.kati_enabled"))
+
+ // Potentially write a marker file for whether kati is enabled. This is used by soong_build to
+ // potentially run the AndroidMk singleton and postinstall commands.
+ // Note that the absence of the file does not not preclude running Kati for product
+ // configuration purposes.
+ katiEnabledMarker := filepath.Join(config.SoongOutDir(), ".soong.kati_enabled")
+ if config.SkipKatiNinja() {
+ os.Remove(katiEnabledMarker)
+ // Note that we can not remove the file for SkipKati builds yet -- some continuous builds
+ // --skip-make builds rely on kati targets being defined.
+ } else if !config.SkipKati() {
+ ensureEmptyFileExists(ctx, katiEnabledMarker)
}
+
// The ninja_build file is used by our buildbots to understand that the output
// can be parsed as ninja output.
ensureEmptyFileExists(ctx, filepath.Join(config.OutDir(), "ninja_build"))
diff --git a/ui/build/config.go b/ui/build/config.go
index 4806721..7370627 100644
--- a/ui/build/config.go
+++ b/ui/build/config.go
@@ -161,6 +161,10 @@
ret.distDir = filepath.Join(ret.OutDir(), "dist")
}
+ if srcDirIsWritable, ok := ret.environ.Get("BUILD_BROKEN_SRC_DIR_IS_WRITABLE"); ok {
+ ret.sandboxConfig.SetSrcDirIsRO(srcDirIsWritable == "false")
+ }
+
ret.environ.Unset(
// We're already using it
"USE_SOONG_UI",
diff --git a/ui/build/sandbox_linux.go b/ui/build/sandbox_linux.go
index b0a6748..5b2046e 100644
--- a/ui/build/sandbox_linux.go
+++ b/ui/build/sandbox_linux.go
@@ -97,8 +97,11 @@
"-u", "nobody",
"-g", sandboxConfig.group,
"-R", "/",
- "-B", sandboxConfig.srcDir,
+ // Mount tmp before srcDir
+ // srcDir is /tmp/.* in integration tests, which is a child dir of /tmp
+ // nsjail throws an error if a child dir is mounted before its parent
"-B", "/tmp",
+ "-B", sandboxConfig.srcDir,
"-B", sandboxConfig.outDir,
}
diff --git a/ui/status/ninja.go b/ui/status/ninja.go
index 765679f..2445972 100644
--- a/ui/status/ninja.go
+++ b/ui/status/ninja.go
@@ -19,6 +19,8 @@
"fmt"
"io"
"os"
+ "regexp"
+ "strings"
"syscall"
"time"
@@ -158,9 +160,10 @@
err = fmt.Errorf("exited with code: %d", exitCode)
}
+ outputWithErrorHint := errorHintGenerator.GetOutputWithErrorHint(msg.EdgeFinished.GetOutput(), exitCode)
n.status.FinishAction(ActionResult{
Action: started,
- Output: msg.EdgeFinished.GetOutput(),
+ Output: outputWithErrorHint,
Error: err,
Stats: ActionResultStats{
UserTime: msg.EdgeFinished.GetUserTime(),
@@ -219,3 +222,53 @@
return ret, nil
}
+
+// key is pattern in stdout/stderr
+// value is error hint
+var allErrorHints = map[string]string{
+ "Read-only file system": `\nWrite to a read-only file system detected. Possible fixes include
+1. Generate file directly to out/ which is ReadWrite, #recommend solution
+2. BUILD_BROKEN_SRC_DIR_RW_ALLOWLIST := <my/path/1> <my/path/2> #discouraged, subset of source tree will be RW
+3. BUILD_BROKEN_SRC_DIR_IS_WRITABLE := true #highly discouraged, entire source tree will be RW
+`,
+}
+var errorHintGenerator = *newErrorHintGenerator(allErrorHints)
+
+type ErrorHintGenerator struct {
+ allErrorHints map[string]string
+ allErrorHintPatternsCompiled *regexp.Regexp
+}
+
+func newErrorHintGenerator(allErrorHints map[string]string) *ErrorHintGenerator {
+ var allErrorHintPatterns []string
+ for errorHintPattern, _ := range allErrorHints {
+ allErrorHintPatterns = append(allErrorHintPatterns, errorHintPattern)
+ }
+ allErrorHintPatternsRegex := strings.Join(allErrorHintPatterns[:], "|")
+ re := regexp.MustCompile(allErrorHintPatternsRegex)
+ return &ErrorHintGenerator{
+ allErrorHints: allErrorHints,
+ allErrorHintPatternsCompiled: re,
+ }
+}
+
+func (errorHintGenerator *ErrorHintGenerator) GetOutputWithErrorHint(rawOutput string, buildExitCode int) string {
+ if buildExitCode == 0 {
+ return rawOutput
+ }
+ errorHint := errorHintGenerator.getErrorHint(rawOutput)
+ if errorHint == nil {
+ return rawOutput
+ }
+ return rawOutput + *errorHint
+}
+
+// Returns the error hint corresponding to the FIRST match in raw output
+func (errorHintGenerator *ErrorHintGenerator) getErrorHint(rawOutput string) *string {
+ firstMatch := errorHintGenerator.allErrorHintPatternsCompiled.FindString(rawOutput)
+ if _, found := errorHintGenerator.allErrorHints[firstMatch]; found {
+ errorHint := errorHintGenerator.allErrorHints[firstMatch]
+ return &errorHint
+ }
+ return nil
+}
diff --git a/ui/status/ninja_test.go b/ui/status/ninja_test.go
index c400c97..f3638b3 100644
--- a/ui/status/ninja_test.go
+++ b/ui/status/ninja_test.go
@@ -43,3 +43,53 @@
t.Errorf("nr.Close timed out, %s > %s", g, w)
}
}
+
+// Test that error hint is added to output if available
+func TestNinjaReader_CorrectErrorHint(t *testing.T) {
+ errorPattern1 := "pattern-1 in input"
+ errorHint1 := "\n Fix by doing task 1"
+ errorPattern2 := "pattern-2 in input"
+ errorHint2 := "\n Fix by doing task 2"
+ mockErrorHints := make(map[string]string)
+ mockErrorHints[errorPattern1] = errorHint1
+ mockErrorHints[errorPattern2] = errorHint2
+
+ errorHintGenerator := *newErrorHintGenerator(mockErrorHints)
+ testCases := []struct {
+ rawOutput string
+ buildExitCode int
+ expectedFinalOutput string
+ testCaseErrorMessage string
+ }{
+ {
+ rawOutput: "ninja build was successful",
+ buildExitCode: 0,
+ expectedFinalOutput: "ninja build was successful",
+ testCaseErrorMessage: "raw output changed when build was successful",
+ },
+ {
+ rawOutput: "ninja build failed",
+ buildExitCode: 1,
+ expectedFinalOutput: "ninja build failed",
+ testCaseErrorMessage: "raw output changed even when no error hint pattern was found",
+ },
+ {
+ rawOutput: "ninja build failed: " + errorPattern1 + "some footnotes",
+ buildExitCode: 1,
+ expectedFinalOutput: "ninja build failed: " + errorPattern1 + "some footnotes" + errorHint1,
+ testCaseErrorMessage: "error hint not added despite pattern match",
+ },
+ {
+ rawOutput: "ninja build failed: " + errorPattern2 + errorPattern1,
+ buildExitCode: 1,
+ expectedFinalOutput: "ninja build failed: " + errorPattern2 + errorPattern1 + errorHint2,
+ testCaseErrorMessage: "error hint should be added for first pattern match in raw output",
+ },
+ }
+ for _, testCase := range testCases {
+ actualFinalOutput := errorHintGenerator.GetOutputWithErrorHint(testCase.rawOutput, testCase.buildExitCode)
+ if actualFinalOutput != testCase.expectedFinalOutput {
+ t.Errorf(testCase.testCaseErrorMessage+"\nexpected: %s\ngot: %s", testCase.expectedFinalOutput, actualFinalOutput)
+ }
+ }
+}