Gcc 如何编写包含多个目录的Makefile

Gcc 如何编写包含多个目录的Makefile,gcc,makefile,arm,Gcc,Makefile,Arm,我有以下设置。在主文件夹中有两个名为/driverlib和/inc的文件夹,在同一文件夹中,我有一个链接器文件和两个c文件,startup_gcc和blink.c #include <stdbool.h> #include <stdint.h> #include "inc/hw_can.h" #include "inc/hw_ints.h" #include "inc/hw_nvic.h" #include "inc/hw_memmap.h" #include "inc/

我有以下设置。在主文件夹中有两个名为/driverlib和/inc的文件夹,在同一文件夹中,我有一个链接器文件和两个c文件,startup_gcc和blink.c

#include <stdbool.h>
#include <stdint.h>
#include "inc/hw_can.h"
#include "inc/hw_ints.h"
#include "inc/hw_nvic.h"
#include "inc/hw_memmap.h"
#include "inc/hw_sysctl.h"
#include "inc/hw_types.h"
#include "driverlib/can.h"
#include "driverlib/debug.h"
#include "driverlib/interrupt.h" 
我遵循了我在网上找到的STM32F4模板。我修改了它,并试图在我的文件夹中包含这两个目录。但是,我得到以下错误:

C:\Users\D\Documents\ARM-Tiva\blinky3>make
driverlib/adc.c:49:24: fatal error: inc/hw_adc.h: No such file or directory
compilation terminated.
make: *** [driverlib/adc.o] Error 1
#include <stdbool.h>
#include <stdint.h>
#include "inc/hw_can.h"
#include "inc/hw_ints.h"
#include "inc/hw_nvic.h"
#include "inc/hw_memmap.h"
#include "inc/hw_sysctl.h"
#include "inc/hw_types.h"
#include "driverlib/can.h"
#include "driverlib/debug.h"
#include "driverlib/interrupt.h" 
有人能给我解释一下如何包括这两个目录,以便/inc文件夹对/driverlib文件夹可见

#include <stdbool.h>
#include <stdint.h>
#include "inc/hw_can.h"
#include "inc/hw_ints.h"
#include "inc/hw_nvic.h"
#include "inc/hw_memmap.h"
#include "inc/hw_sysctl.h"
#include "inc/hw_types.h"
#include "driverlib/can.h"
#include "driverlib/debug.h"
#include "driverlib/interrupt.h" 
以下是生成文件:

OBJCOPY     = $(TC)-objcopy
OBJDUMP     = $(TC)-objdump
SIZE        = $(TC)-size

###################################################
# Set Include Paths
INCLUDES    = -I /inc 
INCLUDES    = -I /driverlib

# Set Sources
LIB_SRCS    = $(wildcard driverlib/*.c)
USER_SRCS   = $(wildcard src/*.c)

# Set Objects
LIB_OBJS    = $(LIB_SRCS:.c=.o)
USER_OBJS   = $(USER_SRCS:.c=.o) startup_gcc.o


# Set Libraries
LIBS        = -lm -lc

###################################################
# Set Board
MCU         = -mthumb -mcpu=cortex-m4
DEFINES     = -DPART_LM4F120H5QR -DTARGET_IS_BLIZZARD_RA1

# Set Compilation and Linking Flags
CFLAGS      = $(MCU) $(FPU) $(DEFINES) $(INCLUDES) \
            -g -Wall -std=gnu90 -O0 -ffunction-sections -fdata-sections
ASFLAGS     = $(MCU) $(FPU) -g -Wa,--warn -x assembler-with-cpp
LDFLAGS     = $(MCU) $(FPU) -g -gdwarf-2 \
            -Ttivalinker.ld \
            -Xlinker --gc-sections -Wl,-Map=$(PROJ_NAME).map \
            $(LIBS) \
            -o $(PROJ_NAME).elf

###################################################
# Default Target
all: $(PROJ_NAME).bin info

# elf Target
$(PROJ_NAME).elf: $(LIB_OBJS) $(USER_OBJS)
    @$(CC) $(LIB_OBJS) $(USER_OBJS) $(LDFLAGS)
    @echo $@

# bin Target
$(PROJ_NAME).bin: $(PROJ_NAME).elf
    @$(OBJCOPY) -O binary $(PROJ_NAME).elf $(PROJ_NAME).bin
    @echo $@

#$(PROJ_NAME).hex: $(PROJ_NAME).elf
#   @$(OBJCOPY) -O ihex $(PROJ_NAME).elf $(PROJ_NAME).hex
#   @echo $@

#$(PROJ_NAME).lst: $(PROJ_NAME).elf
#   @$(OBJDUMP) -h -S $(PROJ_NAME).elf > $(PROJ_NAME).lst
#   @echo $@

# Display Memory Usage Info
info: $(PROJ_NAME).elf
    @$(SIZE) --format=berkeley $(PROJ_NAME).elf

# Rule for .c files
.c.o:
    @$(CC) $(CFLAGS) -c -o $@ $<
    @echo $@

# Rule for .s files
.s.o:
    @$(CC) $(ASFLAGS) -c -o $@ $<
    @echo $@

# Clean Target
clean:
    $(RM) $(LIB_OBJS)
    $(RM) $(USER_OBJS)
    $(RM) $(PROJ_NAME).elf
    $(RM) $(PROJ_NAME).bin
    $(RM) $(PROJ_NAME).map
#include <stdbool.h>
#include <stdint.h>
#include "inc/hw_can.h"
#include "inc/hw_ints.h"
#include "inc/hw_nvic.h"
#include "inc/hw_memmap.h"
#include "inc/hw_sysctl.h"
#include "inc/hw_types.h"
#include "driverlib/can.h"
#include "driverlib/debug.h"
#include "driverlib/interrupt.h" 
我无法理解为什么driverlib不包含inc目录文件

#include <stdbool.h>
#include <stdint.h>
#include "inc/hw_can.h"
#include "inc/hw_ints.h"
#include "inc/hw_nvic.h"
#include "inc/hw_memmap.h"
#include "inc/hw_sysctl.h"
#include "inc/hw_types.h"
#include "driverlib/can.h"
#include "driverlib/debug.h"
#include "driverlib/interrupt.h" 
编辑

#include <stdbool.h>
#include <stdint.h>
#include "inc/hw_can.h"
#include "inc/hw_ints.h"
#include "inc/hw_nvic.h"
#include "inc/hw_memmap.h"
#include "inc/hw_sysctl.h"
#include "inc/hw_types.h"
#include "driverlib/can.h"
#include "driverlib/debug.h"
#include "driverlib/interrupt.h" 
我想澄清我的设置以供将来参考:在名为blinky的主文件夹中,我有三个文件夹:driverlib,inc和src。driverlib和inc文件夹取自TivaWARE文件夹,而src文件夹包含blinky.c和startup_gcc.c文件。如果使用以下选项,则可以获得以下内容:

C:\Users\D\Documents\ARM-Tiva\blinky>make
driverlib/adc.c:49:24: fatal error: inc/hw_adc.h: No such file or directory
compilation terminated.
make: *** [driverlib/adc.o] Error 1   
#include <stdbool.h>
#include <stdint.h>
#include "inc/hw_can.h"
#include "inc/hw_ints.h"
#include "inc/hw_nvic.h"
#include "inc/hw_memmap.h"
#include "inc/hw_sysctl.h"
#include "inc/hw_types.h"
#include "driverlib/can.h"
#include "driverlib/debug.h"
#include "driverlib/interrupt.h" 
这表明driverlib文件夹中的文件adc.c不能包含中的文件hw_adc.h

#include <stdbool.h>
#include <stdint.h>
#include "inc/hw_can.h"
#include "inc/hw_ints.h"
#include "inc/hw_nvic.h"
#include "inc/hw_memmap.h"
#include "inc/hw_sysctl.h"
#include "inc/hw_types.h"
#include "driverlib/can.h"
#include "driverlib/debug.h"
#include "driverlib/interrupt.h" 
我按照以下建议修改了Makefile:

# Set Sources
LIB_SRCS    = $(wildcard driverlib/*.c)
USER_SRCS   = $(wildcard src/*.c)

# Set Objects
LIB_OBJS    = $(LIB_SRCS:.c=.o)
USER_OBJS   = $(USER_SRCS:.c=.o) src/startup_gcc.o

# Set Include Paths
INCLUDES    = -Idriverlib/ \
            -Iinc \
            -Isrc/
#include <stdbool.h>
#include <stdint.h>
#include "inc/hw_can.h"
#include "inc/hw_ints.h"
#include "inc/hw_nvic.h"
#include "inc/hw_memmap.h"
#include "inc/hw_sysctl.h"
#include "inc/hw_types.h"
#include "driverlib/can.h"
#include "driverlib/debug.h"
#include "driverlib/interrupt.h" 
Betas解决方案很有帮助,唯一的问题是我不想编辑driverlib文件夹中的所有文件。目录的命名约定不是我的决定。如果您可以查看driverlib文件夹中的所有文件,您会发现每个驱动程序文件(例如can驱动程序或ADC)都遵循以下约定:

#include <stdbool.h>
#include <stdint.h>
#include "inc/hw_can.h"
#include "inc/hw_ints.h"
#include "inc/hw_nvic.h"
#include "inc/hw_memmap.h"
#include "inc/hw_sysctl.h"
#include "inc/hw_types.h"
#include "driverlib/can.h"
#include "driverlib/debug.h"
#include "driverlib/interrupt.h" 
#包括
#包括
#包括“inc/hw_can.h”
#包括“inc/hw_ints.h”
#包括“inc/hw_nvic.h”
#包括“inc/hw_memmap.h”
#包括“inc/hw_sysctl.h”
#包括“inc/hw_types.h”
#包括“driverlib/can.h”
#包括“driverlib/debug.h”
#包括“driverlib/interrupt.h”
所以现在我知道问题出在哪里了,但我缺乏编辑Makefile的理解。 通常,如果文件can.c和can.h位于driverlib文件夹中,那么使用#include“can.h”就足够了,因此我不明白如果所有的.h和.c文件都位于同一driverlib文件夹中,那么使用#include“driverlib/can.h”有什么意义。如果我编辑所有inc/头,那么我可以得到一个工作的二进制文件。但是,目的不是修改从TI获得的默认库存驱动程序文件和文件夹,而是使用Makefile

#include <stdbool.h>
#include <stdint.h>
#include "inc/hw_can.h"
#include "inc/hw_ints.h"
#include "inc/hw_nvic.h"
#include "inc/hw_memmap.h"
#include "inc/hw_sysctl.h"
#include "inc/hw_types.h"
#include "driverlib/can.h"
#include "driverlib/debug.h"
#include "driverlib/interrupt.h" 

因此,为了澄清您是否遵循Betas解决方案并编辑所有文件,或者如果您将所有文件放在一个大目录中,那么您可以得到一个工作的二进制文件。另外,为了将来参考,我发现我可以使用Energia来完成我的工作,因为它使用相同的编译器,TIVA包括在ROM上烧掉的完整外围库。

我不知道错误的确切原因,但这是不正确的:

#include <stdbool.h>
#include <stdint.h>
#include "inc/hw_can.h"
#include "inc/hw_ints.h"
#include "inc/hw_nvic.h"
#include "inc/hw_memmap.h"
#include "inc/hw_sysctl.h"
#include "inc/hw_types.h"
#include "driverlib/can.h"
#include "driverlib/debug.h"
#include "driverlib/interrupt.h" 
INCLUDES    = -I /inc 

# Now INCLUDES is "-I /inc"

INCLUDES    = -I /driverlib

# Now INCLUDES is "-I /driverlib", and inc has been forgotten.
我想你的意思是:

#include <stdbool.h>
#include <stdint.h>
#include "inc/hw_can.h"
#include "inc/hw_ints.h"
#include "inc/hw_nvic.h"
#include "inc/hw_memmap.h"
#include "inc/hw_sysctl.h"
#include "inc/hw_types.h"
#include "driverlib/can.h"
#include "driverlib/debug.h"
#include "driverlib/interrupt.h" 
INCLUDES    = -I /inc 
INCLUDES    += -I /driverlib
编辑:

#include <stdbool.h>
#include <stdint.h>
#include "inc/hw_can.h"
#include "inc/hw_ints.h"
#include "inc/hw_nvic.h"
#include "inc/hw_memmap.h"
#include "inc/hw_sysctl.h"
#include "inc/hw_types.h"
#include "driverlib/can.h"
#include "driverlib/debug.h"
#include "driverlib/interrupt.h" 

在#include指令中详细说明路径通常是个坏主意。在adc.c中,更改以下内容:

#include <stdbool.h>
#include <stdint.h>
#include "inc/hw_can.h"
#include "inc/hw_ints.h"
#include "inc/hw_nvic.h"
#include "inc/hw_memmap.h"
#include "inc/hw_sysctl.h"
#include "inc/hw_types.h"
#include "driverlib/can.h"
#include "driverlib/debug.h"
#include "driverlib/interrupt.h" 
#include "inc/hw_adc.h"
为此:

#include <stdbool.h>
#include <stdint.h>
#include "inc/hw_can.h"
#include "inc/hw_ints.h"
#include "inc/hw_nvic.h"
#include "inc/hw_memmap.h"
#include "inc/hw_sysctl.h"
#include "inc/hw_types.h"
#include "driverlib/can.h"
#include "driverlib/debug.h"
#include "driverlib/interrupt.h" 
#include "hw_adc.h"
并在makefile中删除前面的斜杠(因为您并不总是在根目录中):

#include <stdbool.h>
#include <stdint.h>
#include "inc/hw_can.h"
#include "inc/hw_ints.h"
#include "inc/hw_nvic.h"
#include "inc/hw_memmap.h"
#include "inc/hw_sysctl.h"
#include "inc/hw_types.h"
#include "driverlib/can.h"
#include "driverlib/debug.h"
#include "driverlib/interrupt.h" 

最有用的是,如果您在问题中提供了一个未找到的头文件的实际完整路径,以及make在错误消息之外运行的示例编译行。考虑到这些信息,很难看出哪里出了问题

#include <stdbool.h>
#include <stdint.h>
#include "inc/hw_can.h"
#include "inc/hw_ints.h"
#include "inc/hw_nvic.h"
#include "inc/hw_memmap.h"
#include "inc/hw_sysctl.h"
#include "inc/hw_types.h"
#include "driverlib/can.h"
#include "driverlib/debug.h"
#include "driverlib/interrupt.h" 
看来有一些沟通失误发生了。在主文件夹上写两个名为/driverlib和/inc的文件夹。根据定义,以
/
开头的文件夹名位于目录结构的根目录中,而不在任何其他文件夹中。我不知道你说的主文件夹是什么意思

#include <stdbool.h>
#include <stdint.h>
#include "inc/hw_can.h"
#include "inc/hw_ints.h"
#include "inc/hw_nvic.h"
#include "inc/hw_memmap.h"
#include "inc/hw_sysctl.h"
#include "inc/hw_types.h"
#include "driverlib/can.h"
#include "driverlib/debug.h"
#include "driverlib/interrupt.h" 
我要说的第一件事是您正在使用Windows(从命令行提示符可以看到),因此您需要确保您正在使用的make版本将正确地将Windows路径名转换为UNIX路径名。例如,如果您使用的是Cygwin版本的GNU make,那么我认为您使用的路径是不正确的

#include <stdbool.h>
#include <stdint.h>
#include "inc/hw_can.h"
#include "inc/hw_ints.h"
#include "inc/hw_nvic.h"
#include "inc/hw_memmap.h"
#include "inc/hw_sysctl.h"
#include "inc/hw_types.h"
#include "driverlib/can.h"
#include "driverlib/debug.h"
#include "driverlib/interrupt.h" 
其次,我注意到您使用的是
-I/inc
;也就是说,
inc
目录位于文件系统的根目录。这是你的本意吗?Beta的答案将其更改为
-I inc
,这意味着目录
inc
作为当前工作目录的子目录,可能会有很大不同

#include <stdbool.h>
#include <stdint.h>
#include "inc/hw_can.h"
#include "inc/hw_ints.h"
#include "inc/hw_nvic.h"
#include "inc/hw_memmap.h"
#include "inc/hw_sysctl.h"
#include "inc/hw_types.h"
#include "driverlib/can.h"
#include "driverlib/debug.h"
#include "driverlib/interrupt.h" 
第三,如果标题的路径名是
/inc/hw_adc.h
,并且您的命令行上有
-I/inc
,并且
#包括“inc/hw_adc.h”
,我相信您可以看到这绝对不起作用。编译器将查找名为
/inc/inc/hw_adc.h
的头文件。如果要在
#include
行中保留相对路径名
inc/hw_adc.h
,并且头文件的路径是
/inc/hw_adc.h
,则应在编译命令行上使用
-I/
(根目录)

#include <stdbool.h>
#include <stdint.h>
#include "inc/hw_can.h"
#include "inc/hw_ints.h"
#include "inc/hw_nvic.h"
#include "inc/hw_memmap.h"
#include "inc/hw_sysctl.h"
#include "inc/hw_types.h"
#include "driverlib/can.h"
#include "driverlib/debug.h"
#include "driverlib/interrupt.h" 
最后,我要说,我实际上不同意Beta的建议,即在包含行中拼写路径是个坏主意。这是很常见的:如果您使用的库包含很多头文件,那么头文件通常收集在一个子目录中(考虑Boost或X11等),在源代码的
#include
行中使用子目录的名称是一种良好的做法

#include <stdbool.h>
#include <stdint.h>
#include "inc/hw_can.h"
#include "inc/hw_ints.h"
#include "inc/hw_nvic.h"
#include "inc/hw_memmap.h"
#include "inc/hw_sysctl.h"
#include "inc/hw_types.h"
#include "driverlib/can.h"
#include "driverlib/debug.h"
#include "driverlib/interrupt.h" 

另一方面,尽管如此,我同意Beta的说法,像
inc
这样的目录名是完全无用的。该目录应该有一个名称,该名称在某种程度上能让人联想到目录中可以找到的各种标题,而不是像“inc”这样无用的通用名称。

可能是一个重复的问题:我已经尝试过了。我仍然会犯同样的错误。我也试着阅读Make手册,但没有太多成功。“inc/hw_adc.h”不在“/inc”或“/driverlib”中。如果您已经在include路径中添加了“inc/”,那么您可以将“inc/hw_adc.h”替换为“hw_adc.h”
#include <stdbool.h>
#include <stdint.h>
#include "inc/hw_can.h"
#include "inc/hw_ints.h"
#include "inc/hw_nvic.h"
#include "inc/hw_memmap.h"
#include "inc/hw_sysctl.h"
#include "inc/hw_types.h"
#include "driverlib/can.h"
#include "driverlib/debug.h"
#include "driverlib/interrupt.h"