diff --git a/package.json b/package.json index 0315368c..0a4777de 100644 --- a/package.json +++ b/package.json @@ -112,6 +112,15 @@ "ros.distro": { "type": "string", "description": "ROS installation distro to be sourced." + }, + "ros.rosSetupScript": { + "type": "string", + "description": "ROS workspace setup script. Overrides ros.distro." + }, + "ros.isolateEnvironment": { + "type": "bool", + "default": false, + "description": "Specify if the extension should not capture the environment VSCode is running in to pass to child processes." } } }, diff --git a/src/debugger/configuration/resolvers/ros2/launch.ts b/src/debugger/configuration/resolvers/ros2/launch.ts index 109d75ff..4842b063 100644 --- a/src/debugger/configuration/resolvers/ros2/launch.ts +++ b/src/debugger/configuration/resolvers/ros2/launch.ts @@ -77,6 +77,9 @@ export class LaunchResolver implements vscode.DebugConfigurationProvider { }, }; + console.log("Executing dumper with the following environment:"); + console.log(rosExecOptions.env); + let ros2_launch_dumper = getExtensionFilePath(path.join("assets", "scripts", "ros2_launch_dumper.py")); let args = [] @@ -91,10 +94,14 @@ export class LaunchResolver implements vscode.DebugConfigurationProvider { `/usr/bin/env python3 ${ros2_launch_dumper} "${config.target}" ${flatten_args}`; let result = await promisifiedExec(ros2_launch_dumper_cmdLine, rosExecOptions); + if (result.stderr) { - throw (new Error(`Error from ROS2 launch dumper:\r\n ${result.stderr}`)); - } else if (result.stdout.length == 0) { - throw (new Error(`ROS2 launch dumper unexpectedly produced no output.`)); + // Having stderr output is not nessesarily a problem, but it is useful for debugging + console.log(`ROS2 launch processor produced stderr output:\r\n ${result.stderr}`); + } + + if (result.stdout.length == 0) { + throw (new Error(`ROS2 launch processor was unable to produce a node list.\r\n ${result.stderr}`)); } let commands = result.stdout.split(os.EOL); diff --git a/src/extension.ts b/src/extension.ts index 1be9a48e..f0d12659 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -276,8 +276,6 @@ async function sourceRosAndWorkspace(): Promise { const kWorkspaceConfigTimeout = 30000; // ms - const config = vscode_utils.getExtensionConfiguration(); - let distro = config.get("distro", ""); let setupScriptExt: string; if (process.platform === "win32") { setupScriptExt = ".bat"; @@ -285,41 +283,72 @@ async function sourceRosAndWorkspace(): Promise { setupScriptExt = ".bash"; } - // Is there a distro defined either by setting or environment? - if (!distro && !process.env.ROS_DISTRO) - { - // No? Try to find one. - const installedDistros = await ros_utils.getDistros(); - if (!installedDistros.length) { - throw new Error("ROS has not been found on this system."); - } else if (installedDistros.length === 1) { - // if there is only one distro installed, directly choose it - config.update("distro", installedDistros[0]); - } else { - const message = "Multiple ROS distros found. Configure this workspace by setting \"ros.distro\": \"\" in settings.json or in the ROS extension settings."; - await vscode.window.setStatusBarMessage(message, kWorkspaceConfigTimeout); + const config = vscode_utils.getExtensionConfiguration(); + let isolateEnvironment = config.get("isolateEnvironment", ""); + if (!isolateEnvironment) { + // Capture the host environment unless specifically isolated + env = process.env; + } + + + let rosSetupScript = config.get("rosSetupScript", ""); + + // If the workspace setup script is not set, try to find the ROS setup script in the environment + let attemptWorkspaceDiscovery = true; + + if (rosSetupScript) { + // Try to support cases where the setup script doesn't make sense on different environments, such as host vs container. + if (await pfs.exists(rosSetupScript)){ + try { + env = await ros_utils.sourceSetupFile(rosSetupScript, env); + + attemptWorkspaceDiscovery = false; + } catch (err) { + vscode.window.showErrorMessage(`A workspace setup script was provided in the configuration, but could not source "${rosSetupScript}". Attempting standard discovery.`); + } } } + + if (attemptWorkspaceDiscovery) { + let distro = config.get("distro", ""); - if (distro) { - try { - let globalInstallPath: string; - if (process.platform === "win32") { - globalInstallPath = path.join("C:", "opt", "ros", `${distro}`, "x64"); + // Is there a distro defined either by setting or environment? + if (!distro && !process.env.ROS_DISTRO) + { + // No? Try to find one. + const installedDistros = await ros_utils.getDistros(); + if (!installedDistros.length) { + throw new Error("ROS has not been found on this system."); + } else if (installedDistros.length === 1) { + // if there is only one distro installed, directly choose it + config.update("distro", installedDistros[0]); } else { - globalInstallPath = path.join("/", "opt", "ros", `${distro}`); + const message = "Unable to determine ROS distribution, please configure this workspace by adding \"ros.distro\": \"\" in settings.json"; + await vscode.window.setStatusBarMessage(message, kWorkspaceConfigTimeout); } - let setupScript: string = path.format({ - dir: globalInstallPath, - name: "setup", - ext: setupScriptExt, - }); - env = await ros_utils.sourceSetupFile(setupScript, {}); - } catch (err) { - vscode.window.showErrorMessage(`Could not source the setup file for ROS distro "${distro}".`); } - } else if (process.env.ROS_DISTRO) { - env = process.env; + + if (distro) { + let setupScript: string; + try { + let globalInstallPath: string; + if (process.platform === "win32") { + globalInstallPath = path.join("C:", "opt", "ros", `${distro}`, "x64"); + } else { + globalInstallPath = path.join("/", "opt", "ros", `${distro}`); + } + setupScript = path.format({ + dir: globalInstallPath, + name: "setup", + ext: setupScriptExt, + }); + env = await ros_utils.sourceSetupFile(setupScript, env); + } catch (err) { + vscode.window.showErrorMessage(`Could not source ROS setup script at "${setupScript}".`); + } + } else if (process.env.ROS_DISTRO) { + env = process.env; + } } // Source the workspace setup over the top. // TODO: we should test what's the build tool (catkin vs colcon). diff --git a/src/ros/utils.ts b/src/ros/utils.ts index 2a9c1ba6..737d0405 100644 --- a/src/ros/utils.ts +++ b/src/ros/utils.ts @@ -20,6 +20,7 @@ export function sourceSetupFile(filename: string, env?: any): Promise { } else { exportEnvCommand = `bash -c "source '${filename}' && env"`; + console.log ("executing " + exportEnvCommand); } let processOptions: child_process.ExecOptions = { @@ -34,7 +35,7 @@ export function sourceSetupFile(filename: string, env?: any): Promise { if (index !== -1) { env[line.substr(0, index)] = line.substr(index + 1); } - + return env; }, {})); } else {