1// Copyright 2020 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 bp2build 16 17import ( 18 "fmt" 19 "os" 20 "strings" 21 22 "android/soong/android" 23 "android/soong/bazel" 24) 25 26// Codegen is the backend of bp2build. The code generator is responsible for 27// writing .bzl files that are equivalent to Android.bp files that are capable 28// of being built with Bazel. 29func Codegen(ctx *CodegenContext) CodegenMetrics { 30 // This directory stores BUILD files that could be eventually checked-in. 31 bp2buildDir := android.PathForOutput(ctx, "bp2build") 32 android.RemoveAllOutputDir(bp2buildDir) 33 34 res, errs := GenerateBazelTargets(ctx, true) 35 if len(errs) > 0 { 36 errMsgs := make([]string, len(errs)) 37 for i, err := range errs { 38 errMsgs[i] = fmt.Sprintf("%q", err) 39 } 40 fmt.Printf("ERROR: Encountered %d error(s): \nERROR: %s", len(errs), strings.Join(errMsgs, "\n")) 41 os.Exit(1) 42 } 43 bp2buildFiles := CreateBazelFiles(nil, res.buildFileToTargets, ctx.mode) 44 writeFiles(ctx, bp2buildDir, bp2buildFiles) 45 46 soongInjectionDir := android.PathForOutput(ctx, bazel.SoongInjectionDirName) 47 writeFiles(ctx, soongInjectionDir, CreateSoongInjectionFiles(ctx.Config(), res.metrics)) 48 49 return res.metrics 50} 51 52// Get the output directory and create it if it doesn't exist. 53func getOrCreateOutputDir(outputDir android.OutputPath, ctx android.PathContext, dir string) android.OutputPath { 54 dirPath := outputDir.Join(ctx, dir) 55 android.CreateOutputDirIfNonexistent(dirPath, os.ModePerm) 56 return dirPath 57} 58 59// writeFiles materializes a list of BazelFile rooted at outputDir. 60func writeFiles(ctx android.PathContext, outputDir android.OutputPath, files []BazelFile) { 61 for _, f := range files { 62 p := getOrCreateOutputDir(outputDir, ctx, f.Dir).Join(ctx, f.Basename) 63 if err := writeFile(ctx, p, f.Contents); err != nil { 64 panic(fmt.Errorf("Failed to write %q (dir %q) due to %q", f.Basename, f.Dir, err)) 65 } 66 } 67} 68 69func writeFile(ctx android.PathContext, pathToFile android.OutputPath, content string) error { 70 // These files are made editable to allow users to modify and iterate on them 71 // in the source tree. 72 return android.WriteFileToOutputDir(pathToFile, []byte(content), 0644) 73} 74