Home > OS >  Makefile:I changed the directory of objs ,but all the files are compiled everytime
Makefile:I changed the directory of objs ,but all the files are compiled everytime

Time:02-04

I want to save all the generated .o files under the folder $(BUILD_DIR).

Although I did not edit any flies, all the src files will be recompiled.

Thanks to @JohnBollinger 's suggestion. I created a new project to test the problem.

My test project directory tree:

/test
   /app
      main.c
      Makefile
   /build_dir
      Makefile
   /bin
   Makefile


This is my top Makefile


TOPDIR := $(PWD)
CROSS_COMPILE :=


AS      = $(CROSS_COMPILE)as
LD      = $(CROSS_COMPILE)ld
CC      = $(CROSS_COMPILE)gcc
CPP     = $(CC) -E
AR      = $(CROSS_COMPILE)ar
NM      = $(CROSS_COMPILE)nm
STRIP       = $(CROSS_COMPILE)strip
OBJCOPY     = $(CROSS_COMPILE)objcopy
OBJDUMP     = $(CROSS_COMPILE)objdump

MARCH :=x86

SZ = $(CROSS_COMPILE)size

OPT = -O0
CFLAGS = $(C_INCLUDES)
CFLAGS = -g -gdwarf-2
CFLAGS = $(OPT)

TARGET = test-$(MARCH)
BUILD_DIR = $(TOPDIR)/build_dir
BIN_DIR = $(TOPDIR)/bin


SUBDIRS = $(TOPDIR)/app \

export  CC CPP LD MARCH CFLAGS LDFLAGS TARGET CROSS_COMPILE
export BUILD_DIR BIN_DIR TOPDIR LINK_SCRIPT
export CPU ARCH MARCH BOARD

ALL:$(SUBDIRS)
    $(OBJCOPY) -O binary -S $(BIN_DIR)/$(TARGET).elf $(BIN_DIR)/$(TARGET).bin
    @echo  "\033[32mbuild success \033[0m"




$(SUBDIRS):ECHO
    @make clean
    @-mkdir -p bin
    @for dir in $(SUBDIRS); do \
    echo -------------------compiling $$dir ------------------;\
    make -C $$dir || exit "$$?";\
    done
    @make -C $(BUILD_DIR)


ECHO:

.PHONY : clean ALL
clean:
    -rm $(BUILD_DIR)/*.o 
    -rm $(BIN_DIR)/*

here is my Makefile in app directory:

objs  = $(BUILD_DIR)/main.o

all:$(objs)

$(BUILD_DIR)/%.o:%.c
    $(CC) $(CFLAGS) -c -o $@ $< -MD -MF [email protected]

.PHONY: all

I tried make -d,and spotted:

 Considering target file '/home/alan/Desktop/test/build_dir/main.o'.
   File '/home/alan/Desktop/test/build_dir/main.o' does not exist.
   ...
   No need to remake target 'main.c'.
   Finished prerequisites of target file '/home/alan/Desktop/test/build_dir/main.o'.
  Must remake target '/home/alan/Desktop/test/build_dir/main.o'.

Actually:

alan@alan-PC:~/Desktop/test/build_dir$ ls
main.o  main.o.d  Makefile

The main.o exist!

Why make think it doesn't exist?

CodePudding user response:

To understand make problems, all that's required usually is to pay attention to the commands that make is running. If they are not correct, then figure out why.

Your problem is right here:

$(SUBDIRS):ECHO
        @make clean
        ...

So the first thing you do for each subdirectory is run make clean. That will of course delete all the object files:

clean:
        -rm $(BUILD_DIR)/*.o 
        -rm $(BIN_DIR)/*

So of course make will have to rebuild them. If you examine the output that make prints, you'll see these commands that remove all object files, and you'll know why make is always rebuilding all the object files.

Also a note, you should never invoke a sub-make with the literal string make. You should always use the variable $(MAKE) (or ${MAKE} if you prefer: same thing).

Old Answer

This:

SOURCES  =$(wildcard *.c) 
objs  = $(patsubst %.c,$(BUILD_DIR)/$(MARCH)-%.o,$(SOURCES))

Let's assume BUILD_DIR is set to obj and MARCH is set to x86_64. Let's assume there is one file foo.c. The we get this:

SOURCES = foo.c
objs = obj/x86_64-foo.o

Now you have defined this rule:

all: obj/x86_64-foo.o

obj/%.o:%.c
        $(CC) $(CFLAGS) -c -o $@ $< -MD -MF [email protected]

this can't work because the % in the target and prerequisite must be identical. Here, the target's % matches x86_64-foo and so this rule will only match if the file x86_64-foo.c exists which, presumably, it doesn't.

I don't actually know how you get anything from this makefile except "don't know how to build target obj/x86_64-foo.o" so clearly there are things about this makefile you've omitted if it builds something for you.

If you write your rule like this instead:

$(BUILD_DIR)/$(MARCH)-%.o : %.c
        $(CC) $(CFLAGS) -c -o $@ $< -MD -MF [email protected]

then it should work.

  •  Tags:  
  • Related