Makefile与链接不同的文件夹

时间:2014-06-12 16:54:47

标签: c linker makefile

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

1)所有标题都在/ include

2)在/ provided_objects

中提供了一些.o编译的实现(没有.c)

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

4)我的C代码生成的.o文件必须在/ built_objects

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

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

LD        = gcc
LDFLAGS   = -lm
OBJDIR    = provided_objects
OBJECTS = $(OBJDIR)/obj1.o    \    /$(OBJDIR)/obj2.o ...
MY_OBJECTS = 
quiet-command = $(if $(VERB),$1,$(if $(2),@echo $2 && $1, @$1))

all     : $(OBJDIR) $(PROG)

$(PROG) : $(OBJECTS) $(MY_OBJECTS)
    $(call quiet-command, $(LD) $^ -o $@, "  LD       $@" $(LDFLAGS))

$(OBJDIR):
    $(call quiet-command, mkdir -p $(OBJDIR),)

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

提前致谢!

2 个答案:

答案 0 :(得分:0)

假设我理解你想要什么,下面的makefile中的OBJECTS := ...行应该做你想要的。

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))

答案 1 :(得分:0)

让我们一步一步地做到这一点:

  1. 所有标题都在/include

     CPPFLAGS := -I /include # preprocessor flags
    
  2. .o

    中提供了一些.c已编译的实施(没有/provided_objects
    PROVIDED_OBJ_DIR := /provided_objects
    PROVIDED_OBJ     := $(wildard $(PROVIDED_OBJ_DIR)/*.o)
    
  3. 我创建的源代码必须位于/src

    SRC_DIR := /src
    SRC     := $(wildcard $(SRC_DIR)/*.c)
    
  4. 我的C代码生成的.o个文件必须位于/built_objects

    MY_OBJ_DIR := /built_objects
    MY_OBJ     := $(SRC:$(SRC_DIR)/%.c=$(MY_OBJ_DIR)/%.o)
    
  5. 可执行文件位于根

    EXE := /executable
    
  6. 我应该删除我在OBJECTS中命名的实施条目,并在MY_OBJECTS中引用它们。

    PROVIDED_OBJ := $(addprefix $(PROVIDED_OBJ_DIR)/,$(filter-out $(notdir $(MY_OBJ)), $(notdir $(PROVIDED_OBJ))))
    

    这条线有点长而复杂,所以让我们一起来看看:

    主要目标是从提供的文件中过滤掉您重新实现的目标文件 因此,使用的函数是$(filter-out files_to_remove, files_to_remove_from)

    $(filter-out $(MY_OBJ), $(PROVIDED_OBJ))
    

    问题是MY_OBJ中的文件以/built_objects/为前缀,而PROVIDED_OBJ中的文件以/provided_objects/为前缀,因此按原样提供,不会过滤掉任何内容。我们需要从名称中删除任何路径组件,因此函数$(notdir files)

    $(filter-out $(notdir $(MY_OBJ)), $(notdir $(PROVIDED_OBJ)))
    

    最后一步:我们需要重新添加正确的路径,否则make将无法找到文件。功能$(addprefix prefix, files)救援!

    $(addprefix $(PROVIDED_OBJ_DIR)/,$(filter-out $(notdir $(MY_OBJ)), $(notdir $(PROVIDED_OBJ))))
    
  7. 最后,不要忘记编译所有这些的正确规则!完成Makefile

    EXE                 :=  /executable
    
    SRC_DIR             :=  /src
    SRC                 :=  $(wildcard $(SRC_DIR)/*.c)
    
    MY_OBJ_DIR          :=  /built_objects
    MY_OBJ              :=  $(SRC:$(SRC_DIR)/%.c=$(MY_OBJ_DIR)/%.o)
    
    PROVIDED_OBJ_DIR    :=  /provided_objects
    PROVIDED_OBJ        :=  $(wildcard $(PROVIDED_OBJ_DIR)/*.o)
    PROVIDED_OBJ        :=  $(addprefix $(PROVIDED_OBJ_DIR)/,$(filter-out $(notdir $(MY_OBJ)), $(notdir $(PROVIDED_OBJ))))
    
    LDFLAGS             :=  # -L flags
    LDLIBS              :=  -lm # -l flags
    
    CFLAGS              :=  -W -Wall
    CPPFLAGS            :=  -I /include
    
    .PHONY: all
    
    all:    $(EXE)
    
    $(EXE): $(MY_OBJ)
        $(CC) $(LDFLAGS) $^ $(PROVIDED_OBJ) $(LDLIBS) -o $@
    
    $(MY_OBJ_DIR)/%.o:  $(SRC_DIR)/%.c
        @mkdir -p $(@D)
        $(CC) $(CPPFLAGS) $(CFLAGS) -o $@ -c $<
    
相关问题