Merge "Add product_variables.uml"
diff --git a/cc/linker.go b/cc/linker.go
index a0f3bc2..678b992 100644
--- a/cc/linker.go
+++ b/cc/linker.go
@@ -48,8 +48,8 @@
No_default_compiler_flags *bool
// list of system libraries that will be dynamically linked to
- // shared library and executable modules. If unset, generally defaults to libc
- // and libm. Set to [] to prevent linking against libc and libm.
+ // shared library and executable modules. If unset, generally defaults to libc,
+ // libm, and libdl. Set to [] to prevent linking against the defaults.
System_shared_libs []string
// allow the module to contain undefined symbols. By default,
@@ -153,34 +153,32 @@
}
if !ctx.static() {
- // libdl should always appear after libc in dt_needed list - see below
- // the only exception is when libc is not in linker.Properties.System_shared_libs
- // such as for libc module itself
- if inList("libc", linker.Properties.System_shared_libs) {
- _, deps.SharedLibs = removeFromList("libdl", deps.SharedLibs)
+ systemSharedLibs := linker.Properties.System_shared_libs
+ if systemSharedLibs == nil {
+ systemSharedLibs = []string{"libc", "libm", "libdl"}
}
- if linker.Properties.System_shared_libs != nil {
- if !inList("libdl", linker.Properties.System_shared_libs) &&
- inList("libc", linker.Properties.System_shared_libs) {
- linker.Properties.System_shared_libs = append(linker.Properties.System_shared_libs,
- "libdl")
+ if inList("libdl", deps.SharedLibs) {
+ // If system_shared_libs has libc but not libdl, make sure shared_libs does not
+ // have libdl to avoid loading libdl before libc.
+ if inList("libc", systemSharedLibs) {
+ if !inList("libdl", systemSharedLibs) {
+ ctx.PropertyErrorf("shared_libs",
+ "libdl must be in system_shared_libs, not shared_libs")
+ }
+ _, deps.SharedLibs = removeFromList("libdl", deps.SharedLibs)
}
- deps.LateSharedLibs = append(deps.LateSharedLibs,
- linker.Properties.System_shared_libs...)
- } else if !ctx.sdk() && !ctx.vndk() {
- deps.LateSharedLibs = append(deps.LateSharedLibs, "libc", "libm", "libdl")
}
- }
- if ctx.sdk() {
- deps.SharedLibs = append(deps.SharedLibs,
- "libc",
- "libm",
- "libdl",
- )
- }
- if ctx.vndk() {
+ // If libc and libdl are both in system_shared_libs make sure libd comes after libc
+ // to avoid loading libdl before libc.
+ if inList("libdl", systemSharedLibs) && inList("libc", systemSharedLibs) &&
+ indexList("libdl", systemSharedLibs) < indexList("libc", systemSharedLibs) {
+ ctx.PropertyErrorf("system_shared_libs", "libdl must be after libc")
+ }
+
+ deps.LateSharedLibs = append(deps.LateSharedLibs, systemSharedLibs...)
+ } else if ctx.sdk() || ctx.vndk() {
deps.LateSharedLibs = append(deps.LateSharedLibs, "libc", "libm", "libdl")
}
}
diff --git a/cc/sanitize.go b/cc/sanitize.go
index 4ea4d26..0409674 100644
--- a/cc/sanitize.go
+++ b/cc/sanitize.go
@@ -264,9 +264,6 @@
if Bool(sanitize.Properties.Sanitize.Address) {
deps.StaticLibs = append(deps.StaticLibs, asanLibs...)
}
- if Bool(sanitize.Properties.Sanitize.Address) || Bool(sanitize.Properties.Sanitize.Thread) {
- deps.SharedLibs = append(deps.SharedLibs, "libdl")
- }
}
return deps
diff --git a/cc/stl.go b/cc/stl.go
index 65d7e40..a123d77 100644
--- a/cc/stl.go
+++ b/cc/stl.go
@@ -107,8 +107,6 @@
}
if ctx.staticBinary() {
deps.StaticLibs = append(deps.StaticLibs, "libm", "libc", "libdl")
- } else {
- deps.SharedLibs = append(deps.SharedLibs, "libdl")
}
}
case "":
@@ -118,15 +116,9 @@
// The system STL doesn't have a prebuilt (it uses the system's libstdc++), but it does have
// its own includes. The includes are handled in CCBase.Flags().
deps.SharedLibs = append([]string{"libstdc++"}, deps.SharedLibs...)
- case "ndk_libc++_shared":
- deps.SharedLibs = append(deps.SharedLibs, stl.Properties.SelectedStl,
- "libdl")
- case "ndk_libc++_static":
- deps.StaticLibs = append(deps.StaticLibs, stl.Properties.SelectedStl)
- deps.SharedLibs = append(deps.SharedLibs, "libdl")
- case "ndk_libstlport_shared":
+ case "ndk_libc++_shared", "ndk_libstlport_shared":
deps.SharedLibs = append(deps.SharedLibs, stl.Properties.SelectedStl)
- case "ndk_libstlport_static", "ndk_libgnustl_static":
+ case "ndk_libc++_static", "ndk_libstlport_static", "ndk_libgnustl_static":
deps.StaticLibs = append(deps.StaticLibs, stl.Properties.SelectedStl)
default:
panic(fmt.Errorf("Unknown stl: %q", stl.Properties.SelectedStl))
diff --git a/finder/finder.go b/finder/finder.go
index 8f9496d..ffda155 100644
--- a/finder/finder.go
+++ b/finder/finder.go
@@ -18,6 +18,7 @@
"bufio"
"bytes"
"encoding/json"
+ "errors"
"fmt"
"io"
"os"
@@ -30,7 +31,6 @@
"time"
"android/soong/fs"
- "errors"
)
// This file provides a Finder struct that can quickly search for files satisfying
@@ -159,11 +159,17 @@
nodes pathMap
}
+var defaultNumThreads = runtime.NumCPU() * 2
+
// New creates a new Finder for use
func New(cacheParams CacheParams, filesystem fs.FileSystem,
logger Logger, dbPath string) (f *Finder, err error) {
+ return newImpl(cacheParams, filesystem, logger, dbPath, defaultNumThreads)
+}
- numThreads := runtime.NumCPU() * 2
+// newImpl is like New but accepts more params
+func newImpl(cacheParams CacheParams, filesystem fs.FileSystem,
+ logger Logger, dbPath string, numThreads int) (f *Finder, err error) {
numDbLoadingThreads := numThreads
numSearchingThreads := numThreads
@@ -661,6 +667,9 @@
for _, info := range infos {
for !strings.HasPrefix(info.P+"/", prefix+"/") {
prefix = filepath.Dir(prefix)
+ if prefix == "/" {
+ break
+ }
}
}
// remove common prefix
diff --git a/finder/finder_test.go b/finder/finder_test.go
index 8d1bbd7..1522c68 100644
--- a/finder/finder_test.go
+++ b/finder/finder_test.go
@@ -35,14 +35,18 @@
}
func newFinder(t *testing.T, filesystem *fs.MockFs, cacheParams CacheParams) *Finder {
- f, err := newFinderAndErr(t, filesystem, cacheParams)
+ return newFinderWithNumThreads(t, filesystem, cacheParams, 2)
+}
+
+func newFinderWithNumThreads(t *testing.T, filesystem *fs.MockFs, cacheParams CacheParams, numThreads int) *Finder {
+ f, err := newFinderAndErr(t, filesystem, cacheParams, numThreads)
if err != nil {
fatal(t, err.Error())
}
return f
}
-func newFinderAndErr(t *testing.T, filesystem *fs.MockFs, cacheParams CacheParams) (*Finder, error) {
+func newFinderAndErr(t *testing.T, filesystem *fs.MockFs, cacheParams CacheParams, numThreads int) (*Finder, error) {
cachePath := "/finder/finder-db"
cacheDir := filepath.Dir(cachePath)
filesystem.MkDirs(cacheDir)
@@ -51,7 +55,7 @@
}
logger := log.New(ioutil.Discard, "", 0)
- f, err := New(cacheParams, filesystem, logger, cachePath)
+ f, err := newImpl(cacheParams, filesystem, logger, cachePath, numThreads)
return f, err
}
@@ -64,11 +68,13 @@
}
func finderAndErrorWithSameParams(t *testing.T, original *Finder) (*Finder, error) {
- f, err := New(
+ f, err := newImpl(
original.cacheMetadata.Config.CacheParams,
original.filesystem,
original.logger,
- original.DbPath)
+ original.DbPath,
+ original.numDbLoadingThreads,
+ )
return f, err
}
@@ -234,6 +240,21 @@
assertSameResponse(t, foundPaths, absoluteMatches)
}
+// testAgainstSeveralThreadcounts runs the given test for each threadcount that we care to test
+func testAgainstSeveralThreadcounts(t *testing.T, tester func(t *testing.T, numThreads int)) {
+ // test singlethreaded, multithreaded, and also using the same number of threads as
+ // will be used on the current system
+ threadCounts := []int{1, 2, defaultNumThreads}
+ for _, numThreads := range threadCounts {
+ testName := fmt.Sprintf("%v threads", numThreads)
+ // store numThreads in a new variable to prevent numThreads from changing in each loop
+ localNumThreads := numThreads
+ t.Run(testName, func(t *testing.T) {
+ tester(t, localNumThreads)
+ })
+ }
+}
+
// end of utils, start of individual tests
func TestSingleFile(t *testing.T) {
@@ -285,24 +306,30 @@
}
func TestFilesystemRoot(t *testing.T) {
- filesystem := newFs()
- root := "/"
- createdPath := "/findme.txt"
- create(t, createdPath, filesystem)
- finder := newFinder(
- t,
- filesystem,
- CacheParams{
- RootDirs: []string{root},
- IncludeFiles: []string{"findme.txt", "skipme.txt"},
- },
- )
- defer finder.Shutdown()
+ testWithNumThreads := func(t *testing.T, numThreads int) {
+ filesystem := newFs()
+ root := "/"
+ createdPath := "/findme.txt"
+ create(t, createdPath, filesystem)
- foundPaths := finder.FindNamedAt(root, "findme.txt")
+ finder := newFinderWithNumThreads(
+ t,
+ filesystem,
+ CacheParams{
+ RootDirs: []string{root},
+ IncludeFiles: []string{"findme.txt", "skipme.txt"},
+ },
+ numThreads,
+ )
+ defer finder.Shutdown()
- assertSameResponse(t, foundPaths, []string{createdPath})
+ foundPaths := finder.FindNamedAt(root, "findme.txt")
+
+ assertSameResponse(t, foundPaths, []string{createdPath})
+ }
+
+ testAgainstSeveralThreadcounts(t, testWithNumThreads)
}
func TestNonexistentDir(t *testing.T) {
@@ -316,6 +343,7 @@
RootDirs: []string{"/tmp/IDontExist"},
IncludeFiles: []string{"findme.txt", "skipme.txt"},
},
+ 1,
)
if err == nil {
fatal(t, "Did not fail when given a nonexistent root directory")
@@ -380,6 +408,8 @@
"/tmp/include/findme.txt"})
}
+// TestRootDir tests that the value of RootDirs is used
+// tests of the filesystem root are in TestFilesystemRoot
func TestRootDir(t *testing.T) {
filesystem := newFs()
create(t, "/tmp/a/findme.txt", filesystem)
@@ -548,48 +578,54 @@
}
func TestConcurrentFindSameDirectory(t *testing.T) {
- filesystem := newFs()
- // create a bunch of files and directories
- paths := []string{}
- for i := 0; i < 10; i++ {
- parentDir := fmt.Sprintf("/tmp/%v", i)
- for j := 0; j < 10; j++ {
- filePath := filepath.Join(parentDir, fmt.Sprintf("%v/findme.txt", j))
- paths = append(paths, filePath)
+ testWithNumThreads := func(t *testing.T, numThreads int) {
+ filesystem := newFs()
+
+ // create a bunch of files and directories
+ paths := []string{}
+ for i := 0; i < 10; i++ {
+ parentDir := fmt.Sprintf("/tmp/%v", i)
+ for j := 0; j < 10; j++ {
+ filePath := filepath.Join(parentDir, fmt.Sprintf("%v/findme.txt", j))
+ paths = append(paths, filePath)
+ }
+ }
+ sort.Strings(paths)
+ for _, path := range paths {
+ create(t, path, filesystem)
+ }
+
+ // set up a finder
+ finder := newFinderWithNumThreads(
+ t,
+ filesystem,
+ CacheParams{
+ RootDirs: []string{"/tmp"},
+ IncludeFiles: []string{"findme.txt"},
+ },
+ numThreads,
+ )
+ defer finder.Shutdown()
+
+ numTests := 20
+ results := make(chan []string, numTests)
+ // make several parallel calls to the finder
+ for i := 0; i < numTests; i++ {
+ go func() {
+ foundPaths := finder.FindNamedAt("/tmp", "findme.txt")
+ results <- foundPaths
+ }()
+ }
+
+ // check that each response was correct
+ for i := 0; i < numTests; i++ {
+ foundPaths := <-results
+ assertSameResponse(t, foundPaths, paths)
}
}
- sort.Strings(paths)
- for _, path := range paths {
- create(t, path, filesystem)
- }
- // set up a finder
- finder := newFinder(
- t,
- filesystem,
- CacheParams{
- RootDirs: []string{"/tmp"},
- IncludeFiles: []string{"findme.txt"},
- },
- )
- defer finder.Shutdown()
-
- numTests := 20
- results := make(chan []string, numTests)
- // make several parallel calls to the finder
- for i := 0; i < numTests; i++ {
- go func() {
- foundPaths := finder.FindNamedAt("/tmp", "findme.txt")
- results <- foundPaths
- }()
- }
-
- // check that each response was correct
- for i := 0; i < numTests; i++ {
- foundPaths := <-results
- assertSameResponse(t, foundPaths, paths)
- }
+ testAgainstSeveralThreadcounts(t, testWithNumThreads)
}
func TestConcurrentFindDifferentDirectories(t *testing.T) {
diff --git a/ui/build/kati.go b/ui/build/kati.go
index 48c38d4..cc02c76 100644
--- a/ui/build/kati.go
+++ b/ui/build/kati.go
@@ -59,11 +59,13 @@
}
func runKati(ctx Context, config Config) {
+ genKatiSuffix(ctx, config)
+
+ runKatiCleanSpec(ctx, config)
+
ctx.BeginTrace("kati")
defer ctx.EndTrace()
- genKatiSuffix(ctx, config)
-
executable := config.PrebuiltBuildTool("ckati")
args := []string{
"--ninja",
@@ -101,9 +103,6 @@
}
cmd.Stderr = cmd.Stdout
- // Kati leaks memory, so ensure leak detection is turned off
- cmd.Environment.Set("ASAN_OPTIONS", "detect_leaks=0")
-
cmd.StartOrFatal()
katiRewriteOutput(ctx, pipe)
cmd.WaitOrFatal()
@@ -162,3 +161,33 @@
fmt.Fprintln(ctx.Stdout())
}
}
+
+func runKatiCleanSpec(ctx Context, config Config) {
+ ctx.BeginTrace("kati cleanspec")
+ defer ctx.EndTrace()
+
+ executable := config.PrebuiltBuildTool("ckati")
+ args := []string{
+ "--ninja",
+ "--ninja_dir=" + config.OutDir(),
+ "--ninja_suffix=" + config.KatiSuffix() + "-cleanspec",
+ "--regen",
+ "--detect_android_echo",
+ "--color_warnings",
+ "--gen_all_targets",
+ "--werror_find_emulator",
+ "--use_find_emulator",
+ "-f", "build/make/core/cleanbuild.mk",
+ "BUILDING_WITH_NINJA=true",
+ "SOONG_MAKEVARS_MK=" + config.SoongMakeVarsMk(),
+ }
+
+ cmd := Command(ctx, config, "ckati", executable, args...)
+ cmd.Sandbox = katiCleanSpecSandbox
+ cmd.Stdout = ctx.Stdout()
+ cmd.Stderr = ctx.Stderr()
+
+ // Kati leaks memory, so ensure leak detection is turned off
+ cmd.Environment.Set("ASAN_OPTIONS", "detect_leaks=0")
+ cmd.RunOrFatal()
+}
diff --git a/ui/build/sandbox_darwin.go b/ui/build/sandbox_darwin.go
index 54c145c..60407d4 100644
--- a/ui/build/sandbox_darwin.go
+++ b/ui/build/sandbox_darwin.go
@@ -22,11 +22,12 @@
type Sandbox string
const (
- noSandbox = ""
- globalSandbox = "build/soong/ui/build/sandbox/darwin/global.sb"
- makeSandbox = globalSandbox
- soongSandbox = globalSandbox
- katiSandbox = globalSandbox
+ noSandbox = ""
+ globalSandbox = "build/soong/ui/build/sandbox/darwin/global.sb"
+ makeSandbox = globalSandbox
+ soongSandbox = globalSandbox
+ katiSandbox = globalSandbox
+ katiCleanSpecSandbox = globalSandbox
)
var sandboxExecPath string
diff --git a/ui/build/sandbox_linux.go b/ui/build/sandbox_linux.go
index fb48b9c..6615d37 100644
--- a/ui/build/sandbox_linux.go
+++ b/ui/build/sandbox_linux.go
@@ -17,11 +17,12 @@
type Sandbox bool
const (
- noSandbox = false
- globalSandbox = false
- makeSandbox = false
- soongSandbox = false
- katiSandbox = false
+ noSandbox = false
+ globalSandbox = false
+ makeSandbox = false
+ soongSandbox = false
+ katiSandbox = false
+ katiCleanSpecSandbox = false
)
func (c *Cmd) sandboxSupported() bool {