0

I have to create a Makefile which creates a single executable from the .c files in different folders. The .c files include header files from any of these folders. The root directory has 3 sub directories x/y, x/z, a, all these sub directories have some .c and .h files. I want to compile the program from the root directory. The nature of these sub directories is that new .c files may be added/removed anytime so it is not possible to hard code their names in the Makefile.

So far I have created this Makefile

CC = gcc
INCLUDES = -Ix/y -Ix/z -Ia -Ilib/include
LIB = -lp -lq -lr

demo: x/y/*_d.o x/z/*_l.o a/*_m.o
    $(CC) $^ $(LIB) -Llib -o b/demo.exe

%_d.o:: x/y/%.c
    $(CC) $(INCLUDES) -c $<

%_l.o:: x/z/%.c
    $(CC) $(INCLUDES) -c $<

%_m.o:: a/%.c
    $(CC) $(INCLUDES) -c $<

I need a solution that will take care of this scenario on its own. Also, if a single file is added to one of these folders then only its dependencies should be built instead of building all .c files all over again. TIA.

  • 1
    https://stackoverflow.com/questions/1484817/how-do-i-make-a-simple-makefile-for-gcc-on-linux/1484873#1484873 – Retired Ninja Apr 25 '19 at 23:49
  • regarding: `INCLUDES = -Ix/y -Ix/z -Ia -Ilib/include` Per your question, there is no `lib/include` – user3629249 Apr 26 '19 at 22:06
  • strongly suggest using: `SRC := $(wildcard x/y/*.c) $(wildcard x/z/*.c ) $(wildcard x/a/*.c )` Then `OBJ := $(SRC:.c=.o)` then `INC := $(SRC:.c=.h)` Then `DEP := $(SRC:.c=.d)` Then use `gcc` to produce the dependency files. Then at the end of the makefile use: `ifneq "$(MAKECMDGOALS)" "clean"` newline `-include $(DEP)` newline `endif` then the compile statement would be: `%.o: %.c %.d` newline tab `$(CC) $(CFLAGS) -c $< -o $@` Note: `CFLAGS := -Wall -Wextra -Wconversion -pedantic -std=gnu11` – user3629249 Apr 26 '19 at 22:24
  • by sending some options to the gcc prepossess step, using `-MD` (or similar) the pre-processer will generate the dependency file before actually compiling the source code – user3629249 Apr 26 '19 at 22:40

1 Answers1

0

You are mostly there. You just need a simple rule to compile .c into a .o, something like

.c.o: $(CC) $(INCLUDES) -c $<

Dependencies with wildcards are OK.