drake 与 OpenSUSE 的集成 - spdlog 和 fmt 的构建错误

问题描述 投票:0回答:1

我创建了这个 GitHub repository,其中包含 OpenSUSE 15.4 docker 文件,我试图在其中集成 OpenSUSE 的 Drake 模拟。我尝试在 Docker 映像中运行 Drake 存储库中的以下构建步骤:

  • dan@d10fea7706bb:~/drake/cmake> cmake ..
  • dan@d10fea7706bb:~/drake/cmake> make install

我得到以下涉及 spdlog 和 fmt 的非常长的错误回溯:

https://gist.github.com/hedaniel7/9b74a2b2c6a6ec625e94ab85cc0f395d

这是一个小样本:

ERROR: /home/dan/drake/common/BUILD.bazel:307:17: Compiling common/find_resource.cc failed: (Exit 1): gcc-10 failed: error executing command (from target //common:_find_resource_compiled_cc_impl) /usr/bin/gcc-10 -U_FORTIFY_SOURCE -fstack-protector -Wall -Wunused-but-set-parameter -Wno-free-nonheap-object -fno-omit-frame-pointer -g0 -O2 '-D_FORTIFY_SOURCE=1' -DNDEBUG -ffunction-sections ... (remaining 71 arguments skipped)

Use --sandbox_debug to see verbose messages from the sandbox and retain the sandbox build root for debugging
In file included from external/fmt/include/_usr_local_include/spdlog/fmt/fmt.h:28,
                 from external/fmt/include/_usr_local_include/spdlog/common.h:50,
                 from external/fmt/include/_usr_local_include/spdlog/spdlog.h:12,
                 from bazel-out/k8-opt/bin/common/_virtual_includes/essential/drake/common/text_logging.h:85,
                 from common/find_resource.cc:17:
external/fmt/include/_usr_local_include/spdlog/fmt/bundled/core.h:308:30: error: redefinition of 'struct fmt::v10::type_identity<T>'
  308 | template <typename T> struct type_identity { using type = T; };
      |                              ^~~~~~~~~~~~~
In file included from external/fmt/include/_usr_local_include/fmt/format.h:54,
                 from common/find_resource.cc:10:
external/fmt/include/_usr_local_include/fmt/base.h:301:30: note: previous definition of 'struct fmt::v10::type_identity<T>'
  301 | template <typename T> struct type_identity {
      |                              ^~~~~~~~~~~~~
In file included from external/fmt/include/_usr_local_include/spdlog/fmt/fmt.h:28,
                 from external/fmt/include/_usr_local_include/spdlog/common.h:50,
                 from external/fmt/include/_usr_local_include/spdlog/spdlog.h:12,
                 from bazel-out/k8-opt/bin/common/_virtual_includes/essential/drake/common/text_logging.h:85,
                 from common/find_resource.cc:17:
external/fmt/include/_usr_local_include/spdlog/fmt/bundled/core.h:325:8: error: redefinition of 'struct fmt::v10::monostate'

问题可能与警告有关

DEBUG: /home/dan/drake/tools/workspace/pkg_config.bzl:240:18: pkg-config of fmt returned an include path that contains /usr/local/include that may contain unrelated headers
DEBUG: /home/dan/drake/tools/workspace/pkg_config.bzl:240:18: pkg-config of fmt returned an include path that contains /usr/local/include that may contain unrelated headers
DEBUG: /home/dan/drake/tools/workspace/pkg_config.bzl:240:18: pkg-config of spdlog returned an include path that contains /usr/local/include that may contain unrelated headers

我在上面的终端交互要点中得到了

这是我使用的 Dockerfile(也可以在 GitHub 存储库中查看)

# Use OpenSUSE Leap 15.4 as base
FROM opensuse/leap:15.4

# Install vim, sudo, and other necessary tools and libraries for drake
RUN zypper --non-interactive update && \
    zypper --non-interactive install -y vim sudo git cmake make java-1_8_0-openjdk-devel \
    glib2-devel lapack-devel libX11-devel ocl-icd-devel opencl-headers patch patchelf \
    pkg-config python3-devel python3-pygame zlib-devel pkg-config eigen3-devel \
    libmumps5 mumps-devel gcc-fortran nasm wget llvm-clang llvm-clang-devel

# Add the repository for GCC 10
RUN zypper addrepo -f http://download.opensuse.org/repositories/devel:/gcc/openSUSE_Leap_15.4/ devel_gcc && \
    zypper --non-interactive --gpg-auto-import-keys refresh && \
    zypper --non-interactive install -y gcc10 gcc10-c++

# Set GCC 10 as the default compiler
RUN update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-10 100 --slave /usr/bin/g++ g++ /usr/bin/g++-10 && \
    update-alternatives --install /usr/bin/cc cc /usr/bin/gcc 30 && \
    update-alternatives --set cc /usr/bin/gcc && \
    update-alternatives --install /usr/bin/c++ c++ /usr/bin/g++ 30 && \
    update-alternatives --set c++ /usr/bin/g++

# Clone, build, and install fmt and spdlog from source
RUN cd /tmp && \
    git clone https://github.com/fmtlib/fmt.git && \
    cd fmt && mkdir build && cd build && cmake .. && make install && \
    cd /tmp && \
    git clone https://github.com/gabime/spdlog.git && \
    cd spdlog && mkdir build && cd build && cmake .. && make install

# Install Bazelisk
RUN curl -L https://github.com/bazelbuild/bazelisk/releases/download/v1.7.5/bazelisk-linux-amd64 > /usr/local/bin/bazelisk && \
    chmod +x /usr/local/bin/bazelisk && \
    ln -s /usr/local/bin/bazelisk /usr/local/bin/bazel

# Download and place jchart2d-3.3.2.jar in /usr/share/java/jchart2d.jar
RUN wget https://repo1.maven.org/maven2/net/sf/jchart2d/jchart2d/3.3.2/jchart2d-3.3.2.jar -O /usr/share/java/jchart2d.jar

# Create .pc files for LAPACK and BLAS
RUN echo -e "prefix=/usr\nexec_prefix=\${prefix}\nlibdir=\${exec_prefix}/lib64\nincludedir=\${prefix}/include\n\nName: LAPACK\nDescription: Linear Algebra Package\nVersion: 3.9.0\nLibs: -L\${libdir} -llapack\nCflags: -I\${includedir}" > /usr/share/pkgconfig/lapack.pc && \
    echo -e "prefix=/usr\nexec_prefix=\${prefix}\nlibdir=\${exec_prefix}/lib64\nincludedir=\${prefix}/include\n\nName: BLAS\nDescription: Basic Linear Algebra Subprograms\nVersion: 3.9.0\nLibs: -L\${libdir} -lblas\nCflags: -I\${includedir}" > /usr/share/pkgconfig/blas.pc

# Set up the environment for user 'dan'
RUN groupadd -r dan && \
    useradd -m -s /bin/bash -r -g dan dan && \
    mkdir -p /home/dan/drake && \
    chown -R dan:dan /home/dan/drake && \
    echo "dan ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers

# Switch to user 'dan' before installing pyenv and Python
USER dan
ENV HOME /home/dan
WORKDIR $HOME

# Install dependencies for pyenv and Python build
RUN sudo zypper --non-interactive install -y git gcc make zlib-devel libbz2-devel libopenssl-devel readline-devel sqlite3-devel tar gzip


# Install pyenv and Python 3.10
RUN git clone https://github.com/pyenv/pyenv.git $HOME/.pyenv && \
    echo 'export PYENV_ROOT="$HOME/.pyenv"' >> $HOME/.bashrc && \
    echo 'export PATH="$PYENV_ROOT/bin:$PATH"' >> $HOME/.bashrc && \
    echo -e 'if command -v pyenv 1>/dev/null 2>&1; then\n  eval "$(pyenv init --path)"\nfi' >> $HOME/.bashrc && \
    /bin/bash -c "source $HOME/.bashrc && pyenv install 3.10.0 && pyenv global 3.10.0"

# Ensure the selected Python version 3.10 is used and install PyYAML
RUN /bin/bash -c "source $HOME/.bashrc && pyenv rehash && pip install PyYAML"

# Set environment variables for GCC to ensure Bazel uses the correct version
ENV CC=/usr/bin/gcc-10
ENV CXX=/usr/bin/g++-10
ENV PYENV_ROOT $HOME/.pyenv
ENV PATH $PYENV_ROOT/shims:$PYENV_ROOT/bin:$PATH

我从 GitHub 存储库的源代码构建了

spdlog
fmt
,以规避 Bazel 抱怨没有找到它之前的问题。

我做了一个小测试,我用

spdlog
fmt
编写了一个最小的 C++ 程序,看看它是否可以编译并运行:

dan@fae637d1a972:~> vim spdlogfmtHelloworld.cpp

#include <spdlog/spdlog.h>
#include <fmt/core.h>

int main() {
    // Using fmt to format a string
    std::string name = "World";
    std::string formatted = fmt::format("Hello, {}!", name);

    // Using spdlog to log the formatted string
    spdlog::info(formatted);

    return 0;
}
dan@fae637d1a972:> g++ main.cpp -o myprogram -lspdlog -lfmt
g++: error: main.cpp: No such file or directory
dan@fae637d1a972:> g++ spdlogfmtHelloworld.cpp -o myprogram -lspdlog -lfmt
dan@fae637d1a972:> ./myprogram
[2024-03-07 13:17:25.889] [info] Hello, World!

OpenSUSE libfmt8 包的旁注

  • 如果我只安装 libfmt8 而没有从源代码构建

    fmt
    ,Bazel 会提前抱怨它找不到 fmt。

  • 如果我安装 libfmt8 并从源代码构建

    fmt
    ,我可能会得到与上面相同的错误

重现错误的步骤:

  • git clone https://github.com/hedaniel7/Drake-OpenSUSE-Integration
  • cd Drake-OpenSUSE-Integration
  • git checkout 6c1eddf5ad19b34e8395533d93829a56e6ccef71
  • docker-compose build --no-cache
    (在 Surfacebook 3、Ubuntu 22.04 上大约需要 10 分钟)
  • docker-compose run drake-opensuse
bazel opensuse drake fmt spdlog
1个回答
0
投票

当使用用户提供的 fmt 和 spdlog 通过 CMake 构建 Drake 时,典型的方法是指示 Drake 的 CMake 代码使用

find_package()
来定位这些依赖项,即

cmake \
    -DWITH_USER_FMT:BOOLEAN=ON \
    -DWITH_USER_SPDLOG:BOOLEAN=ON

这会跳过 pkg-config 逻辑,否则默认情况下 Drake 内部会发生这种情况。

事实上,最典型的做法是让整个 CMakeLists 项目构建这些项目,而不是使用 Dockerfile(如 https://github.com/RobotLocomotion/drake-external-examples/blob/main/drake_cmake_external/CMakeLists 所示) .txt )但这并不是严格要求的。

要点是打开“WITH_USER_FMT”等,并确保您已以 CMake 能够找到的方式构建 fmt 和 spdlog(或者您已设置

CMAKE_PREFIX_PATH
来帮助找到它们)。

查看要点输出,另一个问题是您的

spdlog
构建正在使用
fmt
的捆绑副本。您需要配置 spdlog 构建以使用已构建的 fmt 副本,如
-DSPDLOG_FMT_EXTERNAL:BOOLEAN=ON
所示(请参阅此处)。


大局:如果 SUSE 已经有 spdlog 或 fmt 的任何构建,那么最好使用它们而不是从源代码构建。可能WITH_USER_FMT等带有适当的CMake前缀路径会找到SUSE的。

© www.soinside.com 2019 - 2024. All rights reserved.