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:
@@ -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 {
|
||||||
|
@@ -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 :=",
|
||||||
|
@@ -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")
|
||||||
|
@@ -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")
|
||||||
|
116
cc/builder.go
116
cc/builder.go
@@ -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,15 +203,15 @@ 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,
|
||||||
@@ -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,9 +356,9 @@ 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,
|
||||||
@@ -388,15 +368,15 @@ func TransformObjsToObj(ctx common.AndroidModuleContext, objFiles []string,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 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
274
cc/cc.go
@@ -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) {
|
||||||
|
51
cc/gen.go
51
cc/gen.go
@@ -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
|
||||||
|
@@ -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")
|
||||||
|
@@ -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")
|
||||||
|
@@ -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 {
|
||||||
|
@@ -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")
|
||||||
|
@@ -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")
|
||||||
|
|
||||||
|
@@ -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")
|
||||||
|
@@ -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")
|
||||||
|
|
||||||
|
@@ -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")
|
||||||
|
|
||||||
|
@@ -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,30 +72,15 @@ 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)
|
|
||||||
if err != nil {
|
|
||||||
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] {
|
for _, mod := range dirModules[bpDir] {
|
||||||
androidMkModules[mod] = true
|
androidMkModules[mod] = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Validate that all modules have proper dependencies
|
// Validate that all modules have proper dependencies
|
||||||
androidMkModulesList := make([]AndroidModule, 0, len(androidMkModules))
|
androidMkModulesList := make([]AndroidModule, 0, len(androidMkModules))
|
||||||
@@ -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] {
|
||||||
|
@@ -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")
|
||||||
}
|
}
|
||||||
|
@@ -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.
|
||||||
|
@@ -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())
|
||||||
}
|
}
|
||||||
|
135
common/module.go
135
common/module.go
@@ -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
127
common/package_ctx.go
Normal 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
|
||||||
|
})
|
||||||
|
}
|
624
common/paths.go
624
common/paths.go
@@ -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 {
|
|
||||||
return filepath.Join(ModuleOutDir(ctx), "obj")
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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 {
|
} else {
|
||||||
ctx.PropertyErrorf(prop, "%s", err.Error())
|
panic(fmt.Sprintf(format, args...))
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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)
|
|
||||||
|
// WritablePath is a type of path that can be used as an output for build rules.
|
||||||
|
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 {
|
} else {
|
||||||
ctx.PropertyErrorf(prop, "%s", err.Error())
|
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
167
common/paths_test.go
Normal 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)
|
||||||
|
}
|
||||||
|
}
|
@@ -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
|
||||||
}
|
}
|
||||||
|
101
java/app.go
101
java/app.go
@@ -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())
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@@ -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, " "),
|
||||||
},
|
},
|
||||||
|
104
java/builder.go
104
java/builder.go
@@ -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(),
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
54
java/gen.go
54
java/gen.go
@@ -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(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
106
java/java.go
106
java/java.go
@@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -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})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user