【问题标题】:How to compile/debug a C++ application in Docker with Visual Studio Code on Windows如何在 Windows 上使用 Visual Studio Code 在 Docker 中编译/调试 C++ 应用程序
【发布时间】:2018-07-20 01:43:50
【问题描述】:

我是 Visual Studio Code 和 Docker 的新手。现在我想使用 Visual Studio Code 来编辑我的 C++ 代码和 Docker 来编译/调试。

我不知道如何正确编写launch.json 和task.json 文件,以便我可以在Visual Studio Code 开发环境下使用Docker 编译/调试我的C++ 应用程序。这个问题有解决办法吗?

这是我的平台信息:

操作系统:Windows 10
Visual Studio 代码:v1.25.1
Docker 中的操作系统:Ubuntu 16.04 (Xenial Xerus)
Docker 中的编译器:g++

【问题讨论】:

    标签: c++ docker visual-studio-code


    【解决方案1】:

    此答案假定您没有尝试对多个容器执行任何操作...我假设您只想使用单个容器来构建一些 C++ 代码,并且您的所有代码都在一个名为C:\vsc_docker_cc_gdb。我还假设您在 Visual Studio Code 中安装了 Microsoft 的 C++ 和 Docker 扩展。

    让我们从一个名为 hello.cc 的简单 C++ 文件开始:

    #include <iostream>
    int main(int argc, char **argv) {
      std::cout << "Hello from Docker" << std::endl;
    }
    

    让我们也添加一个 Makefile:

    CXXFLAGS = -O3 -ggdb -m64
    LDFLAGS  = -m64
    
    all: hello.exe
    .PRECIOUS: hello.exe hello.o
    .PHONY: all clean
    
    %.o: %.cc
        $(CXX) -c $< -o $@ $(CXXFLAGS)
    
    %.exe: %.o
        $(CXX) $^ -o $@ $(LDFLAGS)
    
    clean:
        rm -f hello.o hello.exe
    

    这是一个通过添加 GDB 和 gdbserver 扩展 gcc:latest 的 Dockerfile(注意:我不确定是否需要 gdbserver):

    FROM gcc:latest
    LABEL Name=vsc_docker_cc_gdb Version=0.0.2
    RUN apt-get -y update
    RUN apt-get -y install gdb gdbserver
    WORKDIR /root
    

    这里是 .vscode/tasks.json:

    {
        "version": "2.0.0",
        "tasks": [
            {
                "label": "build (in container)",
                "type": "shell",
                "command": "docker run --privileged -v c:/vsc_docker_cc_gdb/:/root vsc_docker_cc_gdb make",
                "group": {
                    "kind": "build",
                    "isDefault": true
                },
                "problemMatcher": {
                    "owner": "cpp",
                    "fileLocation": [
                        "relative",
                        "${workspaceFolder}"
                    ],
                    "pattern": {
                        "regexp": "^(.*):(\\d+):(\\d+):\\s+(warning|error):\\s+(.*)$",
                        "file": 1,
                        "line": 2,
                        "column": 3,
                        "severity": 4,
                        "message": 5
                    }
                }
            },
            {
                "label": "clean (in container)",
                "type": "shell",
                "command": "docker run --privileged -v c:/vsc_docker_cc_gdb/:/root vsc_docker_cc_gdb make clean",
                "group": "build",
                "problemMatcher": []
            },
            {
                "label": "remove containers",
                "type": "shell",
                "command": "docker ps -a -q | % { docker rm $_ }",
                "problemMatcher": []
            },
            {
                "label": "run the code",
                "type": "shell",
                "command": "docker run --privileged -v c:/vsc_docker_cc_gdb/:/root vsc_docker_cc_gdb ./hello.exe",
                "group": "build",
                "problemMatcher": []
            },
            {
                "label": "prepare to debug",
                "type": "shell",
                "command": "docker run --privileged -v c:/vsc_docker_cc_gdb/:/root --name debug_vsc -it vsc_docker_cc_gdb ",
                "group": "build",
                "problemMatcher": []
            }
        ]
    }
    

    最后,.vscode/launch.json:

    {
        "version": "0.2.0",
        "configurations": [{
            "name": "(gdb) Pipe Launch",
            "type": "cppdbg",
            "request": "launch",
            "program": "/root/hello.exe",
            "cwd": "/root",
            "args": [],
            "stopAtEntry": true,
            "environment": [],
            "externalConsole": true,
            "pipeTransport": {
                "debuggerPath": "/usr/bin/gdb",
                "pipeProgram": "docker.exe",
                "pipeArgs": ["exec", "-i", "debug_vsc", "sh", "-c"],
                "pipeCwd": "${workspaceRoot}"
            },
            "MIMode": "gdb",
            "setupCommands": [{
                "description": "Enable pretty-printing for gdb",
                "text": "-enable-pretty-printing",
                "ignoreFailures": true
            }]
        }, ]
    }
    

    这里有两件重要的事情。首先是您会注意到launch.json 的部分引用容器中的路径(/root/),而其他部分引用Windows 主机上的路径(workspaceRoot)。这很重要。

    第二个是你需要有一个容器运行,然后你可以启动一个调试进程进入它。这是从零开始到启动该特殊容器并在其中启动调试器的方法。

    • 来自 PowerShell:docker pull gcc
    • 来自 Visual Studio 代码:F1Docker:构建映像(选择 vsc_docker_cc_gdb:latest)
    • 从 Visual Studio 代码:Ctrl + Shift + B 构建代码
    • 来自 Visual Studio 代码:F1任务:运行任务(选择“删除容器”)
    • 来自 Visual Studio 代码:F1任务:运行任务(选择“准备调试”)
    • 从 Visual Studio 代码:F5 启动调试器

    从那里,Visual Studio Code Debug Console 应该可以工作了,您应该能够设置断点、观察变量和输入调试命令。

    【讨论】:

    • 在 docker 调用中添加--rm 标志很有用,这样每个容器都会自动回收。
    • 我在 launch.json "pipeArgs" 中得到了以下结果:["run", "--privileged", "--rm", "-i", "-v", “/storage/projects/project1/experiments/docker_debug/src:/root”、“dockerdebug:latest”、“sh”、“-c”]、。注意“--privileged”以使 gdb 高兴(我猜),安装目录,并在退出时删除一次性容器,正如前一个评论者所建议的那样。否则完美运行(我在 linux 上)。
    • 你的make文件是否完整?我怀疑它错过了CXX=gcc 行?
    • 只有在将 "sourceFileMap": { "/root": "${workspaceFolder}" } 添加到 launch.json 的配置后才对我有用。没有它,vscode 无法解析调试器给出的路径
    【解决方案2】:

    我在 GitHub 上设置了一个最小的工作示例:https://github.com/fschwaiger/docker-cpp-vscode

    思路如下,假设你有ms-vscode.cpptools扩展:

    1. 您需要安装了gccgdb 的容器(可以相同)
    2. 您在容器中构建应用程序
    3. 您在容器内运行gdb

    1。获取gccgdb 的图像

    gcc 可直接从 Docker Hub 获得:docker pull gcc。我在那里没有找到gdb,所以有一个Dockerfile来构建它:

    FROM gcc:latest
    RUN apt-get update && apt-get install -y gdb
    RUN echo "set auto-load safe-path /" >> /root/.gdbinit
    

    它基于gcc:latest 构建并安装gdb,因此您可以使用相同的映像进行编译和调试。它还在/root/.gdbinit 中设置选项set auto-load safe-path / 以在容器中运行gdb 时抑制警告。安全不应成为当地发展的问题。

    使用工作目录中的docker build -t gdb . 构建映像,或在Visual Studio Code 中从F1运行任务 运行预配置的任务build docker gdb

    2。构建应用程序

    在项目中,从工作目录中的 PowerShell 窗口运行 docker run --rm -it -v ${pwd}:/work --workdir /work gcc make debug。使用 Visual Studio Code,这可以通过 F1Run Task 中的预配置任务 make debug 来完成。

    3。调试应用程序

    您希望将 Visual Studio Code 配置为在容器内运行 /usr/bin/gdb。您可以为此使用launch.json 中的pipeTransport 选项并使其运行:

    docker run --rm --interactive --volume ${workspaceFolder}:/work --workdir /work --privileged gdb sh -c /usr/bin/gdb
    

    解释:

    • --privileged: 允许二进制调试
    • --volume ${workspaceFolder}:/work --workdir /work:将项目文件夹挂载到容器中
    • --rm:退出后移除容器
    • --interactive: VSCode 将向 gdb shell 发出交互式命令
    • sh -c:在 GDB 中定义一个 shell 入口点运行

    整体launch.json 如下所示。请注意,programcwd 是容器的路径。 sourceFileMap 允许调试器将断点与源文件匹配。其余的是来自 C++ 扩展的默认模板。

    {
        "version": "0.2.0",
        "configurations": [
            {
                "name": "(gdb) Docker",
                "type": "cppdbg",
                "request": "launch",
                "program": "build/apps/program",
                "args": [],
                "stopAtEntry": true,
                "cwd": "/work",
                "environment": [],
                "externalConsole": true,
                "preLaunchTask": "make debug",
                "targetArchitecture": "x64",
                "sourceFileMap": { "/work": "${workspaceFolder}" },
                "pipeTransport": {
                    "debuggerPath": "/usr/bin/gdb",
                    "pipeProgram": "docker.exe",
                    "pipeArgs": ["run","--rm","--interactive","--volume","${workspaceFolder}:/work","--workdir","/work","--privileged","gdb","sh","-c"],
                    "pipeCwd": ""
                },
                "MIMode": "gdb",
                "setupCommands": [
                    {
                        "description": "Enable pretty-printing for gdb",
                        "text": "-enable-pretty-printing",
                        "ignoreFailures": true
                    }
                ]
            }
        ]
    }
    

    使用此设置,您只需在调试工作区中按下播放键即可。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-23
      • 2022-07-22
      • 2017-02-13
      • 2017-07-11
      相关资源
      最近更新 更多