C 使用链接不同文件夹的Makefile

C 使用链接不同文件夹的Makefile,c,linker,makefile,C,Linker,Makefile,我必须为具有以下文件夹结构的项目构建makefile: 1) 所有标题都在/include中 2) 在/provided\u对象中提供了一些.o编译实现(没有.c) 3) 我创建的源代码必须在/src中 4) 由我的C代码生成的.o文件必须是in/build\u对象 5) 可执行文件位于根目录中 我最初的目的是用我的实现替换/provided_对象中的一些实现,记住我的实现可以使用我没有实现的头定义的函数。已经有一个默认的makefile包含(在较小的细节中): 我应该删除我实现的在对象中命名的

我必须为具有以下文件夹结构的项目构建makefile:

1) 所有标题都在/include中

2) 在/provided\u对象中提供了一些.o编译实现(没有.c)

3) 我创建的源代码必须在/src中

4) 由我的C代码生成的.o文件必须是in/build\u对象

5) 可执行文件位于根目录中

我最初的目的是用我的实现替换/provided_对象中的一些实现,记住我的实现可以使用我没有实现的头定义的函数。已经有一个默认的makefile包含(在较小的细节中):

我应该删除我实现的在对象中命名的条目,并在我的_对象中引用它们。我的问题是,我应该怎么做?我在makefiles方面不是很有经验,我在研究中发现的链接没有解决我的限制


提前谢谢

假设我正确地理解了您想要的内容,下面makefile中的
对象:=…
行应该执行您想要的操作

OBJDIR    = provided_objects
OBJECTS = $(OBJDIR)/obj1.o \
          $(OBJDIR)/obj2.o \
          $(OBJDIR)/obj3.o \
          $(OBJDIR)/obj4.o \
          $(OBJDIR)/obj5.o
MY_OBJDIR = built_objects
MY_OBJECTS = $(MY_OBJDIR)/obj2.o $(MY_OBJDIR)/obj4.o

$(info Before)
$(info OBJECTS: $(OBJECTS))
$(info MY_OBJECTS: $(MY_OBJECTS))

OBJECTS := $(filter-out $(addprefix $(OBJDIR)/,$(notdir $(MY_OBJECTS))),$(OBJECTS))

$(info After)
$(info OBJECTS: $(OBJECTS))
$(info MY_OBJECTS: $(MY_OBJECTS))

让我们一步一步来:

  • 所有标题都在
    /include

    CPPFLAGS:=-I/include#预处理器标志
    
  • /provided\u对象中提供了一些
    .o
    编译实现(没有
    .c

    提供的对象目录:=/提供的对象
    提供的对象:=$(wildard$(提供的对象目录)/*.o)
    
  • 我创建的源代码必须在
    /src

    SRC\u DIR:=/SRC
    SRC:=$(通配符$(SRC_DIR)/*.c)
    
  • 我的C代码生成的
    .o
    文件必须位于
    /build\u对象中

    MY_OBJ_DIR:=/build_对象
    MY_OBJ:=$(SRC:$(SRC_DIR)/%.c=$(MY_OBJ_DIR)/%.o)
    
  • 可执行文件位于根目录中

    EXE:=/executable
    
  • 我应该删除在
    对象
    中命名的我实现的条目,并在
    我的对象
    中引用它们

    PROVIDED_OBJ:=$(addprefix$(PROVIDED_OBJ_DIR)/,$(filter out$(notdir$(MY_OBJ)),$(notdir$(PROVIDED_OBJ)))
    
    这一行有点长,有点复杂,所以我们也来回顾一下:

    主要目标是从提供的对象文件中筛选出重新实现的对象文件。
    因此,所使用的函数是
    $(过滤掉要删除的文件、要删除的文件)

    $(过滤掉$(我的对象),$(提供的对象))
    
    问题是
    MY\u OBJ
    中的文件以
    /builded\u objects/
    为前缀,而
    PROVIDED\u OBJ
    中的文件以
    /PROVIDED\u objects/
    为前缀,因此按原样提供,不会过滤掉任何内容。我们需要从名称中删除任何路径组件,因此函数
    $(notdir files)

    $(过滤掉$(notdir$(我的对象)),$(notdir$(提供的对象)))
    
    最后一步:我们需要重新添加正确的路径,否则make将找不到文件。函数
    $(addprefix prefix,files)
    用于救援

    $(addprefix$(提供的对象)/,$(过滤掉$(notdir$(我的对象)),$(notdir$(提供的对象)))
    
  • 最后,不要忘记编译所有这些的正确规则!完成生成文件

    EXE:=/executable
    SRC_DIR:=/SRC
    SRC:=$(通配符$(SRC_DIR)/*.c)
    MY_OBJ_DIR:=/build_对象
    MY_OBJ:=$(SRC:$(SRC_DIR)/%.c=$(MY_OBJ_DIR)/%.o)
    提供的对象目录:=/提供的对象
    提供的对象:=$(通配符$(提供的对象目录)/*.o)
    提供的对象:=$(addprefix$(提供的对象)/,$(过滤掉$(notdir$(MY\u OBJ)),$(notdir$(提供的对象)))
    LDFLAGS:=#-L个标志
    LDLIBS:=-lm#-l标志
    CFLAGS:=-W-墙
    CPPFLAGS:=-I/include
    冒牌货:全部
    全部:$(EXE)
    $(EXE):$(MY_OBJ)
    $(CC)$(LDFLAGS)$^$(提供的对象)$(LDLIBS)-o$@
    $(MY_OBJ_DIR)/%.o:$(SRC_DIR)/%.c
    @mkdir-p$(@D)
    $(CC)$(CPPFLAGS)$(CFLAGS)-o$@-c$<
    

  • 为什么要使用退出命令?而且,最好删除它,因为它只会使您的makefile变得复杂,而不会给您的问题添加任何内容。它是给我的,我应该去改变它。我不知道那有什么用。
    OBJDIR    = provided_objects
    OBJECTS = $(OBJDIR)/obj1.o \
              $(OBJDIR)/obj2.o \
              $(OBJDIR)/obj3.o \
              $(OBJDIR)/obj4.o \
              $(OBJDIR)/obj5.o
    MY_OBJDIR = built_objects
    MY_OBJECTS = $(MY_OBJDIR)/obj2.o $(MY_OBJDIR)/obj4.o
    
    $(info Before)
    $(info OBJECTS: $(OBJECTS))
    $(info MY_OBJECTS: $(MY_OBJECTS))
    
    OBJECTS := $(filter-out $(addprefix $(OBJDIR)/,$(notdir $(MY_OBJECTS))),$(OBJECTS))
    
    $(info After)
    $(info OBJECTS: $(OBJECTS))
    $(info MY_OBJECTS: $(MY_OBJECTS))