Make it possible to debug soong_ui.
This works by setting the SOONG_UI_DELVE= environment variable to the port on which soong_ui should accept a Delve connection on. This is achieved by reusing the Delve execution logic between soong_ui and soong_build. Test: Manual. Change-Id: Id2c1d4b6faac1a4a3918c91030ce2239f7daf54f
This commit is contained in:
parent
6d3e726887
commit
7d613bfe2c
6 changed files with 69 additions and 63 deletions
|
@ -15,11 +15,6 @@
|
|||
package android
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
"syscall"
|
||||
|
||||
"android/soong/shared"
|
||||
)
|
||||
|
||||
|
@ -31,9 +26,6 @@ import (
|
|||
// a manifest regeneration.
|
||||
|
||||
var originalEnv map[string]string
|
||||
var soongDelveListen string
|
||||
var soongDelvePath string
|
||||
var isDebugging bool
|
||||
|
||||
func InitEnvironment(envFile string) {
|
||||
var err error
|
||||
|
@ -41,51 +33,6 @@ func InitEnvironment(envFile string) {
|
|||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
soongDelveListen = originalEnv["SOONG_DELVE"]
|
||||
soongDelvePath = originalEnv["SOONG_DELVE_PATH"]
|
||||
}
|
||||
|
||||
// Returns whether the current process is running under Delve due to
|
||||
// ReexecWithDelveMaybe().
|
||||
func IsDebugging() bool {
|
||||
return isDebugging
|
||||
}
|
||||
func ReexecWithDelveMaybe() {
|
||||
isDebugging = os.Getenv("SOONG_DELVE_REEXECUTED") == "true"
|
||||
if isDebugging || soongDelveListen == "" {
|
||||
return
|
||||
}
|
||||
|
||||
if soongDelvePath == "" {
|
||||
fmt.Fprintln(os.Stderr, "SOONG_DELVE is set but failed to find dlv")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
soongDelveEnv := []string{}
|
||||
for _, env := range os.Environ() {
|
||||
idx := strings.IndexRune(env, '=')
|
||||
if idx != -1 {
|
||||
soongDelveEnv = append(soongDelveEnv, env)
|
||||
}
|
||||
}
|
||||
|
||||
soongDelveEnv = append(soongDelveEnv, "SOONG_DELVE_REEXECUTED=true")
|
||||
|
||||
dlvArgv := []string{
|
||||
soongDelvePath,
|
||||
"--listen=:" + soongDelveListen,
|
||||
"--headless=true",
|
||||
"--api-version=2",
|
||||
"exec",
|
||||
os.Args[0],
|
||||
"--",
|
||||
}
|
||||
dlvArgv = append(dlvArgv, os.Args[1:]...)
|
||||
os.Chdir(absSrcDir)
|
||||
syscall.Exec(soongDelvePath, dlvArgv, soongDelveEnv)
|
||||
fmt.Fprintln(os.Stderr, "exec() failed while trying to reexec with Delve")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
func EnvSingleton() Singleton {
|
||||
|
|
|
@ -66,7 +66,9 @@ func (c *docsSingleton) GenerateBuildActions(ctx SingletonContext) {
|
|||
soongDocs := ctx.Rule(pctx, "soongDocs",
|
||||
blueprint.RuleParams{
|
||||
Command: fmt.Sprintf("rm -f ${outDir}/* && %s --soong_docs %s %s",
|
||||
primaryBuilder.String(), docsFile.String(), strings.Join(os.Args[1:], " ")),
|
||||
primaryBuilder.String(),
|
||||
docsFile.String(),
|
||||
"\""+strings.Join(os.Args[1:], "\" \"")+"\""),
|
||||
CommandDeps: []string{primaryBuilder.String()},
|
||||
Description: fmt.Sprintf("%s docs $out", primaryBuilder.Base()),
|
||||
},
|
||||
|
|
|
@ -33,11 +33,15 @@ var (
|
|||
outDir string
|
||||
docFile string
|
||||
bazelQueryViewDir string
|
||||
delveListen string
|
||||
delvePath string
|
||||
)
|
||||
|
||||
func init() {
|
||||
flag.StringVar(&topDir, "top", "", "Top directory of the Android source tree")
|
||||
flag.StringVar(&outDir, "out", "", "Soong output directory (usually $TOP/out/soong)")
|
||||
flag.StringVar(&delveListen, "delve_listen", "", "Delve port to listen on for debugging")
|
||||
flag.StringVar(&delvePath, "delve_path", "", "Path to Delve. Only used if --delve_listen is set")
|
||||
flag.StringVar(&docFile, "soong_docs", "", "build documentation file to output")
|
||||
flag.StringVar(&bazelQueryViewDir, "bazel_queryview_dir", "", "path to the bazel queryview directory")
|
||||
}
|
||||
|
@ -87,9 +91,9 @@ func newConfig(srcDir string) android.Config {
|
|||
func main() {
|
||||
flag.Parse()
|
||||
|
||||
shared.ReexecWithDelveMaybe(delveListen, delvePath)
|
||||
android.InitSandbox(topDir)
|
||||
android.InitEnvironment(shared.JoinPath(topDir, outDir, "soong.environment.available"))
|
||||
android.ReexecWithDelveMaybe()
|
||||
|
||||
// The top-level Blueprints file is passed as the first argument.
|
||||
srcDir := filepath.Dir(flag.Arg(0))
|
||||
|
@ -101,9 +105,7 @@ func main() {
|
|||
// user sets SOONG_DELVE the first time.
|
||||
configuration.Getenv("SOONG_DELVE")
|
||||
configuration.Getenv("SOONG_DELVE_PATH")
|
||||
// Read the SOONG_DELVE again through configuration so that there is a dependency on the environment variable
|
||||
// and soong_build will rerun when it is set for the first time.
|
||||
if listen := configuration.Getenv("SOONG_DELVE"); listen != "" {
|
||||
if shared.IsDebugging() {
|
||||
// Add a non-existent file to the dependencies so that soong_build will rerun when the debugger is
|
||||
// enabled even if it completed successfully.
|
||||
extraNinjaDeps = append(extraNinjaDeps, filepath.Join(configuration.BuildDir(), "always_rerun_for_delve"))
|
||||
|
|
|
@ -25,6 +25,7 @@ import (
|
|||
"strings"
|
||||
"time"
|
||||
|
||||
"android/soong/shared"
|
||||
"android/soong/ui/build"
|
||||
"android/soong/ui/logger"
|
||||
"android/soong/ui/metrics"
|
||||
|
@ -118,6 +119,8 @@ func inList(s string, list []string) bool {
|
|||
// Command is the type of soong_ui execution. Only one type of
|
||||
// execution is specified. The args are specific to the command.
|
||||
func main() {
|
||||
shared.ReexecWithDelveMaybe(os.Getenv("SOONG_UI_DELVE"), shared.ResolveDelveBinary())
|
||||
|
||||
buildStarted := time.Now()
|
||||
|
||||
c, args, err := getCommand(os.Args)
|
||||
|
|
|
@ -1,8 +1,15 @@
|
|||
package shared
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strings"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
var (
|
||||
isDebugging bool
|
||||
)
|
||||
|
||||
// Finds the Delve binary to use. Either uses the SOONG_DELVE_PATH environment
|
||||
|
@ -15,3 +22,48 @@ func ResolveDelveBinary() string {
|
|||
|
||||
return result
|
||||
}
|
||||
|
||||
// Returns whether the current process is running under Delve due to
|
||||
// ReexecWithDelveMaybe().
|
||||
func IsDebugging() bool {
|
||||
return isDebugging
|
||||
}
|
||||
|
||||
// Re-executes the binary in question under the control of Delve when
|
||||
// delveListen is not the empty string. delvePath gives the path to the Delve.
|
||||
func ReexecWithDelveMaybe(delveListen, delvePath string) {
|
||||
isDebugging = os.Getenv("SOONG_DELVE_REEXECUTED") == "true"
|
||||
if isDebugging || delveListen == "" {
|
||||
return
|
||||
}
|
||||
|
||||
if delvePath == "" {
|
||||
fmt.Fprintln(os.Stderr, "Delve debugging requested but failed to find dlv")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
soongDelveEnv := []string{}
|
||||
for _, env := range os.Environ() {
|
||||
idx := strings.IndexRune(env, '=')
|
||||
if idx != -1 {
|
||||
soongDelveEnv = append(soongDelveEnv, env)
|
||||
}
|
||||
}
|
||||
|
||||
soongDelveEnv = append(soongDelveEnv, "SOONG_DELVE_REEXECUTED=true")
|
||||
|
||||
dlvArgv := []string{
|
||||
delvePath,
|
||||
"--listen=:" + delveListen,
|
||||
"--headless=true",
|
||||
"--api-version=2",
|
||||
"exec",
|
||||
os.Args[0],
|
||||
"--",
|
||||
}
|
||||
|
||||
dlvArgv = append(dlvArgv, os.Args[1:]...)
|
||||
syscall.Exec(delvePath, dlvArgv, soongDelveEnv)
|
||||
fmt.Fprintln(os.Stderr, "exec() failed while trying to reexec with Delve")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
|
|
@ -105,11 +105,6 @@ func runSoong(ctx Context, config Config) {
|
|||
soongBuildEnv.Set("BAZEL_WORKSPACE", absPath(ctx, "."))
|
||||
soongBuildEnv.Set("BAZEL_METRICS_DIR", config.BazelMetricsDir())
|
||||
|
||||
if os.Getenv("SOONG_DELVE") != "" {
|
||||
// SOONG_DELVE is already in cmd.Environment
|
||||
soongBuildEnv.Set("SOONG_DELVE_PATH", shared.ResolveDelveBinary())
|
||||
}
|
||||
|
||||
err := writeEnvironmentFile(ctx, envFile, soongBuildEnv.AsMap())
|
||||
if err != nil {
|
||||
ctx.Fatalf("failed to write environment file %s: %s", envFile, err)
|
||||
|
@ -176,6 +171,11 @@ func runSoong(ctx Context, config Config) {
|
|||
"-f", filepath.Join(config.SoongOutDir(), file))
|
||||
|
||||
cmd.Environment.Set("SOONG_OUTDIR", config.SoongOutDir())
|
||||
if os.Getenv("SOONG_DELVE") != "" {
|
||||
// SOONG_DELVE is already in cmd.Environment
|
||||
cmd.Environment.Set("SOONG_DELVE_PATH", shared.ResolveDelveBinary())
|
||||
}
|
||||
|
||||
cmd.Sandbox = soongSandbox
|
||||
cmd.RunAndStreamOrFatal()
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue