如何设置CMake与Windows嵌入式ARM的clang进行交叉编译?

时间:2019-02-05 17:10:21

标签: c++ windows cmake arm clang

我正在尝试生成Ninja makefile,以使用Clang交叉编译用于ARM Cortex A5 CPU的C ++项目。我为CMake创建了一个工具链文件,但似乎有一个错误或缺少的东西,我找不到。当使用下面的工具链文件调用CMake时,出现以下错误。

CMake命令:

  

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

输出:

  

-C编译器标识为C:/Users/user/scoop/apps/cmake/3.13.4/share/cmake-3.13/Modules/CMakeDetermineCompilerId.cmake:802中的Clang 7.0.0 CMake错误   (消息):Clang编译器工具

     

“ C:/ Program Files / LLVM / bin / clang.exe”

     

以MSVC ABI为目标,但具有类似GNU的命令行界面。   不支持。请改用'clang-cl',例如通过设置   环境中的“ CC = clang-cl”。此外,使用MSVC   命令行环境。呼叫堆栈(最新呼叫优先):
  C:/用户/用户/scoop/apps/cmake/3.13.4/share/cmake-3.13/Modules/CMakeDetermineCCompiler.cmake:113   (CMAKE_DIAGNOSE_UNSUPPORTED_CLANG)CMakeLists.txt:2(PROJECT)

     

-配置不完整,发生了错误!

CMake工具链文件(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文档以及网上的一些random link创建了工具链文件。整个项目可以使用Windows版ARM GCC很好地编译,因此工具链文件似乎是唯一一个缺少的难题。

编辑

我试图通过强制编译器来解决CMake编译器检查。我将行替换为SET(CMAKE_C_COMPILER clang),SET(CMAKE_CXX_COMPILER clang ++)等,

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

错误保持不变。

编辑

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

工具版本:

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

2 个答案:

答案 0 :(得分:1)

我的问题已通过reply提交给我的错误报告,但我在此处添加了答案,以便将所有信息集中在一个地方,以备将来参考。

简而言之:如果从llvm.org安装Clang,则CMake当前不支持使用clang / clang ++命令行界面。如果要使用clang / clang ++接口(对于ARM进行交叉编译是必需的),则必须通过msys2安装Clang。

详细信息

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

  • clang/clang++是试图与GCC gcc / g ++兼容并以GNU ABI为目标的默认接口
  • clang-cl,试图与Microsoft的Visual C ++编译器cl.exe兼容,并以MSVC ABI为目标

为了针对ARM进行交叉编译,您需要clang / clang ++接口。问题是CMake根据安装Clang的方式支持不同的接口(有关更多详细信息,请参阅CMake问题跟踪器中的bug

  • 如果从llvm.org安装Clang,则CMake仅支持clang-cl界面。
  • 如果通过msys2安装Clang,则CMake支持clang / clang ++接口。

这就是我所做的:

  1. 安装msys2
  2. 使用pacman安装Clang和CMake。 msys2中有两个clang软件包,一个mingw32和mingw64版本。我使用了mingw64软件包(mingw-w64-x86_64-clang)。
  3. 启动mingw64 shell,然后运行CMake并从那里构建。

工具链文件

我的原始工具链文件存在两个问题,这些问题花了我很长时间才能解决。因此,我希望这可以节省其他人的时间:

  1. target triple(例如arm-none-eabi)需要与GCC binutils的前缀完全匹配 。我的binutils的前缀是arm-none-eabi(例如arm-none-eabi-ar),因此我不得不相应地更改目标三倍。
  2. CMAKE_TRY_COMPILE_TARGET_TYPE需要更改为STATIC_LIBRARY,以防止CMake在编译检查期间运行链接器。

这是我使用的最后一个工具链文件(您也可以在此GitHub repo中找到一个工具链文件的好例子):

<?php 
 while($row = mysqli_fetch_array($result))  
      {  
           $output .= '  
                <tr>  
                     <td>'.$row["id"].'</td>  
     				 <td class="last_name"  >
					 <select id="t1"><option>'.$row["t1"].'</option>';			
							 while($rowcode=mysqli_fetch_array($resulttasks))
									{ $output .= '<option value="'.$rowcode["id"].'">'.$rowcode["code"].'</option>' ; }
							 $output .='</select>
					 </td>  
					 <td class="last_name"  >
					 <select id="t2"><option>'.$row["t2"].'</option>';			
							 while($rowcode=mysqli_fetch_array($resulttasks))
									{ $output .= '<option value="'.$rowcode["id"].'">'.$rowcode["code"].'</option>'; }
							 $output .='</select>
					 </td>  
			</tr>';
?>

答案 1 :(得分:0)

这是一个替代的答案,它使用CMake而不是clang使用GCC工具链交叉编译嵌入式ARM,还使用普通的旧版本而不是Ninja。我知道这不能直接回答问题,但是对于嵌入式ARM来说,这是一个非常合理的选择,我们现在使用的许多基于Eclipse的供应商工具链都是基于GCC而不是LLVM / clang。

首先从https://github.com/gnu-mcu-eclipse/arm-none-eabi-gcc/releases安装最新的“ GNU MCU Eclipse ARM Embedded GCC”工具链(注意:没有安装程序,只需解压缩到所需位置即可)。

接下来,使用https://www.msys2.org/上提供的安装程序安装最新的MSYS2 / MinGW。

由于某些原因,MSYS2的默认安装不包括make。因此,在使用pacman按照安装说明更新默认软件包之后,执行'pacman -S make'来安装make。

在MSYS2中有一个cmake构建可用。但是,它不包括MSYS或MinGW的生成器(不知道为什么),并且(或者由于)似乎在查找外部GCC工具链时遇到问题,即使在命令行或工具链文件中明确提供了完整路径时也是如此。 。因此,此解决方案使用了https://cmake.org/download/上的CMake的本机Window版本,而不是cmake的MSYS2版本。

默认情况下,MSYS Shell不继承Windows环境,因此本机Windows CMake将不在MSYS Shell路径上。简单的解决方案是在命令行上指定cmake的完整路径。就我而言,我在C:/ GNU MCU Eclipse / ARM嵌入式GCC / 8.2.1-1.4-20190214-0604有GCC交叉编译器工具链。因此,执行cmake的完整命令如下所示。

/c/Program\ Files/CMake/bin/cmake.exe -DCMAKE_BUILD_TYPE=Debug -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-arm-none-eabi.cmake "-DTOOLCHAIN_PREFIX=C:/GNU MCU Eclipse/ARM Embedded GCC/8.2.1-1.4-20190214-0604" -G "MSYS Makefiles" ../

此处,命令是从项目根目录下一级的构建目录执行的,而同级cmake目录包含指定的工具链文件。请注意,反斜杠是转义cmake.exe路径中任何空格所必需的,但在作为cmake参数传递的引用路径中不使用反斜杠。

只要Windows路径上的cmake和msys bin目录都可以运行cmake,并从普通的旧Windows命令行(cmd.exe)直接执行。在这种情况下,无需指定cmake的完整路径。但是,PowerShell无法成功。