为Tiva C系列转换一个Makefile到CMakeLists.txt
Converting a Makefile to CMakeLists.txt for Tiva C Series
我想使用CMake构建过程在c++中编程我的Tiva C系列LaunchPad板。我下载了一个简单的例子来闪烁我使用make
构建的RGB LED,我希望能够使用cmake
来启动一个更大的项目。
# Tiva Makefile
# #####################################
#
# Part of the uCtools project
# uctools.github.com
#
#######################################
# user configuration:
#######################################
# TARGET: name of the output file
TARGET = firmware
# MCU: part number to build for
MCU = TM4C123GH6PM
# SOURCES: list of input source sources
SOURCES = main.c startup_gcc.c
# INCLUDES: list of includes, by default, use Includes directory
INCLUDES = -IInclude
# OUTDIR: directory to use for output
OUTDIR = build
# TIVAWARE_PATH: path to tivaware folder
TIVAWARE_PATH = ../tivaware
# LD_SCRIPT: linker script
LD_SCRIPT = $(MCU).ld
# define flags
CFLAGS = -g -mthumb -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=softfp
CFLAGS +=-Os -ffunction-sections -fdata-sections -MD -std=c99 -Wall
CFLAGS += -pedantic -DPART_$(MCU) -c -I$(TIVAWARE_PATH)
CFLAGS += -DTARGET_IS_BLIZZARD_RA1
LDFLAGS = -T $(LD_SCRIPT) --entry ResetISR --gc-sections
#######################################
# end of user configuration
#######################################
#
#######################################
# binaries
#######################################
CC = arm-none-eabi-gcc
LD = arm-none-eabi-ld
OBJCOPY = arm-none-eabi-objcopy
RM = rm -f
MKDIR = mkdir -p
#######################################
# list of object files, placed in the build directory regardless of source path
OBJECTS = $(addprefix $(OUTDIR)/,$(notdir $(SOURCES:.c=.o)))
# default: build bin
all: $(OUTDIR)/$(TARGET).bin
$(OUTDIR)/%.o: src/%.c | $(OUTDIR)
$(CC) -o $@ $^ $(CFLAGS)
$(OUTDIR)/a.out: $(OBJECTS)
$(LD) -o $@ $^ $(LDFLAGS)
$(OUTDIR)/$(TARGET).bin: $(OUTDIR)/a.out
$(OBJCOPY) -O binary $< $@
# create the output directory
$(OUTDIR):
$(MKDIR) $(OUTDIR)
clean:
-$(RM) $(OUTDIR)/*
.PHONY: all clean
我的第一个基于它的CMakeLists.txt文件:
project(firmware)
cmake_minimum_required(VERSION 2.8)
# this one is important
set(CMAKE_SYSTEM_NAME Generic)
#this one not so much
#set(CMAKE_SYSTEM_VERSION 1)
# specify the toolchain
set(TOOLCHAIN_PREFIX ${PROJECT_SOURCE_DIR}/../toolchain/bin/arm-none-eabi-)
set(CMAKE_C_COMPILER ${TOOLCHAIN_PREFIX}gcc)
set(CMAKE_CXX_COMPILER ${TOOLCHAIN_PREFIX}g++)
set(CMAKE_OBJCOPY ${TOOLCHAIN_PREFIX}objcopy)
set(CMAKE_AR ${TOOLCHAIN_PREFIX}ar)
# set compiler flags
set(MCU TM4C123GH6PM)
set(COMMON_FLAGS "-mthumb -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=softfp
-ffunction-sections -fdata-sections -pedantic
-MD -DPART_${MCU} -DTARGET_IS_BLIZZARD_RA1")
set(CMAKE_C_FLAGS_DEBUG "-g -Wall ${COMMON_FLAGS}")
set(CMAKE_CXX_FLAGS_DEBUG "-g -Wall -std=c++11 ${COMMON_FLAGS}")
set(CMAKE_C_FLAGS_RELEASE "-O2 -DNOTEST ${COMMON_FLAGS}")
set(CMAKE_CXX_FLAGS_RELEASE "-O2 -std=c++11 -DNOTEST ${COMMON_FLAGS}")
# 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)
# add TivaWare header files to the project
include_directories(${PROJECT_SOURCE_DIR}/../tivaware)
# add source files to the project
aux_source_directory(. SRC_LIST)
add_executable(${PROJECT_NAME} ${SRC_LIST})
# set linker flags
set(CMAKE_SHARED_LIBRARY_LINK_C_FLAGS)
set(CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS)
set_target_properties(${PROJECT_NAME}
PROPERTIES
LINK_FLAGS "-T ${MCU}.ld --entry ResetISR --gc-sections"
)
# define objcopy macro
macro(OBJCOPY_FILE EXE_NAME)
set(FO ${CMAKE_CURRENT_BINARY_DIR}/${EXE_NAME}.bin)
set(FI ${CMAKE_CURRENT_BINARY_DIR}/${EXE_NAME})
message(STATUS ${FO})
add_custom_command(
OUTPUT ${FO}
COMMAND ${CMAKE_OBJCOPY}
ARGS -O binary -I elf32-little ${FI} ${FO}
DEPENDS ${FI}
)
get_filename_component(TGT "${EXE_NAME}" NAME)
add_custom_target("target-objcopy_${TGT}" ALL DEPENDS ${FO} VERBATIM)
get_directory_property(extra_clean_files ADDITIONAL_MAKE_CLEAN_FILES)
set_directory_properties(
PROPERTIES
ADDITIONAL_MAKE_CLEAN_FILES "${extra_clean_files};${FO}"
)
set_source_files_properties("${FO}" PROPERTIES GENERATED TRUE)
endmacro(OBJCOPY_FILE)
# set the objcopy for binary file
objcopy_file(${PROJECT_NAME})
它通过CMake步骤,但当我尝试使用make
编译时,我得到
arm-none-eabi-g++: error: unrecognized command line option '--gc-sections'
我猜链接器标志应该与arm-none-eabi-ld
一起使用。我该怎么做呢?
Edit1:
我仍然不知道如何设置正确的链接器exe和标志,但我发现CMake在firmware.dir/link.txt中生成文件。其内容为
~/Documents/crh-2016/src/tiva/firmware/../toolchain/bin/arm-none-eabi-g++ -O2 -std=c++11 -fno-exceptions -DNOTEST -mthumb -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=softfp -ffunction-sections -fdata-sections -pedantic -MD -DPART_TM4C123GH6PM -DTARGET_IS_BLIZZARD_RA1 -T ~/Documents/crh-2016/src/tiva/firmware/TM4C123GH6PM.ld --entry ResetISR --gc-sections CMakeFiles/firmware.dir/main.cpp.o CMakeFiles/firmware.dir/startup_gcc.cpp.o -o firmware
我把它编辑成我想临时修复的这个问题
~/Documents/crh-2016/src/tiva/firmware/../toolchain/bin/arm-none-eabi-ld -T ~/Documents/crh-2016/src/tiva/firmware/TM4C123GH6PM.ld --entry ResetISR --gc-sections CMakeFiles/firmware.dir/main.cpp.o CMakeFiles/firmware.dir/startup_gcc.cpp.o -o firmware
但是LD似乎不喜欢g++生成的.o
文件,因为make
说
toolchain/bin/arm-none-eabi-ld: warning: cannot find entry symbol ResetISR; defaulting to 00000000
把我的评论变成答案
Edit:正如Marc Glisse在他的评论中提到的,你可以在CMAKE_EXE_LINKER_FLAGS
中通过-Wl,XXX
传递链接器标志,参见例如cflags '-Wl,-export-dynamic'-export-dynamic'
那么您不需要将链接器命令更改为ld
。
为了与makefile
的可比性,可以使用CMAKE_LINKER
和CMAKE_CXX_LINK_EXECUTABLE
变量来更改链接器命令,如调用ld
。
关于你的问题:
- 如果没有使用链接器标志,只需将它们直接放入链接器命令行本身。
- 获取"cannot find entry symbol"时
- 你应该检查
map
文件,如果ResetISR
存在 - 您可以尝试将
--gc-sections
替换为--discard-none
- 如果你在CMake的尝试编译步骤中得到"找不到入口符号",然后激活
..._COMPILER_WORKS
标志(见下文)
- 你应该检查
我已经采取了你的代码,并将其移动到toolchain
文件的可读性,并演示了什么已经为我在其他"裸机"交叉编译:
TM4C123Toolchain.cmake
# this one is important
set(CMAKE_SYSTEM_NAME Generic)
set(CMAKE_SYSTEM_PROCESSOR arm)
set(MCU TM4C123GH6PM)
# Optional for testing
#set(CMAKE_C_COMPILER_WORKS 1 CACHE INTERNAL "")
#set(CMAKE_CXX_COMPILER_WORKS 1 CACHE INTERNAL "")
# specify the toolchain
set(CMAKE_PREFIX_PATH "${PROJECT_SOURCE_DIR}/../toolchain/bin")
set(TOOLCHAIN_PREFIX "arm-none-eabi-")
# add processor specific definitions
add_definitions(
-DPART_TM4C123GH6PM
-DTARGET_IS_TM4C123_RA1
-Dgcc
)
# add TivaWare header files to the project
set(TIVAWARE_PATH "${PROJECT_SOURCE_DIR}/../tivaware")
include_directories(${TIVAWARE_PATH})
#list(
# APPEND _cxx_standard_libraries_list
# "-l${TIVAWARE_PATH}/usblib/gcc/libusb.a"
# "-l${TIVAWARE_PATH}/driverlib/gcc/libdriver.a"
#)
#unset(CMAKE_CXX_STANDARD_LIBRARIES CACHE)
#string(REPLACE ";" " " CMAKE_CXX_STANDARD_LIBRARIES_INIT "${_cxx_standard_libraries_list}")
set(CMAKE_CXX_COMPILER_ENV_VAR "")
unset(CMAKE_C_COMPILER CACHE)
find_program(CMAKE_C_COMPILER NAMES ${TOOLCHAIN_PREFIX}gcc)
unset(CMAKE_CXX_COMPILER CACHE)
find_program(CMAKE_CXX_COMPILER NAMES ${TOOLCHAIN_PREFIX}g++)
unset(CMAKE_ASM_COMPILER CACHE)
find_program(CMAKE_ASM_COMPILER NAMES ${TOOLCHAIN_PREFIX}as)
unset(CMAKE_OBJCOPY CACHE)
find_program(CMAKE_OBJCOPY NAMES ${TOOLCHAIN_PREFIX}objcopy)
unset(CMAKE_LINKER CACHE)
find_program(CMAKE_LINKER NAMES ${TOOLCHAIN_PREFIX}ld)
# set compiler flags
# NOTE: The following variables are cached by default (CMake<Lang>Information.cmake),
# so we have to prefill the cache with our values. They won't be overwritten.
set(CMAKE_C_FLAGS "-mthumb -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=softfp
-ffunction-sections -fdata-sections -pedantic
-MD -DPART_${MCU} -DTARGET_IS_BLIZZARD_RA1" CACHE INTERNAL "" FORCE)
set(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS} -std=c++11" CACHE INTERNAL "" FORCE)
set(CMAKE_C_FLAGS_DEBUG "-g -Wall" CACHE INTERNAL "" FORCE)
set(CMAKE_CXX_FLAGS_DEBUG "-g -Wall" CACHE INTERNAL "" FORCE)
set(CMAKE_C_FLAGS_RELEASE "-O2 -DNOTEST" CACHE INTERNAL "" FORCE)
set(CMAKE_CXX_FLAGS_RELEASE "-O2 -DNOTEST" CACHE INTERNAL "" FORCE)
set(CMAKE_ASM_FLAGS "-mthumb -mcpu=cortex-m4" CACHE INTERNAL "" FORCE)
set(CMAKE_EXECUTABLE_SUFFIX_CXX ".elf" CACHE INTERNAL "" FORCE)
set(CMAKE_CXX_LINK_EXECUTABLE "<CMAKE_LINKER> <CMAKE_CXX_LINK_FLAGS> -EL -n -Map=<TARGET_NAME>.map -T ${MCU}.ld --entry ResetISR --gc-sections -o <TARGET> --start-group <OBJECTS> <LINK_LIBRARIES> --end-group --cref")
set(CMAKE_C_USE_RESPONSE_FILE_FOR_OBJECTS 0)
set(CMAKE_CXX_USE_RESPONSE_FILE_FOR_OBJECTS 0)
set(CMAKE_C_RESPONSE_FILE_LINK_FLAG "@")
set(CMAKE_CXX_RESPONSE_FILE_LINK_FLAG "@")
# 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 -DCMAKE_TOOLCHAIN_FILE:string=TM4C123Toolchain.cmake ...
- 我添加了一个地图文件与
-Map
CMAKE_CXX_LINK_EXECUTABLE
命令行调试。--start-group
/--end-group
,因为我的发行版的标准库有循环依赖。 - 我更喜欢
CMAKE_PREFIX_PATH
和find_program()
,因为路径和名称可能因工具链供应商或版本而异(并且都接受路径/名称列表)。 - 我更喜欢
FORCE
变量设置,因为我不使用用户可以更改缓存编译器设置的功能,我更喜欢工具链文件中的更改来激活,而不必从头开始运行CMake。 -
_DEBUG
和_RELEASE
标志由CMake附加到标准标志。
引用
- cmake -全局链接标志设置(用于目录中的所有目标)
- CMake设置和使用变量的语法是什么?
我通过使用-specs
标志找到了一个解决方案。
project(firmware)
cmake_minimum_required(VERSION 2.8)
# set cross compilation information
set(CMAKE_SYSTEM_NAME Generic)
set(CMAKE_SYSTEM_PROCESSOR arm)
# specify the toolchain
set(TOOLCHAIN_PREFIX ${PROJECT_SOURCE_DIR}/../toolchain/bin/arm-none-eabi-)
set(CMAKE_C_COMPILER ${TOOLCHAIN_PREFIX}gcc)
set(CMAKE_CXX_COMPILER ${TOOLCHAIN_PREFIX}g++)
set(CMAKE_ASM_COMPILER ${TOOLCHAIN_PREFIX}as)
set(CMAKE_AR ${TOOLCHAIN_PREFIX}ar)
set(CMAKE_OBJCOPY ${TOOLCHAIN_PREFIX}objcopy)
set(CMAKE_OBJDUMP ${TOOLCHAIN_PREFIX}objdump)
enable_language(ASM)
# set compiler flags
set(CPU "-mcpu=cortex-m4")
set(FPU "-mfpu=fpv4-sp-d16 -mfloat-abi=softfp")
set(CMAKE_ASM_FLAGS "-mthumb ${CPU} ${FPU} -MD")
set(CMAKE_C_FLAGS "-mthumb ${CPU} ${FPU} -std=gnu99 -Os -ffunction-sections -fdata-sections -MD -Wall -pedantic")
set(CMAKE_CXX_FLAGS "-mthumb ${CPU} ${FPU} -Os -ffunction-sections -fdata-sections -MD -Wall -pedantic -std=c++11 -fno-exceptions -fno-rtti")
# set linker flags
set(CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "")
set(CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "")
set(CMAKE_EXE_LINKER_FLAGS "-T${PROJECT_SOURCE_DIR}/tm4c123g.ld -specs=${PROJECT_SOURCE_DIR}/tiva.specs")
# add processor specific definitions
add_definitions(-DPART_TM4C123GH6PM)
add_definitions(-DTARGET_IS_TM4C123_RA1)
add_definitions(-Dgcc)
# add TivaWare header files to the project
set(TIVAWARE_PATH "${PROJECT_SOURCE_DIR}/../tivaware")
include_directories(${TIVAWARE_PATH})
# add source files to the project
aux_source_directory(. SRC_LIST)
add_executable(${PROJECT_NAME} ${SRC_LIST})
# add linked library to the project
target_link_libraries(${PROJECT_NAME}
${TIVAWARE_PATH}/usblib/gcc/libusb.a
${TIVAWARE_PATH}/driverlib/gcc/libdriver.a
)
# define objcopy macro
macro(OBJCOPY_FILE EXE_NAME)
set(FO ${CMAKE_CURRENT_BINARY_DIR}/${EXE_NAME}.bin)
set(FI ${CMAKE_CURRENT_BINARY_DIR}/${EXE_NAME})
message(STATUS ${FO})
add_custom_command(
OUTPUT ${FO}
COMMAND ${CMAKE_OBJCOPY}
ARGS -O binary ${FI} ${FO}
DEPENDS ${FI}
)
get_filename_component(TGT "${EXE_NAME}" NAME)
add_custom_target("target-objcopy_${TGT}" ALL DEPENDS ${FO} VERBATIM)
get_directory_property(extra_clean_files ADDITIONAL_MAKE_CLEAN_FILES)
set_directory_properties(
PROPERTIES
ADDITIONAL_MAKE_CLEAN_FILES "${extra_clean_files};${FO}"
)
set_source_files_properties("${FO}" PROPERTIES GENERATED TRUE)
endmacro(OBJCOPY_FILE)
# set the objcopy for binary file
objcopy_file(${PROJECT_NAME})
与tiva.specs: *link:
--entry ResetISR --gc-sections
*lib:
-lm -lc
和tm4c123g。作为链接器脚本:
/******************************************************************************
*
* Linker configuration file.
*
* Copyright (c) 2012-2014 Texas Instruments Incorporated. All rights reserved.
* Software License Agreement
*
* Texas Instruments (TI) is supplying this software for use solely and
* exclusively on TI's microcontroller products. The software is owned by
* TI and/or its suppliers, and is protected under applicable copyright
* laws. You may not combine this software with "viral" open-source
* software in order to form a larger program.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS.
* NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT
* NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY
* CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
* DAMAGES, FOR ANY REASON WHATSOEVER.
*
* This is part of revision 2.1.0.12573 of the EK-TM4C123GXL Firmware Package.
*
*****************************************************************************/
MEMORY
{
FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 0x00040000
SRAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00008000
}
SECTIONS
{
.text :
{
_text = .;
KEEP(*(.isr_vector))
*(.text*)
*(.rodata*)
_etext = .;
} > FLASH
.data : AT(ADDR(.text) + SIZEOF(.text))
{
_data = .;
*(vtable)
*(.data*)
_edata = .;
} > SRAM
.bss :
{
_bss = .;
*(.bss*)
*(COMMON)
_ebss = .;
} > SRAM
}
- Makefile 创建两个库 - 一个依赖于另一个
- C++ 如何将两个 makefile 对象目标规则(位于另一个文件夹中)合并到一个目标/规则中?
- 将makefile中的一个项中的多个类分组
- 有没有办法为 c++ 制作一个 makefile,每次使用 make 命令时都会运行该程序?
- Makefile:编译一个llvm程序,作为g++编译的bnfc项目的一部分
- 如何在makefile中添加.c,.cc和.so文件以创建另一个.so
- makefile不更新一个特定文件
- 将一个用户的gnu makefile转换为另一个用户
- 如何转换一个普通的makefile以创建可以在另一台计算机上使用的静态可执行文件
- 带有两个.cpp文件和一个标头文件的基本makefile
- makefile阅读另一个目录
- 如何(从字面上)创建一个makefile(用于linux中的c)
- 使用一个Makefile构建多个共享库
- 编写一个makefile以在调试构建中使用-D_GLIBCXX_DEBUG
- 如何制作一个makefile来同时编译C、c++和Java文件
- 为Tiva C系列转换一个Makefile到CMakeLists.txt
- 编写一个makefile,将.h .hpp和.cpp一起编译为可执行文件
- 为Unix创建一个makefile
- 如何将两个Makefile(每个生成的脚本都设置了特定的环境变量)合并到一个Makefile中
- 在Makefile中添加/替换另一个Makefile中的字符串