Loading cmd/merge_zips/merge_zips.go +24 −3 Original line number Diff line number Diff line Loading @@ -63,6 +63,7 @@ var ( zipsToNotStrip = make(zipsToNotStripSet) stripDirEntries = flag.Bool("D", false, "strip directory entries from the output zip file") manifest = flag.String("m", "", "manifest file to insert in jar") pyMain = flag.String("pm", "", "__main__.py 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") ) Loading @@ -75,7 +76,7 @@ func init() { func main() { 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() } Loading Loading @@ -125,8 +126,12 @@ func main() { 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 err = mergeZips(readers, writer, *manifest, *entrypoint, *sortEntries, *emulateJar, *emulatePar, err = mergeZips(readers, writer, *manifest, *entrypoint, *pyMain, *sortEntries, *emulateJar, *emulatePar, *stripDirEntries, *ignoreDuplicates) if err != nil { log.Fatal(err) Loading Loading @@ -218,7 +223,7 @@ type fileMapping struct { 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 { sourceByDest := make(map[string]zipSource, 0) Loading Loading @@ -268,6 +273,22 @@ func mergeZips(readers []namedZipReader, writer *zip.Writer, manifest, entrypoin 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 { // the runfiles packages needs to be populated with "__init__.py". newPyPkgs := []string{} Loading python/binary.go +14 −88 Original line number Diff line number Diff line Loading @@ -18,8 +18,6 @@ package python import ( "fmt" "path/filepath" "strings" "android/soong/android" ) Loading Loading @@ -80,89 +78,44 @@ func (binary *binaryDecorator) bootstrapperProps() []interface{} { return []interface{}{&binary.binaryProperties} } func (binary *binaryDecorator) bootstrap(ctx android.ModuleContext, actual_version string, embedded_launcher bool, srcsPathMappings []pathMapping, parSpec parSpec, depsPyRunfiles []string, depsParSpecs []parSpec) 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) } func (binary *binaryDecorator) bootstrap(ctx android.ModuleContext, actualVersion string, embeddedLauncher bool, srcsPathMappings []pathMapping, srcsZip android.Path, depsSrcsZips android.Paths) android.OptionalPath { main := binary.getPyMainFile(ctx, srcsPathMappings) if main == "" { return android.OptionalPath{} } var launcher_path android.Path if embedded_launcher { var launcherPath android.Path if embeddedLauncher { ctx.VisitDirectDepsWithTag(launcherTag, func(m android.Module) { if provider, ok := m.(IntermPathProvider); ok { if launcher_path != nil { if launcherPath != nil { 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, binary.getHostInterpreterName(ctx, actual_version), main, binary.getStem(ctx), newPyPkgs, append(depsParSpecs, parSpec)) binFile := registerBuildActionForParFile(ctx, embeddedLauncher, launcherPath, binary.getHostInterpreterName(ctx, actualVersion), main, binary.getStem(ctx), append(android.Paths{srcsZip}, depsSrcsZips...)) return android.OptionalPathForPath(binFile) } // get host interpreter name. func (binary *binaryDecorator) getHostInterpreterName(ctx android.ModuleContext, actual_version string) string { actualVersion string) string { var interp string switch actual_version { switch actualVersion { case pyVersion2: interp = "python2.7" case pyVersion3: interp = "python3" default: panic(fmt.Errorf("unknown Python actualVersion: %q for module: %q.", actual_version, ctx.ModuleName())) actualVersion, ctx.ModuleName())) } return interp Loading Loading @@ -196,30 +149,3 @@ func (binary *binaryDecorator) getStem(ctx android.ModuleContext) string { 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 "" } python/builder.go +42 −105 Original line number Diff line number Diff line Loading @@ -17,7 +17,6 @@ package python // This file contains Ninja build actions for building Python program. import ( "fmt" "strings" "android/soong/android" Loading @@ -29,25 +28,30 @@ import ( var ( pctx = android.NewPackageContext("android/soong/python") host_par = pctx.AndroidStaticRule("host_par", zip = pctx.AndroidStaticRule("zip", blueprint.RuleParams{ Command: `touch $initFile && ` + `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"}, Command: `$parCmd -o $out $args`, CommandDeps: []string{"$parCmd"}, }, "initFile", "interp", "main", "template", "stub", "parCmd", "parFile", "parArgs") "args") embedded_par = pctx.AndroidStaticRule("embedded_par", hostPar = pctx.AndroidStaticRule("hostPar", 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"}, 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"}, }, "initFile", "main", "entry_point", "parCmd", "parFile", "parArgs", "launcher") "main", "entryPoint", "mergedZip", "srcsZips", "launcher") ) func init() { Loading @@ -55,98 +59,36 @@ func init() { pctx.Import("android/soong/common") pctx.HostBinToolVariable("parCmd", "soong_zip") pctx.HostBinToolVariable("mergeParCmd", "merge_zips") } type fileListSpec struct { fileList android.Path relativeRoot string } type parSpec struct { rootPrefix string fileListSpecs []fileListSpec } func registerBuildActionForParFile(ctx android.ModuleContext, embeddedLauncher bool, launcherPath android.Path, interpreter, main, binName string, srcsZips android.Paths) android.Path { 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 merged zip file. mergedZip := android.PathForModuleOut(ctx, binName+".mergedzip") // .intermediate output path for bin executable. binFile := android.PathForModuleOut(ctx, binName) // implicit dependency for parFile build action. implicits := android.Paths{} for _, p := range parSpecs { for _, f := range p.fileListSpecs { implicits = append(implicits, f.fileList) } } parArgs := []string{} 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()) } implicits := srcsZips if !embedded_launcher { if !embeddedLauncher { // the path of stub_template_host.txt from source tree. template := android.PathForSource(ctx, stubTemplateHost) implicits = append(implicits, template) // intermediate output path for __main__.py 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{ Rule: host_par, Rule: hostPar, Description: "host python archive", Output: binFile, Implicits: implicits, Args: map[string]string{ "initFile": initFile, "interp": strings.Replace(interpreter, "/", `\/`, -1), // we need remove "runfiles/" suffix since stub script starts // searching for main file in each sub-dir of "runfiles" directory tree. Loading @@ -154,33 +96,28 @@ func registerBuildActionForParFile(ctx android.ModuleContext, embedded_launcher "/", `\/`, -1), "template": template.String(), "stub": stub, "parFile": parFile.String(), "parArgs": strings.Join(parArgs, " "), "mergedZip": mergedZip.String(), "srcsZips": strings.Join(srcsZips.Strings(), " "), }, }) } else { // added launcher_path to the implicits Ninja dependencies. implicits = append(implicits, launcher_path) // added launcherPath to the implicits Ninja dependencies. implicits = append(implicits, launcherPath) // .intermediate output path for entry_point.txt 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{ Rule: embedded_par, Rule: embeddedPar, Description: "embedded python archive", Output: binFile, Implicits: implicits, Args: map[string]string{ "initFile": initFile, "main": main, "entry_point": entryPoint, "parFile": parFile.String(), "parArgs": strings.Join(parArgs, " "), "launcher": launcher_path.String(), "entryPoint": entryPoint, "mergedZip": mergedZip.String(), "srcsZips": strings.Join(srcsZips.Strings(), " "), "launcher": launcherPath.String(), }, }) } Loading python/python.go +51 −49 Original line number Diff line number Diff line Loading @@ -132,18 +132,15 @@ type Module struct { // pathMapping: <dest: runfile_path, src: source_path> dataPathMappings []pathMapping // soong_zip arguments of all its dependencies. depsParSpecs []parSpec // the zip filepath for zipping current module source/data files. srcsZip android.Path // Python runfiles paths of all its dependencies. depsPyRunfiles []string // dependency modules' zip filepath for zipping current module source/data files. depsSrcsZips android.Paths // (.intermediate) module output path as installation source. installSource android.OptionalPath // the soong_zip arguments for zipping current module source/data files. parSpec parSpec subAndroidMkOnce map[subAndroidMkProvider]bool } Loading @@ -156,9 +153,9 @@ func newModule(hod android.HostOrDeviceSupported, multilib android.Multilib) *Mo type bootstrapper interface { bootstrapperProps() []interface{} bootstrap(ctx android.ModuleContext, Actual_version string, embedded_launcher bool, srcsPathMappings []pathMapping, parSpec parSpec, depsPyRunfiles []string, depsParSpecs []parSpec) android.OptionalPath bootstrap(ctx android.ModuleContext, ActualVersion string, embeddedLauncher bool, srcsPathMappings []pathMapping, srcsZip android.Path, depsSrcsZips android.Paths) android.OptionalPath } type installer interface { Loading @@ -168,7 +165,7 @@ type installer interface { type PythonDependency interface { GetSrcsPathMappings() []pathMapping GetDataPathMappings() []pathMapping GetParSpec() parSpec GetSrcsZip() android.Path } func (p *Module) GetSrcsPathMappings() []pathMapping { Loading @@ -179,8 +176,8 @@ func (p *Module) GetDataPathMappings() []pathMapping { return p.dataPathMappings } func (p *Module) GetParSpec() parSpec { return p.parSpec func (p *Module) GetSrcsZip() android.Path { return p.srcsZip } var _ PythonDependency = (*Module)(nil) Loading Loading @@ -339,13 +336,12 @@ func (p *Module) GenerateAndroidBuildActions(ctx android.ModuleContext) { if p.bootstrapper != nil { // TODO(nanzhang): Since embedded launcher is not supported for Python3 for now, // so we initialize "embedded_launcher" to false. embedded_launcher := false embeddedLauncher := false 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, embedded_launcher, p.srcsPathMappings, p.parSpec, p.depsPyRunfiles, p.depsParSpecs) embeddedLauncher, p.srcsPathMappings, p.srcsZip, p.depsSrcsZips) } if p.installer != nil && p.installSource.Valid() { Loading Loading @@ -378,11 +374,11 @@ func (p *Module) GeneratePythonBuildActions(ctx android.ModuleContext) { expandedData := ctx.ExpandSources(p.properties.Data, nil) // sanitize pkg_path. pkg_path := String(p.properties.Pkg_path) if pkg_path != "" { pkg_path = filepath.Clean(String(p.properties.Pkg_path)) if pkg_path == ".." || strings.HasPrefix(pkg_path, "../") || strings.HasPrefix(pkg_path, "/") { pkgPath := String(p.properties.Pkg_path) if pkgPath != "" { pkgPath = filepath.Clean(String(p.properties.Pkg_path)) if pkgPath == ".." || strings.HasPrefix(pkgPath, "../") || strings.HasPrefix(pkgPath, "/") { ctx.PropertyErrorf("pkg_path", "%q must be a relative path contained in par file.", String(p.properties.Pkg_path)) Loading @@ -390,31 +386,31 @@ func (p *Module) GeneratePythonBuildActions(ctx android.ModuleContext) { } if p.properties.Is_internal != nil && *p.properties.Is_internal { // pkg_path starts from "internal/" implicitly. pkg_path = filepath.Join(internal, pkg_path) pkgPath = filepath.Join(internal, pkgPath) } else { // pkg_path starts from "runfiles/" implicitly. pkg_path = filepath.Join(runFiles, pkg_path) pkgPath = filepath.Join(runFiles, pkgPath) } } else { if p.properties.Is_internal != nil && *p.properties.Is_internal { // pkg_path starts from "runfiles/" implicitly. pkg_path = internal pkgPath = internal } else { // pkg_path starts from "runfiles/" implicitly. pkg_path = runFiles pkgPath = runFiles } } p.genModulePathMappings(ctx, pkg_path, expandedSrcs, expandedData) p.parSpec = p.dumpFileList(ctx, pkg_path) p.genModulePathMappings(ctx, pkgPath, expandedSrcs, expandedData) p.uniqWholeRunfilesTree(ctx) p.srcsZip = p.createSrcsZip(ctx, pkgPath) } // generate current module unique pathMappings: <dest: runfiles_path, src: source_path> // 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) { // fetch <runfiles_path, source_path> pairs from "src" and "data" properties to // check duplicates. Loading @@ -426,7 +422,7 @@ func (p *Module) genModulePathMappings(ctx android.ModuleContext, pkg_path strin ctx.PropertyErrorf("srcs", "found non (.py) file: %q!", s.String()) continue } runfilesPath := filepath.Join(pkg_path, s.Rel()) runfilesPath := filepath.Join(pkgPath, s.Rel()) identifiers := strings.Split(strings.TrimSuffix(runfilesPath, pyExt), "/") for _, token := range identifiers { if !pyIdentifierRegexp.MatchString(token) { Loading @@ -445,7 +441,7 @@ func (p *Module) genModulePathMappings(ctx android.ModuleContext, pkg_path strin ctx.PropertyErrorf("data", "found (.py) file: %q!", d.String()) 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()) { p.dataPathMappings = append(p.dataPathMappings, pathMapping{dest: runfilesPath, src: d}) Loading @@ -454,12 +450,9 @@ func (p *Module) genModulePathMappings(ctx android.ModuleContext, pkg_path strin } // register build actions to dump filelist to disk. func (p *Module) dumpFileList(ctx android.ModuleContext, pkg_path string) parSpec { // register build actions to zip current module's sources. func (p *Module) createSrcsZip(ctx android.ModuleContext, pkgPath string) android.Path { 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...) // "srcs" or "data" properties may have filegroup so it might happen that Loading @@ -482,15 +475,29 @@ func (p *Module) dumpFileList(ctx android.ModuleContext, pkg_path string) parSpe } sort.Strings(keys) parArgs := []string{} parArgs = append(parArgs, `-P `+pkgPath) implicits := android.Paths{} for _, k := range keys { // use relative root as filelist name. fileListPath := registerBuildActionForModuleFileList( ctx, strings.Replace(k, "/", "_", -1), relativeRootMap[k]) ret.fileListSpecs = append(ret.fileListSpecs, fileListSpec{fileList: fileListPath, relativeRoot: k}) } parArgs = append(parArgs, `-C `+k) for _, path := range relativeRootMap[k] { parArgs = append(parArgs, `-f `+path.String()) implicits = append(implicits, path) } } 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 ret return srcsZip } func isPythonLibModule(module blueprint.Module) bool { Loading Loading @@ -537,9 +544,6 @@ func (p *Module) uniqWholeRunfilesTree(ctx android.ModuleContext) { ctx.OtherModuleName(module)) { 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() for _, path := range data { Loading @@ -547,9 +551,7 @@ func (p *Module) uniqWholeRunfilesTree(ctx android.ModuleContext) { path.dest, path.src.String(), ctx.ModuleName(), ctx.OtherModuleName(module)) } // binary needs the soong_zip arguments from all its // dependencies to generate executable par file. p.depsParSpecs = append(p.depsParSpecs, dep.GetParSpec()) p.depsSrcsZips = append(p.depsSrcsZips, dep.GetSrcsZip()) } }) } Loading python/python_test.go +26 −42 Original line number Diff line number Diff line Loading @@ -32,9 +32,8 @@ type pyModule struct { name string actualVersion string pyRunfiles []string depsPyRunfiles []string parSpec string depsParSpecs []string srcsZip string depsSrcsZips []string } var ( Loading Loading @@ -313,14 +312,10 @@ var ( "runfiles/e/default_py3.py", "runfiles/e/file4.py", }, depsPyRunfiles: []string{ "runfiles/a/b/file1.py", "runfiles/c/d/file2.py", }, 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", srcsZip: "@prefix@/.intermediates/dir/bin/PY3/bin.zip", depsSrcsZips: []string{ "@prefix@/.intermediates/dir/lib5/PY3/lib5.zip", "@prefix@/.intermediates/dir/lib6/PY3/lib6.zip", }, }, }, Loading Loading @@ -356,8 +351,9 @@ func TestPythonModule(t *testing.T) { testErrs = append(testErrs, expectModule(t, ctx, buildDir, e.name, e.actualVersion, e.pyRunfiles, e.depsPyRunfiles, e.parSpec, e.depsParSpecs)...) e.srcsZip, e.pyRunfiles, e.depsSrcsZips)...) } } fail(t, testErrs) Loading Loading @@ -388,9 +384,8 @@ func expectErrors(t *testing.T, actErrs []error, expErrs []string) (testErrs []e return } func expectModule(t *testing.T, ctx *android.TestContext, buildDir, name, variant string, expPyRunfiles, expDepsPyRunfiles []string, expParSpec string, expDepsParSpecs []string) (testErrs []error) { func expectModule(t *testing.T, ctx *android.TestContext, buildDir, name, variant, expectedSrcsZip string, expectedPyRunfiles, expectedDepsSrcsZips []string) (testErrs []error) { module := ctx.ModuleForTests(name, variant) base, baseOk := module.Module().(*Module) Loading @@ -398,47 +393,36 @@ func expectModule(t *testing.T, ctx *android.TestContext, buildDir, name, varian t.Fatalf("%s is not Python module!", name) } actPyRunfiles := []string{} actualPyRunfiles := []string{} 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( `binary "%s" variant "%s" has unexpected pyRunfiles: %q!`, base.Name(), 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( `binary "%s" variant "%s" has unexpected depsPyRunfiles: %q!`, `binary "%s" variant "%s" has unexpected srcsZip: %q!`, base.Name(), base.properties.Actual_version, base.depsPyRunfiles))) base.srcsZip))) } if base.parSpec.soongParArgs() != strings.Replace(expParSpec, "@prefix@", buildDir, 1) { testErrs = append(testErrs, errors.New(fmt.Sprintf( `binary "%s" variant "%s" has unexpected parSpec: %q!`, base.Name(), base.properties.Actual_version, base.parSpec.soongParArgs()))) for i, _ := range expectedDepsSrcsZips { expectedDepsSrcsZips[i] = strings.Replace(expectedDepsSrcsZips[i], "@prefix@", buildDir, 1) } 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) { if !reflect.DeepEqual(base.depsSrcsZips.Strings(), expectedDepsSrcsZips) { testErrs = append(testErrs, errors.New(fmt.Sprintf( `binary "%s" variant "%s" has unexpected depsParSpecs: %q!`, `binary "%s" variant "%s" has unexpected depsSrcsZips: %q!`, base.Name(), base.properties.Actual_version, actDepsParSpecs))) base.depsSrcsZips))) } return Loading Loading
cmd/merge_zips/merge_zips.go +24 −3 Original line number Diff line number Diff line Loading @@ -63,6 +63,7 @@ var ( zipsToNotStrip = make(zipsToNotStripSet) stripDirEntries = flag.Bool("D", false, "strip directory entries from the output zip file") manifest = flag.String("m", "", "manifest file to insert in jar") pyMain = flag.String("pm", "", "__main__.py 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") ) Loading @@ -75,7 +76,7 @@ func init() { func main() { 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() } Loading Loading @@ -125,8 +126,12 @@ func main() { 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 err = mergeZips(readers, writer, *manifest, *entrypoint, *sortEntries, *emulateJar, *emulatePar, err = mergeZips(readers, writer, *manifest, *entrypoint, *pyMain, *sortEntries, *emulateJar, *emulatePar, *stripDirEntries, *ignoreDuplicates) if err != nil { log.Fatal(err) Loading Loading @@ -218,7 +223,7 @@ type fileMapping struct { 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 { sourceByDest := make(map[string]zipSource, 0) Loading Loading @@ -268,6 +273,22 @@ func mergeZips(readers []namedZipReader, writer *zip.Writer, manifest, entrypoin 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 { // the runfiles packages needs to be populated with "__init__.py". newPyPkgs := []string{} Loading
python/binary.go +14 −88 Original line number Diff line number Diff line Loading @@ -18,8 +18,6 @@ package python import ( "fmt" "path/filepath" "strings" "android/soong/android" ) Loading Loading @@ -80,89 +78,44 @@ func (binary *binaryDecorator) bootstrapperProps() []interface{} { return []interface{}{&binary.binaryProperties} } func (binary *binaryDecorator) bootstrap(ctx android.ModuleContext, actual_version string, embedded_launcher bool, srcsPathMappings []pathMapping, parSpec parSpec, depsPyRunfiles []string, depsParSpecs []parSpec) 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) } func (binary *binaryDecorator) bootstrap(ctx android.ModuleContext, actualVersion string, embeddedLauncher bool, srcsPathMappings []pathMapping, srcsZip android.Path, depsSrcsZips android.Paths) android.OptionalPath { main := binary.getPyMainFile(ctx, srcsPathMappings) if main == "" { return android.OptionalPath{} } var launcher_path android.Path if embedded_launcher { var launcherPath android.Path if embeddedLauncher { ctx.VisitDirectDepsWithTag(launcherTag, func(m android.Module) { if provider, ok := m.(IntermPathProvider); ok { if launcher_path != nil { if launcherPath != nil { 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, binary.getHostInterpreterName(ctx, actual_version), main, binary.getStem(ctx), newPyPkgs, append(depsParSpecs, parSpec)) binFile := registerBuildActionForParFile(ctx, embeddedLauncher, launcherPath, binary.getHostInterpreterName(ctx, actualVersion), main, binary.getStem(ctx), append(android.Paths{srcsZip}, depsSrcsZips...)) return android.OptionalPathForPath(binFile) } // get host interpreter name. func (binary *binaryDecorator) getHostInterpreterName(ctx android.ModuleContext, actual_version string) string { actualVersion string) string { var interp string switch actual_version { switch actualVersion { case pyVersion2: interp = "python2.7" case pyVersion3: interp = "python3" default: panic(fmt.Errorf("unknown Python actualVersion: %q for module: %q.", actual_version, ctx.ModuleName())) actualVersion, ctx.ModuleName())) } return interp Loading Loading @@ -196,30 +149,3 @@ func (binary *binaryDecorator) getStem(ctx android.ModuleContext) string { 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 "" }
python/builder.go +42 −105 Original line number Diff line number Diff line Loading @@ -17,7 +17,6 @@ package python // This file contains Ninja build actions for building Python program. import ( "fmt" "strings" "android/soong/android" Loading @@ -29,25 +28,30 @@ import ( var ( pctx = android.NewPackageContext("android/soong/python") host_par = pctx.AndroidStaticRule("host_par", zip = pctx.AndroidStaticRule("zip", blueprint.RuleParams{ Command: `touch $initFile && ` + `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"}, Command: `$parCmd -o $out $args`, CommandDeps: []string{"$parCmd"}, }, "initFile", "interp", "main", "template", "stub", "parCmd", "parFile", "parArgs") "args") embedded_par = pctx.AndroidStaticRule("embedded_par", hostPar = pctx.AndroidStaticRule("hostPar", 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"}, 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"}, }, "initFile", "main", "entry_point", "parCmd", "parFile", "parArgs", "launcher") "main", "entryPoint", "mergedZip", "srcsZips", "launcher") ) func init() { Loading @@ -55,98 +59,36 @@ func init() { pctx.Import("android/soong/common") pctx.HostBinToolVariable("parCmd", "soong_zip") pctx.HostBinToolVariable("mergeParCmd", "merge_zips") } type fileListSpec struct { fileList android.Path relativeRoot string } type parSpec struct { rootPrefix string fileListSpecs []fileListSpec } func registerBuildActionForParFile(ctx android.ModuleContext, embeddedLauncher bool, launcherPath android.Path, interpreter, main, binName string, srcsZips android.Paths) android.Path { 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 merged zip file. mergedZip := android.PathForModuleOut(ctx, binName+".mergedzip") // .intermediate output path for bin executable. binFile := android.PathForModuleOut(ctx, binName) // implicit dependency for parFile build action. implicits := android.Paths{} for _, p := range parSpecs { for _, f := range p.fileListSpecs { implicits = append(implicits, f.fileList) } } parArgs := []string{} 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()) } implicits := srcsZips if !embedded_launcher { if !embeddedLauncher { // the path of stub_template_host.txt from source tree. template := android.PathForSource(ctx, stubTemplateHost) implicits = append(implicits, template) // intermediate output path for __main__.py 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{ Rule: host_par, Rule: hostPar, Description: "host python archive", Output: binFile, Implicits: implicits, Args: map[string]string{ "initFile": initFile, "interp": strings.Replace(interpreter, "/", `\/`, -1), // we need remove "runfiles/" suffix since stub script starts // searching for main file in each sub-dir of "runfiles" directory tree. Loading @@ -154,33 +96,28 @@ func registerBuildActionForParFile(ctx android.ModuleContext, embedded_launcher "/", `\/`, -1), "template": template.String(), "stub": stub, "parFile": parFile.String(), "parArgs": strings.Join(parArgs, " "), "mergedZip": mergedZip.String(), "srcsZips": strings.Join(srcsZips.Strings(), " "), }, }) } else { // added launcher_path to the implicits Ninja dependencies. implicits = append(implicits, launcher_path) // added launcherPath to the implicits Ninja dependencies. implicits = append(implicits, launcherPath) // .intermediate output path for entry_point.txt 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{ Rule: embedded_par, Rule: embeddedPar, Description: "embedded python archive", Output: binFile, Implicits: implicits, Args: map[string]string{ "initFile": initFile, "main": main, "entry_point": entryPoint, "parFile": parFile.String(), "parArgs": strings.Join(parArgs, " "), "launcher": launcher_path.String(), "entryPoint": entryPoint, "mergedZip": mergedZip.String(), "srcsZips": strings.Join(srcsZips.Strings(), " "), "launcher": launcherPath.String(), }, }) } Loading
python/python.go +51 −49 Original line number Diff line number Diff line Loading @@ -132,18 +132,15 @@ type Module struct { // pathMapping: <dest: runfile_path, src: source_path> dataPathMappings []pathMapping // soong_zip arguments of all its dependencies. depsParSpecs []parSpec // the zip filepath for zipping current module source/data files. srcsZip android.Path // Python runfiles paths of all its dependencies. depsPyRunfiles []string // dependency modules' zip filepath for zipping current module source/data files. depsSrcsZips android.Paths // (.intermediate) module output path as installation source. installSource android.OptionalPath // the soong_zip arguments for zipping current module source/data files. parSpec parSpec subAndroidMkOnce map[subAndroidMkProvider]bool } Loading @@ -156,9 +153,9 @@ func newModule(hod android.HostOrDeviceSupported, multilib android.Multilib) *Mo type bootstrapper interface { bootstrapperProps() []interface{} bootstrap(ctx android.ModuleContext, Actual_version string, embedded_launcher bool, srcsPathMappings []pathMapping, parSpec parSpec, depsPyRunfiles []string, depsParSpecs []parSpec) android.OptionalPath bootstrap(ctx android.ModuleContext, ActualVersion string, embeddedLauncher bool, srcsPathMappings []pathMapping, srcsZip android.Path, depsSrcsZips android.Paths) android.OptionalPath } type installer interface { Loading @@ -168,7 +165,7 @@ type installer interface { type PythonDependency interface { GetSrcsPathMappings() []pathMapping GetDataPathMappings() []pathMapping GetParSpec() parSpec GetSrcsZip() android.Path } func (p *Module) GetSrcsPathMappings() []pathMapping { Loading @@ -179,8 +176,8 @@ func (p *Module) GetDataPathMappings() []pathMapping { return p.dataPathMappings } func (p *Module) GetParSpec() parSpec { return p.parSpec func (p *Module) GetSrcsZip() android.Path { return p.srcsZip } var _ PythonDependency = (*Module)(nil) Loading Loading @@ -339,13 +336,12 @@ func (p *Module) GenerateAndroidBuildActions(ctx android.ModuleContext) { if p.bootstrapper != nil { // TODO(nanzhang): Since embedded launcher is not supported for Python3 for now, // so we initialize "embedded_launcher" to false. embedded_launcher := false embeddedLauncher := false 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, embedded_launcher, p.srcsPathMappings, p.parSpec, p.depsPyRunfiles, p.depsParSpecs) embeddedLauncher, p.srcsPathMappings, p.srcsZip, p.depsSrcsZips) } if p.installer != nil && p.installSource.Valid() { Loading Loading @@ -378,11 +374,11 @@ func (p *Module) GeneratePythonBuildActions(ctx android.ModuleContext) { expandedData := ctx.ExpandSources(p.properties.Data, nil) // sanitize pkg_path. pkg_path := String(p.properties.Pkg_path) if pkg_path != "" { pkg_path = filepath.Clean(String(p.properties.Pkg_path)) if pkg_path == ".." || strings.HasPrefix(pkg_path, "../") || strings.HasPrefix(pkg_path, "/") { pkgPath := String(p.properties.Pkg_path) if pkgPath != "" { pkgPath = filepath.Clean(String(p.properties.Pkg_path)) if pkgPath == ".." || strings.HasPrefix(pkgPath, "../") || strings.HasPrefix(pkgPath, "/") { ctx.PropertyErrorf("pkg_path", "%q must be a relative path contained in par file.", String(p.properties.Pkg_path)) Loading @@ -390,31 +386,31 @@ func (p *Module) GeneratePythonBuildActions(ctx android.ModuleContext) { } if p.properties.Is_internal != nil && *p.properties.Is_internal { // pkg_path starts from "internal/" implicitly. pkg_path = filepath.Join(internal, pkg_path) pkgPath = filepath.Join(internal, pkgPath) } else { // pkg_path starts from "runfiles/" implicitly. pkg_path = filepath.Join(runFiles, pkg_path) pkgPath = filepath.Join(runFiles, pkgPath) } } else { if p.properties.Is_internal != nil && *p.properties.Is_internal { // pkg_path starts from "runfiles/" implicitly. pkg_path = internal pkgPath = internal } else { // pkg_path starts from "runfiles/" implicitly. pkg_path = runFiles pkgPath = runFiles } } p.genModulePathMappings(ctx, pkg_path, expandedSrcs, expandedData) p.parSpec = p.dumpFileList(ctx, pkg_path) p.genModulePathMappings(ctx, pkgPath, expandedSrcs, expandedData) p.uniqWholeRunfilesTree(ctx) p.srcsZip = p.createSrcsZip(ctx, pkgPath) } // generate current module unique pathMappings: <dest: runfiles_path, src: source_path> // 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) { // fetch <runfiles_path, source_path> pairs from "src" and "data" properties to // check duplicates. Loading @@ -426,7 +422,7 @@ func (p *Module) genModulePathMappings(ctx android.ModuleContext, pkg_path strin ctx.PropertyErrorf("srcs", "found non (.py) file: %q!", s.String()) continue } runfilesPath := filepath.Join(pkg_path, s.Rel()) runfilesPath := filepath.Join(pkgPath, s.Rel()) identifiers := strings.Split(strings.TrimSuffix(runfilesPath, pyExt), "/") for _, token := range identifiers { if !pyIdentifierRegexp.MatchString(token) { Loading @@ -445,7 +441,7 @@ func (p *Module) genModulePathMappings(ctx android.ModuleContext, pkg_path strin ctx.PropertyErrorf("data", "found (.py) file: %q!", d.String()) 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()) { p.dataPathMappings = append(p.dataPathMappings, pathMapping{dest: runfilesPath, src: d}) Loading @@ -454,12 +450,9 @@ func (p *Module) genModulePathMappings(ctx android.ModuleContext, pkg_path strin } // register build actions to dump filelist to disk. func (p *Module) dumpFileList(ctx android.ModuleContext, pkg_path string) parSpec { // register build actions to zip current module's sources. func (p *Module) createSrcsZip(ctx android.ModuleContext, pkgPath string) android.Path { 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...) // "srcs" or "data" properties may have filegroup so it might happen that Loading @@ -482,15 +475,29 @@ func (p *Module) dumpFileList(ctx android.ModuleContext, pkg_path string) parSpe } sort.Strings(keys) parArgs := []string{} parArgs = append(parArgs, `-P `+pkgPath) implicits := android.Paths{} for _, k := range keys { // use relative root as filelist name. fileListPath := registerBuildActionForModuleFileList( ctx, strings.Replace(k, "/", "_", -1), relativeRootMap[k]) ret.fileListSpecs = append(ret.fileListSpecs, fileListSpec{fileList: fileListPath, relativeRoot: k}) } parArgs = append(parArgs, `-C `+k) for _, path := range relativeRootMap[k] { parArgs = append(parArgs, `-f `+path.String()) implicits = append(implicits, path) } } 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 ret return srcsZip } func isPythonLibModule(module blueprint.Module) bool { Loading Loading @@ -537,9 +544,6 @@ func (p *Module) uniqWholeRunfilesTree(ctx android.ModuleContext) { ctx.OtherModuleName(module)) { 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() for _, path := range data { Loading @@ -547,9 +551,7 @@ func (p *Module) uniqWholeRunfilesTree(ctx android.ModuleContext) { path.dest, path.src.String(), ctx.ModuleName(), ctx.OtherModuleName(module)) } // binary needs the soong_zip arguments from all its // dependencies to generate executable par file. p.depsParSpecs = append(p.depsParSpecs, dep.GetParSpec()) p.depsSrcsZips = append(p.depsSrcsZips, dep.GetSrcsZip()) } }) } Loading
python/python_test.go +26 −42 Original line number Diff line number Diff line Loading @@ -32,9 +32,8 @@ type pyModule struct { name string actualVersion string pyRunfiles []string depsPyRunfiles []string parSpec string depsParSpecs []string srcsZip string depsSrcsZips []string } var ( Loading Loading @@ -313,14 +312,10 @@ var ( "runfiles/e/default_py3.py", "runfiles/e/file4.py", }, depsPyRunfiles: []string{ "runfiles/a/b/file1.py", "runfiles/c/d/file2.py", }, 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", srcsZip: "@prefix@/.intermediates/dir/bin/PY3/bin.zip", depsSrcsZips: []string{ "@prefix@/.intermediates/dir/lib5/PY3/lib5.zip", "@prefix@/.intermediates/dir/lib6/PY3/lib6.zip", }, }, }, Loading Loading @@ -356,8 +351,9 @@ func TestPythonModule(t *testing.T) { testErrs = append(testErrs, expectModule(t, ctx, buildDir, e.name, e.actualVersion, e.pyRunfiles, e.depsPyRunfiles, e.parSpec, e.depsParSpecs)...) e.srcsZip, e.pyRunfiles, e.depsSrcsZips)...) } } fail(t, testErrs) Loading Loading @@ -388,9 +384,8 @@ func expectErrors(t *testing.T, actErrs []error, expErrs []string) (testErrs []e return } func expectModule(t *testing.T, ctx *android.TestContext, buildDir, name, variant string, expPyRunfiles, expDepsPyRunfiles []string, expParSpec string, expDepsParSpecs []string) (testErrs []error) { func expectModule(t *testing.T, ctx *android.TestContext, buildDir, name, variant, expectedSrcsZip string, expectedPyRunfiles, expectedDepsSrcsZips []string) (testErrs []error) { module := ctx.ModuleForTests(name, variant) base, baseOk := module.Module().(*Module) Loading @@ -398,47 +393,36 @@ func expectModule(t *testing.T, ctx *android.TestContext, buildDir, name, varian t.Fatalf("%s is not Python module!", name) } actPyRunfiles := []string{} actualPyRunfiles := []string{} 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( `binary "%s" variant "%s" has unexpected pyRunfiles: %q!`, base.Name(), 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( `binary "%s" variant "%s" has unexpected depsPyRunfiles: %q!`, `binary "%s" variant "%s" has unexpected srcsZip: %q!`, base.Name(), base.properties.Actual_version, base.depsPyRunfiles))) base.srcsZip))) } if base.parSpec.soongParArgs() != strings.Replace(expParSpec, "@prefix@", buildDir, 1) { testErrs = append(testErrs, errors.New(fmt.Sprintf( `binary "%s" variant "%s" has unexpected parSpec: %q!`, base.Name(), base.properties.Actual_version, base.parSpec.soongParArgs()))) for i, _ := range expectedDepsSrcsZips { expectedDepsSrcsZips[i] = strings.Replace(expectedDepsSrcsZips[i], "@prefix@", buildDir, 1) } 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) { if !reflect.DeepEqual(base.depsSrcsZips.Strings(), expectedDepsSrcsZips) { testErrs = append(testErrs, errors.New(fmt.Sprintf( `binary "%s" variant "%s" has unexpected depsParSpecs: %q!`, `binary "%s" variant "%s" has unexpected depsSrcsZips: %q!`, base.Name(), base.properties.Actual_version, actDepsParSpecs))) base.depsSrcsZips))) } return Loading