Merge "Support LLD ThinLTO cache/threshold option"
diff --git a/androidmk/cmd/androidmk/android.go b/androidmk/cmd/androidmk/android.go
index 9276eb5..52bcf9c 100644
--- a/androidmk/cmd/androidmk/android.go
+++ b/androidmk/cmd/androidmk/android.go
@@ -201,6 +201,7 @@
"LOCAL_DEX_PREOPT_GENERATE_PROFILE": "dex_preopt.profile_guided",
"LOCAL_PRIVATE_PLATFORM_APIS": "platform_apis",
+ "LOCAL_JETIFIER_ENABLED": "jetifier",
})
}
diff --git a/androidmk/cmd/androidmk/androidmk_test.go b/androidmk/cmd/androidmk/androidmk_test.go
index b2c3fab..f2dc6ff 100644
--- a/androidmk/cmd/androidmk/androidmk_test.go
+++ b/androidmk/cmd/androidmk/androidmk_test.go
@@ -631,12 +631,14 @@
LOCAL_SRC_FILES := test.jar
LOCAL_MODULE_CLASS := JAVA_LIBRARIES
LOCAL_STATIC_ANDROID_LIBRARIES :=
+ LOCAL_JETIFIER_ENABLED := true
include $(BUILD_PREBUILT)
`,
expected: `
java_import {
jars: ["test.jar"],
+ jetifier: true,
}
`,
},
diff --git a/cc/stl.go b/cc/stl.go
index 5e61e1e..e59f677 100644
--- a/cc/stl.go
+++ b/cc/stl.go
@@ -66,7 +66,7 @@
}
if ctx.useSdk() && ctx.Device() {
switch s {
- case "":
+ case "", "system":
return "ndk_system"
case "c++_shared", "c++_static":
return "ndk_lib" + s
diff --git a/cc/test.go b/cc/test.go
index c3fadbd..045cc4f 100644
--- a/cc/test.go
+++ b/cc/test.go
@@ -30,6 +30,12 @@
Isolated *bool
}
+// Test option struct.
+type TestOptions struct {
+ // The UID that you want to run the test as on a device.
+ Run_test_as *string
+}
+
type TestBinaryProperties struct {
// Create a separate binary for each source file. Useful when there is
// global state that can not be torn down and reset between each test suite.
@@ -55,6 +61,9 @@
// the name of the test configuration template (for example "AndroidTestTemplate.xml") that
// should be installed with the module.
Test_config_template *string `android:"path,arch_variant"`
+
+ // Test options.
+ Test_options TestOptions
}
func init() {
@@ -258,6 +267,11 @@
if Bool(test.testDecorator.Properties.Isolated) {
optionsMap["not-shardable"] = "true"
}
+
+ if test.Properties.Test_options.Run_test_as != nil {
+ optionsMap["run-test-as"] = String(test.Properties.Test_options.Run_test_as)
+ }
+
test.testConfig = tradefed.AutoGenNativeTestConfig(ctx, test.Properties.Test_config,
test.Properties.Test_config_template,
test.Properties.Test_suites, optionsMap)
diff --git a/java/aar.go b/java/aar.go
index ba9e187..a993bf6 100644
--- a/java/aar.go
+++ b/java/aar.go
@@ -446,7 +446,7 @@
Libs []string
// if set to true, run Jetifier against .aar file. Defaults to false.
- Jetifier_enabled *bool
+ Jetifier *bool
}
type AARImport struct {
@@ -540,7 +540,7 @@
aarName := ctx.ModuleName() + ".aar"
var aar android.Path
aar = android.PathForModuleSrc(ctx, a.properties.Aars[0])
- if Bool(a.properties.Jetifier_enabled) {
+ if Bool(a.properties.Jetifier) {
inputFile := aar
aar = android.PathForModuleOut(ctx, "jetifier", aarName)
TransformJetifier(ctx, aar.(android.WritablePath), inputFile)
diff --git a/java/java.go b/java/java.go
index 3eae932..1fd0a9e 100644
--- a/java/java.go
+++ b/java/java.go
@@ -1726,7 +1726,7 @@
Exclude_dirs []string
// if set to true, run Jetifier against .jar file. Defaults to false.
- Jetifier_enabled *bool
+ Jetifier *bool
}
type Import struct {
@@ -1771,7 +1771,7 @@
outputFile := android.PathForModuleOut(ctx, "combined", jarName)
TransformJarsToJar(ctx, outputFile, "for prebuilts", jars, android.OptionalPath{},
false, j.properties.Exclude_files, j.properties.Exclude_dirs)
- if Bool(j.properties.Jetifier_enabled) {
+ if Bool(j.properties.Jetifier) {
inputFile := outputFile
outputFile = android.PathForModuleOut(ctx, "jetifier", jarName)
TransformJetifier(ctx, outputFile, inputFile)
diff --git a/java/jdeps.go b/java/jdeps.go
index 2eaeab8..18498be 100644
--- a/java/jdeps.go
+++ b/java/jdeps.go
@@ -51,6 +51,10 @@
moduleInfos := make(map[string]android.IdeInfo)
ctx.VisitAllModules(func(module android.Module) {
+ if !module.Enabled() {
+ return
+ }
+
ideInfoProvider, ok := module.(android.IDEInfo)
if !ok {
return
diff --git a/java/prebuilt_apis.go b/java/prebuilt_apis.go
index 02b9b45..c370811 100644
--- a/java/prebuilt_apis.go
+++ b/java/prebuilt_apis.go
@@ -22,13 +22,6 @@
"github.com/google/blueprint/proptools"
)
-// prebuilt_apis is a meta-module that generates filegroup modules for all
-// API txt files found under the directory where the Android.bp is located.
-// Specificaly, an API file located at ./<ver>/<scope>/api/<module>.txt
-// generates a filegroup module named <module>-api.<scope>.<ver>.
-//
-// It also creates <module>-api.<scope>.latest for the lastest <ver>.
-//
func init() {
android.RegisterModuleType("prebuilt_apis", PrebuiltApisFactory)
@@ -188,6 +181,12 @@
}
}
+// prebuilt_apis is a meta-module that generates filegroup modules for all
+// API txt files found under the directory where the Android.bp is located.
+// Specifically, an API file located at ./<ver>/<scope>/api/<module>.txt
+// generates a filegroup module named <module>-api.<scope>.<ver>.
+//
+// It also creates <module>-api.<scope>.latest for the latest <ver>.
func PrebuiltApisFactory() android.Module {
module := &prebuiltApis{}
module.AddProperties(&module.properties)
diff --git a/ui/build/ninja.go b/ui/build/ninja.go
index cb41579..7994f3a 100644
--- a/ui/build/ninja.go
+++ b/ui/build/ninja.go
@@ -31,7 +31,8 @@
defer ctx.EndTrace()
fifo := filepath.Join(config.OutDir(), ".ninja_fifo")
- status.NinjaReader(ctx, ctx.Status.StartTool(), fifo)
+ nr := status.NewNinjaReader(ctx, ctx.Status.StartTool(), fifo)
+ defer nr.Close()
executable := config.PrebuiltBuildTool("ninja")
args := []string{
diff --git a/ui/build/soong.go b/ui/build/soong.go
index c89f0d5..2ce1ac9 100644
--- a/ui/build/soong.go
+++ b/ui/build/soong.go
@@ -109,7 +109,8 @@
defer ctx.EndTrace()
fifo := filepath.Join(config.OutDir(), ".ninja_fifo")
- status.NinjaReader(ctx, ctx.Status.StartTool(), fifo)
+ nr := status.NewNinjaReader(ctx, ctx.Status.StartTool(), fifo)
+ defer nr.Close()
cmd := Command(ctx, config, "soong "+name,
config.PrebuiltBuildTool("ninja"),
diff --git a/ui/logger/logger.go b/ui/logger/logger.go
index 58890e9..9b26ae8 100644
--- a/ui/logger/logger.go
+++ b/ui/logger/logger.go
@@ -180,12 +180,16 @@
return s
}
+type panicWriter struct{}
+
+func (panicWriter) Write([]byte) (int, error) { panic("write to panicWriter") }
+
// Close disables logging to the file and closes the file handle.
func (s *stdLogger) Close() {
s.mutex.Lock()
defer s.mutex.Unlock()
if s.file != nil {
- s.fileLogger.SetOutput(ioutil.Discard)
+ s.fileLogger.SetOutput(panicWriter{})
s.file.Close()
s.file = nil
}
diff --git a/ui/status/Android.bp b/ui/status/Android.bp
index 76caaef..901a713 100644
--- a/ui/status/Android.bp
+++ b/ui/status/Android.bp
@@ -28,6 +28,7 @@
],
testSrcs: [
"kati_test.go",
+ "ninja_test.go",
"status_test.go",
],
}
diff --git a/ui/status/ninja.go b/ui/status/ninja.go
index 4ceb5ef..ee2a2da 100644
--- a/ui/status/ninja.go
+++ b/ui/status/ninja.go
@@ -20,6 +20,7 @@
"io"
"os"
"syscall"
+ "time"
"github.com/golang/protobuf/proto"
@@ -27,9 +28,9 @@
"android/soong/ui/status/ninja_frontend"
)
-// NinjaReader reads the protobuf frontend format from ninja and translates it
+// NewNinjaReader reads the protobuf frontend format from ninja and translates it
// into calls on the ToolStatus API.
-func NinjaReader(ctx logger.Logger, status ToolStatus, fifo string) {
+func NewNinjaReader(ctx logger.Logger, status ToolStatus, fifo string) *NinjaReader {
os.Remove(fifo)
err := syscall.Mkfifo(fifo, 0666)
@@ -37,14 +38,69 @@
ctx.Fatalf("Failed to mkfifo(%q): %v", fifo, err)
}
- go ninjaReader(status, fifo)
+ n := &NinjaReader{
+ status: status,
+ fifo: fifo,
+ done: make(chan bool),
+ cancel: make(chan bool),
+ }
+
+ go n.run()
+
+ return n
}
-func ninjaReader(status ToolStatus, fifo string) {
- f, err := os.Open(fifo)
- if err != nil {
- status.Error(fmt.Sprintf("Failed to open fifo: %v", err))
+type NinjaReader struct {
+ status ToolStatus
+ fifo string
+ done chan bool
+ cancel chan bool
+}
+
+const NINJA_READER_CLOSE_TIMEOUT = 5 * time.Second
+
+// Close waits for NinjaReader to finish reading from the fifo, or 5 seconds.
+func (n *NinjaReader) Close() {
+ // Signal the goroutine to stop if it is blocking opening the fifo.
+ close(n.cancel)
+
+ timeoutCh := time.After(NINJA_READER_CLOSE_TIMEOUT)
+
+ select {
+ case <-n.done:
+ // Nothing
+ case <-timeoutCh:
+ n.status.Error(fmt.Sprintf("ninja fifo didn't finish after %s", NINJA_READER_CLOSE_TIMEOUT.String()))
}
+
+ return
+}
+
+func (n *NinjaReader) run() {
+ defer close(n.done)
+
+ // Opening the fifo can block forever if ninja never opens the write end, do it in a goroutine so this
+ // method can exit on cancel.
+ fileCh := make(chan *os.File)
+ go func() {
+ f, err := os.Open(n.fifo)
+ if err != nil {
+ n.status.Error(fmt.Sprintf("Failed to open fifo: %v", err))
+ close(fileCh)
+ return
+ }
+ fileCh <- f
+ }()
+
+ var f *os.File
+
+ select {
+ case f = <-fileCh:
+ // Nothing
+ case <-n.cancel:
+ return
+ }
+
defer f.Close()
r := bufio.NewReader(f)
@@ -55,7 +111,7 @@
size, err := readVarInt(r)
if err != nil {
if err != io.EOF {
- status.Error(fmt.Sprintf("Got error reading from ninja: %s", err))
+ n.status.Error(fmt.Sprintf("Got error reading from ninja: %s", err))
}
return
}
@@ -64,9 +120,9 @@
_, err = io.ReadFull(r, buf)
if err != nil {
if err == io.EOF {
- status.Print(fmt.Sprintf("Missing message of size %d from ninja\n", size))
+ n.status.Print(fmt.Sprintf("Missing message of size %d from ninja\n", size))
} else {
- status.Error(fmt.Sprintf("Got error reading from ninja: %s", err))
+ n.status.Error(fmt.Sprintf("Got error reading from ninja: %s", err))
}
return
}
@@ -74,13 +130,13 @@
msg := &ninja_frontend.Status{}
err = proto.Unmarshal(buf, msg)
if err != nil {
- status.Print(fmt.Sprintf("Error reading message from ninja: %v", err))
+ n.status.Print(fmt.Sprintf("Error reading message from ninja: %v", err))
continue
}
// Ignore msg.BuildStarted
if msg.TotalEdges != nil {
- status.SetTotalActions(int(msg.TotalEdges.GetTotalEdges()))
+ n.status.SetTotalActions(int(msg.TotalEdges.GetTotalEdges()))
}
if msg.EdgeStarted != nil {
action := &Action{
@@ -88,7 +144,7 @@
Outputs: msg.EdgeStarted.Outputs,
Command: msg.EdgeStarted.GetCommand(),
}
- status.StartAction(action)
+ n.status.StartAction(action)
running[msg.EdgeStarted.GetId()] = action
}
if msg.EdgeFinished != nil {
@@ -101,7 +157,7 @@
err = fmt.Errorf("exited with code: %d", exitCode)
}
- status.FinishAction(ActionResult{
+ n.status.FinishAction(ActionResult{
Action: started,
Output: msg.EdgeFinished.GetOutput(),
Error: err,
@@ -112,17 +168,17 @@
message := "ninja: " + msg.Message.GetMessage()
switch msg.Message.GetLevel() {
case ninja_frontend.Status_Message_INFO:
- status.Status(message)
+ n.status.Status(message)
case ninja_frontend.Status_Message_WARNING:
- status.Print("warning: " + message)
+ n.status.Print("warning: " + message)
case ninja_frontend.Status_Message_ERROR:
- status.Error(message)
+ n.status.Error(message)
default:
- status.Print(message)
+ n.status.Print(message)
}
}
if msg.BuildFinished != nil {
- status.Finish()
+ n.status.Finish()
}
}
}
diff --git a/ui/status/ninja_test.go b/ui/status/ninja_test.go
new file mode 100644
index 0000000..c400c97
--- /dev/null
+++ b/ui/status/ninja_test.go
@@ -0,0 +1,45 @@
+// Copyright 2019 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 status
+
+import (
+ "io/ioutil"
+ "os"
+ "path/filepath"
+ "testing"
+ "time"
+
+ "android/soong/ui/logger"
+)
+
+// Tests that closing the ninja reader when nothing has opened the other end of the fifo is fast.
+func TestNinjaReader_Close(t *testing.T) {
+ tempDir, err := ioutil.TempDir("", "ninja_test")
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer os.RemoveAll(tempDir)
+
+ stat := &Status{}
+ nr := NewNinjaReader(logger.New(ioutil.Discard), stat.StartTool(), filepath.Join(tempDir, "fifo"))
+
+ start := time.Now()
+
+ nr.Close()
+
+ if g, w := time.Since(start), NINJA_READER_CLOSE_TIMEOUT; g >= w {
+ t.Errorf("nr.Close timed out, %s > %s", g, w)
+ }
+}