库包含未检测包含路径中的标头
Posted
技术标签:
【中文标题】库包含未检测包含路径中的标头【英文标题】:Library include not detecting header in include path 【发布时间】:2016-09-03 12:32:26 【问题描述】:我正在尝试使用 mbed 库设置一个 makefile 项目,以用于我以后想要做的一个更大的项目。我的项目目录是这样设置的...
.
|-- 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
具体来说,我的错误在lib/mbed/platform.h
中,它试图包含device.h
。我有一个 makefile 应该将它添加到包含路径中,但 g++ 似乎仍然无法找到它。这是确切的错误...
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
main.cc 的第一行是#include "../lib/mbed/mbed.h"
NUCLEO_F446RE.mk
定义了我正在使用的设备特定的包含路径,我希望能够根据我传递给 makefile 的变量来选择要使用的.mk
文件,这样我就可以轻松地如果我愿意,可以使用不同的 mbed 板。以下是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 \
...
为了更好的衡量,这是我的 makefile。我一直在努力保持一切尽可能整洁。
#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)
我这里的很多代码都是基于在线 mbed IDE 将一个简单的项目导出到 makefile 后的输出。但是,导出的所有内容都在一个目录中,当我开始做更大的项目并可能添加更多库时,这将非常混乱。奇怪的是,当我使用单目录导出版本时,这个项目编译没有任何错误。 这是怎么回事?为什么 g++ 在我的多目录版本中没有看到 device.h
?
EDITS 2016-05-09:对 makefile 进行小幅调整,同样的错误。
【问题讨论】:
【参考方案1】:%.o: %.cc %.cpp
此模式规则(可能)不正确,当且仅当 .cc 和 .cpp 文件都存在(或可以由其他规则制定)时,您才告诉 make 应用此规则。由于main.cpp
可能不存在,make 将退回到其内置的隐式规则,这显然不会知道INCLUDE_PATHS
或您用于标志的任何其他非常规变量。
您可以通过将两条规则分开来解决此问题
%.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/$@ $<
然而,这些规则仍然被破坏,因为当其中一个匹配 ./lib/mbed/TARGET_NUCLEO_F446RE/TOOLCHAIN_GCC_ARM/stm32f4xx_hal_flash_ramfunc.o
之类的内容时,您会将其放入 obj/./lib/mbed/TARGET_NUCLEO_F446RE/TOOLCHAIN_GCC_ARM/stm32f4xx_hal_flash_ramfunc.o
,这意味着 make 将始终重新编译该对象,因为它不会在您所在的位置我说过应该是(查看非正式的Rules of Makefiles,特别是2)。
【讨论】:
我修复了%.o
问题,并尝试从NUCLEO_F446RE.mk
中删除所有./
。它仍然给我同样的错误。我是否需要创建单独的规则来处理 mbed 对象文件?
@CalebReister 也许是错字?我猜-include $(TARGET)_mbed.mk
应该是include $(TARGET).mk
,去掉-
它掩盖了错误。删除./
对第二个问题没有帮助,问题是您将对象输出到obj/$@
,但您的规则说您将它们输出到%.o
(即$@
)。
我修复了第一个问题并修复了$(TARGET).mk
中的语法错误。第二个问题被证明更复杂。我会用一些新信息更新我的帖子。
@CalebReister 这与你的makefile无关,但this似乎是一回事。
感谢您的意见。但是,我仍然对 obj/ 部分感到困惑。我让规则在obj/%.o
中查找目标文件,但我仍然遇到同样的错误。这可能与库对象位于不同位置的事实有关吗?我需要一个规则来处理它们吗?为什么要在编译过程的后期使用头文件?以上是关于库包含未检测包含路径中的标头的主要内容,如果未能解决你的问题,请参考以下文章
资源 (.rc) 文件包含标头忽略 Visual Studio 项目包含路径