Merge "Generate java_api_contribution module from droidstubs module"
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/bazel/properties.go b/bazel/properties.go
index 0fca60b..9be21eb 100644
--- a/bazel/properties.go
+++ b/bazel/properties.go
@@ -152,7 +152,7 @@
ll.Includes = append(ll.Includes, other.Includes...)
}
if len(ll.Excludes) > 0 || len(other.Excludes) > 0 {
- ll.Excludes = append(other.Excludes, other.Excludes...)
+ ll.Excludes = append(ll.Excludes, other.Excludes...)
}
}
@@ -888,7 +888,7 @@
// then remove all config-specific excludes
allLabels := baseLabels.deepCopy()
allLabels.Append(val)
- lla.ConfigurableValues[axis][config] = SubtractBazelLabelList(allLabels, LabelList{Includes: val.Excludes})
+ lla.ConfigurableValues[axis][config] = SubtractBazelLabelList(allLabels, LabelList{Includes: allLabels.Excludes})
}
// After going through all configs, delete the duplicates in the config
diff --git a/bazel/properties_test.go b/bazel/properties_test.go
index 8729381..cf03eb5 100644
--- a/bazel/properties_test.go
+++ b/bazel/properties_test.go
@@ -231,6 +231,7 @@
"all_include",
"arm_exclude",
"android_exclude",
+ "product_config_exclude",
},
[]string{"all_exclude"},
),
@@ -251,10 +252,10 @@
"a": makeLabelList([]string{}, []string{"not_in_value"}),
"b": makeLabelList([]string{"b_val"}, []string{}),
"c": makeLabelList([]string{"c_val"}, []string{}),
- ConditionsDefaultConfigKey: makeLabelList([]string{"c_val", "default", "default2"}, []string{}),
+ ConditionsDefaultConfigKey: makeLabelList([]string{"c_val", "default", "default2", "all_exclude"}, []string{}),
},
ProductVariableConfigurationAxis("product_only_with_excludes", NoConfigAxis): labelListSelectValues{
- "a": makeLabelList([]string{}, []string{"not_in_value"}),
+ "a": makeLabelList([]string{}, []string{"product_config_exclude"}),
},
},
}
@@ -287,6 +288,10 @@
"c": makeLabels("c_val"),
ConditionsDefaultConfigKey: makeLabels("c_val", "default", "default2"),
},
+ ProductVariableConfigurationAxis("product_only_with_excludes", NoConfigAxis): {
+ "a": nilLabels,
+ ConditionsDefaultConfigKey: makeLabels("product_config_exclude"),
+ },
}
for _, axis := range attr.SortedConfigurationAxes() {
if _, ok := expectedConfiguredIncludes[axis]; !ok {
diff --git a/bp2build/cc_library_conversion_test.go b/bp2build/cc_library_conversion_test.go
index 052bc32..244ca9c 100644
--- a/bp2build/cc_library_conversion_test.go
+++ b/bp2build/cc_library_conversion_test.go
@@ -3437,23 +3437,23 @@
ExpectedBazelTargets: []string{
MakeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{
"implementation_deps": `[":baz__BP2BUILD__MISSING__DEP"] + select({
- "//build/bazel/rules/apex:non_apex": [":buh__BP2BUILD__MISSING__DEP"],
- "//conditions:default": [],
+ "//build/bazel/rules/apex:in_apex": [],
+ "//conditions:default": [":buh__BP2BUILD__MISSING__DEP"],
})`,
"implementation_dynamic_deps": `[":baz__BP2BUILD__MISSING__DEP"] + select({
- "//build/bazel/rules/apex:non_apex": [":bar__BP2BUILD__MISSING__DEP"],
- "//conditions:default": [],
+ "//build/bazel/rules/apex:in_apex": [],
+ "//conditions:default": [":bar__BP2BUILD__MISSING__DEP"],
})`,
"local_includes": `["."]`,
}),
MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
"implementation_deps": `[":baz__BP2BUILD__MISSING__DEP"] + select({
- "//build/bazel/rules/apex:non_apex": [":buh__BP2BUILD__MISSING__DEP"],
- "//conditions:default": [],
+ "//build/bazel/rules/apex:in_apex": [],
+ "//conditions:default": [":buh__BP2BUILD__MISSING__DEP"],
})`,
"implementation_dynamic_deps": `[":baz__BP2BUILD__MISSING__DEP"] + select({
- "//build/bazel/rules/apex:non_apex": [":bar__BP2BUILD__MISSING__DEP"],
- "//conditions:default": [],
+ "//build/bazel/rules/apex:in_apex": [],
+ "//conditions:default": [":bar__BP2BUILD__MISSING__DEP"],
})`,
"local_includes": `["."]`,
}),
@@ -3483,16 +3483,16 @@
ExpectedBazelTargets: []string{
MakeBazelTarget("cc_library_static", "foo", AttrNameToString{
"implementation_dynamic_deps": `select({
- "//build/bazel/rules/apex:non_apex": [":bar__BP2BUILD__MISSING__DEP"],
- "//conditions:default": [],
+ "//build/bazel/rules/apex:in_apex": [],
+ "//conditions:default": [":bar__BP2BUILD__MISSING__DEP"],
})`,
"dynamic_deps": `select({
- "//build/bazel/rules/apex:non_apex": [":baz__BP2BUILD__MISSING__DEP"],
- "//conditions:default": [],
+ "//build/bazel/rules/apex:in_apex": [],
+ "//conditions:default": [":baz__BP2BUILD__MISSING__DEP"],
})`,
"deps": `select({
- "//build/bazel/rules/apex:non_apex": [":abc__BP2BUILD__MISSING__DEP"],
- "//conditions:default": [],
+ "//build/bazel/rules/apex:in_apex": [],
+ "//conditions:default": [":abc__BP2BUILD__MISSING__DEP"],
})`,
"local_includes": `["."]`,
}),
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/bp2build/soong_config_module_type_conversion_test.go b/bp2build/soong_config_module_type_conversion_test.go
index 89be767..ba42f34 100644
--- a/bp2build/soong_config_module_type_conversion_test.go
+++ b/bp2build/soong_config_module_type_conversion_test.go
@@ -742,6 +742,101 @@
)`}})
}
+func TestSoongConfigModuleType_UnsetConditionsExcludeLibs(t *testing.T) {
+ bp := `
+soong_config_string_variable {
+ name: "library_linking_strategy",
+ values: [
+ "prefer_static",
+ ],
+}
+
+soong_config_module_type {
+ name: "library_linking_strategy_cc_defaults",
+ module_type: "cc_defaults",
+ config_namespace: "ANDROID",
+ variables: ["library_linking_strategy"],
+ properties: ["shared_libs"],
+}
+
+library_linking_strategy_cc_defaults {
+ name: "library_linking_strategy_lib_a_defaults",
+ soong_config_variables: {
+ library_linking_strategy: {
+ prefer_static: {},
+ conditions_default: {
+ shared_libs: [
+ "lib_a",
+ ],
+ },
+ },
+ },
+}
+
+library_linking_strategy_cc_defaults {
+ name: "library_linking_strategy_merged_defaults",
+ defaults: ["library_linking_strategy_lib_a_defaults"],
+ host_supported: true,
+ soong_config_variables: {
+ library_linking_strategy: {
+ prefer_static: {},
+ conditions_default: {
+ shared_libs: [
+ "lib_b",
+ "lib_c",
+ ],
+ },
+ },
+ },
+ exclude_shared_libs: ["lib_a"],
+}
+
+cc_binary {
+ name: "library_linking_strategy_sample_binary",
+ defaults: ["library_linking_strategy_merged_defaults"],
+ include_build_directory: false,
+}
+
+cc_binary {
+ name: "library_linking_strategy_sample_binary_with_excludes",
+ defaults: ["library_linking_strategy_merged_defaults"],
+ exclude_shared_libs: ["lib_c"],
+ include_build_directory: false,
+}`
+
+ otherDeps := `
+cc_library { name: "lib_a", bazel_module: { bp2build_available: false } }
+cc_library { name: "lib_b", bazel_module: { bp2build_available: false } }
+cc_library { name: "lib_c", bazel_module: { bp2build_available: false } }
+`
+
+ runSoongConfigModuleTypeTest(t, Bp2buildTestCase{
+ Description: "soong config variables - generates selects for library_linking_strategy",
+ ModuleTypeUnderTest: "cc_binary",
+ ModuleTypeUnderTestFactory: cc.BinaryFactory,
+ Blueprint: bp,
+ Filesystem: map[string]string{
+ "foo/bar/Android.bp": otherDeps,
+ },
+ ExpectedBazelTargets: []string{
+ MakeBazelTargetNoRestrictions("cc_binary", "library_linking_strategy_sample_binary", AttrNameToString{
+ "dynamic_deps": `select({
+ "//build/bazel/product_variables:android__library_linking_strategy__prefer_static": [],
+ "//conditions:default": [
+ "//foo/bar:lib_b",
+ "//foo/bar:lib_c",
+ ],
+ })`,
+ }),
+ MakeBazelTargetNoRestrictions("cc_binary", "library_linking_strategy_sample_binary_with_excludes", AttrNameToString{
+ "dynamic_deps": `select({
+ "//build/bazel/product_variables:android__library_linking_strategy__prefer_static": [],
+ "//conditions:default": ["//foo/bar:lib_b"],
+ })`,
+ }),
+ }})
+}
+
func TestSoongConfigModuleType_Defaults(t *testing.T) {
bp := `
soong_config_string_variable {
diff --git a/bp2build/testing.go b/bp2build/testing.go
index c340a8f..92a9bf1 100644
--- a/bp2build/testing.go
+++ b/bp2build/testing.go
@@ -258,6 +258,7 @@
}
func (b BazelTestResult) CompareBazelTargets(t *testing.T, description string, expectedContents []string, actualTargets BazelTargets) {
+ t.Helper()
if actualCount, expectedCount := len(actualTargets), len(expectedContents); actualCount != expectedCount {
t.Errorf("%s: Expected %d bazel target (%s), got %d (%s)",
description, expectedCount, expectedContents, actualCount, actualTargets)
diff --git a/cc/bp2build.go b/cc/bp2build.go
index aea1fa1..35419af 100644
--- a/cc/bp2build.go
+++ b/cc/bp2build.go
@@ -979,34 +979,22 @@
// resolveTargetApex re-adds the shared and static libs in target.apex.exclude_shared|static_libs props to non-apex variant
// since all libs are already excluded by default
-func (la *linkerAttributes) resolveTargetApexProp(ctx android.BazelConversionPathContext, isBinary bool, props *BaseLinkerProperties) {
- sharedLibsForNonApex := maybePartitionExportedAndImplementationsDeps(
- ctx,
- true,
- props.Target.Apex.Exclude_shared_libs,
- props.Export_shared_lib_headers,
- bazelLabelForSharedDeps,
- )
- dynamicDeps := la.dynamicDeps.SelectValue(bazel.InApexAxis, bazel.NonApex)
- implDynamicDeps := la.implementationDynamicDeps.SelectValue(bazel.InApexAxis, bazel.NonApex)
- (&dynamicDeps).Append(sharedLibsForNonApex.export)
- (&implDynamicDeps).Append(sharedLibsForNonApex.implementation)
- la.dynamicDeps.SetSelectValue(bazel.InApexAxis, bazel.NonApex, dynamicDeps)
- la.implementationDynamicDeps.SetSelectValue(bazel.InApexAxis, bazel.NonApex, implDynamicDeps)
+func (la *linkerAttributes) resolveTargetApexProp(ctx android.BazelConversionPathContext, props *BaseLinkerProperties) {
+ excludeSharedLibs := bazelLabelForSharedDeps(ctx, props.Target.Apex.Exclude_shared_libs)
+ sharedExcludes := bazel.LabelList{Excludes: excludeSharedLibs.Includes}
+ sharedExcludesLabelList := bazel.LabelListAttribute{}
+ sharedExcludesLabelList.SetSelectValue(bazel.InApexAxis, bazel.InApex, sharedExcludes)
- staticLibsForNonApex := maybePartitionExportedAndImplementationsDeps(
- ctx,
- !isBinary,
- props.Target.Apex.Exclude_static_libs,
- props.Export_static_lib_headers,
- bazelLabelForSharedDeps,
- )
- deps := la.deps.SelectValue(bazel.InApexAxis, bazel.NonApex)
- implDeps := la.implementationDeps.SelectValue(bazel.InApexAxis, bazel.NonApex)
- (&deps).Append(staticLibsForNonApex.export)
- (&implDeps).Append(staticLibsForNonApex.implementation)
- la.deps.SetSelectValue(bazel.InApexAxis, bazel.NonApex, deps)
- la.implementationDeps.SetSelectValue(bazel.InApexAxis, bazel.NonApex, implDeps)
+ la.dynamicDeps.Append(sharedExcludesLabelList)
+ la.implementationDynamicDeps.Append(sharedExcludesLabelList)
+
+ excludeStaticLibs := bazelLabelForStaticDeps(ctx, props.Target.Apex.Exclude_static_libs)
+ staticExcludes := bazel.LabelList{Excludes: excludeStaticLibs.Includes}
+ staticExcludesLabelList := bazel.LabelListAttribute{}
+ staticExcludesLabelList.SetSelectValue(bazel.InApexAxis, bazel.InApex, staticExcludes)
+
+ la.deps.Append(staticExcludesLabelList)
+ la.implementationDeps.Append(staticExcludesLabelList)
}
func (la *linkerAttributes) bp2buildForAxisAndConfig(ctx android.BazelConversionPathContext, isBinary bool, axis bazel.ConfigurationAxis, config string, props *BaseLinkerProperties) {
@@ -1040,8 +1028,7 @@
ctx,
!isBinary,
staticLibs,
- // Exclude static libs in Exclude_static_libs and Target.Apex.Exclude_static_libs props
- append(props.Exclude_static_libs, props.Target.Apex.Exclude_static_libs...),
+ props.Exclude_static_libs,
props.Export_static_lib_headers,
bazelLabelForStaticDepsExcludes,
)
@@ -1080,14 +1067,13 @@
ctx,
!isBinary,
sharedLibs,
- // Exclude shared libs in Exclude_shared_libs and Target.Apex.Exclude_shared_libs props
- append(props.Exclude_shared_libs, props.Target.Apex.Exclude_shared_libs...),
+ props.Exclude_shared_libs,
props.Export_shared_lib_headers,
bazelLabelForSharedDepsExcludes,
)
la.dynamicDeps.SetSelectValue(axis, config, sharedDeps.export)
la.implementationDynamicDeps.SetSelectValue(axis, config, sharedDeps.implementation)
- la.resolveTargetApexProp(ctx, isBinary, props)
+ la.resolveTargetApexProp(ctx, props)
if axis == bazel.NoConfigAxis || (axis == bazel.OsConfigurationAxis && config == bazel.OsAndroid) {
// If a dependency in la.implementationDynamicDeps has stubs, its stub variant should be
diff --git a/cc/config/global.go b/cc/config/global.go
index 2205c9e..d557c0b 100644
--- a/cc/config/global.go
+++ b/cc/config/global.go
@@ -386,30 +386,17 @@
return strings.Join(deviceGlobalCflags, " ")
})
- // Export the static default NoOverrideGlobalCflags and NoOverride64GlobalCflags to Bazel.
+ // Export the static default NoOverrideGlobalCflags 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, " ")
- })
-
+ exportedVars.ExportStringListStaticVariable("NoOverride64GlobalCflags", noOverride64GlobalCflags)
exportedVars.ExportStringListStaticVariable("HostGlobalCflags", hostGlobalCflags)
exportedVars.ExportStringListStaticVariable("NoOverrideExternalGlobalCflags", noOverrideExternalGlobalCflags)
exportedVars.ExportStringListStaticVariable("CommonGlobalCppflags", commonGlobalCppflags)
diff --git a/java/dex.go b/java/dex.go
index 971da92..b6fe109 100644
--- a/java/dex.go
+++ b/java/dex.go
@@ -90,6 +90,7 @@
// list of extra proguard flag files
extraProguardFlagFiles android.Paths
proguardDictionary android.OptionalPath
+ proguardConfiguration android.OptionalPath
proguardUsageZip android.OptionalPath
providesTransitiveHeaderJars
@@ -133,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" && ` +
@@ -179,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,
@@ -370,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")
@@ -382,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/java.go b/java/java.go
index 5859e90..659f98a 100644
--- a/java/java.go
+++ b/java/java.go
@@ -2603,7 +2603,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{})
@@ -2709,11 +2709,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))
+ }
}
}
@@ -2731,7 +2737,7 @@
staticDeps.Add(protoDepLabel)
depLabels := &javaDependencyLabels{}
- depLabels.Deps = bazel.MakeLabelListAttribute(deps)
+ depLabels.Deps = deps
depLabels.StaticDeps = bazel.MakeLabelListAttribute(staticDeps)
bp2BuildInfo := &bp2BuildJavaInfo{
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
}