Home | History | Annotate | Download | only in python
      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