Cortex M4F を搭載した Stellaris Launchpad ボードを持っています。ボード上で FreeRTOS を独自の C++ コードで使用したいと考えています。ただし、FreeRTOS は C で記述されているため、G++ ではコンパイルできません。私はもう試した。
gcc
FreeRTOS を でコンパイルし、次にアプリケーション コードを でコンパイルg++
し、リンカーを使用してそれらをまとめる必要があることをどこかで読みました。これは理にかなっていますが、この動作を Makefile に入れる方法に本当に苦労しています。この Makefileを見つけて、さらに混乱しました。
現在、私は Stellaris のデモで FreeRTOS の例と共に配布されている Makefile を使用していますが、それは C コード用にのみ設定されています。この質問は、私が求めているものと同様のことを求めていますが、FreeRTOS を GCC でコンパイルし、残りのコードを G++ でコンパイルする方法について頭を悩ませることはできません。
FreeRTOS はコードをextern "C" { }
ディレクティブでラップしているようですが、FreeRTOS コードベースのコンパイル時に G++ を使用しようとしても失敗します。
SO に大量のコードを投稿するのは好きではありませんが、情報が多ければ多いほど良いと思います。Stellaris のデモには共通のmakedefs
ファイルがあります。
# Get the operating system name. If this is Cygwin, the .d files will be
# munged to convert c: into /cygdrive/c so that "make" will be happy with the
# auto-generated dependencies.
os:=${shell uname -s}
# The compiler to be used.
ifndef COMPILER
COMPILER=gcc
endif
# Definitions for using GCC.
ifeq (${COMPILER}, g++)
# Get the prefix for the tools to use. Use arm-stellaris-eabi if it exists,
# otherwise fall back to arm-none-eabi.
PREFIX=${shell type arm-stellaris-eabi-gcc > /dev/null 2>&1 && \
echo arm-stellaris-eabi || echo arm-none-eabi}
# The command for calling the compiler.
CC=${PREFIX}-${COMPILER}
# The location of the C compiler
# ARMGCC_ROOT is used by some makefiles that need to know where the compiler
# is installed. It is not used further for normal stellarisware apps
ARMGCC_ROOT:=${shell dirname '${shell sh -c "which ${CC}"}'}/..
# Determine the compiler CPU/FPU options based on the processor variant.
ifndef VARIANT
CPU=-mcpu=cortex-m3
FPU=
else
ifeq (${VARIANT}, cm3)
CPU=-mcpu=cortex-m3
FPU=
else
ifeq (${VARIANT}, cm4f)
CPU=-mcpu=cortex-m4
FPU=-mfpu=fpv4-sp-d16 -mfloat-abi=softfp
else
$(error Unknown processor variant ${VARIANT}!)
endif
endif
endif
# The flags passed to the assembler.
AFLAGS=-mthumb \
${CPU} \
${FPU} \
-MD
# The flags passed to the compiler.
CFLAGS=-mthumb \
${CPU} \
${FPU} \
-Os \
-ffunction-sections \
-fdata-sections \
-MD \
-Wall \
-pedantic \
-DPART_${PART} \
-c
# The command for calling the library archiver.
AR=${PREFIX}-ar
# The command for calling the linker.
LD=${PREFIX}-ld
# The flags passed to the linker.
LDFLAGS=--gc-sections
# Get the location of libgcc.a from the GCC front-end.
LIBGCC=${shell ${CC} ${CFLAGS} -print-libgcc-file-name}
# Get the location of libc.a from the GCC front-end.
LIBC=${shell ${CC} ${CFLAGS} -print-file-name=libc.a}
# Get the location of libm.a from the GCC front-end.
LIBM=${shell ${CC} ${CFLAGS} -print-file-name=libm.a}
# The command for extracting images from the linked executables.
OBJCOPY=${PREFIX}-objcopy
# Tell the compiler to include debugging information if the DEBUG environment
# variable is set.
ifdef DEBUG
CFLAGS+=-g -D DEBUG
endif
# Add the tool specific CFLAGS.
CFLAGS+=${CFLAGSgcc}
# Add the include file paths to AFLAGS and CFLAGS.
AFLAGS+=${patsubst %,-I%,${subst :, ,${IPATH}}}
CFLAGS+=${patsubst %,-I%,${subst :, ,${IPATH}}}
# The rule for building the object file from each C source file.
${COMPILER}${SUFFIX}/%.o: %.c
@if [ 'x${VERBOSE}' = x ]; \
then \
echo " CC ${<}"; \
else \
echo ${CC} ${CFLAGS} -D${COMPILER} -o ${@} ${<}; \
fi
@${CC} ${CFLAGS} -D${COMPILER} -o ${@} ${<}
ifneq ($(findstring CYGWIN, ${os}), )
@sed -i -r 's/ ([A-Za-z]):/ \/cygdrive\/\1/g' ${@:.o=.d}
endif
# The rule for building the object file from each assembly source file.
${COMPILER}${SUFFIX}/%.o: %.S
@if [ 'x${VERBOSE}' = x ]; \
then \
echo " AS ${<}"; \
else \
echo ${CC} ${AFLAGS} -D${COMPILER} -o ${@} -c ${<}; \
fi
@${CC} ${AFLAGS} -D${COMPILER} -o ${@} -c ${<}
ifneq ($(findstring CYGWIN, ${os}), )
@sed -i -r 's/ ([A-Za-z]):/ \/cygdrive\/\1/g' ${@:.o=.d}
endif
# The rule for creating an object library.
${COMPILER}${SUFFIX}/%.a:
@if [ 'x${VERBOSE}' = x ]; \
then \
echo " AR ${@}"; \
else \
echo ${AR} -cr ${@} ${^}; \
fi
@${AR} -cr ${@} ${^}
# The rule for linking the application.
${COMPILER}${SUFFIX}/%.axf:
@if [ 'x${SCATTERgcc_${notdir ${@:.axf=}}}' = x ]; \
then \
ldname="${ROOT}/${COMPILER}/standalone.ld"; \
else \
ldname="${SCATTERgcc_${notdir ${@:.axf=}}}"; \
fi; \
if [ 'x${VERBOSE}' = x ]; \
then \
echo " LD ${@} ${LNK_SCP}"; \
else \
echo ${LD} -T $${ldname} \
--entry ${ENTRY_${notdir ${@:.axf=}}} \
${LDFLAGSgcc_${notdir ${@:.axf=}}} \
${LDFLAGS} -o ${@} $(filter %.o %.a, ${^}) \
'${LIBM}' '${LIBC}' '${LIBGCC}'; \
fi; \
${LD} -T $${ldname} \
--entry ${ENTRY_${notdir ${@:.axf=}}} \
${LDFLAGSgcc_${notdir ${@:.axf=}}} \
${LDFLAGS} -o ${@} $(filter %.o %.a, ${^}) \
'${LIBM}' '${LIBC}' '${LIBGCC}'
@${OBJCOPY} -O binary ${@} ${@:.axf=.bin}
endif
上記のファイルは、Makefile
それ自体に含まれています (以下)。
# Defines the part type that this project uses.
PART=LM4F120H5QR
# Set the processor variant.
VARIANT=cm4f
# The base directory for StellarisWare.
ROOT=../lib
COMPILER=gcc
# Include the common make definitions.
include ${ROOT}/makedefs
# Where to find source files that do not live in this directory.
VPATH=${ROOT}/FreeRTOS/Source/portable/GCC/ARM_CM4F
VPATH+=${ROOT}/FreeRTOS/Source/portable/MemMang/
VPATH+=${ROOT}/FreeRTOS/Source
VPATH+=${ROOT}/drivers
VPATH+=${ROOT}/utils
# Where to find header files that do not live in the source directory.
IPATH=.
IPATH+=..
IPATH+=${ROOT}
IPATH+=${ROOT}/FreeRTOS/Source/portable/GCC/ARM_CM4F
IPATH+=${ROOT}/FreeRTOS
IPATH+=${ROOT}/FreeRTOS/Source/include
IPATH+=${ROOT}
# The default rule, which causes the FreeRTOS example to be built.
all: ${COMPILER}
all: ${COMPILER}/freertos_demo.axf
# The rule to clean out all the build products.
clean:
@rm -rf ${COMPILER} ${wildcard *~}
# The rule to create the target directory.
${COMPILER}:
@mkdir -p ${COMPILER}
# Rules for building the FreeRTOS example.
${COMPILER}/freertos_demo.axf: ${COMPILER}/buttons.o
${COMPILER}/freertos_demo.axf: ${COMPILER}/freertos_demo.o
${COMPILER}/freertos_demo.axf: ${COMPILER}/heap_2.o
${COMPILER}/freertos_demo.axf: ${COMPILER}/led_task.o
${COMPILER}/freertos_demo.axf: ${COMPILER}/list.o
${COMPILER}/freertos_demo.axf: ${COMPILER}/port.o
${COMPILER}/freertos_demo.axf: ${COMPILER}/queue.o
${COMPILER}/freertos_demo.axf: ${COMPILER}/rgb.o
${COMPILER}/freertos_demo.axf: ${COMPILER}/startup_${COMPILER}.o
${COMPILER}/freertos_demo.axf: ${COMPILER}/switch_task.o
${COMPILER}/freertos_demo.axf: ${COMPILER}/tasks.o
${COMPILER}/freertos_demo.axf: ${COMPILER}/uartstdio.o
${COMPILER}/freertos_demo.axf: ${COMPILER}/ustdlib.o
${COMPILER}/freertos_demo.axf: ${ROOT}/driverlib/${COMPILER}-cm4f/libdriver-cm4f.a
${COMPILER}/freertos_demo.axf: freertos_demo.ld
SCATTERgcc_freertos_demo=freertos_demo.ld
ENTRY_freertos_demo=ResetISR
CFLAGSgcc=-DTARGET_IS_BLIZZARD_RA1
# Include the automatically generated dependency files.
ifneq (${MAKECMDGOALS},clean)
-include ${wildcard ${COMPILER}/*.d} __dummy__
endif
私のディレクトリ構造の一部は次のとおりです。
Projects/
lib/
FreeRTOS/
driverlib/
drivers/
inc/
utils/
makedefs
TestProject/
loads.cpp
of.cpp
files.h
here.h
Makefile
FreeRTOS を GCC でコンパイルしてから C++ プロジェクト コードにリンクする必要があると言うのが正しい場合、現在の Makefile を変更してそれを行うにはどうすればよいですか? 他のプロジェクトで再利用できるように、かなり汎用的なソリューションが必要ですが、C/C++ ビルド プロセスや Makefile についてはよく知らないため、この (長い) 質問をします。「私のためにこれをしてください」という質問をしているように聞こえたくない/意味がありませんが、GoogleやSOで検索しても、これを行う方法が本当にわかりません。