blob: 2eb84ca386e3bed11bbffc1d3c33c627014594a2 [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 (
18 "android/soong/finder"
Colin Cross8d6395c2017-12-21 15:46:01 -080019 "android/soong/finder/fs"
Jeff Gastonb64fc1c2017-08-04 12:30:12 -070020 "android/soong/ui/logger"
21 "bytes"
22 "io/ioutil"
23 "os"
24 "path/filepath"
25 "strings"
Nan Zhang17f27672018-12-12 16:01:49 -080026
27 "android/soong/ui/metrics"
Jeff Gastonb64fc1c2017-08-04 12:30:12 -070028)
29
Jingwen Chen096a3bf2020-11-17 04:53:22 -050030// This file provides an interface to the Finder type for soong_ui. Finder is
31// used to recursively traverse the source tree to gather paths of files, such
32// as Android.bp or Android.mk, and store the lists/database of paths in files
33// under `$OUT_DIR/.module_paths`. This directory can also be dist'd.
Jeff Gastonb64fc1c2017-08-04 12:30:12 -070034
35// NewSourceFinder returns a new Finder configured to search for source files.
36// Callers of NewSourceFinder should call <f.Shutdown()> when done
37func NewSourceFinder(ctx Context, config Config) (f *finder.Finder) {
Nan Zhang17f27672018-12-12 16:01:49 -080038 ctx.BeginTrace(metrics.RunSetupTool, "find modules")
Jeff Gastonb64fc1c2017-08-04 12:30:12 -070039 defer ctx.EndTrace()
40
Jingwen Chen096a3bf2020-11-17 04:53:22 -050041 // Set up the working directory for the Finder.
Jeff Gastonb64fc1c2017-08-04 12:30:12 -070042 dir, err := os.Getwd()
43 if err != nil {
44 ctx.Fatalf("No working directory for module-finder: %v", err.Error())
45 }
Jeff Gaston02ae4de2017-12-06 17:48:39 -080046 filesystem := fs.OsFs
47
Jingwen Chen096a3bf2020-11-17 04:53:22 -050048 // .out-dir and .find-ignore are markers for Finder to ignore siblings and
49 // subdirectories of the directory Finder finds them in, hence stopping the
50 // search recursively down those branches. It's possible that these files
51 // are in the root directory, and if they are, then the subsequent error
52 // messages are very confusing, so check for that here.
Jeff Gaston02ae4de2017-12-06 17:48:39 -080053 pruneFiles := []string{".out-dir", ".find-ignore"}
54 for _, name := range pruneFiles {
55 prunePath := filepath.Join(dir, name)
56 _, statErr := filesystem.Lstat(prunePath)
57 if statErr == nil {
58 ctx.Fatalf("%v must not exist", prunePath)
59 }
60 }
61
Jingwen Chen096a3bf2020-11-17 04:53:22 -050062 // Set up configuration parameters for the Finder cache.
Jeff Gastonb64fc1c2017-08-04 12:30:12 -070063 cacheParams := finder.CacheParams{
64 WorkingDirectory: dir,
65 RootDirs: []string{"."},
66 ExcludeDirs: []string{".git", ".repo"},
Jeff Gaston02ae4de2017-12-06 17:48:39 -080067 PruneFiles: pruneFiles,
Dan Willemsen567851c2018-05-01 22:43:52 -070068 IncludeFiles: []string{
Jingwen Chen096a3bf2020-11-17 04:53:22 -050069 // Kati build definitions.
Dan Willemsen567851c2018-05-01 22:43:52 -070070 "Android.mk",
Jingwen Chen096a3bf2020-11-17 04:53:22 -050071 // Product configuration files.
Dan Willemsen567851c2018-05-01 22:43:52 -070072 "AndroidProducts.mk",
Jingwen Chen096a3bf2020-11-17 04:53:22 -050073 // General Soong build definitions, using the Blueprint syntax.
Dan Willemsen567851c2018-05-01 22:43:52 -070074 "Android.bp",
Jingwen Chen096a3bf2020-11-17 04:53:22 -050075 // build/blueprint build definitions, using the Blueprint syntax.
Dan Willemsen567851c2018-05-01 22:43:52 -070076 "Blueprints",
Jingwen Chen096a3bf2020-11-17 04:53:22 -050077 // Bazel build definitions.
Chris Parsonsa798d962020-10-12 23:44:08 -040078 "BUILD.bazel",
Jingwen Chen096a3bf2020-11-17 04:53:22 -050079 // Kati clean definitions.
Dan Willemsen567851c2018-05-01 22:43:52 -070080 "CleanSpec.mk",
Jingwen Chen096a3bf2020-11-17 04:53:22 -050081 // Ownership definition.
Simran Basidf98cd72018-09-06 12:23:28 -070082 "OWNERS",
Jingwen Chen096a3bf2020-11-17 04:53:22 -050083 // Test configuration for modules in directories that contain this
84 // file.
Dan Willemsen567851c2018-05-01 22:43:52 -070085 "TEST_MAPPING",
Jingwen Chen096a3bf2020-11-17 04:53:22 -050086 // Bazel top-level file to mark a directory as a Bazel workspace.
Chris Parsonsa798d962020-10-12 23:44:08 -040087 "WORKSPACE",
Dan Willemsen567851c2018-05-01 22:43:52 -070088 },
Jingwen Chen096a3bf2020-11-17 04:53:22 -050089 // Bazel Starlark configuration files.
Chris Parsonsa798d962020-10-12 23:44:08 -040090 IncludeSuffixes: []string{".bzl"},
Jeff Gastonb64fc1c2017-08-04 12:30:12 -070091 }
92 dumpDir := config.FileListDir()
Jeff Gaston02ae4de2017-12-06 17:48:39 -080093 f, err = finder.New(cacheParams, filesystem, logger.New(ioutil.Discard),
Jeff Gastonb64fc1c2017-08-04 12:30:12 -070094 filepath.Join(dumpDir, "files.db"))
95 if err != nil {
96 ctx.Fatalf("Could not create module-finder: %v", err)
97 }
98 return f
99}
100
Jingwen Chen096a3bf2020-11-17 04:53:22 -0500101// Finds the list of Bazel-related files (BUILD, WORKSPACE and Starlark) in the tree.
Chris Parsonsa798d962020-10-12 23:44:08 -0400102func findBazelFiles(entries finder.DirEntries) (dirNames []string, fileNames []string) {
103 matches := []string{}
104 for _, foundName := range entries.FileNames {
105 if foundName == "BUILD.bazel" || foundName == "WORKSPACE" || strings.HasSuffix(foundName, ".bzl") {
106 matches = append(matches, foundName)
107 }
108 }
109 return entries.DirNames, matches
110}
111
Jeff Gastonb64fc1c2017-08-04 12:30:12 -0700112// FindSources searches for source files known to <f> and writes them to the filesystem for
113// use later.
114func FindSources(ctx Context, config Config, f *finder.Finder) {
115 // note that dumpDir in FindSources may be different than dumpDir in NewSourceFinder
116 // if a caller such as multiproduct_kati wants to share one Finder among several builds
117 dumpDir := config.FileListDir()
118 os.MkdirAll(dumpDir, 0777)
119
Jingwen Chen096a3bf2020-11-17 04:53:22 -0500120 // Stop searching a subdirectory recursively after finding an Android.mk.
Jeff Gastonb64fc1c2017-08-04 12:30:12 -0700121 androidMks := f.FindFirstNamedAt(".", "Android.mk")
Colin Cross8ba7d472020-06-25 11:27:52 -0700122 err := dumpListToFile(ctx, config, androidMks, filepath.Join(dumpDir, "Android.mk.list"))
Jeff Gastonb64fc1c2017-08-04 12:30:12 -0700123 if err != nil {
124 ctx.Fatalf("Could not export module list: %v", err)
125 }
126
Jingwen Chen096a3bf2020-11-17 04:53:22 -0500127 // Stop searching a subdirectory recursively after finding a CleanSpec.mk.
128 cleanSpecs := f.FindFirstNamedAt(".", "CleanSpec.mk")
129 err = dumpListToFile(ctx, config, cleanSpecs, filepath.Join(dumpDir, "CleanSpec.mk.list"))
130 if err != nil {
131 ctx.Fatalf("Could not export module list: %v", err)
132 }
133
134 // Only consider AndroidProducts.mk in device/, vendor/ and product/, recursively in these directories.
Dan Willemsen567851c2018-05-01 22:43:52 -0700135 androidProductsMks := f.FindNamedAt("device", "AndroidProducts.mk")
136 androidProductsMks = append(androidProductsMks, f.FindNamedAt("vendor", "AndroidProducts.mk")...)
137 androidProductsMks = append(androidProductsMks, f.FindNamedAt("product", "AndroidProducts.mk")...)
Colin Cross8ba7d472020-06-25 11:27:52 -0700138 err = dumpListToFile(ctx, config, androidProductsMks, filepath.Join(dumpDir, "AndroidProducts.mk.list"))
Dan Willemsen567851c2018-05-01 22:43:52 -0700139 if err != nil {
140 ctx.Fatalf("Could not export product list: %v", err)
141 }
142
Jingwen Chen096a3bf2020-11-17 04:53:22 -0500143 // Recursively look for all Bazel related files.
Chris Parsonsa798d962020-10-12 23:44:08 -0400144 bazelFiles := f.FindMatching(".", findBazelFiles)
145 err = dumpListToFile(ctx, config, bazelFiles, filepath.Join(dumpDir, "bazel.list"))
146 if err != nil {
147 ctx.Fatalf("Could not export bazel BUILD list: %v", err)
148 }
149
Jingwen Chen096a3bf2020-11-17 04:53:22 -0500150 // Recursively look for all OWNERS files.
Simran Basidf98cd72018-09-06 12:23:28 -0700151 owners := f.FindNamedAt(".", "OWNERS")
Colin Cross8ba7d472020-06-25 11:27:52 -0700152 err = dumpListToFile(ctx, config, owners, filepath.Join(dumpDir, "OWNERS.list"))
Simran Basidf98cd72018-09-06 12:23:28 -0700153 if err != nil {
154 ctx.Fatalf("Could not find OWNERS: %v", err)
155 }
156
Jingwen Chen096a3bf2020-11-17 04:53:22 -0500157 // Recursively look for all TEST_MAPPING files.
Dan Shicc3d9b32017-11-22 15:35:09 -0800158 testMappings := f.FindNamedAt(".", "TEST_MAPPING")
Colin Cross8ba7d472020-06-25 11:27:52 -0700159 err = dumpListToFile(ctx, config, testMappings, filepath.Join(dumpDir, "TEST_MAPPING.list"))
Dan Shicc3d9b32017-11-22 15:35:09 -0800160 if err != nil {
Simran Basidf98cd72018-09-06 12:23:28 -0700161 ctx.Fatalf("Could not find TEST_MAPPING: %v", err)
Dan Shicc3d9b32017-11-22 15:35:09 -0800162 }
163
Jingwen Chen096a3bf2020-11-17 04:53:22 -0500164 // Recursively look for all Android.bp files
Jeff Gaston29e959d2017-12-07 12:38:53 -0800165 androidBps := f.FindNamedAt(".", "Android.bp")
Jingwen Chen096a3bf2020-11-17 04:53:22 -0500166 // The files are named "Blueprints" only in the build/blueprint directory.
Jeff Gaston29e959d2017-12-07 12:38:53 -0800167 androidBps = append(androidBps, f.FindNamedAt("build/blueprint", "Blueprints")...)
Jeff Gaston02ae4de2017-12-06 17:48:39 -0800168 if len(androidBps) == 0 {
169 ctx.Fatalf("No Android.bp found")
170 }
Colin Cross8ba7d472020-06-25 11:27:52 -0700171 err = dumpListToFile(ctx, config, androidBps, filepath.Join(dumpDir, "Android.bp.list"))
Jeff Gastonb64fc1c2017-08-04 12:30:12 -0700172 if err != nil {
173 ctx.Fatalf("Could not find modules: %v", err)
174 }
Colin Cross96e5e412020-07-06 17:13:43 -0700175
176 if config.Dist() {
177 f.WaitForDbDump()
Jingwen Chen096a3bf2020-11-17 04:53:22 -0500178 // Dist the files.db plain text database.
Colin Cross96e5e412020-07-06 17:13:43 -0700179 distFile(ctx, config, f.DbPath, "module_paths")
180 }
Jeff Gastonb64fc1c2017-08-04 12:30:12 -0700181}
182
Jingwen Chen096a3bf2020-11-17 04:53:22 -0500183// Write the .list files to disk.
Colin Cross8ba7d472020-06-25 11:27:52 -0700184func dumpListToFile(ctx Context, config Config, list []string, filePath string) (err error) {
Jeff Gastonb64fc1c2017-08-04 12:30:12 -0700185 desiredText := strings.Join(list, "\n")
186 desiredBytes := []byte(desiredText)
187 actualBytes, readErr := ioutil.ReadFile(filePath)
188 if readErr != nil || !bytes.Equal(desiredBytes, actualBytes) {
189 err = ioutil.WriteFile(filePath, desiredBytes, 0777)
Colin Cross8ba7d472020-06-25 11:27:52 -0700190 if err != nil {
191 return err
192 }
Jeff Gastonb64fc1c2017-08-04 12:30:12 -0700193 }
Colin Cross8ba7d472020-06-25 11:27:52 -0700194
195 distFile(ctx, config, filePath, "module_paths")
196
197 return nil
Jeff Gastonb64fc1c2017-08-04 12:30:12 -0700198}