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 15package python 16 17// This file contains Ninja build actions for building Python program. 18 19import ( 20 "strings" 21 22 "android/soong/android" 23 "github.com/google/blueprint" 24 _ "github.com/google/blueprint/bootstrap" 25) 26 27var ( 28 pctx = android.NewPackageContext("android/soong/python") 29 30 zip = pctx.AndroidStaticRule("zip", 31 blueprint.RuleParams{ 32 Command: `$parCmd -o $out $args`, 33 CommandDeps: []string{"$parCmd"}, 34 }, 35 "args") 36 37 combineZip = pctx.AndroidStaticRule("combineZip", 38 blueprint.RuleParams{ 39 Command: `$mergeParCmd $out $in`, 40 CommandDeps: []string{"$mergeParCmd"}, 41 }, 42 ) 43 44 hostPar = pctx.AndroidStaticRule("hostPar", 45 blueprint.RuleParams{ 46 Command: `sed -e 's/%interpreter%/$interp/g' -e 's/%main%/__soong_entrypoint_redirector__.py/g' build/soong/python/scripts/stub_template_host.txt > $out.main && ` + 47 "sed -e 's/ENTRY_POINT/$main/g' build/soong/python/scripts/main_non_embedded.py >`dirname $out`/__soong_entrypoint_redirector__.py && " + 48 "$parCmd -o $out.entrypoint_zip -C `dirname $out` -f `dirname $out`/__soong_entrypoint_redirector__.py && " + 49 `echo "#!/usr/bin/env $interp" >${out}.prefix &&` + 50 `$mergeParCmd -p --prefix ${out}.prefix -pm $out.main $out $srcsZips $out.entrypoint_zip && ` + 51 "chmod +x $out && (rm -f $out.main; rm -f ${out}.prefix; rm -f $out.entrypoint_zip; rm -f `dirname $out`/__soong_entrypoint_redirector__.py)", 52 CommandDeps: []string{"$mergeParCmd", "$parCmd", "build/soong/python/scripts/stub_template_host.txt", "build/soong/python/scripts/main_non_embedded.py"}, 53 }, 54 "interp", "main", "srcsZips") 55 56 embeddedPar = pctx.AndroidStaticRule("embeddedPar", 57 blueprint.RuleParams{ 58 Command: `rm -f $out.main && ` + 59 `sed 's/ENTRY_POINT/$main/' build/soong/python/scripts/main.py >$out.main &&` + 60 `$mergeParCmd -p -pm $out.main --prefix $launcher $out $srcsZips && ` + 61 `chmod +x $out && rm -rf $out.main`, 62 CommandDeps: []string{"$mergeParCmd", "build/soong/python/scripts/main.py"}, 63 }, 64 "main", "srcsZips", "launcher") 65 66 embeddedParNoMain = pctx.AndroidStaticRule("embeddedParNoMain", 67 blueprint.RuleParams{ 68 Command: `$mergeParCmd -p --prefix $launcher $out $srcsZips && ` + 69 `chmod +x $out`, 70 CommandDeps: []string{"$mergeParCmd"}, 71 }, 72 "srcsZips", "launcher") 73 74 precompile = pctx.AndroidStaticRule("precompilePython", blueprint.RuleParams{ 75 Command: `LD_LIBRARY_PATH="$ldLibraryPath" ` + 76 `PYTHONPATH=$stdlibZip/internal/$stdlibPkg ` + 77 `$launcher build/soong/python/scripts/precompile_python.py $in $out`, 78 CommandDeps: []string{ 79 "$stdlibZip", 80 "$launcher", 81 "build/soong/python/scripts/precompile_python.py", 82 }, 83 }, "stdlibZip", "stdlibPkg", "launcher", "ldLibraryPath") 84) 85 86func init() { 87 pctx.Import("github.com/google/blueprint/bootstrap") 88 pctx.Import("android/soong/android") 89 90 pctx.HostBinToolVariable("parCmd", "soong_zip") 91 pctx.HostBinToolVariable("mergeParCmd", "merge_zips") 92} 93 94func registerBuildActionForParFile(ctx android.ModuleContext, embeddedLauncher bool, 95 launcherPath android.OptionalPath, interpreter, main, binName string, 96 srcsZips android.Paths) android.Path { 97 98 // .intermediate output path for bin executable. 99 binFile := android.PathForModuleOut(ctx, binName) 100 101 // implicit dependency for parFile build action. 102 implicits := srcsZips 103 104 if !embeddedLauncher { 105 ctx.Build(pctx, android.BuildParams{ 106 Rule: hostPar, 107 Description: "host python archive", 108 Output: binFile, 109 Implicits: implicits, 110 Args: map[string]string{ 111 "interp": strings.Replace(interpreter, "/", `\/`, -1), 112 "main": strings.Replace(strings.TrimSuffix(main, pyExt), "/", ".", -1), 113 "srcsZips": strings.Join(srcsZips.Strings(), " "), 114 }, 115 }) 116 } else if launcherPath.Valid() { 117 // added launcherPath to the implicits Ninja dependencies. 118 implicits = append(implicits, launcherPath.Path()) 119 120 if main == "" { 121 ctx.Build(pctx, android.BuildParams{ 122 Rule: embeddedParNoMain, 123 Description: "embedded python archive", 124 Output: binFile, 125 Implicits: implicits, 126 Args: map[string]string{ 127 "srcsZips": strings.Join(srcsZips.Strings(), " "), 128 "launcher": launcherPath.String(), 129 }, 130 }) 131 } else { 132 ctx.Build(pctx, android.BuildParams{ 133 Rule: embeddedPar, 134 Description: "embedded python archive", 135 Output: binFile, 136 Implicits: implicits, 137 Args: map[string]string{ 138 "main": strings.Replace(strings.TrimSuffix(main, pyExt), "/", ".", -1), 139 "srcsZips": strings.Join(srcsZips.Strings(), " "), 140 "launcher": launcherPath.String(), 141 }, 142 }) 143 } 144 } 145 146 return binFile 147} 148