0

I'm coping with an issue, probably due to my lack of knowledge of makefile possibilities. I'd like to set a rule similar to

$(OBJ_DIR)/%.o: %.c
    @echo "Compiling...";
    $(CC) $(CFLAGS) $(INCLUDES) -c $< -o $@
    echo "Files compiled"

but with following target/prerequisites conditions:

targets: All targets at OBJ_DIR folder. Each one for each .c file I want to compile. prerequisites: a list of .c files that comes from a external file (or eventually listed at makefile itself) including folder path. Folders for .c files are different.

DIR1/FILE1.c
DIR2/FILE2.c
DIR3/FILE3.c
DIR4/FILE4.c

Each .o target only depends on its corresponding prerequisite. For instance,

FILE1.o <--> FILE1.c
FILE2.o <--> FILE2.c
FILE3.o <--> FILE3.c
FILE4.o <--> FILE4.c

Of course I can repeat the rules for each target/prerequiste, but I'd like to unify the rule in a single one, assuring that the dependencies are set one by one .o <---> .c, without involving crossed dependencies between prerequisites and targets with no real dependency.

Can you help in regards ?

Renaud Pacalet
  • 25,260
  • 3
  • 34
  • 51
  • Please edit your question and fix the formatting. You want to use code block formatting. Formatting is critical when thinking about makefiles. – MadScientist Jul 05 '23 at 15:35

1 Answers1

1

It seems that the meat of your question is here: Folders for .c files are different. It would be helpful if you made that more clear, describing more exactly what about the pattern rule you show is not working for you.

There are two ways to support putting object files in other directories. If you want all the object files to appear in a single output directory, regardless of where the source files live, then you need to use the VPATH facility. It would look something like this:

SRCS := DIR1/FILE1.c DIR2/FILE2.c DIR3/FILE3.c DIR4/FILE4.c

OBJS := $(patsubst %.c,$(OBJ_DIR)/%.o,$(notdir $(SRCS)))

VPATH := $(sort $(dir $(SRCS))

objects: $(OBJS)

$(OBJ_DIR)/%.o : %.c
        $(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $<

The downside here is that if any two source directories contain the same-named .c file (e.g., foo/one.c and bar/one.c) then your build will fail.

The other option is to reproduce the source file directory structure in the object file subdirectory. Then you don't need VPATH and a simple pattern rule will work and you don't have to worry about duplicate source file names, but you have to create the directory, like this:

SRCS := DIR1/FILE1.c DIR2/FILE2.c DIR3/FILE3.c DIR4/FILE4.c

OBJS := $(patsubst %.c,$(OBJ_DIR)/%.o,$(SRCS))

objects: $(OBJS)

$(OBJ_DIR)/%.o : %.c
        @mkdir -p $(@D)
        $(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $<
MadScientist
  • 92,819
  • 9
  • 109
  • 136