Home | History | Annotate | Download | only in build
      1 // 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 
     15 package build
     16 
     17 import (
     18 	"android/soong/finder"
     19 	"android/soong/finder/fs"
     20 	"android/soong/ui/logger"
     21 	"bytes"
     22 	"io/ioutil"
     23 	"os"
     24 	"path/filepath"
     25 	"strings"
     26 )
     27 
     28 // This file provides an interface to the Finder for use in Soong UI
     29 // This file stores configuration information about which files to find
     30 
     31 // NewSourceFinder returns a new Finder configured to search for source files.
     32 // Callers of NewSourceFinder should call <f.Shutdown()> when done
     33 func NewSourceFinder(ctx Context, config Config) (f *finder.Finder) {
     34 	ctx.BeginTrace("find modules")
     35 	defer ctx.EndTrace()
     36 
     37 	dir, err := os.Getwd()
     38 	if err != nil {
     39 		ctx.Fatalf("No working directory for module-finder: %v", err.Error())
     40 	}
     41 	filesystem := fs.OsFs
     42 
     43 	// if the root dir is ignored, then the subsequent error messages are very confusing,
     44 	// so check for that upfront
     45 	pruneFiles := []string{".out-dir", ".find-ignore"}
     46 	for _, name := range pruneFiles {
     47 		prunePath := filepath.Join(dir, name)
     48 		_, statErr := filesystem.Lstat(prunePath)
     49 		if statErr == nil {
     50 			ctx.Fatalf("%v must not exist", prunePath)
     51 		}
     52 	}
     53 
     54 	cacheParams := finder.CacheParams{
     55 		WorkingDirectory: dir,
     56 		RootDirs:         []string{"."},
     57 		ExcludeDirs:      []string{".git", ".repo"},
     58 		PruneFiles:       pruneFiles,
     59 		IncludeFiles:     []string{"Android.mk", "Android.bp", "Blueprints", "CleanSpec.mk", "TEST_MAPPING"},
     60 	}
     61 	dumpDir := config.FileListDir()
     62 	f, err = finder.New(cacheParams, filesystem, logger.New(ioutil.Discard),
     63 		filepath.Join(dumpDir, "files.db"))
     64 	if err != nil {
     65 		ctx.Fatalf("Could not create module-finder: %v", err)
     66 	}
     67 	return f
     68 }
     69 
     70 // FindSources searches for source files known to <f> and writes them to the filesystem for
     71 // use later.
     72 func FindSources(ctx Context, config Config, f *finder.Finder) {
     73 	// note that dumpDir in FindSources may be different than dumpDir in NewSourceFinder
     74 	// if a caller such as multiproduct_kati wants to share one Finder among several builds
     75 	dumpDir := config.FileListDir()
     76 	os.MkdirAll(dumpDir, 0777)
     77 
     78 	androidMks := f.FindFirstNamedAt(".", "Android.mk")
     79 	err := dumpListToFile(androidMks, filepath.Join(dumpDir, "Android.mk.list"))
     80 	if err != nil {
     81 		ctx.Fatalf("Could not export module list: %v", err)
     82 	}
     83 
     84 	cleanSpecs := f.FindFirstNamedAt(".", "CleanSpec.mk")
     85 	dumpListToFile(cleanSpecs, filepath.Join(dumpDir, "CleanSpec.mk.list"))
     86 	if err != nil {
     87 		ctx.Fatalf("Could not export module list: %v", err)
     88 	}
     89 
     90 	testMappings := f.FindNamedAt(".", "TEST_MAPPING")
     91 	err = dumpListToFile(testMappings, filepath.Join(dumpDir, "TEST_MAPPING.list"))
     92 	if err != nil {
     93 		ctx.Fatalf("Could not find modules: %v", err)
     94 	}
     95 
     96 	androidBps := f.FindNamedAt(".", "Android.bp")
     97 	androidBps = append(androidBps, f.FindNamedAt("build/blueprint", "Blueprints")...)
     98 	if len(androidBps) == 0 {
     99 		ctx.Fatalf("No Android.bp found")
    100 	}
    101 	err = dumpListToFile(androidBps, filepath.Join(dumpDir, "Android.bp.list"))
    102 	if err != nil {
    103 		ctx.Fatalf("Could not find modules: %v", err)
    104 	}
    105 }
    106 
    107 func dumpListToFile(list []string, filePath string) (err error) {
    108 	desiredText := strings.Join(list, "\n")
    109 	desiredBytes := []byte(desiredText)
    110 	actualBytes, readErr := ioutil.ReadFile(filePath)
    111 	if readErr != nil || !bytes.Equal(desiredBytes, actualBytes) {
    112 		err = ioutil.WriteFile(filePath, desiredBytes, 0777)
    113 	}
    114 	return err
    115 }
    116