Merge "Correct global excludes not always being excluded"
diff --git a/android/allowlists/allowlists.go b/android/allowlists/allowlists.go
index 92e8854..0c1be6e 100644
--- a/android/allowlists/allowlists.go
+++ b/android/allowlists/allowlists.go
@@ -673,6 +673,9 @@
// kotlin srcs in java binary
"AnalyzerKt",
"trebuchet-core",
+
+ // kotlin srcs in android_library
+ "renderscript_toolkit",
}
Bp2buildModuleTypeAlwaysConvertList = []string{
diff --git a/android/bazel_handler.go b/android/bazel_handler.go
index 8d45041..4a495f0 100644
--- a/android/bazel_handler.go
+++ b/android/bazel_handler.go
@@ -233,27 +233,42 @@
}
func (m MockBazelContext) GetOutputFiles(label string, _ configKey) ([]string, error) {
- result, _ := m.LabelToOutputFiles[label]
+ result, ok := m.LabelToOutputFiles[label]
+ if !ok {
+ return []string{}, fmt.Errorf("no target with label %q in LabelToOutputFiles", label)
+ }
return result, nil
}
func (m MockBazelContext) GetCcInfo(label string, _ configKey) (cquery.CcInfo, error) {
- result, _ := m.LabelToCcInfo[label]
+ result, ok := m.LabelToCcInfo[label]
+ if !ok {
+ return cquery.CcInfo{}, fmt.Errorf("no target with label %q in LabelToCcInfo", label)
+ }
return result, nil
}
func (m MockBazelContext) GetPythonBinary(label string, _ configKey) (string, error) {
- result, _ := m.LabelToPythonBinary[label]
+ result, ok := m.LabelToPythonBinary[label]
+ if !ok {
+ return "", fmt.Errorf("no target with label %q in LabelToPythonBinary", label)
+ }
return result, nil
}
func (m MockBazelContext) GetApexInfo(label string, _ configKey) (cquery.ApexInfo, error) {
- result, _ := m.LabelToApexInfo[label]
+ result, ok := m.LabelToApexInfo[label]
+ if !ok {
+ return cquery.ApexInfo{}, fmt.Errorf("no target with label %q in LabelToApexInfo", label)
+ }
return result, nil
}
func (m MockBazelContext) GetCcUnstrippedInfo(label string, _ configKey) (cquery.CcUnstrippedInfo, error) {
- result, _ := m.LabelToCcBinary[label]
+ result, ok := m.LabelToCcBinary[label]
+ if !ok {
+ return cquery.CcUnstrippedInfo{}, fmt.Errorf("no target with label %q in LabelToCcBinary", label)
+ }
return result, nil
}
diff --git a/apex/apex.go b/apex/apex.go
index 9485a4b..ad7da27 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -1657,7 +1657,7 @@
return newApexFile(ctx, fileToCopy, androidMkModuleName, dirInApex, nativeSharedLib, rustm)
}
-func apexFileForPyBinary(ctx android.BaseModuleContext, py *python.Module) apexFile {
+func apexFileForPyBinary(ctx android.BaseModuleContext, py *python.PythonBinaryModule) apexFile {
dirInApex := "bin"
fileToCopy := py.HostToolPath().Path()
return newApexFile(ctx, fileToCopy, py.BaseModuleName(), dirInApex, pyBinary, py)
@@ -2147,7 +2147,7 @@
case *cc.Module:
vctx.filesInfo = append(vctx.filesInfo, apexFileForExecutable(ctx, ch))
return true // track transitive dependencies
- case *python.Module:
+ case *python.PythonBinaryModule:
if ch.HostToolPath().Valid() {
vctx.filesInfo = append(vctx.filesInfo, apexFileForPyBinary(ctx, ch))
}
diff --git a/apex/apex_test.go b/apex/apex_test.go
index 28097aa..395da95 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -3328,17 +3328,14 @@
// non-APEX variant does not have __ANDROID_APEX__ defined
mylibCFlags := ctx.ModuleForTests("mylib", "android_arm64_armv8-a_static").Rule("cc").Args["cFlags"]
ensureNotContains(t, mylibCFlags, "-D__ANDROID_APEX__")
- ensureNotContains(t, mylibCFlags, "-D__ANDROID_APEX_MIN_SDK_VERSION__")
- // APEX variant has __ANDROID_APEX__ and __ANDROID_APEX_SDK__ defined
+ // APEX variant has __ANDROID_APEX__ and __ANDROID_APEX__ defined
mylibCFlags = ctx.ModuleForTests("mylib", "android_arm64_armv8-a_static_apex10000").Rule("cc").Args["cFlags"]
ensureContains(t, mylibCFlags, "-D__ANDROID_APEX__")
- ensureContains(t, mylibCFlags, "-D__ANDROID_APEX_MIN_SDK_VERSION__=10000")
- // APEX variant has __ANDROID_APEX__ and __ANDROID_APEX_SDK__ defined
+ // APEX variant has __ANDROID_APEX__ and __ANDROID_APEX__ defined
mylibCFlags = ctx.ModuleForTests("mylib", "android_arm64_armv8-a_static_apex29").Rule("cc").Args["cFlags"]
ensureContains(t, mylibCFlags, "-D__ANDROID_APEX__")
- ensureContains(t, mylibCFlags, "-D__ANDROID_APEX_MIN_SDK_VERSION__=29")
// When a cc_library sets use_apex_name_macro: true each apex gets a unique variant and
// each variant defines additional macros to distinguish which apex variant it is built for
@@ -3347,19 +3344,17 @@
mylibCFlags = ctx.ModuleForTests("mylib3", "android_arm64_armv8-a_static").Rule("cc").Args["cFlags"]
ensureNotContains(t, mylibCFlags, "-D__ANDROID_APEX__")
- // recovery variant does not set __ANDROID_APEX_MIN_SDK_VERSION__
+ // recovery variant does not set __ANDROID_APEX__
mylibCFlags = ctx.ModuleForTests("mylib3", "android_recovery_arm64_armv8-a_static").Rule("cc").Args["cFlags"]
ensureNotContains(t, mylibCFlags, "-D__ANDROID_APEX__")
- ensureNotContains(t, mylibCFlags, "-D__ANDROID_APEX_MIN_SDK_VERSION__")
// non-APEX variant does not have __ANDROID_APEX__ defined
mylibCFlags = ctx.ModuleForTests("mylib2", "android_arm64_armv8-a_static").Rule("cc").Args["cFlags"]
ensureNotContains(t, mylibCFlags, "-D__ANDROID_APEX__")
- // recovery variant does not set __ANDROID_APEX_MIN_SDK_VERSION__
+ // recovery variant does not set __ANDROID_APEX__
mylibCFlags = ctx.ModuleForTests("mylib2", "android_recovery_arm64_armv8-a_static").Rule("cc").Args["cFlags"]
ensureNotContains(t, mylibCFlags, "-D__ANDROID_APEX__")
- ensureNotContains(t, mylibCFlags, "-D__ANDROID_APEX_MIN_SDK_VERSION__")
}
func TestHeaderLibsDependency(t *testing.T) {
diff --git a/bp2build/aar_conversion_test.go b/bp2build/aar_conversion_test.go
index 5f93eb7..0cda5dd 100644
--- a/bp2build/aar_conversion_test.go
+++ b/bp2build/aar_conversion_test.go
@@ -138,3 +138,36 @@
},
)
}
+
+func TestConvertAndroidLibraryKotlin(t *testing.T) {
+ t.Helper()
+ RunBp2BuildTestCase(t, func(ctx android.RegistrationContext) {}, Bp2buildTestCase{
+ Description: "Android Library with .kt srcs and common_srcs attribute",
+ ModuleTypeUnderTest: "android_library",
+ ModuleTypeUnderTestFactory: java.AndroidLibraryFactory,
+ Filesystem: map[string]string{
+ "AndroidManifest.xml": "",
+ },
+ Blueprint: `
+android_library {
+ name: "TestLib",
+ srcs: ["a.java", "b.kt"],
+ common_srcs: ["c.kt"],
+}
+`,
+ ExpectedBazelTargets: []string{
+ MakeBazelTarget(
+ "android_library",
+ "TestLib",
+ AttrNameToString{
+ "srcs": `[
+ "a.java",
+ "b.kt",
+ ]`,
+ "common_srcs": `["c.kt"]`,
+ "manifest": `"AndroidManifest.xml"`,
+ "resource_files": `[]`,
+ }),
+ MakeNeverlinkDuplicateTarget("android_library", "TestLib"),
+ }})
+}
diff --git a/bp2build/java_library_conversion_test.go b/bp2build/java_library_conversion_test.go
index 93a6174..0784f4b 100644
--- a/bp2build/java_library_conversion_test.go
+++ b/bp2build/java_library_conversion_test.go
@@ -715,3 +715,43 @@
},
})
}
+
+func TestJavaLibraryArchVariantLibs(t *testing.T) {
+ runJavaLibraryTestCase(t, Bp2buildTestCase{
+ Description: "java_library with arch variant libs",
+ Blueprint: `java_library {
+ name: "java-lib-1",
+ srcs: ["a.java"],
+ libs: ["java-lib-2"],
+ target: {
+ android: {
+ libs: ["java-lib-3"],
+ },
+ },
+ bazel_module: { bp2build_available: true },
+}
+
+ java_library{
+ name: "java-lib-2",
+}
+
+ java_library{
+ name: "java-lib-3",
+}
+`,
+ ExpectedBazelTargets: []string{
+ MakeBazelTarget("java_library", "java-lib-1", AttrNameToString{
+ "srcs": `["a.java"]`,
+ "deps": `[":java-lib-2-neverlink"] + select({
+ "//build/bazel/platforms/os:android": [":java-lib-3-neverlink"],
+ "//conditions:default": [],
+ })`,
+ }),
+ MakeNeverlinkDuplicateTarget("java_library", "java-lib-1"),
+ MakeBazelTarget("java_library", "java-lib-2", AttrNameToString{}),
+ MakeNeverlinkDuplicateTarget("java_library", "java-lib-2"),
+ MakeBazelTarget("java_library", "java-lib-3", AttrNameToString{}),
+ MakeNeverlinkDuplicateTarget("java_library", "java-lib-3"),
+ },
+ })
+}
diff --git a/cc/builder.go b/cc/builder.go
index 0629406..fef00d4 100644
--- a/cc/builder.go
+++ b/cc/builder.go
@@ -519,6 +519,13 @@
cppflags += " ${config.NoOverrideGlobalCflags}"
toolingCppflags += " ${config.NoOverrideGlobalCflags}"
+ if flags.toolchain.Is64Bit() {
+ cflags += " ${config.NoOverride64GlobalCflags}"
+ toolingCflags += " ${config.NoOverride64GlobalCflags}"
+ cppflags += " ${config.NoOverride64GlobalCflags}"
+ toolingCppflags += " ${config.NoOverride64GlobalCflags}"
+ }
+
modulePath := android.PathForModuleSrc(ctx).String()
if android.IsThirdPartyPath(modulePath) {
cflags += " ${config.NoOverrideExternalGlobalCflags}"
diff --git a/cc/cc_test.go b/cc/cc_test.go
index 6dfd395..8293f2d 100644
--- a/cc/cc_test.go
+++ b/cc/cc_test.go
@@ -4483,6 +4483,39 @@
}
+func TestAddnoOverride64GlobalCflags(t *testing.T) {
+ t.Parallel()
+ ctx := testCc(t, `
+ cc_library_shared {
+ name: "libclient",
+ srcs: ["foo.c"],
+ shared_libs: ["libfoo#1"],
+ }
+
+ cc_library_shared {
+ name: "libfoo",
+ srcs: ["foo.c"],
+ shared_libs: ["libbar"],
+ export_shared_lib_headers: ["libbar"],
+ stubs: {
+ symbol_file: "foo.map.txt",
+ versions: ["1", "2", "3"],
+ },
+ }
+
+ cc_library_shared {
+ name: "libbar",
+ export_include_dirs: ["include/libbar"],
+ srcs: ["foo.c"],
+ }`)
+
+ cFlags := ctx.ModuleForTests("libclient", "android_arm64_armv8-a_shared").Rule("cc").Args["cFlags"]
+
+ if !strings.Contains(cFlags, "${config.NoOverride64GlobalCflags}") {
+ t.Errorf("expected %q in cflags, got %q", "${config.NoOverride64GlobalCflags}", cFlags)
+ }
+}
+
func TestCcBuildBrokenClangProperty(t *testing.T) {
t.Parallel()
tests := []struct {
diff --git a/cc/compiler.go b/cc/compiler.go
index a751754..88985b6 100644
--- a/cc/compiler.go
+++ b/cc/compiler.go
@@ -416,11 +416,6 @@
if ctx.apexVariationName() != "" {
flags.Global.CommonFlags = append(flags.Global.CommonFlags, "-D__ANDROID_APEX__")
- if ctx.Device() {
- flags.Global.CommonFlags = append(flags.Global.CommonFlags,
- fmt.Sprintf("-D__ANDROID_APEX_MIN_SDK_VERSION__=%d",
- ctx.apexSdkVersion().FinalOrFutureInt()))
- }
}
if ctx.Target().NativeBridge == android.NativeBridgeEnabled {
diff --git a/cc/config/global.go b/cc/config/global.go
index 811e86e..2205c9e 100644
--- a/cc/config/global.go
+++ b/cc/config/global.go
@@ -247,6 +247,8 @@
"-Wno-error=enum-constexpr-conversion", // http://b/243964282
}
+ noOverride64GlobalCflags = []string{}
+
noOverrideExternalGlobalCflags = []string{
// http://b/148815709
"-Wno-sizeof-array-div",
@@ -384,12 +386,26 @@
return strings.Join(deviceGlobalCflags, " ")
})
- // Export the static default NoOverrideGlobalCflags to Bazel.
+ // Export the static default NoOverrideGlobalCflags and NoOverride64GlobalCflags to Bazel.
exportedVars.ExportStringList("NoOverrideGlobalCflags", noOverrideGlobalCflags)
+ exportedVars.ExportStringList("NoOverride64GlobalCflags", noOverride64GlobalCflags)
pctx.VariableFunc("NoOverrideGlobalCflags", func(ctx android.PackageVarContext) string {
flags := noOverrideGlobalCflags
if ctx.Config().IsEnvTrue("LLVM_NEXT") {
flags = append(noOverrideGlobalCflags, llvmNextExtraCommonGlobalCflags...)
+ if ctx.Config().Android64() {
+ flags = append(noOverride64GlobalCflags)
+ }
+ }
+ return strings.Join(flags, " ")
+ })
+
+ // Export the static default NoOverride64GlobalCflags to Bazel.
+ exportedVars.ExportStringList("NoOverride64GlobalCflags", noOverride64GlobalCflags)
+ pctx.VariableFunc("NoOverride64GlobalCflags", func(ctx android.PackageVarContext) string {
+ flags := noOverride64GlobalCflags
+ if ctx.Config().IsEnvTrue("LLVM_NEXT") && ctx.Config().Android64() {
+ flags = append(noOverride64GlobalCflags, llvmNextExtraCommonGlobalCflags...)
}
return strings.Join(flags, " ")
})
diff --git a/cc/makevars.go b/cc/makevars.go
index c70d4a6..6c3f551 100644
--- a/cc/makevars.go
+++ b/cc/makevars.go
@@ -93,6 +93,7 @@
ctx.Strict("CLANG_EXTERNAL_CFLAGS", "${config.ExternalCflags}")
ctx.Strict("GLOBAL_CLANG_CFLAGS_NO_OVERRIDE", "${config.NoOverrideGlobalCflags}")
+ ctx.Strict("GLOBAL_CLANG_CFLAGS_64_NO_OVERRIDE", "${config.NoOverride64GlobalCflags}")
ctx.Strict("GLOBAL_CLANG_CPPFLAGS_NO_OVERRIDE", "")
ctx.Strict("GLOBAL_CLANG_EXTERNAL_CFLAGS_NO_OVERRIDE", "${config.NoOverrideExternalGlobalCflags}")
diff --git a/java/aar.go b/java/aar.go
index 58b72ab..a483e13 100644
--- a/java/aar.go
+++ b/java/aar.go
@@ -651,6 +651,8 @@
// Functionality common to Module and Import.
embeddableInModuleAndImport
+ providesTransitiveHeaderJars
+
properties AARImportProperties
classpathFile android.WritablePath
@@ -897,8 +899,11 @@
a.assetsPackage = mergedAssets
}
+ a.collectTransitiveHeaderJars(ctx)
ctx.SetProvider(JavaInfoProvider, JavaInfo{
HeaderJars: android.PathsIfNonNil(a.classpathFile),
+ TransitiveLibsHeaderJars: a.transitiveLibsHeaderJars,
+ TransitiveStaticLibsHeaderJars: a.transitiveStaticLibsHeaderJars,
ImplementationAndResourcesJars: android.PathsIfNonNil(a.classpathFile),
ImplementationJars: android.PathsIfNonNil(a.classpathFile),
})
@@ -1069,6 +1074,10 @@
ctx.ModuleErrorf("Module has direct dependencies but no sources. Bazel will not allow this.")
}
+ if len(a.properties.Common_srcs) != 0 {
+ commonAttrs.Common_srcs = bazel.MakeLabelListAttribute(android.BazelLabelForModuleSrc(ctx, a.properties.Common_srcs))
+ }
+
name := a.Name()
props := bazel.BazelTargetModuleProperties{
Rule_class: "android_library",
diff --git a/java/app.go b/java/app.go
index 98c31bc..4d9c407 100755
--- a/java/app.go
+++ b/java/app.go
@@ -1312,6 +1312,9 @@
ctx.AddVariationDependencies(nil, usesLibCompat28OptTag, dexpreopt.OptionalCompatUsesLibs28...)
ctx.AddVariationDependencies(nil, usesLibCompat30OptTag, dexpreopt.OptionalCompatUsesLibs30...)
}
+ } else {
+ ctx.AddVariationDependencies(nil, r8LibraryJarTag, u.usesLibraryProperties.Uses_libs...)
+ ctx.AddVariationDependencies(nil, r8LibraryJarTag, u.presentOptionalUsesLibs(ctx)...)
}
}
diff --git a/java/base.go b/java/base.go
index 84fda37..cce06a4 100644
--- a/java/base.go
+++ b/java/base.go
@@ -1583,6 +1583,8 @@
ctx.SetProvider(JavaInfoProvider, JavaInfo{
HeaderJars: android.PathsIfNonNil(j.headerJarFile),
+ TransitiveLibsHeaderJars: j.transitiveLibsHeaderJars,
+ TransitiveStaticLibsHeaderJars: j.transitiveStaticLibsHeaderJars,
ImplementationAndResourcesJars: android.PathsIfNonNil(j.implementationAndResourcesJar),
ImplementationJars: android.PathsIfNonNil(j.implementationJarFile),
ResourceJars: android.PathsIfNonNil(j.resourceJar),
@@ -1719,6 +1721,52 @@
return instrumentedJar
}
+type providesTransitiveHeaderJars struct {
+ // set of header jars for all transitive libs deps
+ transitiveLibsHeaderJars *android.DepSet
+ // set of header jars for all transitive static libs deps
+ transitiveStaticLibsHeaderJars *android.DepSet
+}
+
+func (j *providesTransitiveHeaderJars) TransitiveLibsHeaderJars() *android.DepSet {
+ return j.transitiveLibsHeaderJars
+}
+
+func (j *providesTransitiveHeaderJars) TransitiveStaticLibsHeaderJars() *android.DepSet {
+ return j.transitiveStaticLibsHeaderJars
+}
+
+func (j *providesTransitiveHeaderJars) collectTransitiveHeaderJars(ctx android.ModuleContext) {
+ directLibs := android.Paths{}
+ directStaticLibs := android.Paths{}
+ transitiveLibs := []*android.DepSet{}
+ transitiveStaticLibs := []*android.DepSet{}
+ ctx.VisitDirectDeps(func(module android.Module) {
+ // don't add deps of the prebuilt version of the same library
+ if ctx.ModuleName() == android.RemoveOptionalPrebuiltPrefix(module.Name()) {
+ return
+ }
+
+ dep := ctx.OtherModuleProvider(module, JavaInfoProvider).(JavaInfo)
+ if dep.TransitiveLibsHeaderJars != nil {
+ transitiveLibs = append(transitiveLibs, dep.TransitiveLibsHeaderJars)
+ }
+ if dep.TransitiveStaticLibsHeaderJars != nil {
+ transitiveStaticLibs = append(transitiveStaticLibs, dep.TransitiveStaticLibsHeaderJars)
+ }
+
+ tag := ctx.OtherModuleDependencyTag(module)
+ _, isUsesLibDep := tag.(usesLibraryDependencyTag)
+ if tag == libTag || tag == r8LibraryJarTag || isUsesLibDep {
+ directLibs = append(directLibs, dep.HeaderJars...)
+ } else if tag == staticLibTag {
+ directStaticLibs = append(directStaticLibs, dep.HeaderJars...)
+ }
+ })
+ j.transitiveLibsHeaderJars = android.NewDepSet(android.POSTORDER, directLibs, transitiveLibs)
+ j.transitiveStaticLibsHeaderJars = android.NewDepSet(android.POSTORDER, directStaticLibs, transitiveStaticLibs)
+}
+
func (j *Module) HeaderJars() android.Paths {
if j.headerJarFile == nil {
return nil
@@ -1947,6 +1995,7 @@
sdkLinkType, _ := j.getSdkLinkType(ctx, ctx.ModuleName())
+ j.collectTransitiveHeaderJars(ctx)
ctx.VisitDirectDeps(func(module android.Module) {
otherName := ctx.OtherModuleName(module)
tag := ctx.OtherModuleDependencyTag(module)
diff --git a/java/dex.go b/java/dex.go
index 40ee99d..b6fe109 100644
--- a/java/dex.go
+++ b/java/dex.go
@@ -22,6 +22,7 @@
"github.com/google/blueprint/proptools"
"android/soong/android"
+ "android/soong/java/config"
"android/soong/remoteexec"
)
@@ -89,7 +90,10 @@
// list of extra proguard flag files
extraProguardFlagFiles android.Paths
proguardDictionary android.OptionalPath
+ proguardConfiguration android.OptionalPath
proguardUsageZip android.OptionalPath
+
+ providesTransitiveHeaderJars
}
func (d *dexer) effectiveOptimizeEnabled() bool {
@@ -130,17 +134,18 @@
var r8, r8RE = pctx.MultiCommandRemoteStaticRules("r8",
blueprint.RuleParams{
Command: `rm -rf "$outDir" && mkdir -p "$outDir" && ` +
- `rm -f "$outDict" && rm -rf "${outUsageDir}" && ` +
+ `rm -f "$outDict" && rm -f "$outConfig" && rm -rf "${outUsageDir}" && ` +
`mkdir -p $$(dirname ${outUsage}) && ` +
`mkdir -p $$(dirname $tmpJar) && ` +
`${config.Zip2ZipCmd} -i $in -o $tmpJar -x '**/*.dex' && ` +
`$r8Template${config.R8Cmd} ${config.R8Flags} -injars $tmpJar --output $outDir ` +
`--no-data-resources ` +
`-printmapping ${outDict} ` +
+ `--pg-conf-output ${outConfig} ` +
`-printusage ${outUsage} ` +
`--deps-file ${out}.d ` +
`$r8Flags && ` +
- `touch "${outDict}" "${outUsage}" && ` +
+ `touch "${outDict}" "${outConfig}" "${outUsage}" && ` +
`${config.SoongZipCmd} -o ${outUsageZip} -C ${outUsageDir} -f ${outUsage} && ` +
`rm -rf ${outUsageDir} && ` +
`$zipTemplate${config.SoongZipCmd} $zipFlags -o $outDir/classes.dex.jar -C $outDir -f "$outDir/classes*.dex" && ` +
@@ -176,7 +181,7 @@
ExecStrategy: "${config.RER8ExecStrategy}",
Platform: map[string]string{remoteexec.PoolKey: "${config.REJavaPool}"},
},
- }, []string{"outDir", "outDict", "outUsage", "outUsageZip", "outUsageDir",
+ }, []string{"outDir", "outDict", "outConfig", "outUsage", "outUsageZip", "outUsageDir",
"r8Flags", "zipFlags", "tmpJar", "mergeZipsFlags"}, []string{"implicits"})
func (d *dexer) dexCommonFlags(ctx android.ModuleContext,
@@ -249,12 +254,37 @@
})
r8Flags = append(r8Flags, proguardRaiseDeps.FormJavaClassPath("-libraryjars"))
- r8Flags = append(r8Flags, flags.bootClasspath.FormJavaClassPath("-libraryjars"))
- r8Flags = append(r8Flags, flags.dexClasspath.FormJavaClassPath("-libraryjars"))
-
r8Deps = append(r8Deps, proguardRaiseDeps...)
+ r8Flags = append(r8Flags, flags.bootClasspath.FormJavaClassPath("-libraryjars"))
r8Deps = append(r8Deps, flags.bootClasspath...)
+ r8Flags = append(r8Flags, flags.dexClasspath.FormJavaClassPath("-libraryjars"))
r8Deps = append(r8Deps, flags.dexClasspath...)
+ r8Flags = append(r8Flags, flags.processorPath.FormJavaClassPath("-libraryjars"))
+ r8Deps = append(r8Deps, flags.processorPath...)
+
+ errorProneClasspath := classpath(android.PathsForSource(ctx, config.ErrorProneClasspath))
+ r8Flags = append(r8Flags, errorProneClasspath.FormJavaClassPath("-libraryjars"))
+ r8Deps = append(r8Deps, errorProneClasspath...)
+
+ transitiveStaticLibsLookupMap := map[android.Path]bool{}
+ if d.transitiveStaticLibsHeaderJars != nil {
+ for _, jar := range d.transitiveStaticLibsHeaderJars.ToList() {
+ transitiveStaticLibsLookupMap[jar] = true
+ }
+ }
+ transitiveHeaderJars := android.Paths{}
+ if d.transitiveLibsHeaderJars != nil {
+ for _, jar := range d.transitiveLibsHeaderJars.ToList() {
+ if _, ok := transitiveStaticLibsLookupMap[jar]; ok {
+ // don't include a lib if it is already packaged in the current JAR as a static lib
+ continue
+ }
+ transitiveHeaderJars = append(transitiveHeaderJars, jar)
+ }
+ }
+ transitiveClasspath := classpath(transitiveHeaderJars)
+ r8Flags = append(r8Flags, transitiveClasspath.FormJavaClassPath("-libraryjars"))
+ r8Deps = append(r8Deps, transitiveClasspath...)
flagFiles := android.Paths{
android.PathForSource(ctx, "build/make/core/proguard.flags"),
@@ -342,6 +372,8 @@
if useR8 {
proguardDictionary := android.PathForModuleOut(ctx, "proguard_dictionary")
d.proguardDictionary = android.OptionalPathForPath(proguardDictionary)
+ proguardConfiguration := android.PathForModuleOut(ctx, "proguard_configuration")
+ d.proguardConfiguration = android.OptionalPathForPath(proguardConfiguration)
proguardUsageDir := android.PathForModuleOut(ctx, "proguard_usage")
proguardUsage := proguardUsageDir.Join(ctx, ctx.Namespace().Path,
android.ModuleNameWithPossibleOverride(ctx), "unused.txt")
@@ -354,6 +386,7 @@
"r8Flags": strings.Join(append(commonFlags, r8Flags...), " "),
"zipFlags": zipFlags,
"outDict": proguardDictionary.String(),
+ "outConfig": proguardConfiguration.String(),
"outUsageDir": proguardUsageDir.String(),
"outUsage": proguardUsage.String(),
"outUsageZip": proguardUsageZip.String(),
diff --git a/java/dex_test.go b/java/dex_test.go
index fc6cd0f..dc85f9e 100644
--- a/java/dex_test.go
+++ b/java/dex_test.go
@@ -18,6 +18,8 @@
"testing"
"android/soong/android"
+
+ "github.com/google/blueprint/proptools"
)
func TestR8(t *testing.T) {
@@ -74,7 +76,7 @@
android.AssertStringDoesContain(t, "expected lib header jar in app r8 classpath",
appR8.Args["r8Flags"], libHeader.String())
- android.AssertStringDoesNotContain(t, "expected no static_lib header jar in app javac classpath",
+ android.AssertStringDoesNotContain(t, "expected no static_lib header jar in app r8 classpath",
appR8.Args["r8Flags"], staticLibHeader.String())
android.AssertStringDoesContain(t, "expected -ignorewarnings in app r8 flags",
appR8.Args["r8Flags"], "-ignorewarnings")
@@ -86,6 +88,174 @@
corePlatformAppR8.Args["r8Flags"], "--android-platform-build")
}
+func TestR8TransitiveDeps(t *testing.T) {
+ bp := `
+ override_android_app {
+ name: "override_app",
+ base: "app",
+ }
+
+ android_app {
+ name: "app",
+ srcs: ["foo.java"],
+ libs: [
+ "lib",
+ "uses_libs_dep_import",
+ ],
+ static_libs: [
+ "static_lib",
+ "repeated_dep",
+ ],
+ platform_apis: true,
+ }
+
+ java_library {
+ name: "static_lib",
+ srcs: ["foo.java"],
+ }
+
+ java_library {
+ name: "lib",
+ libs: [
+ "transitive_lib",
+ "repeated_dep",
+ "prebuilt_lib",
+ ],
+ static_libs: ["transitive_static_lib"],
+ srcs: ["foo.java"],
+ }
+
+ java_library {
+ name: "repeated_dep",
+ srcs: ["foo.java"],
+ }
+
+ java_library {
+ name: "transitive_static_lib",
+ srcs: ["foo.java"],
+ }
+
+ java_library {
+ name: "transitive_lib",
+ srcs: ["foo.java"],
+ libs: ["transitive_lib_2"],
+ }
+
+ java_library {
+ name: "transitive_lib_2",
+ srcs: ["foo.java"],
+ }
+
+ java_import {
+ name: "lib",
+ jars: ["lib.jar"],
+ }
+
+ java_library {
+ name: "uses_lib",
+ srcs: ["foo.java"],
+ }
+
+ java_library {
+ name: "optional_uses_lib",
+ srcs: ["foo.java"],
+ }
+
+ android_library {
+ name: "uses_libs_dep",
+ uses_libs: ["uses_lib"],
+ optional_uses_libs: ["optional_uses_lib"],
+ }
+
+ android_library_import {
+ name: "uses_libs_dep_import",
+ aars: ["aar.aar"],
+ static_libs: ["uses_libs_dep"],
+ }
+ `
+
+ testcases := []struct {
+ name string
+ unbundled bool
+ }{
+ {
+ name: "non-unbundled build",
+ unbundled: false,
+ },
+ {
+ name: "unbundled build",
+ unbundled: true,
+ },
+ }
+
+ for _, tc := range testcases {
+ t.Run(tc.name, func(t *testing.T) {
+ fixturePreparer := PrepareForTestWithJavaDefaultModulesWithoutFakeDex2oatd
+ if tc.unbundled {
+ fixturePreparer = android.GroupFixturePreparers(
+ fixturePreparer,
+ android.FixtureModifyProductVariables(
+ func(variables android.FixtureProductVariables) {
+ variables.Unbundled_build = proptools.BoolPtr(true)
+ },
+ ),
+ )
+ }
+ result := fixturePreparer.RunTestWithBp(t, bp)
+
+ getHeaderJar := func(name string) android.Path {
+ mod := result.ModuleForTests(name, "android_common")
+ return mod.Output("turbine-combined/" + name + ".jar").Output
+ }
+
+ appR8 := result.ModuleForTests("app", "android_common").Rule("r8")
+ overrideAppR8 := result.ModuleForTests("app", "android_common_override_app").Rule("r8")
+ appHeader := getHeaderJar("app")
+ overrideAppHeader := result.ModuleForTests("app", "android_common_override_app").Output("turbine-combined/app.jar").Output
+ libHeader := getHeaderJar("lib")
+ transitiveLibHeader := getHeaderJar("transitive_lib")
+ transitiveLib2Header := getHeaderJar("transitive_lib_2")
+ staticLibHeader := getHeaderJar("static_lib")
+ transitiveStaticLibHeader := getHeaderJar("transitive_static_lib")
+ repeatedDepHeader := getHeaderJar("repeated_dep")
+ usesLibHeader := getHeaderJar("uses_lib")
+ optionalUsesLibHeader := getHeaderJar("optional_uses_lib")
+ prebuiltLibHeader := result.ModuleForTests("prebuilt_lib", "android_common").Output("combined/lib.jar").Output
+
+ for _, rule := range []android.TestingBuildParams{appR8, overrideAppR8} {
+ android.AssertStringDoesNotContain(t, "expected no app header jar in app r8 classpath",
+ rule.Args["r8Flags"], appHeader.String())
+ android.AssertStringDoesNotContain(t, "expected no override_app header jar in app r8 classpath",
+ rule.Args["r8Flags"], overrideAppHeader.String())
+ android.AssertStringDoesContain(t, "expected transitive lib header jar in app r8 classpath",
+ rule.Args["r8Flags"], transitiveLibHeader.String())
+ android.AssertStringDoesContain(t, "expected transitive lib ^2 header jar in app r8 classpath",
+ rule.Args["r8Flags"], transitiveLib2Header.String())
+ android.AssertStringDoesContain(t, "expected lib header jar in app r8 classpath",
+ rule.Args["r8Flags"], libHeader.String())
+ android.AssertStringDoesContain(t, "expected uses_lib header jar in app r8 classpath",
+ rule.Args["r8Flags"], usesLibHeader.String())
+ android.AssertStringDoesContain(t, "expected optional_uses_lib header jar in app r8 classpath",
+ rule.Args["r8Flags"], optionalUsesLibHeader.String())
+ android.AssertStringDoesNotContain(t, "expected no static_lib header jar in app r8 classpath",
+ rule.Args["r8Flags"], staticLibHeader.String())
+ android.AssertStringDoesNotContain(t, "expected no transitive static_lib header jar in app r8 classpath",
+ rule.Args["r8Flags"], transitiveStaticLibHeader.String())
+ // we shouldn't list this dep because it is already included as static_libs in the app
+ android.AssertStringDoesNotContain(t, "expected no repeated_dep header jar in app r8 classpath",
+ rule.Args["r8Flags"], repeatedDepHeader.String())
+ // skip a prebuilt transitive dep if the source is also a transitive dep
+ android.AssertStringDoesNotContain(t, "expected no prebuilt header jar in app r8 classpath",
+ rule.Args["r8Flags"], prebuiltLibHeader.String())
+ android.AssertStringDoesContain(t, "expected -ignorewarnings in app r8 flags",
+ rule.Args["r8Flags"], "-ignorewarnings")
+ android.AssertStringDoesContain(t, "expected --android-platform-build in app r8 flags",
+ rule.Args["r8Flags"], "--android-platform-build")
+ }
+ })
+ }
+}
+
func TestR8Flags(t *testing.T) {
result := PrepareForTestWithJavaDefaultModulesWithoutFakeDex2oatd.RunTestWithBp(t, `
android_app {
diff --git a/java/java.go b/java/java.go
index d85f3e1..1907731 100644
--- a/java/java.go
+++ b/java/java.go
@@ -230,6 +230,12 @@
// against this module. If empty, ImplementationJars should be used instead.
HeaderJars android.Paths
+ // set of header jars for all transitive libs deps
+ TransitiveLibsHeaderJars *android.DepSet
+
+ // set of header jars for all transitive static libs deps
+ TransitiveStaticLibsHeaderJars *android.DepSet
+
// ImplementationAndResourceJars is a list of jars that contain the implementations of classes
// in the module as well as any resources included in the module.
ImplementationAndResourcesJars android.Paths
@@ -380,6 +386,7 @@
instrumentationForTag = dependencyTag{name: "instrumentation_for"}
extraLintCheckTag = dependencyTag{name: "extra-lint-check", toolchain: true}
jniLibTag = dependencyTag{name: "jnilib", runtimeLinked: true}
+ r8LibraryJarTag = dependencyTag{name: "r8-libraryjar", runtimeLinked: true}
syspropPublicStubDepTag = dependencyTag{name: "sysprop public stub"}
jniInstallTag = installDependencyTag{name: "jni install"}
binaryInstallTag = installDependencyTag{name: "binary install"}
@@ -1944,9 +1951,9 @@
var flags javaBuilderFlags
+ j.collectTransitiveHeaderJars(ctx)
ctx.VisitDirectDeps(func(module android.Module) {
tag := ctx.OtherModuleDependencyTag(module)
-
if ctx.OtherModuleHasProvider(module, JavaInfoProvider) {
dep := ctx.OtherModuleProvider(module, JavaInfoProvider).(JavaInfo)
switch tag {
@@ -2036,6 +2043,8 @@
ctx.SetProvider(JavaInfoProvider, JavaInfo{
HeaderJars: android.PathsIfNonNil(j.combinedClasspathFile),
+ TransitiveLibsHeaderJars: j.transitiveLibsHeaderJars,
+ TransitiveStaticLibsHeaderJars: j.transitiveStaticLibsHeaderJars,
ImplementationAndResourcesJars: android.PathsIfNonNil(j.combinedClasspathFile),
ImplementationJars: android.PathsIfNonNil(j.combinedClasspathFile),
AidlIncludeDirs: j.exportAidlIncludeDirs,
@@ -2586,7 +2595,7 @@
// to be returned to the calling function.
func (m *Library) convertLibraryAttrsBp2Build(ctx android.TopDownMutatorContext) (*javaCommonAttributes, *bp2BuildJavaInfo) {
var srcs bazel.LabelListAttribute
- var deps bazel.LabelList
+ var deps bazel.LabelListAttribute
var staticDeps bazel.LabelList
archVariantProps := m.GetArchVariantProperties(ctx, &CommonProperties{})
@@ -2692,11 +2701,17 @@
Javacopts: bazel.MakeStringListAttribute(javacopts),
}
- if m.properties.Libs != nil {
- for _, d := range m.properties.Libs {
- neverlinkLabel := android.BazelLabelForModuleDepSingle(ctx, d)
- neverlinkLabel.Label = neverlinkLabel.Label + "-neverlink"
- deps.Add(&neverlinkLabel)
+ for axis, configToProps := range archVariantProps {
+ for config, _props := range configToProps {
+ if archProps, ok := _props.(*CommonProperties); ok {
+ var libLabels []bazel.Label
+ for _, d := range archProps.Libs {
+ neverlinkLabel := android.BazelLabelForModuleDepSingle(ctx, d)
+ neverlinkLabel.Label = neverlinkLabel.Label + "-neverlink"
+ libLabels = append(libLabels, neverlinkLabel)
+ }
+ deps.SetSelectValue(axis, config, bazel.MakeLabelList(libLabels))
+ }
}
}
@@ -2714,7 +2729,7 @@
staticDeps.Add(protoDepLabel)
depLabels := &javaDependencyLabels{}
- depLabels.Deps = bazel.MakeLabelListAttribute(deps)
+ depLabels.Deps = deps
depLabels.StaticDeps = bazel.MakeLabelListAttribute(staticDeps)
bp2BuildInfo := &bp2BuildJavaInfo{
diff --git a/java/kotlin_test.go b/java/kotlin_test.go
index 491ce29..933fc51 100644
--- a/java/kotlin_test.go
+++ b/java/kotlin_test.go
@@ -44,6 +44,10 @@
kotlinStdlib := ctx.ModuleForTests("kotlin-stdlib", "android_common").
Output("turbine-combined/kotlin-stdlib.jar").Output
+ kotlinStdlibJdk7 := ctx.ModuleForTests("kotlin-stdlib-jdk7", "android_common").
+ Output("turbine-combined/kotlin-stdlib-jdk7.jar").Output
+ kotlinStdlibJdk8 := ctx.ModuleForTests("kotlin-stdlib-jdk8", "android_common").
+ Output("turbine-combined/kotlin-stdlib-jdk8.jar").Output
kotlinAnnotations := ctx.ModuleForTests("kotlin-annotations", "android_common").
Output("turbine-combined/kotlin-annotations.jar").Output
@@ -79,6 +83,16 @@
fooJar.Inputs.Strings(), kotlinStdlib.String())
}
+ if !inList(kotlinStdlibJdk7.String(), fooJar.Inputs.Strings()) {
+ t.Errorf("foo jar inputs %v does not contain %v",
+ fooJar.Inputs.Strings(), kotlinStdlibJdk7.String())
+ }
+
+ if !inList(kotlinStdlibJdk8.String(), fooJar.Inputs.Strings()) {
+ t.Errorf("foo jar inputs %v does not contain %v",
+ fooJar.Inputs.Strings(), kotlinStdlibJdk8.String())
+ }
+
if !inList(kotlinAnnotations.String(), fooJar.Inputs.Strings()) {
t.Errorf("foo jar inputs %v does not contain %v",
fooJar.Inputs.Strings(), kotlinAnnotations.String())
diff --git a/python/Android.bp b/python/Android.bp
index e49fa6a..4584f1e 100644
--- a/python/Android.bp
+++ b/python/Android.bp
@@ -11,11 +11,10 @@
"soong-tradefed",
],
srcs: [
- "androidmk.go",
"binary.go",
+ "bp2build.go",
"builder.go",
"defaults.go",
- "installer.go",
"library.go",
"proto.go",
"python.go",
diff --git a/python/androidmk.go b/python/androidmk.go
deleted file mode 100644
index 7dc4713..0000000
--- a/python/androidmk.go
+++ /dev/null
@@ -1,90 +0,0 @@
-// Copyright 2017 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 python
-
-import (
- "path/filepath"
- "strings"
-
- "android/soong/android"
-)
-
-type subAndroidMkProvider interface {
- AndroidMk(*Module, *android.AndroidMkEntries)
-}
-
-func (p *Module) subAndroidMk(entries *android.AndroidMkEntries, obj interface{}) {
- if p.subAndroidMkOnce == nil {
- p.subAndroidMkOnce = make(map[subAndroidMkProvider]bool)
- }
- if androidmk, ok := obj.(subAndroidMkProvider); ok {
- if !p.subAndroidMkOnce[androidmk] {
- p.subAndroidMkOnce[androidmk] = true
- androidmk.AndroidMk(p, entries)
- }
- }
-}
-
-func (p *Module) AndroidMkEntries() []android.AndroidMkEntries {
- entries := android.AndroidMkEntries{OutputFile: p.installSource}
-
- p.subAndroidMk(&entries, p.installer)
-
- return []android.AndroidMkEntries{entries}
-}
-
-func (p *binaryDecorator) AndroidMk(base *Module, entries *android.AndroidMkEntries) {
- entries.Class = "EXECUTABLES"
-
- entries.ExtraEntries = append(entries.ExtraEntries,
- func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
- entries.AddCompatibilityTestSuites(p.binaryProperties.Test_suites...)
- })
- base.subAndroidMk(entries, p.pythonInstaller)
-}
-
-func (p *testDecorator) AndroidMk(base *Module, entries *android.AndroidMkEntries) {
- entries.Class = "NATIVE_TESTS"
-
- entries.ExtraEntries = append(entries.ExtraEntries,
- func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
- entries.AddCompatibilityTestSuites(p.binaryDecorator.binaryProperties.Test_suites...)
- if p.testConfig != nil {
- entries.SetString("LOCAL_FULL_TEST_CONFIG", p.testConfig.String())
- }
-
- entries.SetBoolIfTrue("LOCAL_DISABLE_AUTO_GENERATE_TEST_CONFIG", !BoolDefault(p.binaryProperties.Auto_gen_config, true))
-
- entries.AddStrings("LOCAL_TEST_DATA", android.AndroidMkDataPaths(p.data)...)
-
- p.testProperties.Test_options.SetAndroidMkEntries(entries)
- })
- base.subAndroidMk(entries, p.binaryDecorator.pythonInstaller)
-}
-
-func (installer *pythonInstaller) AndroidMk(base *Module, entries *android.AndroidMkEntries) {
- entries.Required = append(entries.Required, "libc++")
- entries.ExtraEntries = append(entries.ExtraEntries,
- func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
- path, file := filepath.Split(installer.path.String())
- stem := strings.TrimSuffix(file, filepath.Ext(file))
-
- entries.SetString("LOCAL_MODULE_SUFFIX", filepath.Ext(file))
- entries.SetString("LOCAL_MODULE_PATH", path)
- entries.SetString("LOCAL_MODULE_STEM", stem)
- entries.AddStrings("LOCAL_SHARED_LIBRARIES", installer.androidMkSharedLibs...)
- entries.SetBool("LOCAL_CHECK_ELF_FILES", false)
- })
-}
diff --git a/python/binary.go b/python/binary.go
index 670e0d3..95eb2c6 100644
--- a/python/binary.go
+++ b/python/binary.go
@@ -18,11 +18,12 @@
import (
"fmt"
+ "path/filepath"
+ "strings"
+
+ "github.com/google/blueprint"
"android/soong/android"
- "android/soong/bazel"
-
- "github.com/google/blueprint/proptools"
)
func init() {
@@ -33,63 +34,6 @@
ctx.RegisterModuleType("python_binary_host", PythonBinaryHostFactory)
}
-type bazelPythonBinaryAttributes struct {
- Main *bazel.Label
- Srcs bazel.LabelListAttribute
- Deps bazel.LabelListAttribute
- Python_version *string
- Imports bazel.StringListAttribute
-}
-
-func pythonBinaryBp2Build(ctx android.TopDownMutatorContext, m *Module) {
- // TODO(b/182306917): this doesn't fully handle all nested props versioned
- // by the python version, which would have been handled by the version split
- // mutator. This is sufficient for very simple python_binary_host modules
- // under Bionic.
- py3Enabled := proptools.BoolDefault(m.properties.Version.Py3.Enabled, false)
- py2Enabled := proptools.BoolDefault(m.properties.Version.Py2.Enabled, false)
- var python_version *string
- if py3Enabled && py2Enabled {
- panic(fmt.Errorf(
- "error for '%s' module: bp2build's python_binary_host converter does not support "+
- "converting a module that is enabled for both Python 2 and 3 at the same time.", m.Name()))
- } else if py2Enabled {
- python_version = &pyVersion2
- } else {
- // do nothing, since python_version defaults to PY3.
- }
-
- baseAttrs := m.makeArchVariantBaseAttributes(ctx)
- attrs := &bazelPythonBinaryAttributes{
- Main: nil,
- Srcs: baseAttrs.Srcs,
- Deps: baseAttrs.Deps,
- Python_version: python_version,
- Imports: baseAttrs.Imports,
- }
-
- for _, propIntf := range m.GetProperties() {
- if props, ok := propIntf.(*BinaryProperties); ok {
- // main is optional.
- if props.Main != nil {
- main := android.BazelLabelForModuleSrcSingle(ctx, *props.Main)
- attrs.Main = &main
- break
- }
- }
- }
-
- props := bazel.BazelTargetModuleProperties{
- // Use the native py_binary rule.
- Rule_class: "py_binary",
- }
-
- ctx.CreateBazelTargetModule(props, android.CommonAttributes{
- Name: m.Name(),
- Data: baseAttrs.Data,
- }, attrs)
-}
-
type BinaryProperties struct {
// the name of the source file that is the main entry point of the program.
// this file must also be listed in srcs.
@@ -118,52 +62,61 @@
Auto_gen_config *bool
}
-type binaryDecorator struct {
+type PythonBinaryModule struct {
+ PythonLibraryModule
binaryProperties BinaryProperties
- *pythonInstaller
+ // (.intermediate) module output path as installation source.
+ installSource android.Path
+
+ // Final installation path.
+ installedDest android.Path
+
+ androidMkSharedLibs []string
}
+var _ android.AndroidMkEntriesProvider = (*PythonBinaryModule)(nil)
+var _ android.Module = (*PythonBinaryModule)(nil)
+
type IntermPathProvider interface {
IntermPathForModuleOut() android.OptionalPath
}
-func NewBinary(hod android.HostOrDeviceSupported) (*Module, *binaryDecorator) {
- module := newModule(hod, android.MultilibFirst)
- decorator := &binaryDecorator{pythonInstaller: NewPythonInstaller("bin", "")}
-
- module.bootstrapper = decorator
- module.installer = decorator
-
- return module, decorator
+func NewBinary(hod android.HostOrDeviceSupported) *PythonBinaryModule {
+ return &PythonBinaryModule{
+ PythonLibraryModule: *newModule(hod, android.MultilibFirst),
+ }
}
func PythonBinaryHostFactory() android.Module {
- module, _ := NewBinary(android.HostSupported)
-
- android.InitBazelModule(module)
-
- return module.init()
+ return NewBinary(android.HostSupported).init()
}
-func (binary *binaryDecorator) autorun() bool {
- return BoolDefault(binary.binaryProperties.Autorun, true)
+func (p *PythonBinaryModule) init() android.Module {
+ p.AddProperties(&p.properties, &p.protoProperties)
+ p.AddProperties(&p.binaryProperties)
+ android.InitAndroidArchModule(p, p.hod, p.multilib)
+ android.InitDefaultableModule(p)
+ android.InitBazelModule(p)
+ return p
}
-func (binary *binaryDecorator) bootstrapperProps() []interface{} {
- return []interface{}{&binary.binaryProperties}
+func (p *PythonBinaryModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ p.PythonLibraryModule.GenerateAndroidBuildActions(ctx)
+ p.buildBinary(ctx)
+ p.installedDest = ctx.InstallFile(installDir(ctx, "bin", "", ""),
+ p.installSource.Base(), p.installSource)
}
-func (binary *binaryDecorator) bootstrap(ctx android.ModuleContext, actualVersion string,
- embeddedLauncher bool, srcsPathMappings []pathMapping, srcsZip android.Path,
- depsSrcsZips android.Paths) android.OptionalPath {
-
+func (p *PythonBinaryModule) buildBinary(ctx android.ModuleContext) {
+ depsSrcsZips := p.collectPathsFromTransitiveDeps(ctx)
main := ""
- if binary.autorun() {
- main = binary.getPyMainFile(ctx, srcsPathMappings)
+ if p.autorun() {
+ main = p.getPyMainFile(ctx, p.srcsPathMappings)
}
var launcherPath android.OptionalPath
+ embeddedLauncher := p.isEmbeddedLauncherEnabled()
if embeddedLauncher {
ctx.VisitDirectDepsWithTag(launcherTag, func(m android.Module) {
if provider, ok := m.(IntermPathProvider); ok {
@@ -175,15 +128,137 @@
}
})
}
- binFile := registerBuildActionForParFile(ctx, embeddedLauncher, launcherPath,
- binary.getHostInterpreterName(ctx, actualVersion),
- main, binary.getStem(ctx), append(android.Paths{srcsZip}, depsSrcsZips...))
+ p.installSource = registerBuildActionForParFile(ctx, embeddedLauncher, launcherPath,
+ p.getHostInterpreterName(ctx, p.properties.Actual_version),
+ main, p.getStem(ctx), append(android.Paths{p.srcsZip}, depsSrcsZips...))
- return android.OptionalPathForPath(binFile)
+ var sharedLibs []string
+ // if embedded launcher is enabled, we need to collect the shared library dependencies of the
+ // launcher
+ for _, dep := range ctx.GetDirectDepsWithTag(launcherSharedLibTag) {
+ sharedLibs = append(sharedLibs, ctx.OtherModuleName(dep))
+ }
+ p.androidMkSharedLibs = sharedLibs
+}
+
+func (p *PythonBinaryModule) AndroidMkEntries() []android.AndroidMkEntries {
+ entries := android.AndroidMkEntries{OutputFile: android.OptionalPathForPath(p.installSource)}
+
+ entries.Class = "EXECUTABLES"
+
+ entries.ExtraEntries = append(entries.ExtraEntries,
+ func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
+ entries.AddCompatibilityTestSuites(p.binaryProperties.Test_suites...)
+ })
+
+ entries.Required = append(entries.Required, "libc++")
+ entries.ExtraEntries = append(entries.ExtraEntries,
+ func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
+ path, file := filepath.Split(p.installedDest.String())
+ stem := strings.TrimSuffix(file, filepath.Ext(file))
+
+ entries.SetString("LOCAL_MODULE_SUFFIX", filepath.Ext(file))
+ entries.SetString("LOCAL_MODULE_PATH", path)
+ entries.SetString("LOCAL_MODULE_STEM", stem)
+ entries.AddStrings("LOCAL_SHARED_LIBRARIES", p.androidMkSharedLibs...)
+ entries.SetBool("LOCAL_CHECK_ELF_FILES", false)
+ })
+
+ return []android.AndroidMkEntries{entries}
+}
+
+func (p *PythonBinaryModule) DepsMutator(ctx android.BottomUpMutatorContext) {
+ p.PythonLibraryModule.DepsMutator(ctx)
+
+ versionVariation := []blueprint.Variation{
+ {"python_version", p.properties.Actual_version},
+ }
+
+ // If this module will be installed and has an embedded launcher, we need to add dependencies for:
+ // * standard library
+ // * launcher
+ // * shared dependencies of the launcher
+ if p.isEmbeddedLauncherEnabled() {
+ var stdLib string
+ var launcherModule string
+ // Add launcher shared lib dependencies. Ideally, these should be
+ // derived from the `shared_libs` property of the launcher. However, we
+ // cannot read the property at this stage and it will be too late to add
+ // dependencies later.
+ launcherSharedLibDeps := []string{
+ "libsqlite",
+ }
+ // Add launcher-specific dependencies for bionic
+ if ctx.Target().Os.Bionic() {
+ launcherSharedLibDeps = append(launcherSharedLibDeps, "libc", "libdl", "libm")
+ }
+ if ctx.Target().Os == android.LinuxMusl && !ctx.Config().HostStaticBinaries() {
+ launcherSharedLibDeps = append(launcherSharedLibDeps, "libc_musl")
+ }
+
+ switch p.properties.Actual_version {
+ case pyVersion2:
+ stdLib = "py2-stdlib"
+
+ launcherModule = "py2-launcher"
+ if p.autorun() {
+ launcherModule = "py2-launcher-autorun"
+ }
+
+ launcherSharedLibDeps = append(launcherSharedLibDeps, "libc++")
+
+ case pyVersion3:
+ stdLib = "py3-stdlib"
+
+ launcherModule = "py3-launcher"
+ if p.autorun() {
+ launcherModule = "py3-launcher-autorun"
+ }
+ if ctx.Config().HostStaticBinaries() && ctx.Target().Os == android.LinuxMusl {
+ launcherModule += "-static"
+ }
+
+ if ctx.Device() {
+ launcherSharedLibDeps = append(launcherSharedLibDeps, "liblog")
+ }
+ default:
+ panic(fmt.Errorf("unknown Python Actual_version: %q for module: %q.",
+ p.properties.Actual_version, ctx.ModuleName()))
+ }
+ ctx.AddVariationDependencies(versionVariation, pythonLibTag, stdLib)
+ ctx.AddFarVariationDependencies(ctx.Target().Variations(), launcherTag, launcherModule)
+ ctx.AddFarVariationDependencies(ctx.Target().Variations(), launcherSharedLibTag, launcherSharedLibDeps...)
+ }
+}
+
+// HostToolPath returns a path if appropriate such that this module can be used as a host tool,
+// fulfilling the android.HostToolProvider interface.
+func (p *PythonBinaryModule) HostToolPath() android.OptionalPath {
+ // TODO: This should only be set when building host binaries -- tests built for device would be
+ // setting this incorrectly.
+ return android.OptionalPathForPath(p.installedDest)
+}
+
+// OutputFiles returns output files based on given tag, returns an error if tag is unsupported.
+func (p *PythonBinaryModule) OutputFiles(tag string) (android.Paths, error) {
+ switch tag {
+ case "":
+ return android.Paths{p.installSource}, nil
+ default:
+ return nil, fmt.Errorf("unsupported module reference tag %q", tag)
+ }
+}
+
+func (p *PythonBinaryModule) isEmbeddedLauncherEnabled() bool {
+ return Bool(p.properties.Embedded_launcher)
+}
+
+func (b *PythonBinaryModule) autorun() bool {
+ return BoolDefault(b.binaryProperties.Autorun, true)
}
// get host interpreter name.
-func (binary *binaryDecorator) getHostInterpreterName(ctx android.ModuleContext,
+func (p *PythonBinaryModule) getHostInterpreterName(ctx android.ModuleContext,
actualVersion string) string {
var interp string
switch actualVersion {
@@ -200,13 +275,13 @@
}
// find main program path within runfiles tree.
-func (binary *binaryDecorator) getPyMainFile(ctx android.ModuleContext,
+func (p *PythonBinaryModule) getPyMainFile(ctx android.ModuleContext,
srcsPathMappings []pathMapping) string {
var main string
- if String(binary.binaryProperties.Main) == "" {
+ if String(p.binaryProperties.Main) == "" {
main = ctx.ModuleName() + pyExt
} else {
- main = String(binary.binaryProperties.Main)
+ main = String(p.binaryProperties.Main)
}
for _, path := range srcsPathMappings {
@@ -219,11 +294,21 @@
return ""
}
-func (binary *binaryDecorator) getStem(ctx android.ModuleContext) string {
+func (p *PythonBinaryModule) getStem(ctx android.ModuleContext) string {
stem := ctx.ModuleName()
- if String(binary.binaryProperties.Stem) != "" {
- stem = String(binary.binaryProperties.Stem)
+ if String(p.binaryProperties.Stem) != "" {
+ stem = String(p.binaryProperties.Stem)
}
- return stem + String(binary.binaryProperties.Suffix)
+ return stem + String(p.binaryProperties.Suffix)
+}
+
+func installDir(ctx android.ModuleContext, dir, dir64, relative string) android.InstallPath {
+ if ctx.Arch().ArchType.Multilib == "lib64" && dir64 != "" {
+ dir = dir64
+ }
+ if !ctx.Host() && ctx.Config().HasMultilibConflict(ctx.Arch().ArchType) {
+ dir = filepath.Join(dir, ctx.Arch().ArchType.String())
+ }
+ return android.PathForModuleInstall(ctx, dir, relative)
}
diff --git a/python/bp2build.go b/python/bp2build.go
new file mode 100644
index 0000000..bdac2dc
--- /dev/null
+++ b/python/bp2build.go
@@ -0,0 +1,226 @@
+// Copyright 2023 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 python
+
+import (
+ "fmt"
+ "path/filepath"
+ "strings"
+
+ "github.com/google/blueprint/proptools"
+
+ "android/soong/android"
+ "android/soong/bazel"
+)
+
+type bazelPythonLibraryAttributes struct {
+ Srcs bazel.LabelListAttribute
+ Deps bazel.LabelListAttribute
+ Imports bazel.StringListAttribute
+ Srcs_version *string
+}
+
+type bazelPythonProtoLibraryAttributes struct {
+ Deps bazel.LabelListAttribute
+}
+
+type baseAttributes struct {
+ // TODO(b/200311466): Probably not translate b/c Bazel has no good equiv
+ //Pkg_path bazel.StringAttribute
+ // TODO: Related to Pkg_bath and similarLy gated
+ //Is_internal bazel.BoolAttribute
+ // Combines Srcs and Exclude_srcs
+ Srcs bazel.LabelListAttribute
+ Deps bazel.LabelListAttribute
+ // Combines Data and Java_data (invariant)
+ Data bazel.LabelListAttribute
+ Imports bazel.StringListAttribute
+}
+
+func (m *PythonLibraryModule) makeArchVariantBaseAttributes(ctx android.TopDownMutatorContext) baseAttributes {
+ var attrs baseAttributes
+ archVariantBaseProps := m.GetArchVariantProperties(ctx, &BaseProperties{})
+ for axis, configToProps := range archVariantBaseProps {
+ for config, props := range configToProps {
+ if baseProps, ok := props.(*BaseProperties); ok {
+ attrs.Srcs.SetSelectValue(axis, config,
+ android.BazelLabelForModuleSrcExcludes(ctx, baseProps.Srcs, baseProps.Exclude_srcs))
+ attrs.Deps.SetSelectValue(axis, config,
+ android.BazelLabelForModuleDeps(ctx, baseProps.Libs))
+ data := android.BazelLabelForModuleSrc(ctx, baseProps.Data)
+ data.Append(android.BazelLabelForModuleSrc(ctx, baseProps.Java_data))
+ attrs.Data.SetSelectValue(axis, config, data)
+ }
+ }
+ }
+
+ partitionedSrcs := bazel.PartitionLabelListAttribute(ctx, &attrs.Srcs, bazel.LabelPartitions{
+ "proto": android.ProtoSrcLabelPartition,
+ "py": bazel.LabelPartition{Keep_remainder: true},
+ })
+ attrs.Srcs = partitionedSrcs["py"]
+
+ if !partitionedSrcs["proto"].IsEmpty() {
+ protoInfo, _ := android.Bp2buildProtoProperties(ctx, &m.ModuleBase, partitionedSrcs["proto"])
+ protoLabel := bazel.Label{Label: ":" + protoInfo.Name}
+
+ pyProtoLibraryName := m.Name() + "_py_proto"
+ ctx.CreateBazelTargetModule(bazel.BazelTargetModuleProperties{
+ Rule_class: "py_proto_library",
+ Bzl_load_location: "//build/bazel/rules/python:py_proto.bzl",
+ }, android.CommonAttributes{
+ Name: pyProtoLibraryName,
+ }, &bazelPythonProtoLibraryAttributes{
+ Deps: bazel.MakeSingleLabelListAttribute(protoLabel),
+ })
+
+ attrs.Deps.Add(bazel.MakeLabelAttribute(":" + pyProtoLibraryName))
+ }
+
+ // Bazel normally requires `import path.from.top.of.tree` statements in
+ // python code, but with soong you can directly import modules from libraries.
+ // Add "imports" attributes to the bazel library so it matches soong's behavior.
+ imports := "."
+ if m.properties.Pkg_path != nil {
+ // TODO(b/215119317) This is a hack to handle the fact that we don't convert
+ // pkg_path properly right now. If the folder structure that contains this
+ // Android.bp file matches pkg_path, we can set imports to an appropriate
+ // number of ../..s to emulate moving the files under a pkg_path folder.
+ pkg_path := filepath.Clean(*m.properties.Pkg_path)
+ if strings.HasPrefix(pkg_path, "/") {
+ ctx.ModuleErrorf("pkg_path cannot start with a /: %s", pkg_path)
+ }
+
+ if !strings.HasSuffix(ctx.ModuleDir(), "/"+pkg_path) && ctx.ModuleDir() != pkg_path {
+ ctx.ModuleErrorf("Currently, bp2build only supports pkg_paths that are the same as the folders the Android.bp file is in. pkg_path: %s, module directory: %s", pkg_path, ctx.ModuleDir())
+ }
+ numFolders := strings.Count(pkg_path, "/") + 1
+ dots := make([]string, numFolders)
+ for i := 0; i < numFolders; i++ {
+ dots[i] = ".."
+ }
+ imports = strings.Join(dots, "/")
+ }
+ attrs.Imports = bazel.MakeStringListAttribute([]string{imports})
+
+ return attrs
+}
+
+func pythonLibBp2Build(ctx android.TopDownMutatorContext, m *PythonLibraryModule) {
+ // TODO(b/182306917): this doesn't fully handle all nested props versioned
+ // by the python version, which would have been handled by the version split
+ // mutator. This is sufficient for very simple python_library modules under
+ // Bionic.
+ py3Enabled := proptools.BoolDefault(m.properties.Version.Py3.Enabled, true)
+ py2Enabled := proptools.BoolDefault(m.properties.Version.Py2.Enabled, false)
+ var python_version *string
+ if py2Enabled && !py3Enabled {
+ python_version = &pyVersion2
+ } else if !py2Enabled && py3Enabled {
+ python_version = &pyVersion3
+ } else if !py2Enabled && !py3Enabled {
+ ctx.ModuleErrorf("bp2build converter doesn't understand having neither py2 nor py3 enabled")
+ } else {
+ // do nothing, since python_version defaults to PY2ANDPY3
+ }
+
+ baseAttrs := m.makeArchVariantBaseAttributes(ctx)
+
+ attrs := &bazelPythonLibraryAttributes{
+ Srcs: baseAttrs.Srcs,
+ Deps: baseAttrs.Deps,
+ Srcs_version: python_version,
+ Imports: baseAttrs.Imports,
+ }
+
+ props := bazel.BazelTargetModuleProperties{
+ // Use the native py_library rule.
+ Rule_class: "py_library",
+ }
+
+ ctx.CreateBazelTargetModule(props, android.CommonAttributes{
+ Name: m.Name(),
+ Data: baseAttrs.Data,
+ }, attrs)
+}
+
+type bazelPythonBinaryAttributes struct {
+ Main *bazel.Label
+ Srcs bazel.LabelListAttribute
+ Deps bazel.LabelListAttribute
+ Python_version *string
+ Imports bazel.StringListAttribute
+}
+
+func pythonBinaryBp2Build(ctx android.TopDownMutatorContext, m *PythonBinaryModule) {
+ // TODO(b/182306917): this doesn't fully handle all nested props versioned
+ // by the python version, which would have been handled by the version split
+ // mutator. This is sufficient for very simple python_binary_host modules
+ // under Bionic.
+ py3Enabled := proptools.BoolDefault(m.properties.Version.Py3.Enabled, false)
+ py2Enabled := proptools.BoolDefault(m.properties.Version.Py2.Enabled, false)
+ var python_version *string
+ if py3Enabled && py2Enabled {
+ panic(fmt.Errorf(
+ "error for '%s' module: bp2build's python_binary_host converter does not support "+
+ "converting a module that is enabled for both Python 2 and 3 at the same time.", m.Name()))
+ } else if py2Enabled {
+ python_version = &pyVersion2
+ } else {
+ // do nothing, since python_version defaults to PY3.
+ }
+
+ baseAttrs := m.makeArchVariantBaseAttributes(ctx)
+ attrs := &bazelPythonBinaryAttributes{
+ Main: nil,
+ Srcs: baseAttrs.Srcs,
+ Deps: baseAttrs.Deps,
+ Python_version: python_version,
+ Imports: baseAttrs.Imports,
+ }
+
+ for _, propIntf := range m.GetProperties() {
+ if props, ok := propIntf.(*BinaryProperties); ok {
+ // main is optional.
+ if props.Main != nil {
+ main := android.BazelLabelForModuleSrcSingle(ctx, *props.Main)
+ attrs.Main = &main
+ break
+ }
+ }
+ }
+
+ props := bazel.BazelTargetModuleProperties{
+ // Use the native py_binary rule.
+ Rule_class: "py_binary",
+ }
+
+ ctx.CreateBazelTargetModule(props, android.CommonAttributes{
+ Name: m.Name(),
+ Data: baseAttrs.Data,
+ }, attrs)
+}
+
+func (p *PythonLibraryModule) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
+ pythonLibBp2Build(ctx, p)
+}
+
+func (p *PythonBinaryModule) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
+ pythonBinaryBp2Build(ctx, p)
+}
+
+func (p *PythonTestModule) ConvertWithBp2build(_ android.TopDownMutatorContext) {
+ // Tests are currently unsupported
+}
diff --git a/python/installer.go b/python/installer.go
deleted file mode 100644
index 396f036..0000000
--- a/python/installer.go
+++ /dev/null
@@ -1,67 +0,0 @@
-// Copyright 2017 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 python
-
-import (
- "path/filepath"
-
- "android/soong/android"
-)
-
-// This file handles installing python executables into their final location
-
-type installLocation int
-
-const (
- InstallInData installLocation = iota
-)
-
-type pythonInstaller struct {
- dir string
- dir64 string
- relative string
-
- path android.InstallPath
-
- androidMkSharedLibs []string
-}
-
-func NewPythonInstaller(dir, dir64 string) *pythonInstaller {
- return &pythonInstaller{
- dir: dir,
- dir64: dir64,
- }
-}
-
-var _ installer = (*pythonInstaller)(nil)
-
-func (installer *pythonInstaller) installDir(ctx android.ModuleContext) android.InstallPath {
- dir := installer.dir
- if ctx.Arch().ArchType.Multilib == "lib64" && installer.dir64 != "" {
- dir = installer.dir64
- }
- if !ctx.Host() && ctx.Config().HasMultilibConflict(ctx.Arch().ArchType) {
- dir = filepath.Join(dir, ctx.Arch().ArchType.String())
- }
- return android.PathForModuleInstall(ctx, dir, installer.relative)
-}
-
-func (installer *pythonInstaller) install(ctx android.ModuleContext, file android.Path) {
- installer.path = ctx.InstallFile(installer.installDir(ctx), file.Base(), file)
-}
-
-func (installer *pythonInstaller) setAndroidMkSharedLibs(sharedLibs []string) {
- installer.androidMkSharedLibs = sharedLibs
-}
diff --git a/python/library.go b/python/library.go
index df92df4..7cdb80b 100644
--- a/python/library.go
+++ b/python/library.go
@@ -18,9 +18,6 @@
import (
"android/soong/android"
- "android/soong/bazel"
-
- "github.com/google/blueprint/proptools"
)
func init() {
@@ -33,66 +30,9 @@
}
func PythonLibraryHostFactory() android.Module {
- module := newModule(android.HostSupported, android.MultilibFirst)
-
- android.InitBazelModule(module)
-
- return module.init()
-}
-
-type bazelPythonLibraryAttributes struct {
- Srcs bazel.LabelListAttribute
- Deps bazel.LabelListAttribute
- Imports bazel.StringListAttribute
- Srcs_version *string
-}
-
-type bazelPythonProtoLibraryAttributes struct {
- Deps bazel.LabelListAttribute
-}
-
-func pythonLibBp2Build(ctx android.TopDownMutatorContext, m *Module) {
- // TODO(b/182306917): this doesn't fully handle all nested props versioned
- // by the python version, which would have been handled by the version split
- // mutator. This is sufficient for very simple python_library modules under
- // Bionic.
- py3Enabled := proptools.BoolDefault(m.properties.Version.Py3.Enabled, true)
- py2Enabled := proptools.BoolDefault(m.properties.Version.Py2.Enabled, false)
- var python_version *string
- if py2Enabled && !py3Enabled {
- python_version = &pyVersion2
- } else if !py2Enabled && py3Enabled {
- python_version = &pyVersion3
- } else if !py2Enabled && !py3Enabled {
- ctx.ModuleErrorf("bp2build converter doesn't understand having neither py2 nor py3 enabled")
- } else {
- // do nothing, since python_version defaults to PY2ANDPY3
- }
-
- baseAttrs := m.makeArchVariantBaseAttributes(ctx)
-
- attrs := &bazelPythonLibraryAttributes{
- Srcs: baseAttrs.Srcs,
- Deps: baseAttrs.Deps,
- Srcs_version: python_version,
- Imports: baseAttrs.Imports,
- }
-
- props := bazel.BazelTargetModuleProperties{
- // Use the native py_library rule.
- Rule_class: "py_library",
- }
-
- ctx.CreateBazelTargetModule(props, android.CommonAttributes{
- Name: m.Name(),
- Data: baseAttrs.Data,
- }, attrs)
+ return newModule(android.HostSupported, android.MultilibFirst).init()
}
func PythonLibraryFactory() android.Module {
- module := newModule(android.HostAndDeviceSupported, android.MultilibBoth)
-
- android.InitBazelModule(module)
-
- return module.init()
+ return newModule(android.HostAndDeviceSupported, android.MultilibBoth).init()
}
diff --git a/python/python.go b/python/python.go
index 24e1bb2..2b71e83 100644
--- a/python/python.go
+++ b/python/python.go
@@ -22,8 +22,6 @@
"regexp"
"strings"
- "android/soong/bazel"
-
"github.com/google/blueprint"
"github.com/google/blueprint/proptools"
@@ -122,26 +120,13 @@
Embedded_launcher *bool `blueprint:"mutated"`
}
-type baseAttributes struct {
- // TODO(b/200311466): Probably not translate b/c Bazel has no good equiv
- //Pkg_path bazel.StringAttribute
- // TODO: Related to Pkg_bath and similarLy gated
- //Is_internal bazel.BoolAttribute
- // Combines Srcs and Exclude_srcs
- Srcs bazel.LabelListAttribute
- Deps bazel.LabelListAttribute
- // Combines Data and Java_data (invariant)
- Data bazel.LabelListAttribute
- Imports bazel.StringListAttribute
-}
-
// Used to store files of current module after expanding dependencies
type pathMapping struct {
dest string
src android.Path
}
-type Module struct {
+type PythonLibraryModule struct {
android.ModuleBase
android.DefaultableModuleBase
android.BazelModuleBase
@@ -153,16 +138,6 @@
hod android.HostOrDeviceSupported
multilib android.Multilib
- // interface used to bootstrap .par executable when embedded_launcher is true
- // this should be set by Python modules which are runnable, e.g. binaries and tests
- // bootstrapper might be nil (e.g. Python library module).
- bootstrapper bootstrapper
-
- // interface that implements functions required for installation
- // this should be set by Python modules which are runnable, e.g. binaries and tests
- // installer might be nil (e.g. Python library module).
- installer installer
-
// the Python files of current module after expanding source dependencies.
// pathMapping: <dest: runfile_path, src: source_path>
srcsPathMappings []pathMapping
@@ -173,110 +148,16 @@
// the zip filepath for zipping current module source/data files.
srcsZip android.Path
-
- // dependency modules' zip filepath for zipping current module source/data files.
- depsSrcsZips android.Paths
-
- // (.intermediate) module output path as installation source.
- installSource android.OptionalPath
-
- // Map to ensure sub-part of the AndroidMk for this module is only added once
- subAndroidMkOnce map[subAndroidMkProvider]bool
}
// newModule generates new Python base module
-func newModule(hod android.HostOrDeviceSupported, multilib android.Multilib) *Module {
- return &Module{
+func newModule(hod android.HostOrDeviceSupported, multilib android.Multilib) *PythonLibraryModule {
+ return &PythonLibraryModule{
hod: hod,
multilib: multilib,
}
}
-func (m *Module) makeArchVariantBaseAttributes(ctx android.TopDownMutatorContext) baseAttributes {
- var attrs baseAttributes
- archVariantBaseProps := m.GetArchVariantProperties(ctx, &BaseProperties{})
- for axis, configToProps := range archVariantBaseProps {
- for config, props := range configToProps {
- if baseProps, ok := props.(*BaseProperties); ok {
- attrs.Srcs.SetSelectValue(axis, config,
- android.BazelLabelForModuleSrcExcludes(ctx, baseProps.Srcs, baseProps.Exclude_srcs))
- attrs.Deps.SetSelectValue(axis, config,
- android.BazelLabelForModuleDeps(ctx, baseProps.Libs))
- data := android.BazelLabelForModuleSrc(ctx, baseProps.Data)
- data.Append(android.BazelLabelForModuleSrc(ctx, baseProps.Java_data))
- attrs.Data.SetSelectValue(axis, config, data)
- }
- }
- }
-
- partitionedSrcs := bazel.PartitionLabelListAttribute(ctx, &attrs.Srcs, bazel.LabelPartitions{
- "proto": android.ProtoSrcLabelPartition,
- "py": bazel.LabelPartition{Keep_remainder: true},
- })
- attrs.Srcs = partitionedSrcs["py"]
-
- if !partitionedSrcs["proto"].IsEmpty() {
- protoInfo, _ := android.Bp2buildProtoProperties(ctx, &m.ModuleBase, partitionedSrcs["proto"])
- protoLabel := bazel.Label{Label: ":" + protoInfo.Name}
-
- pyProtoLibraryName := m.Name() + "_py_proto"
- ctx.CreateBazelTargetModule(bazel.BazelTargetModuleProperties{
- Rule_class: "py_proto_library",
- Bzl_load_location: "//build/bazel/rules/python:py_proto.bzl",
- }, android.CommonAttributes{
- Name: pyProtoLibraryName,
- }, &bazelPythonProtoLibraryAttributes{
- Deps: bazel.MakeSingleLabelListAttribute(protoLabel),
- })
-
- attrs.Deps.Add(bazel.MakeLabelAttribute(":" + pyProtoLibraryName))
- }
-
- // Bazel normally requires `import path.from.top.of.tree` statements in
- // python code, but with soong you can directly import modules from libraries.
- // Add "imports" attributes to the bazel library so it matches soong's behavior.
- imports := "."
- if m.properties.Pkg_path != nil {
- // TODO(b/215119317) This is a hack to handle the fact that we don't convert
- // pkg_path properly right now. If the folder structure that contains this
- // Android.bp file matches pkg_path, we can set imports to an appropriate
- // number of ../..s to emulate moving the files under a pkg_path folder.
- pkg_path := filepath.Clean(*m.properties.Pkg_path)
- if strings.HasPrefix(pkg_path, "/") {
- ctx.ModuleErrorf("pkg_path cannot start with a /: %s", pkg_path)
- }
-
- if !strings.HasSuffix(ctx.ModuleDir(), "/"+pkg_path) && ctx.ModuleDir() != pkg_path {
- ctx.ModuleErrorf("Currently, bp2build only supports pkg_paths that are the same as the folders the Android.bp file is in. pkg_path: %s, module directory: %s", pkg_path, ctx.ModuleDir())
- }
- numFolders := strings.Count(pkg_path, "/") + 1
- dots := make([]string, numFolders)
- for i := 0; i < numFolders; i++ {
- dots[i] = ".."
- }
- imports = strings.Join(dots, "/")
- }
- attrs.Imports = bazel.MakeStringListAttribute([]string{imports})
-
- return attrs
-}
-
-// bootstrapper interface should be implemented for runnable modules, e.g. binary and test
-type bootstrapper interface {
- bootstrapperProps() []interface{}
- bootstrap(ctx android.ModuleContext, ActualVersion string, embeddedLauncher bool,
- srcsPathMappings []pathMapping, srcsZip android.Path,
- depsSrcsZips android.Paths) android.OptionalPath
-
- autorun() bool
-}
-
-// installer interface should be implemented for installable modules, e.g. binary and test
-type installer interface {
- install(ctx android.ModuleContext, path android.Path)
- setAndroidMkSharedLibs(sharedLibs []string)
-}
-
// interface implemented by Python modules to provide source and data mappings and zip to python
// modules that depend on it
type pythonDependency interface {
@@ -286,37 +167,31 @@
}
// getSrcsPathMappings gets this module's path mapping of src source path : runfiles destination
-func (p *Module) getSrcsPathMappings() []pathMapping {
+func (p *PythonLibraryModule) getSrcsPathMappings() []pathMapping {
return p.srcsPathMappings
}
// getSrcsPathMappings gets this module's path mapping of data source path : runfiles destination
-func (p *Module) getDataPathMappings() []pathMapping {
+func (p *PythonLibraryModule) getDataPathMappings() []pathMapping {
return p.dataPathMappings
}
// getSrcsZip returns the filepath where the current module's source/data files are zipped.
-func (p *Module) getSrcsZip() android.Path {
+func (p *PythonLibraryModule) getSrcsZip() android.Path {
return p.srcsZip
}
-var _ pythonDependency = (*Module)(nil)
+func (p *PythonLibraryModule) getBaseProperties() *BaseProperties {
+ return &p.properties
+}
-var _ android.AndroidMkEntriesProvider = (*Module)(nil)
+var _ pythonDependency = (*PythonLibraryModule)(nil)
-func (p *Module) init(additionalProps ...interface{}) android.Module {
+func (p *PythonLibraryModule) init() android.Module {
p.AddProperties(&p.properties, &p.protoProperties)
-
- // Add additional properties for bootstrapping/installation
- // This is currently tied to the bootstrapper interface;
- // however, these are a combination of properties for the installation and bootstrapping of a module
- if p.bootstrapper != nil {
- p.AddProperties(p.bootstrapper.bootstrapperProps()...)
- }
-
android.InitAndroidArchModule(p, p.hod, p.multilib)
android.InitDefaultableModule(p)
-
+ android.InitBazelModule(p)
return p
}
@@ -350,24 +225,29 @@
internalPath = "internal"
)
+type basePropertiesProvider interface {
+ getBaseProperties() *BaseProperties
+}
+
// versionSplitMutator creates version variants for modules and appends the version-specific
// properties for a given variant to the properties in the variant module
func versionSplitMutator() func(android.BottomUpMutatorContext) {
return func(mctx android.BottomUpMutatorContext) {
- if base, ok := mctx.Module().(*Module); ok {
- versionNames := []string{}
+ if base, ok := mctx.Module().(basePropertiesProvider); ok {
+ props := base.getBaseProperties()
+ var versionNames []string
// collect version specific properties, so that we can merge version-specific properties
// into the module's overall properties
- versionProps := []VersionProperties{}
+ var versionProps []VersionProperties
// PY3 is first so that we alias the PY3 variant rather than PY2 if both
// are available
- if proptools.BoolDefault(base.properties.Version.Py3.Enabled, true) {
+ if proptools.BoolDefault(props.Version.Py3.Enabled, true) {
versionNames = append(versionNames, pyVersion3)
- versionProps = append(versionProps, base.properties.Version.Py3)
+ versionProps = append(versionProps, props.Version.Py3)
}
- if proptools.BoolDefault(base.properties.Version.Py2.Enabled, false) {
+ if proptools.BoolDefault(props.Version.Py2.Enabled, false) {
versionNames = append(versionNames, pyVersion2)
- versionProps = append(versionProps, base.properties.Version.Py2)
+ versionProps = append(versionProps, props.Version.Py2)
}
modules := mctx.CreateLocalVariations(versionNames...)
// Alias module to the first variant
@@ -376,9 +256,10 @@
}
for i, v := range versionNames {
// set the actual version for Python module.
- modules[i].(*Module).properties.Actual_version = v
+ newProps := modules[i].(basePropertiesProvider).getBaseProperties()
+ newProps.Actual_version = v
// append versioned properties for the Python module to the overall properties
- err := proptools.AppendMatchingProperties([]interface{}{&modules[i].(*Module).properties}, &versionProps[i], nil)
+ err := proptools.AppendMatchingProperties([]interface{}{newProps}, &versionProps[i], nil)
if err != nil {
panic(err)
}
@@ -387,38 +268,6 @@
}
}
-// HostToolPath returns a path if appropriate such that this module can be used as a host tool,
-// fulfilling HostToolProvider interface.
-func (p *Module) HostToolPath() android.OptionalPath {
- if p.installer != nil {
- if bin, ok := p.installer.(*binaryDecorator); ok {
- // TODO: This should only be set when building host binaries -- tests built for device would be
- // setting this incorrectly.
- return android.OptionalPathForPath(bin.path)
- }
- }
-
- return android.OptionalPath{}
-
-}
-
-// OutputFiles returns output files based on given tag, returns an error if tag is unsupported.
-func (p *Module) OutputFiles(tag string) (android.Paths, error) {
- switch tag {
- case "":
- if outputFile := p.installSource; outputFile.Valid() {
- return android.Paths{outputFile.Path()}, nil
- }
- return android.Paths{}, nil
- default:
- return nil, fmt.Errorf("unsupported module reference tag %q", tag)
- }
-}
-
-func (p *Module) isEmbeddedLauncherEnabled() bool {
- return p.installer != nil && Bool(p.properties.Embedded_launcher)
-}
-
func anyHasExt(paths []string, ext string) bool {
for _, p := range paths {
if filepath.Ext(p) == ext {
@@ -429,7 +278,7 @@
return false
}
-func (p *Module) anySrcHasExt(ctx android.BottomUpMutatorContext, ext string) bool {
+func (p *PythonLibraryModule) anySrcHasExt(ctx android.BottomUpMutatorContext, ext string) bool {
return anyHasExt(p.properties.Srcs, ext)
}
@@ -437,7 +286,7 @@
// - handles proto dependencies,
// - if required, specifies launcher and adds launcher dependencies,
// - applies python version mutations to Python dependencies
-func (p *Module) DepsMutator(ctx android.BottomUpMutatorContext) {
+func (p *PythonLibraryModule) DepsMutator(ctx android.BottomUpMutatorContext) {
android.ProtoDeps(ctx, &p.protoProperties)
versionVariation := []blueprint.Variation{
@@ -452,111 +301,15 @@
// Add python library dependencies for this python version variation
ctx.AddVariationDependencies(versionVariation, pythonLibTag, android.LastUniqueStrings(p.properties.Libs)...)
- // If this module will be installed and has an embedded launcher, we need to add dependencies for:
- // * standard library
- // * launcher
- // * shared dependencies of the launcher
- if p.installer != nil && p.isEmbeddedLauncherEnabled() {
- var stdLib string
- var launcherModule string
- // Add launcher shared lib dependencies. Ideally, these should be
- // derived from the `shared_libs` property of the launcher. However, we
- // cannot read the property at this stage and it will be too late to add
- // dependencies later.
- launcherSharedLibDeps := []string{
- "libsqlite",
- }
- // Add launcher-specific dependencies for bionic
- if ctx.Target().Os.Bionic() {
- launcherSharedLibDeps = append(launcherSharedLibDeps, "libc", "libdl", "libm")
- }
- if ctx.Target().Os == android.LinuxMusl && !ctx.Config().HostStaticBinaries() {
- launcherSharedLibDeps = append(launcherSharedLibDeps, "libc_musl")
- }
-
- switch p.properties.Actual_version {
- case pyVersion2:
- stdLib = "py2-stdlib"
-
- launcherModule = "py2-launcher"
- if p.bootstrapper.autorun() {
- launcherModule = "py2-launcher-autorun"
- }
-
- launcherSharedLibDeps = append(launcherSharedLibDeps, "libc++")
-
- case pyVersion3:
- stdLib = "py3-stdlib"
-
- launcherModule = "py3-launcher"
- if p.bootstrapper.autorun() {
- launcherModule = "py3-launcher-autorun"
- }
- if ctx.Config().HostStaticBinaries() && ctx.Target().Os == android.LinuxMusl {
- launcherModule += "-static"
- }
-
- if ctx.Device() {
- launcherSharedLibDeps = append(launcherSharedLibDeps, "liblog")
- }
- default:
- panic(fmt.Errorf("unknown Python Actual_version: %q for module: %q.",
- p.properties.Actual_version, ctx.ModuleName()))
- }
- ctx.AddVariationDependencies(versionVariation, pythonLibTag, stdLib)
- ctx.AddFarVariationDependencies(ctx.Target().Variations(), launcherTag, launcherModule)
- ctx.AddFarVariationDependencies(ctx.Target().Variations(), launcherSharedLibTag, launcherSharedLibDeps...)
- }
-
// Emulate the data property for java_data but with the arch variation overridden to "common"
// so that it can point to java modules.
javaDataVariation := []blueprint.Variation{{"arch", android.Common.String()}}
ctx.AddVariationDependencies(javaDataVariation, javaDataTag, p.properties.Java_data...)
}
-func (p *Module) GenerateAndroidBuildActions(ctx android.ModuleContext) {
- p.generatePythonBuildActions(ctx)
-
- // Only Python binary and test modules have non-empty bootstrapper.
- if p.bootstrapper != nil {
- // if the module is being installed, we need to collect all transitive dependencies to embed in
- // the final par
- p.collectPathsFromTransitiveDeps(ctx)
- // bootstrap the module, including resolving main file, getting launcher path, and
- // registering actions to build the par file
- // bootstrap returns the binary output path
- p.installSource = p.bootstrapper.bootstrap(ctx, p.properties.Actual_version,
- p.isEmbeddedLauncherEnabled(), p.srcsPathMappings, p.srcsZip, p.depsSrcsZips)
- }
-
- // Only Python binary and test modules have non-empty installer.
- if p.installer != nil {
- var sharedLibs []string
- // if embedded launcher is enabled, we need to collect the shared library depenendencies of the
- // launcher
- for _, dep := range ctx.GetDirectDepsWithTag(launcherSharedLibTag) {
- sharedLibs = append(sharedLibs, ctx.OtherModuleName(dep))
- }
-
- p.installer.setAndroidMkSharedLibs(sharedLibs)
-
- // Install the par file from installSource
- if p.installSource.Valid() {
- p.installer.install(ctx, p.installSource.Path())
- }
- }
-}
-
-// generatePythonBuildActions performs build actions common to all Python modules
-func (p *Module) generatePythonBuildActions(ctx android.ModuleContext) {
+// GenerateAndroidBuildActions performs build actions common to all Python modules
+func (p *PythonLibraryModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
expandedSrcs := android.PathsForModuleSrcExcludes(ctx, p.properties.Srcs, p.properties.Exclude_srcs)
- requiresSrcs := true
- if p.bootstrapper != nil && !p.bootstrapper.autorun() {
- requiresSrcs = false
- }
- if len(expandedSrcs) == 0 && requiresSrcs {
- ctx.ModuleErrorf("doesn't have any source files!")
- }
// expand data files from "data" property.
expandedData := android.PathsForModuleSrc(ctx, p.properties.Data)
@@ -607,7 +360,7 @@
// For this module, generate unique pathMappings: <dest: runfiles_path, src: source_path>
// for python/data files expanded from properties.
-func (p *Module) genModulePathMappings(ctx android.ModuleContext, pkgPath string,
+func (p *PythonLibraryModule) genModulePathMappings(ctx android.ModuleContext, pkgPath string,
expandedSrcs, expandedData android.Paths) {
// fetch <runfiles_path, source_path> pairs from "src" and "data" properties to
// check current module duplicates.
@@ -642,7 +395,7 @@
}
// createSrcsZip registers build actions to zip current module's sources and data.
-func (p *Module) createSrcsZip(ctx android.ModuleContext, pkgPath string) android.Path {
+func (p *PythonLibraryModule) createSrcsZip(ctx android.ModuleContext, pkgPath string) android.Path {
relativeRootMap := make(map[string]android.Paths)
pathMappings := append(p.srcsPathMappings, p.dataPathMappings...)
@@ -654,13 +407,8 @@
if path.src.Ext() == protoExt {
protoSrcs = append(protoSrcs, path.src)
} else {
- var relativeRoot string
- relativeRoot = strings.TrimSuffix(path.src.String(), path.src.Rel())
- if v, found := relativeRootMap[relativeRoot]; found {
- relativeRootMap[relativeRoot] = append(v, path.src)
- } else {
- relativeRootMap[relativeRoot] = android.Paths{path.src}
- }
+ relativeRoot := strings.TrimSuffix(path.src.String(), path.src.Rel())
+ relativeRootMap[relativeRoot] = append(relativeRootMap[relativeRoot], path.src)
}
}
var zips android.Paths
@@ -736,30 +484,20 @@
}
}
-// isPythonLibModule returns whether the given module is a Python library Module or not
+// isPythonLibModule returns whether the given module is a Python library PythonLibraryModule or not
func isPythonLibModule(module blueprint.Module) bool {
- if m, ok := module.(*Module); ok {
- return m.isLibrary()
+ if _, ok := module.(*PythonLibraryModule); ok {
+ if _, ok := module.(*PythonBinaryModule); !ok {
+ return true
+ }
}
return false
}
-// This is distinguished by the fact that Python libraries are not installable, while other Python
-// modules are.
-func (p *Module) isLibrary() bool {
- // Python library has no bootstrapper or installer
- return p.bootstrapper == nil && p.installer == nil
-}
-
-func (p *Module) isBinary() bool {
- _, ok := p.bootstrapper.(*binaryDecorator)
- return ok
-}
-
// collectPathsFromTransitiveDeps checks for source/data files for duplicate paths
// for module and its transitive dependencies and collects list of data/source file
// zips for transitive dependencies.
-func (p *Module) collectPathsFromTransitiveDeps(ctx android.ModuleContext) {
+func (p *PythonLibraryModule) collectPathsFromTransitiveDeps(ctx android.ModuleContext) android.Paths {
// fetch <runfiles_path, source_path> pairs from "src" and "data" properties to
// check duplicates.
destToPySrcs := make(map[string]string)
@@ -773,6 +511,8 @@
seen := make(map[android.Module]bool)
+ var result android.Paths
+
// visit all its dependencies in depth first.
ctx.WalkDeps(func(child, parent android.Module) bool {
// we only collect dependencies tagged as python library deps
@@ -801,10 +541,11 @@
checkForDuplicateOutputPath(ctx, destToPyData,
path.dest, path.src.String(), ctx.ModuleName(), ctx.OtherModuleName(child))
}
- p.depsSrcsZips = append(p.depsSrcsZips, dep.getSrcsZip())
+ result = append(result, dep.getSrcsZip())
}
return true
})
+ return result
}
// chckForDuplicateOutputPath checks whether outputPath has already been included in map m, which
@@ -825,18 +566,10 @@
}
// InstallInData returns true as Python is not supported in the system partition
-func (p *Module) InstallInData() bool {
+func (p *PythonLibraryModule) InstallInData() bool {
return true
}
-func (p *Module) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
- if p.isLibrary() {
- pythonLibBp2Build(ctx, p)
- } else if p.isBinary() {
- pythonBinaryBp2Build(ctx, p)
- }
-}
-
var Bool = proptools.Bool
var BoolDefault = proptools.BoolDefault
var String = proptools.String
diff --git a/python/python_test.go b/python/python_test.go
index 42a1ffb..6f4223a 100644
--- a/python/python_test.go
+++ b/python/python_test.go
@@ -312,10 +312,6 @@
"e/file4.py",
},
srcsZip: "out/soong/.intermediates/dir/bin/PY3/bin.py.srcszip",
- depsSrcsZips: []string{
- "out/soong/.intermediates/dir/lib5/PY3/lib5.py.srcszip",
- "out/soong/.intermediates/dir/lib6/PY3/lib6.py.srcszip",
- },
},
},
},
@@ -346,17 +342,17 @@
for _, e := range d.expectedBinaries {
t.Run(e.name, func(t *testing.T) {
- expectModule(t, result.TestContext, e.name, e.actualVersion, e.srcsZip, e.pyRunfiles, e.depsSrcsZips)
+ expectModule(t, result.TestContext, e.name, e.actualVersion, e.srcsZip, e.pyRunfiles)
})
}
})
}
}
-func expectModule(t *testing.T, ctx *android.TestContext, name, variant, expectedSrcsZip string, expectedPyRunfiles, expectedDepsSrcsZips []string) {
+func expectModule(t *testing.T, ctx *android.TestContext, name, variant, expectedSrcsZip string, expectedPyRunfiles []string) {
module := ctx.ModuleForTests(name, variant)
- base, baseOk := module.Module().(*Module)
+ base, baseOk := module.Module().(*PythonLibraryModule)
if !baseOk {
t.Fatalf("%s is not Python module!", name)
}
@@ -369,8 +365,6 @@
android.AssertDeepEquals(t, "pyRunfiles", expectedPyRunfiles, actualPyRunfiles)
android.AssertPathRelativeToTopEquals(t, "srcsZip", expectedSrcsZip, base.srcsZip)
-
- android.AssertPathsRelativeToTopEquals(t, "depsSrcsZips", expectedDepsSrcsZips, base.depsSrcsZips)
}
func TestMain(m *testing.M) {
diff --git a/python/test.go b/python/test.go
index fc5c211..fb8e918 100644
--- a/python/test.go
+++ b/python/test.go
@@ -32,6 +32,20 @@
ctx.RegisterModuleType("python_test", PythonTestFactory)
}
+func NewTest(hod android.HostOrDeviceSupported) *PythonTestModule {
+ return &PythonTestModule{PythonBinaryModule: *NewBinary(hod)}
+}
+
+func PythonTestHostFactory() android.Module {
+ return NewTest(android.HostSupportedNoCross).init()
+}
+
+func PythonTestFactory() android.Module {
+ module := NewTest(android.HostAndDeviceSupported)
+ module.multilib = android.MultilibBoth
+ return module.init()
+}
+
type TestProperties struct {
// the name of the test configuration (for example "AndroidTest.xml") that should be
// installed with the module.
@@ -52,76 +66,79 @@
Test_options android.CommonTestOptions
}
-type testDecorator struct {
- *binaryDecorator
+type PythonTestModule struct {
+ PythonBinaryModule
testProperties TestProperties
-
- testConfig android.Path
-
- data []android.DataPath
+ testConfig android.Path
+ data []android.DataPath
}
-func (test *testDecorator) bootstrapperProps() []interface{} {
- return append(test.binaryDecorator.bootstrapperProps(), &test.testProperties)
+func (p *PythonTestModule) init() android.Module {
+ p.AddProperties(&p.properties, &p.protoProperties)
+ p.AddProperties(&p.binaryProperties)
+ p.AddProperties(&p.testProperties)
+ android.InitAndroidArchModule(p, p.hod, p.multilib)
+ android.InitDefaultableModule(p)
+ android.InitBazelModule(p)
+ if p.hod == android.HostSupportedNoCross && p.testProperties.Test_options.Unit_test == nil {
+ p.testProperties.Test_options.Unit_test = proptools.BoolPtr(true)
+ }
+ return p
}
-func (test *testDecorator) install(ctx android.ModuleContext, file android.Path) {
- test.testConfig = tradefed.AutoGenTestConfig(ctx, tradefed.AutoGenTestConfigOptions{
- TestConfigProp: test.testProperties.Test_config,
- TestConfigTemplateProp: test.testProperties.Test_config_template,
- TestSuites: test.binaryDecorator.binaryProperties.Test_suites,
- AutoGenConfig: test.binaryDecorator.binaryProperties.Auto_gen_config,
+func (p *PythonTestModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ // We inherit from only the library's GenerateAndroidBuildActions, and then
+ // just use buildBinary() so that the binary is not installed into the location
+ // it would be for regular binaries.
+ p.PythonLibraryModule.GenerateAndroidBuildActions(ctx)
+ p.buildBinary(ctx)
+
+ p.testConfig = tradefed.AutoGenTestConfig(ctx, tradefed.AutoGenTestConfigOptions{
+ TestConfigProp: p.testProperties.Test_config,
+ TestConfigTemplateProp: p.testProperties.Test_config_template,
+ TestSuites: p.binaryProperties.Test_suites,
+ AutoGenConfig: p.binaryProperties.Auto_gen_config,
DeviceTemplate: "${PythonBinaryHostTestConfigTemplate}",
HostTemplate: "${PythonBinaryHostTestConfigTemplate}",
})
- test.binaryDecorator.pythonInstaller.dir = "nativetest"
- test.binaryDecorator.pythonInstaller.dir64 = "nativetest64"
+ p.installedDest = ctx.InstallFile(installDir(ctx, "nativetest", "nativetest64", ctx.ModuleName()), p.installSource.Base(), p.installSource)
- test.binaryDecorator.pythonInstaller.relative = ctx.ModuleName()
-
- test.binaryDecorator.pythonInstaller.install(ctx, file)
-
- dataSrcPaths := android.PathsForModuleSrc(ctx, test.testProperties.Data)
-
- for _, dataSrcPath := range dataSrcPaths {
- test.data = append(test.data, android.DataPath{SrcPath: dataSrcPath})
+ for _, dataSrcPath := range android.PathsForModuleSrc(ctx, p.testProperties.Data) {
+ p.data = append(p.data, android.DataPath{SrcPath: dataSrcPath})
}
// Emulate the data property for java_data dependencies.
for _, javaData := range ctx.GetDirectDepsWithTag(javaDataTag) {
for _, javaDataSrcPath := range android.OutputFilesForModule(ctx, javaData, "") {
- test.data = append(test.data, android.DataPath{SrcPath: javaDataSrcPath})
+ p.data = append(p.data, android.DataPath{SrcPath: javaDataSrcPath})
}
}
}
-func NewTest(hod android.HostOrDeviceSupported) *Module {
- module, binary := NewBinary(hod)
-
- binary.pythonInstaller = NewPythonInstaller("nativetest", "nativetest64")
-
- test := &testDecorator{binaryDecorator: binary}
- if hod == android.HostSupportedNoCross && test.testProperties.Test_options.Unit_test == nil {
- test.testProperties.Test_options.Unit_test = proptools.BoolPtr(true)
+func (p *PythonTestModule) AndroidMkEntries() []android.AndroidMkEntries {
+ entriesList := p.PythonBinaryModule.AndroidMkEntries()
+ if len(entriesList) != 1 {
+ panic("Expected 1 entry")
}
+ entries := &entriesList[0]
- module.bootstrapper = test
- module.installer = test
+ entries.Class = "NATIVE_TESTS"
- return module
-}
+ entries.ExtraEntries = append(entries.ExtraEntries,
+ func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
+ //entries.AddCompatibilityTestSuites(p.binaryProperties.Test_suites...)
+ if p.testConfig != nil {
+ entries.SetString("LOCAL_FULL_TEST_CONFIG", p.testConfig.String())
+ }
-func PythonTestHostFactory() android.Module {
- module := NewTest(android.HostSupportedNoCross)
+ entries.SetBoolIfTrue("LOCAL_DISABLE_AUTO_GENERATE_TEST_CONFIG", !BoolDefault(p.binaryProperties.Auto_gen_config, true))
- return module.init()
-}
+ entries.AddStrings("LOCAL_TEST_DATA", android.AndroidMkDataPaths(p.data)...)
-func PythonTestFactory() android.Module {
- module := NewTest(android.HostAndDeviceSupported)
- module.multilib = android.MultilibBoth
+ p.testProperties.Test_options.SetAndroidMkEntries(entries)
+ })
- return module.init()
+ return entriesList
}
diff --git a/rust/bindgen.go b/rust/bindgen.go
index 17d80dd..1ad33a1 100644
--- a/rust/bindgen.go
+++ b/rust/bindgen.go
@@ -15,7 +15,6 @@
package rust
import (
- "fmt"
"strings"
"github.com/google/blueprint"
@@ -178,10 +177,6 @@
if mctx, ok := ctx.(*moduleContext); ok && mctx.apexVariationName() != "" {
cflags = append(cflags, "-D__ANDROID_APEX__")
- if ctx.Device() {
- cflags = append(cflags, fmt.Sprintf("-D__ANDROID_APEX_MIN_SDK_VERSION__=%d",
- ctx.RustModule().apexSdkVersion.FinalOrFutureInt()))
- }
}
if ctx.Target().NativeBridge == android.NativeBridgeEnabled {
diff --git a/rust/image.go b/rust/image.go
index dfc7f74..50bf02a 100644
--- a/rust/image.go
+++ b/rust/image.go
@@ -129,6 +129,10 @@
return ctx.ModuleContext.DeviceSpecific() || (ctx.RustModule().InVendor() && ctx.RustModule().VendorVariantToOdm())
}
+func (ctx *moduleContext) SystemExtSpecific() bool {
+ return ctx.ModuleContext.SystemExtSpecific()
+}
+
// Returns true when this module creates a vendor variant and wants to install the vendor variant
// to the odm partition.
func (c *Module) VendorVariantToOdm() bool {
@@ -158,22 +162,15 @@
}
func (mod *Module) OnlyInRamdisk() bool {
- // TODO(b/165791368)
- return false
+ return mod.ModuleBase.InstallInRamdisk()
}
func (mod *Module) OnlyInRecovery() bool {
- // TODO(b/165791368)
- return false
+ return mod.ModuleBase.InstallInRecovery()
}
func (mod *Module) OnlyInVendorRamdisk() bool {
- return false
-}
-
-func (mod *Module) OnlyInProduct() bool {
- //TODO(b/165791368)
- return false
+ return mod.ModuleBase.InstallInVendorRamdisk()
}
// Returns true when this module is configured to have core and vendor variants.
@@ -226,10 +223,7 @@
// Rust does not support installing to the product image yet.
vendorSpecific := mctx.SocSpecific() || mctx.DeviceSpecific()
- if mctx.ProductSpecific() {
- mctx.PropertyErrorf("product_specific",
- "Rust modules do not yet support installing to the product image.")
- } else if Bool(mod.VendorProperties.Double_loadable) {
+ if Bool(mod.VendorProperties.Double_loadable) {
mctx.PropertyErrorf("double_loadable",
"Rust modules do not yet support double loading")
}
@@ -243,6 +237,11 @@
mctx.PropertyErrorf("vendor", "Vendor-only dylibs are not yet supported, use rust_library_rlib.")
}
}
+ if mctx.ProductSpecific() {
+ if lib, ok := mod.compiler.(libraryInterface); ok && lib.buildDylib() {
+ mctx.PropertyErrorf("product", "Product-only dylibs are not yet supported, use rust_library_rlib.")
+ }
+ }
cc.MutateImage(mctx, mod)
diff --git a/rust/image_test.go b/rust/image_test.go
index 95e788f..8185872 100644
--- a/rust/image_test.go
+++ b/rust/image_test.go
@@ -103,3 +103,93 @@
}
`)
}
+
+func checkInstallPartition(t *testing.T, ctx *android.TestContext, name, variant, expected string) {
+ mod := ctx.ModuleForTests(name, variant).Module().(*Module)
+ partitionDefined := false
+ checkPartition := func(specific bool, partition string) {
+ if specific {
+ if expected != partition && !partitionDefined {
+ // The variant is installed to the 'partition'
+ t.Errorf("%s variant of %q must not be installed to %s partition", variant, name, partition)
+ }
+ partitionDefined = true
+ } else {
+ // The variant is not installed to the 'partition'
+ if expected == partition {
+ t.Errorf("%s variant of %q must be installed to %s partition", variant, name, partition)
+ }
+ }
+ }
+ socSpecific := func(m *Module) bool {
+ return m.SocSpecific()
+ }
+ deviceSpecific := func(m *Module) bool {
+ return m.DeviceSpecific()
+ }
+ productSpecific := func(m *Module) bool {
+ return m.ProductSpecific() || m.productSpecificModuleContext()
+ }
+ systemExtSpecific := func(m *Module) bool {
+ return m.SystemExtSpecific()
+ }
+ checkPartition(socSpecific(mod), "vendor")
+ checkPartition(deviceSpecific(mod), "odm")
+ checkPartition(productSpecific(mod), "product")
+ checkPartition(systemExtSpecific(mod), "system_ext")
+ if !partitionDefined && expected != "system" {
+ t.Errorf("%s variant of %q is expected to be installed to %s partition,"+
+ " but installed to system partition", variant, name, expected)
+ }
+}
+
+func TestInstallPartition(t *testing.T) {
+ t.Parallel()
+ t.Helper()
+ ctx := testRust(t, `
+ rust_binary {
+ name: "sample_system",
+ crate_name: "sample",
+ srcs: ["foo.rs"],
+ }
+ rust_binary {
+ name: "sample_system_ext",
+ crate_name: "sample",
+ srcs: ["foo.rs"],
+ system_ext_specific: true,
+ }
+ rust_binary {
+ name: "sample_product",
+ crate_name: "sample",
+ srcs: ["foo.rs"],
+ product_specific: true,
+ }
+ rust_binary {
+ name: "sample_vendor",
+ crate_name: "sample",
+ srcs: ["foo.rs"],
+ vendor: true,
+ }
+ rust_binary {
+ name: "sample_odm",
+ crate_name: "sample",
+ srcs: ["foo.rs"],
+ device_specific: true,
+ }
+ rust_binary {
+ name: "sample_all_available",
+ crate_name: "sample",
+ srcs: ["foo.rs"],
+ vendor_available: true,
+ product_available: true,
+ }
+ `)
+
+ checkInstallPartition(t, ctx, "sample_system", binaryCoreVariant, "system")
+ checkInstallPartition(t, ctx, "sample_system_ext", binaryCoreVariant, "system_ext")
+ checkInstallPartition(t, ctx, "sample_product", binaryProductVariant, "product")
+ checkInstallPartition(t, ctx, "sample_vendor", binaryVendorVariant, "vendor")
+ checkInstallPartition(t, ctx, "sample_odm", binaryVendorVariant, "odm")
+
+ checkInstallPartition(t, ctx, "sample_all_available", binaryCoreVariant, "system")
+}
diff --git a/rust/rust_test.go b/rust/rust_test.go
index 97bd541..3bcd58c 100644
--- a/rust/rust_test.go
+++ b/rust/rust_test.go
@@ -83,6 +83,10 @@
rlibVendorVariant = "android_vendor.29_arm64_armv8-a_rlib_rlib-std"
sharedRecoveryVariant = "android_recovery_arm64_armv8-a_shared"
rlibRecoveryVariant = "android_recovery_arm64_armv8-a_rlib_rlib-std"
+ binaryCoreVariant = "android_arm64_armv8-a"
+ binaryVendorVariant = "android_vendor.29_arm64_armv8-a"
+ binaryProductVariant = "android_product.29_arm64_armv8-a"
+ binaryRecoveryVariant = "android_recovery_arm64_armv8-a"
)
func testRustVndkFs(t *testing.T, bp string, fs android.MockFS) *android.TestContext {
diff --git a/rust/testing.go b/rust/testing.go
index 4796f69..24ca3d6 100644
--- a/rust/testing.go
+++ b/rust/testing.go
@@ -104,6 +104,7 @@
crate_name: "std",
srcs: ["foo.rs"],
no_stdlibs: true,
+ product_available: true,
host_supported: true,
vendor_available: true,
vendor_ramdisk_available: true,