【问题标题】:How to get standard library c++ using clang for cross compiling如何使用clang获取标准库c++进行交叉编译
【发布时间】:2019-10-01 23:32:17
【问题描述】:

首先:我已经阅读了所有类似的帖子,并且一直在寻找一个多星期。问题不再重复,我搜索了很多。

基本上我正在尝试使用 docker 使用 clang 作为 raspberry pi 3 的交叉编译器来编译一个简单的 helloWorld c++ 程序。

我正在使用虚拟机 Ubuntu 18.04

编译器clang 8 当我使用clang交叉编译docker中的代码时:

致命错误:'bits/c++config.h' 没有这样的文件或目录...

这里是 CMakeLists.txt 文件

cmake_minimum_required(VERSION 3.7.2)

set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR arm)

set(triple arm-linux-gnueabihf)

set(CMAKE_C_COMPILER clang)
set(CMAKE_C_COMPILER_TARGET ${triple})
set(CMAKE_CXX_COMPILER clang++)
set(CMAKE_CXX_COMPILER_TARGET ${triple})
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17")

set(DCMAKE_CROSSCOMPILING=True)
set(DLLVM_DEFAULT_TARGET_TRIPLE=arm-linux-gnueabihf)
set(DLLVM_TARGET_ARCH=ARM)
set(DLLVM_TARGETS_TO_BUILD=ARM)

#executing...
project (arm_cross)
add_executable(hello hello.cpp )

我希望在调用 make 后得到 arm 的可执行文件

【问题讨论】:

    标签: clang++ llvm-clang


    【解决方案1】:

    我从未与 docker 打过交道。但是半年前,我也遇到了在mac os下交叉编译raspberry代码的问题。反正我用clang作为工具链,终于成功了。

    关键是要为clang提供好的目标rootfs。我刚刚通过 sshfs 安装了真正的树莓派。

    还有一点是我没有将编译器设置放入CMakeLists.txt,而是提供了带有工具链文件的cmake。

    我的 cmake 工具链文件:

    SET(CMAKE_SYSTEM_VERSION 1)
    set(CMAKE_SYSTEM_NAME Linux)
    set(CMAKE_SYSTEM_PROCESSOR arm)
    
    # Custom toolchain-specific definitions for your project
    set(PLATFORM_ARM "1")
    set(PLATFORM_COMPILE_DEFS "COMPILE_GLES")
    
    # There we go!
    # Below, we specify toolchain itself!
    
    SET(TARGET_TRIPLE arm-linux-gnueabihf)
    
    # Specify your target rootfs mount point on your compiler host machine
    SET(TARGET_ROOTFS /Volumes/rootfs-${TARGET_TRIPLE})
    
    # Specify clang paths
    SET(LLVM_DIR /Users/stepan/projects/shared/toolchains/llvm-7.0.darwin-release-x86_64/install)
    SET(CLANG ${LLVM_DIR}/bin/clang)
    SET(CLANGXX ${LLVM_DIR}/bin/clang++)
    
    # Specify compiler (which is clang)
    SET(CMAKE_C_COMPILER   ${CLANG})
    SET(CMAKE_CXX_COMPILER ${CLANGXX})
    
    # Specify binutils
    
    SET (CMAKE_AR      "${LLVM_DIR}/bin/llvm-ar" CACHE FILEPATH "Archiver")
    SET (CMAKE_LINKER  "${LLVM_DIR}/bin/llvm-ld" CACHE FILEPATH "Linker")
    SET (CMAKE_NM      "${LLVM_DIR}/bin/llvm-nm" CACHE FILEPATH "NM")
    SET (CMAKE_OBJDUMP "${LLVM_DIR}/bin/llvm-objdump" CACHE FILEPATH "Objdump")
    SET (CMAKE_RANLIB  "${LLVM_DIR}/bin/llvm-ranlib" CACHE FILEPATH "ranlib")
    
    # You may use legacy binutils though.
    #SET(BINUTILS /usr/local/Cellar/arm-linux-gnueabihf-binutils/2.31.1)
    #SET (CMAKE_AR      "${BINUTILS}/bin/${TARGET_TRIPLE}-ar" CACHE FILEPATH "Archiver")
    #SET (CMAKE_LINKER  "${BINUTILS}/bin/${TARGET_TRIPLE}-ld" CACHE FILEPATH "Linker")
    #SET (CMAKE_NM      "${BINUTILS}/bin/${TARGET_TRIPLE}-nm" CACHE FILEPATH "NM")
    #SET (CMAKE_OBJDUMP "${BINUTILS}/bin/${TARGET_TRIPLE}-objdump" CACHE FILEPATH "Objdump")
    #SET (CMAKE_RANLIB  "${BINUTILS}/bin/${TARGET_TRIPLE}-ranlib" CACHE FILEPATH "ranlib")
    
    # Specify sysroot (almost same as rootfs)
    SET(CMAKE_SYSROOT ${TARGET_ROOTFS})
    SET(CMAKE_FIND_ROOT_PATH ${TARGET_ROOTFS})
    
    # Specify lookup methods for cmake
    set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
    set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
    set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
    
    # Sometimes you also need this:
    # set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
    
    # Specify raspberry triple
    set(CROSS_FLAGS "--target=${TARGET_TRIPLE}")
    
    # Specify other raspberry related flags
    set(RASP_FLAGS "-D__STDC_CONSTANT_MACROS -D__STDC_LIMIT_MACROS")
    
    # Gather and distribute flags specified at prev steps.
    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${CROSS_FLAGS} ${RASP_FLAGS}")
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CROSS_FLAGS} ${RASP_FLAGS}")
    
    # Use clang linker. Why?
    # Well, you may install custom arm-linux-gnueabihf binutils,
    # but then, you also need to recompile clang, with customized triple;
    # otherwise clang will try to use host 'ld' for linking,
    # so... use clang linker.
    set(CMAKE_EXE_LINKER_FLAGS ${CMAKE_EXE_LINKER_FLAGS} -fuse-ld=lld)
    

    我的文章有详细描述是here

    希望它会有所帮助。 我也将这个问题分为两个步骤: 1.通过clang编译获取。 2. 将编译设置集成到docker中。

    祝你好运!

    【讨论】:

    • 嘿@StepanDyatkovskiy 很久以前就看到了你的博客。我找到了一个不合适的解决方案,所以在 /usr/ 下我安装了 g++-7-arm-linux-gbueabihf 然后我得到了一个类似 /usr/arm-linux-gnueabihf 的目录。如果我从 /usr/include 中删除 include 并将 include 从 arm-linux-gnueabihf 移动到 up (一个文件夹向上),那么它就可以了。 ;(是什么原因导致这种行为?
    • 通常是由于将包含目录硬编码到编译器中而发生的。或者它硬编码了如何找到一些目录的方式。我怀疑,在您的情况下,gcc 期望在 /include// 中看到包含,其中“triple”是 arm-linux-gnueabihf。如果您可以修改要编译的应用程序的编译标志,只需将包含搜索路径“-I”添加到 CXXFLAGS。如果没有,那么最好的办法是遵循遗留应用程序构建说明,使用他们建议使用的工具链等等。
    • @ Stepan Dyatkovskiy 我也猜想编译器包含路径是硬编码的。我可以使用编译器参数忽略默认路径,但可以忽略或仅默认包含路径。因此我使用了工具链并建立了一个符号链接。谢谢!
    • @mWelt,不客气。使用 -### 选项干运行编译器也很有用。它将向您显示 gcc/clang 驱动程序在编译期间将调用的所有命令。例如。 "g++ -### test.cpp"
    【解决方案2】:

    解决方案如下我所做的 首先备份 /usr/include 然后将 /usr/arm/include 文件向上移动。最后运行你的 32 位 arm 应用程序。 此步骤可以通过简单的 shell 脚本自动执行。

    【讨论】:

      猜你喜欢
      • 2016-05-11
      • 2023-04-02
      • 2019-12-11
      • 2015-05-13
      • 1970-01-01
      • 1970-01-01
      • 2017-03-09
      • 2018-07-11
      • 1970-01-01
      相关资源
      最近更新 更多