构建一个可以使用LLVM编译ROS项目的docker镜像

build a docker image that can use LLVM to compile ROS projects

我打算构建一个可以使用 LLVM 编译 ROS 项目代码的 Docker 映像。根据Docker的官方文档https://docs.docker.com/config/containers/multi-service_container/,最好避免在一个容器中使用多个服务。 LLVM 和 ROS 都得到了它们的 Docker 图像,如何将它们合二为一并一起发布?

更新(2019.12.13):

如果您想在官方 ROS docker 图像中使用 clang,您可以这样做:

FROM ros:melodic
RUN apt-get -y install clang-6.0
RUN update-alternatives --install /usr/bin/c++ c++ $(command -v clang++-6.0) 1000
RUN update-alternatives --install /usr/bin/cc  cc  $(command -v clang-6.0)   1000

您可以这样做,因为官方 ROS 图像继承自 Ubuntu 图像,这些图像使用 update-alternatives 来管理通用命令(例如,C/C++ 编译器)如何映射到包提供它们。简而言之,对 update-alternatives 的调用将安装各种符号链接,使得 /usr/bin/cc/usr/bin/c++ 都(最终)分别指向 clang-6.0clang++-6.0

有关 update-alternatives 工作原理的详细信息,请参阅其 man page

原回答如下。


您有一些可用的策略:

合并 Dockerfiles

如果您可以访问两个 Dockerfile,请尝试将其中的内容合并为一个Dockerfile。您必须选择一条 FROM 指令,但可以按照您选择的方式组合其他指令。

在一个

上更改FROM

如果您只能访问 一个 Dockerfile,请尝试更改其 FROM 指令以从另一个图像继承。例如,ros:kinetic-ros-core-xenial 图像继承自 ubuntu:xenial;尝试将其更改为继承自 reaverproject/llvm.

ADD 两个压缩包

如果您无法访问 Dockerfile,那么您将不得不进行一些逆向工程。首先从每个图像创建一个 "noop" 容器并从中 exporting 一个文件系统 tarball。即,做...

$ docker container run --name noop-foobar foobar sh -c 'exit 0'
$ docker container export --output foobar.tar noop-foobar
$ docker container rm noop-foobar

...根据需要替换 "foobar"。

导出两个文件系统 tarball 后,通过 ADD 将它们转成 scratch 图像来创建 "base image":

FROM scratch
ADD llvm.tar
ADD ros.tar
...

您很可能必须手动解决文件系统 tarball 之间的冲突才能使基本映像按预期工作。

参考文献: