0

I am not entirely sure if what I am doing is possible in make, but I will give it a go.

So normally I can have a pattern matching rule like so

$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c | $(OBJ_DIR)
    $(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $@

and if my understanding is correct, each target, like obj/file.o will be paired (depend on) with its respective prerequisite src/file.c.

Now, in my situation, I have a lot of nested directories under my src directory. So I was able to make/find a recursive command such that I can group all the source files together. An example looks like

SOURCES := [src/main.c src/dir1/a.c src/dir2/b.c]

and using the pattern substitution I was able to get a list of all the object files (without their nested directories) in the object directory like so

OBJECTS := [obj/main.o obj/a.o obj/b.o]

My problem is, I want a similar pattern rule like my first pattern where I can somehow say

obj/main.o   depends on    src/main.c
obj/a.o      depends on    src/dir1/a.c
...

and not have to write out all the targets and prerequisites explicitly.

Is this type of pattern matching possible in make?

This may be a duplicate, but I had an issue trying to articulate my problem while searching, so apologies in advance.

nick2225
  • 527
  • 5
  • 17
  • 1
    Is it okay if `src/dir1/a.c` -> `obj/dir1/a.o`? That's definitely possible with a substitution. – Neil May 08 '23 at 07:52
  • @Neil It wouldn't be my first pick but I think that could work. Any idea on how to accomplish that? – nick2225 May 08 '23 at 07:55
  • The order only prerequisite $(OBJ_DIR) will be for every single object file you build. 100 object files that 100 `[ -d $dir ] || mkdir $dir`. It's more efficient to have a single .PHONY rule to build your directories once. – Allan Wind May 08 '23 at 08:03
  • 1
    Can you use vpath to find your src? – Allan Wind May 08 '23 at 08:05
  • @AllanWind That might be a potential solution. Though I would need to add all the recursive subdirectories under `src` to the VPATH right? – nick2225 May 08 '23 at 08:08
  • Yes, that is correct. – Allan Wind May 08 '23 at 08:12
  • If you haven't you might want to read this over https://stackoverflow.com/questions/9178285/how-can-makefile-use-separate-directories-for-source-code-and-binaries – Allan Wind May 08 '23 at 08:15
  • Did you think about nested Makefiles? Or using a Makefile Generator like CMake? You might find some interesting information about Makefiles here: https://make.mad-scientist.net/papers/ – Bodo May 08 '23 at 09:41
  • 1
    The rule you already have should do `src/dir1/a.c -> obj/dir1/a.o`, except for creating `obj/dir1/`. And you can put that in the recipe: `mkdir -p $$(dirname $@)`. That would even relieve you of need for the separate rule you have for `$(OBJ_DIR)`. – John Bollinger May 08 '23 at 12:30
  • In *thegnumakebook* by *John Graham-Cumming* `rwildcard=$(foreach d,$(wildcard $1*),$(call rwildcard,$d/,$2) \ $(filter $(subst *,%,$2),$d))`, `c_srcs := $(call rwildcard, $(src), *.c)`, `c_objs := $(patsubst $(src)/%.c, $(build)/%.o, $(c_srcs))`. – Neil May 11 '23 at 19:01

1 Answers1

2

The short answer to your question Is this type of pattern matching possible in make? is "no, that type of pattern matching is not possible".

In make patterns the stem (the part that matches the %) must be byte-for-byte identical in the target and prerequisite.

The only way to do what you want without writing a separate pattern rule for each subdirectory is to use vpath. However you can easily do this as:

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

which will set VPATH to all the directories of all the source files. The sort also does a unique operation.

MadScientist
  • 92,819
  • 9
  • 109
  • 136