Loading android/env.go +37 −4 Original line number Diff line number Diff line Loading @@ -15,9 +15,11 @@ package android import ( "fmt" "os" "os/exec" "strings" "syscall" "android/soong/env" ) Loading @@ -30,28 +32,59 @@ import ( // a manifest regeneration. var originalEnv map[string]string var SoongDelveListen string var SoongDelvePath string var soongDelveListen string var soongDelvePath string var soongDelveEnv []string func init() { // Delve support needs to read this environment variable very early, before NewConfig has created a way to // access originalEnv with dependencies. Store the value where soong_build can find it, it will manually // ensure the dependencies are created. SoongDelveListen = os.Getenv("SOONG_DELVE") SoongDelvePath, _ = exec.LookPath("dlv") soongDelveListen = os.Getenv("SOONG_DELVE") soongDelvePath, _ = exec.LookPath("dlv") originalEnv = make(map[string]string) soongDelveEnv = []string{} for _, env := range os.Environ() { idx := strings.IndexRune(env, '=') if idx != -1 { originalEnv[env[:idx]] = env[idx+1:] if env[:idx] != "SOONG_DELVE" { soongDelveEnv = append(soongDelveEnv, env) } } } // Clear the environment to prevent use of os.Getenv(), which would not provide dependencies on environment // variable values. The environment is available through ctx.Config().Getenv, ctx.Config().IsEnvTrue, etc. os.Clearenv() } func ReexecWithDelveMaybe() { if soongDelveListen == "" { return } if soongDelvePath == "" { fmt.Fprintln(os.Stderr, "SOONG_DELVE is set but failed to find dlv") os.Exit(1) } 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) } // getenv checks either os.Getenv or originalEnv so that it works before or after the init() // function above. It doesn't add any dependencies on the environment variable, so it should // only be used for values that won't change. For values that might change use ctx.Config().Getenv. Loading cmd/soong_build/main.go +1 −41 Original line number Diff line number Diff line Loading @@ -18,12 +18,7 @@ import ( "flag" "fmt" "os" "os/exec" "path/filepath" "strconv" "strings" "syscall" "time" "github.com/google/blueprint/bootstrap" Loading Loading @@ -55,42 +50,7 @@ func newNameResolver(config android.Config) *android.NameResolver { } func main() { if android.SoongDelveListen != "" { if android.SoongDelvePath == "" { fmt.Fprintln(os.Stderr, "SOONG_DELVE is set but failed to find dlv") os.Exit(1) } pid := strconv.Itoa(os.Getpid()) cmd := []string{android.SoongDelvePath, "attach", pid, "--headless", "-l", android.SoongDelveListen, "--api-version=2", "--accept-multiclient", "--log", } fmt.Println("Starting", strings.Join(cmd, " ")) dlv := exec.Command(cmd[0], cmd[1:]...) dlv.Stdout = os.Stdout dlv.Stderr = os.Stderr dlv.Stdin = nil // Put dlv into its own process group so we can kill it and the child process it starts. dlv.SysProcAttr = &syscall.SysProcAttr{Setpgid: true} err := dlv.Start() if err != nil { // Print the error starting dlv and continue. fmt.Println(err) } else { // Kill the process group for dlv when soong_build exits. defer syscall.Kill(-dlv.Process.Pid, syscall.SIGKILL) // Wait to give dlv a chance to connect and pause the process. time.Sleep(time.Second) } } android.ReexecWithDelveMaybe() flag.Parse() // The top-level Blueprints file is passed as the first argument. Loading Loading
android/env.go +37 −4 Original line number Diff line number Diff line Loading @@ -15,9 +15,11 @@ package android import ( "fmt" "os" "os/exec" "strings" "syscall" "android/soong/env" ) Loading @@ -30,28 +32,59 @@ import ( // a manifest regeneration. var originalEnv map[string]string var SoongDelveListen string var SoongDelvePath string var soongDelveListen string var soongDelvePath string var soongDelveEnv []string func init() { // Delve support needs to read this environment variable very early, before NewConfig has created a way to // access originalEnv with dependencies. Store the value where soong_build can find it, it will manually // ensure the dependencies are created. SoongDelveListen = os.Getenv("SOONG_DELVE") SoongDelvePath, _ = exec.LookPath("dlv") soongDelveListen = os.Getenv("SOONG_DELVE") soongDelvePath, _ = exec.LookPath("dlv") originalEnv = make(map[string]string) soongDelveEnv = []string{} for _, env := range os.Environ() { idx := strings.IndexRune(env, '=') if idx != -1 { originalEnv[env[:idx]] = env[idx+1:] if env[:idx] != "SOONG_DELVE" { soongDelveEnv = append(soongDelveEnv, env) } } } // Clear the environment to prevent use of os.Getenv(), which would not provide dependencies on environment // variable values. The environment is available through ctx.Config().Getenv, ctx.Config().IsEnvTrue, etc. os.Clearenv() } func ReexecWithDelveMaybe() { if soongDelveListen == "" { return } if soongDelvePath == "" { fmt.Fprintln(os.Stderr, "SOONG_DELVE is set but failed to find dlv") os.Exit(1) } 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) } // getenv checks either os.Getenv or originalEnv so that it works before or after the init() // function above. It doesn't add any dependencies on the environment variable, so it should // only be used for values that won't change. For values that might change use ctx.Config().Getenv. Loading
cmd/soong_build/main.go +1 −41 Original line number Diff line number Diff line Loading @@ -18,12 +18,7 @@ import ( "flag" "fmt" "os" "os/exec" "path/filepath" "strconv" "strings" "syscall" "time" "github.com/google/blueprint/bootstrap" Loading Loading @@ -55,42 +50,7 @@ func newNameResolver(config android.Config) *android.NameResolver { } func main() { if android.SoongDelveListen != "" { if android.SoongDelvePath == "" { fmt.Fprintln(os.Stderr, "SOONG_DELVE is set but failed to find dlv") os.Exit(1) } pid := strconv.Itoa(os.Getpid()) cmd := []string{android.SoongDelvePath, "attach", pid, "--headless", "-l", android.SoongDelveListen, "--api-version=2", "--accept-multiclient", "--log", } fmt.Println("Starting", strings.Join(cmd, " ")) dlv := exec.Command(cmd[0], cmd[1:]...) dlv.Stdout = os.Stdout dlv.Stderr = os.Stderr dlv.Stdin = nil // Put dlv into its own process group so we can kill it and the child process it starts. dlv.SysProcAttr = &syscall.SysProcAttr{Setpgid: true} err := dlv.Start() if err != nil { // Print the error starting dlv and continue. fmt.Println(err) } else { // Kill the process group for dlv when soong_build exits. defer syscall.Kill(-dlv.Process.Pid, syscall.SIGKILL) // Wait to give dlv a chance to connect and pause the process. time.Sleep(time.Second) } } android.ReexecWithDelveMaybe() flag.Parse() // The top-level Blueprints file is passed as the first argument. Loading