使用make生成c源的目标文件时如何生成依赖文件

时间:2020-04-16 22:08:19

标签: c linux gcc makefile

我正在使用GNU工具,GCC实现构建系统,并使make编译多个目标,将它们链接在一起并创建最终的可执行文件。所有这些都支持两个平台。主机环境和嵌入式系统MSP432。

我正在学习有关嵌入式系统的入门课程,并做了几天前与之抗衡的作业。我自己尝试着通过互联网阅读,也在stackoverflow中阅读了这篇文章,但我还没明白,我仍然是一个菜鸟,所以我希望有人可以向我解释或给我一些有关解决问题的提示

如前所述,构建系统必须支持这两个平台,因此,第一步,我着重于确保所有工作都适用于主机环境。

在makefile文件中,我为以下目标创建了规则:

  1. build-生成可执行文件,目标文件,依赖项文件和映射文件
  2. %.o: %.c ...-生成目标文件及其依赖项
  3. compile-all-编译所有对象,但不链接它们
  4. %.i: %.c-生成C源文件的预处理输出
  5. %.asm: %.C-生成C源文件的程序集输出
  6. clean-清除所有生成的文件

问题在于执行make build PLATFORM=HOST

运行命令,我们得到:

.../src$ sudo make build PLATFORM=HOST
gcc -Wall -Werror -g -std=c99 -DHOST -Wl,-O0,-Map=c1m2.map main.c memory.c -I../includes/common -o c1m2.out
make: *** No rule to make target 'main.o', needed by 'build'.  Stop.

我注意到出现错误是因为第132行是我们

%.o: %.c

此行旨在禁用内置规则,并使用用户定义的下一行来的规则,但并没有这样做,因此我尝试注释此行并再次执行构建,然后得到:

.../src$ sudo make build PLATFORM=HOST
gcc -Wall -Werror -g -std=c99 -DHOST -Wl,-O0,-Map=c1m2.map main.c memory.c -I../includes/common -o c1m2.out
gcc -Wall -Werror -g -std=c99 -DHOST -E  -c -o main.o main.c
main.c:23:22: fatal error: platform.h: No such file or directory
compilation terminated.
< builtin >: recipe for target 'main.o' failed
make: *** [main.o] Error 1

现在它说,尽管包含包含头文件位置的INCLUDES变量指示它找不到“ platform.h”。另外,它使用内置配方来生成目标文件,并且失败。

因此,我被困在这一点上,想法是在执行“ make build PLATFORM = HOST”时构建输出可执行文件,映射文件,目标文件及其依赖文件。

在一开始,我编写了生成目标文件,仅用于生成输出,地图和目标文件,并且确实起作用,然后在进行了修改以生成依赖项文件后,我因该错误而迷失了方向。

生成预先处理的文件,程序集文件和进行清理的其他方法都可以正常工作。

您可以从以下位置克隆包含所有所需文件的文件夹:https://github.com/Fornaso/C1M2.git

谢谢大家。

这是我的Makefile:

#****************************************************************************** # Copyright (C) 2017 by Alex Fosdick - University of Colorado # # Redistribution, modification or use of this software in source or binary # forms is permitted as long as the files maintain this copyright. Users are # permitted to modify this and use it to learn about the field of embedded # software. Alex Fosdick and the University of Colorado are not liable for any # misuse of this material. # #****************************************************************************** # Modified on April 2020 by Adrián Fornaso #------------------------------------------------------------------------------ # Simple Makefile for multitarget build system # # Use: make [TARGET] [PLATFORM-OVERRIDES] # # Build Targets: # # build - Builds and links all source files and genereates: # # c1m2.map - Map file for the full build # *.d - Dependency Files for each source file # *.o - Individual object files # c1m2.out - Output Executable file # #<FILE>.i - Builds <FILE>.i preprocessed file. #<FILE>.asm - Builds <FILE>.i assembly file. #<FILE>.o - Builds <FILE>.o object file. #compile-all - Compile all objects but do NOT link them. #clean - Removes all generated files. # # Platform Overrides: Conditionally assign the appropriate compiler flags, # linker flags, and architecture flags. The target platform # must be provided at the command line with the make # command to set the platform you are compiling for. # # PLATFORM = MSP432 - The target embedded system will use # the cross compiler, arm-none-eabi-gcc. # PLATFORM = HOST - The host embedded system will use the # native compiler, gcc. # #------------------------------------------------------------------------------ #------------------------------------------------------------------------------ #General Flags (Both Platforms) # # -Wall Enable All Warning Messages (CFLAGS) # -Werror Treats All Warnings as Errors(CFLAGS) # -g Generate Debugging Info in Executable (CFLAGS) # -O0 The level of optimization (-O0, -O1, -O2, -O3)) (LDFLAGS) # -std=c99 The C standard set (CFLAGS) # #------------------------------------------------------------------------------ #Target name BASENAME = c1m2 TARGET = $(BASENAME).out #General Flags COMMONCFLAGS = -Wall -Werror -g -std=c99 COMMONLDFLAGS = -Wl,-O0,-Map=$(BASENAME).map #No spaces after commas after -Wl option. CPPFLAGS = -E # -E flag makes the compiler stop in the preprocessed output #Compile time switches ifeq ($(PLATFORM), MSP432) INCLUDES = -I../includes/common \ -I../includes/msp432 \ -I../includes/CMSIS SOURCES = main.c \ memory.c \ interrupts_msp432p401r_gcc.c \ startup_msp432p401r_gcc.c \ system_msp432p401r.c LINKER_FILE = msp432p401r.lds CPU = cortex-m4 ARCH = armv7e-m SPECS = nosys.specs CC = arm-none-eabi-gcc LD = arm-none-eabi-ld LDFLAGS = $(COMMONLDFLAGS), -T=$(LINKER_FILE) CFLAGS = $(COMMONCFLAGS) -D$(PLATFORM) -mcpu=$(CPU) \ -march=$(ARCH) --specs=$(SPECS) OBJDUMP = arm-none-eabi-objdump endif ifeq ($(PLATFORM), HOST) INCLUDES = -I../includes/common SOURCES = main.c \ memory.c CC = gcc LD = ld LDFLAGS = $(COMMONLDFLAGS) CFLAGS = $(COMMONCFLAGS) -D$(PLATFORM) OBJDUMP = objdump endif #Listing object files: OBJECTS = $(SOURCES:.c=.o) # 1. -------------------------------------------------------------------------- # Complete build: c1m2.map - Map file for the full build # *.d - Dependency Files for each source file # *.o - Individual object files # c1m2.out - Output Executable file # LDFLAGS contains the flags for creating the *.map file .PHONY: build build: $(TARGET) $(OBJECTS) $(TARGET): $(CC) $(CFLAGS) $(LDFLAGS) $(SOURCES) $(INCLUDES) -o $@ # 2. -------------------------------------------------------------------------- # //// Generates the object files of all c-program implementation files and its # dependecies. /////////////////////////////////////////////////////////// #This implementation places dependency files into a subdirectory named .deps. DEPDIR := .deps DEPFLAGS = -MT $@ -MD -MP -MF $(DEPDIR)/$*.d # Delete the built-in rules for building object files from .c files, so that # our rule is used instead. #%.o: %.c # Our rule for building object files with its dependency %.o: %.c $(DEPDIR)/%.d | $(DEPDIR) $(CC) $(DEPFLAGS) -c $(CFLAGS) $(INCLUDES) -o $@ $^ # Declare a rule for creating the dependency directory if it doesn’t exist. $(DEPDIR): ; @mkdir -p $@ # Generate a list of all the dependency files that could exist. DEPFILES := $(SRCS:%.c=$(DEPDIR)/%.d) # Mention each dependency file as a target, so that make won’t fail if the file # doesn’t exist. $(DEPFILES): # 2 bis. ---------------------------------------------------------------------- # /// Generates the object file of all c-program implementation files. //////// #%.o: %.c # $(CC) -c $(CFLAGS) $(INCLUDES) -o $@ $^ # 3. -------------------------------------------------------------------------- # /// Compile all objects but do NOT link them. /////////////////////////////// .PHONY: compile-all compile-all: $(SOURCES) $(CC) -c $(CFLAGS) $(INCLUDES) $^ # 4. -------------------------------------------------------------------------- # /// Generates the preprocessed output of all c-program implementation files. %.i: %.c $(CC) $(CPPFLAGS) $(CFLAGS) $(INCLUDES) -o $@ $^ # 5. -------------------------------------------------------------------------- # /// Create assembler file of a C source. //////////////////////////////////// %.asm: %.c $(CC) -S $(CFLAGS) $(INCLUDES) $< -o $@ # -S flag tells the compiler just generate the assembly file # 6. -------------------------------------------------------------------------- # /// Removes all compiled objects, preprocessed outputs, assembly outputs, # executable files and build output files. //////////////////////////////// .PHONY: clean clean: rm -f $(OBJECTS) $(TARGET) $(BASENAME).map *.asm *.i rm -r .dep #End of file

1 个答案:

答案 0 :(得分:1)

有两个小错误使我花了相当长时间才能看到:

  • DEPFILES := $(SRCS:%.c=$(DEPDIR)/%.d)必须为DEPFILES := $(SOURCES:%.c=$(DEPDIR)/%.d)-否则DEPFILES为空,因为SRCS未定义。
  • $(CC) $(DEPFLAGS) -c $(CFLAGS) $(INCLUDES) -o $@ $^中,$^所有先决条件)扩展为e。 G。 main.c .deps/main.d,因此将尚不存在的.deps/main.d作为输入文件传递;我们希望使用$*.c而不是$^

另一个小错误是:

  • rm -r .dep应该是rm -r .depsrm -r $(DEPDIR)