我正试图交叉编译嵌入式ARM Cortex构建的项目,但我无法获得链接器工作。我想使用armlink,但是没有文件被传递给armlink,因此没有生成.elf文件。
我的CMakeLists.txt非常简单,如下所示。之后显示了失败,说明makefile在没有任何参数的情况下调用了armlink。
任何指针都会有所帮助-我搜索并阅读了许多帖子,但它们似乎都有更多涉及的要求。
cmake_minimum_required(VERSION 2.8)
project(test_arm)
enable_language(C ASM)
# Cross-compilation for ARM
SET(CMAKE_C_COMPILER armcc)
SET(CMAKE_LINKER armlink)
SET(CMAKE_C_LINK_EXECUTABLE armlink)
SET(CMAKE_C_FLAGS "--cpu=Cortex-M3")
SET(LINK_FLAGS "--map --ro-base=0x0 --rw-base=0x0008000 --first='boot.o(RESET)' --datacompressor=off")
SET(CMAKE_EXE_LINKER_FLAGS "--map --ro-base=0x0 --rw-base=0x0008000 --first='boot.o(RESET)' --datacompressor=off")
include_directories(../include)
add_executable(blinky blinky.c)
set_target_properties(blinky PROPERTIES LINKER_LANGUAGE C)
失败如下,但我想这对某人来说是显而易见的,因为我在CMakeLists中有一些愚蠢的问题:
$ make VERBOSE=1
[100%] Building C object CMakeFiles/blinky.dir/blinky.c.o
/usr/bin/cmake -E cmake_link_script CMakeFiles/blinky.dir/link.txt --verbose=1
armlink
Linking C executable blinky
Product: DS-5 Professional 5.21.0 [5210017]
Component: ARM Compiler 5.05 update 1 (build 106)
Tool: armlink [4d0efa]
For support see http://www.arm.com/support/
Software supplied by: ARM Limited
Usage: armlink option-list input-file-list
where
....
我期待CMake生成的Makefile调用armlink类似:
armlink --map --ro-base=0x0 --rw-base=0x0008000
--first='boot.o(RESET)' --datacompressor=off
CMakeFiles/blinky.dir/blinky.c.o -o blinky.elf
从CMake v3.5开始,您不再需要Keil ARM C/c++编译工具的工具链:
增加了对编译器id为ARMCC的ARM编译器(arm.com)的支持。
只需设置相应的C/CXX编译器变量
cmake -DCMAKE_C_COMPILER:PATH="C:Program Files (x86)DS-5binarmcc.exe"
-DCMAKE_CXX_COMPILER:PATH="C:Program Files (x86)DS-5binarmcc.exe"
...
引用
- ARMCC工具链支持
- 添加支持ARM编译器(arm.com)
- CMake Error at CMakeLists.txt:30 (project): No CMAKE_C_COMPILER could found
根据我的经验,您不能在CMakeLists.txt文件中设置CMAKE_EXE_LINKER_FLAGS
。当CMake在构建目录中第一次被调用时,它必须通过CMAKE_TOOLCHAIN_FILE传递。
我没有找到任何关于这个问题的文档,但是如果你做交叉编译,你应该使用CMake页面的交叉编译。
首先,只需将set
调用放在工具链文件中并运行
cmake -DCMAKE_TOOLCHAIN_FILE=<yourfile.toolchain>
工具链文件可能是个好主意。这是我最后一次用DS-5工具链尝试CMake 2.8.10时所遇到的情况(它仍然可以优化,但它应该给你一个起点):
INCLUDE(CMakeForceCompiler)
# This one is important
SET(CMAKE_SYSTEM_NAME Generic)
SET(CMAKE_SYSTEM_PROCESSOR arm)
# Specify the cross compiler
SET(CMAKE_C_COMPILER "C:/Program Files (x86)/DS-5/bin/armcc.exe")
SET(CMAKE_CXX_COMPILER "C:/Program Files (x86)/DS-5/bin/armcc.exe")
SET(CMAKE_AR "C:/Program Files (x86)/DS-5/bin/armar.exe" CACHE FILEPATH "Archiver")
#CMAKE_FORCE_C_COMPILER("C:/Program Files (x86)/DS-5/sw/gcc/bin/arm-linux-gnueabihf-gcc.exe" GNU)
#CMAKE_FORCE_CXX_COMPILER("C:/Program Files (x86)/DS-5/sw/gcc/bin/arm-linux-gnueabihf-g++.exe" GNU)
UNSET(CMAKE_C_FLAGS CACHE)
SET(CMAKE_C_FLAGS "--cpu=Cortex-A9 --thumb -Ospace" CACHE STRING "" FORCE)
UNSET(CMAKE_CXX_FLAGS CACHE)
SET(CMAKE_CXX_FLAGS ${CMAKE_C_FLAGS} CACHE STRING "" FORCE)
UNSET(CMAKE_EXE_LINKER_FLAGS CACHE)
SET(CMAKE_EXE_LINKER_FLAGS "" CACHE STRING "" FORCE)
UNSET(CMAKE_AR_FLAGS CACHE)
SET(CMAKE_AR_FLAGS "-p -armcc,-Ospace" CACHE STRING "" FORCE)
# set(CMAKE_C_ARCHIVE_CREATE "<CMAKE_AR> cr <TARGET> <LINK_FLAGS> <OBJECTS>")
SET(CMAKE_C_ARCHIVE_CREATE "<CMAKE_AR> ${CMAKE_AR_FLAGS} -o <TARGET> <OBJECTS>" CACHE STRING "C Archive Create")
# set(CMAKE_CXX_ARCHIVE_CREATE "<CMAKE_AR> cr <TARGET> <LINK_FLAGS> <OBJECTS>")
SET(CMAKE_CXX_ARCHIVE_CREATE "<CMAKE_AR> ${CMAKE_AR_FLAGS} -o <TARGET> <OBJECTS>" CACHE STRING "CXX Archive Create")
include_directories("C:/Program Files (x86)/DS-5/include")
#include_directories("C:/Program Files (x86)/DS-5/sw/gcc/arm-linux-gnueabihf/libc/usr/include/arm-linux-gnueabi")
# Where is the target environment
SET(CMAKE_FIND_ROOT_PATH "C:/Program Files (x86)/DS-5")
# 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文件中添加链接器或编译标志?)。但是似乎在配置步骤中出现了问题。
我不知道你的命令行调用CMake的配置/生成步骤,所以一些一般的技巧来找到根本原因:
你可以试着调用
cmake.exe --trace ...
查看CMAKE_EXE_LINKER_FLAGS
变量出了什么问题。这将产生大量输出,所以这里有一些CMake的基本功能:
-
project()
命令将触发编译器评估 这将把 - 你正在用一个局部变量覆盖它(见这里的变量作用域文档)
CMAKE_EXE_LINKER_FLAGS
写入你的CMakeCache.txt如果你查看sharecmake-2.8ModulesCMakeCommonLanguageInclude.cmake
:
set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS_INIT} $ENV{LDFLAGS}"
CACHE STRING "Flags used by the linker.")
您可以使用CMAKE_EXE_LINKER_FLAGS_INIT
,但您必须在project()
命令之前或在工具链文件中设置它。
因为您将链接语言设置为C
,所以请查看sharecmake-2.8ModulesCMakeCInformation.cmake
:
if(NOT CMAKE_C_LINK_EXECUTABLE)
set(CMAKE_C_LINK_EXECUTABLE
"<CMAKE_C_COMPILER> <FLAGS> <CMAKE_C_LINK_FLAGS> <LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES>")
endif()
所以你可以使用CMAKE_C_LINK_EXECUTABLE
来覆盖整个链接器调用,或者你可以使用CMAKE_C_LINK_FLAGS
来设置额外的标志。
"官方"方式
设置目标的链接器和编译器标志的正式方式是(在CMake 2.8.12之前):
set_property(TARGET blinky APPEND_STRING PROPERTY COMPILE_FLAGS "--cpu=Cortex-M3")
set_property(TARGET blinky APPEND_STRING PROPERTIES LINK_FLAGS "--map --ro-base=0x0 --rw-base=0x0008000 --first='boot.o(RESET)' --datacompressor=off")
从CMake 2.8.12开始,它将是这样的:
add_compile_options("--cpu=Cortex-M3")