0d7231170f
This intial list contains the directories that don't have any Android.mk file, and this will prevent new Android.mk file being added in these directories. Bug: 318428689 Test: CIs Change-Id: Ifde1b77ad17b8bb2e7ba962229cee6ba267d6316
224 lines
7.8 KiB
Go
224 lines
7.8 KiB
Go
// Copyright 2017 Google Inc. All rights reserved.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
package build
|
|
|
|
import (
|
|
"bytes"
|
|
"io/ioutil"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
|
|
"android/soong/finder"
|
|
"android/soong/finder/fs"
|
|
"android/soong/ui/logger"
|
|
|
|
"android/soong/ui/metrics"
|
|
)
|
|
|
|
// This file provides an interface to the Finder type for soong_ui. Finder is
|
|
// used to recursively traverse the source tree to gather paths of files, such
|
|
// as Android.bp or Android.mk, and store the lists/database of paths in files
|
|
// under `$OUT_DIR/.module_paths`. This directory can also be dist'd.
|
|
|
|
// NewSourceFinder returns a new Finder configured to search for source files.
|
|
// Callers of NewSourceFinder should call <f.Shutdown()> when done
|
|
func NewSourceFinder(ctx Context, config Config) (f *finder.Finder) {
|
|
ctx.BeginTrace(metrics.RunSetupTool, "find modules")
|
|
defer ctx.EndTrace()
|
|
|
|
// Set up the working directory for the Finder.
|
|
dir, err := os.Getwd()
|
|
if err != nil {
|
|
ctx.Fatalf("No working directory for module-finder: %v", err.Error())
|
|
}
|
|
filesystem := fs.OsFs
|
|
|
|
// .out-dir and .find-ignore are markers for Finder to ignore siblings and
|
|
// subdirectories of the directory Finder finds them in, hence stopping the
|
|
// search recursively down those branches. It's possible that these files
|
|
// are in the root directory, and if they are, then the subsequent error
|
|
// messages are very confusing, so check for that here.
|
|
pruneFiles := []string{".out-dir", ".find-ignore"}
|
|
for _, name := range pruneFiles {
|
|
prunePath := filepath.Join(dir, name)
|
|
_, statErr := filesystem.Lstat(prunePath)
|
|
if statErr == nil {
|
|
ctx.Fatalf("%v must not exist", prunePath)
|
|
}
|
|
}
|
|
|
|
// Set up configuration parameters for the Finder cache.
|
|
cacheParams := finder.CacheParams{
|
|
WorkingDirectory: dir,
|
|
RootDirs: androidBpSearchDirs(config),
|
|
FollowSymlinks: config.environ.IsEnvTrue("ALLOW_BP_UNDER_SYMLINKS"),
|
|
ExcludeDirs: []string{".git", ".repo"},
|
|
PruneFiles: pruneFiles,
|
|
IncludeFiles: []string{
|
|
// Kati build definitions.
|
|
"Android.mk",
|
|
// Product configuration files.
|
|
"AndroidProducts.mk",
|
|
// General Soong build definitions, using the Blueprint syntax.
|
|
"Android.bp",
|
|
// Kati clean definitions.
|
|
"CleanSpec.mk",
|
|
// Ownership definition.
|
|
"OWNERS",
|
|
// Test configuration for modules in directories that contain this
|
|
// file.
|
|
"TEST_MAPPING",
|
|
// METADATA file of packages
|
|
"METADATA",
|
|
},
|
|
// .mk files for product/board configuration.
|
|
IncludeSuffixes: []string{".mk"},
|
|
}
|
|
dumpDir := config.FileListDir()
|
|
f, err = finder.New(cacheParams, filesystem, logger.New(ioutil.Discard),
|
|
filepath.Join(dumpDir, "files.db"))
|
|
if err != nil {
|
|
ctx.Fatalf("Could not create module-finder: %v", err)
|
|
}
|
|
return f
|
|
}
|
|
|
|
func androidBpSearchDirs(config Config) []string {
|
|
dirs := []string{"."} // always search from root of source tree.
|
|
if config.searchApiDir {
|
|
// Search in out/api_surfaces
|
|
dirs = append(dirs, config.ApiSurfacesOutDir())
|
|
}
|
|
return dirs
|
|
}
|
|
|
|
func findProductAndBoardConfigFiles(entries finder.DirEntries) (dirNames []string, fileNames []string) {
|
|
matches := []string{}
|
|
for _, foundName := range entries.FileNames {
|
|
if foundName != "Android.mk" &&
|
|
foundName != "AndroidProducts.mk" &&
|
|
foundName != "CleanSpec.mk" &&
|
|
strings.HasSuffix(foundName, ".mk") {
|
|
matches = append(matches, foundName)
|
|
}
|
|
}
|
|
return entries.DirNames, matches
|
|
}
|
|
|
|
// FindSources searches for source files known to <f> and writes them to the filesystem for
|
|
// use later.
|
|
func FindSources(ctx Context, config Config, f *finder.Finder) {
|
|
// note that dumpDir in FindSources may be different than dumpDir in NewSourceFinder
|
|
// if a caller such as multiproduct_kati wants to share one Finder among several builds
|
|
dumpDir := config.FileListDir()
|
|
os.MkdirAll(dumpDir, 0777)
|
|
|
|
// Stop searching a subdirectory recursively after finding an Android.mk.
|
|
androidMks := f.FindFirstNamedAt(".", "Android.mk")
|
|
androidMks = blockAndroidMks(androidMks)
|
|
err := dumpListToFile(ctx, config, androidMks, filepath.Join(dumpDir, "Android.mk.list"))
|
|
if err != nil {
|
|
ctx.Fatalf("Could not export module list: %v", err)
|
|
}
|
|
|
|
// Gate collecting/reporting mk metrics on builds that specifically request
|
|
// it, as identifying the total number of mk files adds 4-5ms onto null
|
|
// builds.
|
|
if config.reportMkMetrics {
|
|
androidMksTotal := f.FindNamedAt(".", "Android.mk")
|
|
|
|
ctx.Metrics.SetToplevelMakefiles(len(androidMks))
|
|
ctx.Metrics.SetTotalMakefiles(len(androidMksTotal))
|
|
ctx.Metrics.DumpMkMetrics(config.MkMetrics())
|
|
}
|
|
|
|
// Stop searching a subdirectory recursively after finding a CleanSpec.mk.
|
|
cleanSpecs := f.FindFirstNamedAt(".", "CleanSpec.mk")
|
|
err = dumpListToFile(ctx, config, cleanSpecs, filepath.Join(dumpDir, "CleanSpec.mk.list"))
|
|
if err != nil {
|
|
ctx.Fatalf("Could not export module list: %v", err)
|
|
}
|
|
|
|
// Only consider AndroidProducts.mk in device/, vendor/ and product/, recursively in these directories.
|
|
androidProductsMks := f.FindNamedAt("device", "AndroidProducts.mk")
|
|
androidProductsMks = append(androidProductsMks, f.FindNamedAt("vendor", "AndroidProducts.mk")...)
|
|
androidProductsMks = append(androidProductsMks, f.FindNamedAt("product", "AndroidProducts.mk")...)
|
|
err = dumpListToFile(ctx, config, androidProductsMks, filepath.Join(dumpDir, "AndroidProducts.mk.list"))
|
|
if err != nil {
|
|
ctx.Fatalf("Could not export product list: %v", err)
|
|
}
|
|
|
|
// Recursively look for all OWNERS files.
|
|
owners := f.FindNamedAt(".", "OWNERS")
|
|
err = dumpListToFile(ctx, config, owners, filepath.Join(dumpDir, "OWNERS.list"))
|
|
if err != nil {
|
|
ctx.Fatalf("Could not find OWNERS: %v", err)
|
|
}
|
|
|
|
// Recursively look for all METADATA files.
|
|
metadataFiles := f.FindNamedAt(".", "METADATA")
|
|
err = dumpListToFile(ctx, config, metadataFiles, filepath.Join(dumpDir, "METADATA.list"))
|
|
if err != nil {
|
|
ctx.Fatalf("Could not find METADATA: %v", err)
|
|
}
|
|
|
|
// Recursively look for all TEST_MAPPING files.
|
|
testMappings := f.FindNamedAt(".", "TEST_MAPPING")
|
|
err = dumpListToFile(ctx, config, testMappings, filepath.Join(dumpDir, "TEST_MAPPING.list"))
|
|
if err != nil {
|
|
ctx.Fatalf("Could not find TEST_MAPPING: %v", err)
|
|
}
|
|
|
|
// Recursively look for all Android.bp files
|
|
androidBps := f.FindNamedAt(".", "Android.bp")
|
|
if len(androidBps) == 0 {
|
|
ctx.Fatalf("No Android.bp found")
|
|
}
|
|
err = dumpListToFile(ctx, config, androidBps, filepath.Join(dumpDir, "Android.bp.list"))
|
|
if err != nil {
|
|
ctx.Fatalf("Could not find modules: %v", err)
|
|
}
|
|
|
|
// Recursively look for all product/board config files.
|
|
configurationFiles := f.FindMatching(".", findProductAndBoardConfigFiles)
|
|
err = dumpListToFile(ctx, config, configurationFiles, filepath.Join(dumpDir, "configuration.list"))
|
|
if err != nil {
|
|
ctx.Fatalf("Could not export product/board configuration list: %v", err)
|
|
}
|
|
|
|
if config.Dist() {
|
|
f.WaitForDbDump()
|
|
// Dist the files.db plain text database.
|
|
distFile(ctx, config, f.DbPath, "module_paths")
|
|
}
|
|
}
|
|
|
|
// Write the .list files to disk.
|
|
func dumpListToFile(ctx Context, config Config, list []string, filePath string) (err error) {
|
|
desiredText := strings.Join(list, "\n")
|
|
desiredBytes := []byte(desiredText)
|
|
actualBytes, readErr := ioutil.ReadFile(filePath)
|
|
if readErr != nil || !bytes.Equal(desiredBytes, actualBytes) {
|
|
err = ioutil.WriteFile(filePath, desiredBytes, 0777)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
distFile(ctx, config, filePath, "module_paths")
|
|
|
|
return nil
|
|
}
|