稍微理解和修改这个makefile

稍微理解和修改这个makefile,makefile,Makefile,我一直在编辑这个makefile,但主要是尝试和错误 基本上,我在同一个目录中有n.c文件。我希望使用我的makefile hacks编译和链接第一个文件(具有固定名称),在链接步骤中包含不同的.o文件,并且只使用LIBS(不使用其他.o文件)编译和链接所有其他文件 这是“主”生成文件: MAKEFILE_BASE = ./Build-Assets/Makefile MAKEFILE_CONTROLLERS = ./Controllers/Makefile .PHONY: default cl

我一直在编辑这个makefile,但主要是尝试和错误

基本上,我在同一个目录中有
n
.c文件。我希望使用我的makefile hacks编译和链接第一个文件(具有固定名称),在链接步骤中包含不同的.o文件,并且只使用
LIBS
(不使用其他.o文件)编译和链接所有其他文件

这是“主”生成文件:

MAKEFILE_BASE = ./Build-Assets/Makefile
MAKEFILE_CONTROLLERS = ./Controllers/Makefile

.PHONY: default clean release release-clean

default: release

clean: release-clean

release:
    $(MAKE) -f $(MAKEFILE_CONTROLLERS) # This generates the .o files, and it works well
    $(MAKE) -f $(MAKEFILE_BASE).Release

release-clean:
    $(MAKE) -f $(MAKEFILE_BASE).Release clean
这就是“Makefile.Release”,它处理这些.c文件的编译/链接

TARGET = $(notdir $(shell pwd))

LIBS = -lm -lev3dev-c -pthread
D_BIN = Build-Assets

ifeq ($(OS),Windows_NT)
LIBS := $(LIBS) -lws2_32
D_BIN := $(D_BIN)/mingw
endif

D_H = ../../source/ev3
CFLAGS = $(addprefix -I, $(D_H)) -O2 -std=gnu99 -W -Wall -Wno-comment

ifeq ($(OS),Windows_NT)
CC = gcc
else
CC = arm-linux-gnueabi-gcc
endif

ifeq ($(OS),Windows_NT)
E_BIN = .exe
else
E_BIN =
endif

F_BIN = $(TARGET)$(E_BIN)

OBJECTS = $(addprefix $(D_BIN)/, $(patsubst %.c, %.o, $(wildcard *.c))) $(addprefix $(D_BIN)/, $(patsubst %.c, %.o, $(wildcard Controllers/*.c)))

.PHONY: default all clean

default: $(F_BIN)
all: default

$(OBJECTS): $(D_BIN)/%.o: %.c
    $(CC) $(CFLAGS) -c $< -o $@

.PRECIOUS: $(F_BIN) $(OBJECTS)

$(F_BIN): $(OBJECTS)
    $(info    VAR is $@)
    $(CC) $(OBJECTS) -Wall $(LIBS) -o $@

clean:
    -rm -f $(D_BIN)/*.o
    -rm -f $(F_BIN)
关于“目标名称作为目录名称的位置”,如下所示:

TARGET = $(notdir $(shell pwd))
这将运行shell命令
pwd
获取当前目录的完整路径,然后使用
notdir
剥离父目录。然后链接可执行文件的规则使用以下内容:

F_BIN = $(TARGET)$(E_BIN)
  ...
$(F_BIN): $(OBJECTS)
关于为什么会出现多个主要错误,这是因为您将新的
.c
文件与新的
main
一起添加到同一目录中,而不是使用makefile列出要编译和链接的特定源文件集,它使用
通配符来获取所有源文件:

OBJECTS = $(addprefix $(D_BIN)/, $(patsubst %.c, %.o, $(wildcard *.c))) $(addprefix $(D_BIN)/, $(patsubst %.c, %.o, $(wildcard Controllers/*.c)))
这些
$(通配符*.c)
函数将扩展到这些目录中的所有
*.c
文件,包括您添加的任何新文件。然后它们都将链接到目标中,这将为您提供两个不同的对象文件,其中包含
main


您必须更改此选项,以便仅列出所需的文件,或将文件放在其他位置,或使用make的
过滤功能将文件从列表中删除,或诸如此类的操作。

有一个严重的术语问题,使您很难理解您要做的事情。编译文件使用编译器将单个源文件
.c
转换为单个目标文件
.o
。无法执行对象文件,它们是构建的中间步骤。链接文件使用编译器(通常)将一个或多个对象文件转换为可运行的可执行文件。如果您可以编辑您的问题,将其改写为使用正确的术语,这将非常有用,这样我们就可以理解您正在尝试执行的操作。当您将一组对象文件链接到可执行文件中时,只有一个对象文件(从一个源文件构建)可以具有
main()
函数。如果您试图将包含
main()
的多个对象文件(来自源文件)链接到一个可执行文件中,您将得到有关
main
的多个定义的错误。我已编辑了该问题。谢谢
OBJECTS = $(addprefix $(D_BIN)/, $(patsubst %.c, %.o, $(wildcard *.c))) $(addprefix $(D_BIN)/, $(patsubst %.c, %.o, $(wildcard Controllers/*.c)))