blob: d1dfb9d36ef95e881e548ca1f607f8e28adfa720 [file] [log] [blame]
Liz Kammer2dd9ca42020-11-25 16:06:39 -08001// 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 (
Jingwen Chendaa54bc2020-12-14 02:58:54 -050018 "fmt"
Liz Kammer2dd9ca42020-11-25 16:06:39 -080019 "os"
Chris Parsons520e88b2023-02-09 17:54:00 -050020 "path/filepath"
Liz Kammer6eff3232021-08-26 08:37:59 -040021 "strings"
Chris Parsons3b1f83d2021-10-14 14:08:38 -040022
23 "android/soong/android"
24 "android/soong/bazel"
Chris Parsons520e88b2023-02-09 17:54:00 -050025 "android/soong/shared"
Liz Kammer2dd9ca42020-11-25 16:06:39 -080026)
27
Chris Parsons520e88b2023-02-09 17:54:00 -050028func deleteFilesExcept(ctx *CodegenContext, rootOutputPath android.OutputPath, except []BazelFile) {
29 // Delete files that should no longer be present.
30 bp2buildDirAbs := shared.JoinPath(ctx.topDir, rootOutputPath.String())
31
32 filesToDelete := make(map[string]struct{})
33 err := filepath.Walk(bp2buildDirAbs,
34 func(path string, info os.FileInfo, err error) error {
35 if err != nil {
36 return err
37 }
38 if !info.IsDir() {
39 relPath, err := filepath.Rel(bp2buildDirAbs, path)
40 if err != nil {
41 return err
42 }
43 filesToDelete[relPath] = struct{}{}
44 }
45 return nil
46 })
47 if err != nil {
48 fmt.Printf("ERROR reading %s: %s", bp2buildDirAbs, err)
49 os.Exit(1)
50 }
51
52 for _, bazelFile := range except {
53 filePath := filepath.Join(bazelFile.Dir, bazelFile.Basename)
54 delete(filesToDelete, filePath)
55 }
56 for f, _ := range filesToDelete {
57 absPath := shared.JoinPath(bp2buildDirAbs, f)
58 if err := os.RemoveAll(absPath); err != nil {
59 fmt.Printf("ERROR deleting %s: %s", absPath, err)
60 os.Exit(1)
61 }
62 }
63}
64
Jingwen Chen12b4c272021-03-10 02:05:59 -050065// Codegen is the backend of bp2build. The code generator is responsible for
66// writing .bzl files that are equivalent to Android.bp files that are capable
67// of being built with Bazel.
usta4f5d2c12022-10-28 23:32:01 -040068func Codegen(ctx *CodegenContext) *CodegenMetrics {
Jingwen Chenbf61afb2021-05-06 13:31:18 +000069 // This directory stores BUILD files that could be eventually checked-in.
70 bp2buildDir := android.PathForOutput(ctx, "bp2build")
Liz Kammer2dd9ca42020-11-25 16:06:39 -080071
Liz Kammer6eff3232021-08-26 08:37:59 -040072 res, errs := GenerateBazelTargets(ctx, true)
73 if len(errs) > 0 {
74 errMsgs := make([]string, len(errs))
75 for i, err := range errs {
76 errMsgs[i] = fmt.Sprintf("%q", err)
77 }
78 fmt.Printf("ERROR: Encountered %d error(s): \nERROR: %s", len(errs), strings.Join(errMsgs, "\n"))
79 os.Exit(1)
80 }
Sasha Smundak0fd93e02022-05-19 19:34:31 -070081 bp2buildFiles := CreateBazelFiles(ctx.Config(), nil, res.buildFileToTargets, ctx.mode)
Jingwen Chenbf61afb2021-05-06 13:31:18 +000082 writeFiles(ctx, bp2buildDir, bp2buildFiles)
Chris Parsons520e88b2023-02-09 17:54:00 -050083 // Delete files under the bp2build root which weren't just written. An
84 // alternative would have been to delete the whole directory and write these
85 // files. However, this would regenerate files which were otherwise unchanged
86 // since the last bp2build run, which would have negative incremental
87 // performance implications.
88 deleteFilesExcept(ctx, bp2buildDir, bp2buildFiles)
Liz Kammer2dd9ca42020-11-25 16:06:39 -080089
Cole Faust9e384e22023-02-08 17:43:09 -080090 injectionFiles, err := CreateSoongInjectionDirFiles(ctx, res.metrics)
91 if err != nil {
92 fmt.Printf("%s\n", err.Error())
93 os.Exit(1)
94 }
95 writeFiles(ctx, android.PathForOutput(ctx, bazel.SoongInjectionDirName), injectionFiles)
Spandan Das83e787e2023-01-11 02:50:00 +000096 return &res.metrics
97}
98
99// Wrapper function that will be responsible for all files in soong_injection directory
100// This includes
101// 1. config value(s) that are hardcoded in Soong
102// 2. product_config variables
Cole Faust9e384e22023-02-08 17:43:09 -0800103func CreateSoongInjectionDirFiles(ctx *CodegenContext, metrics CodegenMetrics) ([]BazelFile, error) {
Spandan Das83e787e2023-01-11 02:50:00 +0000104 var ret []BazelFile
105
Cole Faustb85d1a12022-11-08 18:14:01 -0800106 productConfigFiles, err := CreateProductConfigFiles(ctx)
107 if err != nil {
Cole Faust9e384e22023-02-08 17:43:09 -0800108 return nil, err
Cole Faustb85d1a12022-11-08 18:14:01 -0800109 }
Spandan Das83e787e2023-01-11 02:50:00 +0000110 ret = append(ret, productConfigFiles...)
Cole Faust9e384e22023-02-08 17:43:09 -0800111 injectionFiles, err := soongInjectionFiles(ctx.Config(), metrics)
112 if err != nil {
113 return nil, err
114 }
115 ret = append(ret, injectionFiles...)
116 return ret, nil
Liz Kammer2dd9ca42020-11-25 16:06:39 -0800117}
118
Jingwen Chen12b4c272021-03-10 02:05:59 -0500119// Get the output directory and create it if it doesn't exist.
120func getOrCreateOutputDir(outputDir android.OutputPath, ctx android.PathContext, dir string) android.OutputPath {
121 dirPath := outputDir.Join(ctx, dir)
Usta Shresthadb46a9b2022-07-11 11:29:56 -0400122 if err := android.CreateOutputDirIfNonexistent(dirPath, os.ModePerm); err != nil {
123 fmt.Printf("ERROR: path %s: %s", dirPath, err.Error())
124 }
Jingwen Chen12b4c272021-03-10 02:05:59 -0500125 return dirPath
Liz Kammer2dd9ca42020-11-25 16:06:39 -0800126}
127
Jingwen Chenbf61afb2021-05-06 13:31:18 +0000128// writeFiles materializes a list of BazelFile rooted at outputDir.
129func writeFiles(ctx android.PathContext, outputDir android.OutputPath, files []BazelFile) {
130 for _, f := range files {
131 p := getOrCreateOutputDir(outputDir, ctx, f.Dir).Join(ctx, f.Basename)
Usta Shresthadb46a9b2022-07-11 11:29:56 -0400132 if err := writeFile(p, f.Contents); err != nil {
Jingwen Chenbf61afb2021-05-06 13:31:18 +0000133 panic(fmt.Errorf("Failed to write %q (dir %q) due to %q", f.Basename, f.Dir, err))
134 }
135 }
136}
137
Usta Shresthadb46a9b2022-07-11 11:29:56 -0400138func writeFile(pathToFile android.OutputPath, content string) error {
Jingwen Chen12b4c272021-03-10 02:05:59 -0500139 // These files are made editable to allow users to modify and iterate on them
140 // in the source tree.
141 return android.WriteFileToOutputDir(pathToFile, []byte(content), 0644)
Liz Kammer2dd9ca42020-11-25 16:06:39 -0800142}