Run make in each subdirectory

I have a directory (root_dir), that contains a number of sub-directories (subdir1, subdir2, ...).

I want to run the make in each directory in root_dir, using a Makefile placed in it. (Obviously supposed that each of subdir... has inside its own Makefile).

So there are essentially two questions:

  1. How to get a list of directories in Makefile (automatically)?
  2. How to run make for each of the directories inside a make file?

As I know in order to run make in a specific directory I need to do the following:

$(MAKE) -C subdir

Solution 1:

There are various problems with doing the sub-make inside a for loop in a single recipe. The best way to do multiple subdirectories is like this:

SUBDIRS := $(wildcard */.)

all: $(SUBDIRS)
$(SUBDIRS):
        $(MAKE) -C $@

.PHONY: all $(SUBDIRS)

(Just to point out this is GNU make specific; you didn't mention any restrictions on the version of make you're using).

ETA Here's a version which supports multiple top-level targets.

TOPTARGETS := all clean

SUBDIRS := $(wildcard */.)

$(TOPTARGETS): $(SUBDIRS)
$(SUBDIRS):
        $(MAKE) -C $@ $(MAKECMDGOALS)

.PHONY: $(TOPTARGETS) $(SUBDIRS)

Solution 2:

Try this :

SUBDIRS = foo bar baz

subdirs:
    for dir in $(SUBDIRS); do \
        $(MAKE) -C $$dir; \
    done

This may help you link

Edit : you can also do :

The simplest way is to do:

CODE_DIR = code

.PHONY: project_code

project_code:
       $(MAKE) -C $(CODE_DIR)

The .PHONY rule means that project_code is not a file that needs to be built, and the -C flag indicates a change in directory (equivalent to running cd code before calling make). You can use the same approach for calling other targets in the code Makefile.

For example:

clean:
   $(MAKE) -C $(CODE_DIR) clean

Source

Solution 3:

This is another approach to MadScientist's answer. .PHONY is a GNU-specific feature that can be used to force make into recursing into each subdirectory. However, some non-GNU versions of make do not support .PHONY, so an alternative is a force target.

4.7 Rules without Recipes or Prerequisites

If a rule has no prerequisites or recipe, and the target of the rule is a nonexistent file, then make imagines this target to have been updated whenever its rule is run. This implies that all targets depending on this one will always have their recipe run.

An example will illustrate this:

clean: FORCE
        rm $(objects)
FORCE:

Here the target ‘FORCE’ satisfies the special conditions, so the target clean that depends on it is forced to run its recipe. There is nothing special about the name ‘FORCE’, but that is one name commonly used this way.

As you can see, using ‘FORCE’ this way has the same results as using ‘.PHONY: clean’.

Using ‘.PHONY’ is more explicit and more efficient. However, other versions of make do not support ‘.PHONY’; thus ‘FORCE’ appears in many makefiles. See Phony Targets.

The following is a minimal example that recurses make into each subdirectory, each of which presumably contains a Makefile. If you simply run make, only the first subdirectory, which is non-deterministic, is processed. You may also run make subdir1 subdir2 ....

# Register all subdirectories in the project's root directory.
SUBDIRS := $(wildcard */.)

# Recurse `make` into each subdirectory.
$(SUBDIRS): FORCE
        $(MAKE) -C $@

# A target without prerequisites and a recipe, and there is no file named `FORCE`.
# `make` will always run this and any other target that depends on it.
FORCE:

Here is another example with top-level phony targets: all and clean. Note that the all and clean targets, passed from command-line via $(MAKECMDGOALS), are handled by each subdirectory's all and clean targets respectively.

# Register all subdirectories in the project's root directory.
SUBDIRS := $(wildcard */.)

# Top-level phony targets.
all clean: $(SUBDIRS) FORCE
# Similar to:
# .PHONY: all clean
# all clean: $(SUBDIRS)
# GNU's .PHONY target is more efficient in that it explicitly declares non-files.

# Recurse `make` into each subdirectory
# Pass along targets specified at command-line (if any).
$(SUBDIRS): FORCE
        $(MAKE) -C $@ $(MAKECMDGOALS)

# Force targets.
FORCE:

Solution 4:

You can also define a function in the Makefile (also you of course need an additional makefile in each subdirectory). This is shell-dependent, but can be useful:

define FOREACH
    for DIR in packages/*; do \
        $(MAKE) -C $$DIR $(1); \
    done
endef

.PHONY: build
build:
    $(call FOREACH,build)

.PHONY: clean
clean:
    $(call FOREACH,clean)

.PHONY: test
test:
    $(call FOREACH,test)

Solution 5:

Since I was not aware of the MAKECMDGOALS variable and overlooked that MadScientist has its own implementation of multiple top-level targets, I wrote an alternative implementation. Maybe someone find it useful.

SUBDIRS := $(wildcard */.)

define submake
        for d in $(SUBDIRS);                  \
        do                                    \
                $(MAKE) $(1) --directory=$$d; \
        done
endef

all:
        $(call submake,$@)

install:
        $(call submake,$@)

.PHONY: all install $(SUBDIRS)