Merge changes from topic "refactor-packagingbase"
* changes:
Move GatherPackagingSpecs out of CopyDepsToZip
Keep 'partition' in PackagingSpec
diff --git a/android/module.go b/android/module.go
index d0e2a76..66a5f60 100644
--- a/android/module.go
+++ b/android/module.go
@@ -1470,8 +1470,10 @@
}
type propInfo struct {
- Name string
- Type string
+ Name string
+ Type string
+ Value string
+ Values []string
}
func (m *ModuleBase) propertiesWithValues() []propInfo {
@@ -1511,18 +1513,60 @@
return
}
elKind := v.Type().Elem().Kind()
- info = append(info, propInfo{name, elKind.String() + " " + kind.String()})
+ info = append(info, propInfo{Name: name, Type: elKind.String() + " " + kind.String(), Values: sliceReflectionValue(v)})
default:
- info = append(info, propInfo{name, kind.String()})
+ info = append(info, propInfo{Name: name, Type: kind.String(), Value: reflectionValue(v)})
}
}
for _, p := range props {
propsWithValues("", reflect.ValueOf(p).Elem())
}
+ sort.Slice(info, func(i, j int) bool {
+ return info[i].Name < info[j].Name
+ })
return info
}
+func reflectionValue(value reflect.Value) string {
+ switch value.Kind() {
+ case reflect.Bool:
+ return fmt.Sprintf("%t", value.Bool())
+ case reflect.Int64:
+ return fmt.Sprintf("%d", value.Int())
+ case reflect.String:
+ return fmt.Sprintf("%s", value.String())
+ case reflect.Struct:
+ if value.IsZero() {
+ return "{}"
+ }
+ length := value.NumField()
+ vals := make([]string, length, length)
+ for i := 0; i < length; i++ {
+ sTyp := value.Type().Field(i)
+ if proptools.ShouldSkipProperty(sTyp) {
+ continue
+ }
+ name := sTyp.Name
+ vals[i] = fmt.Sprintf("%s: %s", name, reflectionValue(value.Field(i)))
+ }
+ return fmt.Sprintf("%s{%s}", value.Type(), strings.Join(vals, ", "))
+ case reflect.Array, reflect.Slice:
+ vals := sliceReflectionValue(value)
+ return fmt.Sprintf("[%s]", strings.Join(vals, ", "))
+ }
+ return ""
+}
+
+func sliceReflectionValue(value reflect.Value) []string {
+ length := value.Len()
+ vals := make([]string, length, length)
+ for i := 0; i < length; i++ {
+ vals[i] = reflectionValue(value.Index(i))
+ }
+ return vals
+}
+
func (m *ModuleBase) ComponentDepsMutator(BottomUpMutatorContext) {}
func (m *ModuleBase) DepsMutator(BottomUpMutatorContext) {}
diff --git a/android/module_test.go b/android/module_test.go
index 1dcddf7..77ef146 100644
--- a/android/module_test.go
+++ b/android/module_test.go
@@ -563,6 +563,12 @@
Embedded_prop *string
}
+type StructInSlice struct {
+ G string
+ H bool
+ I []string
+}
+
type propsTestModule struct {
ModuleBase
DefaultableModuleBase
@@ -579,6 +585,8 @@
E *string
}
F *string `blueprint:"mutated"`
+
+ Slice_of_struct []StructInSlice
}
}
@@ -621,7 +629,7 @@
}
`,
expectedProps: []propInfo{
- propInfo{"Name", "string"},
+ propInfo{Name: "Name", Type: "string", Value: "foo"},
},
},
{
@@ -634,10 +642,10 @@
}
`,
expectedProps: []propInfo{
- propInfo{"A", "string"},
- propInfo{"B", "bool"},
- propInfo{"D", "int64"},
- propInfo{"Name", "string"},
+ propInfo{Name: "A", Type: "string", Value: "abc"},
+ propInfo{Name: "B", Type: "bool", Value: "true"},
+ propInfo{Name: "D", Type: "int64", Value: "123"},
+ propInfo{Name: "Name", Type: "string", Value: "foo"},
},
},
{
@@ -650,10 +658,10 @@
`,
expectedProps: []propInfo{
// for non-pointer cannot distinguish between unused and intentionally set to empty
- propInfo{"A", "string"},
- propInfo{"B", "bool"},
- propInfo{"D", "int64"},
- propInfo{"Name", "string"},
+ propInfo{Name: "A", Type: "string", Value: ""},
+ propInfo{Name: "B", Type: "bool", Value: "true"},
+ propInfo{Name: "D", Type: "int64", Value: "123"},
+ propInfo{Name: "Name", Type: "string", Value: "foo"},
},
},
{
@@ -666,8 +674,8 @@
}
`,
expectedProps: []propInfo{
- propInfo{"Nested.E", "string"},
- propInfo{"Name", "string"},
+ propInfo{Name: "Name", Type: "string", Value: "foo"},
+ propInfo{Name: "Nested.E", Type: "string", Value: "abc"},
},
},
{
@@ -682,8 +690,8 @@
}
`,
expectedProps: []propInfo{
- propInfo{"Name", "string"},
- propInfo{"Arch.X86_64.A", "string"},
+ propInfo{Name: "Arch.X86_64.A", Type: "string", Value: "abc"},
+ propInfo{Name: "Name", Type: "string", Value: "foo"},
},
},
{
@@ -694,8 +702,34 @@
}
`,
expectedProps: []propInfo{
- propInfo{"Embedded_prop", "string"},
- propInfo{"Name", "string"},
+ propInfo{Name: "Embedded_prop", Type: "string", Value: "a"},
+ propInfo{Name: "Name", Type: "string", Value: "foo"},
+ },
+ },
+ {
+ desc: "struct slice",
+ bp: `test {
+ name: "foo",
+ slice_of_struct: [
+ {
+ g: "abc",
+ h: false,
+ i: ["baz"],
+ },
+ {
+ g: "def",
+ h: true,
+ i: [],
+ },
+ ]
+ }
+ `,
+ expectedProps: []propInfo{
+ propInfo{Name: "Name", Type: "string", Value: "foo"},
+ propInfo{Name: "Slice_of_struct", Type: "struct slice", Values: []string{
+ `android.StructInSlice{G: abc, H: false, I: [baz]}`,
+ `android.StructInSlice{G: def, H: true, I: []}`,
+ }},
},
},
{
@@ -705,19 +739,20 @@
name: "foo_defaults",
a: "a",
b: true,
+ c: ["default_c"],
embedded_prop:"a",
arch: {
x86_64: {
- a: "a",
+ a: "x86_64 a",
},
},
}
test {
name: "foo",
defaults: ["foo_defaults"],
- c: ["a"],
+ c: ["c"],
nested: {
- e: "d",
+ e: "nested e",
},
target: {
linux: {
@@ -727,15 +762,15 @@
}
`,
expectedProps: []propInfo{
- propInfo{"A", "string"},
- propInfo{"B", "bool"},
- propInfo{"C", "string slice"},
- propInfo{"Embedded_prop", "string"},
- propInfo{"Nested.E", "string"},
- propInfo{"Name", "string"},
- propInfo{"Arch.X86_64.A", "string"},
- propInfo{"Target.Linux.A", "string"},
- propInfo{"Defaults", "string slice"},
+ propInfo{Name: "A", Type: "string", Value: "a"},
+ propInfo{Name: "Arch.X86_64.A", Type: "string", Value: "x86_64 a"},
+ propInfo{Name: "B", Type: "bool", Value: "true"},
+ propInfo{Name: "C", Type: "string slice", Values: []string{"default_c", "c"}},
+ propInfo{Name: "Defaults", Type: "string slice", Values: []string{"foo_defaults"}},
+ propInfo{Name: "Embedded_prop", Type: "string", Value: "a"},
+ propInfo{Name: "Name", Type: "string", Value: "foo"},
+ propInfo{Name: "Nested.E", Type: "string", Value: "nested e"},
+ propInfo{Name: "Target.Linux.A", Type: "string", Value: "a"},
},
},
}
diff --git a/java/builder.go b/java/builder.go
index c48e3fa..c0fadd4 100644
--- a/java/builder.go
+++ b/java/builder.go
@@ -131,31 +131,28 @@
turbine, turbineRE = pctx.RemoteStaticRules("turbine",
blueprint.RuleParams{
- Command: `rm -rf "$outDir" && mkdir -p "$outDir" && ` +
- `$reTemplate${config.JavaCmd} ${config.JavaVmFlags} -jar ${config.TurbineJar} --output $out.tmp ` +
- `--temp_dir "$outDir" --sources @$out.rsp --source_jars $srcJars ` +
+ Command: `$reTemplate${config.JavaCmd} ${config.JavaVmFlags} -jar ${config.TurbineJar} $outputFlags ` +
+ `--sources @$out.rsp --source_jars $srcJars ` +
`--javacopts ${config.CommonJdkFlags} ` +
- `$javacFlags -source $javaVersion -target $javaVersion -- $bootClasspath $classpath && ` +
- `${config.Ziptime} $out.tmp && ` +
- `(if cmp -s $out.tmp $out ; then rm $out.tmp ; else mv $out.tmp $out ; fi )`,
+ `$javacFlags -source $javaVersion -target $javaVersion -- $turbineFlags && ` +
+ `(for o in $outputs; do if cmp -s $${o}.tmp $${o} ; then rm $${o}.tmp ; else mv $${o}.tmp $${o} ; fi; done )`,
CommandDeps: []string{
"${config.TurbineJar}",
"${config.JavaCmd}",
- "${config.Ziptime}",
},
Rspfile: "$out.rsp",
RspfileContent: "$in",
Restat: true,
},
&remoteexec.REParams{Labels: map[string]string{"type": "tool", "name": "turbine"},
- ExecStrategy: "${config.RETurbineExecStrategy}",
- Inputs: []string{"${config.TurbineJar}", "${out}.rsp", "$implicits"},
- RSPFiles: []string{"${out}.rsp"},
- OutputFiles: []string{"$out.tmp"},
- OutputDirectories: []string{"$outDir"},
- ToolchainInputs: []string{"${config.JavaCmd}"},
- Platform: map[string]string{remoteexec.PoolKey: "${config.REJavaPool}"},
- }, []string{"javacFlags", "bootClasspath", "classpath", "srcJars", "outDir", "javaVersion"}, []string{"implicits"})
+ ExecStrategy: "${config.RETurbineExecStrategy}",
+ Inputs: []string{"${config.TurbineJar}", "${out}.rsp", "$implicits"},
+ RSPFiles: []string{"${out}.rsp"},
+ OutputFiles: []string{"$rbeOutputs"},
+ ToolchainInputs: []string{"${config.JavaCmd}"},
+ Platform: map[string]string{remoteexec.PoolKey: "${config.REJavaPool}"},
+ },
+ []string{"javacFlags", "turbineFlags", "outputFlags", "javaVersion", "outputs", "rbeOutputs", "srcJars"}, []string{"implicits"})
jar, jarRE = pctx.RemoteStaticRules("jar",
blueprint.RuleParams{
@@ -358,11 +355,8 @@
})
}
-func TransformJavaToHeaderClasses(ctx android.ModuleContext, outputFile android.WritablePath,
- srcFiles, srcJars android.Paths, flags javaBuilderFlags) {
-
+func turbineFlags(ctx android.ModuleContext, flags javaBuilderFlags) (string, android.Paths) {
var deps android.Paths
- deps = append(deps, srcJars...)
classpath := flags.classpath
@@ -384,20 +378,31 @@
}
deps = append(deps, classpath...)
- deps = append(deps, flags.processorPath...)
+ turbineFlags := bootClasspath + " " + classpath.FormTurbineClassPath("--classpath ")
+
+ return turbineFlags, deps
+}
+
+func TransformJavaToHeaderClasses(ctx android.ModuleContext, outputFile android.WritablePath,
+ srcFiles, srcJars android.Paths, flags javaBuilderFlags) {
+
+ turbineFlags, deps := turbineFlags(ctx, flags)
+
+ deps = append(deps, srcJars...)
rule := turbine
args := map[string]string{
- "javacFlags": flags.javacFlags,
- "bootClasspath": bootClasspath,
- "srcJars": strings.Join(srcJars.Strings(), " "),
- "classpath": classpath.FormTurbineClassPath("--classpath "),
- "outDir": android.PathForModuleOut(ctx, "turbine", "classes").String(),
- "javaVersion": flags.javaVersion.String(),
+ "javacFlags": flags.javacFlags,
+ "srcJars": strings.Join(srcJars.Strings(), " "),
+ "javaVersion": flags.javaVersion.String(),
+ "turbineFlags": turbineFlags,
+ "outputFlags": "--output " + outputFile.String() + ".tmp",
+ "outputs": outputFile.String(),
}
if ctx.Config().UseRBE() && ctx.Config().IsEnvTrue("RBE_TURBINE") {
rule = turbineRE
args["implicits"] = strings.Join(deps.Strings(), ",")
+ args["rbeOutputs"] = outputFile.String() + ".tmp"
}
ctx.Build(pctx, android.BuildParams{
Rule: rule,
@@ -409,6 +414,47 @@
})
}
+// TurbineApt produces a rule to run annotation processors using turbine.
+func TurbineApt(ctx android.ModuleContext, outputSrcJar, outputResJar android.WritablePath,
+ srcFiles, srcJars android.Paths, flags javaBuilderFlags) {
+
+ turbineFlags, deps := turbineFlags(ctx, flags)
+
+ deps = append(deps, srcJars...)
+
+ deps = append(deps, flags.processorPath...)
+ turbineFlags += " " + flags.processorPath.FormTurbineClassPath("--processorpath ")
+ turbineFlags += " --processors " + strings.Join(flags.processors, " ")
+
+ outputs := android.WritablePaths{outputSrcJar, outputResJar}
+ outputFlags := "--gensrc_output " + outputSrcJar.String() + ".tmp " +
+ "--resource_output " + outputResJar.String() + ".tmp"
+
+ rule := turbine
+ args := map[string]string{
+ "javacFlags": flags.javacFlags,
+ "srcJars": strings.Join(srcJars.Strings(), " "),
+ "javaVersion": flags.javaVersion.String(),
+ "turbineFlags": turbineFlags,
+ "outputFlags": outputFlags,
+ "outputs": strings.Join(outputs.Strings(), " "),
+ }
+ if ctx.Config().UseRBE() && ctx.Config().IsEnvTrue("RBE_TURBINE") {
+ rule = turbineRE
+ args["implicits"] = strings.Join(deps.Strings(), ",")
+ args["rbeOutputs"] = outputSrcJar.String() + ".tmp," + outputResJar.String() + ".tmp"
+ }
+ ctx.Build(pctx, android.BuildParams{
+ Rule: rule,
+ Description: "turbine apt",
+ Output: outputs[0],
+ ImplicitOutputs: outputs[1:],
+ Inputs: srcFiles,
+ Implicits: deps,
+ Args: args,
+ })
+}
+
// transformJavaToClasses takes source files and converts them to a jar containing .class files.
// srcFiles is a list of paths to sources, srcJars is a list of paths to jar files that contain
// sources. flags contains various command line flags to be passed to the compiler.
@@ -670,6 +716,6 @@
} else if forceEmpty {
return `--bootclasspath ""`, nil
} else {
- return "", nil
+ return "--system ${config.JavaHome}", nil
}
}
diff --git a/java/java_test.go b/java/java_test.go
index f095c5e..4c93824 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -973,7 +973,7 @@
fooHeaderJar := filepath.Join("out", "soong", ".intermediates", "foo", "android_common", "turbine-combined", "foo.jar")
barTurbineJar := filepath.Join("out", "soong", ".intermediates", "bar", "android_common", "turbine", "bar.jar")
- android.AssertStringDoesContain(t, "bar turbine classpath", barTurbine.Args["classpath"], fooHeaderJar)
+ android.AssertStringDoesContain(t, "bar turbine classpath", barTurbine.Args["turbineFlags"], fooHeaderJar)
android.AssertStringDoesContain(t, "bar javac classpath", barJavac.Args["classpath"], fooHeaderJar)
android.AssertPathsRelativeToTopEquals(t, "bar turbine combineJar", []string{barTurbineJar, fooHeaderJar}, barTurbineCombined.Inputs)
android.AssertStringDoesContain(t, "baz javac classpath", bazJavac.Args["classpath"], "prebuilts/sdk/14/public/android.jar")
diff --git a/java/kotlin.go b/java/kotlin.go
index 3e5cec0..ce79bae 100644
--- a/java/kotlin.go
+++ b/java/kotlin.go
@@ -118,7 +118,7 @@
})
}
-var kapt = pctx.AndroidRemoteStaticRule("kapt", android.RemoteRuleSupports{Goma: true},
+var kaptStubs = pctx.AndroidRemoteStaticRule("kaptStubs", android.RemoteRuleSupports{Goma: true},
blueprint.RuleParams{
Command: `rm -rf "$srcJarDir" "$kotlinBuildFile" "$kaptDir" && ` +
`mkdir -p "$srcJarDir" "$kaptDir/sources" "$kaptDir/classes" && ` +
@@ -133,13 +133,12 @@
`-P plugin:org.jetbrains.kotlin.kapt3:classes=$kaptDir/classes ` +
`-P plugin:org.jetbrains.kotlin.kapt3:stubs=$kaptDir/stubs ` +
`-P plugin:org.jetbrains.kotlin.kapt3:correctErrorTypes=true ` +
- `-P plugin:org.jetbrains.kotlin.kapt3:aptMode=stubsAndApt ` +
+ `-P plugin:org.jetbrains.kotlin.kapt3:aptMode=stubs ` +
`-P plugin:org.jetbrains.kotlin.kapt3:javacArguments=$encodedJavacFlags ` +
`$kaptProcessorPath ` +
`$kaptProcessor ` +
`-Xbuild-file=$kotlinBuildFile && ` +
- `${config.SoongZipCmd} -jar -o $out -C $kaptDir/sources -D $kaptDir/sources && ` +
- `${config.SoongZipCmd} -jar -o $classesJarOut -C $kaptDir/classes -D $kaptDir/classes && ` +
+ `${config.SoongZipCmd} -jar -o $out -C $kaptDir/stubs -D $kaptDir/stubs && ` +
`rm -rf "$srcJarDir"`,
CommandDeps: []string{
"${config.KotlincCmd}",
@@ -197,13 +196,14 @@
kotlinName := filepath.Join(ctx.ModuleDir(), ctx.ModuleSubDir(), ctx.ModuleName())
kotlinName = strings.ReplaceAll(kotlinName, "/", "__")
+ // First run kapt to generate .java stubs from .kt files
+ kaptStubsJar := android.PathForModuleOut(ctx, "kapt", "stubs.jar")
ctx.Build(pctx, android.BuildParams{
- Rule: kapt,
- Description: "kapt",
- Output: srcJarOutputFile,
- ImplicitOutput: resJarOutputFile,
- Inputs: srcFiles,
- Implicits: deps,
+ Rule: kaptStubs,
+ Description: "kapt stubs",
+ Output: kaptStubsJar,
+ Inputs: srcFiles,
+ Implicits: deps,
Args: map[string]string{
"classpath": flags.kotlincClasspath.FormJavaClassPath(""),
"kotlincFlags": flags.kotlincFlags,
@@ -219,6 +219,11 @@
"classesJarOut": resJarOutputFile.String(),
},
})
+
+ // Then run turbine to perform annotation processing on the stubs and any .java srcFiles.
+ javaSrcFiles := srcFiles.FilterByExt(".java")
+ turbineSrcJars := append(android.Paths{kaptStubsJar}, srcJars...)
+ TurbineApt(ctx, srcJarOutputFile, resJarOutputFile, javaSrcFiles, turbineSrcJars, flags)
}
// kapt converts a list of key, value pairs into a base64 encoded Java serialization, which is what kapt expects.
diff --git a/java/kotlin_test.go b/java/kotlin_test.go
index cac0af3..d51bc04 100644
--- a/java/kotlin_test.go
+++ b/java/kotlin_test.go
@@ -117,51 +117,71 @@
buildOS := ctx.Config().BuildOS.String()
- kapt := ctx.ModuleForTests("foo", "android_common").Rule("kapt")
- kotlinc := ctx.ModuleForTests("foo", "android_common").Rule("kotlinc")
- javac := ctx.ModuleForTests("foo", "android_common").Rule("javac")
+ foo := ctx.ModuleForTests("foo", "android_common")
+ kaptStubs := foo.Rule("kapt")
+ turbineApt := foo.Description("turbine apt")
+ kotlinc := foo.Rule("kotlinc")
+ javac := foo.Rule("javac")
bar := ctx.ModuleForTests("bar", buildOS+"_common").Rule("javac").Output.String()
baz := ctx.ModuleForTests("baz", buildOS+"_common").Rule("javac").Output.String()
// Test that the kotlin and java sources are passed to kapt and kotlinc
- if len(kapt.Inputs) != 2 || kapt.Inputs[0].String() != "a.java" || kapt.Inputs[1].String() != "b.kt" {
- t.Errorf(`foo kapt inputs %v != ["a.java", "b.kt"]`, kapt.Inputs)
+ if len(kaptStubs.Inputs) != 2 || kaptStubs.Inputs[0].String() != "a.java" || kaptStubs.Inputs[1].String() != "b.kt" {
+ t.Errorf(`foo kapt inputs %v != ["a.java", "b.kt"]`, kaptStubs.Inputs)
}
if len(kotlinc.Inputs) != 2 || kotlinc.Inputs[0].String() != "a.java" || kotlinc.Inputs[1].String() != "b.kt" {
t.Errorf(`foo kotlinc inputs %v != ["a.java", "b.kt"]`, kotlinc.Inputs)
}
- // Test that only the java sources are passed to javac
+ // Test that only the java sources are passed to turbine-apt and javac
+ if len(turbineApt.Inputs) != 1 || turbineApt.Inputs[0].String() != "a.java" {
+ t.Errorf(`foo turbine apt inputs %v != ["a.java"]`, turbineApt.Inputs)
+ }
if len(javac.Inputs) != 1 || javac.Inputs[0].String() != "a.java" {
t.Errorf(`foo inputs %v != ["a.java"]`, javac.Inputs)
}
- // Test that the kapt srcjar is a dependency of kotlinc and javac rules
- if !inList(kapt.Output.String(), kotlinc.Implicits.Strings()) {
- t.Errorf("expected %q in kotlinc implicits %v", kapt.Output.String(), kotlinc.Implicits.Strings())
- }
- if !inList(kapt.Output.String(), javac.Implicits.Strings()) {
- t.Errorf("expected %q in javac implicits %v", kapt.Output.String(), javac.Implicits.Strings())
+ // Test that the kapt stubs jar is a dependency of turbine-apt
+ if !inList(kaptStubs.Output.String(), turbineApt.Implicits.Strings()) {
+ t.Errorf("expected %q in turbine-apt implicits %v", kaptStubs.Output.String(), kotlinc.Implicits.Strings())
}
- // Test that the kapt srcjar is extracted by the kotlinc and javac rules
- if kotlinc.Args["srcJars"] != kapt.Output.String() {
- t.Errorf("expected %q in kotlinc srcjars %v", kapt.Output.String(), kotlinc.Args["srcJars"])
+ // Test that the turbine-apt srcjar is a dependency of kotlinc and javac rules
+ if !inList(turbineApt.Output.String(), kotlinc.Implicits.Strings()) {
+ t.Errorf("expected %q in kotlinc implicits %v", turbineApt.Output.String(), kotlinc.Implicits.Strings())
}
- if javac.Args["srcJars"] != kapt.Output.String() {
- t.Errorf("expected %q in javac srcjars %v", kapt.Output.String(), kotlinc.Args["srcJars"])
+ if !inList(turbineApt.Output.String(), javac.Implicits.Strings()) {
+ t.Errorf("expected %q in javac implicits %v", turbineApt.Output.String(), javac.Implicits.Strings())
+ }
+
+ // Test that the turbine-apt srcjar is extracted by the kotlinc and javac rules
+ if kotlinc.Args["srcJars"] != turbineApt.Output.String() {
+ t.Errorf("expected %q in kotlinc srcjars %v", turbineApt.Output.String(), kotlinc.Args["srcJars"])
+ }
+ if javac.Args["srcJars"] != turbineApt.Output.String() {
+ t.Errorf("expected %q in javac srcjars %v", turbineApt.Output.String(), kotlinc.Args["srcJars"])
}
// Test that the processors are passed to kapt
expectedProcessorPath := "-P plugin:org.jetbrains.kotlin.kapt3:apclasspath=" + bar +
" -P plugin:org.jetbrains.kotlin.kapt3:apclasspath=" + baz
- if kapt.Args["kaptProcessorPath"] != expectedProcessorPath {
- t.Errorf("expected kaptProcessorPath %q, got %q", expectedProcessorPath, kapt.Args["kaptProcessorPath"])
+ if kaptStubs.Args["kaptProcessorPath"] != expectedProcessorPath {
+ t.Errorf("expected kaptProcessorPath %q, got %q", expectedProcessorPath, kaptStubs.Args["kaptProcessorPath"])
}
expectedProcessor := "-P plugin:org.jetbrains.kotlin.kapt3:processors=com.bar -P plugin:org.jetbrains.kotlin.kapt3:processors=com.baz"
- if kapt.Args["kaptProcessor"] != expectedProcessor {
- t.Errorf("expected kaptProcessor %q, got %q", expectedProcessor, kapt.Args["kaptProcessor"])
+ if kaptStubs.Args["kaptProcessor"] != expectedProcessor {
+ t.Errorf("expected kaptProcessor %q, got %q", expectedProcessor, kaptStubs.Args["kaptProcessor"])
+ }
+
+ // Test that the processors are passed to turbine-apt
+ expectedProcessorPath = "--processorpath " + bar + " " + baz
+ if !strings.Contains(turbineApt.Args["turbineFlags"], expectedProcessorPath) {
+ t.Errorf("expected turbine-apt processorpath %q, got %q", expectedProcessorPath, turbineApt.Args["turbineFlags"])
+ }
+ expectedProcessor = "--processors com.bar com.baz"
+ if !strings.Contains(turbineApt.Args["turbineFlags"], expectedProcessor) {
+ t.Errorf("expected turbine-apt processor %q, got %q", expectedProcessor, turbineApt.Args["turbineFlags"])
}
// Test that the processors are not passed to javac
diff --git a/rust/prebuilt.go b/rust/prebuilt.go
index 6f17272..6cdd07d 100644
--- a/rust/prebuilt.go
+++ b/rust/prebuilt.go
@@ -22,6 +22,7 @@
android.RegisterModuleType("rust_prebuilt_library", PrebuiltLibraryFactory)
android.RegisterModuleType("rust_prebuilt_dylib", PrebuiltDylibFactory)
android.RegisterModuleType("rust_prebuilt_rlib", PrebuiltRlibFactory)
+ android.RegisterModuleType("rust_prebuilt_proc_macro", PrebuiltProcMacroFactory)
}
type PrebuiltProperties struct {
@@ -38,8 +39,42 @@
Properties PrebuiltProperties
}
+type prebuiltProcMacroDecorator struct {
+ android.Prebuilt
+
+ *procMacroDecorator
+ Properties PrebuiltProperties
+}
+
+func PrebuiltProcMacroFactory() android.Module {
+ module, _ := NewPrebuiltProcMacro(android.HostSupportedNoCross)
+ return module.Init()
+}
+
+type rustPrebuilt interface {
+ prebuiltSrcs() []string
+ prebuilt() *android.Prebuilt
+}
+
+func NewPrebuiltProcMacro(hod android.HostOrDeviceSupported) (*Module, *prebuiltProcMacroDecorator) {
+ module, library := NewProcMacro(hod)
+ prebuilt := &prebuiltProcMacroDecorator{
+ procMacroDecorator: library,
+ }
+ module.compiler = prebuilt
+
+ addSrcSupplier(module, prebuilt)
+
+ return module, prebuilt
+}
+
var _ compiler = (*prebuiltLibraryDecorator)(nil)
var _ exportedFlagsProducer = (*prebuiltLibraryDecorator)(nil)
+var _ rustPrebuilt = (*prebuiltLibraryDecorator)(nil)
+
+var _ compiler = (*prebuiltProcMacroDecorator)(nil)
+var _ exportedFlagsProducer = (*prebuiltProcMacroDecorator)(nil)
+var _ rustPrebuilt = (*prebuiltProcMacroDecorator)(nil)
func PrebuiltLibraryFactory() android.Module {
module, _ := NewPrebuiltLibrary(android.HostAndDeviceSupported)
@@ -56,7 +91,7 @@
return module.Init()
}
-func addSrcSupplier(module android.PrebuiltInterface, prebuilt *prebuiltLibraryDecorator) {
+func addSrcSupplier(module android.PrebuiltInterface, prebuilt rustPrebuilt) {
srcsSupplier := func(_ android.BaseModuleContext, _ android.Module) []string {
return prebuilt.prebuiltSrcs()
}
@@ -152,3 +187,44 @@
func (prebuilt *prebuiltLibraryDecorator) prebuilt() *android.Prebuilt {
return &prebuilt.Prebuilt
}
+
+func (prebuilt *prebuiltProcMacroDecorator) prebuiltSrcs() []string {
+ srcs := prebuilt.Properties.Srcs
+ return srcs
+}
+
+func (prebuilt *prebuiltProcMacroDecorator) prebuilt() *android.Prebuilt {
+ return &prebuilt.Prebuilt
+}
+
+func (prebuilt *prebuiltProcMacroDecorator) compilerProps() []interface{} {
+ return append(prebuilt.procMacroDecorator.compilerProps(),
+ &prebuilt.Properties)
+}
+
+func (prebuilt *prebuiltProcMacroDecorator) compile(ctx ModuleContext, flags Flags, deps PathDeps) android.Path {
+ prebuilt.flagExporter.exportLinkDirs(android.PathsForModuleSrc(ctx, prebuilt.Properties.Link_dirs).Strings()...)
+ prebuilt.flagExporter.setProvider(ctx)
+
+ srcPath, paths := srcPathFromModuleSrcs(ctx, prebuilt.prebuiltSrcs())
+ if len(paths) > 0 {
+ ctx.PropertyErrorf("srcs", "prebuilt libraries can only have one entry in srcs (the prebuilt path)")
+ }
+ prebuilt.baseCompiler.unstrippedOutputFile = srcPath
+ return srcPath
+}
+
+func (prebuilt *prebuiltProcMacroDecorator) rustdoc(ctx ModuleContext, flags Flags,
+ deps PathDeps) android.OptionalPath {
+
+ return android.OptionalPath{}
+}
+
+func (prebuilt *prebuiltProcMacroDecorator) compilerDeps(ctx DepsContext, deps Deps) Deps {
+ deps = prebuilt.baseCompiler.compilerDeps(ctx, deps)
+ return deps
+}
+
+func (prebuilt *prebuiltProcMacroDecorator) nativeCoverage() bool {
+ return false
+}
diff --git a/rust/proc_macro.go b/rust/proc_macro.go
index 974c096..f8a4bbd 100644
--- a/rust/proc_macro.go
+++ b/rust/proc_macro.go
@@ -33,6 +33,7 @@
}
type procMacroInterface interface {
+ ProcMacro() bool
}
var _ compiler = (*procMacroDecorator)(nil)
@@ -90,6 +91,10 @@
return rlibAutoDep
}
+func (procMacro *procMacroDecorator) ProcMacro() bool {
+ return true
+}
+
func (procMacro *procMacroDecorator) everInstallable() bool {
// Proc_macros are never installed
return false
diff --git a/rust/rust.go b/rust/rust.go
index 1c718a4..d627261 100644
--- a/rust/rust.go
+++ b/rust/rust.go
@@ -27,6 +27,7 @@
cc_config "android/soong/cc/config"
"android/soong/fuzz"
"android/soong/rust/config"
+ "android/soong/snapshot"
)
var pctx = android.NewPackageContext("android/soong/rust")
@@ -806,6 +807,13 @@
return mod.Properties.Installable
}
+func (mod *Module) ProcMacro() bool {
+ if pm, ok := mod.compiler.(procMacroInterface); ok {
+ return pm.ProcMacro()
+ }
+ return false
+}
+
func (mod *Module) toolchain(ctx android.BaseModuleContext) config.Toolchain {
if mod.cachedToolchain == nil {
mod.cachedToolchain = config.FindToolchain(ctx.Os(), ctx.Arch())
@@ -920,12 +928,13 @@
}
apexInfo := actx.Provider(android.ApexInfoProvider).(android.ApexInfo)
- if !proptools.BoolDefault(mod.Installable(), mod.EverInstallable()) {
+ if !proptools.BoolDefault(mod.Installable(), mod.EverInstallable()) && !mod.ProcMacro() {
// If the module has been specifically configure to not be installed then
// hide from make as otherwise it will break when running inside make as the
// output path to install will not be specified. Not all uninstallable
// modules can be hidden from make as some are needed for resolving make
- // side dependencies.
+ // side dependencies. In particular, proc-macros need to be captured in the
+ // host snapshot.
mod.HideFromMake()
} else if !mod.installable(apexInfo) {
mod.SkipInstall()
@@ -1046,7 +1055,7 @@
}
func (mod *Module) Prebuilt() *android.Prebuilt {
- if p, ok := mod.compiler.(*prebuiltLibraryDecorator); ok {
+ if p, ok := mod.compiler.(rustPrebuilt); ok {
return p.prebuilt()
}
return nil
@@ -1501,6 +1510,7 @@
}
var _ android.HostToolProvider = (*Module)(nil)
+var _ snapshot.RelativeInstallPath = (*Module)(nil)
func (mod *Module) HostToolPath() android.OptionalPath {
if !mod.Host() {
@@ -1508,6 +1518,10 @@
}
if binary, ok := mod.compiler.(*binaryDecorator); ok {
return android.OptionalPathForPath(binary.baseCompiler.path)
+ } else if pm, ok := mod.compiler.(*procMacroDecorator); ok {
+ // Even though proc-macros aren't strictly "tools", since they target the compiler
+ // and act as compiler plugins, we treat them similarly.
+ return android.OptionalPathForPath(pm.baseCompiler.path)
}
return android.OptionalPath{}
}
diff --git a/scripts/Android.bp b/scripts/Android.bp
index a694b95..4c847a1 100644
--- a/scripts/Android.bp
+++ b/scripts/Android.bp
@@ -188,11 +188,3 @@
"get_clang_version.py",
],
}
-
-python_binary_host {
- name: "list_image",
- main: "list_image.py",
- srcs: [
- "list_image.py",
- ],
-}
diff --git a/scripts/list_image.py b/scripts/list_image.py
deleted file mode 100644
index 7f76537..0000000
--- a/scripts/list_image.py
+++ /dev/null
@@ -1,103 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright (C) 2022 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-"""list_image is a tool that prints out content of an .img file.
-
-To print content of an image to stdout:
- list_image foo.img
-"""
-from __future__ import print_function
-
-import argparse
-import os
-import sys
-import subprocess
-
-class ImageEntry(object):
-
- def __init__(self, name, base_dir, is_directory=False):
- self._name = name
- self._base_dir = base_dir
- self._is_directory = is_directory
-
- @property
- def name(self):
- return self._name
-
- @property
- def full_path(self):
- return os.path.join(self._base_dir, self._name)
-
- @property
- def is_directory(self):
- return self._is_directory
-
-
-class Image(object):
-
- def __init__(self, debugfs_path, img_path):
- self._debugfs = debugfs_path
- self._img_path = img_path
-
- def list(self, path):
- print(path)
- process = subprocess.Popen([self._debugfs, '-R', 'ls -l -p %s' % path, self._img_path],
- stdout=subprocess.PIPE, stderr=subprocess.PIPE,
- universal_newlines=True)
- stdout, _ = process.communicate()
- res = str(stdout)
- entries = []
- for line in res.split('\n'):
- if not line:
- continue
- parts = line.split('/')
- if len(parts) != 8:
- continue
- name = parts[5]
- if not name:
- continue
- bits = parts[2]
- is_directory = bits[1] == '4'
- entries.append(ImageEntry(name, path, is_directory))
-
- for e in sorted(entries, key=lambda e: e.name):
- yield e
- if e.is_directory and e.name != '.' and e.name != '..':
- yield from self.list(path + e.name + '/')
-
-
-def main(argv):
- parser = argparse.ArgumentParser()
-
- debugfs_default = None
- if 'ANDROID_HOST_OUT' in os.environ:
- debugfs_default = '%s/bin/debugfs_static' % os.environ['ANDROID_HOST_OUT']
- parser.add_argument('--debugfs_path', help='The path to debugfs binary', default=debugfs_default)
- parser.add_argument('img_path', type=str, help='.img file')
- args = parser.parse_args(argv)
-
- if not args.debugfs_path:
- print('ANDROID_HOST_OUT environment variable is not defined, --debugfs_path must be set',
- file=sys.stderr)
- sys.exit(1)
-
- for e in Image(args.debugfs_path, args.img_path).list('./'):
- if e.is_directory:
- continue
- print(e.full_path)
-
-
-if __name__ == '__main__':
- main(sys.argv[1:])
diff --git a/snapshot/host_fake_snapshot.go b/snapshot/host_fake_snapshot.go
index 6b4e12b..1a75f3a 100644
--- a/snapshot/host_fake_snapshot.go
+++ b/snapshot/host_fake_snapshot.go
@@ -114,13 +114,13 @@
if !apexInfo.IsForPlatform() {
return
}
- path := hostBinToolPath(module)
+ path := hostToolPath(module)
if path.Valid() && path.String() != "" {
outFile := filepath.Join(c.snapshotDir, path.String())
if !seen[outFile] {
seen[outFile] = true
outputs = append(outputs, WriteStringToFileRule(ctx, "", outFile))
- jsonData = append(jsonData, *hostBinJsonDesc(module))
+ jsonData = append(jsonData, *hostJsonDesc(module))
}
}
})
diff --git a/snapshot/host_snapshot.go b/snapshot/host_snapshot.go
index e1d6154..9793218 100644
--- a/snapshot/host_snapshot.go
+++ b/snapshot/host_snapshot.go
@@ -19,6 +19,7 @@
"fmt"
"path/filepath"
"sort"
+ "strings"
"github.com/google/blueprint"
"github.com/google/blueprint/proptools"
@@ -62,6 +63,11 @@
installDir android.InstallPath
}
+type ProcMacro interface {
+ ProcMacro() bool
+ CrateName() string
+}
+
func hostSnapshotFactory() android.Module {
module := &hostSnapshot{}
initHostToolsModule(module)
@@ -94,7 +100,7 @@
// Create JSON file based on the direct dependencies
ctx.VisitDirectDeps(func(dep android.Module) {
- desc := hostBinJsonDesc(dep)
+ desc := hostJsonDesc(dep)
if desc != nil {
jsonData = append(jsonData, *desc)
}
@@ -183,7 +189,7 @@
}
// Get host tools path and relative install string helpers
-func hostBinToolPath(m android.Module) android.OptionalPath {
+func hostToolPath(m android.Module) android.OptionalPath {
if provider, ok := m.(android.HostToolProvider); ok {
return provider.HostToolPath()
}
@@ -198,18 +204,30 @@
return outString
}
-// Create JSON description for given module, only create descriptions for binary modueles which
-// provide a valid HostToolPath
-func hostBinJsonDesc(m android.Module) *SnapshotJsonFlags {
- path := hostBinToolPath(m)
+// Create JSON description for given module, only create descriptions for binary modules
+// and rust_proc_macro modules which provide a valid HostToolPath
+func hostJsonDesc(m android.Module) *SnapshotJsonFlags {
+ path := hostToolPath(m)
relPath := hostRelativePathString(m)
+ procMacro := false
+ moduleStem := filepath.Base(path.String())
+ crateName := ""
+
+ if pm, ok := m.(ProcMacro); ok && pm.ProcMacro() {
+ procMacro = pm.ProcMacro()
+ moduleStem = strings.TrimSuffix(moduleStem, filepath.Ext(moduleStem))
+ crateName = pm.CrateName()
+ }
+
if path.Valid() && path.String() != "" {
return &SnapshotJsonFlags{
ModuleName: m.Name(),
- ModuleStemName: filepath.Base(path.String()),
+ ModuleStemName: moduleStem,
Filename: path.String(),
Required: append(m.HostRequiredModuleNames(), m.RequiredModuleNames()...),
RelativeInstallPath: relPath,
+ RustProcMacro: procMacro,
+ CrateName: crateName,
}
}
return nil
diff --git a/snapshot/snapshot_base.go b/snapshot/snapshot_base.go
index 79d3cf6..4a14f2e 100644
--- a/snapshot/snapshot_base.go
+++ b/snapshot/snapshot_base.go
@@ -114,6 +114,8 @@
RelativeInstallPath string `json:",omitempty"`
Filename string `json:",omitempty"`
ModuleStemName string `json:",omitempty"`
+ RustProcMacro bool `json:",omitempty"`
+ CrateName string `json:",omitempty"`
// dependencies
Required []string `json:",omitempty"`