[Lldb-commits] [lldb] 4ec6eba - [lldb-vscode] Add inheritEnvironment option

Walter Erquinigo via lldb-commits lldb-commits at lists.llvm.org
Fri Mar 20 18:52:01 PDT 2020


Author: Hector Diaz
Date: 2020-03-20T18:51:25-07:00
New Revision: 4ec6ebabfc3ec03d3ad4d3bdf05a7292d01391b3

URL: https://github.com/llvm/llvm-project/commit/4ec6ebabfc3ec03d3ad4d3bdf05a7292d01391b3
DIFF: https://github.com/llvm/llvm-project/commit/4ec6ebabfc3ec03d3ad4d3bdf05a7292d01391b3.diff

LOG: [lldb-vscode] Add inheritEnvironment option

Summary:
If no custom launching is used, lldb-vscode launches a program with an empty environment by default. In some scenarios, the user might want to simply use the same environment as the IDE to have a set of working environment variables (e.g. PATH wouldn't be empty). In fact, most DAPs in VSCode have this behavior by default. In other cases the user definitely needs to set their custom environment, which is already supported. To make the first case easier for the user (e.g. not having to copy the PATH to the launch.json every time they want to debug simple programs that rely on PATH), a new option is now offered. inheritEnvironment will launch the program copying its own environment, and it's just a boolean flag.

{F11347695}

Reviewers: clayborg, aadsm, diazhector98, kusmour

Subscribers: labath, JDevlieghere, lldb-commits

Tags: #lldb

Differential Revision: https://reviews.llvm.org/D74636

Added: 
    lldb/test/API/tools/lldb-vscode/environmentVariables/Makefile
    lldb/test/API/tools/lldb-vscode/environmentVariables/TestVSCode_environmentVariables.py
    lldb/test/API/tools/lldb-vscode/environmentVariables/main.cpp

Modified: 
    lldb/packages/Python/lldbsuite/test/tools/lldb-vscode/lldbvscode_testcase.py
    lldb/packages/Python/lldbsuite/test/tools/lldb-vscode/vscode.py
    lldb/tools/lldb-vscode/lldb-vscode.cpp
    lldb/tools/lldb-vscode/package.json

Removed: 
    


################################################################################
diff  --git a/lldb/packages/Python/lldbsuite/test/tools/lldb-vscode/lldbvscode_testcase.py b/lldb/packages/Python/lldbsuite/test/tools/lldb-vscode/lldbvscode_testcase.py
index 54f09e2cdbee..25b28cacefb4 100644
--- a/lldb/packages/Python/lldbsuite/test/tools/lldb-vscode/lldbvscode_testcase.py
+++ b/lldb/packages/Python/lldbsuite/test/tools/lldb-vscode/lldbvscode_testcase.py
@@ -267,7 +267,7 @@ def launch(self, program=None, args=None, cwd=None, env=None,
                disableSTDIO=False, shellExpandArguments=False,
                trace=False, initCommands=None, preRunCommands=None,
                stopCommands=None, exitCommands=None,sourcePath= None,
-               debuggerRoot=None, launchCommands=None):
+               debuggerRoot=None, launchCommands=None, inheritEnvironment=False):
         '''Sending launch request to vscode
         '''
 
@@ -298,7 +298,8 @@ def cleanup():
             exitCommands=exitCommands,
             sourcePath=sourcePath,
             debuggerRoot=debuggerRoot,
-            launchCommands=launchCommands)
+            launchCommands=launchCommands,
+            inheritEnvironment=inheritEnvironment)
         if not (response and response['success']):
             self.assertTrue(response['success'],
                             'launch failed (%s)' % (response['message']))
@@ -308,7 +309,7 @@ def build_and_launch(self, program, args=None, cwd=None, env=None,
                          disableSTDIO=False, shellExpandArguments=False,
                          trace=False, initCommands=None, preRunCommands=None,
                          stopCommands=None, exitCommands=None,
-                         sourcePath=None, debuggerRoot=None):
+                         sourcePath=None, debuggerRoot=None, inheritEnvironment=False):
         '''Build the default Makefile target, create the VSCode debug adaptor,
            and launch the process.
         '''
@@ -318,4 +319,4 @@ def build_and_launch(self, program, args=None, cwd=None, env=None,
         self.launch(program, args, cwd, env, stopOnEntry, disableASLR,
                     disableSTDIO, shellExpandArguments, trace,
                     initCommands, preRunCommands, stopCommands, exitCommands,
-                    sourcePath, debuggerRoot)
+                    sourcePath, debuggerRoot, inheritEnvironment=inheritEnvironment)

diff  --git a/lldb/packages/Python/lldbsuite/test/tools/lldb-vscode/vscode.py b/lldb/packages/Python/lldbsuite/test/tools/lldb-vscode/vscode.py
index 3cdf1ee90ccb..e2cd25186ffa 100644
--- a/lldb/packages/Python/lldbsuite/test/tools/lldb-vscode/vscode.py
+++ b/lldb/packages/Python/lldbsuite/test/tools/lldb-vscode/vscode.py
@@ -570,7 +570,7 @@ def request_launch(self, program, args=None, cwd=None, env=None,
                        disableSTDIO=False, shellExpandArguments=False,
                        trace=False, initCommands=None, preRunCommands=None,
                        stopCommands=None, exitCommands=None, sourcePath=None,
-                       debuggerRoot=None, launchCommands=None):
+                       debuggerRoot=None, launchCommands=None, inheritEnvironment=False):
         args_dict = {
             'program': program
         }
@@ -605,6 +605,8 @@ def request_launch(self, program, args=None, cwd=None, env=None,
             args_dict['debuggerRoot'] = debuggerRoot
         if launchCommands:
             args_dict['launchCommands'] = launchCommands
+        if inheritEnvironment:
+            args_dict['inheritEnvironment'] = inheritEnvironment
         command_dict = {
             'command': 'launch',
             'type': 'request',
@@ -912,7 +914,8 @@ def run_vscode(dbg, args, options):
                                       initCommands=options.initCmds,
                                       preRunCommands=options.preRunCmds,
                                       stopCommands=options.stopCmds,
-                                      exitCommands=options.exitCmds)
+                                      exitCommands=options.exitCmds,
+                                      inheritEnvironment=options.inheritEnvironment)
 
     if response['success']:
         if options.sourceBreakpoints:

diff  --git a/lldb/test/API/tools/lldb-vscode/environmentVariables/Makefile b/lldb/test/API/tools/lldb-vscode/environmentVariables/Makefile
new file mode 100644
index 000000000000..99998b20bcb0
--- /dev/null
+++ b/lldb/test/API/tools/lldb-vscode/environmentVariables/Makefile
@@ -0,0 +1,3 @@
+CXX_SOURCES := main.cpp
+
+include Makefile.rules

diff  --git a/lldb/test/API/tools/lldb-vscode/environmentVariables/TestVSCode_environmentVariables.py b/lldb/test/API/tools/lldb-vscode/environmentVariables/TestVSCode_environmentVariables.py
new file mode 100644
index 000000000000..f19cbebe9dd5
--- /dev/null
+++ b/lldb/test/API/tools/lldb-vscode/environmentVariables/TestVSCode_environmentVariables.py
@@ -0,0 +1,107 @@
+"""
+Test lldb-vscode environment variables
+"""
+
+
+import lldbvscode_testcase
+import unittest2
+import vscode
+import os
+from lldbsuite.test import lldbutil
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+
+class TestVSCode_variables(lldbvscode_testcase.VSCodeTestCaseBase):
+
+    mydir = TestBase.compute_mydir(__file__)
+
+    def getEnvOutputByProgram(self):
+        env = {}
+        for line in self.get_stdout().encode('utf-8').splitlines():
+            (name, value) = line.split("=")
+            env[name] = value
+        return env
+
+    @skipIfWindows
+    @skipIfRemote
+    def test_empty_environment(self):
+        """
+            Tests running a process with an empty environment
+        """
+        program = self.getBuildArtifact("a.out")
+        self.build_and_launch(program)
+        self.continue_to_exit()
+        env = self.getEnvOutputByProgram()
+
+        self.assertNotIn("PATH", env)
+
+    @skipIfWindows
+    @skipIfRemote
+    def test_inheriting_environment(self):
+        """
+            Tests running a process inheriting the environment
+        """
+        program = self.getBuildArtifact("a.out")
+        self.build_and_launch(program, inheritEnvironment=True, env=["FOO=bar"])
+        self.continue_to_exit()
+        env = self.getEnvOutputByProgram()
+
+        self.assertEqual(env["PATH"], os.environ['PATH'])
+        self.assertEqual(env["FOO"], "bar")
+
+    @skipIfWindows
+    @skipIfRemote
+    def test_override_when_inheriting_environment(self):
+        """
+            Tests the environment variables priority.
+            The launch.json's environment has precedence.
+        """
+        program = self.getBuildArtifact("a.out")
+        new_path_value = "#" + os.environ["PATH"]
+
+        self.build_and_launch(
+            program,
+            inheritEnvironment=True,
+            env=["PATH=" + new_path_value])
+        self.continue_to_exit()
+        env = self.getEnvOutputByProgram()
+
+        self.assertEqual(env["PATH"], new_path_value)
+
+    @skipIfWindows
+    @skipIfRemote
+    def test_empty_environment_custom_launcher(self):
+        """
+            Tests running a process with an empty environment from a custom
+            launcher
+        """
+        program = self.getBuildArtifact("a.out")
+        self.build_and_create_debug_adaptor()
+
+        launchCommands = [
+            'target create "%s"' % (program),
+            "run"
+        ]
+        self.launch(launchCommands=launchCommands)
+        self.continue_to_exit()
+        env = self.getEnvOutputByProgram() 
+        self.assertNotIn("PATH", env)
+
+    @skipIfWindows
+    @skipIfRemote
+    def test_inheriting_environment_custom_launcher(self):
+        """
+            Tests running a process from a custom launcher inheriting the
+            environment
+        """
+        program = self.getBuildArtifact("a.out")
+        self.build_and_create_debug_adaptor()
+
+        launchCommands = [
+            'target create "%s"' % (program),
+            "run"
+        ]
+        self.launch(launchCommands=launchCommands, inheritEnvironment=True)
+        self.continue_to_exit()
+        env = self.getEnvOutputByProgram() 
+        self.assertIn("PATH", env)

diff  --git a/lldb/test/API/tools/lldb-vscode/environmentVariables/main.cpp b/lldb/test/API/tools/lldb-vscode/environmentVariables/main.cpp
new file mode 100644
index 000000000000..968671d20c09
--- /dev/null
+++ b/lldb/test/API/tools/lldb-vscode/environmentVariables/main.cpp
@@ -0,0 +1,15 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+extern char **environ;
+
+int main(int argc, char const *argv[]) {
+  char **env_var_pointer = environ;
+  for (char *env_variable = *env_var_pointer; env_variable;
+       env_variable = *++env_var_pointer) {
+    printf("%s\n", env_variable);
+  }
+  return 0;
+}

diff  --git a/lldb/tools/lldb-vscode/lldb-vscode.cpp b/lldb/tools/lldb-vscode/lldb-vscode.cpp
index 8c68dd0e7055..149b89bd3fe2 100644
--- a/lldb/tools/lldb-vscode/lldb-vscode.cpp
+++ b/lldb/tools/lldb-vscode/lldb-vscode.cpp
@@ -40,6 +40,7 @@
 #include <sstream>
 #include <thread>
 
+#include "lldb/API/SBEnvironment.h"
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/Option/Arg.h"
 #include "llvm/Option/ArgList.h"
@@ -1355,6 +1356,8 @@ void request_launch(const llvm::json::Object &request) {
   auto launchCommands = GetStrings(arguments, "launchCommands");
   g_vsc.stop_at_entry = GetBoolean(arguments, "stopOnEntry", false);
   const auto debuggerRoot = GetString(arguments, "debuggerRoot");
+  bool launchWithDebuggerEnvironment =
+      GetBoolean(arguments, "inheritEnvironment", false);
 
   // This is a hack for loading DWARF in .o files on Mac where the .o files
   // in the debug map of the main executable have relative paths which require
@@ -1371,6 +1374,13 @@ void request_launch(const llvm::json::Object &request) {
   // the targets - preRunCommands are run with the target.
   g_vsc.RunInitCommands();
 
+  // Reset the default value of the inherit environment setting, so that the
+  // environment of programs launched by launchCommands is consistent with the
+  // "inheritEnvironment" argument.
+  if (!launchWithDebuggerEnvironment)
+    g_vsc.RunLLDBCommands(llvm::StringRef(),
+                          {"settings set target.inherit-env false"});
+
   lldb::SBError status;
   g_vsc.SetTarget(g_vsc.CreateTargetFromArguments(*arguments, status));
   if (status.Fail()) {
@@ -1395,10 +1405,12 @@ void request_launch(const llvm::json::Object &request) {
   if (!args.empty())
     g_vsc.launch_info.SetArguments(MakeArgv(args).data(), true);
 
-  // Pass any environment variables along that the user specified.
-  auto envs = GetStrings(arguments, "env");
-  if (!envs.empty())
-    g_vsc.launch_info.SetEnvironmentEntries(MakeArgv(envs).data(), true);
+  // This mimics what CommandObjectProcess does when launching a process
+  lldb::SBEnvironment env = g_vsc.target.GetEnvironment();
+  for (const auto &name_and_value : GetStrings(arguments, "env"))
+    env.PutEntry(name_and_value.c_str());
+
+  g_vsc.launch_info.SetEnvironment(env, true);
 
   auto flags = g_vsc.launch_info.GetLaunchFlags();
 

diff  --git a/lldb/tools/lldb-vscode/package.json b/lldb/tools/lldb-vscode/package.json
index 0799acfa116e..dd4158ffaa01 100644
--- a/lldb/tools/lldb-vscode/package.json
+++ b/lldb/tools/lldb-vscode/package.json
@@ -84,6 +84,11 @@
 								"description": "Additional environment variables.",
 								"default": []
 							},
+							"inheritEnvironment": {
+								"type": "boolean",
+								"description": "Inherit the debugger environment when launching a process. Only works for binaries launched directly by LLDB.",
+								"default": false
+							},
 							"stopOnEntry": {
 								"type": "boolean",
 								"description": "Automatically stop after launch.",


        


More information about the lldb-commits mailing list