blob: ff8908b29ab46ec250144fd131f558a9a0607be3 [file] [log] [blame]
Jeff Gastonb64fc1c2017-08-04 12:30:12 -07001// 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 build
16
17import (
Jeff Gastonb64fc1c2017-08-04 12:30:12 -070018 "bytes"
19 "io/ioutil"
20 "os"
21 "path/filepath"
22 "strings"
Nan Zhang17f27672018-12-12 16:01:49 -080023
Lukacs T. Berkib838b0a2021-09-02 11:46:24 +020024 "android/soong/finder"
25 "android/soong/finder/fs"
26 "android/soong/ui/logger"
27
Nan Zhang17f27672018-12-12 16:01:49 -080028 "android/soong/ui/metrics"
Jeff Gastonb64fc1c2017-08-04 12:30:12 -070029)
30
Jingwen Chen096a3bf2020-11-17 04:53:22 -050031// This file provides an interface to the Finder type for soong_ui. Finder is
32// used to recursively traverse the source tree to gather paths of files, such
33// as Android.bp or Android.mk, and store the lists/database of paths in files
34// under `$OUT_DIR/.module_paths`. This directory can also be dist'd.
Jeff Gastonb64fc1c2017-08-04 12:30:12 -070035
36// NewSourceFinder returns a new Finder configured to search for source files.
37// Callers of NewSourceFinder should call <f.Shutdown()> when done
38func NewSourceFinder(ctx Context, config Config) (f *finder.Finder) {
Nan Zhang17f27672018-12-12 16:01:49 -080039 ctx.BeginTrace(metrics.RunSetupTool, "find modules")
Jeff Gastonb64fc1c2017-08-04 12:30:12 -070040 defer ctx.EndTrace()
41
Jingwen Chen096a3bf2020-11-17 04:53:22 -050042 // Set up the working directory for the Finder.
Jeff Gastonb64fc1c2017-08-04 12:30:12 -070043 dir, err := os.Getwd()
44 if err != nil {
45 ctx.Fatalf("No working directory for module-finder: %v", err.Error())
46 }
Jeff Gaston02ae4de2017-12-06 17:48:39 -080047 filesystem := fs.OsFs
48
Jingwen Chen096a3bf2020-11-17 04:53:22 -050049 // .out-dir and .find-ignore are markers for Finder to ignore siblings and
50 // subdirectories of the directory Finder finds them in, hence stopping the
51 // search recursively down those branches. It's possible that these files
52 // are in the root directory, and if they are, then the subsequent error
53 // messages are very confusing, so check for that here.
Jeff Gaston02ae4de2017-12-06 17:48:39 -080054 pruneFiles := []string{".out-dir", ".find-ignore"}
55 for _, name := range pruneFiles {
56 prunePath := filepath.Join(dir, name)
57 _, statErr := filesystem.Lstat(prunePath)
58 if statErr == nil {
59 ctx.Fatalf("%v must not exist", prunePath)
60 }
61 }
62
Jingwen Chen096a3bf2020-11-17 04:53:22 -050063 // Set up configuration parameters for the Finder cache.
Jeff Gastonb64fc1c2017-08-04 12:30:12 -070064 cacheParams := finder.CacheParams{
65 WorkingDirectory: dir,
Spandan Das394aa322022-11-03 17:02:10 +000066 RootDirs: androidBpSearchDirs(config),
Lukacs T. Berkie3487c82022-05-02 10:13:19 +020067 FollowSymlinks: config.environ.IsEnvTrue("ALLOW_BP_UNDER_SYMLINKS"),
Jeff Gastonb64fc1c2017-08-04 12:30:12 -070068 ExcludeDirs: []string{".git", ".repo"},
Jeff Gaston02ae4de2017-12-06 17:48:39 -080069 PruneFiles: pruneFiles,
Dan Willemsen567851c2018-05-01 22:43:52 -070070 IncludeFiles: []string{
Jingwen Chen096a3bf2020-11-17 04:53:22 -050071 // Kati build definitions.
Dan Willemsen567851c2018-05-01 22:43:52 -070072 "Android.mk",
Jingwen Chen096a3bf2020-11-17 04:53:22 -050073 // Product configuration files.
Dan Willemsen567851c2018-05-01 22:43:52 -070074 "AndroidProducts.mk",
Jingwen Chen096a3bf2020-11-17 04:53:22 -050075 // General Soong build definitions, using the Blueprint syntax.
Dan Willemsen567851c2018-05-01 22:43:52 -070076 "Android.bp",
Jingwen Chen096a3bf2020-11-17 04:53:22 -050077 // Kati clean definitions.
Dan Willemsen567851c2018-05-01 22:43:52 -070078 "CleanSpec.mk",
Jingwen Chen096a3bf2020-11-17 04:53:22 -050079 // Ownership definition.
Simran Basidf98cd72018-09-06 12:23:28 -070080 "OWNERS",
Jingwen Chen096a3bf2020-11-17 04:53:22 -050081 // Test configuration for modules in directories that contain this
82 // file.
Dan Willemsen567851c2018-05-01 22:43:52 -070083 "TEST_MAPPING",
Wei Li2c9e8d62023-05-05 01:07:15 -070084 // METADATA file of packages
85 "METADATA",
Dan Willemsen567851c2018-05-01 22:43:52 -070086 },
Herbert Xuee3b554a2025-03-19 16:48:50 +080087 IncludeSuffixes: []string{
88 // .mk files for product/board configuration.
89 ".mk",
90 // otatools cert files
91 ".pk8",
92 ".pem",
93 ".avbpubkey",
94 },
Jeff Gastonb64fc1c2017-08-04 12:30:12 -070095 }
96 dumpDir := config.FileListDir()
Jeff Gaston02ae4de2017-12-06 17:48:39 -080097 f, err = finder.New(cacheParams, filesystem, logger.New(ioutil.Discard),
Jeff Gastonb64fc1c2017-08-04 12:30:12 -070098 filepath.Join(dumpDir, "files.db"))
99 if err != nil {
100 ctx.Fatalf("Could not create module-finder: %v", err)
101 }
102 return f
103}
104
Spandan Das394aa322022-11-03 17:02:10 +0000105func androidBpSearchDirs(config Config) []string {
106 dirs := []string{"."} // always search from root of source tree.
107 if config.searchApiDir {
108 // Search in out/api_surfaces
109 dirs = append(dirs, config.ApiSurfacesOutDir())
110 }
111 return dirs
112}
113
Cole Faust8d47c482022-01-26 14:27:44 -0800114func findProductAndBoardConfigFiles(entries finder.DirEntries) (dirNames []string, fileNames []string) {
115 matches := []string{}
116 for _, foundName := range entries.FileNames {
117 if foundName != "Android.mk" &&
118 foundName != "AndroidProducts.mk" &&
119 foundName != "CleanSpec.mk" &&
120 strings.HasSuffix(foundName, ".mk") {
121 matches = append(matches, foundName)
122 }
123 }
124 return entries.DirNames, matches
125}
126
Herbert Xuee3b554a2025-03-19 16:48:50 +0800127func findOtaToolsCertFiles(entries finder.DirEntries) (dirNames []string, fileNames []string) {
128 matches := []string{}
129 for _, foundName := range entries.FileNames {
130 if strings.HasSuffix(foundName, ".pk8") ||
131 strings.HasSuffix(foundName, ".pem") ||
132 strings.HasSuffix(foundName, ".avbpubkey") {
133 matches = append(matches, foundName)
134 }
135 }
136 return entries.DirNames, matches
137}
138
Jeff Gastonb64fc1c2017-08-04 12:30:12 -0700139// FindSources searches for source files known to <f> and writes them to the filesystem for
140// use later.
141func FindSources(ctx Context, config Config, f *finder.Finder) {
142 // note that dumpDir in FindSources may be different than dumpDir in NewSourceFinder
143 // if a caller such as multiproduct_kati wants to share one Finder among several builds
144 dumpDir := config.FileListDir()
145 os.MkdirAll(dumpDir, 0777)
146
Jingwen Chen096a3bf2020-11-17 04:53:22 -0500147 // Stop searching a subdirectory recursively after finding an Android.mk.
Jeff Gastonb64fc1c2017-08-04 12:30:12 -0700148 androidMks := f.FindFirstNamedAt(".", "Android.mk")
Wei Lif3a70902025-01-15 02:14:44 -0800149 androidMks = ignoreSomeAndroidMks(androidMks)
Wei Lid0a2e322024-02-06 11:54:55 -0800150 blockAndroidMks(ctx, androidMks)
Colin Cross8ba7d472020-06-25 11:27:52 -0700151 err := dumpListToFile(ctx, config, androidMks, filepath.Join(dumpDir, "Android.mk.list"))
Jeff Gastonb64fc1c2017-08-04 12:30:12 -0700152 if err != nil {
153 ctx.Fatalf("Could not export module list: %v", err)
154 }
155
Chris Parsons53f68ae2022-03-03 12:01:40 -0500156 // Gate collecting/reporting mk metrics on builds that specifically request
157 // it, as identifying the total number of mk files adds 4-5ms onto null
158 // builds.
159 if config.reportMkMetrics {
160 androidMksTotal := f.FindNamedAt(".", "Android.mk")
161
162 ctx.Metrics.SetToplevelMakefiles(len(androidMks))
163 ctx.Metrics.SetTotalMakefiles(len(androidMksTotal))
164 ctx.Metrics.DumpMkMetrics(config.MkMetrics())
165 }
166
Jingwen Chen096a3bf2020-11-17 04:53:22 -0500167 // Stop searching a subdirectory recursively after finding a CleanSpec.mk.
168 cleanSpecs := f.FindFirstNamedAt(".", "CleanSpec.mk")
169 err = dumpListToFile(ctx, config, cleanSpecs, filepath.Join(dumpDir, "CleanSpec.mk.list"))
170 if err != nil {
171 ctx.Fatalf("Could not export module list: %v", err)
172 }
173
174 // Only consider AndroidProducts.mk in device/, vendor/ and product/, recursively in these directories.
Dan Willemsen567851c2018-05-01 22:43:52 -0700175 androidProductsMks := f.FindNamedAt("device", "AndroidProducts.mk")
176 androidProductsMks = append(androidProductsMks, f.FindNamedAt("vendor", "AndroidProducts.mk")...)
177 androidProductsMks = append(androidProductsMks, f.FindNamedAt("product", "AndroidProducts.mk")...)
Colin Cross8ba7d472020-06-25 11:27:52 -0700178 err = dumpListToFile(ctx, config, androidProductsMks, filepath.Join(dumpDir, "AndroidProducts.mk.list"))
Dan Willemsen567851c2018-05-01 22:43:52 -0700179 if err != nil {
180 ctx.Fatalf("Could not export product list: %v", err)
181 }
182
Jingwen Chen096a3bf2020-11-17 04:53:22 -0500183 // Recursively look for all OWNERS files.
Simran Basidf98cd72018-09-06 12:23:28 -0700184 owners := f.FindNamedAt(".", "OWNERS")
Colin Cross8ba7d472020-06-25 11:27:52 -0700185 err = dumpListToFile(ctx, config, owners, filepath.Join(dumpDir, "OWNERS.list"))
Simran Basidf98cd72018-09-06 12:23:28 -0700186 if err != nil {
187 ctx.Fatalf("Could not find OWNERS: %v", err)
188 }
189
Wei Li2c9e8d62023-05-05 01:07:15 -0700190 // Recursively look for all METADATA files.
191 metadataFiles := f.FindNamedAt(".", "METADATA")
Wei Liae3c12b2024-10-29 15:26:49 -0700192 metadataFiles = ignoreNonAndroidMetadataFiles(metadataFiles)
Wei Li2c9e8d62023-05-05 01:07:15 -0700193 err = dumpListToFile(ctx, config, metadataFiles, filepath.Join(dumpDir, "METADATA.list"))
194 if err != nil {
195 ctx.Fatalf("Could not find METADATA: %v", err)
196 }
197
Jingwen Chen096a3bf2020-11-17 04:53:22 -0500198 // Recursively look for all TEST_MAPPING files.
Dan Shicc3d9b32017-11-22 15:35:09 -0800199 testMappings := f.FindNamedAt(".", "TEST_MAPPING")
Colin Cross8ba7d472020-06-25 11:27:52 -0700200 err = dumpListToFile(ctx, config, testMappings, filepath.Join(dumpDir, "TEST_MAPPING.list"))
Dan Shicc3d9b32017-11-22 15:35:09 -0800201 if err != nil {
Simran Basidf98cd72018-09-06 12:23:28 -0700202 ctx.Fatalf("Could not find TEST_MAPPING: %v", err)
Dan Shicc3d9b32017-11-22 15:35:09 -0800203 }
204
Herbert Xuee3b554a2025-03-19 16:48:50 +0800205 // Recursively look for all otatools cert files.
206 otatools_cert_files := f.FindMatching("build/make/target/product/security", findOtaToolsCertFiles)
207 otatools_cert_files = append(otatools_cert_files, f.FindMatching("device", findOtaToolsCertFiles)...)
208 otatools_cert_files = append(otatools_cert_files, f.FindMatching("external/avb/test/data", findOtaToolsCertFiles)...)
209 otatools_cert_files = append(otatools_cert_files, f.FindMatching("packages/modules", findOtaToolsCertFiles)...)
210 otatools_cert_files = append(otatools_cert_files, f.FindMatching("vendor", findOtaToolsCertFiles)...)
211 err = dumpListToFile(ctx, config, otatools_cert_files, filepath.Join(dumpDir, "OtaToolsCertFiles.list"))
212 if err != nil {
213 ctx.Fatalf("Could not find otatools cert files: %v", err)
214 }
215
Jingwen Chen096a3bf2020-11-17 04:53:22 -0500216 // Recursively look for all Android.bp files
Jeff Gaston29e959d2017-12-07 12:38:53 -0800217 androidBps := f.FindNamedAt(".", "Android.bp")
Jeff Gaston02ae4de2017-12-06 17:48:39 -0800218 if len(androidBps) == 0 {
219 ctx.Fatalf("No Android.bp found")
220 }
Colin Cross8ba7d472020-06-25 11:27:52 -0700221 err = dumpListToFile(ctx, config, androidBps, filepath.Join(dumpDir, "Android.bp.list"))
Jeff Gastonb64fc1c2017-08-04 12:30:12 -0700222 if err != nil {
223 ctx.Fatalf("Could not find modules: %v", err)
224 }
Colin Cross96e5e412020-07-06 17:13:43 -0700225
Cole Faust8d47c482022-01-26 14:27:44 -0800226 // Recursively look for all product/board config files.
227 configurationFiles := f.FindMatching(".", findProductAndBoardConfigFiles)
228 err = dumpListToFile(ctx, config, configurationFiles, filepath.Join(dumpDir, "configuration.list"))
229 if err != nil {
230 ctx.Fatalf("Could not export product/board configuration list: %v", err)
231 }
232
Colin Cross96e5e412020-07-06 17:13:43 -0700233 if config.Dist() {
234 f.WaitForDbDump()
Jingwen Chen096a3bf2020-11-17 04:53:22 -0500235 // Dist the files.db plain text database.
Colin Cross96e5e412020-07-06 17:13:43 -0700236 distFile(ctx, config, f.DbPath, "module_paths")
237 }
Jeff Gastonb64fc1c2017-08-04 12:30:12 -0700238}
239
Jingwen Chen096a3bf2020-11-17 04:53:22 -0500240// Write the .list files to disk.
Colin Cross8ba7d472020-06-25 11:27:52 -0700241func dumpListToFile(ctx Context, config Config, list []string, filePath string) (err error) {
Jeff Gastonb64fc1c2017-08-04 12:30:12 -0700242 desiredText := strings.Join(list, "\n")
243 desiredBytes := []byte(desiredText)
244 actualBytes, readErr := ioutil.ReadFile(filePath)
245 if readErr != nil || !bytes.Equal(desiredBytes, actualBytes) {
246 err = ioutil.WriteFile(filePath, desiredBytes, 0777)
Colin Cross8ba7d472020-06-25 11:27:52 -0700247 if err != nil {
248 return err
249 }
Jeff Gastonb64fc1c2017-08-04 12:30:12 -0700250 }
Colin Cross8ba7d472020-06-25 11:27:52 -0700251
252 distFile(ctx, config, filePath, "module_paths")
253
254 return nil
Jeff Gastonb64fc1c2017-08-04 12:30:12 -0700255}
Wei Liae3c12b2024-10-29 15:26:49 -0700256
257func ignoreNonAndroidMetadataFiles(metadataFiles []string) []string {
258 result := make([]string, 0, len(metadataFiles))
259 for _, file := range metadataFiles {
260 // Ignore files like prebuilts/clang/host/linux-x86/clang-r536225/python3/lib/python3.11/site-packages/pip-23.1.2.dist-info/METADATA
261 // these METADATA files are from upstream and are not the METADATA files used in Android codebase.
262 if strings.Contains(file, "prebuilts/clang/host/") && strings.Contains(file, "/site-packages/") {
263 continue
264 }
265 result = append(result, file)
266 }
267 return result
268}