如何将 CMake 设置为与嵌入在 Windows 上的 ARM 的 clang 交叉编译? [英] How to set up CMake to cross compile with clang for ARM embedded on Windows?

查看:33
本文介绍了如何将 CMake 设置为与嵌入在 Windows 上的 ARM 的 clang 交叉编译?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试生成 Ninja 生成文件,以使用 Clang 为 ARM Cortex A5 CPU 交叉编译 C++ 项目.我为 CMake 创建了一个工具链文件,但似乎存在我无法找到的错误或缺失的内容.当使用下面的工具链文件调用 CMake 时,我收到以下错误.

I'm trying to generate Ninja makefiles to cross compile a C++ project with Clang for an ARM Cortex A5 CPU. I created a toolchain file for CMake but it seems like there is an error or something missing which I'm unable to find. When invoke CMake with the toolchain file below I get the following error.

CMake 命令:

cmake -DCMAKE_TOOLCHAIN_FILE="..\Src\Build\Toolchain-clang-arm.cmake"-GNinja ..\Src\

cmake -DCMAKE_TOOLCHAIN_FILE="..\Src\Build\Toolchain-clang-arm.cmake" -GNinja ..\Src\

输出:

-- C 编译器标识是 Clang 7.0.0 CMake Error at C:/Users/user/scoop/apps/cmake/3.13.4/share/cmake-3.13/Modules/CMakeDetermineCompilerId.cmake:802(消息):Clang 编译器工具

-- The C compiler identification is Clang 7.0.0 CMake Error at C:/Users/user/scoop/apps/cmake/3.13.4/share/cmake-3.13/Modules/CMakeDetermineCompilerId.cmake:802 (message): The Clang compiler tool

"C:/Program Files/LLVM/bin/clang.exe"

"C:/Program Files/LLVM/bin/clang.exe"

以 MSVC ABI 为目标,但具有类似 GNU 的命令行界面.这不受支持.使用 'clang-cl' 代替,例如通过设置'CC=clang-cl' 在环境中.此外,使用 MSVC命令行环境.调用堆栈(最近调用优先):
C:/Users/user/scoop/apps/cmake/3.13.4/share/cmake-3.13/Modules/CMakeDetermineCCompiler.cmake:113(CMAKE_DIAGNOSE_UNSUPPORTED_CLANG) CMakeLists.txt:2 (PROJECT)

targets the MSVC ABI but has a GNU-like command-line interface. This is not supported. Use 'clang-cl' instead, e.g. by setting 'CC=clang-cl' in the environment. Furthermore, use the MSVC command-line environment. Call Stack (most recent call first):
C:/Users/user/scoop/apps/cmake/3.13.4/share/cmake-3.13/Modules/CMakeDetermineCCompiler.cmake:113 (CMAKE_DIAGNOSE_UNSUPPORTED_CLANG) CMakeLists.txt:2 (PROJECT)

-- 配置不完整,出现错误!

-- Configuring incomplete, errors occurred!

CMake 工具链文件(Toolchain-clang-arm.cmake):

CMake toolchain file (Toolchain-clang-arm.cmake):

set(CMAKE_CROSSCOMPILING TRUE)
SET(CMAKE_SYSTEM_NAME Generic)
set(CMAKE_SYSTEM_PROCESSOR arm)

# Clang target triple
SET(TARGET armv7-none-eabi)

# specify the cross compiler
SET(CMAKE_C_COMPILER_TARGET ${TARGET})
SET(CMAKE_C_COMPILER clang)
SET(CMAKE_CXX_COMPILER_TARGET ${TARGET})
SET(CMAKE_CXX_COMPILER clang++)
SET(CMAKE_ASM_COMPILER_TARGET ${TARGET})
SET(CMAKE_ASM_COMPILER clang)

# C/C++ toolchain
SET(TOOLCHAIN "C:/Program Files (x86)/GNU Tools ARM Embedded/7 2018-q2-update")
SET(CMAKE_C_COMPILER_EXTERNAL_TOOLCHAIN ${TOOLCHAIN})
SET(CMAKE_CXX_COMPILER_EXTERNAL_TOOLCHAIN ${TOOLCHAIN})

# specify compiler flags
SET(ARCH_FLAGS "-target armv7-none-eabi -mcpu=cortex-a5")
SET(CMAKE_C_FLAGS "-Wall -Wextra ${ARCH_FLAGS}" CACHE STRING "Common flags for C compiler")
SET(CMAKE_CXX_FLAGS "-Wall -Wextra -std=c++11 -fno-exceptions -fno-threadsafe-statics ${ARCH_FLAGS}" CACHE STRING "Common flags for C++ compiler")

我使用了 CMakeClang 文档和一些 随机链接 来自网络以创建工具链文件.整个项目使用 ARM GCC for Windows 编译得很好,所以工具链文件似乎是唯一缺少的部分.

I used the CMake and Clang documentation and some random link from the net to create the toolchain file. The whole project compiles fine with ARM GCC for Windows, so the toolchain file seems to be the only missing piece of the puzzle.

编辑

我试图通过强制编译器来解决 CMake 编译器检查.我用 SET(CMAKE_C_COMPILER clang), SET(CMAKE_CXX_COMPILER clang++) 等替换了这些行:

I tried to work around the CMake compiler checks by forcing the compiler. I replace the lines with SET(CMAKE_C_COMPILER clang), SET(CMAKE_CXX_COMPILER clang++) etc. with:

CMAKE_FORCE_C_COMPILER(clang Clang)
CMAKE_FORCE_CXX_COMPILER(clang++ Clang)

错误保持不变.

编辑

我可以使用 clang -target arm-none-eabi 成功编译一个 hello world 示例.所以问题似乎出在 CMake 中.我在 CMake 问题跟踪器中创建了一个 bug.

I can successfully compile a hello world example with clang -target arm-none-eabi. So the issue seems to be in CMake. I created a bug in the CMake issue tracker.

工具版本:

  • clang 7.0.0 版(标签/RELEASE_700/final)
  • cmake 3.13.4 版

推荐答案

我的问题已通过 回复 我的错误报告,但我在此处添加了答案,以便将所有信息集中在一处以供将来参考.

My question was answered through the reply to my bug report, but I add the answer here to have all information in one place for future reference.

简而言之:如果您从 llvm.org.如果您想使用 clang/clang++ 接口(这是为 ARM 交叉编译所必需的),您必须通过 msys2 安装 Clang.

In short: CMake currently does not support to use the clang/clang++ command line interface if you install Clang from llvm.org. If you want to use the clang/clang++ interface (which is necessary to cross-compile for ARM) you have to install Clang via msys2.

详细

Windows 上的 Clang 有两个不同的命令行界面:

Clang on Windows has two different command line interfaces:

  • clang/clang++ 试图成为的默认界面与 GCCs gcc/g++ 兼容并针对 GNU ABI
  • clang-cl 试图与微软的 Visual C++ 兼容编译器 cl.exe 并针对 MSVC ABI
  • clang/clang++ the default interface that attempts to be compatible with GCCs gcc/g++ and targets the GNU ABI
  • clang-cl that attempts to be compatible with Microsofts Visual C++ compiler cl.exe and targets the MSVC ABI

为了对 ARM 进行交叉编译,您需要 clang/clang++ 接口.问题是 CMake 支持不同的接口,具体取决于您安装 Clang 的方式(请参阅 bug在 CMake 问题跟踪器中了解更多详细信息):

In order to cross-compile for ARM you need the clang/clang++ interface. The Problem is CMake supports different interfaces depending on how you installed Clang (see the bug in the CMake issue tracker for more details):

  • 如果您从 llvm.org 安装 Clang,则 CMake 仅支持 clang-cl 接口.
  • 如果您通过 msys2 安装 Clang,则 CMake 支持 clang/clang++ 接口.
  • If you install Clang from llvm.org CMake only supports the clang-cl interface.
  • If you install Clang via msys2 CMake supports the clang/clang++ interface.

这就是我所做的:

  1. 安装msys2
  2. 使用 pacman 安装 Clang 和 CMake.msys2中有两个clang包,一个mingw32和一个mingw64版本.我使用了 mingw64 包 (mingw-w64-x86_64-clang).
  3. 启动 mingw64 shell 并运行 CMake 并从那里构建.
  1. Install msys2
  2. Install Clang and CMake with pacman. There are two clang packages in msys2, a mingw32 and a mingw64 version. I used the mingw64 package (mingw-w64-x86_64-clang).
  3. Launch the mingw64 shell and run CMake and build from there.

工具链文件

我的原始工具链文件有两个问题花了我很长时间才修复.所以我希望这会为其他人节省一些时间:

There were two problems with my original toolchain file that took my a long time to fix. So I hope this will save others some time:

  1. 目标三元组(例如 arm-none-eabi)需要匹配 GCC binutils 的前缀完全.我的 binutils 的前缀是 arm-none-eabi(例如 arm-none-eabi-ar),所以我不得不相应地更改目标三元组.
  2. CMAKE_TRY_COMPILE_TARGET_TYPE 需要更改为 STATIC_LIBRARY 才能防止 CMake 在编译检查期间运行链接器.
  1. The target triple (e.g. arm-none-eabi) needs to match the prefix of the GCC binutils exactly. The prefix of my binutils was arm-none-eabi (e.g. arm-none-eabi-ar) so I had to change the target triple accordingly.
  2. CMAKE_TRY_COMPILE_TARGET_TYPE needs to be changed to STATIC_LIBRARY in order to prevent CMake from running the linker during the compile check.

这是我使用的最终工具链文件(您还可以在此GitHub 存储库):

Here is the final toolchain file I used (you can also find a good example for a toolchain file in this GitHub repo):

cmake_minimum_required(VERSION 3.13)

set(CMAKE_SYSTEM_NAME Generic)
set(CMAKE_SYSTEM_PROCESSOR ARM)

if(DEFINED ENV{GCC_ARM_TOOLCHAIN})
    set(GCC_ARM_TOOLCHAIN $ENV{GCC_ARM_TOOLCHAIN})
else()
    set(GCC_ARM_TOOLCHAIN "C:/Users/user/tools/gcc-arm-none-eabi-7-2018-q2-update-win32")
endif()

LIST(APPEND CMAKE_PROGRAM_PATH ${GCC_ARM_TOOLCHAIN})

# Specify the cross compiler
# The target triple needs to match the prefix of the binutils exactly
# (e.g. CMake looks for arm-none-eabi-ar)
set(CLANG_TARGET_TRIPLE arm-none-eabi)
set(GCC_ARM_TOOLCHAIN_PREFIX ${CLANG_CLANG_TARGET_TRIPLE})
set(CMAKE_C_COMPILER clang)
set(CMAKE_C_COMPILER_TARGET ${CLANG_TARGET_TRIPLE})
set(CMAKE_CXX_COMPILER clang++)
set(CMAKE_CXX_COMPILER_TARGET ${CLANG_TARGET_TRIPLE})
set(CMAKE_ASM_COMPILER clang)
set(CMAKE_ASM_COMPILER_TARGET ${CLANG_TARGET_TRIPLE})

# Don't run the linker on compiler check
set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)

# Specify compiler flags
set(ARCH_FLAGS "-mcpu=cortex-a5 -mthumb -mfpu=neon-vfpv4 -mfloat-abi=hard -mno-unaligned-access")
set(CMAKE_C_FLAGS "-Wall ${ARCH_FLAGS}" CACHE STRING "Common flags for C compiler")
set(CMAKE_CXX_FLAGS "-Wall -std=c++17 -fno-exceptions -fno-rtti -fno-threadsafe-statics ${ARCH_FLAGS}" CACHE STRING "Common flags for C++ compiler")
set(CMAKE_ASM_FLAGS "-Wall ${ARCH_FLAGS} -x assembler-with-cpp" CACHE STRING "Common flags for assembler")
set(CMAKE_EXE_LINKER_FLAGS "-nostartfiles -Wl,-Map,kernel.map,--gc-sections -fuse-linker-plugin -Wl,--use-blx --specs=nano.specs --specs=nosys.specs" CACHE STRING "")

# C/C++ toolchain
set(GCC_ARM_SYSROOT "${GCC_ARM_TOOLCHAIN}/${GCC_ARM_TOOLCHAIN_PREFIX}")
# set(CMAKE_SYSROOT ${GCC_ARM_SYSROOT})
set(CMAKE_FIND_ROOT_PATH ${GCC_ARM_SYSROOT})

# Search for programs in the build host directories
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
# For libraries and headers in the target directories
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)

这篇关于如何将 CMake 设置为与嵌入在 Windows 上的 ARM 的 clang 交叉编译?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆