Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

VS Code debugging fails when there's a space in the source path

I'm trying to create a GDB debugging pipeline for my c files in VS Code (windows). You can find my tasks.json and launch.json below.

Now if the path to my source file(s) doesn't contain any spaces this works fine. However, if it does include spaces I will receive a message like this whenever the debugger tries to break: Unable to open 'Semester': File not found

This is because the source file it's looking for is actually located at

E:\Libraries\Dropbox\UNI\Semester 5\test.c

And I'm guessing either GDB has sent VS Code a bad link to the file, or VS Code doesn't understand spaces in it's file paths (which I doubt). Sorry but I don't really understand the link between GDB and VS Code during the debugging session.

Does anyone know how to fix this?

tasks.json:

{
    "version": "2.0.0",
    "tasks": [
        {
            "label": "Build C Program",
            "type": "shell",
            "command": "gcc",
            "options": {"cwd": "${fileDirname}"},
            "args": [
                "-g", "-o", "${fileBasenameNoExtension}.exe", "${fileBasename}"
            ],
            "group": {"kind": "build","isDefault": true}
        }
    ]
}

launch.json:

{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "(gdb) Launch",
            "type": "cppdbg",
            "request": "launch",
            "program": "${fileDirname}\\${fileBasenameNoExtension}.exe",
            "args": [],
            "stopAtEntry": false,
            "cwd": "${fileDirname}",
            "environment": [],
            "externalConsole": true,
            "MIMode": "gdb",
            "miDebuggerPath": "C:\\cygwin64\\bin\\gdb.exe",
            "setupCommands": [
                {
                    "description": "Enable pretty-printing for gdb",
                    "text": "-enable-pretty-printing",
                    "ignoreFailures": true
                }
            ],
            "preLaunchTask": "Build C Program"
        }
    ]
}
like image 478
protango Avatar asked Nov 08 '22 03:11

protango


1 Answers

I think the latest version of VS Code may have already solved this issue. However, some knowledge about how command line arguments work might help you understand the cause of this problem.

Basically, shells split words separated by whitespaces and treat these words as stand-alone arguments. For files with no embedded spaces in their paths, everything's okay. For files with embedded spaces in their paths, it takes some extra typing to walk around the pitfall.


Say we want to compile a file named pathWithNoEmbeddedSpaces.c, we simply type:

gcc -g -o target1.exe pathWithNoEmbeddedSpaces.c

Command line arguments separated by whitespaces, from gcc, -g to pathWithNoEmbeddedSpaces.c in the above case, are treated as stand-alone arguments. They are then passed by the shell to GCC, our compiler, which understands that we want to compile 1 source file.


Say we want to compile another file named path With Embedded Spaces.c, we type:

gcc -g -o target2.exe path With Embedded Spaces.c

How many stand-alone arguments do we have this time? 8! Now, the shell treat gcc ... path With Embeded Spaces.c all as stand-alone arguments. GCC is confused since what it sees is a requirement to compile 4 source files, which may not even exist in the current directory!


As for the solution, quotation marks come to the rescue, which is also known as quoting. Most shells are fine with both single quote (') and double quote ("). But you may want to check out the details for your shell. Whenever there are embedded spaces in the file path, use the quotation. Such as:

gcc -g -o target2.exe "path With Embedded Spaces.c"

The shell now knows that path With Embedded Spaces.c is one argument and should be treated as a whole, which is then passed to GCC for compilation to be done.


Now, what does VS Code have to do with the issue?

In the "Ancient Times" of VS Code, it simply replaces predefined variables such as ${fileDirname} in your JSON files, then joins the arguments separated by spaces, and passes the command to the underlying shell. Even though VS Code performs special treatment when it comes to commands and arguments that contain spaces or other special characters, it doesn't go over the replacements for predefined variables. So ${fileBasename} gets replaced without quotation.

Assume our current working directory is E:\Libraries\Dropbox\UNI\Semester 5, then VS Code will replace ${fileBasename} by test.c and ${fileDirname} by E:\Libraries\Dropbox\UNI\Semester 5:

gcc -g -o test.exe test.c

The compilation should be performed without any issue, since test.c is in the current working directory. However, condiser the target path in launch.json:

"program": "${fileDirname}\\${fileBasenameNoExtension}.exe"

GDB will search for a program named E:\Libraries\Dropbox\UNI\Semester since no quotation is used, and then exit abnormally because there isn't such a program.


To cope with file path with embedded spaces, consider use quotations. For example, you could surround predefined variables with single quotation marks: '${fileDirname}', '${fileBasename}', etc. Several lines in your JSON files should look like these examples:

"-g", "-o", "'${fileBasenameNoExtension}.exe'", "'${fileBasename}'"
"-g", "-o", "\"${fileBasenameNoExtension}.exe\"", "\"${fileBasename}\""
"program": "'${fileDirname}\\${fileBasenameNoExtension}.exe'"

However, as a general rule, avoid spaces in paths for source files when every possible.

like image 50
MarkG Avatar answered Nov 14 '22 23:11

MarkG