VSCode,Dev Containers和Docker:推进软件开发

2021-01-21 23:29:59

本博客的长期读者将知道我们致力于使用基于容器的技术,尤其是Docker,通过可重复的构建来显着提高软件质量。

在2020年秋/秋季,Microsoft推出了Visual Studio Code(VSCode)扩展Remote – Containers。快速扩展,此扩展使您可以在Docker容器中打开VSCode项目。

有多种使用开发容器的方法。在这篇文章中,我们将介绍三个选项:

任何使用C进行测试驱动开发或在其中进行实验的人都可能会意识到Ceedling,团结和CMock。

无论您是否安装了Ceedling或任何依赖项(例如Ruby),我们都可以将Dev Container与现有Dockerhub容器映像一起使用。容器化确保我们可以在已知环境中使用Ceedling迅速启动并运行。在真正的“ Blue Peter”风格中,我们恰巧在Docker Hub上有一个基于Ceedling的预先构建的Docker映像。

VScode将检测“开发容器”配置文件,并询问您是否要重新打开容器中的文件夹。单击在容器中重新打开。

在VSCode中打开一个终端窗口,您将看到一个shell提示符#。我们现在正在基于映像feabhas / ceedling的Docker容器中运行。

#ceedling new test_project欢迎来到Ceedling!创建test_project / project.ymlProject' test_project'创建! -执行“帮助帮助”从test_project查看可用的测试&构建任务#cd test_project#ceedling模块:create [widget]文件src / widget.c createdFile src / widget.h createdFile test / test_widget.c createdGenerate Complete#ceedling testTest' test_widget.c' ---- ----------------为test_widget.c生成运行程序...正在编译test_widget_runner.c ...正在编译test_widget.c ...正在编译unity.c ...正在编译widget.c ...正在编译cmock.c ...链接test_widget.out ...正在运行test_widget.out ...--------------------忽略的测试摘要- ----------------- [test_widget.c]测试:test_widget_NeedToImplement在第(15)行:"需要实现小部件" -------- ------------总体测试摘要--------------------测试:1通过:0失败:0忽略:1

退出VSCode后,所有创建的文件将存在于本地文件系统中。重新打开VSCode,将再次提示您在容器中重新打开。

接下来,您可以选择首选的基础Linux映像–我已经使用了ubuntu-20.04基础(此示例无关紧要)。

默认的Microsoft C ++容器映像具有许多其他软件包,适用于已安装在容器中的托管C / C ++开发,例如(在撰写本文时)

最后,我们可以构建“应用程序”。在VSCode终端窗口中,构建CMake项目,例如:

vscode➜/ workspaces / ms-cpp $ mkdir build&& cd buildmkdir:创建目录' / workspaces / ms-cpp / buildvscode➜/ workspaces / ms-cpp / build $ cmake ..-C编译器标识为GNU 9.3.0-CXX编译器标识为GNU 9.3.0-检查工作的C编译器:/ usr / bin / cc--检查工作的C编译器:/ usr / bin / cc-工作-检测C编译器ABI信息-检测C编译器ABI信息-完成-检测C编译功能-检测C编译功能-完成-检查工作的CXX编译器:/ usr / bin / c ++-检查工作的CXX编译器:/ usr / bin / c ++-工作-检测CXX编译器ABI信息-检测CXX编译器ABI信息-完成-检测CXX编译功能-检测CXX编译功能-完成-配置完成-生成完成-构建文件已写入到/ workspaces / ms- cpp / buildvscode➜/ workspaces / ms-cpp / build $ make扫描目标App的依赖项[50%]构建CXX对象CMakeFiles / App.dir / main.cpp.o [100%]链接CXX可执行App [100%]构建目标Appvscode➜/工作区s / ms-cpp / build $ ./Dev Containers的App Hello

那么,这一切如何运作?如果检查项目,将看到创建了一个.devcontainer文件夹以及两个文件:

devcontainer.json文件引用了定义核心Microsoft C ++ Docker映像的Dockerfile。如果您了解Docker,则文件非常直观。在下一个示例中,我们将以此为基础。

默认的Microsoft映像不包括使用Googletest,GoogleMock或其他构建系统(例如Meson Build系统)的功能。

我们可以构建自己的Docker映像并将其存储在Dockerhub上,如前所示。但是,根据您的容器要求的复杂性,可以更轻松地在基础Microsoft Dockerfile上构建并添加所需的软件包。

使用上一个“ hello world”项目,我们想使用GoogleTest编写一个简单的测试。

#[可选]取消注释此部分以安装其他软件包。#RUN apt-get update&&导出DEBIAN_FRONTEND =非交互式\#&& apt-get -y install --no-install-recommends< your-package-list-here>

并且可以使用apt软件包管理器进行安装。由于GoogleMock依赖于GoogleTest,因此我们只需要指定软件包libgmock-dev,apt还将安装libgtest-dev。取消注释并修改Dockerfile中的行以读取:

重新打开容器中的工作空间(可能会提示您重新构建容器–如果是,则选择rebuild选项)。我们可以通过创建一个简单的测试文件test.cpp来快速测试是否已安装GoogleTest:

vscode➜/ workspaces / ms-cpp $ mkdir build&& cd buildmkdir:创建目录' build' / workspaces / ms-cpp / buildvscode➜/ workspaces / ms-cpp / build $ cmake .....-配置完成-生成完成-构建文件具有写入到:/ workspaces / ms-CPP / build

vscode➜/ workspaces / ms-cpp / build $ make [50%]构建CXX对象CMakeFiles / gtest_test.dir / test.cpp.o [100%]链接CXX可执行文件gtest_test [100%]构建目标gtest_test

vscode➜/ workspaces / ms-cpp / build $ ctest -VUpdateCTestConfiguration来自:/workspaces/ms-cpp/build/DartConfiguration.tclUpdateCTestConfiguration来自:/workspaces/ms-cpp/build/DartConfiguration.tclTest项目/ workspaces / ms-cpp /构建构建测试列表完成构建测试列表更新夹具的测试列表☎0满足夹具要求的测试检查测试依赖图...检查测试依赖图endtest 1开始1:FailingTest1:测试命令:/ workspaces / ms-cpp / build / gtest_test1 :测试超时计算为:100000001:从/build/googletest-j5yxiC/googletest-1.10.0/googletest/src/gtest_main.cc1运行main():[==========]正在运行1个测试来自1个测试套件。1:[----------]全局测试环境设置。1:[----------]来自setup_test_case1的1个测试:[RUN] setup_test_case。 testWillFail1:/workspaces/ms-cpp/test.cpp:4:Failure1:这些值的预期相等:1:421:01:[失败] setup_test_case.testWillFail(0 ms)1:[-------- -]来自setup_tes的1个测试t_case(总计0毫秒)1:1:[----------]全局测试环境拆解1:[==========]从1个测试套件中运行了1个测试。 (总计0毫秒)1:[通过] 0个测试。1:[失​​败] 1个测试,列出如下:1:[失败] setup_test_case.testWillFail1:1:1失败的TEST1 / 1测试#1:FailingTest ..... ........ ***失败0.01秒0%测试通过,1个测试中有1个失败总测试时间(真实)= 0.04秒以下测试失败:1-不通过测试(失败运行CTest时出现错误

最后,我们不是使用CMake / make进行构建,而是选择使用Meson和Ninja进行项目。 Meson是基于Python的构建系统,我发现它比CMake直观得多(注意:CMake还可以生成Ninja生成文件而不是Makefile)。

将介子添加到apt软件包列表中。也值得添加pkg-config,并且介子在查找软件包依赖项时会使用它(这不是必不可少的,但可以使事情更清洁)。

运行apt-get update&&导出DEBIAN_FRONTEND =非交互式\&& apt-get -y install --no-install-recommends libgmock-dev介子pkg-config

项目(' tdd-cpp',' cpp',default_options:[' cpp_std = c ++ 17'])gtest_dep =依赖项(' gtest&# 39; main:true,必需:true)gmock_dep =依赖关系(' gmock&#39 ;, main:true,必需:true)gtest_test =可执行文件(' gtest_test&#39 ;,来源:[&# 39; test.cpp&#39 ;,],依赖项:[gtest_dep,])test(' failing_test&#39 ;, gtest_test)

vscode➜/ workspaces / ms-cpp $ meson builddir&& cd builddir Meson构建系统版本:0.53.2源目录:/ workspaces / ms-cppBuild目录:/ workspaces / ms-cpp / builddir构建类型:本机build项目名称:tdd-cpp项目版本:主机的未定义C ++编译器:c ++(gcc 9.3。 0" c ++(Ubuntu 9.3.0-17ubuntu1〜20.04)9.3.0")主机的C ++链接器:c ++ ld.bfd 2.34主机cpu系列:x86_64主机cpu:x86_64找到pkg-config:/ usr / bin / pkg-config(0.29.1)找到运行时相关的GTest:是1.10.0找到运行时相关的GMock:是1.10.0在项目中构建目标:1在/ usr / bin / ninja中找到了ninja-1.10.0 / workspaces / ms-cpp / builddir

vscode➜/ workspaces / ms-cpp / builddir $介子测试-vninja:输入目录`/ workspaces / ms-cpp / builddir' [2/2]链接目标gtest_test。从/ build / googletest-j5yxiC运行main() /googletest-1.10.0/googletest/src/gtest_main.cc[==========]从1个测试套件中运行1个测试。[----------]全局测试环境集-up。[----------] 1个来自setup_test_case [RUN] setup_test_case.testWillFail ../ test.cpp:4的测试:失败这些值的期望相等性:42 0 [FAILED] setup_test_case.testWillFail(0 ms)[----------]从setup_test_case中进行1个测试(总计0 ms)[----------]删除整个测试环境[======== ==]运行了1个测试套件中的1个测试。 (总计1毫秒)[通过] 0个测试。[失败] 1个测试,列出如下:[失败] setup_test_case.testWillFail 1失败TEST1 / 1 failureing_test失败0.01 s(退出状态1)确定:0预期失败:0

通过devcontainer.json文件,可以配置和扩展创建的容器(devcontainer.json参考),包括VSCode扩展(Visual Studio Marketplace)。

例如,介子和GoogleTest都可以使用VSCode扩展名。有许多特定的扩展,在这里我们将使用asabil.meson和C ++ TestMate。可以使用devcontainer.json文件将它们添加到容器配置中,例如

//添加创建容器时要安装的扩展的ID。 "扩展名&#34 ;: [" ms-vscode.cpptools&#34 ;、" asabil.meson&#34 ;、" matepek.vscode-catch2-test-adapter" ],

现在,当我们打开容器时,存在扩展名,并允许我们管理项目。

在急忙将所有项目转换为VSCode Dev Containers之前,我遇到了两个问题。

首先,我们现有的某些容器,尤其是针对小尺寸进行了优化的容器(特别是基于多层构建的基于高山的映像)无法使用Dev Containers运行。我还没有深入探讨这些问题(还有另一个待办事项)。

另外,在现有的Dockerfile大量使用bash脚本进行内部配置时,我遇到了问题。这些脚本通常围绕特定的路径配置构建。使用Dev Containers时,工作空间安装在内部路径/ workspaces /< git repo name>下。并可能导致脚本失败。看来可以使用高级容器配置进行管理,但这是我还需要尝试的另一件事。

容器技术(特别是Docker)与VSCode的集成创建了一个令人兴奋的开发环境。通过确保使用Docker的通用构建和测试环境,它巩固了本地TDD开发和CI管道构建之间的关系。

示例CMake和介子项目是基本项目,并不打算代表现实世界中的CMake或介子项目,但希望能够继续进行下去。可以在这里找到Meson / gtest / gmock示例项目,虽然稍微好一点,但还算不完整。

如果Dev Containers激起了您的兴趣,那么您会喜欢Codespaces·GitHub。 GitHub Codepsaces是下一篇文章的主题。