Use Path instead of string for file paths

This centralizes verification and common operations, like converting the
path to a source file to the path for a built object.

It also embeds the configuration knowledge into the path, so that we can
remove "${SrcDir}/path" from the ninja file. When SrcDir is '.', that
leads to paths like './path' instead of just 'path' like make is doing,
causing differences in compiled binaries.

Change-Id: Ib4e8910a6e867ce1b7b420d927c04f1142a7589e
This commit is contained in:
Dan Willemsen
2015-09-23 15:26:20 -07:00
parent fafa3dc7e2
commit 34cc69e4bf
30 changed files with 1430 additions and 763 deletions

View File

@@ -98,10 +98,14 @@ bootstrap_go_package {
"common/glob.go", "common/glob.go",
"common/module.go", "common/module.go",
"common/mutator.go", "common/mutator.go",
"common/package_ctx.go",
"common/paths.go", "common/paths.go",
"common/util.go", "common/util.go",
"common/variable.go", "common/variable.go",
], ],
testSrcs: [
"common/paths_test.go",
],
} }
bootstrap_go_package { bootstrap_go_package {

View File

@@ -16,7 +16,6 @@ package cc
import ( import (
"io" "io"
"path/filepath"
"strings" "strings"
"android/soong/common" "android/soong/common"
@@ -29,7 +28,7 @@ func (c *CCLibrary) AndroidMk() (ret common.AndroidMkData) {
ret.Class = "SHARED_LIBRARIES" ret.Class = "SHARED_LIBRARIES"
} }
ret.OutputFile = c.outputFile() ret.OutputFile = c.outputFile()
ret.Extra = func(name, prefix, outputFile string, arch common.Arch) (ret []string) { ret.Extra = func(name, prefix string, outputFile common.Path, arch common.Arch) (ret []string) {
exportedIncludes := c.exportedFlags() exportedIncludes := c.exportedFlags()
for i := range exportedIncludes { for i := range exportedIncludes {
exportedIncludes[i] = strings.TrimPrefix(exportedIncludes[i], "-I") exportedIncludes[i] = strings.TrimPrefix(exportedIncludes[i], "-I")
@@ -38,7 +37,7 @@ func (c *CCLibrary) AndroidMk() (ret common.AndroidMkData) {
ret = append(ret, "LOCAL_EXPORT_C_INCLUDE_DIRS := "+strings.Join(exportedIncludes, " ")) ret = append(ret, "LOCAL_EXPORT_C_INCLUDE_DIRS := "+strings.Join(exportedIncludes, " "))
} }
ret = append(ret, "LOCAL_MODULE_SUFFIX := "+filepath.Ext(outputFile)) ret = append(ret, "LOCAL_MODULE_SUFFIX := "+outputFile.Ext())
ret = append(ret, "LOCAL_SHARED_LIBRARIES_"+arch.ArchType.String()+" := "+strings.Join(c.savedDepNames.SharedLibs, " ")) ret = append(ret, "LOCAL_SHARED_LIBRARIES_"+arch.ArchType.String()+" := "+strings.Join(c.savedDepNames.SharedLibs, " "))
if c.Properties.Relative_install_path != "" { if c.Properties.Relative_install_path != "" {
@@ -57,9 +56,9 @@ func (c *CCLibrary) AndroidMk() (ret common.AndroidMkData) {
func (c *ccObject) AndroidMk() (ret common.AndroidMkData) { func (c *ccObject) AndroidMk() (ret common.AndroidMkData) {
ret.OutputFile = c.outputFile() ret.OutputFile = c.outputFile()
ret.Custom = func(w io.Writer, name, prefix string) { ret.Custom = func(w io.Writer, name, prefix string) {
out := c.outputFile() out := c.outputFile().Path()
io.WriteString(w, "$("+prefix+"TARGET_OUT_INTERMEDIATE_LIBRARIES)/"+name+objectExtension+": "+out+" | $(ACP)\n") io.WriteString(w, "$("+prefix+"TARGET_OUT_INTERMEDIATE_LIBRARIES)/"+name+objectExtension+": "+out.String()+" | $(ACP)\n")
io.WriteString(w, "\t$(copy-file-to-target)\n") io.WriteString(w, "\t$(copy-file-to-target)\n")
} }
return return
@@ -67,7 +66,7 @@ func (c *ccObject) AndroidMk() (ret common.AndroidMkData) {
func (c *CCBinary) AndroidMk() (ret common.AndroidMkData) { func (c *CCBinary) AndroidMk() (ret common.AndroidMkData) {
ret.Class = "EXECUTABLES" ret.Class = "EXECUTABLES"
ret.Extra = func(name, prefix, outputFile string, arch common.Arch) []string { ret.Extra = func(name, prefix string, outputFile common.Path, arch common.Arch) []string {
ret := []string{ ret := []string{
"LOCAL_CXX_STL := none", "LOCAL_CXX_STL := none",
"LOCAL_SYSTEM_SHARED_LIBRARIES :=", "LOCAL_SYSTEM_SHARED_LIBRARIES :=",

View File

@@ -78,7 +78,7 @@ const (
func init() { func init() {
pctx.StaticVariable("arm64GccVersion", arm64GccVersion) pctx.StaticVariable("arm64GccVersion", arm64GccVersion)
pctx.StaticVariable("arm64GccRoot", pctx.SourcePathVariable("arm64GccRoot",
"prebuilts/gcc/${HostPrebuiltTag}/aarch64/aarch64-linux-android-${arm64GccVersion}") "prebuilts/gcc/${HostPrebuiltTag}/aarch64/aarch64-linux-android-${arm64GccVersion}")
pctx.StaticVariable("arm64GccTriple", "aarch64-linux-android") pctx.StaticVariable("arm64GccTriple", "aarch64-linux-android")

View File

@@ -154,7 +154,7 @@ func init() {
pctx.StaticVariable("armGccVersion", armGccVersion) pctx.StaticVariable("armGccVersion", armGccVersion)
pctx.StaticVariable("armGccRoot", pctx.SourcePathVariable("armGccRoot",
"prebuilts/gcc/${HostPrebuiltTag}/arm/arm-linux-androideabi-${armGccVersion}") "prebuilts/gcc/${HostPrebuiltTag}/arm/arm-linux-androideabi-${armGccVersion}")
pctx.StaticVariable("armGccTriple", "arm-linux-androideabi") pctx.StaticVariable("armGccTriple", "arm-linux-androideabi")

View File

@@ -28,7 +28,6 @@ import (
"strings" "strings"
"github.com/google/blueprint" "github.com/google/blueprint"
"github.com/google/blueprint/pathtools"
) )
const ( const (
@@ -37,7 +36,7 @@ const (
) )
var ( var (
pctx = blueprint.NewPackageContext("android/soong/cc") pctx = common.NewPackageContext("android/soong/cc")
cc = pctx.StaticRule("cc", cc = pctx.StaticRule("cc",
blueprint.RuleParams{ blueprint.RuleParams{
@@ -102,7 +101,7 @@ var (
}, },
"objcopyCmd", "prefix") "objcopyCmd", "prefix")
copyGccLibPath = pctx.StaticVariable("copyGccLibPath", "${SrcDir}/build/soong/copygcclib.sh") copyGccLibPath = pctx.SourcePathVariable("copyGccLibPath", "build/soong/copygcclib.sh")
copyGccLib = pctx.StaticRule("copyGccLib", copyGccLib = pctx.StaticRule("copyGccLib",
blueprint.RuleParams{ blueprint.RuleParams{
@@ -141,45 +140,24 @@ type builderFlags struct {
} }
// Generate rules for compiling multiple .c, .cpp, or .S files to individual .o files // Generate rules for compiling multiple .c, .cpp, or .S files to individual .o files
func TransformSourceToObj(ctx common.AndroidModuleContext, subdir string, srcFiles []string, func TransformSourceToObj(ctx common.AndroidModuleContext, subdir string, srcFiles common.Paths,
flags builderFlags, deps []string) (objFiles []string) { flags builderFlags, deps common.Paths) (objFiles common.Paths) {
srcRoot := ctx.AConfig().SrcDir() objFiles = make(common.Paths, len(srcFiles))
intermediatesRoot := ctx.AConfig().IntermediatesDir()
objFiles = make([]string, len(srcFiles))
objDir := common.ModuleObjDir(ctx)
if subdir != "" {
objDir = filepath.Join(objDir, subdir)
}
cflags := flags.globalFlags + " " + flags.cFlags + " " + flags.conlyFlags cflags := flags.globalFlags + " " + flags.cFlags + " " + flags.conlyFlags
cppflags := flags.globalFlags + " " + flags.cFlags + " " + flags.cppFlags cppflags := flags.globalFlags + " " + flags.cFlags + " " + flags.cppFlags
asflags := flags.globalFlags + " " + flags.asFlags asflags := flags.globalFlags + " " + flags.asFlags
for i, srcFile := range srcFiles { for i, srcFile := range srcFiles {
var objFile string objFile := common.ObjPathWithExt(ctx, srcFile, subdir, "o")
if strings.HasPrefix(srcFile, intermediatesRoot) {
objFile = strings.TrimPrefix(srcFile, intermediatesRoot)
objFile = filepath.Join(objDir, "gen", objFile)
} else if strings.HasPrefix(srcFile, srcRoot) {
srcFile, _ = filepath.Rel(srcRoot, srcFile)
objFile = filepath.Join(objDir, srcFile)
} else if srcRoot == "." && srcFile[0] != '/' {
objFile = filepath.Join(objDir, srcFile)
} else {
ctx.ModuleErrorf("source file %q is not in source directory %q", srcFile, srcRoot)
continue
}
objFile = pathtools.ReplaceExtension(objFile, "o")
objFiles[i] = objFile objFiles[i] = objFile
var moduleCflags string var moduleCflags string
var ccCmd string var ccCmd string
switch filepath.Ext(srcFile) { switch srcFile.Ext() {
case ".S", ".s": case ".S", ".s":
ccCmd = "gcc" ccCmd = "gcc"
moduleCflags = asflags moduleCflags = asflags
@@ -204,15 +182,15 @@ func TransformSourceToObj(ctx common.AndroidModuleContext, subdir string, srcFil
panic("unrecoginzied ccCmd") panic("unrecoginzied ccCmd")
} }
ccCmd = "${clangPath}" + ccCmd ccCmd = "${clangPath}/" + ccCmd
} else { } else {
ccCmd = gccCmd(flags.toolchain, ccCmd) ccCmd = gccCmd(flags.toolchain, ccCmd)
} }
ctx.Build(pctx, blueprint.BuildParams{ ctx.ModuleBuild(pctx, common.ModuleBuildParams{
Rule: cc, Rule: cc,
Outputs: []string{objFile}, Output: objFile,
Inputs: []string{srcFile}, Input: srcFile,
Implicits: deps, Implicits: deps,
Args: map[string]string{ Args: map[string]string{
"cFlags": moduleCflags, "cFlags": moduleCflags,
@@ -225,16 +203,16 @@ func TransformSourceToObj(ctx common.AndroidModuleContext, subdir string, srcFil
} }
// Generate a rule for compiling multiple .o files to a static library (.a) // Generate a rule for compiling multiple .o files to a static library (.a)
func TransformObjToStaticLib(ctx common.AndroidModuleContext, objFiles []string, func TransformObjToStaticLib(ctx common.AndroidModuleContext, objFiles common.Paths,
flags builderFlags, outputFile string) { flags builderFlags, outputFile common.ModuleOutPath) {
arCmd := gccCmd(flags.toolchain, "ar") arCmd := gccCmd(flags.toolchain, "ar")
arFlags := "crsPD" arFlags := "crsPD"
ctx.Build(pctx, blueprint.BuildParams{ ctx.ModuleBuild(pctx, common.ModuleBuildParams{
Rule: ar, Rule: ar,
Outputs: []string{outputFile}, Output: outputFile,
Inputs: objFiles, Inputs: objFiles,
Args: map[string]string{ Args: map[string]string{
"arFlags": arFlags, "arFlags": arFlags,
"arCmd": arCmd, "arCmd": arCmd,
@@ -246,18 +224,20 @@ func TransformObjToStaticLib(ctx common.AndroidModuleContext, objFiles []string,
// darwin. The darwin ar tool doesn't support @file for list files, and has a // darwin. The darwin ar tool doesn't support @file for list files, and has a
// very small command line length limit, so we have to split the ar into multiple // very small command line length limit, so we have to split the ar into multiple
// steps, each appending to the previous one. // steps, each appending to the previous one.
func TransformDarwinObjToStaticLib(ctx common.AndroidModuleContext, objFiles []string, func TransformDarwinObjToStaticLib(ctx common.AndroidModuleContext, objFiles common.Paths,
flags builderFlags, outputFile string) { flags builderFlags, outputPath common.ModuleOutPath) {
arCmd := "ar" arCmd := "ar"
arFlags := "cqs" arFlags := "cqs"
// ARG_MAX on darwin is 262144, use half that to be safe // ARG_MAX on darwin is 262144, use half that to be safe
objFilesLists, err := splitListForSize(objFiles, 131072) objFilesLists, err := splitListForSize(objFiles.Strings(), 131072)
if err != nil { if err != nil {
ctx.ModuleErrorf("%s", err.Error()) ctx.ModuleErrorf("%s", err.Error())
} }
outputFile := outputPath.String()
var in, out string var in, out string
for i, l := range objFilesLists { for i, l := range objFilesLists {
in = out in = out
@@ -295,12 +275,12 @@ func TransformDarwinObjToStaticLib(ctx common.AndroidModuleContext, objFiles []s
// Generate a rule for compiling multiple .o files, plus static libraries, whole static libraries, // Generate a rule for compiling multiple .o files, plus static libraries, whole static libraries,
// and shared libraires, to a shared library (.so) or dynamic executable // and shared libraires, to a shared library (.so) or dynamic executable
func TransformObjToDynamicBinary(ctx common.AndroidModuleContext, func TransformObjToDynamicBinary(ctx common.AndroidModuleContext,
objFiles, sharedLibs, staticLibs, lateStaticLibs, wholeStaticLibs, deps []string, objFiles, sharedLibs, staticLibs, lateStaticLibs, wholeStaticLibs, deps common.Paths,
crtBegin, crtEnd string, groupLate bool, flags builderFlags, outputFile string) { crtBegin, crtEnd common.OptionalPath, groupLate bool, flags builderFlags, outputFile common.WritablePath) {
var ldCmd string var ldCmd string
if flags.clang { if flags.clang {
ldCmd = "${clangPath}clang++" ldCmd = "${clangPath}/clang++"
} else { } else {
ldCmd = gccCmd(flags.toolchain, "g++") ldCmd = gccCmd(flags.toolchain, "g++")
} }
@@ -310,31 +290,31 @@ func TransformObjToDynamicBinary(ctx common.AndroidModuleContext,
if len(wholeStaticLibs) > 0 { if len(wholeStaticLibs) > 0 {
if ctx.Host() && ctx.Darwin() { if ctx.Host() && ctx.Darwin() {
libFlagsList = append(libFlagsList, common.JoinWithPrefix(wholeStaticLibs, "-force_load ")) libFlagsList = append(libFlagsList, common.JoinWithPrefix(wholeStaticLibs.Strings(), "-force_load "))
} else { } else {
libFlagsList = append(libFlagsList, "-Wl,--whole-archive ") libFlagsList = append(libFlagsList, "-Wl,--whole-archive ")
libFlagsList = append(libFlagsList, wholeStaticLibs...) libFlagsList = append(libFlagsList, wholeStaticLibs.Strings()...)
libFlagsList = append(libFlagsList, "-Wl,--no-whole-archive ") libFlagsList = append(libFlagsList, "-Wl,--no-whole-archive ")
} }
} }
libFlagsList = append(libFlagsList, staticLibs...) libFlagsList = append(libFlagsList, staticLibs.Strings()...)
if groupLate && len(lateStaticLibs) > 0 { if groupLate && len(lateStaticLibs) > 0 {
libFlagsList = append(libFlagsList, "-Wl,--start-group") libFlagsList = append(libFlagsList, "-Wl,--start-group")
} }
libFlagsList = append(libFlagsList, lateStaticLibs...) libFlagsList = append(libFlagsList, lateStaticLibs.Strings()...)
if groupLate && len(lateStaticLibs) > 0 { if groupLate && len(lateStaticLibs) > 0 {
libFlagsList = append(libFlagsList, "-Wl,--end-group") libFlagsList = append(libFlagsList, "-Wl,--end-group")
} }
for _, lib := range sharedLibs { for _, lib := range sharedLibs {
dir, file := filepath.Split(lib) dir, file := filepath.Split(lib.String())
if !strings.HasPrefix(file, "lib") { if !strings.HasPrefix(file, "lib") {
panic("shared library " + lib + " does not start with lib") panic("shared library " + lib.String() + " does not start with lib")
} }
if !strings.HasSuffix(file, flags.toolchain.ShlibSuffix()) { if !strings.HasSuffix(file, flags.toolchain.ShlibSuffix()) {
panic("shared library " + lib + " does not end with " + flags.toolchain.ShlibSuffix()) panic("shared library " + lib.String() + " does not end with " + flags.toolchain.ShlibSuffix())
} }
libFlagsList = append(libFlagsList, libFlagsList = append(libFlagsList,
"-l"+strings.TrimSuffix(strings.TrimPrefix(file, "lib"), flags.toolchain.ShlibSuffix())) "-l"+strings.TrimSuffix(strings.TrimPrefix(file, "lib"), flags.toolchain.ShlibSuffix()))
@@ -345,29 +325,29 @@ func TransformObjToDynamicBinary(ctx common.AndroidModuleContext,
deps = append(deps, staticLibs...) deps = append(deps, staticLibs...)
deps = append(deps, lateStaticLibs...) deps = append(deps, lateStaticLibs...)
deps = append(deps, wholeStaticLibs...) deps = append(deps, wholeStaticLibs...)
if crtBegin != "" { if crtBegin.Valid() {
deps = append(deps, crtBegin, crtEnd) deps = append(deps, crtBegin.Path(), crtEnd.Path())
} }
ctx.Build(pctx, blueprint.BuildParams{ ctx.ModuleBuild(pctx, common.ModuleBuildParams{
Rule: ld, Rule: ld,
Outputs: []string{outputFile}, Output: outputFile,
Inputs: objFiles, Inputs: objFiles,
Implicits: deps, Implicits: deps,
Args: map[string]string{ Args: map[string]string{
"ldCmd": ldCmd, "ldCmd": ldCmd,
"ldDirFlags": ldDirsToFlags(ldDirs), "ldDirFlags": ldDirsToFlags(ldDirs),
"crtBegin": crtBegin, "crtBegin": crtBegin.String(),
"libFlags": strings.Join(libFlagsList, " "), "libFlags": strings.Join(libFlagsList, " "),
"ldFlags": flags.ldFlags, "ldFlags": flags.ldFlags,
"crtEnd": crtEnd, "crtEnd": crtEnd.String(),
}, },
}) })
} }
// Generate a rule for compiling multiple .o files to a .o using ld partial linking // Generate a rule for compiling multiple .o files to a .o using ld partial linking
func TransformObjsToObj(ctx common.AndroidModuleContext, objFiles []string, func TransformObjsToObj(ctx common.AndroidModuleContext, objFiles common.Paths,
flags builderFlags, outputFile string) { flags builderFlags, outputFile common.WritablePath) {
var ldCmd string var ldCmd string
if flags.clang { if flags.clang {
@@ -376,27 +356,27 @@ func TransformObjsToObj(ctx common.AndroidModuleContext, objFiles []string,
ldCmd = gccCmd(flags.toolchain, "g++") ldCmd = gccCmd(flags.toolchain, "g++")
} }
ctx.Build(pctx, blueprint.BuildParams{ ctx.ModuleBuild(pctx, common.ModuleBuildParams{
Rule: partialLd, Rule: partialLd,
Outputs: []string{outputFile}, Output: outputFile,
Inputs: objFiles, Inputs: objFiles,
Args: map[string]string{ Args: map[string]string{
"ldCmd": ldCmd, "ldCmd": ldCmd,
"ldFlags": flags.ldFlags, "ldFlags": flags.ldFlags,
}, },
}) })
} }
// Generate a rule for runing objcopy --prefix-symbols on a binary // Generate a rule for runing objcopy --prefix-symbols on a binary
func TransformBinaryPrefixSymbols(ctx common.AndroidModuleContext, prefix string, inputFile string, func TransformBinaryPrefixSymbols(ctx common.AndroidModuleContext, prefix string, inputFile common.Path,
flags builderFlags, outputFile string) { flags builderFlags, outputFile common.WritablePath) {
objcopyCmd := gccCmd(flags.toolchain, "objcopy") objcopyCmd := gccCmd(flags.toolchain, "objcopy")
ctx.Build(pctx, blueprint.BuildParams{ ctx.ModuleBuild(pctx, common.ModuleBuildParams{
Rule: prefixSymbols, Rule: prefixSymbols,
Outputs: []string{outputFile}, Output: outputFile,
Inputs: []string{inputFile}, Input: inputFile,
Args: map[string]string{ Args: map[string]string{
"objcopyCmd": objcopyCmd, "objcopyCmd": objcopyCmd,
"prefix": prefix, "prefix": prefix,
@@ -405,11 +385,11 @@ func TransformBinaryPrefixSymbols(ctx common.AndroidModuleContext, prefix string
} }
func CopyGccLib(ctx common.AndroidModuleContext, libName string, func CopyGccLib(ctx common.AndroidModuleContext, libName string,
flags builderFlags, outputFile string) { flags builderFlags, outputFile common.WritablePath) {
ctx.Build(pctx, blueprint.BuildParams{ ctx.ModuleBuild(pctx, common.ModuleBuildParams{
Rule: copyGccLib, Rule: copyGccLib,
Outputs: []string{outputFile}, Output: outputFile,
Args: map[string]string{ Args: map[string]string{
"ccCmd": gccCmd(flags.toolchain, "gcc"), "ccCmd": gccCmd(flags.toolchain, "gcc"),
"cFlags": flags.globalFlags, "cFlags": flags.globalFlags,

274
cc/cc.go
View File

@@ -24,7 +24,6 @@ import (
"strings" "strings"
"github.com/google/blueprint" "github.com/google/blueprint"
"github.com/google/blueprint/pathtools"
"github.com/google/blueprint/proptools" "github.com/google/blueprint/proptools"
"android/soong" "android/soong"
@@ -64,10 +63,9 @@ func init() {
var ( var (
HostPrebuiltTag = pctx.VariableConfigMethod("HostPrebuiltTag", common.Config.PrebuiltOS) HostPrebuiltTag = pctx.VariableConfigMethod("HostPrebuiltTag", common.Config.PrebuiltOS)
SrcDir = pctx.VariableConfigMethod("SrcDir", common.Config.SrcDir)
LibcRoot = pctx.StaticVariable("LibcRoot", "bionic/libc") LibcRoot = pctx.SourcePathVariable("LibcRoot", "bionic/libc")
LibmRoot = pctx.StaticVariable("LibmRoot", "bionic/libm") LibmRoot = pctx.SourcePathVariable("LibmRoot", "bionic/libm")
) )
// Flags used by lots of devices. Putting them in package static variables will save bytes in // Flags used by lots of devices. Putting them in package static variables will save bytes in
@@ -127,19 +125,20 @@ func init() {
// Everything in this list is a crime against abstraction and dependency tracking. // Everything in this list is a crime against abstraction and dependency tracking.
// Do not add anything to this list. // Do not add anything to this list.
pctx.StaticVariable("commonGlobalIncludes", strings.Join([]string{ pctx.PrefixedPathsForSourceVariable("commonGlobalIncludes", "-isystem ",
"-isystem ${SrcDir}/system/core/include", []string{
"-isystem ${SrcDir}/hardware/libhardware/include", "system/core/include",
"-isystem ${SrcDir}/hardware/libhardware_legacy/include", "hardware/libhardware/include",
"-isystem ${SrcDir}/hardware/ril/include", "hardware/libhardware_legacy/include",
"-isystem ${SrcDir}/libnativehelper/include", "hardware/ril/include",
"-isystem ${SrcDir}/frameworks/native/include", "libnativehelper/include",
"-isystem ${SrcDir}/frameworks/native/opengl/include", "frameworks/native/include",
"-isystem ${SrcDir}/frameworks/av/include", "frameworks/native/opengl/include",
"-isystem ${SrcDir}/frameworks/base/include", "frameworks/av/include",
}, " ")) "frameworks/base/include",
})
pctx.StaticVariable("clangPath", "${SrcDir}/prebuilts/clang/host/${HostPrebuiltTag}/3.8/bin/") pctx.SourcePathVariable("clangPath", "prebuilts/clang/host/${HostPrebuiltTag}/3.8/bin")
} }
type CCModuleContext common.AndroidBaseContext type CCModuleContext common.AndroidBaseContext
@@ -162,23 +161,36 @@ type CCModuleType interface {
depsMutator(common.AndroidBottomUpMutatorContext) depsMutator(common.AndroidBottomUpMutatorContext)
// Compile objects into final module // Compile objects into final module
compileModule(common.AndroidModuleContext, CCFlags, CCDeps, []string) compileModule(common.AndroidModuleContext, CCFlags, CCPathDeps, common.Paths)
// Install the built module. // Install the built module.
installModule(common.AndroidModuleContext, CCFlags) installModule(common.AndroidModuleContext, CCFlags)
// Return the output file (.o, .a or .so) for use by other modules // Return the output file (.o, .a or .so) for use by other modules
outputFile() string outputFile() common.OptionalPath
} }
type CCDeps struct { type CCDeps struct {
StaticLibs, SharedLibs, LateStaticLibs, WholeStaticLibs, ObjFiles, Cflags, ReexportedCflags []string StaticLibs, SharedLibs, LateStaticLibs, WholeStaticLibs []string
WholeStaticLibObjFiles []string ObjFiles common.Paths
Cflags, ReexportedCflags []string
CrtBegin, CrtEnd string CrtBegin, CrtEnd string
} }
type CCPathDeps struct {
StaticLibs, SharedLibs, LateStaticLibs, WholeStaticLibs common.Paths
ObjFiles common.Paths
WholeStaticLibObjFiles common.Paths
Cflags, ReexportedCflags []string
CrtBegin, CrtEnd common.OptionalPath
}
type CCFlags struct { type CCFlags struct {
GlobalFlags []string // Flags that apply to C, C++, and assembly source files GlobalFlags []string // Flags that apply to C, C++, and assembly source files
AsFlags []string // Flags that apply to assembly source files AsFlags []string // Flags that apply to assembly source files
@@ -440,7 +452,7 @@ func (c *CCBase) depsMutator(ctx common.AndroidBottomUpMutatorContext) {
ctx.AddVariationDependencies([]blueprint.Variation{{"link", "shared"}}, c.savedDepNames.SharedLibs...) ctx.AddVariationDependencies([]blueprint.Variation{{"link", "shared"}}, c.savedDepNames.SharedLibs...)
ctx.AddDependency(ctx.Module(), c.savedDepNames.ObjFiles...) ctx.AddDependency(ctx.Module(), c.savedDepNames.ObjFiles.Strings()...)
if c.savedDepNames.CrtBegin != "" { if c.savedDepNames.CrtBegin != "" {
ctx.AddDependency(ctx.Module(), c.savedDepNames.CrtBegin) ctx.AddDependency(ctx.Module(), c.savedDepNames.CrtBegin)
} }
@@ -472,17 +484,14 @@ func (c *CCBase) collectFlags(ctx common.AndroidModuleContext, toolchain Toolcha
} }
// Include dir cflags // Include dir cflags
common.CheckSrcDirsExist(ctx, c.Properties.Include_dirs, "include_dirs") rootIncludeDirs := common.PathsForSource(ctx, c.Properties.Include_dirs)
common.CheckModuleSrcDirsExist(ctx, c.Properties.Local_include_dirs, "local_include_dirs") localIncludeDirs := common.PathsForModuleSrc(ctx, c.Properties.Local_include_dirs)
rootIncludeDirs := pathtools.PrefixPaths(c.Properties.Include_dirs, ctx.AConfig().SrcDir())
localIncludeDirs := pathtools.PrefixPaths(c.Properties.Local_include_dirs, common.ModuleSrcDir(ctx))
flags.GlobalFlags = append(flags.GlobalFlags, flags.GlobalFlags = append(flags.GlobalFlags,
includeDirsToFlags(localIncludeDirs), includeDirsToFlags(localIncludeDirs),
includeDirsToFlags(rootIncludeDirs)) includeDirsToFlags(rootIncludeDirs))
rootIncludeFiles := pathtools.PrefixPaths(c.Properties.Include_files, ctx.AConfig().SrcDir()) rootIncludeFiles := common.PathsForSource(ctx, c.Properties.Include_files)
localIncludeFiles := pathtools.PrefixPaths(c.Properties.Local_include_files, common.ModuleSrcDir(ctx)) localIncludeFiles := common.PathsForModuleSrc(ctx, c.Properties.Local_include_files)
flags.GlobalFlags = append(flags.GlobalFlags, flags.GlobalFlags = append(flags.GlobalFlags,
includeFilesToFlags(rootIncludeFiles), includeFilesToFlags(rootIncludeFiles),
@@ -493,13 +502,13 @@ func (c *CCBase) collectFlags(ctx common.AndroidModuleContext, toolchain Toolcha
flags.GlobalFlags = append(flags.GlobalFlags, flags.GlobalFlags = append(flags.GlobalFlags,
"${commonGlobalIncludes}", "${commonGlobalIncludes}",
toolchain.IncludeFlags(), toolchain.IncludeFlags(),
"-I${SrcDir}/libnativehelper/include/nativehelper") "-I"+common.PathForSource(ctx, "libnativehelper/include/nativehelper").String())
} }
flags.GlobalFlags = append(flags.GlobalFlags, []string{ flags.GlobalFlags = append(flags.GlobalFlags, []string{
"-I" + common.ModuleSrcDir(ctx), "-I" + common.PathForModuleSrc(ctx).String(),
"-I" + common.ModuleOutDir(ctx), "-I" + common.PathForModuleOut(ctx).String(),
"-I" + common.ModuleGenDir(ctx), "-I" + common.PathForModuleGen(ctx).String(),
}...) }...)
} }
@@ -636,18 +645,18 @@ func (c *CCBase) flags(ctx common.AndroidModuleContext, flags CCFlags) CCFlags {
// Compile a list of source files into objects a specified subdirectory // Compile a list of source files into objects a specified subdirectory
func (c *CCBase) customCompileObjs(ctx common.AndroidModuleContext, flags CCFlags, func (c *CCBase) customCompileObjs(ctx common.AndroidModuleContext, flags CCFlags,
subdir string, srcFiles, excludes []string) []string { subdir string, srcFiles, excludes []string) common.Paths {
buildFlags := ccFlagsToBuilderFlags(flags) buildFlags := ccFlagsToBuilderFlags(flags)
srcFiles = ctx.ExpandSources(srcFiles, excludes) inputFiles := ctx.ExpandSources(srcFiles, excludes)
srcFiles, deps := genSources(ctx, srcFiles, buildFlags) srcPaths, deps := genSources(ctx, inputFiles, buildFlags)
return TransformSourceToObj(ctx, subdir, srcFiles, buildFlags, deps) return TransformSourceToObj(ctx, subdir, srcPaths, buildFlags, deps)
} }
// Compile files listed in c.Properties.Srcs into objects // Compile files listed in c.Properties.Srcs into objects
func (c *CCBase) compileObjs(ctx common.AndroidModuleContext, flags CCFlags) []string { func (c *CCBase) compileObjs(ctx common.AndroidModuleContext, flags CCFlags) common.Paths {
if c.Properties.SkipCompileObjs { if c.Properties.SkipCompileObjs {
return nil return nil
@@ -657,8 +666,8 @@ func (c *CCBase) compileObjs(ctx common.AndroidModuleContext, flags CCFlags) []s
} }
// Compile generated source files from dependencies // Compile generated source files from dependencies
func (c *CCBase) compileGeneratedObjs(ctx common.AndroidModuleContext, flags CCFlags) []string { func (c *CCBase) compileGeneratedObjs(ctx common.AndroidModuleContext, flags CCFlags) common.Paths {
var srcs []string var srcs common.Paths
if c.Properties.SkipCompileObjs { if c.Properties.SkipCompileObjs {
return nil return nil
@@ -677,13 +686,13 @@ func (c *CCBase) compileGeneratedObjs(ctx common.AndroidModuleContext, flags CCF
return TransformSourceToObj(ctx, "", srcs, ccFlagsToBuilderFlags(flags), nil) return TransformSourceToObj(ctx, "", srcs, ccFlagsToBuilderFlags(flags), nil)
} }
func (c *CCBase) outputFile() string { func (c *CCBase) outputFile() common.OptionalPath {
return "" return common.OptionalPath{}
} }
func (c *CCBase) depsToPathsFromList(ctx common.AndroidModuleContext, func (c *CCBase) depsToPathsFromList(ctx common.AndroidModuleContext,
names []string) (modules []common.AndroidModule, names []string) (modules []common.AndroidModule,
outputFiles []string, exportedFlags []string) { outputFiles common.Paths, exportedFlags []string) {
for _, n := range names { for _, n := range names {
found := false found := false
@@ -707,12 +716,12 @@ func (c *CCBase) depsToPathsFromList(ctx common.AndroidModuleContext,
return return
} }
if outputFile := a.outputFile(); outputFile != "" { if outputFile := a.outputFile(); outputFile.Valid() {
if found { if found {
ctx.ModuleErrorf("multiple modules satisified dependency on %q", otherName) ctx.ModuleErrorf("multiple modules satisified dependency on %q", otherName)
return return
} }
outputFiles = append(outputFiles, outputFile) outputFiles = append(outputFiles, outputFile.Path())
modules = append(modules, a) modules = append(modules, a)
if i, ok := a.(ccExportedFlagsProducer); ok { if i, ok := a.(ccExportedFlagsProducer); ok {
exportedFlags = append(exportedFlags, i.exportedFlags()...) exportedFlags = append(exportedFlags, i.exportedFlags()...)
@@ -735,10 +744,10 @@ func (c *CCBase) depsToPathsFromList(ctx common.AndroidModuleContext,
return modules, outputFiles, exportedFlags return modules, outputFiles, exportedFlags
} }
// Convert depenedency names to paths. Takes a CCDeps containing names and returns a CCDeps // Convert dependency names to paths. Takes a CCDeps containing names and returns a CCPathDeps
// containing paths // containing paths
func (c *CCBase) depsToPaths(ctx common.AndroidModuleContext, depNames CCDeps) CCDeps { func (c *CCBase) depsToPaths(ctx common.AndroidModuleContext, depNames CCDeps) CCPathDeps {
var depPaths CCDeps var depPaths CCPathDeps
var newCflags []string var newCflags []string
var wholeStaticLibModules []common.AndroidModule var wholeStaticLibModules []common.AndroidModule
@@ -778,7 +787,12 @@ func (c *CCBase) depsToPaths(ctx common.AndroidModuleContext, depNames CCDeps) C
depPaths.CrtEnd = obj.object().outputFile() depPaths.CrtEnd = obj.object().outputFile()
} }
} else { } else {
depPaths.ObjFiles = append(depPaths.ObjFiles, obj.object().outputFile()) output := obj.object().outputFile()
if output.Valid() {
depPaths.ObjFiles = append(depPaths.ObjFiles, output.Path())
} else {
ctx.ModuleErrorf("module %s did not provide an output file", otherName)
}
} }
} }
}) })
@@ -908,11 +922,11 @@ func (c *CCLinked) flags(ctx common.AndroidModuleContext, flags CCFlags) CCFlags
// tree is in good enough shape to not need it. // tree is in good enough shape to not need it.
// Host builds will use GNU libstdc++. // Host builds will use GNU libstdc++.
if ctx.Device() { if ctx.Device() {
flags.CFlags = append(flags.CFlags, "-I${SrcDir}/bionic/libstdc++/include") flags.CFlags = append(flags.CFlags, "-I"+common.PathForSource(ctx, "bionic/libstdc++/include").String())
} }
case "ndk_system": case "ndk_system":
ndkSrcRoot := ctx.AConfig().SrcDir() + "/prebuilts/ndk/current/sources/" ndkSrcRoot := common.PathForSource(ctx, "prebuilts/ndk/current/sources/cxx-stl/system/include")
flags.CFlags = append(flags.CFlags, "-isystem "+ndkSrcRoot+"cxx-stl/system/include") flags.CFlags = append(flags.CFlags, "-isystem "+ndkSrcRoot.String())
case "ndk_libc++_shared", "ndk_libc++_static": case "ndk_libc++_shared", "ndk_libc++_static":
// TODO(danalbert): This really shouldn't be here... // TODO(danalbert): This really shouldn't be here...
flags.CppFlags = append(flags.CppFlags, "-std=c++11") flags.CppFlags = append(flags.CppFlags, "-std=c++11")
@@ -1067,23 +1081,23 @@ type CCLibraryProperties struct {
} `android:"arch_variant"` } `android:"arch_variant"`
// local file name to pass to the linker as --version_script // local file name to pass to the linker as --version_script
Version_script string `android:"arch_variant"` Version_script *string `android:"arch_variant"`
// local file name to pass to the linker as -unexported_symbols_list // local file name to pass to the linker as -unexported_symbols_list
Unexported_symbols_list string `android:"arch_variant"` Unexported_symbols_list *string `android:"arch_variant"`
// local file name to pass to the linker as -force_symbols_not_weak_list // local file name to pass to the linker as -force_symbols_not_weak_list
Force_symbols_not_weak_list string `android:"arch_variant"` Force_symbols_not_weak_list *string `android:"arch_variant"`
// local file name to pass to the linker as -force_symbols_weak_list // local file name to pass to the linker as -force_symbols_weak_list
Force_symbols_weak_list string `android:"arch_variant"` Force_symbols_weak_list *string `android:"arch_variant"`
} }
type CCLibrary struct { type CCLibrary struct {
CCLinked CCLinked
reuseFrom ccLibraryInterface reuseFrom ccLibraryInterface
reuseObjFiles []string reuseObjFiles common.Paths
objFiles []string objFiles common.Paths
exportFlags []string exportFlags []string
out string out common.Path
systemLibs []string systemLibs []string
LibraryProperties CCLibraryProperties LibraryProperties CCLibraryProperties
@@ -1102,8 +1116,8 @@ type ccLibraryInterface interface {
ccLibrary() *CCLibrary ccLibrary() *CCLibrary
setReuseFrom(ccLibraryInterface) setReuseFrom(ccLibraryInterface)
getReuseFrom() ccLibraryInterface getReuseFrom() ccLibraryInterface
getReuseObjFiles() []string getReuseObjFiles() common.Paths
allObjFiles() []string allObjFiles() common.Paths
} }
var _ ccLibraryInterface = (*CCLibrary)(nil) var _ ccLibraryInterface = (*CCLibrary)(nil)
@@ -1154,11 +1168,11 @@ func (c *CCLibrary) depNames(ctx common.AndroidBaseContext, depNames CCDeps) CCD
return depNames return depNames
} }
func (c *CCLibrary) outputFile() string { func (c *CCLibrary) outputFile() common.OptionalPath {
return c.out return common.OptionalPathForPath(c.out)
} }
func (c *CCLibrary) getReuseObjFiles() []string { func (c *CCLibrary) getReuseObjFiles() common.Paths {
return c.reuseObjFiles return c.reuseObjFiles
} }
@@ -1170,7 +1184,7 @@ func (c *CCLibrary) getReuseFrom() ccLibraryInterface {
return c.reuseFrom return c.reuseFrom
} }
func (c *CCLibrary) allObjFiles() []string { func (c *CCLibrary) allObjFiles() common.Paths {
return c.objFiles return c.objFiles
} }
@@ -1225,7 +1239,7 @@ func (c *CCLibrary) flags(ctx common.AndroidModuleContext, flags CCFlags) CCFlag
} }
func (c *CCLibrary) compileStaticLibrary(ctx common.AndroidModuleContext, func (c *CCLibrary) compileStaticLibrary(ctx common.AndroidModuleContext,
flags CCFlags, deps CCDeps, objFiles []string) { flags CCFlags, deps CCPathDeps, objFiles common.Paths) {
staticFlags := flags staticFlags := flags
objFilesStatic := c.customCompileObjs(ctx, staticFlags, common.DeviceStaticLibrary, objFilesStatic := c.customCompileObjs(ctx, staticFlags, common.DeviceStaticLibrary,
@@ -1234,7 +1248,7 @@ func (c *CCLibrary) compileStaticLibrary(ctx common.AndroidModuleContext,
objFiles = append(objFiles, objFilesStatic...) objFiles = append(objFiles, objFilesStatic...)
objFiles = append(objFiles, deps.WholeStaticLibObjFiles...) objFiles = append(objFiles, deps.WholeStaticLibObjFiles...)
outputFile := filepath.Join(common.ModuleOutDir(ctx), ctx.ModuleName()+staticLibraryExtension) outputFile := common.PathForModuleOut(ctx, ctx.ModuleName()+staticLibraryExtension)
if ctx.Darwin() { if ctx.Darwin() {
TransformDarwinObjToStaticLib(ctx, objFiles, ccFlagsToBuilderFlags(flags), outputFile) TransformDarwinObjToStaticLib(ctx, objFiles, ccFlagsToBuilderFlags(flags), outputFile)
@@ -1245,8 +1259,7 @@ func (c *CCLibrary) compileStaticLibrary(ctx common.AndroidModuleContext,
c.objFiles = objFiles c.objFiles = objFiles
c.out = outputFile c.out = outputFile
common.CheckModuleSrcDirsExist(ctx, c.Properties.Export_include_dirs, "export_include_dirs") includeDirs := common.PathsForModuleSrc(ctx, c.Properties.Export_include_dirs)
includeDirs := pathtools.PrefixPaths(c.Properties.Export_include_dirs, common.ModuleSrcDir(ctx))
c.exportFlags = []string{includeDirsToFlags(includeDirs)} c.exportFlags = []string{includeDirsToFlags(includeDirs)}
c.exportFlags = append(c.exportFlags, deps.ReexportedCflags...) c.exportFlags = append(c.exportFlags, deps.ReexportedCflags...)
@@ -1254,7 +1267,7 @@ func (c *CCLibrary) compileStaticLibrary(ctx common.AndroidModuleContext,
} }
func (c *CCLibrary) compileSharedLibrary(ctx common.AndroidModuleContext, func (c *CCLibrary) compileSharedLibrary(ctx common.AndroidModuleContext,
flags CCFlags, deps CCDeps, objFiles []string) { flags CCFlags, deps CCPathDeps, objFiles common.Paths) {
sharedFlags := flags sharedFlags := flags
objFilesShared := c.customCompileObjs(ctx, sharedFlags, common.DeviceSharedLibrary, objFilesShared := c.customCompileObjs(ctx, sharedFlags, common.DeviceSharedLibrary,
@@ -1262,43 +1275,43 @@ func (c *CCLibrary) compileSharedLibrary(ctx common.AndroidModuleContext,
objFiles = append(objFiles, objFilesShared...) objFiles = append(objFiles, objFilesShared...)
outputFile := filepath.Join(common.ModuleOutDir(ctx), ctx.ModuleName()+flags.Toolchain.ShlibSuffix()) outputFile := common.PathForModuleOut(ctx, ctx.ModuleName()+flags.Toolchain.ShlibSuffix())
var linkerDeps []string var linkerDeps common.Paths
versionScript := common.OptionalPathForModuleSrc(ctx, c.LibraryProperties.Version_script)
unexportedSymbols := common.OptionalPathForModuleSrc(ctx, c.LibraryProperties.Unexported_symbols_list)
forceNotWeakSymbols := common.OptionalPathForModuleSrc(ctx, c.LibraryProperties.Force_symbols_not_weak_list)
forceWeakSymbols := common.OptionalPathForModuleSrc(ctx, c.LibraryProperties.Force_symbols_weak_list)
if !ctx.Darwin() { if !ctx.Darwin() {
if c.LibraryProperties.Version_script != "" { if versionScript.Valid() {
versionScript := filepath.Join(common.ModuleSrcDir(ctx), c.LibraryProperties.Version_script) sharedFlags.LdFlags = append(sharedFlags.LdFlags, "-Wl,--version-script,"+versionScript.String())
sharedFlags.LdFlags = append(sharedFlags.LdFlags, "-Wl,--version-script,"+versionScript) linkerDeps = append(linkerDeps, versionScript.Path())
linkerDeps = append(linkerDeps, versionScript)
} }
if c.LibraryProperties.Unexported_symbols_list != "" { if unexportedSymbols.Valid() {
ctx.PropertyErrorf("unexported_symbols_list", "Only supported on Darwin") ctx.PropertyErrorf("unexported_symbols_list", "Only supported on Darwin")
} }
if c.LibraryProperties.Force_symbols_not_weak_list != "" { if forceNotWeakSymbols.Valid() {
ctx.PropertyErrorf("force_symbols_not_weak_list", "Only supported on Darwin") ctx.PropertyErrorf("force_symbols_not_weak_list", "Only supported on Darwin")
} }
if c.LibraryProperties.Force_symbols_weak_list != "" { if forceWeakSymbols.Valid() {
ctx.PropertyErrorf("force_symbols_weak_list", "Only supported on Darwin") ctx.PropertyErrorf("force_symbols_weak_list", "Only supported on Darwin")
} }
} else { } else {
if c.LibraryProperties.Version_script != "" { if versionScript.Valid() {
ctx.PropertyErrorf("version_script", "Not supported on Darwin") ctx.PropertyErrorf("version_script", "Not supported on Darwin")
} }
if c.LibraryProperties.Unexported_symbols_list != "" { if unexportedSymbols.Valid() {
localFile := filepath.Join(common.ModuleSrcDir(ctx), c.LibraryProperties.Unexported_symbols_list) sharedFlags.LdFlags = append(sharedFlags.LdFlags, "-Wl,-unexported_symbols_list,"+unexportedSymbols.String())
sharedFlags.LdFlags = append(sharedFlags.LdFlags, "-Wl,-unexported_symbols_list,"+localFile) linkerDeps = append(linkerDeps, unexportedSymbols.Path())
linkerDeps = append(linkerDeps, localFile)
} }
if c.LibraryProperties.Force_symbols_not_weak_list != "" { if forceNotWeakSymbols.Valid() {
localFile := filepath.Join(common.ModuleSrcDir(ctx), c.LibraryProperties.Force_symbols_not_weak_list) sharedFlags.LdFlags = append(sharedFlags.LdFlags, "-Wl,-force_symbols_not_weak_list,"+forceNotWeakSymbols.String())
sharedFlags.LdFlags = append(sharedFlags.LdFlags, "-Wl,-force_symbols_not_weak_list,"+localFile) linkerDeps = append(linkerDeps, forceNotWeakSymbols.Path())
linkerDeps = append(linkerDeps, localFile)
} }
if c.LibraryProperties.Force_symbols_weak_list != "" { if forceWeakSymbols.Valid() {
localFile := filepath.Join(common.ModuleSrcDir(ctx), c.LibraryProperties.Force_symbols_weak_list) sharedFlags.LdFlags = append(sharedFlags.LdFlags, "-Wl,-force_symbols_weak_list,"+forceWeakSymbols.String())
sharedFlags.LdFlags = append(sharedFlags.LdFlags, "-Wl,-force_symbols_weak_list,"+localFile) linkerDeps = append(linkerDeps, forceWeakSymbols.Path())
linkerDeps = append(linkerDeps, localFile)
} }
} }
@@ -1307,13 +1320,13 @@ func (c *CCLibrary) compileSharedLibrary(ctx common.AndroidModuleContext,
ccFlagsToBuilderFlags(sharedFlags), outputFile) ccFlagsToBuilderFlags(sharedFlags), outputFile)
c.out = outputFile c.out = outputFile
includeDirs := pathtools.PrefixPaths(c.Properties.Export_include_dirs, common.ModuleSrcDir(ctx)) includeDirs := common.PathsForModuleSrc(ctx, c.Properties.Export_include_dirs)
c.exportFlags = []string{includeDirsToFlags(includeDirs)} c.exportFlags = []string{includeDirsToFlags(includeDirs)}
c.exportFlags = append(c.exportFlags, deps.ReexportedCflags...) c.exportFlags = append(c.exportFlags, deps.ReexportedCflags...)
} }
func (c *CCLibrary) compileModule(ctx common.AndroidModuleContext, func (c *CCLibrary) compileModule(ctx common.AndroidModuleContext,
flags CCFlags, deps CCDeps, objFiles []string) { flags CCFlags, deps CCPathDeps, objFiles common.Paths) {
// Reuse the object files from the matching static library if it exists // Reuse the object files from the matching static library if it exists
if c.getReuseFrom().ccLibrary() == c { if c.getReuseFrom().ccLibrary() == c {
@@ -1321,7 +1334,7 @@ func (c *CCLibrary) compileModule(ctx common.AndroidModuleContext,
} else { } else {
if c.getReuseFrom().ccLibrary().LibraryProperties.Static.Cflags == nil && if c.getReuseFrom().ccLibrary().LibraryProperties.Static.Cflags == nil &&
c.LibraryProperties.Shared.Cflags == nil { c.LibraryProperties.Shared.Cflags == nil {
objFiles = append([]string(nil), c.getReuseFrom().getReuseObjFiles()...) objFiles = append(common.Paths(nil), c.getReuseFrom().getReuseObjFiles()...)
} }
} }
@@ -1363,7 +1376,7 @@ type ccObjectProvider interface {
type ccObject struct { type ccObject struct {
CCBase CCBase
out string out common.OptionalPath
} }
func (c *ccObject) object() *ccObject { func (c *ccObject) object() *ccObject {
@@ -1382,19 +1395,20 @@ func (*ccObject) depNames(ctx common.AndroidBaseContext, depNames CCDeps) CCDeps
} }
func (c *ccObject) compileModule(ctx common.AndroidModuleContext, func (c *ccObject) compileModule(ctx common.AndroidModuleContext,
flags CCFlags, deps CCDeps, objFiles []string) { flags CCFlags, deps CCPathDeps, objFiles common.Paths) {
objFiles = append(objFiles, deps.ObjFiles...) objFiles = append(objFiles, deps.ObjFiles...)
var outputFile string var outputFile common.Path
if len(objFiles) == 1 { if len(objFiles) == 1 {
outputFile = objFiles[0] outputFile = objFiles[0]
} else { } else {
outputFile = filepath.Join(common.ModuleOutDir(ctx), ctx.ModuleName()+objectExtension) output := common.PathForModuleOut(ctx, ctx.ModuleName()+objectExtension)
TransformObjsToObj(ctx, objFiles, ccFlagsToBuilderFlags(flags), outputFile) TransformObjsToObj(ctx, objFiles, ccFlagsToBuilderFlags(flags), output)
outputFile = output
} }
c.out = outputFile c.out = common.OptionalPathForPath(outputFile)
ctx.CheckbuildFile(outputFile) ctx.CheckbuildFile(outputFile)
} }
@@ -1403,7 +1417,7 @@ func (c *ccObject) installModule(ctx common.AndroidModuleContext, flags CCFlags)
// Object files do not get installed. // Object files do not get installed.
} }
func (c *ccObject) outputFile() string { func (c *ccObject) outputFile() common.OptionalPath {
return c.out return c.out
} }
@@ -1433,8 +1447,8 @@ type CCBinaryProperties struct {
type CCBinary struct { type CCBinary struct {
CCLinked CCLinked
out string out common.Path
installFile string installFile common.Path
BinaryProperties CCBinaryProperties BinaryProperties CCBinaryProperties
} }
@@ -1569,23 +1583,23 @@ func (c *CCBinary) flags(ctx common.AndroidModuleContext, flags CCFlags) CCFlags
} }
func (c *CCBinary) compileModule(ctx common.AndroidModuleContext, func (c *CCBinary) compileModule(ctx common.AndroidModuleContext,
flags CCFlags, deps CCDeps, objFiles []string) { flags CCFlags, deps CCPathDeps, objFiles common.Paths) {
if !Bool(c.BinaryProperties.Static_executable) && inList("libc", c.Properties.Static_libs) { if !Bool(c.BinaryProperties.Static_executable) && inList("libc", c.Properties.Static_libs) {
ctx.ModuleErrorf("statically linking libc to dynamic executable, please remove libc\n" + ctx.ModuleErrorf("statically linking libc to dynamic executable, please remove libc\n" +
"from static libs or set static_executable: true") "from static libs or set static_executable: true")
} }
outputFile := filepath.Join(common.ModuleOutDir(ctx), c.getStem(ctx)+flags.Toolchain.ExecutableSuffix()) outputFile := common.PathForModuleOut(ctx, c.getStem(ctx)+flags.Toolchain.ExecutableSuffix())
c.out = outputFile c.out = outputFile
if c.BinaryProperties.Prefix_symbols != "" { if c.BinaryProperties.Prefix_symbols != "" {
afterPrefixSymbols := outputFile afterPrefixSymbols := outputFile
outputFile = outputFile + ".intermediate" outputFile = common.PathForModuleOut(ctx, c.getStem(ctx)+".intermediate")
TransformBinaryPrefixSymbols(ctx, c.BinaryProperties.Prefix_symbols, outputFile, TransformBinaryPrefixSymbols(ctx, c.BinaryProperties.Prefix_symbols, outputFile,
ccFlagsToBuilderFlags(flags), afterPrefixSymbols) ccFlagsToBuilderFlags(flags), afterPrefixSymbols)
} }
var linkerDeps []string var linkerDeps common.Paths
TransformObjToDynamicBinary(ctx, objFiles, deps.SharedLibs, deps.StaticLibs, TransformObjToDynamicBinary(ctx, objFiles, deps.SharedLibs, deps.StaticLibs,
deps.LateStaticLibs, deps.WholeStaticLibs, linkerDeps, deps.CrtBegin, deps.CrtEnd, true, deps.LateStaticLibs, deps.WholeStaticLibs, linkerDeps, deps.CrtBegin, deps.CrtEnd, true,
@@ -1596,11 +1610,11 @@ func (c *CCBinary) installModule(ctx common.AndroidModuleContext, flags CCFlags)
c.installFile = ctx.InstallFile(filepath.Join("bin", c.Properties.Relative_install_path), c.out) c.installFile = ctx.InstallFile(filepath.Join("bin", c.Properties.Relative_install_path), c.out)
} }
func (c *CCBinary) HostToolPath() string { func (c *CCBinary) HostToolPath() common.OptionalPath {
if c.HostOrDevice().Host() { if c.HostOrDevice().Host() {
return c.installFile return common.OptionalPathForPath(c.installFile)
} }
return "" return common.OptionalPath{}
} }
func (c *CCBinary) testPerSrc() bool { func (c *CCBinary) testPerSrc() bool {
@@ -1649,7 +1663,7 @@ func (c *CCTest) flags(ctx common.AndroidModuleContext, flags CCFlags) CCFlags {
// TODO(danalbert): Make gtest export its dependencies. // TODO(danalbert): Make gtest export its dependencies.
flags.CFlags = append(flags.CFlags, flags.CFlags = append(flags.CFlags,
"-I"+filepath.Join(ctx.AConfig().SrcDir(), "external/gtest/include")) "-I"+common.PathForSource(ctx, "external/gtest/include").String())
return flags return flags
} }
@@ -1832,10 +1846,10 @@ func ToolchainLibraryFactory() (blueprint.Module, []interface{}) {
} }
func (c *toolchainLibrary) compileModule(ctx common.AndroidModuleContext, func (c *toolchainLibrary) compileModule(ctx common.AndroidModuleContext,
flags CCFlags, deps CCDeps, objFiles []string) { flags CCFlags, deps CCPathDeps, objFiles common.Paths) {
libName := ctx.ModuleName() + staticLibraryExtension libName := ctx.ModuleName() + staticLibraryExtension
outputFile := filepath.Join(common.ModuleOutDir(ctx), libName) outputFile := common.PathForModuleOut(ctx, libName)
CopyGccLib(ctx, libName, ccFlagsToBuilderFlags(flags), outputFile) CopyGccLib(ctx, libName, ccFlagsToBuilderFlags(flags), outputFile)
@@ -1854,19 +1868,19 @@ func (c *toolchainLibrary) installModule(ctx common.AndroidModuleContext, flags
// either (with the exception of the shared STLs, which are installed to the app's directory rather // either (with the exception of the shared STLs, which are installed to the app's directory rather
// than to the system image). // than to the system image).
func getNdkLibDir(ctx common.AndroidModuleContext, toolchain Toolchain, version string) string { func getNdkLibDir(ctx common.AndroidModuleContext, toolchain Toolchain, version string) common.SourcePath {
return fmt.Sprintf("%s/prebuilts/ndk/current/platforms/android-%s/arch-%s/usr/lib", return common.PathForSource(ctx, fmt.Sprintf("prebuilts/ndk/current/platforms/android-%s/arch-%s/usr/lib",
ctx.AConfig().SrcDir(), version, toolchain.Name()) version, toolchain.Name()))
} }
func ndkPrebuiltModuleToPath(ctx common.AndroidModuleContext, toolchain Toolchain, func ndkPrebuiltModuleToPath(ctx common.AndroidModuleContext, toolchain Toolchain,
ext string, version string) string { ext string, version string) common.Path {
// NDK prebuilts are named like: ndk_NAME.EXT.SDK_VERSION. // NDK prebuilts are named like: ndk_NAME.EXT.SDK_VERSION.
// We want to translate to just NAME.EXT // We want to translate to just NAME.EXT
name := strings.Split(strings.TrimPrefix(ctx.ModuleName(), "ndk_"), ".")[0] name := strings.Split(strings.TrimPrefix(ctx.ModuleName(), "ndk_"), ".")[0]
dir := getNdkLibDir(ctx, toolchain, version) dir := getNdkLibDir(ctx, toolchain, version)
return filepath.Join(dir, name+ext) return dir.Join(ctx, name+ext)
} }
type ndkPrebuiltObject struct { type ndkPrebuiltObject struct {
@@ -1884,13 +1898,13 @@ func NdkPrebuiltObjectFactory() (blueprint.Module, []interface{}) {
} }
func (c *ndkPrebuiltObject) compileModule(ctx common.AndroidModuleContext, flags CCFlags, func (c *ndkPrebuiltObject) compileModule(ctx common.AndroidModuleContext, flags CCFlags,
deps CCDeps, objFiles []string) { deps CCPathDeps, objFiles common.Paths) {
// A null build step, but it sets up the output path. // A null build step, but it sets up the output path.
if !strings.HasPrefix(ctx.ModuleName(), "ndk_crt") { if !strings.HasPrefix(ctx.ModuleName(), "ndk_crt") {
ctx.ModuleErrorf("NDK prebuilts must have an ndk_crt prefixed name") ctx.ModuleErrorf("NDK prebuilts must have an ndk_crt prefixed name")
} }
c.out = ndkPrebuiltModuleToPath(ctx, flags.Toolchain, objectExtension, c.Properties.Sdk_version) c.out = common.OptionalPathForPath(ndkPrebuiltModuleToPath(ctx, flags.Toolchain, objectExtension, c.Properties.Sdk_version))
} }
func (c *ndkPrebuiltObject) installModule(ctx common.AndroidModuleContext, flags CCFlags) { func (c *ndkPrebuiltObject) installModule(ctx common.AndroidModuleContext, flags CCFlags) {
@@ -1915,14 +1929,14 @@ func NdkPrebuiltLibraryFactory() (blueprint.Module, []interface{}) {
} }
func (c *ndkPrebuiltLibrary) compileModule(ctx common.AndroidModuleContext, flags CCFlags, func (c *ndkPrebuiltLibrary) compileModule(ctx common.AndroidModuleContext, flags CCFlags,
deps CCDeps, objFiles []string) { deps CCPathDeps, objFiles common.Paths) {
// A null build step, but it sets up the output path. // A null build step, but it sets up the output path.
if !strings.HasPrefix(ctx.ModuleName(), "ndk_lib") { if !strings.HasPrefix(ctx.ModuleName(), "ndk_lib") {
ctx.ModuleErrorf("NDK prebuilts must have an ndk_lib prefixed name") ctx.ModuleErrorf("NDK prebuilts must have an ndk_lib prefixed name")
} }
includeDirs := pathtools.PrefixPaths(c.Properties.Export_include_dirs, common.ModuleSrcDir(ctx)) includeDirs := common.PathsForModuleSrc(ctx, c.Properties.Export_include_dirs)
c.exportFlags = []string{common.JoinWithPrefix(includeDirs, "-isystem ")} c.exportFlags = []string{common.JoinWithPrefix(includeDirs.Strings(), "-isystem ")}
c.out = ndkPrebuiltModuleToPath(ctx, flags.Toolchain, flags.Toolchain.ShlibSuffix(), c.out = ndkPrebuiltModuleToPath(ctx, flags.Toolchain, flags.Toolchain.ShlibSuffix(),
c.Properties.Sdk_version) c.Properties.Sdk_version)
@@ -1960,7 +1974,7 @@ func NdkPrebuiltStaticStlFactory() (blueprint.Module, []interface{}) {
return NewCCLibrary(&module.CCLibrary, module, common.DeviceSupported) return NewCCLibrary(&module.CCLibrary, module, common.DeviceSupported)
} }
func getNdkStlLibDir(ctx common.AndroidModuleContext, toolchain Toolchain, stl string) string { func getNdkStlLibDir(ctx common.AndroidModuleContext, toolchain Toolchain, stl string) common.SourcePath {
gccVersion := toolchain.GccVersion() gccVersion := toolchain.GccVersion()
var libDir string var libDir string
switch stl { switch stl {
@@ -1973,22 +1987,22 @@ func getNdkStlLibDir(ctx common.AndroidModuleContext, toolchain Toolchain, stl s
} }
if libDir != "" { if libDir != "" {
ndkSrcRoot := ctx.AConfig().SrcDir() + "/prebuilts/ndk/current/sources" ndkSrcRoot := "prebuilts/ndk/current/sources"
return fmt.Sprintf("%s/%s/%s", ndkSrcRoot, libDir, ctx.Arch().Abi) return common.PathForSource(ctx, ndkSrcRoot).Join(ctx, libDir, ctx.Arch().Abi[0])
} }
ctx.ModuleErrorf("Unknown NDK STL: %s", stl) ctx.ModuleErrorf("Unknown NDK STL: %s", stl)
return "" return common.PathForSource(ctx, "")
} }
func (c *ndkPrebuiltStl) compileModule(ctx common.AndroidModuleContext, flags CCFlags, func (c *ndkPrebuiltStl) compileModule(ctx common.AndroidModuleContext, flags CCFlags,
deps CCDeps, objFiles []string) { deps CCPathDeps, objFiles common.Paths) {
// A null build step, but it sets up the output path. // A null build step, but it sets up the output path.
if !strings.HasPrefix(ctx.ModuleName(), "ndk_lib") { if !strings.HasPrefix(ctx.ModuleName(), "ndk_lib") {
ctx.ModuleErrorf("NDK prebuilts must have an ndk_lib prefixed name") ctx.ModuleErrorf("NDK prebuilts must have an ndk_lib prefixed name")
} }
includeDirs := pathtools.PrefixPaths(c.Properties.Export_include_dirs, common.ModuleSrcDir(ctx)) includeDirs := common.PathsForModuleSrc(ctx, c.Properties.Export_include_dirs)
c.exportFlags = []string{includeDirsToFlags(includeDirs)} c.exportFlags = []string{includeDirsToFlags(includeDirs)}
libName := strings.TrimPrefix(ctx.ModuleName(), "ndk_") libName := strings.TrimPrefix(ctx.ModuleName(), "ndk_")
@@ -2000,7 +2014,7 @@ func (c *ndkPrebuiltStl) compileModule(ctx common.AndroidModuleContext, flags CC
stlName := strings.TrimSuffix(libName, "_shared") stlName := strings.TrimSuffix(libName, "_shared")
stlName = strings.TrimSuffix(stlName, "_static") stlName = strings.TrimSuffix(stlName, "_static")
libDir := getNdkStlLibDir(ctx, flags.Toolchain, stlName) libDir := getNdkStlLibDir(ctx, flags.Toolchain, stlName)
c.out = libDir + "/" + libName + libExt c.out = libDir.Join(ctx, libName+libExt)
} }
func linkageMutator(mctx common.AndroidBottomUpMutatorContext) { func linkageMutator(mctx common.AndroidBottomUpMutatorContext) {

View File

@@ -19,18 +19,15 @@ package cc
// functions. // functions.
import ( import (
"path/filepath"
"github.com/google/blueprint" "github.com/google/blueprint"
"github.com/google/blueprint/pathtools"
"android/soong/common" "android/soong/common"
) )
func init() { func init() {
pctx.StaticVariable("lexCmd", "${SrcDir}/prebuilts/misc/${HostPrebuiltTag}/flex/flex-2.5.39") pctx.SourcePathVariable("lexCmd", "prebuilts/misc/${HostPrebuiltTag}/flex/flex-2.5.39")
pctx.StaticVariable("yaccCmd", "${SrcDir}/prebuilts/misc/${HostPrebuiltTag}/bison/bison") pctx.SourcePathVariable("yaccCmd", "prebuilts/misc/${HostPrebuiltTag}/bison/bison")
pctx.StaticVariable("yaccDataDir", "${SrcDir}/external/bison/data") pctx.SourcePathVariable("yaccDataDir", "external/bison/data")
} }
var ( var (
@@ -51,49 +48,45 @@ var (
}) })
) )
func genYacc(ctx common.AndroidModuleContext, yaccFile, yaccFlags string) (cppFile, headerFile string) { func genYacc(ctx common.AndroidModuleContext, yaccFile common.Path, yaccFlags string) (cppFile, headerFile common.ModuleGenPath) {
cppFile = common.SrcDirRelPath(ctx, yaccFile) cppFile = common.GenPathWithExt(ctx, yaccFile, "cpp")
cppFile = filepath.Join(common.ModuleGenDir(ctx), cppFile) hppFile := common.GenPathWithExt(ctx, yaccFile, "hpp")
cppFile = pathtools.ReplaceExtension(cppFile, "cpp") headerFile = common.GenPathWithExt(ctx, yaccFile, "h")
hppFile := pathtools.ReplaceExtension(cppFile, "hpp")
headerFile = pathtools.ReplaceExtension(cppFile, "h")
ctx.Build(pctx, blueprint.BuildParams{ ctx.ModuleBuild(pctx, common.ModuleBuildParams{
Rule: yacc, Rule: yacc,
Outputs: []string{cppFile, headerFile}, Outputs: common.WritablePaths{cppFile, headerFile},
Inputs: []string{yaccFile}, Input: yaccFile,
Args: map[string]string{ Args: map[string]string{
"yaccFlags": yaccFlags, "yaccFlags": yaccFlags,
"cppFile": cppFile, "cppFile": cppFile.String(),
"hppFile": hppFile, "hppFile": hppFile.String(),
"hFile": headerFile, "hFile": headerFile.String(),
}, },
}) })
return cppFile, headerFile return cppFile, headerFile
} }
func genLex(ctx common.AndroidModuleContext, lexFile string) (cppFile string) { func genLex(ctx common.AndroidModuleContext, lexFile common.Path) (cppFile common.ModuleGenPath) {
cppFile = common.SrcDirRelPath(ctx, lexFile) cppFile = common.GenPathWithExt(ctx, lexFile, "cpp")
cppFile = filepath.Join(common.ModuleGenDir(ctx), cppFile)
cppFile = pathtools.ReplaceExtension(cppFile, "cpp")
ctx.Build(pctx, blueprint.BuildParams{ ctx.ModuleBuild(pctx, common.ModuleBuildParams{
Rule: lex, Rule: lex,
Outputs: []string{cppFile}, Output: cppFile,
Inputs: []string{lexFile}, Input: lexFile,
}) })
return cppFile return cppFile
} }
func genSources(ctx common.AndroidModuleContext, srcFiles []string, func genSources(ctx common.AndroidModuleContext, srcFiles common.Paths,
buildFlags builderFlags) ([]string, []string) { buildFlags builderFlags) (common.Paths, common.Paths) {
var deps []string var deps common.Paths
for i, srcFile := range srcFiles { for i, srcFile := range srcFiles {
switch filepath.Ext(srcFile) { switch srcFile.Ext() {
case ".y", ".yy": case ".y", ".yy":
cppFile, headerFile := genYacc(ctx, srcFile, buildFlags.yaccFlags) cppFile, headerFile := genYacc(ctx, srcFile, buildFlags.yaccFlags)
srcFiles[i] = cppFile srcFiles[i] = cppFile

View File

@@ -90,7 +90,7 @@ func init() {
pctx.StaticVariable("mips64GccVersion", mips64GccVersion) pctx.StaticVariable("mips64GccVersion", mips64GccVersion)
pctx.StaticVariable("mips64GccRoot", pctx.SourcePathVariable("mips64GccRoot",
"prebuilts/gcc/${HostPrebuiltTag}/mips/mips64el-linux-android-${mips64GccVersion}") "prebuilts/gcc/${HostPrebuiltTag}/mips/mips64el-linux-android-${mips64GccVersion}")
pctx.StaticVariable("mips64GccTriple", "mips64el-linux-android") pctx.StaticVariable("mips64GccTriple", "mips64el-linux-android")

View File

@@ -121,7 +121,7 @@ func init() {
pctx.StaticVariable("mipsGccVersion", mipsGccVersion) pctx.StaticVariable("mipsGccVersion", mipsGccVersion)
pctx.StaticVariable("mipsGccRoot", pctx.SourcePathVariable("mipsGccRoot",
"prebuilts/gcc/${HostPrebuiltTag}/mips/mips64el-linux-android-${mipsGccVersion}") "prebuilts/gcc/${HostPrebuiltTag}/mips/mips64el-linux-android-${mipsGccVersion}")
pctx.StaticVariable("mipsGccTriple", "mips64el-linux-android") pctx.StaticVariable("mipsGccTriple", "mips64el-linux-android")

View File

@@ -24,12 +24,12 @@ import (
// Efficiently converts a list of include directories to a single string // Efficiently converts a list of include directories to a single string
// of cflags with -I prepended to each directory. // of cflags with -I prepended to each directory.
func includeDirsToFlags(dirs []string) string { func includeDirsToFlags(dirs common.Paths) string {
return common.JoinWithPrefix(dirs, "-I") return common.JoinWithPrefix(dirs.Strings(), "-I")
} }
func includeFilesToFlags(dirs []string) string { func includeFilesToFlags(files common.Paths) string {
return common.JoinWithPrefix(dirs, "-include ") return common.JoinWithPrefix(files.Strings(), "-include ")
} }
func ldDirsToFlags(dirs []string) string { func ldDirsToFlags(dirs []string) string {

View File

@@ -137,7 +137,7 @@ func init() {
pctx.StaticVariable("x86_64GccVersion", x86_64GccVersion) pctx.StaticVariable("x86_64GccVersion", x86_64GccVersion)
pctx.StaticVariable("x86_64GccRoot", pctx.SourcePathVariable("x86_64GccRoot",
"prebuilts/gcc/${HostPrebuiltTag}/x86/x86_64-linux-android-${x86_64GccVersion}") "prebuilts/gcc/${HostPrebuiltTag}/x86/x86_64-linux-android-${x86_64GccVersion}")
pctx.StaticVariable("x86_64GccTriple", "x86_64-linux-android") pctx.StaticVariable("x86_64GccTriple", "x86_64-linux-android")

View File

@@ -83,8 +83,8 @@ func init() {
pctx.StaticVariable("macSdkRoot", "${macSdkPath}/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk") pctx.StaticVariable("macSdkRoot", "${macSdkPath}/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk")
pctx.StaticVariable("darwinGccVersion", darwinGccVersion) pctx.StaticVariable("darwinGccVersion", darwinGccVersion)
pctx.StaticVariable("darwinGccRoot", pctx.SourcePathVariable("darwinGccRoot",
"${SrcDir}/prebuilts/gcc/${HostPrebuiltTag}/host/i686-apple-darwin-${darwinGccVersion}") "prebuilts/gcc/${HostPrebuiltTag}/host/i686-apple-darwin-${darwinGccVersion}")
pctx.StaticVariable("darwinGccTriple", "i686-apple-darwin11") pctx.StaticVariable("darwinGccTriple", "i686-apple-darwin11")

View File

@@ -139,7 +139,7 @@ func init() {
pctx.StaticVariable("x86GccVersion", x86GccVersion) pctx.StaticVariable("x86GccVersion", x86GccVersion)
pctx.StaticVariable("x86GccRoot", pctx.SourcePathVariable("x86GccRoot",
"prebuilts/gcc/${HostPrebuiltTag}/x86/x86_64-linux-android-${x86GccVersion}") "prebuilts/gcc/${HostPrebuiltTag}/x86/x86_64-linux-android-${x86GccVersion}")
pctx.StaticVariable("x86GccTriple", "x86_64-linux-android") pctx.StaticVariable("x86GccTriple", "x86_64-linux-android")

View File

@@ -108,8 +108,8 @@ const (
func init() { func init() {
pctx.StaticVariable("linuxGccVersion", linuxGccVersion) pctx.StaticVariable("linuxGccVersion", linuxGccVersion)
pctx.StaticVariable("linuxGccRoot", pctx.SourcePathVariable("linuxGccRoot",
"${SrcDir}/prebuilts/gcc/${HostPrebuiltTag}/host/x86_64-linux-glibc2.15-${linuxGccVersion}") "prebuilts/gcc/${HostPrebuiltTag}/host/x86_64-linux-glibc2.15-${linuxGccVersion}")
pctx.StaticVariable("linuxGccTriple", "x86_64-linux") pctx.StaticVariable("linuxGccTriple", "x86_64-linux")

View File

@@ -68,8 +68,8 @@ const (
func init() { func init() {
pctx.StaticVariable("windowsGccVersion", windowsGccVersion) pctx.StaticVariable("windowsGccVersion", windowsGccVersion)
pctx.StaticVariable("windowsGccRoot", pctx.SourcePathVariable("windowsGccRoot",
"${SrcDir}/prebuilts/gcc/${HostPrebuiltTag}/host/x86_64-w64-mingw32-${windowsGccVersion}") "prebuilts/gcc/${HostPrebuiltTag}/host/x86_64-w64-mingw32-${windowsGccVersion}")
pctx.StaticVariable("windowsGccTriple", "x86_64-w64-mingw32") pctx.StaticVariable("windowsGccTriple", "x86_64-w64-mingw32")

View File

@@ -37,11 +37,11 @@ type AndroidMkDataProvider interface {
type AndroidMkData struct { type AndroidMkData struct {
Class string Class string
OutputFile string OutputFile OptionalPath
Custom func(w io.Writer, name, prefix string) Custom func(w io.Writer, name, prefix string)
Extra func(name, prefix, outputFile string, arch Arch) []string Extra func(name, prefix string, outputFile Path, arch Arch) []string
} }
func AndroidMkSingleton() blueprint.Singleton { func AndroidMkSingleton() blueprint.Singleton {
@@ -55,7 +55,7 @@ func (c *androidMkSingleton) GenerateBuildActions(ctx blueprint.SingletonContext
hasBPDir := make(map[string]bool) hasBPDir := make(map[string]bool)
bpDirs := []string{} bpDirs := []string{}
ctx.SetNinjaBuildDir(pctx, filepath.Join(ctx.Config().(Config).BuildDir(), "..")) ctx.SetNinjaBuildDir(pctx, filepath.Join(ctx.Config().(Config).buildDir, ".."))
ctx.VisitAllModules(func(module blueprint.Module) { ctx.VisitAllModules(func(module blueprint.Module) {
if _, ok := module.(AndroidModule); ok { if _, ok := module.(AndroidModule); ok {
@@ -72,28 +72,13 @@ func (c *androidMkSingleton) GenerateBuildActions(ctx blueprint.SingletonContext
// Gather list of eligible Android modules for translation // Gather list of eligible Android modules for translation
androidMkModules := make(map[blueprint.Module]bool) androidMkModules := make(map[blueprint.Module]bool)
srcDir := ctx.Config().(Config).SrcDir()
intermediatesDir := filepath.Join(ctx.Config().(Config).IntermediatesDir(), "androidmk")
sort.Strings(bpDirs) sort.Strings(bpDirs)
for _, bpDir := range bpDirs { for _, bpDir := range bpDirs {
mkFile := filepath.Join(srcDir, bpDir, "Android.mk") mkFile := OptionalPathForSource(ctx, "androidmk", bpDir, "Android.mk")
if !mkFile.Valid() {
files, err := Glob(ctx, intermediatesDir, mkFile, nil) for _, mod := range dirModules[bpDir] {
if err != nil { androidMkModules[mod] = true
ctx.Errorf("glob: %s", err.Error())
continue
}
// Existing Android.mk file, use that instead
if len(files) > 0 {
for _, file := range files {
ctx.AddNinjaFileDeps(file)
} }
continue
}
for _, mod := range dirModules[bpDir] {
androidMkModules[mod] = true
} }
} }
@@ -110,16 +95,19 @@ func (c *androidMkSingleton) GenerateBuildActions(ctx blueprint.SingletonContext
} }
} }
transMk := filepath.Join(ctx.Config().(Config).BuildDir(), "Android.mk") transMk := PathForOutput(ctx, "Android.mk")
if ctx.Failed() {
return
}
err := translateAndroidMk(ctx, transMk, androidMkModulesList) err := translateAndroidMk(ctx, transMk.String(), androidMkModulesList)
if err != nil { if err != nil {
ctx.Errorf(err.Error()) ctx.Errorf(err.Error())
} }
ctx.Build(pctx, blueprint.BuildParams{ ctx.Build(pctx, blueprint.BuildParams{
Rule: blueprint.Phony, Rule: blueprint.Phony,
Outputs: []string{transMk}, Outputs: []string{transMk.String()},
Optional: true, Optional: true,
}) })
} }
@@ -177,7 +165,7 @@ func translateAndroidMkModule(ctx blueprint.SingletonContext, w io.Writer, mod b
type archSrc struct { type archSrc struct {
arch Arch arch Arch
src string src Path
extra []string extra []string
} }
@@ -211,6 +199,10 @@ func translateAndroidMkModule(ctx blueprint.SingletonContext, w io.Writer, mod b
return return
} }
if !data.OutputFile.Valid() {
return
}
hC := hostClass{ hC := hostClass{
host: amod.HostOrDevice() == Host, host: amod.HostOrDevice() == Host,
class: data.Class, class: data.Class,
@@ -219,7 +211,7 @@ func translateAndroidMkModule(ctx blueprint.SingletonContext, w io.Writer, mod b
src := archSrc{ src := archSrc{
arch: arch, arch: arch,
src: data.OutputFile, src: data.OutputFile.Path(),
} }
if data.Extra != nil { if data.Extra != nil {
@@ -242,7 +234,7 @@ func translateAndroidMkModule(ctx blueprint.SingletonContext, w io.Writer, mod b
printed := make(map[string]bool) printed := make(map[string]bool)
for _, src := range archSrcs { for _, src := range archSrcs {
io.WriteString(w, "LOCAL_SRC_FILES_"+src.arch.ArchType.String()+" := "+src.src+"\n") io.WriteString(w, "LOCAL_SRC_FILES_"+src.arch.ArchType.String()+" := "+src.src.String()+"\n")
for _, extra := range src.extra { for _, extra := range src.extra {
if !printed[extra] { if !printed[extra] {

View File

@@ -20,6 +20,7 @@ import (
"os" "os"
"path/filepath" "path/filepath"
"runtime" "runtime"
"strings"
"sync" "sync"
) )
@@ -38,8 +39,6 @@ func (f *FileConfigurableOptions) SetDefaultConfig() {
type Config struct { type Config struct {
*config *config
dontCreateNinjaFile bool
} }
// A config object represents the entire build configuration for Android. // A config object represents the entire build configuration for Android.
@@ -142,8 +141,24 @@ func NewConfig(srcDir, buildDir string) (Config, error) {
}, },
} }
// Sanity check the build and source directories. This won't catch strange
// configurations with symlinks, but at least checks the obvious cases.
absBuildDir, err := filepath.Abs(buildDir)
if err != nil {
return Config{}, err
}
absSrcDir, err := filepath.Abs(srcDir)
if err != nil {
return Config{}, err
}
if strings.HasPrefix(absSrcDir, absBuildDir) {
return Config{}, fmt.Errorf("Build dir must not contain source directory")
}
// Load any configurable options from the configuration file // Load any configurable options from the configuration file
err := loadConfig(config.config) err = loadConfig(config.config)
if err != nil { if err != nil {
return Config{}, err return Config{}, err
} }
@@ -159,18 +174,6 @@ func NewConfig(srcDir, buildDir string) (Config, error) {
return config, nil return config, nil
} }
func (c *config) SrcDir() string {
return c.srcDir
}
func (c *config) BuildDir() string {
return c.buildDir
}
func (c *config) IntermediatesDir() string {
return filepath.Join(c.BuildDir(), ".intermediates")
}
func (c *config) RemoveAbandonedFiles() bool { func (c *config) RemoveAbandonedFiles() bool {
return false return false
} }
@@ -238,37 +241,7 @@ func (c *config) DeviceUsesClang() bool {
return false return false
} }
// DeviceOut returns the path to out directory for device targets func (c *config) ResourceOverlays() []SourcePath {
func (c *config) DeviceOut() string {
return filepath.Join(c.BuildDir(), "target/product", c.DeviceName())
}
// HostOut returns the path to out directory for host targets
func (c *config) HostOut() string {
return filepath.Join(c.BuildDir(), "host", c.PrebuiltOS())
}
// HostBin returns the path to bin directory for host targets
func (c *config) HostBin() string {
return filepath.Join(c.HostOut(), "bin")
}
// HostBinTool returns the path to a host tool in the bin directory for host targets
func (c *config) HostBinTool(tool string) (string, error) {
return filepath.Join(c.HostBin(), tool), nil
}
// HostJavaDir returns the path to framework directory for host targets
func (c *config) HostJavaDir() string {
return filepath.Join(c.HostOut(), "framework")
}
// HostJavaTool returns the path to a host tool in the frameworks directory for host targets
func (c *config) HostJavaTool(tool string) (string, error) {
return filepath.Join(c.HostJavaDir(), tool), nil
}
func (c *config) ResourceOverlays() []string {
return nil return nil
} }
@@ -296,10 +269,10 @@ func (c *config) ProductAaptCharacteristics() string {
return "nosdcard" return "nosdcard"
} }
func (c *config) DefaultAppCertificateDir() string { func (c *config) DefaultAppCertificateDir(ctx PathContext) SourcePath {
return filepath.Join(c.SrcDir(), "build/target/product/security") return PathForSource(ctx, "build/target/product/security")
} }
func (c *config) DefaultAppCertificate() string { func (c *config) DefaultAppCertificate(ctx PathContext) SourcePath {
return filepath.Join(c.DefaultAppCertificateDir(), "testkey") return c.DefaultAppCertificateDir(ctx).Join(ctx, "testkey")
} }

View File

@@ -20,13 +20,11 @@ import (
) )
var ( var (
pctx = blueprint.NewPackageContext("android/soong/common") pctx = NewPackageContext("android/soong/common")
cpPreserveSymlinks = pctx.VariableConfigMethod("cpPreserveSymlinks", cpPreserveSymlinks = pctx.VariableConfigMethod("cpPreserveSymlinks",
Config.CpPreserveSymlinksFlags) Config.CpPreserveSymlinksFlags)
srcDir = pctx.VariableConfigMethod("srcDir", Config.SrcDir)
// A phony rule that is not the built-in Ninja phony rule. The built-in // A phony rule that is not the built-in Ninja phony rule. The built-in
// phony rule has special behavior that is sometimes not desired. See the // phony rule has special behavior that is sometimes not desired. See the
// Ninja docs for more details. // Ninja docs for more details.

View File

@@ -15,8 +15,6 @@
package common package common
import ( import (
"path/filepath"
"android/soong" "android/soong"
"android/soong/env" "android/soong/env"
@@ -43,12 +41,15 @@ type envSingleton struct{}
func (c *envSingleton) GenerateBuildActions(ctx blueprint.SingletonContext) { func (c *envSingleton) GenerateBuildActions(ctx blueprint.SingletonContext) {
envDeps := ctx.Config().(Config).EnvDeps() envDeps := ctx.Config().(Config).EnvDeps()
envFile := filepath.Join(ctx.Config().(Config).BuildDir(), ".soong.environment") envFile := PathForOutput(ctx, ".soong.environment")
if ctx.Failed() {
return
}
err := env.WriteEnvFile(envFile, envDeps) err := env.WriteEnvFile(envFile.String(), envDeps)
if err != nil { if err != nil {
ctx.Errorf(err.Error()) ctx.Errorf(err.Error())
} }
ctx.AddNinjaFileDeps(envFile) ctx.AddNinjaFileDeps(envFile.String())
} }

View File

@@ -32,6 +32,19 @@ var (
HostExecutable = "host_executable" HostExecutable = "host_executable"
) )
type ModuleBuildParams struct {
Rule blueprint.Rule
Output WritablePath
Outputs WritablePaths
Input Path
Inputs Paths
Implicit Path
Implicits Paths
OrderOnly Paths
Default bool
Args map[string]string
}
type androidBaseContext interface { type androidBaseContext interface {
Arch() Arch Arch() Arch
HostOrDevice() HostOrDevice HostOrDevice() HostOrDevice
@@ -52,12 +65,16 @@ type AndroidModuleContext interface {
blueprint.ModuleContext blueprint.ModuleContext
androidBaseContext androidBaseContext
ExpandSources(srcFiles, excludes []string) []string // Similar to Build, but takes Paths instead of []string,
Glob(outDir, globPattern string, excludes []string) []string // and performs more verification.
ModuleBuild(pctx blueprint.PackageContext, params ModuleBuildParams)
InstallFile(installPath, srcPath string, deps ...string) string ExpandSources(srcFiles, excludes []string) Paths
InstallFileName(installPath, name, srcPath string, deps ...string) string Glob(outDir, globPattern string, excludes []string) Paths
CheckbuildFile(srcPath string)
InstallFile(installPath string, srcPath Path, deps ...Path) Path
InstallFileName(installPath, name string, srcPath Path, deps ...Path) Path
CheckbuildFile(srcPath Path)
} }
type AndroidModule interface { type AndroidModule interface {
@@ -196,8 +213,8 @@ type AndroidModuleBase struct {
archProperties []*archProperties archProperties []*archProperties
noAddressSanitizer bool noAddressSanitizer bool
installFiles []string installFiles Paths
checkbuildFiles []string checkbuildFiles Paths
// Used by buildTargetSingleton to create checkbuild and per-directory build targets // Used by buildTargetSingleton to create checkbuild and per-directory build targets
// Only set on the final variant of each module // Only set on the final variant of each module
@@ -254,9 +271,9 @@ func (a *AndroidModuleBase) Enabled() bool {
} }
func (a *AndroidModuleBase) computeInstallDeps( func (a *AndroidModuleBase) computeInstallDeps(
ctx blueprint.ModuleContext) []string { ctx blueprint.ModuleContext) Paths {
result := []string{} result := Paths{}
ctx.VisitDepsDepthFirstIf(isFileInstaller, ctx.VisitDepsDepthFirstIf(isFileInstaller,
func(m blueprint.Module) { func(m blueprint.Module) {
fileInstaller := m.(fileInstaller) fileInstaller := m.(fileInstaller)
@@ -267,7 +284,7 @@ func (a *AndroidModuleBase) computeInstallDeps(
return result return result
} }
func (a *AndroidModuleBase) filesToInstall() []string { func (a *AndroidModuleBase) filesToInstall() Paths {
return a.installFiles return a.installFiles
} }
@@ -280,8 +297,8 @@ func (a *AndroidModuleBase) generateModuleTarget(ctx blueprint.ModuleContext) {
return return
} }
allInstalledFiles := []string{} allInstalledFiles := Paths{}
allCheckbuildFiles := []string{} allCheckbuildFiles := Paths{}
ctx.VisitAllModuleVariants(func(module blueprint.Module) { ctx.VisitAllModuleVariants(func(module blueprint.Module) {
a := module.(AndroidModule).base() a := module.(AndroidModule).base()
allInstalledFiles = append(allInstalledFiles, a.installFiles...) allInstalledFiles = append(allInstalledFiles, a.installFiles...)
@@ -295,7 +312,7 @@ func (a *AndroidModuleBase) generateModuleTarget(ctx blueprint.ModuleContext) {
ctx.Build(pctx, blueprint.BuildParams{ ctx.Build(pctx, blueprint.BuildParams{
Rule: blueprint.Phony, Rule: blueprint.Phony,
Outputs: []string{name}, Outputs: []string{name},
Implicits: allInstalledFiles, Implicits: allInstalledFiles.Strings(),
}) })
deps = append(deps, name) deps = append(deps, name)
a.installTarget = name a.installTarget = name
@@ -306,7 +323,7 @@ func (a *AndroidModuleBase) generateModuleTarget(ctx blueprint.ModuleContext) {
ctx.Build(pctx, blueprint.BuildParams{ ctx.Build(pctx, blueprint.BuildParams{
Rule: blueprint.Phony, Rule: blueprint.Phony,
Outputs: []string{name}, Outputs: []string{name},
Implicits: allCheckbuildFiles, Implicits: allCheckbuildFiles.Strings(),
Optional: true, Optional: true,
}) })
deps = append(deps, name) deps = append(deps, name)
@@ -371,9 +388,9 @@ type androidBaseContextImpl struct {
type androidModuleContext struct { type androidModuleContext struct {
blueprint.ModuleContext blueprint.ModuleContext
androidBaseContextImpl androidBaseContextImpl
installDeps []string installDeps Paths
installFiles []string installFiles Paths
checkbuildFiles []string checkbuildFiles Paths
} }
func (a *androidModuleContext) Build(pctx blueprint.PackageContext, params blueprint.BuildParams) { func (a *androidModuleContext) Build(pctx blueprint.PackageContext, params blueprint.BuildParams) {
@@ -381,6 +398,30 @@ func (a *androidModuleContext) Build(pctx blueprint.PackageContext, params bluep
a.ModuleContext.Build(pctx, params) a.ModuleContext.Build(pctx, params)
} }
func (a *androidModuleContext) ModuleBuild(pctx blueprint.PackageContext, params ModuleBuildParams) {
bparams := blueprint.BuildParams{
Rule: params.Rule,
Outputs: params.Outputs.Strings(),
Inputs: params.Inputs.Strings(),
Implicits: params.Implicits.Strings(),
OrderOnly: params.OrderOnly.Strings(),
Args: params.Args,
Optional: !params.Default,
}
if params.Output != nil {
bparams.Outputs = append(bparams.Outputs, params.Output.String())
}
if params.Input != nil {
bparams.Inputs = append(bparams.Inputs, params.Input.String())
}
if params.Implicit != nil {
bparams.Implicits = append(bparams.Implicits, params.Implicit.String())
}
a.ModuleContext.Build(pctx, bparams)
}
func (a *androidBaseContextImpl) Arch() Arch { func (a *androidBaseContextImpl) Arch() Arch {
return a.arch return a.arch
} }
@@ -413,31 +454,19 @@ func (a *androidBaseContextImpl) AConfig() Config {
return a.config return a.config
} }
func (a *androidModuleContext) InstallFileName(installPath, name, srcPath string, func (a *androidModuleContext) InstallFileName(installPath, name string, srcPath Path,
deps ...string) string { deps ...Path) Path {
config := a.AConfig() fullInstallPath := PathForModuleInstall(a, installPath, name)
var fullInstallPath string
if a.hod.Device() {
// TODO: replace unset with a device name once we have device targeting
fullInstallPath = filepath.Join(config.DeviceOut(), "system",
installPath, name)
} else {
// TODO
if a.ht == Windows {
fullInstallPath = filepath.Join(config.BuildDir(), "host", "windows-x86", installPath, name)
} else {
fullInstallPath = filepath.Join(config.HostOut(), installPath, name)
}
}
deps = append(deps, a.installDeps...) deps = append(deps, a.installDeps...)
a.ModuleContext.Build(pctx, blueprint.BuildParams{ a.ModuleBuild(pctx, ModuleBuildParams{
Rule: Cp, Rule: Cp,
Outputs: []string{fullInstallPath}, Output: fullInstallPath,
Inputs: []string{srcPath}, Input: srcPath,
OrderOnly: deps, OrderOnly: Paths(deps),
Default: true,
}) })
a.installFiles = append(a.installFiles, fullInstallPath) a.installFiles = append(a.installFiles, fullInstallPath)
@@ -445,16 +474,16 @@ func (a *androidModuleContext) InstallFileName(installPath, name, srcPath string
return fullInstallPath return fullInstallPath
} }
func (a *androidModuleContext) InstallFile(installPath, srcPath string, deps ...string) string { func (a *androidModuleContext) InstallFile(installPath string, srcPath Path, deps ...Path) Path {
return a.InstallFileName(installPath, filepath.Base(srcPath), srcPath, deps...) return a.InstallFileName(installPath, filepath.Base(srcPath.String()), srcPath, deps...)
} }
func (a *androidModuleContext) CheckbuildFile(srcPath string) { func (a *androidModuleContext) CheckbuildFile(srcPath Path) {
a.checkbuildFiles = append(a.checkbuildFiles, srcPath) a.checkbuildFiles = append(a.checkbuildFiles, srcPath)
} }
type fileInstaller interface { type fileInstaller interface {
filesToInstall() []string filesToInstall() Paths
} }
func isFileInstaller(m blueprint.Module) bool { func isFileInstaller(m blueprint.Module) bool {
@@ -476,8 +505,8 @@ func findStringInSlice(str string, slice []string) int {
return -1 return -1
} }
func (ctx *androidModuleContext) ExpandSources(srcFiles, excludes []string) []string { func (ctx *androidModuleContext) ExpandSources(srcFiles, excludes []string) Paths {
prefix := ModuleSrcDir(ctx) prefix := PathForModuleSrc(ctx).String()
for i, e := range excludes { for i, e := range excludes {
j := findStringInSlice(e, srcFiles) j := findStringInSlice(e, srcFiles)
if j != -1 { if j != -1 {
@@ -487,32 +516,24 @@ func (ctx *androidModuleContext) ExpandSources(srcFiles, excludes []string) []st
excludes[i] = filepath.Join(prefix, e) excludes[i] = filepath.Join(prefix, e)
} }
for i, srcFile := range srcFiles { globbedSrcFiles := make(Paths, 0, len(srcFiles))
srcFiles[i] = filepath.Join(prefix, srcFile)
}
if !hasGlob(srcFiles) {
return srcFiles
}
globbedSrcFiles := make([]string, 0, len(srcFiles))
for _, s := range srcFiles { for _, s := range srcFiles {
if glob.IsGlob(s) { if glob.IsGlob(s) {
globbedSrcFiles = append(globbedSrcFiles, ctx.Glob("src_glob", s, excludes)...) globbedSrcFiles = append(globbedSrcFiles, ctx.Glob("src_glob", filepath.Join(prefix, s), excludes)...)
} else { } else {
globbedSrcFiles = append(globbedSrcFiles, s) globbedSrcFiles = append(globbedSrcFiles, PathForModuleSrc(ctx, s))
} }
} }
return globbedSrcFiles return globbedSrcFiles
} }
func (ctx *androidModuleContext) Glob(outDir, globPattern string, excludes []string) []string { func (ctx *androidModuleContext) Glob(outDir, globPattern string, excludes []string) Paths {
ret, err := Glob(ctx, filepath.Join(ModuleOutDir(ctx), outDir), globPattern, excludes) ret, err := Glob(ctx, PathForModuleOut(ctx, outDir).String(), globPattern, excludes)
if err != nil { if err != nil {
ctx.ModuleErrorf("glob: %s", err.Error()) ctx.ModuleErrorf("glob: %s", err.Error())
} }
return ret return pathsForModuleSrcFromFullPath(ctx, ret)
} }
func init() { func init() {

127
common/package_ctx.go Normal file
View File

@@ -0,0 +1,127 @@
// Copyright 2015 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 common
import (
"fmt"
"github.com/google/blueprint"
)
// AndroidPackageContext is a wrapper for blueprint.PackageContext that adds
// some android-specific helper functions.
type AndroidPackageContext struct {
blueprint.PackageContext
}
func NewPackageContext(pkgPath string) AndroidPackageContext {
return AndroidPackageContext{blueprint.NewPackageContext(pkgPath)}
}
// configErrorWrapper can be used with Path functions when a Context is not
// available. A Config can be provided, and errors are stored as a list for
// later retrieval.
//
// The most common use here will be with VariableFunc, where only a config is
// provided, and an error should be returned.
type configErrorWrapper struct {
config Config
errors []error
}
var _ PathContext = &configErrorWrapper{}
var _ errorfContext = &configErrorWrapper{}
func (e *configErrorWrapper) Config() interface{} {
return e.config
}
func (e *configErrorWrapper) Errorf(format string, args ...interface{}) {
e.errors = append(e.errors, fmt.Errorf(format, args...))
}
// SourcePathVariable returns a Variable whose value is the source directory
// appended with the supplied path. It may only be called during a Go package's
// initialization - either from the init() function or as part of a
// package-scoped variable's initialization.
func (p AndroidPackageContext) SourcePathVariable(name, path string) blueprint.Variable {
return p.VariableFunc(name, func(config interface{}) (string, error) {
ctx := &configErrorWrapper{config.(Config), []error{}}
p := safePathForSource(ctx, path)
if len(ctx.errors) > 0 {
return "", ctx.errors[0]
}
return p.String(), nil
})
}
// HostBinVariable returns a Variable whose value is the path to a host tool
// in the bin directory for host targets. It may only be called during a Go
// package's initialization - either from the init() function or as part of a
// package-scoped variable's initialization.
func (p AndroidPackageContext) HostBinToolVariable(name, path string) blueprint.Variable {
return p.VariableFunc(name, func(config interface{}) (string, error) {
ctx := &configErrorWrapper{config.(Config), []error{}}
p := PathForOutput(ctx, "host", ctx.config.PrebuiltOS(), "bin", path)
if len(ctx.errors) > 0 {
return "", ctx.errors[0]
}
return p.String(), nil
})
}
// HostJavaToolVariable returns a Variable whose value is the path to a host
// tool in the frameworks directory for host targets. It may only be called
// during a Go package's initialization - either from the init() function or as
// part of a package-scoped variable's initialization.
func (p AndroidPackageContext) HostJavaToolVariable(name, path string) blueprint.Variable {
return p.VariableFunc(name, func(config interface{}) (string, error) {
ctx := &configErrorWrapper{config.(Config), []error{}}
p := PathForOutput(ctx, "host", ctx.config.PrebuiltOS(), "framework", path)
if len(ctx.errors) > 0 {
return "", ctx.errors[0]
}
return p.String(), nil
})
}
// IntermediatesPathVariable returns a Variable whose value is the intermediate
// directory appended with the supplied path. It may only be called during a Go
// package's initialization - either from the init() function or as part of a
// package-scoped variable's initialization.
func (p AndroidPackageContext) IntermediatesPathVariable(name, path string) blueprint.Variable {
return p.VariableFunc(name, func(config interface{}) (string, error) {
ctx := &configErrorWrapper{config.(Config), []error{}}
p := PathForIntermediates(ctx, path)
if len(ctx.errors) > 0 {
return "", ctx.errors[0]
}
return p.String(), nil
})
}
// PrefixedPathsForSourceVariable returns a Variable whose value is the
// list of source paths prefixed with the supplied prefix. It may only be
// called during a Go package's initialization - either from the init()
// function or as part of a package-scoped variable's initialization.
func (p AndroidPackageContext) PrefixedPathsForSourceVariable(name, prefix string, paths []string) blueprint.Variable {
return p.VariableFunc(name, func(config interface{}) (string, error) {
ctx := &configErrorWrapper{config.(Config), []error{}}
paths := PathsForSource(ctx, paths)
if len(ctx.errors) > 0 {
return "", ctx.errors[0]
}
return JoinWithPrefix(paths.Strings(), prefix), nil
})
}

View File

@@ -18,103 +18,571 @@ import (
"fmt" "fmt"
"os" "os"
"path/filepath" "path/filepath"
"reflect"
"strings"
"github.com/google/blueprint"
"github.com/google/blueprint/pathtools"
) )
// ModuleOutDir returns the path to the module-specific output directory. // PathContext is the subset of a (Module|Singleton)Context required by the
func ModuleOutDir(ctx AndroidModuleContext) string { // Path methods.
return filepath.Join(ctx.AConfig().IntermediatesDir(), type PathContext interface {
ctx.ModuleDir(), ctx.ModuleName(), ctx.ModuleSubDir()) Config() interface{}
} }
// ModuleSrcDir returns the path of the directory that all source file paths are var _ PathContext = blueprint.SingletonContext(nil)
// specified relative to. var _ PathContext = blueprint.ModuleContext(nil)
func ModuleSrcDir(ctx AndroidModuleContext) string {
return filepath.Join(ctx.AConfig().SrcDir(), ctx.ModuleDir()) // errorfContext is the interface containing the Errorf method matching the
// Errorf method in blueprint.SingletonContext.
type errorfContext interface {
Errorf(format string, args ...interface{})
} }
// ModuleBinDir returns the path to the module- and architecture-specific binary var _ errorfContext = blueprint.SingletonContext(nil)
// output directory.
func ModuleBinDir(ctx AndroidModuleContext) string { // moduleErrorf is the interface containing the ModuleErrorf method matching
return filepath.Join(ModuleOutDir(ctx), "bin") // the ModuleErrorf method in blueprint.ModuleContext.
type moduleErrorf interface {
ModuleErrorf(format string, args ...interface{})
} }
// ModuleLibDir returns the path to the module- and architecture-specific var _ moduleErrorf = blueprint.ModuleContext(nil)
// library output directory.
func ModuleLibDir(ctx AndroidModuleContext) string { // pathConfig returns the android Config interface associated to the context.
return filepath.Join(ModuleOutDir(ctx), "lib") // Panics if the context isn't affiliated with an android build.
func pathConfig(ctx PathContext) Config {
if ret, ok := ctx.Config().(Config); ok {
return ret
}
panic("Paths may only be used on Soong builds")
} }
// ModuleGenDir returns the module directory for generated files // reportPathError will register an error with the attached context. It
// path. // attempts ctx.ModuleErrorf for a better error message first, then falls
func ModuleGenDir(ctx AndroidModuleContext) string { // back to ctx.Errorf.
return filepath.Join(ModuleOutDir(ctx), "gen") func reportPathError(ctx PathContext, format string, args ...interface{}) {
} if mctx, ok := ctx.(moduleErrorf); ok {
mctx.ModuleErrorf(format, args...)
// ModuleObjDir returns the module- and architecture-specific object directory } else if ectx, ok := ctx.(errorfContext); ok {
// path. ectx.Errorf(format, args...)
func ModuleObjDir(ctx AndroidModuleContext) string { } else {
return filepath.Join(ModuleOutDir(ctx), "obj") panic(fmt.Sprintf(format, args...))
}
// ModuleGoPackageDir returns the module-specific package root directory path.
// This directory is where the final package .a files are output and where
// dependent modules search for this package via -I arguments.
func ModuleGoPackageDir(ctx AndroidModuleContext) string {
return filepath.Join(ModuleOutDir(ctx), "pkg")
}
// ModuleIncludeDir returns the module-specific public include directory path.
func ModuleIncludeDir(ctx AndroidModuleContext) string {
return filepath.Join(ModuleOutDir(ctx), "include")
}
// ModuleProtoDir returns the module-specific public proto include directory path.
func ModuleProtoDir(ctx AndroidModuleContext) string {
return filepath.Join(ModuleOutDir(ctx), "proto")
}
func ModuleJSCompiledDir(ctx AndroidModuleContext) string {
return filepath.Join(ModuleOutDir(ctx), "js")
}
// CheckModuleSrcDirsExist logs an error on a property if any of the directories relative to the
// Blueprints file don't exist.
func CheckModuleSrcDirsExist(ctx AndroidModuleContext, dirs []string, prop string) {
for _, dir := range dirs {
fullDir := filepath.Join(ModuleSrcDir(ctx), dir)
if _, err := os.Stat(fullDir); err != nil {
if os.IsNotExist(err) {
ctx.PropertyErrorf(prop, "module source directory %q does not exist", dir)
} else {
ctx.PropertyErrorf(prop, "%s", err.Error())
}
}
} }
} }
// CheckModuleSrcDirsExist logs an error on a property if any of the directories relative to the type Path interface {
// top of the source tree don't exist. // Returns the path in string form
func CheckSrcDirsExist(ctx AndroidModuleContext, dirs []string, prop string) { String() string
for _, dir := range dirs {
fullDir := filepath.Join(ctx.AConfig().SrcDir(), dir) // Returns the current file extension of the path
if _, err := os.Stat(fullDir); err != nil { Ext() string
if os.IsNotExist(err) { }
ctx.PropertyErrorf(prop, "top-level source directory %q does not exist", dir)
} else { // WritablePath is a type of path that can be used as an output for build rules.
ctx.PropertyErrorf(prop, "%s", err.Error()) type WritablePath interface {
} Path
}
writablePath()
}
type genPathProvider interface {
genPathWithExt(ctx AndroidModuleContext, ext string) ModuleGenPath
}
type objPathProvider interface {
objPathWithExt(ctx AndroidModuleContext, subdir, ext string) ModuleObjPath
}
type resPathProvider interface {
resPathWithName(ctx AndroidModuleContext, name string) ModuleResPath
}
// GenPathWithExt derives a new file path in ctx's generated sources directory
// from the current path, but with the new extension.
func GenPathWithExt(ctx AndroidModuleContext, p Path, ext string) ModuleGenPath {
if path, ok := p.(genPathProvider); ok {
return path.genPathWithExt(ctx, ext)
}
reportPathError(ctx, "Tried to create generated file from unsupported path: %s(%s)", reflect.TypeOf(p).Name(), p)
return PathForModuleGen(ctx)
}
// ObjPathWithExt derives a new file path in ctx's object directory from the
// current path, but with the new extension.
func ObjPathWithExt(ctx AndroidModuleContext, p Path, subdir, ext string) ModuleObjPath {
if path, ok := p.(objPathProvider); ok {
return path.objPathWithExt(ctx, subdir, ext)
}
reportPathError(ctx, "Tried to create object file from unsupported path: %s (%s)", reflect.TypeOf(p).Name(), p)
return PathForModuleObj(ctx)
}
// ResPathWithName derives a new path in ctx's output resource directory, using
// the current path to create the directory name, and the `name` argument for
// the filename.
func ResPathWithName(ctx AndroidModuleContext, p Path, name string) ModuleResPath {
if path, ok := p.(resPathProvider); ok {
return path.resPathWithName(ctx, name)
}
reportPathError(ctx, "Tried to create object file from unsupported path: %s (%s)", reflect.TypeOf(p).Name(), p)
return PathForModuleRes(ctx)
}
// OptionalPath is a container that may or may not contain a valid Path.
type OptionalPath struct {
valid bool
path Path
}
// OptionalPathForPath returns an OptionalPath containing the path.
func OptionalPathForPath(path Path) OptionalPath {
if path == nil {
return OptionalPath{}
}
return OptionalPath{valid: true, path: path}
}
// Valid returns whether there is a valid path
func (p OptionalPath) Valid() bool {
return p.valid
}
// Path returns the Path embedded in this OptionalPath. You must be sure that
// there is a valid path, since this method will panic if there is not.
func (p OptionalPath) Path() Path {
if !p.valid {
panic("Requesting an invalid path")
}
return p.path
}
// String returns the string version of the Path, or "" if it isn't valid.
func (p OptionalPath) String() string {
if p.valid {
return p.path.String()
} else {
return ""
} }
} }
// Returns a path relative to the top level source directory. Panics if path is not inside the // Paths is a slice of Path objects, with helpers to operate on the collection.
// top level source directory. type Paths []Path
func SrcDirRelPath(ctx AndroidModuleContext, path string) string {
srcDir := ctx.AConfig().SrcDir() // PathsForSource returns Paths rooted from SrcDir
relPath, err := filepath.Rel(srcDir, path) func PathsForSource(ctx PathContext, paths []string) Paths {
ret := make(Paths, len(paths))
for i, path := range paths {
ret[i] = PathForSource(ctx, path)
}
return ret
}
// PathsForModuleSrc returns Paths rooted from the module's local source
// directory
func PathsForModuleSrc(ctx AndroidModuleContext, paths []string) Paths {
ret := make(Paths, len(paths))
for i, path := range paths {
ret[i] = PathForModuleSrc(ctx, path)
}
return ret
}
// pathsForModuleSrcFromFullPath returns Paths rooted from the module's local
// source directory, but strip the local source directory from the beginning of
// each string.
func pathsForModuleSrcFromFullPath(ctx AndroidModuleContext, paths []string) Paths {
prefix := filepath.Join(ctx.AConfig().srcDir, ctx.ModuleDir()) + "/"
ret := make(Paths, 0, len(paths))
for _, p := range paths {
path := filepath.Clean(p)
if !strings.HasPrefix(path, prefix) {
reportPathError(ctx, "Path '%s' is not in module source directory '%s'", p, prefix)
continue
}
ret = append(ret, PathForModuleSrc(ctx, path[len(prefix):]))
}
return ret
}
// PathsWithOptionalDefaultForModuleSrc returns Paths rooted from the module's
// local source directory. If none are provided, use the default if it exists.
func PathsWithOptionalDefaultForModuleSrc(ctx AndroidModuleContext, input []string, def string) Paths {
if len(input) > 0 {
return PathsForModuleSrc(ctx, input)
}
// Use Glob so that if the default doesn't exist, a dependency is added so that when it
// is created, we're run again.
path := filepath.Join(ctx.AConfig().srcDir, ctx.ModuleDir(), def)
return ctx.Glob("default", path, []string{})
}
// Strings returns the Paths in string form
func (p Paths) Strings() []string {
if p == nil {
return nil
}
ret := make([]string, len(p))
for i, path := range p {
ret[i] = path.String()
}
return ret
}
// WritablePaths is a slice of WritablePaths, used for multiple outputs.
type WritablePaths []WritablePath
// Strings returns the string forms of the writable paths.
func (p WritablePaths) Strings() []string {
if p == nil {
return nil
}
ret := make([]string, len(p))
for i, path := range p {
ret[i] = path.String()
}
return ret
}
type basePath struct {
path string
config Config
}
func (p basePath) Ext() string {
return filepath.Ext(p.path)
}
// SourcePath is a Path representing a file path rooted from SrcDir
type SourcePath struct {
basePath
}
var _ Path = SourcePath{}
// safePathForSource is for paths that we expect are safe -- only for use by go
// code that is embedding ninja variables in paths
func safePathForSource(ctx PathContext, path string) SourcePath {
p := validateSafePath(ctx, path)
ret := SourcePath{basePath{p, pathConfig(ctx)}}
abs, err := filepath.Abs(ret.String())
if err != nil { if err != nil {
panic(fmt.Errorf("%q is not inside %q: %s", path, srcDir, err.Error())) reportPathError(ctx, "%s", err.Error())
return ret
}
buildroot, err := filepath.Abs(pathConfig(ctx).buildDir)
if err != nil {
reportPathError(ctx, "%s", err.Error())
return ret
}
if strings.HasPrefix(abs, buildroot) {
reportPathError(ctx, "source path %s is in output", abs)
return ret
} }
return relPath return ret
}
// PathForSource returns a SourcePath for the provided paths... (which are
// joined together with filepath.Join). This also validates that the path
// doesn't escape the source dir, or is contained in the build dir. On error, it
// will return a usable, but invalid SourcePath, and report a ModuleError.
func PathForSource(ctx PathContext, paths ...string) SourcePath {
p := validatePath(ctx, paths...)
ret := SourcePath{basePath{p, pathConfig(ctx)}}
abs, err := filepath.Abs(ret.String())
if err != nil {
reportPathError(ctx, "%s", err.Error())
return ret
}
buildroot, err := filepath.Abs(pathConfig(ctx).buildDir)
if err != nil {
reportPathError(ctx, "%s", err.Error())
return ret
}
if strings.HasPrefix(abs, buildroot) {
reportPathError(ctx, "source path %s is in output", abs)
return ret
}
if _, err = os.Stat(ret.String()); err != nil {
if os.IsNotExist(err) {
reportPathError(ctx, "source path %s does not exist", ret)
} else {
reportPathError(ctx, "%s: %s", ret, err.Error())
}
}
return ret
}
// OptionalPathForSource returns an OptionalPath with the SourcePath if the
// path exists, or an empty OptionalPath if it doesn't exist. Dependencies are added
// so that the ninja file will be regenerated if the state of the path changes.
func OptionalPathForSource(ctx blueprint.SingletonContext, intermediates string, paths ...string) OptionalPath {
p := validatePath(ctx, paths...)
path := SourcePath{basePath{p, pathConfig(ctx)}}
abs, err := filepath.Abs(path.String())
if err != nil {
reportPathError(ctx, "%s", err.Error())
return OptionalPath{}
}
buildroot, err := filepath.Abs(pathConfig(ctx).buildDir)
if err != nil {
reportPathError(ctx, "%s", err.Error())
return OptionalPath{}
}
if strings.HasPrefix(abs, buildroot) {
reportPathError(ctx, "source path %s is in output", abs)
return OptionalPath{}
}
// Use glob to produce proper dependencies, even though we only want
// a single file.
files, err := Glob(ctx, PathForIntermediates(ctx, intermediates).String(), path.String(), nil)
if err != nil {
reportPathError(ctx, "glob: %s", err.Error())
return OptionalPath{}
}
if len(files) == 0 {
return OptionalPath{}
}
return OptionalPathForPath(path)
}
func (p SourcePath) String() string {
return filepath.Join(p.config.srcDir, p.path)
}
// Join creates a new SourcePath with paths... joined with the current path. The
// provided paths... may not use '..' to escape from the current path.
func (p SourcePath) Join(ctx PathContext, paths ...string) SourcePath {
path := validatePath(ctx, paths...)
return PathForSource(ctx, p.path, path)
}
// OverlayPath returns the overlay for `path' if it exists. This assumes that the
// SourcePath is the path to a resource overlay directory.
func (p SourcePath) OverlayPath(ctx AndroidModuleContext, path Path) OptionalPath {
var relDir string
if moduleSrcPath, ok := path.(ModuleSrcPath); ok {
relDir = moduleSrcPath.sourcePath.path
} else if srcPath, ok := path.(SourcePath); ok {
relDir = srcPath.path
} else {
reportPathError(ctx, "Cannot find relative path for %s(%s)", reflect.TypeOf(path).Name(), path)
return OptionalPath{}
}
dir := filepath.Join(p.config.srcDir, p.path, relDir)
// Use Glob so that we are run again if the directory is added.
paths, err := Glob(ctx, PathForModuleOut(ctx, "overlay").String(), dir, []string{})
if err != nil {
reportPathError(ctx, "glob: %s", err.Error())
return OptionalPath{}
}
if len(paths) == 0 {
return OptionalPath{}
}
relPath, err := filepath.Rel(p.config.srcDir, paths[0])
if err != nil {
reportPathError(ctx, "%s", err.Error())
return OptionalPath{}
}
return OptionalPathForPath(PathForSource(ctx, relPath))
}
// OutputPath is a Path representing a file path rooted from the build directory
type OutputPath struct {
basePath
}
var _ Path = OutputPath{}
// PathForOutput returns an OutputPath for the provided paths... (which are
// joined together with filepath.Join). This also validates that the path
// does not escape the build dir. On error, it will return a usable, but invalid
// OutputPath, and report a ModuleError.
func PathForOutput(ctx PathContext, paths ...string) OutputPath {
path := validatePath(ctx, paths...)
return OutputPath{basePath{path, pathConfig(ctx)}}
}
func (p OutputPath) writablePath() {}
func (p OutputPath) String() string {
return filepath.Join(p.config.buildDir, p.path)
}
// Join creates a new OutputPath with paths... joined with the current path. The
// provided paths... may not use '..' to escape from the current path.
func (p OutputPath) Join(ctx PathContext, paths ...string) OutputPath {
path := validatePath(ctx, paths...)
return PathForOutput(ctx, p.path, path)
}
// PathForIntermediates returns an OutputPath representing the top-level
// intermediates directory.
func PathForIntermediates(ctx PathContext, paths ...string) OutputPath {
path := validatePath(ctx, paths...)
return PathForOutput(ctx, ".intermediates", path)
}
// ModuleSrcPath is a Path representing a file rooted from a module's local source dir
type ModuleSrcPath struct {
basePath
sourcePath SourcePath
moduleDir string
}
var _ Path = ModuleSrcPath{}
var _ genPathProvider = ModuleSrcPath{}
var _ objPathProvider = ModuleSrcPath{}
var _ resPathProvider = ModuleSrcPath{}
// PathForModuleSrc returns a ModuleSrcPath representing the paths... under the
// module's local source directory.
func PathForModuleSrc(ctx AndroidModuleContext, paths ...string) ModuleSrcPath {
path := validatePath(ctx, paths...)
return ModuleSrcPath{basePath{path, ctx.AConfig()}, PathForSource(ctx, ctx.ModuleDir(), path), ctx.ModuleDir()}
}
// OptionalPathForModuleSrc returns an OptionalPath. The OptionalPath contains a
// valid path if p is non-nil.
func OptionalPathForModuleSrc(ctx AndroidModuleContext, p *string) OptionalPath {
if p == nil {
return OptionalPath{}
}
return OptionalPathForPath(PathForModuleSrc(ctx, *p))
}
func (p ModuleSrcPath) String() string {
return p.sourcePath.String()
}
func (p ModuleSrcPath) genPathWithExt(ctx AndroidModuleContext, ext string) ModuleGenPath {
return PathForModuleGen(ctx, p.moduleDir, pathtools.ReplaceExtension(p.path, ext))
}
func (p ModuleSrcPath) objPathWithExt(ctx AndroidModuleContext, subdir, ext string) ModuleObjPath {
return PathForModuleObj(ctx, subdir, p.moduleDir, pathtools.ReplaceExtension(p.path, ext))
}
func (p ModuleSrcPath) resPathWithName(ctx AndroidModuleContext, name string) ModuleResPath {
// TODO: Use full directory if the new ctx is not the current ctx?
return PathForModuleRes(ctx, p.path, name)
}
// ModuleOutPath is a Path representing a module's output directory.
type ModuleOutPath struct {
OutputPath
}
var _ Path = ModuleOutPath{}
// PathForModuleOut returns a Path representing the paths... under the module's
// output directory.
func PathForModuleOut(ctx AndroidModuleContext, paths ...string) ModuleOutPath {
p := validatePath(ctx, paths...)
return ModuleOutPath{PathForOutput(ctx, ".intermediates", ctx.ModuleDir(), ctx.ModuleName(), ctx.ModuleSubDir(), p)}
}
// ModuleGenPath is a Path representing the 'gen' directory in a module's output
// directory. Mainly used for generated sources.
type ModuleGenPath struct {
ModuleOutPath
path string
}
var _ Path = ModuleGenPath{}
var _ genPathProvider = ModuleGenPath{}
var _ objPathProvider = ModuleGenPath{}
// PathForModuleGen returns a Path representing the paths... under the module's
// `gen' directory.
func PathForModuleGen(ctx AndroidModuleContext, paths ...string) ModuleGenPath {
p := validatePath(ctx, paths...)
return ModuleGenPath{
PathForModuleOut(ctx, "gen", p),
p,
}
}
func (p ModuleGenPath) genPathWithExt(ctx AndroidModuleContext, ext string) ModuleGenPath {
// TODO: make a different path for local vs remote generated files?
return PathForModuleGen(ctx, pathtools.ReplaceExtension(p.path, ext))
}
func (p ModuleGenPath) objPathWithExt(ctx AndroidModuleContext, subdir, ext string) ModuleObjPath {
return PathForModuleObj(ctx, subdir, pathtools.ReplaceExtension(p.path, ext))
}
// ModuleObjPath is a Path representing the 'obj' directory in a module's output
// directory. Used for compiled objects.
type ModuleObjPath struct {
ModuleOutPath
}
var _ Path = ModuleObjPath{}
// PathForModuleObj returns a Path representing the paths... under the module's
// 'obj' directory.
func PathForModuleObj(ctx AndroidModuleContext, paths ...string) ModuleObjPath {
p := validatePath(ctx, paths...)
return ModuleObjPath{PathForModuleOut(ctx, "obj", p)}
}
// ModuleResPath is a a Path representing the 'res' directory in a module's
// output directory.
type ModuleResPath struct {
ModuleOutPath
}
var _ Path = ModuleResPath{}
// PathForModuleRes returns a Path representing the paths... under the module's
// 'res' directory.
func PathForModuleRes(ctx AndroidModuleContext, paths ...string) ModuleResPath {
p := validatePath(ctx, paths...)
return ModuleResPath{PathForModuleOut(ctx, "res", p)}
}
// PathForModuleInstall returns a Path representing the install path for the
// module appended with paths...
func PathForModuleInstall(ctx AndroidModuleContext, paths ...string) OutputPath {
var outPaths []string
if ctx.Device() {
outPaths = []string{"target", "product", ctx.AConfig().DeviceName(), "system"}
} else {
outPaths = []string{"host", ctx.HostType().String() + "-x86"}
}
outPaths = append(outPaths, paths...)
return PathForOutput(ctx, outPaths...)
}
// validateSafePath validates a path that we trust (may contain ninja variables).
// Ensures that it does not attempt to leave the containing directory.
func validateSafePath(ctx PathContext, paths ...string) string {
// TODO: filepath.Join isn't necessarily correct with embedded ninja
// variables. '..' may remove the entire ninja variable, even if it
// will be expanded to multiple nested directories.
p := filepath.Join(paths...)
if p == ".." || strings.HasPrefix(p, "../") || strings.HasPrefix(p, "/") {
reportPathError(ctx, "Path is outside directory: %s", p)
return ""
}
return p
}
// validatePath validates that a path does not include ninja variables, and does
// not attempt to leave the containing directory.
func validatePath(ctx PathContext, paths ...string) string {
for _, path := range paths {
if strings.Contains(path, "$") {
reportPathError(ctx, "Path contains invalid character($): %s", path)
return ""
}
}
return validateSafePath(ctx, paths...)
} }

167
common/paths_test.go Normal file
View File

@@ -0,0 +1,167 @@
// Copyright 2015 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 common
import (
"errors"
"fmt"
"reflect"
"strings"
"testing"
)
type strsTestCase struct {
in []string
out string
err []error
}
var commonValidatePathTestCases = []strsTestCase{
{
in: []string{""},
out: "",
},
{
in: []string{"a/b"},
out: "a/b",
},
{
in: []string{"a/b", "c"},
out: "a/b/c",
},
{
in: []string{"a/.."},
out: ".",
},
{
in: []string{"."},
out: ".",
},
{
in: []string{".."},
out: "",
err: []error{errors.New("Path is outside directory: ..")},
},
{
in: []string{"../a"},
out: "",
err: []error{errors.New("Path is outside directory: ../a")},
},
{
in: []string{"b/../../a"},
out: "",
err: []error{errors.New("Path is outside directory: ../a")},
},
{
in: []string{"/a"},
out: "",
err: []error{errors.New("Path is outside directory: /a")},
},
}
var validateSafePathTestCases = append(commonValidatePathTestCases, []strsTestCase{
{
in: []string{"$host/../$a"},
out: "$a",
},
}...)
var validatePathTestCases = append(commonValidatePathTestCases, []strsTestCase{
{
in: []string{"$host/../$a"},
out: "",
err: []error{errors.New("Path contains invalid character($): $host/../$a")},
},
{
in: []string{"$host/.."},
out: "",
err: []error{errors.New("Path contains invalid character($): $host/..")},
},
}...)
func TestValidateSafePath(t *testing.T) {
for _, testCase := range validateSafePathTestCases {
ctx := &configErrorWrapper{}
out := validateSafePath(ctx, testCase.in...)
check(t, "validateSafePath", p(testCase.in), out, ctx.errors, testCase.out, testCase.err)
}
}
func TestValidatePath(t *testing.T) {
for _, testCase := range validatePathTestCases {
ctx := &configErrorWrapper{}
out := validatePath(ctx, testCase.in...)
check(t, "validatePath", p(testCase.in), out, ctx.errors, testCase.out, testCase.err)
}
}
func TestOptionalPath(t *testing.T) {
var path OptionalPath
checkInvalidOptionalPath(t, path)
path = OptionalPathForPath(nil)
checkInvalidOptionalPath(t, path)
}
func checkInvalidOptionalPath(t *testing.T, path OptionalPath) {
if path.Valid() {
t.Errorf("Uninitialized OptionalPath should not be valid")
}
if path.String() != "" {
t.Errorf("Uninitialized OptionalPath String() should return \"\", not %q", path.String())
}
defer func() {
if r := recover(); r == nil {
t.Errorf("Expected a panic when calling Path() on an uninitialized OptionalPath")
}
}()
path.Path()
}
func check(t *testing.T, testType, testString string,
got interface{}, err []error,
expected interface{}, expectedErr []error) {
printedTestCase := false
e := func(s string, expected, got interface{}) {
if !printedTestCase {
t.Errorf("test case %s: %s", testType, testString)
printedTestCase = true
}
t.Errorf("incorrect %s", s)
t.Errorf(" expected: %s", p(expected))
t.Errorf(" got: %s", p(got))
}
if !reflect.DeepEqual(expectedErr, err) {
e("errors:", expectedErr, err)
}
if !reflect.DeepEqual(expected, got) {
e("output:", expected, got)
}
}
func p(in interface{}) string {
if v, ok := in.([]interface{}); ok {
s := make([]string, len(v))
for i := range v {
s[i] = fmt.Sprintf("%#v", v[i])
}
return "[" + strings.Join(s, ", ") + "]"
} else {
return fmt.Sprintf("%#v", in)
}
}

View File

@@ -15,10 +15,7 @@
package genrule package genrule
import ( import (
"path/filepath"
"github.com/google/blueprint" "github.com/google/blueprint"
"github.com/google/blueprint/pathtools"
"android/soong" "android/soong"
"android/soong/common" "android/soong/common"
@@ -32,20 +29,20 @@ func init() {
} }
var ( var (
pctx = blueprint.NewPackageContext("android/soong/genrule") pctx = common.NewPackageContext("android/soong/genrule")
) )
func init() { func init() {
pctx.VariableConfigMethod("srcDir", common.Config.SrcDir) pctx.SourcePathVariable("srcDir", "")
pctx.VariableConfigMethod("hostBin", common.Config.HostBin) pctx.HostBinToolVariable("hostBin", "")
} }
type SourceFileGenerator interface { type SourceFileGenerator interface {
GeneratedSourceFiles() []string GeneratedSourceFiles() common.Paths
} }
type HostToolProvider interface { type HostToolProvider interface {
HostToolPath() string HostToolPath() common.OptionalPath
} }
type generatorProperties struct { type generatorProperties struct {
@@ -68,20 +65,20 @@ type generator struct {
tasks taskFunc tasks taskFunc
deps []string deps common.Paths
rule blueprint.Rule rule blueprint.Rule
outputFiles []string outputFiles common.Paths
} }
type taskFunc func(ctx common.AndroidModuleContext) []generateTask type taskFunc func(ctx common.AndroidModuleContext) []generateTask
type generateTask struct { type generateTask struct {
in []string in common.Paths
out string out common.ModuleGenPath
} }
func (g *generator) GeneratedSourceFiles() []string { func (g *generator) GeneratedSourceFiles() common.Paths {
return g.outputFiles return g.outputFiles
} }
@@ -104,8 +101,8 @@ func (g *generator) GenerateAndroidBuildActions(ctx common.AndroidModuleContext)
ctx.VisitDirectDeps(func(module blueprint.Module) { ctx.VisitDirectDeps(func(module blueprint.Module) {
if t, ok := module.(HostToolProvider); ok { if t, ok := module.(HostToolProvider); ok {
p := t.HostToolPath() p := t.HostToolPath()
if p != "" { if p.Valid() {
g.deps = append(g.deps, p) g.deps = append(g.deps, p.Path())
} else { } else {
ctx.ModuleErrorf("host tool %q missing output file", ctx.OtherModuleName(module)) ctx.ModuleErrorf("host tool %q missing output file", ctx.OtherModuleName(module))
} }
@@ -120,12 +117,11 @@ func (g *generator) GenerateAndroidBuildActions(ctx common.AndroidModuleContext)
} }
func (g *generator) generateSourceFile(ctx common.AndroidModuleContext, task generateTask) { func (g *generator) generateSourceFile(ctx common.AndroidModuleContext, task generateTask) {
ctx.ModuleBuild(pctx, common.ModuleBuildParams{
ctx.Build(pctx, blueprint.BuildParams{
Rule: g.rule, Rule: g.rule,
Output: task.out,
Inputs: task.in, Inputs: task.in,
Implicits: g.deps, Implicits: g.deps,
Outputs: []string{task.out},
}) })
g.outputFiles = append(g.outputFiles, task.out) g.outputFiles = append(g.outputFiles, task.out)
@@ -148,9 +144,10 @@ func GenSrcsFactory() (blueprint.Module, []interface{}) {
srcFiles := ctx.ExpandSources(properties.Srcs, nil) srcFiles := ctx.ExpandSources(properties.Srcs, nil)
tasks := make([]generateTask, 0, len(srcFiles)) tasks := make([]generateTask, 0, len(srcFiles))
for _, in := range srcFiles { for _, in := range srcFiles {
out := pathtools.ReplaceExtension(in, properties.Output_extension) tasks = append(tasks, generateTask{
out = filepath.Join(common.ModuleGenDir(ctx), out) in: common.Paths{in},
tasks = append(tasks, generateTask{[]string{in}, out}) out: common.GenPathWithExt(ctx, in, properties.Output_extension),
})
} }
return tasks return tasks
} }
@@ -173,7 +170,7 @@ func GenRuleFactory() (blueprint.Module, []interface{}) {
return []generateTask{ return []generateTask{
{ {
in: ctx.ExpandSources(properties.Srcs, nil), in: ctx.ExpandSources(properties.Srcs, nil),
out: filepath.Join(common.ModuleGenDir(ctx), properties.Out), out: properties.Out,
}, },
} }
} }
@@ -186,5 +183,5 @@ type genRuleProperties struct {
Srcs []string Srcs []string
// name of the output file that will be generated // name of the output file that will be generated
Out string Out common.ModuleGenPath
} }

View File

@@ -17,12 +17,10 @@ package java
// This file contains the module types for compiling Android apps. // This file contains the module types for compiling Android apps.
import ( import (
"os"
"path/filepath" "path/filepath"
"strings" "strings"
"github.com/google/blueprint" "github.com/google/blueprint"
"github.com/google/blueprint/pathtools"
"android/soong/common" "android/soong/common"
) )
@@ -63,8 +61,8 @@ type AndroidApp struct {
appProperties androidAppProperties appProperties androidAppProperties
aaptJavaFileList string aaptJavaFileList common.Path
exportPackage string exportPackage common.Path
} }
func (a *AndroidApp) JavaDependencies(ctx AndroidJavaModuleContext) []string { func (a *AndroidApp) JavaDependencies(ctx AndroidJavaModuleContext) []string {
@@ -117,7 +115,7 @@ func (a *AndroidApp) GenerateJavaBuildActions(ctx common.AndroidModuleContext) {
} }
// apps manifests are handled by aapt, don't let javaBase see them // apps manifests are handled by aapt, don't let javaBase see them
a.properties.Manifest = "" a.properties.Manifest = nil
//if !ctx.ContainsProperty("proguard.enabled") { //if !ctx.ContainsProperty("proguard.enabled") {
// a.properties.Proguard.Enabled = true // a.properties.Proguard.Enabled = true
@@ -141,16 +139,16 @@ func (a *AndroidApp) GenerateJavaBuildActions(ctx common.AndroidModuleContext) {
certificate := a.appProperties.Certificate certificate := a.appProperties.Certificate
if certificate == "" { if certificate == "" {
certificate = ctx.AConfig().DefaultAppCertificate() certificate = ctx.AConfig().DefaultAppCertificate(ctx).String()
} else if dir, _ := filepath.Split(certificate); dir == "" { } else if dir, _ := filepath.Split(certificate); dir == "" {
certificate = filepath.Join(ctx.AConfig().DefaultAppCertificateDir(), certificate) certificate = filepath.Join(ctx.AConfig().DefaultAppCertificateDir(ctx).String(), certificate)
} else { } else {
certificate = filepath.Join(ctx.AConfig().SrcDir(), certificate) certificate = filepath.Join(common.PathForSource(ctx).String(), certificate)
} }
certificates := []string{certificate} certificates := []string{certificate}
for _, c := range a.appProperties.Additional_certificates { for _, c := range a.appProperties.Additional_certificates {
certificates = append(certificates, filepath.Join(ctx.AConfig().SrcDir(), c)) certificates = append(certificates, filepath.Join(common.PathForSource(ctx).String(), c))
} }
a.outputFile = CreateAppPackage(ctx, aaptPackageFlags, a.outputFile, certificates) a.outputFile = CreateAppPackage(ctx, aaptPackageFlags, a.outputFile, certificates)
@@ -169,7 +167,7 @@ var aaptIgnoreFilenames = []string{
"*~", "*~",
} }
func (a *AndroidApp) aaptFlags(ctx common.AndroidModuleContext) ([]string, []string, bool) { func (a *AndroidApp) aaptFlags(ctx common.AndroidModuleContext) ([]string, common.Paths, bool) {
aaptFlags := a.appProperties.Aaptflags aaptFlags := a.appProperties.Aaptflags
hasVersionCode := false hasVersionCode := false
hasVersionName := false hasVersionName := false
@@ -185,54 +183,17 @@ func (a *AndroidApp) aaptFlags(ctx common.AndroidModuleContext) ([]string, []str
aaptFlags = append(aaptFlags, "-z") aaptFlags = append(aaptFlags, "-z")
} }
assetDirs := a.appProperties.Asset_dirs assetDirs := common.PathsWithOptionalDefaultForModuleSrc(ctx, a.appProperties.Asset_dirs, "assets")
if len(assetDirs) == 0 { resourceDirs := common.PathsWithOptionalDefaultForModuleSrc(ctx, a.appProperties.Android_resource_dirs, "res")
defaultAssetDir := filepath.Join(common.ModuleSrcDir(ctx), "assets")
if _, err := os.Stat(defaultAssetDir); err == nil {
assetDirs = []string{defaultAssetDir}
} else {
// Default asset directory doesn't exist, add a dep on the parent directory to
// regenerate the manifest if it is created later
// TODO: use glob to avoid rerunning whole regenerate if a different file is created?
ctx.AddNinjaFileDeps(common.ModuleSrcDir(ctx))
}
} else {
assetDirs = pathtools.PrefixPaths(assetDirs, common.ModuleSrcDir(ctx))
}
resourceDirs := a.appProperties.Android_resource_dirs var overlayResourceDirs common.Paths
if len(resourceDirs) == 0 {
defaultResourceDir := filepath.Join(common.ModuleSrcDir(ctx), "res")
if _, err := os.Stat(defaultResourceDir); err == nil {
resourceDirs = []string{defaultResourceDir}
} else {
// Default resource directory doesn't exist, add a dep on the parent directory to
// regenerate the manifest if it is created later
// TODO: use glob to avoid rerunning whole regenerate if a different file is created?
ctx.AddNinjaFileDeps(common.ModuleSrcDir(ctx))
}
} else {
resourceDirs = pathtools.PrefixPaths(resourceDirs, common.ModuleSrcDir(ctx))
}
rootSrcDir := ctx.AConfig().SrcDir()
var overlayResourceDirs []string
// For every resource directory, check if there is an overlay directory with the same path. // For every resource directory, check if there is an overlay directory with the same path.
// If found, it will be prepended to the list of resource directories. // If found, it will be prepended to the list of resource directories.
for _, overlayDir := range ctx.AConfig().ResourceOverlays() { for _, overlayDir := range ctx.AConfig().ResourceOverlays() {
for _, resourceDir := range resourceDirs { for _, resourceDir := range resourceDirs {
relResourceDir, err := filepath.Rel(rootSrcDir, resourceDir) overlay := overlayDir.OverlayPath(ctx, resourceDir)
if err != nil { if overlay.Valid() {
ctx.ModuleErrorf("resource directory %q is not in source tree", resourceDir) overlayResourceDirs = append(overlayResourceDirs, overlay.Path())
continue
}
overlayResourceDir := filepath.Join(overlayDir, relResourceDir)
if _, err := os.Stat(overlayResourceDir); err == nil {
overlayResourceDirs = append(overlayResourceDirs, overlayResourceDir)
} else {
// Overlay resource directory doesn't exist, add a dep to regenerate the manifest if
// it is created later
ctx.AddNinjaFileDeps(overlayResourceDir)
} }
} }
} }
@@ -243,44 +204,46 @@ func (a *AndroidApp) aaptFlags(ctx common.AndroidModuleContext) ([]string, []str
// aapt needs to rerun if any files are added or modified in the assets or resource directories, // aapt needs to rerun if any files are added or modified in the assets or resource directories,
// use glob to create a filelist. // use glob to create a filelist.
var aaptDeps []string var aaptDeps common.Paths
var hasResources bool var hasResources bool
for _, d := range resourceDirs { for _, d := range resourceDirs {
newDeps := ctx.Glob("app_resources", filepath.Join(d, "**/*"), aaptIgnoreFilenames) newDeps := ctx.Glob("app_resources", filepath.Join(d.String(), "**/*"), aaptIgnoreFilenames)
aaptDeps = append(aaptDeps, newDeps...) aaptDeps = append(aaptDeps, newDeps...)
if len(newDeps) > 0 { if len(newDeps) > 0 {
hasResources = true hasResources = true
} }
} }
for _, d := range assetDirs { for _, d := range assetDirs {
newDeps := ctx.Glob("app_assets", filepath.Join(d, "**/*"), aaptIgnoreFilenames) newDeps := ctx.Glob("app_assets", filepath.Join(d.String(), "**/*"), aaptIgnoreFilenames)
aaptDeps = append(aaptDeps, newDeps...) aaptDeps = append(aaptDeps, newDeps...)
} }
manifestFile := a.properties.Manifest var manifestFile string
if manifestFile == "" { if a.properties.Manifest == nil {
manifestFile = "AndroidManifest.xml" manifestFile = "AndroidManifest.xml"
} else {
manifestFile = *a.properties.Manifest
} }
manifestFile = filepath.Join(common.ModuleSrcDir(ctx), manifestFile) manifestPath := common.PathForModuleSrc(ctx, manifestFile)
aaptDeps = append(aaptDeps, manifestFile) aaptDeps = append(aaptDeps, manifestPath)
aaptFlags = append(aaptFlags, "-M "+manifestFile) aaptFlags = append(aaptFlags, "-M "+manifestPath.String())
aaptFlags = append(aaptFlags, common.JoinWithPrefix(assetDirs, "-A ")) aaptFlags = append(aaptFlags, common.JoinWithPrefix(assetDirs.Strings(), "-A "))
aaptFlags = append(aaptFlags, common.JoinWithPrefix(resourceDirs, "-S ")) aaptFlags = append(aaptFlags, common.JoinWithPrefix(resourceDirs.Strings(), "-S "))
ctx.VisitDirectDeps(func(module blueprint.Module) { ctx.VisitDirectDeps(func(module blueprint.Module) {
var depFile string var depFile common.OptionalPath
if sdkDep, ok := module.(sdkDependency); ok { if sdkDep, ok := module.(sdkDependency); ok {
depFile = sdkDep.ClasspathFile() depFile = common.OptionalPathForPath(sdkDep.ClasspathFile())
} else if javaDep, ok := module.(JavaDependency); ok { } else if javaDep, ok := module.(JavaDependency); ok {
if ctx.OtherModuleName(module) == "framework-res" { if ctx.OtherModuleName(module) == "framework-res" {
depFile = javaDep.(*javaBase).module.(*AndroidApp).exportPackage depFile = common.OptionalPathForPath(javaDep.(*javaBase).module.(*AndroidApp).exportPackage)
} }
} }
if depFile != "" { if depFile.Valid() {
aaptFlags = append(aaptFlags, "-I "+depFile) aaptFlags = append(aaptFlags, "-I "+depFile.String())
aaptDeps = append(aaptDeps, depFile) aaptDeps = append(aaptDeps, depFile.Path())
} }
}) })

View File

@@ -19,7 +19,6 @@ package java
// functions. // functions.
import ( import (
"path/filepath"
"strings" "strings"
"github.com/google/blueprint" "github.com/google/blueprint"
@@ -75,44 +74,40 @@ var (
) )
func init() { func init() {
pctx.StaticVariable("androidManifestMergerCmd", "${srcDir}/prebuilts/devtools/tools/lib/manifest-merger.jar") pctx.SourcePathVariable("androidManifestMergerCmd", "prebuilts/devtools/tools/lib/manifest-merger.jar")
pctx.VariableFunc("aaptCmd", func(c interface{}) (string, error) { pctx.HostBinToolVariable("aaptCmd", "aapt")
return c.(common.Config).HostBinTool("aapt") pctx.HostJavaToolVariable("signapkCmd", "signapk.jar")
})
pctx.VariableFunc("signapkCmd", func(c interface{}) (string, error) {
return c.(common.Config).HostJavaTool("signapk.jar")
})
} }
func CreateResourceJavaFiles(ctx common.AndroidModuleContext, flags []string, func CreateResourceJavaFiles(ctx common.AndroidModuleContext, flags []string,
deps []string) (string, string, string) { deps common.Paths) (common.Path, common.Path, common.Path) {
javaDir := filepath.Join(common.ModuleGenDir(ctx), "R") javaDir := common.PathForModuleGen(ctx, "R")
javaFileList := filepath.Join(common.ModuleOutDir(ctx), "R.filelist") javaFileList := common.PathForModuleOut(ctx, "R.filelist")
publicResourcesFile := filepath.Join(common.ModuleOutDir(ctx), "public_resources.xml") publicResourcesFile := common.PathForModuleOut(ctx, "public_resources.xml")
proguardOptionsFile := filepath.Join(common.ModuleOutDir(ctx), "proguard.options") proguardOptionsFile := common.PathForModuleOut(ctx, "proguard.options")
ctx.Build(pctx, blueprint.BuildParams{ ctx.ModuleBuild(pctx, common.ModuleBuildParams{
Rule: aaptCreateResourceJavaFile, Rule: aaptCreateResourceJavaFile,
Outputs: []string{publicResourcesFile, proguardOptionsFile, javaFileList}, Outputs: common.WritablePaths{publicResourcesFile, proguardOptionsFile, javaFileList},
Implicits: deps, Implicits: deps,
Args: map[string]string{ Args: map[string]string{
"aaptFlags": strings.Join(flags, " "), "aaptFlags": strings.Join(flags, " "),
"publicResourcesFile": publicResourcesFile, "publicResourcesFile": publicResourcesFile.String(),
"proguardOptionsFile": proguardOptionsFile, "proguardOptionsFile": proguardOptionsFile.String(),
"javaDir": javaDir, "javaDir": javaDir.String(),
"javaFileList": javaFileList, "javaFileList": javaFileList.String(),
}, },
}) })
return publicResourcesFile, proguardOptionsFile, javaFileList return publicResourcesFile, proguardOptionsFile, javaFileList
} }
func CreateExportPackage(ctx common.AndroidModuleContext, flags []string, deps []string) string { func CreateExportPackage(ctx common.AndroidModuleContext, flags []string, deps common.Paths) common.ModuleOutPath {
outputFile := filepath.Join(common.ModuleOutDir(ctx), "package-export.apk") outputFile := common.PathForModuleOut(ctx, "package-export.apk")
ctx.Build(pctx, blueprint.BuildParams{ ctx.ModuleBuild(pctx, common.ModuleBuildParams{
Rule: aaptCreateAssetsPackage, Rule: aaptCreateAssetsPackage,
Outputs: []string{outputFile}, Output: outputFile,
Implicits: deps, Implicits: deps,
Args: map[string]string{ Args: map[string]string{
"aaptFlags": strings.Join(flags, " "), "aaptFlags": strings.Join(flags, " "),
@@ -122,31 +117,31 @@ func CreateExportPackage(ctx common.AndroidModuleContext, flags []string, deps [
return outputFile return outputFile
} }
func CreateAppPackage(ctx common.AndroidModuleContext, flags []string, jarFile string, func CreateAppPackage(ctx common.AndroidModuleContext, flags []string, jarFile common.Path,
certificates []string) string { certificates []string) common.Path {
resourceApk := filepath.Join(common.ModuleOutDir(ctx), "resources.apk") resourceApk := common.PathForModuleOut(ctx, "resources.apk")
ctx.Build(pctx, blueprint.BuildParams{ ctx.ModuleBuild(pctx, common.ModuleBuildParams{
Rule: aaptAddResources, Rule: aaptAddResources,
Outputs: []string{resourceApk}, Output: resourceApk,
Inputs: []string{jarFile}, Input: jarFile,
Args: map[string]string{ Args: map[string]string{
"aaptFlags": strings.Join(flags, " "), "aaptFlags": strings.Join(flags, " "),
}, },
}) })
outputFile := filepath.Join(common.ModuleOutDir(ctx), "package.apk") outputFile := common.PathForModuleOut(ctx, "package.apk")
var certificateArgs []string var certificateArgs []string
for _, c := range certificates { for _, c := range certificates {
certificateArgs = append(certificateArgs, c+".x509.pem", c+".pk8") certificateArgs = append(certificateArgs, c+".x509.pem", c+".pk8")
} }
ctx.Build(pctx, blueprint.BuildParams{ ctx.ModuleBuild(pctx, common.ModuleBuildParams{
Rule: signapk, Rule: signapk,
Outputs: []string{outputFile}, Output: outputFile,
Inputs: []string{resourceApk}, Input: resourceApk,
Args: map[string]string{ Args: map[string]string{
"certificates": strings.Join(certificateArgs, " "), "certificates": strings.Join(certificateArgs, " "),
}, },

View File

@@ -29,7 +29,7 @@ import (
) )
var ( var (
pctx = blueprint.NewPackageContext("android/soong/java") pctx = common.NewPackageContext("android/soong/java")
// Compiling java is not conducive to proper dependency tracking. The path-matches-class-name // Compiling java is not conducive to proper dependency tracking. The path-matches-class-name
// requirement leads to unpredictable generated source file names, and a single .java file // requirement leads to unpredictable generated source file names, and a single .java file
@@ -91,12 +91,8 @@ func init() {
pctx.StaticVariable("commonJdkFlags", "-source 1.7 -target 1.7 -Xmaxerrs 9999999") pctx.StaticVariable("commonJdkFlags", "-source 1.7 -target 1.7 -Xmaxerrs 9999999")
pctx.StaticVariable("javacCmd", "javac -J-Xmx1024M $commonJdkFlags") pctx.StaticVariable("javacCmd", "javac -J-Xmx1024M $commonJdkFlags")
pctx.StaticVariable("jarCmd", filepath.Join("${bootstrap.BinDir}", "soong_jar")) pctx.StaticVariable("jarCmd", filepath.Join("${bootstrap.BinDir}", "soong_jar"))
pctx.VariableFunc("dxCmd", func(c interface{}) (string, error) { pctx.HostBinToolVariable("dxCmd", "dx")
return c.(common.Config).HostBinTool("dx") pctx.HostJavaToolVariable("jarjarCmd", "jarjar.jar")
})
pctx.VariableFunc("jarjarCmd", func(c interface{}) (string, error) {
return c.(common.Config).HostJavaTool("jarjar.jar")
})
} }
type javaBuilderFlags struct { type javaBuilderFlags struct {
@@ -108,33 +104,33 @@ type javaBuilderFlags struct {
} }
type jarSpec struct { type jarSpec struct {
fileList, dir string fileList, dir common.Path
} }
func (j jarSpec) soongJarArgs() string { func (j jarSpec) soongJarArgs() string {
return "-C " + j.dir + " -l " + j.fileList return "-C " + j.dir.String() + " -l " + j.fileList.String()
} }
func TransformJavaToClasses(ctx common.AndroidModuleContext, srcFiles []string, srcFileLists []string, func TransformJavaToClasses(ctx common.AndroidModuleContext, srcFiles common.Paths, srcFileLists common.Paths,
flags javaBuilderFlags, deps []string) jarSpec { flags javaBuilderFlags, deps common.Paths) jarSpec {
classDir := filepath.Join(common.ModuleOutDir(ctx), "classes") classDir := common.PathForModuleOut(ctx, "classes")
classFileList := filepath.Join(common.ModuleOutDir(ctx), "classes.list") classFileList := common.PathForModuleOut(ctx, "classes.list")
javacFlags := flags.javacFlags + common.JoinWithPrefix(srcFileLists, "@") javacFlags := flags.javacFlags + common.JoinWithPrefix(srcFileLists.Strings(), "@")
deps = append(deps, srcFileLists...) deps = append(deps, srcFileLists...)
ctx.Build(pctx, blueprint.BuildParams{ ctx.ModuleBuild(pctx, common.ModuleBuildParams{
Rule: javac, Rule: javac,
Outputs: []string{classFileList}, Output: classFileList,
Inputs: srcFiles, Inputs: srcFiles,
Implicits: deps, Implicits: deps,
Args: map[string]string{ Args: map[string]string{
"javacFlags": javacFlags, "javacFlags": javacFlags,
"bootClasspath": flags.bootClasspath, "bootClasspath": flags.bootClasspath,
"classpath": flags.classpath, "classpath": flags.classpath,
"outDir": classDir, "outDir": classDir.String(),
}, },
}) })
@@ -142,11 +138,11 @@ func TransformJavaToClasses(ctx common.AndroidModuleContext, srcFiles []string,
} }
func TransformClassesToJar(ctx common.AndroidModuleContext, classes []jarSpec, func TransformClassesToJar(ctx common.AndroidModuleContext, classes []jarSpec,
manifest string) string { manifest common.OptionalPath) common.Path {
outputFile := filepath.Join(common.ModuleOutDir(ctx), "classes-full-debug.jar") outputFile := common.PathForModuleOut(ctx, "classes-full-debug.jar")
deps := []string{} deps := common.Paths{}
jarArgs := []string{} jarArgs := []string{}
for _, j := range classes { for _, j := range classes {
@@ -154,14 +150,14 @@ func TransformClassesToJar(ctx common.AndroidModuleContext, classes []jarSpec,
jarArgs = append(jarArgs, j.soongJarArgs()) jarArgs = append(jarArgs, j.soongJarArgs())
} }
if manifest != "" { if manifest.Valid() {
deps = append(deps, manifest) deps = append(deps, manifest.Path())
jarArgs = append(jarArgs, "-m "+manifest) jarArgs = append(jarArgs, "-m "+manifest.String())
} }
ctx.Build(pctx, blueprint.BuildParams{ ctx.ModuleBuild(pctx, common.ModuleBuildParams{
Rule: jar, Rule: jar,
Outputs: []string{outputFile}, Output: outputFile,
Implicits: deps, Implicits: deps,
Args: map[string]string{ Args: map[string]string{
"jarArgs": strings.Join(jarArgs, " "), "jarArgs": strings.Join(jarArgs, " "),
@@ -171,19 +167,19 @@ func TransformClassesToJar(ctx common.AndroidModuleContext, classes []jarSpec,
return outputFile return outputFile
} }
func TransformClassesJarToDex(ctx common.AndroidModuleContext, classesJar string, func TransformClassesJarToDex(ctx common.AndroidModuleContext, classesJar common.Path,
flags javaBuilderFlags) jarSpec { flags javaBuilderFlags) jarSpec {
outDir := filepath.Join(common.ModuleOutDir(ctx), "dex") outDir := common.PathForModuleOut(ctx, "dex")
outputFile := filepath.Join(common.ModuleOutDir(ctx), "dex.filelist") outputFile := common.PathForModuleOut(ctx, "dex.filelist")
ctx.Build(pctx, blueprint.BuildParams{ ctx.ModuleBuild(pctx, common.ModuleBuildParams{
Rule: dx, Rule: dx,
Outputs: []string{outputFile}, Output: outputFile,
Inputs: []string{classesJar}, Input: classesJar,
Args: map[string]string{ Args: map[string]string{
"dxFlags": flags.dxFlags, "dxFlags": flags.dxFlags,
"outDir": outDir, "outDir": outDir.String(),
}, },
}) })
@@ -191,10 +187,10 @@ func TransformClassesJarToDex(ctx common.AndroidModuleContext, classesJar string
} }
func TransformDexToJavaLib(ctx common.AndroidModuleContext, resources []jarSpec, func TransformDexToJavaLib(ctx common.AndroidModuleContext, resources []jarSpec,
dexJarSpec jarSpec) string { dexJarSpec jarSpec) common.Path {
outputFile := filepath.Join(common.ModuleOutDir(ctx), "javalib.jar") outputFile := common.PathForModuleOut(ctx, "javalib.jar")
var deps []string var deps common.Paths
var jarArgs []string var jarArgs []string
for _, j := range resources { for _, j := range resources {
@@ -205,9 +201,9 @@ func TransformDexToJavaLib(ctx common.AndroidModuleContext, resources []jarSpec,
deps = append(deps, dexJarSpec.fileList) deps = append(deps, dexJarSpec.fileList)
jarArgs = append(jarArgs, dexJarSpec.soongJarArgs()) jarArgs = append(jarArgs, dexJarSpec.soongJarArgs())
ctx.Build(pctx, blueprint.BuildParams{ ctx.ModuleBuild(pctx, common.ModuleBuildParams{
Rule: jar, Rule: jar,
Outputs: []string{outputFile}, Output: outputFile,
Implicits: deps, Implicits: deps,
Args: map[string]string{ Args: map[string]string{
"jarArgs": strings.Join(jarArgs, " "), "jarArgs": strings.Join(jarArgs, " "),
@@ -217,14 +213,15 @@ func TransformDexToJavaLib(ctx common.AndroidModuleContext, resources []jarSpec,
return outputFile return outputFile
} }
func TransformJarJar(ctx common.AndroidModuleContext, classesJar string, rulesFile string) string { func TransformJarJar(ctx common.AndroidModuleContext, classesJar common.Path, rulesFile common.Path) common.Path {
outputFile := filepath.Join(common.ModuleOutDir(ctx), "classes-jarjar.jar") outputFile := common.PathForModuleOut(ctx, "classes-jarjar.jar")
ctx.Build(pctx, blueprint.BuildParams{ ctx.ModuleBuild(pctx, common.ModuleBuildParams{
Rule: jarjar, Rule: jarjar,
Outputs: []string{outputFile}, Output: outputFile,
Inputs: []string{classesJar}, Input: classesJar,
Implicit: rulesFile,
Args: map[string]string{ Args: map[string]string{
"rulesFile": rulesFile, "rulesFile": rulesFile.String(),
}, },
}) })
@@ -232,21 +229,20 @@ func TransformJarJar(ctx common.AndroidModuleContext, classesJar string, rulesFi
} }
func TransformPrebuiltJarToClasses(ctx common.AndroidModuleContext, func TransformPrebuiltJarToClasses(ctx common.AndroidModuleContext,
prebuilt string) (classJarSpec, resourceJarSpec jarSpec) { prebuilt common.Path) (classJarSpec, resourceJarSpec jarSpec) {
extractedDir := filepath.Join(common.ModuleOutDir(ctx), "extracted") classDir := common.PathForModuleOut(ctx, "extracted/classes")
classDir := filepath.Join(extractedDir, "classes") classFileList := common.PathForModuleOut(ctx, "extracted/classes.list")
classFileList := filepath.Join(extractedDir, "classes.list") resourceFileList := common.PathForModuleOut(ctx, "extracted/resources.list")
resourceFileList := filepath.Join(extractedDir, "resources.list")
ctx.Build(pctx, blueprint.BuildParams{ ctx.ModuleBuild(pctx, common.ModuleBuildParams{
Rule: extractPrebuilt, Rule: extractPrebuilt,
Outputs: []string{classFileList, resourceFileList}, Outputs: common.WritablePaths{classFileList, resourceFileList},
Inputs: []string{prebuilt}, Input: prebuilt,
Args: map[string]string{ Args: map[string]string{
"outDir": classDir, "outDir": classDir.String(),
"classFile": classFileList, "classFile": classFileList.String(),
"resourceFile": resourceFileList, "resourceFile": resourceFileList.String(),
}, },
}) })

View File

@@ -19,25 +19,17 @@ package java
// functions. // functions.
import ( import (
"path/filepath"
"github.com/google/blueprint" "github.com/google/blueprint"
"github.com/google/blueprint/pathtools"
"android/soong/common" "android/soong/common"
) )
func init() { func init() {
pctx.VariableFunc("aidlCmd", func(c interface{}) (string, error) { pctx.HostBinToolVariable("aidlCmd", "aidl")
return c.(common.Config).HostBinTool("aidl") pctx.SourcePathVariable("logtagsCmd", "build/tools/java-event-log-tags.py")
}) pctx.SourcePathVariable("mergeLogtagsCmd", "build/tools/merge-event-log-tags.py")
pctx.StaticVariable("logtagsCmd", "${srcDir}/build/tools/java-event-log-tags.py")
pctx.StaticVariable("mergeLogtagsCmd", "${srcDir}/build/tools/merge-event-log-tags.py")
pctx.VariableConfigMethod("srcDir", common.Config.SrcDir)
pctx.VariableFunc("allLogtagsFile", func(c interface{}) (string, error) { pctx.IntermediatesPathVariable("allLogtagsFile", "all-event-log-tags.txt")
return filepath.Join(c.(common.Config).IntermediatesDir(), "all-event-log-tags.txt"), nil
})
} }
var ( var (
@@ -64,16 +56,14 @@ var (
}) })
) )
func genAidl(ctx common.AndroidModuleContext, aidlFile, aidlFlags string) string { func genAidl(ctx common.AndroidModuleContext, aidlFile common.Path, aidlFlags string) common.Path {
javaFile := common.SrcDirRelPath(ctx, aidlFile) javaFile := common.GenPathWithExt(ctx, aidlFile, "java")
javaFile = filepath.Join(common.ModuleGenDir(ctx), javaFile) depFile := javaFile.String() + ".d"
javaFile = pathtools.ReplaceExtension(javaFile, "java")
depFile := javaFile + ".d"
ctx.Build(pctx, blueprint.BuildParams{ ctx.ModuleBuild(pctx, common.ModuleBuildParams{
Rule: aidl, Rule: aidl,
Outputs: []string{javaFile}, Output: javaFile,
Inputs: []string{aidlFile}, Input: aidlFile,
Args: map[string]string{ Args: map[string]string{
"depFile": depFile, "depFile": depFile,
"aidlFlags": aidlFlags, "aidlFlags": aidlFlags,
@@ -83,25 +73,23 @@ func genAidl(ctx common.AndroidModuleContext, aidlFile, aidlFlags string) string
return javaFile return javaFile
} }
func genLogtags(ctx common.AndroidModuleContext, logtagsFile string) string { func genLogtags(ctx common.AndroidModuleContext, logtagsFile common.Path) common.Path {
javaFile := common.SrcDirRelPath(ctx, logtagsFile) javaFile := common.GenPathWithExt(ctx, logtagsFile, "java")
javaFile = filepath.Join(common.ModuleGenDir(ctx), javaFile)
javaFile = pathtools.ReplaceExtension(javaFile, "java")
ctx.Build(pctx, blueprint.BuildParams{ ctx.ModuleBuild(pctx, common.ModuleBuildParams{
Rule: logtags, Rule: logtags,
Outputs: []string{javaFile}, Output: javaFile,
Inputs: []string{logtagsFile}, Input: logtagsFile,
}) })
return javaFile return javaFile
} }
func (j *javaBase) genSources(ctx common.AndroidModuleContext, srcFiles []string, func (j *javaBase) genSources(ctx common.AndroidModuleContext, srcFiles common.Paths,
flags javaBuilderFlags) []string { flags javaBuilderFlags) common.Paths {
for i, srcFile := range srcFiles { for i, srcFile := range srcFiles {
switch filepath.Ext(srcFile) { switch srcFile.Ext() {
case ".aidl": case ".aidl":
javaFile := genAidl(ctx, srcFile, flags.aidlFlags) javaFile := genAidl(ctx, srcFile, flags.aidlFlags)
srcFiles[i] = javaFile srcFiles[i] = javaFile
@@ -120,13 +108,13 @@ func LogtagsSingleton() blueprint.Singleton {
} }
type logtagsProducer interface { type logtagsProducer interface {
logtags() []string logtags() common.Paths
} }
type logtagsSingleton struct{} type logtagsSingleton struct{}
func (l *logtagsSingleton) GenerateBuildActions(ctx blueprint.SingletonContext) { func (l *logtagsSingleton) GenerateBuildActions(ctx blueprint.SingletonContext) {
var allLogtags []string var allLogtags common.Paths
ctx.VisitAllModules(func(module blueprint.Module) { ctx.VisitAllModules(func(module blueprint.Module) {
if logtags, ok := module.(logtagsProducer); ok { if logtags, ok := module.(logtagsProducer); ok {
allLogtags = append(allLogtags, logtags.logtags()...) allLogtags = append(allLogtags, logtags.logtags()...)
@@ -136,6 +124,6 @@ func (l *logtagsSingleton) GenerateBuildActions(ctx blueprint.SingletonContext)
ctx.Build(pctx, blueprint.BuildParams{ ctx.Build(pctx, blueprint.BuildParams{
Rule: mergeLogtags, Rule: mergeLogtags,
Outputs: []string{"$allLogtagsFile"}, Outputs: []string{"$allLogtagsFile"},
Inputs: allLogtags, Inputs: allLogtags.Strings(),
}) })
} }

View File

@@ -20,11 +20,9 @@ package java
import ( import (
"fmt" "fmt"
"path/filepath"
"strings" "strings"
"github.com/google/blueprint" "github.com/google/blueprint"
"github.com/google/blueprint/pathtools"
"android/soong" "android/soong"
"android/soong/common" "android/soong/common"
@@ -93,7 +91,7 @@ type javaBaseProperties struct {
Java_static_libs []string `android:"arch_variant"` Java_static_libs []string `android:"arch_variant"`
// manifest file to be included in resulting jar // manifest file to be included in resulting jar
Manifest string Manifest *string
// if not blank, set to the version of the sdk to compile against // if not blank, set to the version of the sdk to compile against
Sdk_version string Sdk_version string
@@ -103,7 +101,7 @@ type javaBaseProperties struct {
Dex bool `blueprint:"mutated"` Dex bool `blueprint:"mutated"`
// if not blank, run jarjar using the specified rules file // if not blank, run jarjar using the specified rules file
Jarjar_rules string Jarjar_rules *string
// directories to pass to aidl tool // directories to pass to aidl tool
Aidl_includes []string Aidl_includes []string
@@ -122,10 +120,10 @@ type javaBase struct {
properties javaBaseProperties properties javaBaseProperties
// output file suitable for inserting into the classpath of another compile // output file suitable for inserting into the classpath of another compile
classpathFile string classpathFile common.Path
// output file suitable for installing or running // output file suitable for installing or running
outputFile string outputFile common.Path
// jarSpecs suitable for inserting classes from a static library into another jar // jarSpecs suitable for inserting classes from a static library into another jar
classJarSpecs []jarSpec classJarSpecs []jarSpec
@@ -133,16 +131,16 @@ type javaBase struct {
// jarSpecs suitable for inserting resources from a static library into another jar // jarSpecs suitable for inserting resources from a static library into another jar
resourceJarSpecs []jarSpec resourceJarSpecs []jarSpec
exportAidlIncludeDirs []string exportAidlIncludeDirs common.Paths
logtagsSrcs []string logtagsSrcs common.Paths
// filelists of extra source files that should be included in the javac command line, // filelists of extra source files that should be included in the javac command line,
// for example R.java generated by aapt for android apps // for example R.java generated by aapt for android apps
ExtraSrcLists []string ExtraSrcLists common.Paths
// installed file for binary dependency // installed file for binary dependency
installFile string installFile common.Path
} }
type AndroidJavaModuleContext common.AndroidBaseContext type AndroidJavaModuleContext common.AndroidBaseContext
@@ -153,10 +151,10 @@ type JavaModuleType interface {
} }
type JavaDependency interface { type JavaDependency interface {
ClasspathFile() string ClasspathFile() common.Path
ClassJarSpecs() []jarSpec ClassJarSpecs() []jarSpec
ResourceJarSpecs() []jarSpec ResourceJarSpecs() []jarSpec
AidlIncludeDirs() []string AidlIncludeDirs() common.Paths
} }
func NewJavaBase(base *javaBase, module JavaModuleType, hod common.HostOrDeviceSupported, func NewJavaBase(base *javaBase, module JavaModuleType, hod common.HostOrDeviceSupported,
@@ -217,35 +215,35 @@ func (j *javaBase) JavaDependencies(ctx AndroidJavaModuleContext) []string {
return deps return deps
} }
func (j *javaBase) aidlFlags(ctx common.AndroidModuleContext, aidlPreprocess string, func (j *javaBase) aidlFlags(ctx common.AndroidModuleContext, aidlPreprocess common.OptionalPath,
aidlIncludeDirs []string) []string { aidlIncludeDirs common.Paths) []string {
localAidlIncludes := pathtools.PrefixPaths(j.properties.Aidl_includes, common.ModuleSrcDir(ctx)) localAidlIncludes := common.PathsForModuleSrc(ctx, j.properties.Aidl_includes)
var flags []string var flags []string
if aidlPreprocess != "" { if aidlPreprocess.Valid() {
flags = append(flags, "-p"+aidlPreprocess) flags = append(flags, "-p"+aidlPreprocess.String())
} else { } else {
flags = append(flags, common.JoinWithPrefix(aidlIncludeDirs, "-I")) flags = append(flags, common.JoinWithPrefix(aidlIncludeDirs.Strings(), "-I"))
} }
flags = append(flags, common.JoinWithPrefix(j.exportAidlIncludeDirs, "-I")) flags = append(flags, common.JoinWithPrefix(j.exportAidlIncludeDirs.Strings(), "-I"))
flags = append(flags, common.JoinWithPrefix(localAidlIncludes, "-I")) flags = append(flags, common.JoinWithPrefix(localAidlIncludes.Strings(), "-I"))
flags = append(flags, "-I"+common.ModuleSrcDir(ctx)) flags = append(flags, "-I"+common.PathForModuleSrc(ctx).String())
flags = append(flags, "-I"+filepath.Join(common.ModuleSrcDir(ctx), "src")) flags = append(flags, "-I"+common.PathForModuleSrc(ctx, "src").String())
return flags return flags
} }
func (j *javaBase) collectDeps(ctx common.AndroidModuleContext) (classpath []string, func (j *javaBase) collectDeps(ctx common.AndroidModuleContext) (classpath common.Paths,
bootClasspath string, classJarSpecs, resourceJarSpecs []jarSpec, aidlPreprocess string, bootClasspath common.OptionalPath, classJarSpecs, resourceJarSpecs []jarSpec, aidlPreprocess common.OptionalPath,
aidlIncludeDirs []string, srcFileLists []string) { aidlIncludeDirs common.Paths, srcFileLists common.Paths) {
ctx.VisitDirectDeps(func(module blueprint.Module) { ctx.VisitDirectDeps(func(module blueprint.Module) {
otherName := ctx.OtherModuleName(module) otherName := ctx.OtherModuleName(module)
if javaDep, ok := module.(JavaDependency); ok { if javaDep, ok := module.(JavaDependency); ok {
if otherName == j.BootClasspath(ctx) { if otherName == j.BootClasspath(ctx) {
bootClasspath = javaDep.ClasspathFile() bootClasspath = common.OptionalPathForPath(javaDep.ClasspathFile())
} else if inList(otherName, defaultJavaLibraries) { } else if inList(otherName, defaultJavaLibraries) {
classpath = append(classpath, javaDep.ClasspathFile()) classpath = append(classpath, javaDep.ClasspathFile())
} else if inList(otherName, j.properties.Java_libs) { } else if inList(otherName, j.properties.Java_libs) {
@@ -265,8 +263,8 @@ func (j *javaBase) collectDeps(ctx common.AndroidModuleContext) (classpath []str
} }
aidlIncludeDirs = append(aidlIncludeDirs, javaDep.AidlIncludeDirs()...) aidlIncludeDirs = append(aidlIncludeDirs, javaDep.AidlIncludeDirs()...)
if sdkDep, ok := module.(sdkDependency); ok { if sdkDep, ok := module.(sdkDependency); ok {
if sdkDep.AidlPreprocessed() != "" { if sdkDep.AidlPreprocessed().Valid() {
if aidlPreprocess != "" { if aidlPreprocess.Valid() {
ctx.ModuleErrorf("multiple dependencies with preprocessed aidls:\n %q\n %q", ctx.ModuleErrorf("multiple dependencies with preprocessed aidls:\n %q\n %q",
aidlPreprocess, sdkDep.AidlPreprocessed()) aidlPreprocess, sdkDep.AidlPreprocessed())
} else { } else {
@@ -287,8 +285,7 @@ func (j *javaBase) GenerateAndroidBuildActions(ctx common.AndroidModuleContext)
func (j *javaBase) GenerateJavaBuildActions(ctx common.AndroidModuleContext) { func (j *javaBase) GenerateJavaBuildActions(ctx common.AndroidModuleContext) {
j.exportAidlIncludeDirs = pathtools.PrefixPaths(j.properties.Export_aidl_include_dirs, j.exportAidlIncludeDirs = common.PathsForModuleSrc(ctx, j.properties.Export_aidl_include_dirs)
common.ModuleSrcDir(ctx))
classpath, bootClasspath, classJarSpecs, resourceJarSpecs, aidlPreprocess, classpath, bootClasspath, classJarSpecs, resourceJarSpecs, aidlPreprocess,
aidlIncludeDirs, srcFileLists := j.collectDeps(ctx) aidlIncludeDirs, srcFileLists := j.collectDeps(ctx)
@@ -307,15 +304,15 @@ func (j *javaBase) GenerateJavaBuildActions(ctx common.AndroidModuleContext) {
flags.aidlFlags = "$aidlFlags" flags.aidlFlags = "$aidlFlags"
} }
var javacDeps []string var javacDeps common.Paths
if bootClasspath != "" { if bootClasspath.Valid() {
flags.bootClasspath = "-bootclasspath " + bootClasspath flags.bootClasspath = "-bootclasspath " + bootClasspath.String()
javacDeps = append(javacDeps, bootClasspath) javacDeps = append(javacDeps, bootClasspath.Path())
} }
if len(classpath) > 0 { if len(classpath) > 0 {
flags.classpath = "-classpath " + strings.Join(classpath, ":") flags.classpath = "-classpath " + strings.Join(classpath.Strings(), ":")
javacDeps = append(javacDeps, classpath...) javacDeps = append(javacDeps, classpath...)
} }
@@ -344,10 +341,7 @@ func (j *javaBase) GenerateJavaBuildActions(ctx common.AndroidModuleContext) {
resourceJarSpecs = append(ResourceDirsToJarSpecs(ctx, j.properties.Java_resource_dirs, j.properties.Exclude_java_resource_dirs), resourceJarSpecs = append(ResourceDirsToJarSpecs(ctx, j.properties.Java_resource_dirs, j.properties.Exclude_java_resource_dirs),
resourceJarSpecs...) resourceJarSpecs...)
manifest := j.properties.Manifest manifest := common.OptionalPathForModuleSrc(ctx, j.properties.Manifest)
if manifest != "" {
manifest = filepath.Join(common.ModuleSrcDir(ctx), manifest)
}
allJarSpecs := append([]jarSpec(nil), classJarSpecs...) allJarSpecs := append([]jarSpec(nil), classJarSpecs...)
allJarSpecs = append(allJarSpecs, resourceJarSpecs...) allJarSpecs = append(allJarSpecs, resourceJarSpecs...)
@@ -358,8 +352,8 @@ func (j *javaBase) GenerateJavaBuildActions(ctx common.AndroidModuleContext) {
return return
} }
if j.properties.Jarjar_rules != "" { if j.properties.Jarjar_rules != nil {
jarjar_rules := filepath.Join(common.ModuleSrcDir(ctx), j.properties.Jarjar_rules) jarjar_rules := common.PathForModuleSrc(ctx, *j.properties.Jarjar_rules)
// Transform classes-full-debug.jar into classes-jarjar.jar // Transform classes-full-debug.jar into classes-jarjar.jar
outputFile = TransformJarJar(ctx, outputFile, jarjar_rules) outputFile = TransformJarJar(ctx, outputFile, jarjar_rules)
if ctx.Failed() { if ctx.Failed() {
@@ -394,7 +388,7 @@ func (j *javaBase) GenerateJavaBuildActions(ctx common.AndroidModuleContext) {
dxFlags = append(dxFlags, dxFlags = append(dxFlags,
"--debug", "--debug",
"--verbose", "--verbose",
"--dump-to="+filepath.Join(common.ModuleOutDir(ctx), "classes.lst"), "--dump-to="+common.PathForModuleOut(ctx, "classes.lst").String(),
"--dump-width=1000") "--dump-width=1000")
} }
@@ -415,7 +409,7 @@ func (j *javaBase) GenerateJavaBuildActions(ctx common.AndroidModuleContext) {
var _ JavaDependency = (*JavaLibrary)(nil) var _ JavaDependency = (*JavaLibrary)(nil)
func (j *javaBase) ClasspathFile() string { func (j *javaBase) ClasspathFile() common.Path {
return j.classpathFile return j.classpathFile
} }
@@ -427,13 +421,13 @@ func (j *javaBase) ResourceJarSpecs() []jarSpec {
return j.resourceJarSpecs return j.resourceJarSpecs
} }
func (j *javaBase) AidlIncludeDirs() []string { func (j *javaBase) AidlIncludeDirs() common.Paths {
return j.exportAidlIncludeDirs return j.exportAidlIncludeDirs
} }
var _ logtagsProducer = (*javaBase)(nil) var _ logtagsProducer = (*javaBase)(nil)
func (j *javaBase) logtags() []string { func (j *javaBase) logtags() common.Paths {
return j.logtagsSrcs return j.logtagsSrcs
} }
@@ -485,7 +479,7 @@ func (j *JavaBinary) GenerateJavaBuildActions(ctx common.AndroidModuleContext) {
// Depend on the installed jar (j.installFile) so that the wrapper doesn't get executed by // Depend on the installed jar (j.installFile) so that the wrapper doesn't get executed by
// another build rule before the jar has been installed. // another build rule before the jar has been installed.
ctx.InstallFile("bin", filepath.Join(common.ModuleSrcDir(ctx), j.binaryProperties.Wrapper), ctx.InstallFile("bin", common.PathForModuleSrc(ctx, j.binaryProperties.Wrapper),
j.installFile) j.installFile)
} }
@@ -516,7 +510,7 @@ type JavaPrebuilt struct {
properties javaPrebuiltProperties properties javaPrebuiltProperties
classpathFile string classpathFile common.Path
classJarSpecs, resourceJarSpecs []jarSpec classJarSpecs, resourceJarSpecs []jarSpec
} }
@@ -525,7 +519,7 @@ func (j *JavaPrebuilt) GenerateAndroidBuildActions(ctx common.AndroidModuleConte
ctx.ModuleErrorf("expected exactly one jar in srcs") ctx.ModuleErrorf("expected exactly one jar in srcs")
return return
} }
prebuilt := filepath.Join(common.ModuleSrcDir(ctx), j.properties.Srcs[0]) prebuilt := common.PathForModuleSrc(ctx, j.properties.Srcs[0])
classJarSpec, resourceJarSpec := TransformPrebuiltJarToClasses(ctx, prebuilt) classJarSpec, resourceJarSpec := TransformPrebuiltJarToClasses(ctx, prebuilt)
@@ -537,7 +531,7 @@ func (j *JavaPrebuilt) GenerateAndroidBuildActions(ctx common.AndroidModuleConte
var _ JavaDependency = (*JavaPrebuilt)(nil) var _ JavaDependency = (*JavaPrebuilt)(nil)
func (j *JavaPrebuilt) ClasspathFile() string { func (j *JavaPrebuilt) ClasspathFile() common.Path {
return j.classpathFile return j.classpathFile
} }
@@ -549,7 +543,7 @@ func (j *JavaPrebuilt) ResourceJarSpecs() []jarSpec {
return j.resourceJarSpecs return j.resourceJarSpecs
} }
func (j *JavaPrebuilt) AidlIncludeDirs() []string { func (j *JavaPrebuilt) AidlIncludeDirs() common.Paths {
return nil return nil
} }
@@ -566,13 +560,13 @@ func JavaPrebuiltFactory() (blueprint.Module, []interface{}) {
type sdkDependency interface { type sdkDependency interface {
JavaDependency JavaDependency
AidlPreprocessed() string AidlPreprocessed() common.OptionalPath
} }
var _ sdkDependency = (*sdkPrebuilt)(nil) var _ sdkDependency = (*sdkPrebuilt)(nil)
type sdkPrebuiltProperties struct { type sdkPrebuiltProperties struct {
Aidl_preprocessed string Aidl_preprocessed *string
} }
type sdkPrebuilt struct { type sdkPrebuilt struct {
@@ -580,18 +574,16 @@ type sdkPrebuilt struct {
sdkProperties sdkPrebuiltProperties sdkProperties sdkPrebuiltProperties
aidlPreprocessed string aidlPreprocessed common.OptionalPath
} }
func (j *sdkPrebuilt) GenerateAndroidBuildActions(ctx common.AndroidModuleContext) { func (j *sdkPrebuilt) GenerateAndroidBuildActions(ctx common.AndroidModuleContext) {
j.JavaPrebuilt.GenerateAndroidBuildActions(ctx) j.JavaPrebuilt.GenerateAndroidBuildActions(ctx)
if j.sdkProperties.Aidl_preprocessed != "" { j.aidlPreprocessed = common.OptionalPathForModuleSrc(ctx, j.sdkProperties.Aidl_preprocessed)
j.aidlPreprocessed = filepath.Join(common.ModuleSrcDir(ctx), j.sdkProperties.Aidl_preprocessed)
}
} }
func (j *sdkPrebuilt) AidlPreprocessed() string { func (j *sdkPrebuilt) AidlPreprocessed() common.OptionalPath {
return j.aidlPreprocessed return j.aidlPreprocessed
} }

View File

@@ -42,7 +42,7 @@ func ResourceDirsToJarSpecs(ctx common.AndroidModuleContext, resourceDirs, exclu
var excludes []string var excludes []string
for _, exclude := range excludeDirs { for _, exclude := range excludeDirs {
excludes = append(excludes, filepath.Join(common.ModuleSrcDir(ctx), exclude, "**/*")) excludes = append(excludes, common.PathForModuleSrc(ctx, exclude, "**/*").String())
} }
excludes = append(excludes, resourceExcludes...) excludes = append(excludes, resourceExcludes...)
@@ -53,15 +53,14 @@ func ResourceDirsToJarSpecs(ctx common.AndroidModuleContext, resourceDirs, exclu
if isStringInSlice(resourceDir, excludeDirs) { if isStringInSlice(resourceDir, excludeDirs) {
continue continue
} }
resourceDir := filepath.Join(common.ModuleSrcDir(ctx), resourceDir) resourceDir := common.PathForModuleSrc(ctx, resourceDir)
dirs := ctx.Glob("java_resources", resourceDir, nil) dirs := ctx.Glob("java_resources", resourceDir.String(), nil)
for _, dir := range dirs { for _, dir := range dirs {
relDir := common.SrcDirRelPath(ctx, dir) fileListFile := common.ResPathWithName(ctx, dir, "resources.list")
fileListFile := filepath.Join(common.ModuleOutDir(ctx), "res", relDir, "resources.list") depFile := fileListFile.String() + ".d"
depFile := fileListFile + ".d"
glob := filepath.Join(dir, "**/*") glob := filepath.Join(dir.String(), "**/*")
common.GlobRule(ctx, glob, excludes, fileListFile, depFile) common.GlobRule(ctx, glob, excludes, fileListFile.String(), depFile)
jarSpecs = append(jarSpecs, jarSpec{fileListFile, dir}) jarSpecs = append(jarSpecs, jarSpec{fileListFile, dir})
} }
} }