From ace260dc3b7a119452e5d6ead22476333a0d9b1d Mon Sep 17 00:00:00 2001 From: Bob Brown Date: Wed, 6 Oct 2021 02:52:16 -0700 Subject: [PATCH] reorder some logic in the debugger override case (#2123) * reorder some logic in the debugger override case * update tests * update paths * Get absolute path Co-authored-by: Andreea Isac <48239328+andreeis@users.noreply.github.com> --- src/debugger.ts | 77 ++++++++++--------- src/expand.ts | 2 +- test/fakeOutputGenerator/configfiles/gdb.cfg | 2 + .../configfiles/lldb-mi.cfg | 2 + test/fakeOutputGenerator/main.cpp | 25 +++--- test/unit-tests/select-debugger.test.ts | 10 ++- 6 files changed, 67 insertions(+), 51 deletions(-) create mode 100644 test/fakeOutputGenerator/configfiles/gdb.cfg create mode 100644 test/fakeOutputGenerator/configfiles/lldb-mi.cfg diff --git a/src/debugger.ts b/src/debugger.ts index d86f4576..a5dfe56a 100644 --- a/src/debugger.ts +++ b/src/debugger.ts @@ -165,47 +165,59 @@ export async function getDebugConfigurationFromCache(cache: CMakeCache, target: } } + const debugger_name = modeOverride || (platform === 'darwin' ? 'lldb' : 'gdb'); + const description = DEBUG_GEN[debugger_name]; + + if (debuggerPathOverride) { + if (path.isAbsolute(debuggerPathOverride) && await fs.exists(debuggerPathOverride)) { + return description.createConfig(debuggerPathOverride, target); + } + log.warning(localize('invalid.miDebuggerPath.override', + "'{0}' in '{1}' must be an absolute path to a debugger (variable expansion is not currently supported). Got: '{2}'", + "miDebuggerPath", "cmake.debugConfig", debuggerPathOverride)); + } + const compiler_path = searchForCompilerPathInCache(cache); if (compiler_path === null) { throw Error(localize('no.compiler.found.in.cache', 'No compiler found in cache file.')); // MSVC should be already found by CMAKE_LINKER } - if (!debuggerPathOverride) { - // Look for a debugger, in the following order: - // 1. LLDB-MI - const clang_compiler_regex = /(clang[\+]{0,2})+(?!-cl)/gi; - let mi_debugger_path = compiler_path.replace(clang_compiler_regex, 'lldb-mi'); - if (modeOverride !== "gdb" && (mi_debugger_path.search(new RegExp('lldb-mi')) !== -1)) { - const cpptoolsExtension = vscode.extensions.getExtension('ms-vscode.cpptools'); - const cpptoolsDebuggerPath = cpptoolsExtension ? path.join(cpptoolsExtension.extensionPath, "debugAdapters", "lldb-mi", "bin", "lldb-mi") : undefined; - // 1a. lldb-mi in the compiler path - if (await checkDebugger(mi_debugger_path)) { - return createLLDBDebugConfiguration(mi_debugger_path, target); - } + if (compiler_path.endsWith('cl.exe')) { + return createMSVCDebugConfiguration(target); + } - // 1b. lldb-mi installed by CppTools - if (cpptoolsDebuggerPath && await checkDebugger(cpptoolsDebuggerPath)) { - return createLLDBDebugConfiguration(cpptoolsDebuggerPath, target); - } - } - - // 2. gdb in the compiler path - mi_debugger_path = compiler_path.replace(clang_compiler_regex, 'gdb'); - if (modeOverride !== "lldb" && (mi_debugger_path.search(new RegExp('gdb')) !== -1) && await checkDebugger(mi_debugger_path)) { - return createGDBDebugConfiguration(mi_debugger_path, target); - } - - // 3. lldb in the compiler path - mi_debugger_path = compiler_path.replace(clang_compiler_regex, 'lldb'); - if (modeOverride !== "gdb" && (mi_debugger_path.search(new RegExp('lldb')) !== -1) && await checkDebugger(mi_debugger_path)) { + // Look for a debugger, in the following order: + // 1. LLDB-MI + const clang_compiler_regex = /(clang[\+]{0,2})+(?!-cl)/gi; + let mi_debugger_path = compiler_path.replace(clang_compiler_regex, 'lldb-mi'); + if (modeOverride !== "gdb" && (mi_debugger_path.search(new RegExp('lldb-mi')) !== -1)) { + const cpptoolsExtension = vscode.extensions.getExtension('ms-vscode.cpptools'); + const cpptoolsDebuggerPath = cpptoolsExtension ? path.join(cpptoolsExtension.extensionPath, "debugAdapters", "lldb-mi", "bin", "lldb-mi") : undefined; + // 1a. lldb-mi in the compiler path + if (await checkDebugger(mi_debugger_path)) { return createLLDBDebugConfiguration(mi_debugger_path, target); } + + // 1b. lldb-mi installed by CppTools + if (cpptoolsDebuggerPath && await checkDebugger(cpptoolsDebuggerPath)) { + return createLLDBDebugConfiguration(cpptoolsDebuggerPath, target); + } + } + + // 2. gdb in the compiler path + mi_debugger_path = compiler_path.replace(clang_compiler_regex, 'gdb'); + if (modeOverride !== "lldb" && (mi_debugger_path.search(new RegExp('gdb')) !== -1) && await checkDebugger(mi_debugger_path)) { + return createGDBDebugConfiguration(mi_debugger_path, target); + } + + // 3. lldb in the compiler path + mi_debugger_path = compiler_path.replace(clang_compiler_regex, 'lldb'); + if (modeOverride !== "gdb" && (mi_debugger_path.search(new RegExp('lldb')) !== -1) && await checkDebugger(mi_debugger_path)) { + return createLLDBDebugConfiguration(mi_debugger_path, target); } - const debugger_name = modeOverride || (platform === 'darwin' ? 'lldb' : 'gdb'); - const description = DEBUG_GEN[debugger_name]; const gcc_compiler_regex = /([cg]\+\+|g?cc)(?=[^\/\\]*$)/gi; - let gdb_debugger_path = debuggerPathOverride || compiler_path.replace(gcc_compiler_regex, description.miMode); + let gdb_debugger_path = compiler_path.replace(gcc_compiler_regex, description.miMode); if (path.isAbsolute(gdb_debugger_path) && !await fs.exists(gdb_debugger_path)) { gdb_debugger_path = path.join(path.dirname(compiler_path), description.miMode); if (process.platform === 'win32') { @@ -216,11 +228,6 @@ export async function getDebugConfigurationFromCache(cache: CMakeCache, target: return description.createConfig(gdb_debugger_path, target); } - const is_msvc_compiler = compiler_path.endsWith('cl.exe'); - if (is_msvc_compiler) { - return createMSVCDebugConfiguration(target); - } - log.warning(localize('unable.to.determine.debugger.for.compiler', 'Unable to automatically determine debugger corresponding to compiler: {0}', compiler_path)); return null; diff --git a/src/expand.ts b/src/expand.ts index 43962551..62dcc601 100644 --- a/src/expand.ts +++ b/src/expand.ts @@ -120,7 +120,7 @@ export async function expandString(tmpl: string, opts: ExpansionOptions) { return replaceAll(result, '${dollar}', '$'); } -export async function expandStringHelper(tmpl: string, opts: ExpansionOptions) { +async function expandStringHelper(tmpl: string, opts: ExpansionOptions) { const envPreNormalize = opts.envOverride ? opts.envOverride : process.env as EnvironmentVariables; const env = mergeEnvironment(envPreNormalize); const repls = opts.vars; diff --git a/test/fakeOutputGenerator/configfiles/gdb.cfg b/test/fakeOutputGenerator/configfiles/gdb.cfg new file mode 100644 index 00000000..7021954f --- /dev/null +++ b/test/fakeOutputGenerator/configfiles/gdb.cfg @@ -0,0 +1,2 @@ +The version information is not needed. +This is to ensure a binary exists for tests. \ No newline at end of file diff --git a/test/fakeOutputGenerator/configfiles/lldb-mi.cfg b/test/fakeOutputGenerator/configfiles/lldb-mi.cfg new file mode 100644 index 00000000..7021954f --- /dev/null +++ b/test/fakeOutputGenerator/configfiles/lldb-mi.cfg @@ -0,0 +1,2 @@ +The version information is not needed. +This is to ensure a binary exists for tests. \ No newline at end of file diff --git a/test/fakeOutputGenerator/main.cpp b/test/fakeOutputGenerator/main.cpp index e5b001a9..a40dc1ff 100644 --- a/test/fakeOutputGenerator/main.cpp +++ b/test/fakeOutputGenerator/main.cpp @@ -5,7 +5,8 @@ #include #endif -std::string generateConfigFilename(std::string inputFileName) { +std::string generateConfigFilename(std::string inputFileName) +{ #ifdef _WIN32 const std::string nameNoExt = (inputFileName.rfind(".exe") == inputFileName.size() - 4) ? inputFileName.substr(0, inputFileName.length() - 4) : inputFileName; #else @@ -14,25 +15,27 @@ std::string generateConfigFilename(std::string inputFileName) { return nameNoExt + ".cfg"; } -int main(int argc, char** argv) { +int main(int argc, char** argv) +{ #ifdef _WIN32 char buffer[MAX_PATH]; DWORD length = GetModuleFileName( NULL, buffer, MAX_PATH); - std::string filePath( buffer); + std::string filePath(buffer); #else - - std::string filePath = argv[0]; + std::string filePath = argv[0]; #endif - std::string configFilePath = generateConfigFilename(filePath); + std::string configFilePath = generateConfigFilename(filePath); + std::ifstream inputData(configFilePath.c_str()); - std::ifstream inputData(configFilePath.c_str()); - - if(inputData.good()) { - for( std::string line; std::getline(inputData, line ); ) + if (inputData.good()) + { + for (std::string line; std::getline(inputData, line ); ) { std::cerr << line << std::endl; } - } else { + } + else + { std::cerr << "Argv[0]" << argv[0] << std::endl; std::cerr << "ERROR: config file is missing '" << configFilePath << "'" << std::endl; return -99; diff --git a/test/unit-tests/select-debugger.test.ts b/test/unit-tests/select-debugger.test.ts index 46c02e93..77af07a7 100644 --- a/test/unit-tests/select-debugger.test.ts +++ b/test/unit-tests/select-debugger.test.ts @@ -174,8 +174,9 @@ suite('Select debugger', async () => { const target = {name: 'Test', path: 'Target'}; const cache = await CMakeCache.fromPath(getTestResourceFilePath('TestCMakeCache-gcc.txt')); + const debuggerPath = getTestResourceFilePath('../fakebin/gdb'); - const config = await Debugger.getDebugConfigurationFromCache(cache, target, 'darwin', Debugger.MIModes.gdb, "../folder/debugger/gdb"); + const config = await Debugger.getDebugConfigurationFromCache(cache, target, 'darwin', Debugger.MIModes.gdb, debuggerPath); expect(config).to.not.be.null; if (!config) { throw new Error(); @@ -183,7 +184,7 @@ suite('Select debugger', async () => { expect(config.name).to.be.eq('Debug Test'); expect(config['MIMode']).to.be.eq('gdb'); expect(config.type).to.be.eq('cppdbg'); - expect(config['miDebuggerPath']).to.be.eq('../folder/debugger/gdb'); + expect(config['miDebuggerPath']).to.be.eq(debuggerPath); }); test('Create debug config from cache - debugger override', async () => { @@ -210,8 +211,9 @@ suite('Select debugger', async () => { const target = {name: 'Test', path: 'Target'}; const cache = await CMakeCache.fromPath(getTestResourceFilePath('TestCMakeCache-gcc.txt')); + const debuggerPath = getTestResourceFilePath('../fakebin/lldb-mi'); - const config = await Debugger.getDebugConfigurationFromCache(cache, target, 'darwin', undefined, "../folder/debugger/lldb-mi"); + const config = await Debugger.getDebugConfigurationFromCache(cache, target, 'darwin', undefined, debuggerPath); expect(config).to.not.be.null; if (!config) { throw new Error(); @@ -219,6 +221,6 @@ suite('Select debugger', async () => { expect(config.name).to.be.eq('Debug Test'); expect(config['MIMode']).to.be.eq('lldb'); expect(config.type).to.be.eq('cppdbg'); - expect(config['miDebuggerPath']).to.be.eq('../folder/debugger/lldb-mi'); + expect(config['miDebuggerPath']).to.be.eq(debuggerPath); }); });