Merge "Remove timestamp based filelist file for tracking Python dependencies"
am: 8b00247b66
Change-Id: Ib8213c35e21fbb56837d4f9a3cc78228fbedf8f1
This commit is contained in:
@@ -63,6 +63,7 @@ var (
|
|||||||
zipsToNotStrip = make(zipsToNotStripSet)
|
zipsToNotStrip = make(zipsToNotStripSet)
|
||||||
stripDirEntries = flag.Bool("D", false, "strip directory entries from the output zip file")
|
stripDirEntries = flag.Bool("D", false, "strip directory entries from the output zip file")
|
||||||
manifest = flag.String("m", "", "manifest file to insert in jar")
|
manifest = flag.String("m", "", "manifest file to insert in jar")
|
||||||
|
pyMain = flag.String("pm", "", "__main__.py file to insert in par")
|
||||||
entrypoint = flag.String("e", "", "par entrypoint file to insert in par")
|
entrypoint = flag.String("e", "", "par entrypoint file to insert in par")
|
||||||
ignoreDuplicates = flag.Bool("ignore-duplicates", false, "take each entry from the first zip it exists in and don't warn")
|
ignoreDuplicates = flag.Bool("ignore-duplicates", false, "take each entry from the first zip it exists in and don't warn")
|
||||||
)
|
)
|
||||||
@@ -75,7 +76,7 @@ func init() {
|
|||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
flag.Usage = func() {
|
flag.Usage = func() {
|
||||||
fmt.Fprintln(os.Stderr, "usage: merge_zips [-jpsD] [-m manifest] [-e entrypoint] output [inputs...]")
|
fmt.Fprintln(os.Stderr, "usage: merge_zips [-jpsD] [-m manifest] [-e entrypoint] [-pm __main__.py] output [inputs...]")
|
||||||
flag.PrintDefaults()
|
flag.PrintDefaults()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -125,8 +126,12 @@ func main() {
|
|||||||
log.Fatal(errors.New("must specify -p when specifying a entrypoint via -e"))
|
log.Fatal(errors.New("must specify -p when specifying a entrypoint via -e"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if *pyMain != "" && !*emulatePar {
|
||||||
|
log.Fatal(errors.New("must specify -p when specifying a Python __main__.py via -pm"))
|
||||||
|
}
|
||||||
|
|
||||||
// do merge
|
// do merge
|
||||||
err = mergeZips(readers, writer, *manifest, *entrypoint, *sortEntries, *emulateJar, *emulatePar,
|
err = mergeZips(readers, writer, *manifest, *entrypoint, *pyMain, *sortEntries, *emulateJar, *emulatePar,
|
||||||
*stripDirEntries, *ignoreDuplicates)
|
*stripDirEntries, *ignoreDuplicates)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
@@ -218,7 +223,7 @@ type fileMapping struct {
|
|||||||
source zipSource
|
source zipSource
|
||||||
}
|
}
|
||||||
|
|
||||||
func mergeZips(readers []namedZipReader, writer *zip.Writer, manifest, entrypoint string,
|
func mergeZips(readers []namedZipReader, writer *zip.Writer, manifest, entrypoint, pyMain string,
|
||||||
sortEntries, emulateJar, emulatePar, stripDirEntries, ignoreDuplicates bool) error {
|
sortEntries, emulateJar, emulatePar, stripDirEntries, ignoreDuplicates bool) error {
|
||||||
|
|
||||||
sourceByDest := make(map[string]zipSource, 0)
|
sourceByDest := make(map[string]zipSource, 0)
|
||||||
@@ -268,6 +273,22 @@ func mergeZips(readers []namedZipReader, writer *zip.Writer, manifest, entrypoin
|
|||||||
addMapping("entry_point.txt", fileSource)
|
addMapping("entry_point.txt", fileSource)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if pyMain != "" {
|
||||||
|
buf, err := ioutil.ReadFile(pyMain)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
fh := &zip.FileHeader{
|
||||||
|
Name: "__main__.py",
|
||||||
|
Method: zip.Store,
|
||||||
|
UncompressedSize64: uint64(len(buf)),
|
||||||
|
}
|
||||||
|
fh.SetMode(0700)
|
||||||
|
fh.SetModTime(jar.DefaultTime)
|
||||||
|
fileSource := bufferEntry{fh, buf}
|
||||||
|
addMapping("__main__.py", fileSource)
|
||||||
|
}
|
||||||
|
|
||||||
if emulatePar {
|
if emulatePar {
|
||||||
// the runfiles packages needs to be populated with "__init__.py".
|
// the runfiles packages needs to be populated with "__init__.py".
|
||||||
newPyPkgs := []string{}
|
newPyPkgs := []string{}
|
||||||
|
102
python/binary.go
102
python/binary.go
@@ -18,8 +18,6 @@ package python
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"path/filepath"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"android/soong/android"
|
"android/soong/android"
|
||||||
)
|
)
|
||||||
@@ -80,89 +78,44 @@ func (binary *binaryDecorator) bootstrapperProps() []interface{} {
|
|||||||
return []interface{}{&binary.binaryProperties}
|
return []interface{}{&binary.binaryProperties}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (binary *binaryDecorator) bootstrap(ctx android.ModuleContext, actual_version string,
|
func (binary *binaryDecorator) bootstrap(ctx android.ModuleContext, actualVersion string,
|
||||||
embedded_launcher bool, srcsPathMappings []pathMapping, parSpec parSpec,
|
embeddedLauncher bool, srcsPathMappings []pathMapping, srcsZip android.Path,
|
||||||
depsPyRunfiles []string, depsParSpecs []parSpec) android.OptionalPath {
|
depsSrcsZips android.Paths) android.OptionalPath {
|
||||||
// no Python source file for compiling .par file.
|
|
||||||
if len(srcsPathMappings) == 0 {
|
|
||||||
return android.OptionalPath{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// the runfiles packages needs to be populated with "__init__.py".
|
|
||||||
newPyPkgs := []string{}
|
|
||||||
// the set to de-duplicate the new Python packages above.
|
|
||||||
newPyPkgSet := make(map[string]bool)
|
|
||||||
// the runfiles dirs have been treated as packages.
|
|
||||||
existingPyPkgSet := make(map[string]bool)
|
|
||||||
|
|
||||||
wholePyRunfiles := []string{}
|
|
||||||
for _, path := range srcsPathMappings {
|
|
||||||
wholePyRunfiles = append(wholePyRunfiles, path.dest)
|
|
||||||
}
|
|
||||||
wholePyRunfiles = append(wholePyRunfiles, depsPyRunfiles...)
|
|
||||||
|
|
||||||
// find all the runfiles dirs which have been treated as packages.
|
|
||||||
for _, path := range wholePyRunfiles {
|
|
||||||
if filepath.Base(path) != initFileName {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
existingPyPkg := PathBeforeLastSlash(path)
|
|
||||||
if _, found := existingPyPkgSet[existingPyPkg]; found {
|
|
||||||
panic(fmt.Errorf("found init file path duplicates: %q for module: %q.",
|
|
||||||
path, ctx.ModuleName()))
|
|
||||||
} else {
|
|
||||||
existingPyPkgSet[existingPyPkg] = true
|
|
||||||
}
|
|
||||||
parentPath := PathBeforeLastSlash(existingPyPkg)
|
|
||||||
populateNewPyPkgs(parentPath, existingPyPkgSet, newPyPkgSet, &newPyPkgs)
|
|
||||||
}
|
|
||||||
|
|
||||||
// create new packages under runfiles tree.
|
|
||||||
for _, path := range wholePyRunfiles {
|
|
||||||
if filepath.Base(path) == initFileName {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
parentPath := PathBeforeLastSlash(path)
|
|
||||||
populateNewPyPkgs(parentPath, existingPyPkgSet, newPyPkgSet, &newPyPkgs)
|
|
||||||
}
|
|
||||||
|
|
||||||
main := binary.getPyMainFile(ctx, srcsPathMappings)
|
main := binary.getPyMainFile(ctx, srcsPathMappings)
|
||||||
if main == "" {
|
|
||||||
return android.OptionalPath{}
|
|
||||||
}
|
|
||||||
|
|
||||||
var launcher_path android.Path
|
var launcherPath android.Path
|
||||||
if embedded_launcher {
|
if embeddedLauncher {
|
||||||
ctx.VisitDirectDepsWithTag(launcherTag, func(m android.Module) {
|
ctx.VisitDirectDepsWithTag(launcherTag, func(m android.Module) {
|
||||||
if provider, ok := m.(IntermPathProvider); ok {
|
if provider, ok := m.(IntermPathProvider); ok {
|
||||||
if launcher_path != nil {
|
if launcherPath != nil {
|
||||||
panic(fmt.Errorf("launcher path was found before: %q",
|
panic(fmt.Errorf("launcher path was found before: %q",
|
||||||
launcher_path))
|
launcherPath))
|
||||||
}
|
}
|
||||||
launcher_path = provider.IntermPathForModuleOut().Path()
|
launcherPath = provider.IntermPathForModuleOut().Path()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
binFile := registerBuildActionForParFile(ctx, embedded_launcher, launcher_path,
|
binFile := registerBuildActionForParFile(ctx, embeddedLauncher, launcherPath,
|
||||||
binary.getHostInterpreterName(ctx, actual_version),
|
binary.getHostInterpreterName(ctx, actualVersion),
|
||||||
main, binary.getStem(ctx), newPyPkgs, append(depsParSpecs, parSpec))
|
main, binary.getStem(ctx), append(android.Paths{srcsZip}, depsSrcsZips...))
|
||||||
|
|
||||||
return android.OptionalPathForPath(binFile)
|
return android.OptionalPathForPath(binFile)
|
||||||
}
|
}
|
||||||
|
|
||||||
// get host interpreter name.
|
// get host interpreter name.
|
||||||
func (binary *binaryDecorator) getHostInterpreterName(ctx android.ModuleContext,
|
func (binary *binaryDecorator) getHostInterpreterName(ctx android.ModuleContext,
|
||||||
actual_version string) string {
|
actualVersion string) string {
|
||||||
var interp string
|
var interp string
|
||||||
switch actual_version {
|
switch actualVersion {
|
||||||
case pyVersion2:
|
case pyVersion2:
|
||||||
interp = "python2.7"
|
interp = "python2.7"
|
||||||
case pyVersion3:
|
case pyVersion3:
|
||||||
interp = "python3"
|
interp = "python3"
|
||||||
default:
|
default:
|
||||||
panic(fmt.Errorf("unknown Python actualVersion: %q for module: %q.",
|
panic(fmt.Errorf("unknown Python actualVersion: %q for module: %q.",
|
||||||
actual_version, ctx.ModuleName()))
|
actualVersion, ctx.ModuleName()))
|
||||||
}
|
}
|
||||||
|
|
||||||
return interp
|
return interp
|
||||||
@@ -196,30 +149,3 @@ func (binary *binaryDecorator) getStem(ctx android.ModuleContext) string {
|
|||||||
|
|
||||||
return stem + String(binary.binaryProperties.Suffix)
|
return stem + String(binary.binaryProperties.Suffix)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sets the given directory and all its ancestor directories as Python packages.
|
|
||||||
func populateNewPyPkgs(pkgPath string, existingPyPkgSet,
|
|
||||||
newPyPkgSet map[string]bool, newPyPkgs *[]string) {
|
|
||||||
for pkgPath != "" {
|
|
||||||
if _, found := existingPyPkgSet[pkgPath]; found {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
if _, found := newPyPkgSet[pkgPath]; !found {
|
|
||||||
newPyPkgSet[pkgPath] = true
|
|
||||||
*newPyPkgs = append(*newPyPkgs, pkgPath)
|
|
||||||
// Gets its ancestor directory by trimming last slash.
|
|
||||||
pkgPath = PathBeforeLastSlash(pkgPath)
|
|
||||||
} else {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// filepath.Dir("abc") -> "." and filepath.Dir("/abc") -> "/". However,
|
|
||||||
// the PathBeforeLastSlash() will return "" for both cases above.
|
|
||||||
func PathBeforeLastSlash(path string) string {
|
|
||||||
if idx := strings.LastIndex(path, "/"); idx != -1 {
|
|
||||||
return path[:idx]
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
@@ -17,7 +17,6 @@ package python
|
|||||||
// This file contains Ninja build actions for building Python program.
|
// This file contains Ninja build actions for building Python program.
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"android/soong/android"
|
"android/soong/android"
|
||||||
@@ -29,25 +28,30 @@ import (
|
|||||||
var (
|
var (
|
||||||
pctx = android.NewPackageContext("android/soong/python")
|
pctx = android.NewPackageContext("android/soong/python")
|
||||||
|
|
||||||
host_par = pctx.AndroidStaticRule("host_par",
|
zip = pctx.AndroidStaticRule("zip",
|
||||||
blueprint.RuleParams{
|
blueprint.RuleParams{
|
||||||
Command: `touch $initFile && ` +
|
Command: `$parCmd -o $out $args`,
|
||||||
`sed -e 's/%interpreter%/$interp/g' -e 's/%main%/$main/g' $template > $stub && ` +
|
|
||||||
`$parCmd -o $parFile $parArgs && echo '#!/usr/bin/env python' | cat - $parFile > $out && ` +
|
|
||||||
`chmod +x $out && (rm -f $initFile; rm -f $stub; rm -f $parFile)`,
|
|
||||||
CommandDeps: []string{"$parCmd", "$template"},
|
|
||||||
},
|
|
||||||
"initFile", "interp", "main", "template", "stub", "parCmd", "parFile", "parArgs")
|
|
||||||
|
|
||||||
embedded_par = pctx.AndroidStaticRule("embedded_par",
|
|
||||||
blueprint.RuleParams{
|
|
||||||
Command: `touch $initFile && ` +
|
|
||||||
`echo '$main' > $entry_point && ` +
|
|
||||||
`$parCmd -o $parFile $parArgs && cat $launcher | cat - $parFile > $out && ` +
|
|
||||||
`chmod +x $out && (rm -f $initFile; rm -f $entry_point; rm -f $parFile)`,
|
|
||||||
CommandDeps: []string{"$parCmd"},
|
CommandDeps: []string{"$parCmd"},
|
||||||
},
|
},
|
||||||
"initFile", "main", "entry_point", "parCmd", "parFile", "parArgs", "launcher")
|
"args")
|
||||||
|
|
||||||
|
hostPar = pctx.AndroidStaticRule("hostPar",
|
||||||
|
blueprint.RuleParams{
|
||||||
|
Command: `sed -e 's/%interpreter%/$interp/g' -e 's/%main%/$main/g' $template > $stub && ` +
|
||||||
|
`$mergeParCmd -p -pm $stub $mergedZip $srcsZips && echo '#!/usr/bin/env python' | cat - $mergedZip > $out && ` +
|
||||||
|
`chmod +x $out && (rm -f $stub; rm -f $mergedZip)`,
|
||||||
|
CommandDeps: []string{"$mergeParCmd"},
|
||||||
|
},
|
||||||
|
"interp", "main", "template", "stub", "mergedZip", "srcsZips")
|
||||||
|
|
||||||
|
embeddedPar = pctx.AndroidStaticRule("embeddedPar",
|
||||||
|
blueprint.RuleParams{
|
||||||
|
Command: `echo '$main' > $entryPoint &&` +
|
||||||
|
`$mergeParCmd -p -e $entryPoint $mergedZip $srcsZips && cat $launcher | cat - $mergedZip > $out && ` +
|
||||||
|
`chmod +x $out && (rm -f $entryPoint; rm -f $mergedZip)`,
|
||||||
|
CommandDeps: []string{"$mergeParCmd"},
|
||||||
|
},
|
||||||
|
"main", "entryPoint", "mergedZip", "srcsZips", "launcher")
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@@ -55,132 +59,65 @@ func init() {
|
|||||||
pctx.Import("android/soong/common")
|
pctx.Import("android/soong/common")
|
||||||
|
|
||||||
pctx.HostBinToolVariable("parCmd", "soong_zip")
|
pctx.HostBinToolVariable("parCmd", "soong_zip")
|
||||||
|
pctx.HostBinToolVariable("mergeParCmd", "merge_zips")
|
||||||
}
|
}
|
||||||
|
|
||||||
type fileListSpec struct {
|
func registerBuildActionForParFile(ctx android.ModuleContext, embeddedLauncher bool,
|
||||||
fileList android.Path
|
launcherPath android.Path, interpreter, main, binName string,
|
||||||
relativeRoot string
|
srcsZips android.Paths) android.Path {
|
||||||
}
|
|
||||||
|
|
||||||
type parSpec struct {
|
// .intermediate output path for merged zip file.
|
||||||
rootPrefix string
|
mergedZip := android.PathForModuleOut(ctx, binName+".mergedzip")
|
||||||
|
|
||||||
fileListSpecs []fileListSpec
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p parSpec) soongParArgs() string {
|
|
||||||
ret := `-P ` + p.rootPrefix
|
|
||||||
|
|
||||||
for _, spec := range p.fileListSpecs {
|
|
||||||
ret += ` -C ` + spec.relativeRoot + ` -l ` + spec.fileList.String()
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret
|
|
||||||
}
|
|
||||||
|
|
||||||
func registerBuildActionForModuleFileList(ctx android.ModuleContext,
|
|
||||||
name string, files android.Paths) android.Path {
|
|
||||||
fileList := android.PathForModuleOut(ctx, name+".list")
|
|
||||||
|
|
||||||
content := []string{}
|
|
||||||
for _, file := range files {
|
|
||||||
content = append(content, file.String())
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx.Build(pctx, android.BuildParams{
|
|
||||||
Rule: android.WriteFile,
|
|
||||||
Description: "generate " + fileList.Rel(),
|
|
||||||
Output: fileList,
|
|
||||||
Implicits: files,
|
|
||||||
Args: map[string]string{
|
|
||||||
"content": strings.Join(content, `\n`),
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
return fileList
|
|
||||||
}
|
|
||||||
|
|
||||||
func registerBuildActionForParFile(ctx android.ModuleContext, embedded_launcher bool,
|
|
||||||
launcher_path android.Path, interpreter, main, binName string,
|
|
||||||
newPyPkgs []string, parSpecs []parSpec) android.Path {
|
|
||||||
|
|
||||||
// .intermediate output path for __init__.py
|
|
||||||
initFile := android.PathForModuleOut(ctx, initFileName).String()
|
|
||||||
|
|
||||||
// .intermediate output path for par file.
|
|
||||||
parFile := android.PathForModuleOut(ctx, binName+parFileExt)
|
|
||||||
|
|
||||||
// .intermediate output path for bin executable.
|
// .intermediate output path for bin executable.
|
||||||
binFile := android.PathForModuleOut(ctx, binName)
|
binFile := android.PathForModuleOut(ctx, binName)
|
||||||
|
|
||||||
// implicit dependency for parFile build action.
|
// implicit dependency for parFile build action.
|
||||||
implicits := android.Paths{}
|
implicits := srcsZips
|
||||||
for _, p := range parSpecs {
|
|
||||||
for _, f := range p.fileListSpecs {
|
|
||||||
implicits = append(implicits, f.fileList)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
parArgs := []string{}
|
if !embeddedLauncher {
|
||||||
parArgs = append(parArgs, `-P "" `+`-C `+strings.TrimSuffix(initFile, initFileName)+` -f `+initFile)
|
|
||||||
for _, pkg := range newPyPkgs {
|
|
||||||
parArgs = append(parArgs, `-P `+pkg+` -f `+initFile)
|
|
||||||
}
|
|
||||||
for _, p := range parSpecs {
|
|
||||||
parArgs = append(parArgs, p.soongParArgs())
|
|
||||||
}
|
|
||||||
|
|
||||||
if !embedded_launcher {
|
|
||||||
// the path of stub_template_host.txt from source tree.
|
// the path of stub_template_host.txt from source tree.
|
||||||
template := android.PathForSource(ctx, stubTemplateHost)
|
template := android.PathForSource(ctx, stubTemplateHost)
|
||||||
|
implicits = append(implicits, template)
|
||||||
|
|
||||||
// intermediate output path for __main__.py
|
// intermediate output path for __main__.py
|
||||||
stub := android.PathForModuleOut(ctx, mainFileName).String()
|
stub := android.PathForModuleOut(ctx, mainFileName).String()
|
||||||
|
|
||||||
// added stub file to the soong_zip args.
|
|
||||||
parArgs = append(parArgs, `-P "" `+`-C `+strings.TrimSuffix(stub, mainFileName)+` -f `+stub)
|
|
||||||
|
|
||||||
ctx.Build(pctx, android.BuildParams{
|
ctx.Build(pctx, android.BuildParams{
|
||||||
Rule: host_par,
|
Rule: hostPar,
|
||||||
Description: "host python archive",
|
Description: "host python archive",
|
||||||
Output: binFile,
|
Output: binFile,
|
||||||
Implicits: implicits,
|
Implicits: implicits,
|
||||||
Args: map[string]string{
|
Args: map[string]string{
|
||||||
"initFile": initFile,
|
"interp": strings.Replace(interpreter, "/", `\/`, -1),
|
||||||
"interp": strings.Replace(interpreter, "/", `\/`, -1),
|
|
||||||
// we need remove "runfiles/" suffix since stub script starts
|
// we need remove "runfiles/" suffix since stub script starts
|
||||||
// searching for main file in each sub-dir of "runfiles" directory tree.
|
// searching for main file in each sub-dir of "runfiles" directory tree.
|
||||||
"main": strings.Replace(strings.TrimPrefix(main, runFiles+"/"),
|
"main": strings.Replace(strings.TrimPrefix(main, runFiles+"/"),
|
||||||
"/", `\/`, -1),
|
"/", `\/`, -1),
|
||||||
"template": template.String(),
|
"template": template.String(),
|
||||||
"stub": stub,
|
"stub": stub,
|
||||||
"parFile": parFile.String(),
|
"mergedZip": mergedZip.String(),
|
||||||
"parArgs": strings.Join(parArgs, " "),
|
"srcsZips": strings.Join(srcsZips.Strings(), " "),
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
// added launcher_path to the implicits Ninja dependencies.
|
// added launcherPath to the implicits Ninja dependencies.
|
||||||
implicits = append(implicits, launcher_path)
|
implicits = append(implicits, launcherPath)
|
||||||
|
|
||||||
// .intermediate output path for entry_point.txt
|
// .intermediate output path for entry_point.txt
|
||||||
entryPoint := android.PathForModuleOut(ctx, entryPointFile).String()
|
entryPoint := android.PathForModuleOut(ctx, entryPointFile).String()
|
||||||
|
|
||||||
// added entry_point file to the soong_zip args.
|
|
||||||
parArgs = append(parArgs, `-P "" `+`-C `+fmt.Sprintf(
|
|
||||||
"%q", strings.TrimSuffix(entryPoint, entryPointFile))+` -f `+entryPoint)
|
|
||||||
|
|
||||||
ctx.Build(pctx, android.BuildParams{
|
ctx.Build(pctx, android.BuildParams{
|
||||||
Rule: embedded_par,
|
Rule: embeddedPar,
|
||||||
Description: "embedded python archive",
|
Description: "embedded python archive",
|
||||||
Output: binFile,
|
Output: binFile,
|
||||||
Implicits: implicits,
|
Implicits: implicits,
|
||||||
Args: map[string]string{
|
Args: map[string]string{
|
||||||
"initFile": initFile,
|
"main": main,
|
||||||
"main": main,
|
"entryPoint": entryPoint,
|
||||||
"entry_point": entryPoint,
|
"mergedZip": mergedZip.String(),
|
||||||
"parFile": parFile.String(),
|
"srcsZips": strings.Join(srcsZips.Strings(), " "),
|
||||||
"parArgs": strings.Join(parArgs, " "),
|
"launcher": launcherPath.String(),
|
||||||
"launcher": launcher_path.String(),
|
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
100
python/python.go
100
python/python.go
@@ -132,18 +132,15 @@ type Module struct {
|
|||||||
// pathMapping: <dest: runfile_path, src: source_path>
|
// pathMapping: <dest: runfile_path, src: source_path>
|
||||||
dataPathMappings []pathMapping
|
dataPathMappings []pathMapping
|
||||||
|
|
||||||
// soong_zip arguments of all its dependencies.
|
// the zip filepath for zipping current module source/data files.
|
||||||
depsParSpecs []parSpec
|
srcsZip android.Path
|
||||||
|
|
||||||
// Python runfiles paths of all its dependencies.
|
// dependency modules' zip filepath for zipping current module source/data files.
|
||||||
depsPyRunfiles []string
|
depsSrcsZips android.Paths
|
||||||
|
|
||||||
// (.intermediate) module output path as installation source.
|
// (.intermediate) module output path as installation source.
|
||||||
installSource android.OptionalPath
|
installSource android.OptionalPath
|
||||||
|
|
||||||
// the soong_zip arguments for zipping current module source/data files.
|
|
||||||
parSpec parSpec
|
|
||||||
|
|
||||||
subAndroidMkOnce map[subAndroidMkProvider]bool
|
subAndroidMkOnce map[subAndroidMkProvider]bool
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -156,9 +153,9 @@ func newModule(hod android.HostOrDeviceSupported, multilib android.Multilib) *Mo
|
|||||||
|
|
||||||
type bootstrapper interface {
|
type bootstrapper interface {
|
||||||
bootstrapperProps() []interface{}
|
bootstrapperProps() []interface{}
|
||||||
bootstrap(ctx android.ModuleContext, Actual_version string, embedded_launcher bool,
|
bootstrap(ctx android.ModuleContext, ActualVersion string, embeddedLauncher bool,
|
||||||
srcsPathMappings []pathMapping, parSpec parSpec,
|
srcsPathMappings []pathMapping, srcsZip android.Path,
|
||||||
depsPyRunfiles []string, depsParSpecs []parSpec) android.OptionalPath
|
depsSrcsZips android.Paths) android.OptionalPath
|
||||||
}
|
}
|
||||||
|
|
||||||
type installer interface {
|
type installer interface {
|
||||||
@@ -168,7 +165,7 @@ type installer interface {
|
|||||||
type PythonDependency interface {
|
type PythonDependency interface {
|
||||||
GetSrcsPathMappings() []pathMapping
|
GetSrcsPathMappings() []pathMapping
|
||||||
GetDataPathMappings() []pathMapping
|
GetDataPathMappings() []pathMapping
|
||||||
GetParSpec() parSpec
|
GetSrcsZip() android.Path
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Module) GetSrcsPathMappings() []pathMapping {
|
func (p *Module) GetSrcsPathMappings() []pathMapping {
|
||||||
@@ -179,8 +176,8 @@ func (p *Module) GetDataPathMappings() []pathMapping {
|
|||||||
return p.dataPathMappings
|
return p.dataPathMappings
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Module) GetParSpec() parSpec {
|
func (p *Module) GetSrcsZip() android.Path {
|
||||||
return p.parSpec
|
return p.srcsZip
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ PythonDependency = (*Module)(nil)
|
var _ PythonDependency = (*Module)(nil)
|
||||||
@@ -339,13 +336,12 @@ func (p *Module) GenerateAndroidBuildActions(ctx android.ModuleContext) {
|
|||||||
if p.bootstrapper != nil {
|
if p.bootstrapper != nil {
|
||||||
// TODO(nanzhang): Since embedded launcher is not supported for Python3 for now,
|
// TODO(nanzhang): Since embedded launcher is not supported for Python3 for now,
|
||||||
// so we initialize "embedded_launcher" to false.
|
// so we initialize "embedded_launcher" to false.
|
||||||
embedded_launcher := false
|
embeddedLauncher := false
|
||||||
if p.properties.Actual_version == pyVersion2 {
|
if p.properties.Actual_version == pyVersion2 {
|
||||||
embedded_launcher = p.isEmbeddedLauncherEnabled(pyVersion2)
|
embeddedLauncher = p.isEmbeddedLauncherEnabled(pyVersion2)
|
||||||
}
|
}
|
||||||
p.installSource = p.bootstrapper.bootstrap(ctx, p.properties.Actual_version,
|
p.installSource = p.bootstrapper.bootstrap(ctx, p.properties.Actual_version,
|
||||||
embedded_launcher, p.srcsPathMappings, p.parSpec, p.depsPyRunfiles,
|
embeddedLauncher, p.srcsPathMappings, p.srcsZip, p.depsSrcsZips)
|
||||||
p.depsParSpecs)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if p.installer != nil && p.installSource.Valid() {
|
if p.installer != nil && p.installSource.Valid() {
|
||||||
@@ -378,11 +374,11 @@ func (p *Module) GeneratePythonBuildActions(ctx android.ModuleContext) {
|
|||||||
expandedData := ctx.ExpandSources(p.properties.Data, nil)
|
expandedData := ctx.ExpandSources(p.properties.Data, nil)
|
||||||
|
|
||||||
// sanitize pkg_path.
|
// sanitize pkg_path.
|
||||||
pkg_path := String(p.properties.Pkg_path)
|
pkgPath := String(p.properties.Pkg_path)
|
||||||
if pkg_path != "" {
|
if pkgPath != "" {
|
||||||
pkg_path = filepath.Clean(String(p.properties.Pkg_path))
|
pkgPath = filepath.Clean(String(p.properties.Pkg_path))
|
||||||
if pkg_path == ".." || strings.HasPrefix(pkg_path, "../") ||
|
if pkgPath == ".." || strings.HasPrefix(pkgPath, "../") ||
|
||||||
strings.HasPrefix(pkg_path, "/") {
|
strings.HasPrefix(pkgPath, "/") {
|
||||||
ctx.PropertyErrorf("pkg_path",
|
ctx.PropertyErrorf("pkg_path",
|
||||||
"%q must be a relative path contained in par file.",
|
"%q must be a relative path contained in par file.",
|
||||||
String(p.properties.Pkg_path))
|
String(p.properties.Pkg_path))
|
||||||
@@ -390,31 +386,31 @@ func (p *Module) GeneratePythonBuildActions(ctx android.ModuleContext) {
|
|||||||
}
|
}
|
||||||
if p.properties.Is_internal != nil && *p.properties.Is_internal {
|
if p.properties.Is_internal != nil && *p.properties.Is_internal {
|
||||||
// pkg_path starts from "internal/" implicitly.
|
// pkg_path starts from "internal/" implicitly.
|
||||||
pkg_path = filepath.Join(internal, pkg_path)
|
pkgPath = filepath.Join(internal, pkgPath)
|
||||||
} else {
|
} else {
|
||||||
// pkg_path starts from "runfiles/" implicitly.
|
// pkg_path starts from "runfiles/" implicitly.
|
||||||
pkg_path = filepath.Join(runFiles, pkg_path)
|
pkgPath = filepath.Join(runFiles, pkgPath)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if p.properties.Is_internal != nil && *p.properties.Is_internal {
|
if p.properties.Is_internal != nil && *p.properties.Is_internal {
|
||||||
// pkg_path starts from "runfiles/" implicitly.
|
// pkg_path starts from "runfiles/" implicitly.
|
||||||
pkg_path = internal
|
pkgPath = internal
|
||||||
} else {
|
} else {
|
||||||
// pkg_path starts from "runfiles/" implicitly.
|
// pkg_path starts from "runfiles/" implicitly.
|
||||||
pkg_path = runFiles
|
pkgPath = runFiles
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
p.genModulePathMappings(ctx, pkg_path, expandedSrcs, expandedData)
|
p.genModulePathMappings(ctx, pkgPath, expandedSrcs, expandedData)
|
||||||
|
|
||||||
p.parSpec = p.dumpFileList(ctx, pkg_path)
|
|
||||||
|
|
||||||
p.uniqWholeRunfilesTree(ctx)
|
p.uniqWholeRunfilesTree(ctx)
|
||||||
|
|
||||||
|
p.srcsZip = p.createSrcsZip(ctx, pkgPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
// generate current module unique pathMappings: <dest: runfiles_path, src: source_path>
|
// generate current module unique pathMappings: <dest: runfiles_path, src: source_path>
|
||||||
// for python/data files.
|
// for python/data files.
|
||||||
func (p *Module) genModulePathMappings(ctx android.ModuleContext, pkg_path string,
|
func (p *Module) genModulePathMappings(ctx android.ModuleContext, pkgPath string,
|
||||||
expandedSrcs, expandedData android.Paths) {
|
expandedSrcs, expandedData android.Paths) {
|
||||||
// fetch <runfiles_path, source_path> pairs from "src" and "data" properties to
|
// fetch <runfiles_path, source_path> pairs from "src" and "data" properties to
|
||||||
// check duplicates.
|
// check duplicates.
|
||||||
@@ -426,7 +422,7 @@ func (p *Module) genModulePathMappings(ctx android.ModuleContext, pkg_path strin
|
|||||||
ctx.PropertyErrorf("srcs", "found non (.py) file: %q!", s.String())
|
ctx.PropertyErrorf("srcs", "found non (.py) file: %q!", s.String())
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
runfilesPath := filepath.Join(pkg_path, s.Rel())
|
runfilesPath := filepath.Join(pkgPath, s.Rel())
|
||||||
identifiers := strings.Split(strings.TrimSuffix(runfilesPath, pyExt), "/")
|
identifiers := strings.Split(strings.TrimSuffix(runfilesPath, pyExt), "/")
|
||||||
for _, token := range identifiers {
|
for _, token := range identifiers {
|
||||||
if !pyIdentifierRegexp.MatchString(token) {
|
if !pyIdentifierRegexp.MatchString(token) {
|
||||||
@@ -445,7 +441,7 @@ func (p *Module) genModulePathMappings(ctx android.ModuleContext, pkg_path strin
|
|||||||
ctx.PropertyErrorf("data", "found (.py) file: %q!", d.String())
|
ctx.PropertyErrorf("data", "found (.py) file: %q!", d.String())
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
runfilesPath := filepath.Join(pkg_path, d.Rel())
|
runfilesPath := filepath.Join(pkgPath, d.Rel())
|
||||||
if fillInMap(ctx, destToPyData, runfilesPath, d.String(), p.Name(), p.Name()) {
|
if fillInMap(ctx, destToPyData, runfilesPath, d.String(), p.Name(), p.Name()) {
|
||||||
p.dataPathMappings = append(p.dataPathMappings,
|
p.dataPathMappings = append(p.dataPathMappings,
|
||||||
pathMapping{dest: runfilesPath, src: d})
|
pathMapping{dest: runfilesPath, src: d})
|
||||||
@@ -454,12 +450,9 @@ func (p *Module) genModulePathMappings(ctx android.ModuleContext, pkg_path strin
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// register build actions to dump filelist to disk.
|
// register build actions to zip current module's sources.
|
||||||
func (p *Module) dumpFileList(ctx android.ModuleContext, pkg_path string) parSpec {
|
func (p *Module) createSrcsZip(ctx android.ModuleContext, pkgPath string) android.Path {
|
||||||
relativeRootMap := make(map[string]android.Paths)
|
relativeRootMap := make(map[string]android.Paths)
|
||||||
// the soong_zip params in order to pack current module's Python/data files.
|
|
||||||
ret := parSpec{rootPrefix: pkg_path}
|
|
||||||
|
|
||||||
pathMappings := append(p.srcsPathMappings, p.dataPathMappings...)
|
pathMappings := append(p.srcsPathMappings, p.dataPathMappings...)
|
||||||
|
|
||||||
// "srcs" or "data" properties may have filegroup so it might happen that
|
// "srcs" or "data" properties may have filegroup so it might happen that
|
||||||
@@ -482,15 +475,29 @@ func (p *Module) dumpFileList(ctx android.ModuleContext, pkg_path string) parSpe
|
|||||||
}
|
}
|
||||||
sort.Strings(keys)
|
sort.Strings(keys)
|
||||||
|
|
||||||
|
parArgs := []string{}
|
||||||
|
parArgs = append(parArgs, `-P `+pkgPath)
|
||||||
|
implicits := android.Paths{}
|
||||||
for _, k := range keys {
|
for _, k := range keys {
|
||||||
// use relative root as filelist name.
|
parArgs = append(parArgs, `-C `+k)
|
||||||
fileListPath := registerBuildActionForModuleFileList(
|
for _, path := range relativeRootMap[k] {
|
||||||
ctx, strings.Replace(k, "/", "_", -1), relativeRootMap[k])
|
parArgs = append(parArgs, `-f `+path.String())
|
||||||
ret.fileListSpecs = append(ret.fileListSpecs,
|
implicits = append(implicits, path)
|
||||||
fileListSpec{fileList: fileListPath, relativeRoot: k})
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret
|
srcsZip := android.PathForModuleOut(ctx, ctx.ModuleName()+".zip")
|
||||||
|
ctx.Build(pctx, android.BuildParams{
|
||||||
|
Rule: zip,
|
||||||
|
Description: "python library archive",
|
||||||
|
Output: srcsZip,
|
||||||
|
Implicits: implicits,
|
||||||
|
Args: map[string]string{
|
||||||
|
"args": strings.Join(parArgs, " "),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
return srcsZip
|
||||||
}
|
}
|
||||||
|
|
||||||
func isPythonLibModule(module blueprint.Module) bool {
|
func isPythonLibModule(module blueprint.Module) bool {
|
||||||
@@ -537,9 +544,6 @@ func (p *Module) uniqWholeRunfilesTree(ctx android.ModuleContext) {
|
|||||||
ctx.OtherModuleName(module)) {
|
ctx.OtherModuleName(module)) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
// binary needs the Python runfiles paths from all its
|
|
||||||
// dependencies to fill __init__.py in each runfiles dir.
|
|
||||||
p.depsPyRunfiles = append(p.depsPyRunfiles, path.dest)
|
|
||||||
}
|
}
|
||||||
data := dep.GetDataPathMappings()
|
data := dep.GetDataPathMappings()
|
||||||
for _, path := range data {
|
for _, path := range data {
|
||||||
@@ -547,9 +551,7 @@ func (p *Module) uniqWholeRunfilesTree(ctx android.ModuleContext) {
|
|||||||
path.dest, path.src.String(), ctx.ModuleName(),
|
path.dest, path.src.String(), ctx.ModuleName(),
|
||||||
ctx.OtherModuleName(module))
|
ctx.OtherModuleName(module))
|
||||||
}
|
}
|
||||||
// binary needs the soong_zip arguments from all its
|
p.depsSrcsZips = append(p.depsSrcsZips, dep.GetSrcsZip())
|
||||||
// dependencies to generate executable par file.
|
|
||||||
p.depsParSpecs = append(p.depsParSpecs, dep.GetParSpec())
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@@ -29,12 +29,11 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type pyModule struct {
|
type pyModule struct {
|
||||||
name string
|
name string
|
||||||
actualVersion string
|
actualVersion string
|
||||||
pyRunfiles []string
|
pyRunfiles []string
|
||||||
depsPyRunfiles []string
|
srcsZip string
|
||||||
parSpec string
|
depsSrcsZips []string
|
||||||
depsParSpecs []string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -313,14 +312,10 @@ var (
|
|||||||
"runfiles/e/default_py3.py",
|
"runfiles/e/default_py3.py",
|
||||||
"runfiles/e/file4.py",
|
"runfiles/e/file4.py",
|
||||||
},
|
},
|
||||||
depsPyRunfiles: []string{
|
srcsZip: "@prefix@/.intermediates/dir/bin/PY3/bin.zip",
|
||||||
"runfiles/a/b/file1.py",
|
depsSrcsZips: []string{
|
||||||
"runfiles/c/d/file2.py",
|
"@prefix@/.intermediates/dir/lib5/PY3/lib5.zip",
|
||||||
},
|
"@prefix@/.intermediates/dir/lib6/PY3/lib6.zip",
|
||||||
parSpec: "-P runfiles/e -C dir/ -l @prefix@/.intermediates/dir/bin/PY3/dir_.list",
|
|
||||||
depsParSpecs: []string{
|
|
||||||
"-P runfiles/a/b -C dir/ -l @prefix@/.intermediates/dir/lib5/PY3/dir_.list",
|
|
||||||
"-P runfiles/c/d -C dir/ -l @prefix@/.intermediates/dir/lib6/PY3/dir_.list",
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -356,8 +351,9 @@ func TestPythonModule(t *testing.T) {
|
|||||||
testErrs = append(testErrs,
|
testErrs = append(testErrs,
|
||||||
expectModule(t, ctx, buildDir, e.name,
|
expectModule(t, ctx, buildDir, e.name,
|
||||||
e.actualVersion,
|
e.actualVersion,
|
||||||
e.pyRunfiles, e.depsPyRunfiles,
|
e.srcsZip,
|
||||||
e.parSpec, e.depsParSpecs)...)
|
e.pyRunfiles,
|
||||||
|
e.depsSrcsZips)...)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fail(t, testErrs)
|
fail(t, testErrs)
|
||||||
@@ -388,9 +384,8 @@ func expectErrors(t *testing.T, actErrs []error, expErrs []string) (testErrs []e
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func expectModule(t *testing.T, ctx *android.TestContext, buildDir, name, variant string,
|
func expectModule(t *testing.T, ctx *android.TestContext, buildDir, name, variant, expectedSrcsZip string,
|
||||||
expPyRunfiles, expDepsPyRunfiles []string,
|
expectedPyRunfiles, expectedDepsSrcsZips []string) (testErrs []error) {
|
||||||
expParSpec string, expDepsParSpecs []string) (testErrs []error) {
|
|
||||||
module := ctx.ModuleForTests(name, variant)
|
module := ctx.ModuleForTests(name, variant)
|
||||||
|
|
||||||
base, baseOk := module.Module().(*Module)
|
base, baseOk := module.Module().(*Module)
|
||||||
@@ -398,47 +393,36 @@ func expectModule(t *testing.T, ctx *android.TestContext, buildDir, name, varian
|
|||||||
t.Fatalf("%s is not Python module!", name)
|
t.Fatalf("%s is not Python module!", name)
|
||||||
}
|
}
|
||||||
|
|
||||||
actPyRunfiles := []string{}
|
actualPyRunfiles := []string{}
|
||||||
for _, path := range base.srcsPathMappings {
|
for _, path := range base.srcsPathMappings {
|
||||||
actPyRunfiles = append(actPyRunfiles, path.dest)
|
actualPyRunfiles = append(actualPyRunfiles, path.dest)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !reflect.DeepEqual(actPyRunfiles, expPyRunfiles) {
|
if !reflect.DeepEqual(actualPyRunfiles, expectedPyRunfiles) {
|
||||||
testErrs = append(testErrs, errors.New(fmt.Sprintf(
|
testErrs = append(testErrs, errors.New(fmt.Sprintf(
|
||||||
`binary "%s" variant "%s" has unexpected pyRunfiles: %q!`,
|
`binary "%s" variant "%s" has unexpected pyRunfiles: %q!`,
|
||||||
base.Name(),
|
base.Name(),
|
||||||
base.properties.Actual_version,
|
base.properties.Actual_version,
|
||||||
actPyRunfiles)))
|
actualPyRunfiles)))
|
||||||
}
|
}
|
||||||
|
|
||||||
if !reflect.DeepEqual(base.depsPyRunfiles, expDepsPyRunfiles) {
|
if base.srcsZip.String() != strings.Replace(expectedSrcsZip, "@prefix@", buildDir, 1) {
|
||||||
testErrs = append(testErrs, errors.New(fmt.Sprintf(
|
testErrs = append(testErrs, errors.New(fmt.Sprintf(
|
||||||
`binary "%s" variant "%s" has unexpected depsPyRunfiles: %q!`,
|
`binary "%s" variant "%s" has unexpected srcsZip: %q!`,
|
||||||
base.Name(),
|
base.Name(),
|
||||||
base.properties.Actual_version,
|
base.properties.Actual_version,
|
||||||
base.depsPyRunfiles)))
|
base.srcsZip)))
|
||||||
}
|
}
|
||||||
|
|
||||||
if base.parSpec.soongParArgs() != strings.Replace(expParSpec, "@prefix@", buildDir, 1) {
|
for i, _ := range expectedDepsSrcsZips {
|
||||||
|
expectedDepsSrcsZips[i] = strings.Replace(expectedDepsSrcsZips[i], "@prefix@", buildDir, 1)
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(base.depsSrcsZips.Strings(), expectedDepsSrcsZips) {
|
||||||
testErrs = append(testErrs, errors.New(fmt.Sprintf(
|
testErrs = append(testErrs, errors.New(fmt.Sprintf(
|
||||||
`binary "%s" variant "%s" has unexpected parSpec: %q!`,
|
`binary "%s" variant "%s" has unexpected depsSrcsZips: %q!`,
|
||||||
base.Name(),
|
base.Name(),
|
||||||
base.properties.Actual_version,
|
base.properties.Actual_version,
|
||||||
base.parSpec.soongParArgs())))
|
base.depsSrcsZips)))
|
||||||
}
|
|
||||||
|
|
||||||
actDepsParSpecs := []string{}
|
|
||||||
for i, p := range base.depsParSpecs {
|
|
||||||
actDepsParSpecs = append(actDepsParSpecs, p.soongParArgs())
|
|
||||||
expDepsParSpecs[i] = strings.Replace(expDepsParSpecs[i], "@prefix@", buildDir, 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
if !reflect.DeepEqual(actDepsParSpecs, expDepsParSpecs) {
|
|
||||||
testErrs = append(testErrs, errors.New(fmt.Sprintf(
|
|
||||||
`binary "%s" variant "%s" has unexpected depsParSpecs: %q!`,
|
|
||||||
base.Name(),
|
|
||||||
base.properties.Actual_version,
|
|
||||||
actDepsParSpecs)))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
|
Reference in New Issue
Block a user