¿Cómo configurar CMake para compilar de forma cruzada con clang para ARM incrustado en Windows?

 C Programming >> Programación C >  >> Tags >> Clang
¿Cómo configurar CMake para compilar de forma cruzada con clang para ARM incrustado en Windows?

Mi pregunta fue respondida a través de la respuesta a mi informe de error, pero agrego la respuesta aquí para tener toda la información en un solo lugar para referencia futura.

En resumen: Actualmente, CMake no admite el uso de la interfaz de línea de comandos clang/clang++ si instala Clang desde llvm.org. Si desea utilizar la interfaz clang/clang++ (que es necesaria para la compilación cruzada para ARM), debe instalar Clang a través de msys2.

En detalle

Clang en Windows tiene dos interfaces de línea de comandos diferentes:

  • clang/clang++ la interfaz predeterminada que intenta ser compatible con GCC gcc/g++ y apunta a GNU ABI
  • clang-cl que intenta ser compatible con el compilador cl.exe de Visual C++ de Microsoft y apunta a MSVC ABI

Para realizar una compilación cruzada para ARM, necesita la interfaz clang/clang++. El problema es que CMake admite diferentes interfaces según cómo haya instalado Clang (consulte el error en el rastreador de problemas de CMake para obtener más detalles):

  • Si instala Clang desde llvm.org, CMake solo es compatible con la interfaz clang-cl.
  • Si instala Clang a través de msys2, CMake es compatible con la interfaz clang/clang++.

Así que esto es lo que hice:

  1. Instalar msys2
  2. Instala Clang y CMake con pacman. Hay dos paquetes clang en msys2, una versión mingw32 y una versión mingw64. Usé el paquete mingw64 (mingw-w64-x86_64-clang).
  3. Inicie el shell mingw64 y ejecute CMake y construya desde allí.

Archivo de cadena de herramientas

Hubo dos problemas con mi archivo de cadena de herramientas original que me tomó mucho tiempo solucionar. Así que espero que esto ahorre tiempo a otros:

  1. El triple de destino (por ejemplo, arm-none-eabi) debe coincidir con el prefijo de GCC binutils exactamente . El prefijo de mis binutils era arm-none-eabi (por ejemplo, arm-none-eabi-ar), por lo que tuve que cambiar el triple objetivo en consecuencia.
  2. CMAKE_TRY_COMPILE_TARGET_TYPE debe cambiarse a STATIC_LIBRARY para evitar que CMake ejecute el enlazador durante la comprobación de compilación.

Aquí está el archivo de cadena de herramientas final que utilicé (también puede encontrar un buen ejemplo para un archivo de cadena de herramientas en este repositorio de GitHub):

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)