Merge "Use correct flags for host-side assembly"
diff --git a/cc/cc.go b/cc/cc.go
index b4b70ed..4f10a11 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -673,6 +673,12 @@
if c.compiler != nil {
deps = c.compiler.compilerDeps(ctx, deps)
}
+ // Add the PGO dependency (the clang_rt.profile runtime library), which
+ // sometimes depends on symbols from libgcc, before libgcc gets added
+ // in linkerDeps().
+ if c.pgo != nil {
+ deps = c.pgo.deps(ctx, deps)
+ }
if c.linker != nil {
deps = c.linker.linkerDeps(ctx, deps)
}
diff --git a/cc/config/toolchain.go b/cc/config/toolchain.go
index d62ebe4..796ccfb 100644
--- a/cc/config/toolchain.go
+++ b/cc/config/toolchain.go
@@ -233,6 +233,10 @@
return SanitizerRuntimeLibrary(t, "tsan")
}
+func ProfileRuntimeLibrary(t Toolchain) string {
+ return SanitizerRuntimeLibrary(t, "profile")
+}
+
func ToolPath(t Toolchain) string {
if p := t.ToolPath(); p != "" {
return p
diff --git a/cc/pgo.go b/cc/pgo.go
index f9c8bbf..a99cbad 100644
--- a/cc/pgo.go
+++ b/cc/pgo.go
@@ -19,6 +19,7 @@
"strings"
"android/soong/android"
+ "android/soong/cc/config"
)
var (
@@ -50,25 +51,38 @@
Properties PgoProperties
}
+func (props *PgoProperties) isInstrumentation() bool {
+ return props.Pgo.Instrumentation != nil && *props.Pgo.Instrumentation == true
+}
+
+func (props *PgoProperties) isSampling() bool {
+ return props.Pgo.Sampling != nil && *props.Pgo.Sampling == true
+}
+
func (pgo *pgo) props() []interface{} {
return []interface{}{&pgo.Properties}
}
-func (pgo *pgo) profileGatherFlags(ctx ModuleContext) string {
- if *pgo.Properties.Pgo.Instrumentation {
- return profileInstrumentFlag
+func (pgo *pgo) addProfileGatherFlags(ctx ModuleContext, flags Flags) Flags {
+ if pgo.Properties.isInstrumentation() {
+ flags.CFlags = append(flags.CFlags, profileInstrumentFlag)
+ // The profile runtime is added below in deps(). Add the below
+ // flag, which is the only other link-time action performed by
+ // the Clang driver during link.
+ flags.LdFlags = append(flags.LdFlags, "-u__llvm_profile_runtime")
}
- if *pgo.Properties.Pgo.Sampling {
- return profileSamplingFlag
+ if pgo.Properties.isSampling() {
+ flags.CFlags = append(flags.CFlags, profileSamplingFlag)
+ flags.LdFlags = append(flags.LdFlags, profileSamplingFlag)
}
- return ""
+ return flags
}
func (pgo *pgo) profileUseFlag(ctx ModuleContext, file string) string {
- if *pgo.Properties.Pgo.Instrumentation {
+ if pgo.Properties.isInstrumentation() {
return fmt.Sprintf(profileUseInstrumentFormat, file)
}
- if *pgo.Properties.Pgo.Sampling {
+ if pgo.Properties.isSampling() {
return fmt.Sprintf(profileUseSamplingFormat, file)
}
return ""
@@ -81,8 +95,8 @@
}
func (props *PgoProperties) isPGO(ctx BaseModuleContext) bool {
- isInstrumentation := props.Pgo.Instrumentation != nil
- isSampling := props.Pgo.Sampling != nil
+ isInstrumentation := props.isInstrumentation()
+ isSampling := props.isSampling()
profileKindPresent := isInstrumentation || isSampling
filePresent := props.Pgo.Profile_file != nil
@@ -110,13 +124,14 @@
}
// Sampling not supported yet
- //
- // TODO When sampling support is turned on, check that instrumentation and
- // sampling are not simultaneously specified
if isSampling {
ctx.PropertyErrorf("pgo.sampling", "\"sampling\" is not supported yet)")
}
+ if isSampling && isInstrumentation {
+ ctx.PropertyErrorf("pgo", "Exactly one of \"instrumentation\" and \"sampling\" properties must be set")
+ }
+
return true
}
@@ -156,6 +171,14 @@
}
}
+func (pgo *pgo) deps(ctx BaseModuleContext, deps Deps) Deps {
+ if pgo.Properties.ShouldProfileModule {
+ runtimeLibrary := config.ProfileRuntimeLibrary(ctx.toolchain())
+ deps.LateStaticLibs = append(deps.LateStaticLibs, runtimeLibrary)
+ }
+ return deps
+}
+
func (pgo *pgo) flags(ctx ModuleContext, flags Flags) Flags {
if ctx.Host() {
return flags
@@ -165,10 +188,7 @@
// Add flags to profile this module based on its profile_kind
if props.ShouldProfileModule {
- profileGatherFlags := pgo.profileGatherFlags(ctx)
- flags.LdFlags = append(flags.LdFlags, profileGatherFlags)
- flags.CFlags = append(flags.CFlags, profileGatherFlags)
- return flags
+ return pgo.addProfileGatherFlags(ctx, flags)
}
// If the PGO profiles project is found, and this module has PGO
diff --git a/cmd/merge_zips/merge_zips.go b/cmd/merge_zips/merge_zips.go
index a94392b..e16c00e 100644
--- a/cmd/merge_zips/merge_zips.go
+++ b/cmd/merge_zips/merge_zips.go
@@ -29,26 +29,26 @@
"android/soong/third_party/zip"
)
-type stripDir struct{}
+type fileList []string
-func (s *stripDir) String() string {
+func (f *fileList) String() string {
return `""`
}
-func (s *stripDir) Set(dir string) error {
- stripDirs = append(stripDirs, filepath.Clean(dir))
+func (f *fileList) Set(name string) error {
+ *f = append(*f, filepath.Clean(name))
return nil
}
-type zipToNotStrip struct{}
+type zipsToNotStripSet map[string]bool
-func (s *zipToNotStrip) String() string {
+func (s zipsToNotStripSet) String() string {
return `""`
}
-func (s *zipToNotStrip) Set(zip_path string) error {
- zipsToNotStrip[zip_path] = true
+func (s zipsToNotStripSet) Set(zip_path string) error {
+ s[zip_path] = true
return nil
}
@@ -56,15 +56,17 @@
var (
sortEntries = flag.Bool("s", false, "sort entries (defaults to the order from the input zip files)")
emulateJar = flag.Bool("j", false, "sort zip entries using jar ordering (META-INF first)")
- stripDirs []string
- zipsToNotStrip = make(map[string]bool)
+ stripDirs fileList
+ stripFiles fileList
+ zipsToNotStrip = make(zipsToNotStripSet)
stripDirEntries = flag.Bool("D", false, "strip directory entries from the output zip file")
manifest = flag.String("m", "", "manifest file to insert in jar")
)
func init() {
- flag.Var(&stripDir{}, "stripDir", "the prefix of file path to be excluded from the output zip")
- flag.Var(&zipToNotStrip{}, "zipToNotStrip", "the input zip file which is not applicable for stripping")
+ flag.Var(&stripDirs, "stripDir", "the prefix of file path to be excluded from the output zip")
+ flag.Var(&stripFiles, "stripFile", "filenames to be excluded from the output zip, accepts wildcards")
+ flag.Var(&zipsToNotStrip, "zipToNotStrip", "the input zip file which is not applicable for stripping")
}
func main() {
@@ -243,20 +245,9 @@
for _, namedReader := range readers {
_, skipStripThisZip := zipsToNotStrip[namedReader.path]
- FileLoop:
for _, file := range namedReader.reader.File {
- if !skipStripThisZip {
- for _, dir := range stripDirs {
- if strings.HasPrefix(file.Name, dir+"/") {
- if emulateJar {
- if file.Name != jar.MetaDir && file.Name != jar.ManifestFile {
- continue FileLoop
- }
- } else {
- continue FileLoop
- }
- }
- }
+ if !skipStripThisZip && shouldStripFile(emulateJar, file.Name) {
+ continue
}
if stripDirEntries && file.FileInfo().IsDir() {
@@ -310,6 +301,28 @@
return nil
}
+func shouldStripFile(emulateJar bool, name string) bool {
+ for _, dir := range stripDirs {
+ if strings.HasPrefix(name, dir+"/") {
+ if emulateJar {
+ if name != jar.MetaDir && name != jar.ManifestFile {
+ return true
+ }
+ } else {
+ return true
+ }
+ }
+ }
+ for _, pattern := range stripFiles {
+ if match, err := filepath.Match(pattern, filepath.Base(name)); err != nil {
+ panic(fmt.Errorf("%s: %s", err.Error(), pattern))
+ } else if match {
+ return true
+ }
+ }
+ return false
+}
+
func jarSort(files []fileMapping) {
sort.SliceStable(files, func(i, j int) bool {
return jar.EntryNamesLess(files[i].dest, files[j].dest)
diff --git a/jar/jar.go b/jar/jar.go
index 08fa1ab..653e5ee 100644
--- a/jar/jar.go
+++ b/jar/jar.go
@@ -31,7 +31,7 @@
ModuleInfoClass = "module-info.class"
)
-var DefaultTime = time.Date(2009, 1, 1, 0, 0, 0, 0, time.UTC)
+var DefaultTime = time.Date(2008, 1, 1, 0, 0, 0, 0, time.UTC)
var MetaDirExtra = [2]byte{0xca, 0xfe}
diff --git a/java/builder.go b/java/builder.go
index b924d65..ca0d2c5 100644
--- a/java/builder.go
+++ b/java/builder.go
@@ -99,10 +99,12 @@
blueprint.RuleParams{
Command: `rm -rf "$outDir" && mkdir -p "$outDir" && ` +
`${config.DxCmd} --dex --output=$outDir $dxFlags $in && ` +
- `${config.SoongZipCmd} -jar -o $out -C $outDir -D $outDir`,
+ `${config.SoongZipCmd} -o $outDir/classes.dex.jar -C $outDir -D $outDir && ` +
+ `${config.MergeZipsCmd} -D -stripFile "*.class" $out $outDir/classes.dex.jar $in`,
CommandDeps: []string{
"${config.DxCmd}",
"${config.SoongZipCmd}",
+ "${config.MergeZipsCmd}",
},
},
"outDir", "dxFlags")
@@ -298,11 +300,13 @@
return outputFile
}
-func TransformClassesJarToDexJar(ctx android.ModuleContext, classesJar android.Path,
+// Converts a classes.jar file to classes*.dex, then combines the dex files with any resources
+// in the classes.jar file into a dex jar.
+func TransformClassesJarToDexJar(ctx android.ModuleContext, stem string, classesJar android.Path,
flags javaBuilderFlags) android.Path {
outDir := android.PathForModuleOut(ctx, "dex")
- outputFile := android.PathForModuleOut(ctx, "classes.dex.jar")
+ outputFile := android.PathForModuleOut(ctx, stem)
ctx.ModuleBuild(pctx, android.ModuleBuildParams{
Rule: dx,
diff --git a/java/config/config.go b/java/config/config.go
index 4f74ef2..70b8fe5 100644
--- a/java/config/config.go
+++ b/java/config/config.go
@@ -53,8 +53,16 @@
pctx.VariableConfigMethod("hostPrebuiltTag", android.Config.PrebuiltOS)
- pctx.SourcePathVariableWithEnvOverride("JavaHome",
- "prebuilts/jdk/jdk8/${hostPrebuiltTag}", "OVERRIDE_ANDROID_JAVA_HOME")
+ pctx.VariableFunc("JavaHome", func(config interface{}) (string, error) {
+ if override := config.(android.Config).Getenv("OVERRIDE_ANDROID_JAVA_HOME"); override != "" {
+ return override, nil
+ }
+ if jdk9 := config.(android.Config).Getenv("EXPERIMENTAL_USE_OPENJDK9"); jdk9 != "" {
+ return "prebuilts/jdk/jdk9/${hostPrebuiltTag}", nil
+ }
+ return "prebuilts/jdk/jdk8/${hostPrebuiltTag}", nil
+ })
+
pctx.SourcePathVariable("JavaToolchain", "${JavaHome}/bin")
pctx.SourcePathVariableWithEnvOverride("JavacCmd",
"${JavaToolchain}/javac", "ALTERNATE_JAVAC")
diff --git a/java/java.go b/java/java.go
index 9cde824..bab77c5 100644
--- a/java/java.go
+++ b/java/java.go
@@ -153,9 +153,6 @@
// output file containing classes.dex
dexJarFile android.Path
- // output files containing resources
- resourceJarFiles android.Paths
-
// output file suitable for installing or running
outputFile android.Path
@@ -173,7 +170,6 @@
type Dependency interface {
ClasspathFiles() android.Paths
- ResourceJarFiles() android.Paths
AidlIncludeDirs() android.Paths
}
@@ -380,7 +376,6 @@
case staticLibTag:
deps.classpath = append(deps.classpath, dep.ClasspathFiles()...)
deps.staticJars = append(deps.staticJars, dep.ClasspathFiles()...)
- deps.staticJarResources = append(deps.staticJarResources, dep.ResourceJarFiles()...)
case frameworkResTag:
if ctx.ModuleName() == "framework" {
// framework.jar has a one-off dependency on the R.java and Manifest.java files
@@ -486,26 +481,20 @@
resDeps = append(resDeps, fileDeps...)
if proptools.Bool(j.properties.Include_srcs) {
- srcArgs, srcDeps := ResourceFilesToJarArgs(ctx, j.properties.Srcs, j.properties.Exclude_srcs)
+ srcArgs, srcDeps := SourceFilesToJarArgs(ctx, j.properties.Srcs, j.properties.Exclude_srcs)
resArgs = append(resArgs, srcArgs...)
resDeps = append(resDeps, srcDeps...)
}
if len(resArgs) > 0 {
- // Combine classes + resources into classes-full-debug.jar
resourceJar := TransformResourcesToJar(ctx, resArgs, resDeps)
if ctx.Failed() {
return
}
- j.resourceJarFiles = append(j.resourceJarFiles, resourceJar)
jars = append(jars, resourceJar)
}
- // Propagate the resources from the transitive closure of static dependencies for copying
- // into dex jars
- j.resourceJarFiles = append(j.resourceJarFiles, deps.staticJarResources...)
-
// static classpath jars have the resources in them, so the resource jars aren't necessary here
jars = append(jars, deps.staticJars...)
@@ -580,17 +569,12 @@
return
}
- // Compile classes.jar into classes.dex
- dexJarFile := TransformClassesJarToDexJar(ctx, desugarJar, flags)
+ // Compile classes.jar into classes.dex and then javalib.jar
+ outputFile = TransformClassesJarToDexJar(ctx, "javalib.jar", desugarJar, flags)
if ctx.Failed() {
return
}
- jars := android.Paths{dexJarFile}
- jars = append(jars, j.resourceJarFiles...)
-
- outputFile = TransformJarsToJar(ctx, "javalib.jar", jars, android.OptionalPath{}, true)
-
j.dexJarFile = outputFile
}
ctx.CheckbuildFile(outputFile)
@@ -607,10 +591,6 @@
return android.Paths{j.classpathFile}
}
-func (j *Module) ResourceJarFiles() android.Paths {
- return j.resourceJarFiles
-}
-
func (j *Module) AidlIncludeDirs() android.Paths {
return j.exportAidlIncludeDirs
}
@@ -777,11 +757,6 @@
return j.classpathFiles
}
-func (j *Import) ResourceJarFiles() android.Paths {
- // resources are in the ClasspathFiles
- return nil
-}
-
func (j *Import) AidlIncludeDirs() android.Paths {
return nil
}
diff --git a/java/java_test.go b/java/java_test.go
index a4a3f52..c2c7ee2 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -408,16 +408,16 @@
args string
}{
{
- // Test that a module with java_resource_dirs includes a file list file
+ // Test that a module with java_resource_dirs includes the files
name: "resource dirs",
prop: `java_resource_dirs: ["res"]`,
- args: "-C res -l ",
+ args: "-C res -f res/a -f res/b",
},
{
// Test that a module with java_resources includes the files
name: "resource files",
prop: `java_resources: ["res/a", "res/b"]`,
- args: "-C . -f res/a -C . -f res/b",
+ args: "-C . -f res/a -f res/b",
},
{
// Test that a module with a filegroup in java_resources includes the files with the
@@ -430,13 +430,13 @@
path: "res",
srcs: ["res/a", "res/b"],
}`,
- args: "-C res -f res/a -C res -f res/b",
+ args: "-C res -f res/a -f res/b",
},
{
// Test that a module with "include_srcs: true" includes its source files in the resources jar
name: "include sources",
prop: `include_srcs: true`,
- args: "-C . -f a.java -C . -f b.java -C . -f c.java",
+ args: "-C . -f a.java -f b.java -f c.java",
},
}
@@ -462,8 +462,8 @@
foo.Inputs.Strings(), fooRes.Output.String())
}
- if !strings.Contains(fooRes.Args["jarArgs"], test.args) {
- t.Errorf("foo resource jar args %q does not contain %q",
+ if fooRes.Args["jarArgs"] != test.args {
+ t.Errorf("foo resource jar args %q is not %q",
fooRes.Args["jarArgs"], test.args)
}
})
@@ -489,7 +489,7 @@
fooRes := ctx.ModuleForTests("foo", "android_common").Output("res.jar")
- expected := "-C res -l " + fooRes.Implicits[0].String()
+ expected := "-C res -f res/a -f res/b"
if fooRes.Args["jarArgs"] != expected {
t.Errorf("foo resource jar args %q is not %q",
fooRes.Args["jarArgs"], expected)
diff --git a/java/proto.go b/java/proto.go
index 324868a..dd8cabd 100644
--- a/java/proto.go
+++ b/java/proto.go
@@ -88,7 +88,7 @@
flags.protoOutFlag = "--javanano_out"
case "stream":
flags.protoOutFlag = "--javastream_out"
- case "lite", "":
+ case "lite", "full", "":
flags.protoOutFlag = "--java_out"
default:
ctx.PropertyErrorf("proto.type", "unknown proto type %q",
diff --git a/java/resources.go b/java/resources.go
index 85ebd52..a596fd7 100644
--- a/java/resources.go
+++ b/java/resources.go
@@ -19,8 +19,6 @@
"path/filepath"
"strings"
- "github.com/google/blueprint/bootstrap"
-
"android/soong/android"
)
@@ -33,15 +31,6 @@
"**/*~",
}
-func isStringInSlice(str string, slice []string) bool {
- for _, s := range slice {
- if s == str {
- return true
- }
- }
- return false
-}
-
func ResourceDirsToJarArgs(ctx android.ModuleContext,
resourceDirs, excludeDirs []string) (args []string, deps android.Paths) {
var excludes []string
@@ -53,40 +42,64 @@
excludes = append(excludes, resourceExcludes...)
- for _, resourceDir := range resourceDirs {
- if isStringInSlice(resourceDir, excludeDirs) {
- continue
- }
- resourceDir := android.PathForModuleSrc(ctx, resourceDir)
- dirs := ctx.Glob(resourceDir.String(), nil)
- for _, dir := range dirs {
- fileListFile := android.ResPathWithName(ctx, dir, "resources.list")
- depFile := fileListFile.String() + ".d"
+ for _, dir := range resourceDirs {
+ dir := android.PathForModuleSrc(ctx, dir).String()
+ files := ctx.Glob(filepath.Join(dir, "**/*"), excludes)
- pattern := filepath.Join(dir.String(), "**/*")
- bootstrap.GlobFile(ctx, pattern, excludes, fileListFile.String(), depFile)
- args = append(args,
- "-C", dir.String(),
- "-l", fileListFile.String())
- deps = append(deps, fileListFile)
+ deps = append(deps, files...)
+
+ if len(files) > 0 {
+ args = append(args, "-C", dir)
+
+ for _, f := range files {
+ path := f.String()
+ if !strings.HasPrefix(path, dir) {
+ panic(fmt.Errorf("path %q does not start with %q", path, dir))
+ }
+ args = append(args, "-f", path)
+ }
}
}
return args, deps
}
+// Convert java_resources properties to arguments to soong_zip -jar, ignoring common patterns
+// that should not be treated as resources (including *.java).
func ResourceFilesToJarArgs(ctx android.ModuleContext,
res, exclude []string) (args []string, deps android.Paths) {
+
+ exclude = append([]string(nil), exclude...)
+ exclude = append(exclude, resourceExcludes...)
+ return resourceFilesToJarArgs(ctx, res, exclude)
+}
+
+// Convert java_resources properties to arguments to soong_zip -jar, keeping files that should
+// normally not used as resources like *.java
+func SourceFilesToJarArgs(ctx android.ModuleContext,
+ res, exclude []string) (args []string, deps android.Paths) {
+
+ return resourceFilesToJarArgs(ctx, res, exclude)
+}
+
+func resourceFilesToJarArgs(ctx android.ModuleContext,
+ res, exclude []string) (args []string, deps android.Paths) {
+
files := ctx.ExpandSources(res, exclude)
- for _, f := range files {
+ lastDir := ""
+ for i, f := range files {
rel := f.Rel()
path := f.String()
if !strings.HasSuffix(path, rel) {
panic(fmt.Errorf("path %q does not end with %q", path, rel))
}
- path = filepath.Clean(strings.TrimSuffix(path, rel))
- args = append(args, "-C", filepath.Clean(path), "-f", f.String())
+ dir := filepath.Clean(strings.TrimSuffix(path, rel))
+ if i == 0 || dir != lastDir {
+ args = append(args, "-C", dir)
+ }
+ args = append(args, "-f", path)
+ lastDir = dir
}
return args, files