github.com/westcoastroms/westcoastroms-build@v0.0.0-20190928114312-2350e5a73030/build/soong/python/builder.go (about)

     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  	"fmt"
    21  	"strings"
    22  
    23  	"android/soong/android"
    24  
    25  	"github.com/google/blueprint"
    26  	_ "github.com/google/blueprint/bootstrap"
    27  )
    28  
    29  var (
    30  	pctx = android.NewPackageContext("android/soong/python")
    31  
    32  	host_par = pctx.AndroidStaticRule("host_par",
    33  		blueprint.RuleParams{
    34  			Command: `touch $initFile && ` +
    35  				`sed -e 's/%interpreter%/$interp/g' -e 's/%main%/$main/g' $template > $stub && ` +
    36  				`$parCmd -o $parFile $parArgs && echo '#!/usr/bin/env python' | cat - $parFile > $out && ` +
    37  				`chmod +x $out && (rm -f $initFile; rm -f $stub; rm -f $parFile)`,
    38  			CommandDeps: []string{"$parCmd", "$template"},
    39  		},
    40  		"initFile", "interp", "main", "template", "stub", "parCmd", "parFile", "parArgs")
    41  
    42  	embedded_par = pctx.AndroidStaticRule("embedded_par",
    43  		blueprint.RuleParams{
    44  			Command: `touch $initFile && ` +
    45  				`echo '$main' > $entry_point && ` +
    46  				`$parCmd -o $parFile $parArgs && cat $launcher | cat - $parFile > $out && ` +
    47  				`chmod +x $out && (rm -f $initFile; rm -f $entry_point; rm -f $parFile)`,
    48  			CommandDeps: []string{"$parCmd"},
    49  		},
    50  		"initFile", "main", "entry_point", "parCmd", "parFile", "parArgs", "launcher")
    51  )
    52  
    53  func init() {
    54  	pctx.Import("github.com/google/blueprint/bootstrap")
    55  	pctx.Import("android/soong/common")
    56  
    57  	pctx.HostBinToolVariable("parCmd", "soong_zip")
    58  }
    59  
    60  type fileListSpec struct {
    61  	fileList     android.Path
    62  	relativeRoot string
    63  }
    64  
    65  type parSpec struct {
    66  	rootPrefix string
    67  
    68  	fileListSpecs []fileListSpec
    69  }
    70  
    71  func (p parSpec) soongParArgs() string {
    72  	ret := `-P ` + p.rootPrefix
    73  
    74  	for _, spec := range p.fileListSpecs {
    75  		ret += ` -C ` + spec.relativeRoot + ` -l ` + spec.fileList.String()
    76  	}
    77  
    78  	return ret
    79  }
    80  
    81  func registerBuildActionForModuleFileList(ctx android.ModuleContext,
    82  	name string, files android.Paths) android.Path {
    83  	fileList := android.PathForModuleOut(ctx, name+".list")
    84  
    85  	content := []string{}
    86  	for _, file := range files {
    87  		content = append(content, file.String())
    88  	}
    89  
    90  	ctx.Build(pctx, android.BuildParams{
    91  		Rule:        android.WriteFile,
    92  		Description: "generate " + fileList.Rel(),
    93  		Output:      fileList,
    94  		Implicits:   files,
    95  		Args: map[string]string{
    96  			"content": strings.Join(content, `\n`),
    97  		},
    98  	})
    99  
   100  	return fileList
   101  }
   102  
   103  func registerBuildActionForParFile(ctx android.ModuleContext, embedded_launcher bool,
   104  	launcher_path android.Path, interpreter, main, binName string,
   105  	newPyPkgs []string, parSpecs []parSpec) android.Path {
   106  
   107  	// .intermediate output path for __init__.py
   108  	initFile := android.PathForModuleOut(ctx, initFileName).String()
   109  
   110  	// .intermediate output path for par file.
   111  	parFile := android.PathForModuleOut(ctx, binName+parFileExt)
   112  
   113  	// .intermediate output path for bin executable.
   114  	binFile := android.PathForModuleOut(ctx, binName)
   115  
   116  	// implicit dependency for parFile build action.
   117  	implicits := android.Paths{}
   118  	for _, p := range parSpecs {
   119  		for _, f := range p.fileListSpecs {
   120  			implicits = append(implicits, f.fileList)
   121  		}
   122  	}
   123  
   124  	parArgs := []string{}
   125  	parArgs = append(parArgs, `-P "" `+`-C `+strings.TrimSuffix(initFile, initFileName)+` -f `+initFile)
   126  	for _, pkg := range newPyPkgs {
   127  		parArgs = append(parArgs, `-P `+pkg+` -f `+initFile)
   128  	}
   129  	for _, p := range parSpecs {
   130  		parArgs = append(parArgs, p.soongParArgs())
   131  	}
   132  
   133  	if !embedded_launcher {
   134  		// the path of stub_template_host.txt from source tree.
   135  		template := android.PathForSource(ctx, stubTemplateHost)
   136  
   137  		// intermediate output path for __main__.py
   138  		stub := android.PathForModuleOut(ctx, mainFileName).String()
   139  
   140  		// added stub file to the soong_zip args.
   141  		parArgs = append(parArgs, `-P "" `+`-C `+strings.TrimSuffix(stub, mainFileName)+` -f `+stub)
   142  
   143  		ctx.Build(pctx, android.BuildParams{
   144  			Rule:        host_par,
   145  			Description: "host python archive",
   146  			Output:      binFile,
   147  			Implicits:   implicits,
   148  			Args: map[string]string{
   149  				"initFile": initFile,
   150  				"interp":   strings.Replace(interpreter, "/", `\/`, -1),
   151  				// we need remove "runfiles/" suffix since stub script starts
   152  				// searching for main file in each sub-dir of "runfiles" directory tree.
   153  				"main": strings.Replace(strings.TrimPrefix(main, runFiles+"/"),
   154  					"/", `\/`, -1),
   155  				"template": template.String(),
   156  				"stub":     stub,
   157  				"parFile":  parFile.String(),
   158  				"parArgs":  strings.Join(parArgs, " "),
   159  			},
   160  		})
   161  	} else {
   162  		// added launcher_path to the implicits Ninja dependencies.
   163  		implicits = append(implicits, launcher_path)
   164  
   165  		// .intermediate output path for entry_point.txt
   166  		entryPoint := android.PathForModuleOut(ctx, entryPointFile).String()
   167  
   168  		// added entry_point file to the soong_zip args.
   169  		parArgs = append(parArgs, `-P "" `+`-C `+fmt.Sprintf(
   170  			"%q", strings.TrimSuffix(entryPoint, entryPointFile))+` -f `+entryPoint)
   171  
   172  		ctx.Build(pctx, android.BuildParams{
   173  			Rule:        embedded_par,
   174  			Description: "embedded python archive",
   175  			Output:      binFile,
   176  			Implicits:   implicits,
   177  			Args: map[string]string{
   178  				"initFile":    initFile,
   179  				"main":        main,
   180  				"entry_point": entryPoint,
   181  				"parFile":     parFile.String(),
   182  				"parArgs":     strings.Join(parArgs, " "),
   183  				"launcher":    launcher_path.String(),
   184  			},
   185  		})
   186  	}
   187  
   188  	return binFile
   189  }