问题
I am trying to set up a makefile project using the mbed library for use in a larger project I am wanting to do later on. I have the project directory set up like this...
.
|-- Doxyfile
|-- NUCLEO_F446RE.mk
|-- Nucleo_blink.map
|-- asm
|-- attach.gdb
|-- debug
|-- gdb-pipe.cfg
|-- lib
| `-- mbed
| |-- AnalogIn.h
| |-- ...
| |-- TARGET_NUCLEO_F446RE
| | |-- TARGET_STM
| | | `-- TARGET_STM32F4
| | | |-- PeripheralPins.h
| | | |-- TARGET_NUCLEO_F446RE
| | | | |-- PeripheralNames.h
| | | | |-- PinNames.h
| | | | |-- PortNames.h
| | | | |-- device.h
| | | | `-- objects.h
| | | `-- gpio_object.h
| | |-- TOOLCHAIN_GCC_ARM
| | | |-- STM32F446XE.ld
| | | |-- board.o
| | | |-- ...
| | | `-- system_stm32f4xx.o
| | |-- arm_common_tables.h
| | |-- ...
| | `-- system_stm32f4xx.h
| |-- Ticker.h
| |-- ...
| `-- wait_api.h
|-- makefile
|-- obj
|-- release
`-- src
`-- main.cc
Specifically, my error is in lib/mbed/platform.h
, which tries to include device.h
. I have a makefile that should add it to the include path, but g++ still seems to be unable to find it. Here is the exact error...
arm-none-eabi-g++ -c -o main.o source/main.cc
In file included from source/../lib/mbed/mbed.h:21:0,
from source/main.cc:1:
source/../lib/mbed/platform.h:21:20: fatal error: device.h: No such file or directory
#include "device.h"
^
compilation terminated.
<builtin>: recipe for target 'main.o' failed
make: *** [main.o] Error 1
Line 1 of main.cc is #include "../lib/mbed/mbed.h"
NUCLEO_F446RE.mk
defines the device-specific include path I am using, and I hope to be able to be able to choose the .mk
file to use based on a variable I pass to the makefile, so that I can easily use a different mbed board if I want. Here are the contents of NUCLEO_F446RE.mk
...
HARDFP = 1
LIBRARY_PATHS = -L./lib/mbed/TARGET_NUCLEO_F446RE/TOOLCHAIN_GCC_ARM
CPU = -mcpu=cortex-m4 -mthumb -mfpu=fpv4-sp-d16 -mfloat-abi=$(FLOAT_ABI)
LINKER_SCRIPT = ./lib/mbed/TARGET_NUCLEO_F446RE/TOOLCHAIN_GCC_ARM/STM32F446XE.ld
CC_SYMBOLS = -DTARGET_M4 -DMBED_BUILD_TIMESTAMP=1453683815.81 -DTOOLCHAIN_GCC_ARM -DTOOLCHAIN_GCC -DTARGET_RTOS_M4_M7 -DTARGET_FF_MORPHO -DTARGET_CORTEX_M -D__FPU_PRESENT=1 -DTARGET_FF_ARDUINO -DTARGET_STM32F446RE -DTARGET_NUCLEO_F446RE -D__MBED__=1 -DTARGET_STM -DTARGET_STM32F4 -D__CORTEX_M4 -DARM_MATH_CM4
INCLUDE_PATHS = -I./lib/ -I./lib/mbed/ \
-I./lib/mbed/TARGET_NUCLEO_F446RE/ \
-I./lib/mbed/TARGET_NUCLEO_F44\6RE/TARGET_STM/ \
-I./lib/mbed/TARGET_NUCLEO_F446RE/TARGET_STM/TARGET_STM32F4/ \
-I./lib/mbed/TARGET_NUCLEO_F446RE/TOOLCHAIN_GCC_ARM/ \
-I./lib/mbed/TARGET_NUCLEO_F446RE/TARGET_STM/TARGET_STM32F4/TARGET_NUCLEO_F446RE/ #<--device.h is here
SYS_OBJECTS = ./lib/mbed/TARGET_NUCLEO_F446RE/TOOLCHAIN_GCC_ARM/stm32f4xx_hal_flash_ramfunc.o \
./lib/mbed/TARGET_NUCLEO_F446RE/TOOLCHAIN_GCC_ARM/board.o \
...
For good measure, here is my makefile. I have been trying to keep everything as neat as possible.
#Project parameters
PROJECT = Nucleo_blink
OBJECTS = main.o
DEST = debug
VPATH = src lib $DEST
TARGET = NUCLEO_F446RE
#Compilation options
DEBUG = 1
#Tools
AS = $(GCC_BIN)arm-none-eabi-as
CC = $(GCC_BIN)arm-none-eabi-gcc
CXX = $(GCC_BIN)arm-none-eabi-g++
LD = $(GCC_BIN)arm-none-eabi-gcc
OBJCOPY = $(GCC_BIN)arm-none-eabi-objcopy
OBJDUMP = $(GCC_BIN)arm-none-eabi-objdump
SIZE = $(GCC_BIN)arm-none-eabi-size
include $(TARGET).mk
CFLAGS = $(INCLUDE_PATHS) $(CC_SYMBOLS) $(CPU) -c -g -fno-common -fmessage-length=0 -Wall -Wextra -fno-exceptions -ffunction-sections -fdata-sections -fomit-frame-pointer -MMD -MP
ifeq ($(HARDFP),1)
FLOAT_ABI = hard
else
FLOAT_ABI = softfp
endif
ifeq ($(DEBUG), 1)
CFLAGS += -DDEBUG -O0
else
CFLAGS += -DNDEBUG -Os
endif
LD_FLAGS = $(CPU) -Wl,--gc-sections --specs=nano.specs -u _printf_float -u _scanf_float -Wl,--wrap,main -Wl,-Map=$(PROJECT).map,--cref
LD_SYS_LIBS = -lstdc++ -lsupc++ -lm -lc -lgcc -lnosys
LIBRARIES = -lmbed
.PHONY: all clean lst size
all: $(PROJECT).bin $(PROJECT).hex
clean:
rm -f debug/* obj/* asm/* $(DEPS)
obj/%.o: %.c #<---Attempt to fix target error mentioned by @user657267
$(CC) $(CC_FLAGS) $(CC_SYMBOLS) -std=c99 $(INCLUDE_PATHS) -o obj/$@ $<
obj/%.o: %.cc
$(CXX) $(CC_FLAGS) $(CC_SYMBOLS) -std=c++98 -fno-rtti $(INCLUDE_PATHS) -o obj/$@ $<
obj/%.o: %.cpp
$(CXX) $(CC_FLAGS) $(CC_SYMBOLS) -std=c++98 -fno-rtti $(INCLUDE_PATHS) -o obj/$@ $<
obj/%.o: %.asm
$(CC) $(CPU) -c -x assembler-with-cpp -o asm/$@ $<
$(PROJECT).elf: $(OBJECTS) $(SYS_OBJECTS)
$(LD) $(LD_FLAGS) -T$(LINKER_SCRIPT) $(LIBRARY_PATHS) -o $(DEST)/$@ $^ $(LIBRARIES) $(LD_SYS_LIBS) $(LIBRARIES) $(LD_SYS_LIBS)
$(PROJECT).bin: $(PROJECT).elf
$(OBJCOPY) -O binary $< $@
$(PROJECT).hex: $(PROJECT).elf
@$(OBJCOPY) -O ihex $< $@
$(PROJECT).lst: $(PROJECT).elf
@$(OBJDUMP) -Sdh $< > $@
lst: $(PROJECT).lst
size: $(PROJECT).elf
$(SIZE) $(PROJECT).elf
DEPS = $(OBJECTS:.o=.d) $(SYS_OBJECTS:.o=.d)
-include $(DEPS)
A lot of the code I have here is based on the output from the online mbed IDE after exporting a simple project to a makefile. However, the export had everything in a single directory, and that will be extremely messy as I start doing larger projects and possibly add more libraries. The strange part is that this project compiles without any errors when I use the single-directory exported version. What is going on here? Why is g++ not seeing device.h
in my multi-directory version?
EDITS 2016-05-09: Minor tweaks to makefile, same error.
回答1:
%.o: %.cc %.cpp
This pattern rule is (probably) incorrect, you're telling make to apply this rule if and only if both the .cc and .cpp files exist (or can be made by other rules). As main.cpp
presumably doesn't exist make will fall back to its built-in implicit rule, which obviously won't know about INCLUDE_PATHS
or any other of the unconventional variables you're using for flags.
You can fix this by making the two rules separate
%.o: %.cc
$(CXX) $(CC_FLAGS) $(CC_SYMBOLS) -std=c++98 -fno-rtti $(INCLUDE_PATHS) -o obj/$@ $<
%.o: %.cpp
$(CXX) $(CC_FLAGS) $(CC_SYMBOLS) -std=c++98 -fno-rtti $(INCLUDE_PATHS) -o obj/$@ $<
These rules are still broken however, as when one of them matches something like ./lib/mbed/TARGET_NUCLEO_F446RE/TOOLCHAIN_GCC_ARM/stm32f4xx_hal_flash_ramfunc.o
you're going to place it into obj/./lib/mbed/TARGET_NUCLEO_F446RE/TOOLCHAIN_GCC_ARM/stm32f4xx_hal_flash_ramfunc.o
, which means make will always recompile the object because it won't be where you've said it should be (check out the informal Rules of Makefiles, specifically 2).
来源:https://stackoverflow.com/questions/37106184/library-include-not-detecting-header-in-include-path