0

I am trying to make some sub directories in a makefile. I know how to do it using a rule for each sub-directory. I am looking for the syntax that will do it using one rule for all subdirectories (either using a loop or using SUBDIRs list).

For example:

$(dst_dir)/%.o : $(M2M_GENERIC_DIR)/rm/src/%.c
    $(TRACE_CC)
    $(Q)$(GCC) -c $(CFLAGS) $< -o $@
    $(Q)$(GCC) -c $(CFLAGS) -MM -MT $@ -MF $(subst .o,.d,$@) $< -o $(subst .o,.d,$@)

$(dst_dir)/%.o : $(M2M_GENERIC_DIR)/utility/src/%.c
    $(TRACE_CC)
    $(Q)$(GCC) -c $(CFLAGS) $< -o $@
    $(Q)$(GCC) -c $(CFLAGS) -MM -MT $@ -MF $(subst .o,.d,$@) $< -o $(subst .o,.d,$@)

$(dst_dir)/%.o : $(M2M_GENERIC_DIR)/fota/src/%.c
    $(TRACE_CC)
    $(Q)$(GCC) -c $(CFLAGS) $< -o $@
    $(Q)$(GCC) -c $(CFLAGS) -MM -MT $@ -MF $(subst .o,.d,$@) $< -o $(subst .o,.d,$@)

$(dst_dir)/%.o : $(M2M_GENERIC_DIR)/fota/src/lzo/%.c
    $(TRACE_CC)
    $(Q)$(GCC) -c $(CFLAGS) $< -o $@
    $(Q)$(GCC) -c $(CFLAGS) -MM -MT $@ -MF $(subst .o,.d,$@) $< -o $(subst .o,.d,$@)
tripleee
  • 175,061
  • 34
  • 275
  • 318
Ran Teshuva
  • 11
  • 1
  • 1
  • 2
    The heavy repetition makes it harder to see what you are trying to accomplish, and is an antipattern in its own right. https://en.wikipedia.org/wiki/Don%27t_repeat_yourself – tripleee Dec 04 '17 at 12:26
  • 1
    Are you simply looking for `mkdir -p "$(dst_dir)"`? – tripleee Dec 04 '17 at 12:27

2 Answers2

1

This should do the job (GNU make):

define DIR_RULE
$$(dst_dir)/%.o : $$(M2M_GENERIC_DIR)/$(1)/%.c
    $$(TRACE_CC)
    $$(Q)$$(GCC) -c $$(CFLAGS) $$< -o $$@
    $$(Q)$$(GCC) -c $$(CFLAGS) -MM -MT $$@ -MF $$(subst .o,.d,$$@) $$< -o $$(subst .o,.d,$$@)
endef
SUBDIRS = rm/src utility/src fota/src fota/src/lzo
$(foreach d,$(SUBDIRS),$(eval $(call DIR_RULE,$(d))))

For a slightly more detailed explanation, see for instance this other question (and answer).

Renaud Pacalet
  • 25,260
  • 3
  • 34
  • 51
0

Ok, I think what you're looking for is this:

#-------------------------------------
define mk_subdir =

$1/%.o : $(M2M_GENERIC_DIR)/rm/src/%.c
    $(TRACE_CC)
    $(Q)$(GCC) -c $(CFLAGS) $< -o $@
    $(Q)$(GCC) -c $(CFLAGS) -MM -MT $@ -MF $(subst .o,.d,$@) $< -o $(subst .o,.d,$@)

$1/%.o : $(M2M_GENERIC_DIR)/utility/src/%.c
    $(TRACE_CC)
    $(Q)$(GCC) -c $(CFLAGS) $< -o $@
    $(Q)$(GCC) -c $(CFLAGS) -MM -MT $@ -MF $(subst .o,.d,$@) $< -o $(subst .o,.d,$@)

$1/%.o : $(M2M_GENERIC_DIR)/fota/src/%.c
    $(TRACE_CC)
    $(Q)$(GCC) -c $(CFLAGS) $< -o $@
    $(Q)$(GCC) -c $(CFLAGS) -MM -MT $@ -MF $(subst .o,.d,$@) $< -o $(subst .o,.d,$@)

$1/%.o : $(M2M_GENERIC_DIR)/fota/src/lzo/%.c
    $(TRACE_CC)
    $(Q)$(GCC) -c $(CFLAGS) $< -o $@
    $(Q)$(GCC) -c $(CFLAGS) -MM -MT $@ -MF $(subst .o,.d,$@) $< -o $(subst .o,.d,$@) 

endef
#-------------------------------------

foreach (dir,$(SUBDIRS),$(eval $(call mk_subdir,$(dir)))

See eval for more details.

Of course defines like these make it hard for others to understand/debug/maintain makefiles, so only use if you really need to... (disclaimer -- I never tested the above code, so there could be a syntax error hiding in there somewhere...)

HardcoreHenry
  • 5,909
  • 2
  • 19
  • 44