1 // Copyright 2017 Google Inc. All rights reserved. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package python 16 17 // This file contains Ninja build actions for building Python program. 18 19 import ( 20 "strings" 21 22 "android/soong/android" 23 24 "github.com/google/blueprint" 25 _ "github.com/google/blueprint/bootstrap" 26 ) 27 28 var ( 29 pctx = android.NewPackageContext("android/soong/python") 30 31 par = pctx.AndroidStaticRule("par", 32 blueprint.RuleParams{ 33 Command: `touch $initFile && ` + 34 `sed -e 's/%interpreter%/$interp/g' -e 's/%main%/$main/g' $template > $stub && ` + 35 `$parCmd -o $parFile $parArgs && echo '#!/usr/bin/env python' | cat - $parFile > $out && ` + 36 `chmod +x $out && (rm -f $initFile; rm -f $stub; rm -f $parFile)`, 37 CommandDeps: []string{"$parCmd", "$template"}, 38 }, 39 "initFile", "interp", "main", "template", "stub", "parCmd", "parFile", "parArgs") 40 ) 41 42 func init() { 43 pctx.Import("github.com/google/blueprint/bootstrap") 44 pctx.Import("android/soong/common") 45 46 pctx.HostBinToolVariable("parCmd", "soong_zip") 47 } 48 49 type fileListSpec struct { 50 fileList android.Path 51 relativeRoot string 52 } 53 54 type parSpec struct { 55 rootPrefix string 56 57 fileListSpecs []fileListSpec 58 } 59 60 func (p parSpec) soongParArgs() string { 61 ret := "-P " + p.rootPrefix 62 63 for _, spec := range p.fileListSpecs { 64 ret += " -C " + spec.relativeRoot + " -l " + spec.fileList.String() 65 } 66 67 return ret 68 } 69 70 func registerBuildActionForModuleFileList(ctx android.ModuleContext, 71 name string, files android.Paths) android.Path { 72 fileList := android.PathForModuleOut(ctx, name+".list") 73 74 content := []string{} 75 for _, file := range files { 76 content = append(content, file.String()) 77 } 78 79 ctx.ModuleBuild(pctx, android.ModuleBuildParams{ 80 Rule: android.WriteFile, 81 Description: "generate " + fileList.Rel(), 82 Output: fileList, 83 Implicits: files, 84 Args: map[string]string{ 85 "content": strings.Join(content, `\n`), 86 }, 87 }) 88 89 return fileList 90 } 91 92 func registerBuildActionForParFile(ctx android.ModuleContext, 93 interpreter, main, binName string, newPyPkgs []string, parSpecs []parSpec) android.Path { 94 95 // intermediate output path for __init__.py 96 initFile := android.PathForModuleOut(ctx, initFileName).String() 97 98 // the path of stub_template_host.txt from source tree. 99 template := android.PathForSource(ctx, stubTemplateHost) 100 101 // intermediate output path for __main__.py 102 stub := android.PathForModuleOut(ctx, mainFileName).String() 103 104 // intermediate output path for par file. 105 parFile := android.PathForModuleOut(ctx, binName+parFileExt) 106 107 // intermediate output path for bin executable. 108 binFile := android.PathForModuleOut(ctx, binName) 109 110 // implicit dependency for parFile build action. 111 implicits := android.Paths{} 112 for _, p := range parSpecs { 113 for _, f := range p.fileListSpecs { 114 implicits = append(implicits, f.fileList) 115 } 116 } 117 118 parArgs := []string{} 119 parArgs = append(parArgs, "-C "+strings.TrimSuffix(stub, mainFileName)+" -f "+stub) 120 parArgs = append(parArgs, "-C "+strings.TrimSuffix(initFile, initFileName)+" -f "+initFile) 121 for _, pkg := range newPyPkgs { 122 parArgs = append(parArgs, "-P "+pkg+" -f "+initFile) 123 } 124 for _, p := range parSpecs { 125 parArgs = append(parArgs, p.soongParArgs()) 126 } 127 128 ctx.ModuleBuild(pctx, android.ModuleBuildParams{ 129 Rule: par, 130 Description: "python archive", 131 Output: binFile, 132 Implicits: implicits, 133 Args: map[string]string{ 134 "initFile": initFile, 135 // the "\" isn't being interpreted by regex parser, it's being 136 // interpreted in the string literal. 137 "interp": strings.Replace(interpreter, "/", `\/`, -1), 138 "main": strings.Replace(main, "/", `\/`, -1), 139 "template": template.String(), 140 "stub": stub, 141 "parFile": parFile.String(), 142 "parArgs": strings.Join(parArgs, " "), 143 }, 144 }) 145 146 return binFile 147 } 148