Makefile: Generate list with subdirectories

3

Let's suppose I have this directory structure:

-src
  |
  |-- subdir1
  |
  |
  |-- subdir2
  |      |
  |      |-- subdir3

I want to generate automatically a variable that finds the name of each subdir.

So something like:

BASE_DIR = src
# magic_recursive_wildcard_here := ...
DIRS = $(call magic_recursive_wildcard_here)

all:
    @echo dirs: $(DIRS)

And I want the output from all to be:

dirs: src subdir1 subdir2 subdir3

Is there any way to do that?

EDIT: If possible, I need a solution that works on both windows and Unix.

EDIT 27/4/2015: I tried Chnossos's answer and the output is this:

[21:59:27] ~\Desktop\makefileproj\src> make -d
GNU Make 3.81
Copyright (C) 2006  Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.

This program built for i386-pc-mingw32
Reading makefiles...
Reading makefile `makefile'...
CreateProcess(NULL,CHDIR,...)
process_begin: CreateProcess(NULL, CHDIR, ...) failed.
CreateProcess(F:\Programs\CmdTools\coreutils\bin\DIR.exe,DIR /A:D /B /S .,...)
DIR: /A\:D: No such file or directory
DIR: /B: No such file or directory
DIR: /S: No such file or directory
Main thread handle = 0x000000e0
.: dira dirb Makefile
Updating makefiles....
 Considering target file `makefile'.
  Looking for an implicit rule for `makefile'.
  Trying pattern rule with stem `makefile'.
  Trying implicit prerequisite `makefile.o'.
  Trying pattern rule with stem `makefile'.
  Trying implicit prerequisite `makefile.c'.
  Trying pattern rule with stem `makefile'.
  Trying implicit prerequisite `makefile.cc'.
  Trying pattern rule with stem `makefile'.
  Trying implicit prerequisite `makefile.cpp'.
  Trying pattern rule with stem `makefile'.
  Trying implicit prerequisite `makefile.p'.
  Trying pattern rule with stem `makefile'.
  Trying implicit prerequisite `makefile.f'.
  Trying pattern rule with stem `makefile'.
  Trying implicit prerequisite `makefile.r'.
  Trying pattern rule with stem `makefile'.
  Trying implicit prerequisite `makefile.s'.
  Trying pattern rule with stem `makefile'.
  Trying implicit prerequisite `makefile.mod'.
  Trying pattern rule with stem `makefile'.
  Trying implicit prerequisite `makefile.sh'.
  Trying pattern rule with stem `makefile'.
  Trying implicit prerequisite `makefile,v'.
  Trying pattern rule with stem `makefile'.
  Trying implicit prerequisite `RCS/makefile,v'.
  Trying pattern rule with stem `makefile'.
  Trying implicit prerequisite `RCS/makefile'.
  Trying pattern rule with stem `makefile'.
  Trying implicit prerequisite `s.makefile'.
  Trying pattern rule with stem `makefile'.
  Trying implicit prerequisite `SCCS/s.makefile'.
  Trying pattern rule with stem `makefile'.
  Trying implicit prerequisite `makefile.o'.
  Looking for a rule with intermediate file `makefile.o'.
   Avoiding implicit rule recursion.
   Trying pattern rule with stem `makefile'.
   Trying implicit prerequisite `makefile.c'.
   Trying pattern rule with stem `makefile'.
   Trying implicit prerequisite `makefile.cc'.
   Trying pattern rule with stem `makefile'.
   Trying implicit prerequisite `makefile.cpp'.
   Trying pattern rule with stem `makefile'.
   Trying implicit prerequisite `makefile.p'.
   Trying pattern rule with stem `makefile'.
   Trying implicit prerequisite `makefile.f'.
   Trying pattern rule with stem `makefile'.
   Trying implicit prerequisite `makefile.r'.
   Trying pattern rule with stem `makefile'.
   Trying implicit prerequisite `makefile.s'.
   Trying pattern rule with stem `makefile'.
   Trying implicit prerequisite `makefile.mod'.
   Trying pattern rule with stem `makefile.o'.
   Trying implicit prerequisite `makefile.o,v'.
   Trying pattern rule with stem `makefile.o'.
   Trying implicit prerequisite `RCS/makefile.o,v'.
   Trying pattern rule with stem `makefile.o'.
   Trying implicit prerequisite `RCS/makefile.o'.
   Trying pattern rule with stem `makefile.o'.
   Trying implicit prerequisite `s.makefile.o'.
   Trying pattern rule with stem `makefile.o'.
   Trying implicit prerequisite `SCCS/s.makefile.o'.
   Trying pattern rule with stem `makefile'.
   Trying implicit prerequisite `makefile.c'.
   Looking for a rule with intermediate file `makefile.c'.
    Avoiding implicit rule recursion.
    Avoiding implicit rule recursion.
    Trying pattern rule with stem `makefile'.
    Trying implicit prerequisite `makefile.y'.
    Trying pattern rule with stem `makefile'.
    Trying implicit prerequisite `makefile.l'.
    Trying pattern rule with stem `makefile'.
    Trying implicit prerequisite `makefile.w'.
    Trying pattern rule with stem `makefile'.
    Trying implicit prerequisite `makefile.w'.
    Trying pattern rule with stem `makefile.c'.
    Trying implicit prerequisite `makefile.c,v'.
    Trying pattern rule with stem `makefile.c'.
    Trying implicit prerequisite `RCS/makefile.c,v'.
    Trying pattern rule with stem `makefile.c'.
    Trying implicit prerequisite `RCS/makefile.c'.
    Trying pattern rule with stem `makefile.c'.
    Trying implicit prerequisite `s.makefile.c'.
    Trying pattern rule with stem `makefile.c'.
    Trying implicit prerequisite `SCCS/s.makefile.c'.
    Trying pattern rule with stem `makefile'.
    Trying implicit prerequisite `makefile.y'.
    Looking for a rule with intermediate file `makefile.y'.
     Avoiding implicit rule recursion.
     Avoiding implicit rule recursion.
     Avoiding implicit rule recursion.
     Trying pattern rule with stem `makefile.y'.
     Trying implicit prerequisite `makefile.y,v'.
     Trying pattern rule with stem `makefile.y'.
     Trying implicit prerequisite `RCS/makefile.y,v'.
     Trying pattern rule with stem `makefile.y'.
     Trying implicit prerequisite `RCS/makefile.y'.
     Trying pattern rule with stem `makefile.y'.
     Trying implicit prerequisite `s.makefile.y'.
     Trying pattern rule with stem `makefile.y'.
     Trying implicit prerequisite `SCCS/s.makefile.y'.
    Trying pattern rule with stem `makefile'.
    Trying implicit prerequisite `makefile.l'.
    Looking for a rule with intermediate file `makefile.l'.
     Avoiding implicit rule recursion.
     Avoiding implicit rule recursion.
     Avoiding implicit rule recursion.
     Trying pattern rule with stem `makefile.l'.
     Trying implicit prerequisite `makefile.l,v'.
     Trying pattern rule with stem `makefile.l'.
     Trying implicit prerequisite `RCS/makefile.l,v'.
     Trying pattern rule with stem `makefile.l'.
     Trying implicit prerequisite `RCS/makefile.l'.
     Trying pattern rule with stem `makefile.l'.
     Trying implicit prerequisite `s.makefile.l'.
     Trying pattern rule with stem `makefile.l'.
     Trying implicit prerequisite `SCCS/s.makefile.l'.
    Trying pattern rule with stem `makefile'.
    Trying implicit prerequisite `makefile.w'.
    Looking for a rule with intermediate file `makefile.w'.
     Avoiding implicit rule recursion.
     Avoiding implicit rule recursion.
     Avoiding implicit rule recursion.
     Trying pattern rule with stem `makefile.w'.
     Trying implicit prerequisite `makefile.w,v'.
     Trying pattern rule with stem `makefile.w'.
     Trying implicit prerequisite `RCS/makefile.w,v'.
     Trying pattern rule with stem `makefile.w'.
     Trying implicit prerequisite `RCS/makefile.w'.
     Trying pattern rule with stem `makefile.w'.
     Trying implicit prerequisite `s.makefile.w'.
     Trying pattern rule with stem `makefile.w'.
     Trying implicit prerequisite `SCCS/s.makefile.w'.
    Trying pattern rule with stem `makefile'.
    Rejecting impossible implicit prerequisite `makefile.w'.
   Trying pattern rule with stem `makefile'.
   Trying implicit prerequisite `makefile.cc'.
   Looking for a rule with intermediate file `makefile.cc'.
    Avoiding implicit rule recursion.
    Avoiding implicit rule recursion.
    Trying pattern rule with stem `makefile.cc'.
    Trying implicit prerequisite `makefile.cc,v'.
    Trying pattern rule with stem `makefile.cc'.
    Trying implicit prerequisite `RCS/makefile.cc,v'.
    Trying pattern rule with stem `makefile.cc'.
    Trying implicit prerequisite `RCS/makefile.cc'.
    Trying pattern rule with stem `makefile.cc'.
    Trying implicit prerequisite `s.makefile.cc'.
    Trying pattern rule with stem `makefile.cc'.
    Trying implicit prerequisite `SCCS/s.makefile.cc'.
   Trying pattern rule with stem `makefile'.
   Trying implicit prerequisite `makefile.cpp'.
   Looking for a rule with intermediate file `makefile.cpp'.
    Avoiding implicit rule recursion.
    Avoiding implicit rule recursion.
    Trying pattern rule with stem `makefile.cpp'.
    Trying implicit prerequisite `makefile.cpp,v'.
    Trying pattern rule with stem `makefile.cpp'.
    Trying implicit prerequisite `RCS/makefile.cpp,v'.
    Trying pattern rule with stem `makefile.cpp'.
    Trying implicit prerequisite `RCS/makefile.cpp'.
    Trying pattern rule with stem `makefile.cpp'.
    Trying implicit prerequisite `s.makefile.cpp'.
    Trying pattern rule with stem `makefile.cpp'.
    Trying implicit prerequisite `SCCS/s.makefile.cpp'.
   Trying pattern rule with stem `makefile'.
   Trying implicit prerequisite `makefile.p'.
   Looking for a rule with intermediate file `makefile.p'.
    Avoiding implicit rule recursion.
    Avoiding implicit rule recursion.
    Trying pattern rule with stem `makefile'.
    Trying implicit prerequisite `makefile.web'.
    Trying pattern rule with stem `makefile.p'.
    Trying implicit prerequisite `makefile.p,v'.
    Trying pattern rule with stem `makefile.p'.
    Trying implicit prerequisite `RCS/makefile.p,v'.
    Trying pattern rule with stem `makefile.p'.
    Trying implicit prerequisite `RCS/makefile.p'.
    Trying pattern rule with stem `makefile.p'.
    Trying implicit prerequisite `s.makefile.p'.
    Trying pattern rule with stem `makefile.p'.
    Trying implicit prerequisite `SCCS/s.makefile.p'.
    Trying pattern rule with stem `makefile'.
    Trying implicit prerequisite `makefile.web'.
    Looking for a rule with intermediate file `makefile.web'.
     Avoiding implicit rule recursion.
     Avoiding implicit rule recursion.
     Avoiding implicit rule recursion.
     Trying pattern rule with stem `makefile.web'.
     Trying implicit prerequisite `makefile.web,v'.
     Trying pattern rule with stem `makefile.web'.
     Trying implicit prerequisite `RCS/makefile.web,v'.
     Trying pattern rule with stem `makefile.web'.
     Trying implicit prerequisite `RCS/makefile.web'.
     Trying pattern rule with stem `makefile.web'.
     Trying implicit prerequisite `s.makefile.web'.
     Trying pattern rule with stem `makefile.web'.
     Trying implicit prerequisite `SCCS/s.makefile.web'.
   Trying pattern rule with stem `makefile'.
   Trying implicit prerequisite `makefile.f'.
   Looking for a rule with intermediate file `makefile.f'.
    Avoiding implicit rule recursion.
    Avoiding implicit rule recursion.
    Trying pattern rule with stem `makefile'.
    Trying implicit prerequisite `makefile.r'.
    Trying pattern rule with stem `makefile.f'.
    Trying implicit prerequisite `makefile.f,v'.
    Trying pattern rule with stem `makefile.f'.
    Trying implicit prerequisite `RCS/makefile.f,v'.
    Trying pattern rule with stem `makefile.f'.
    Trying implicit prerequisite `RCS/makefile.f'.
    Trying pattern rule with stem `makefile.f'.
    Trying implicit prerequisite `s.makefile.f'.
    Trying pattern rule with stem `makefile.f'.
    Trying implicit prerequisite `SCCS/s.makefile.f'.
    Trying pattern rule with stem `makefile'.
    Trying implicit prerequisite `makefile.r'.
    Looking for a rule with intermediate file `makefile.r'.
     Avoiding implicit rule recursion.
     Avoiding implicit rule recursion.
     Avoiding implicit rule recursion.
     Trying pattern rule with stem `makefile'.
     Rejecting impossible implicit prerequisite `makefile.l'.
     Trying pattern rule with stem `makefile.r'.
     Trying implicit prerequisite `makefile.r,v'.
     Trying pattern rule with stem `makefile.r'.
     Trying implicit prerequisite `RCS/makefile.r,v'.
     Trying pattern rule with stem `makefile.r'.
     Trying implicit prerequisite `RCS/makefile.r'.
     Trying pattern rule with stem `makefile.r'.
     Trying implicit prerequisite `s.makefile.r'.
     Trying pattern rule with stem `makefile.r'.
     Trying implicit prerequisite `SCCS/s.makefile.r'.
   Trying pattern rule with stem `makefile'.
   Rejecting impossible implicit prerequisite `makefile.r'.
   Trying pattern rule with stem `makefile'.
   Trying implicit prerequisite `makefile.s'.
   Looking for a rule with intermediate file `makefile.s'.
    Avoiding implicit rule recursion.
    Avoiding implicit rule recursion.
    Trying pattern rule with stem `makefile.s'.
    Trying implicit prerequisite `makefile.s,v'.
    Trying pattern rule with stem `makefile.s'.
    Trying implicit prerequisite `RCS/makefile.s,v'.
    Trying pattern rule with stem `makefile.s'.
    Trying implicit prerequisite `RCS/makefile.s'.
    Trying pattern rule with stem `makefile.s'.
    Trying implicit prerequisite `s.makefile.s'.
    Trying pattern rule with stem `makefile.s'.
    Trying implicit prerequisite `SCCS/s.makefile.s'.
   Trying pattern rule with stem `makefile'.
   Trying implicit prerequisite `makefile.mod'.
   Looking for a rule with intermediate file `makefile.mod'.
    Avoiding implicit rule recursion.
    Avoiding implicit rule recursion.
    Trying pattern rule with stem `makefile.mod'.
    Trying implicit prerequisite `makefile.mod,v'.
    Trying pattern rule with stem `makefile.mod'.
    Trying implicit prerequisite `RCS/makefile.mod,v'.
    Trying pattern rule with stem `makefile.mod'.
    Trying implicit prerequisite `RCS/makefile.mod'.
    Trying pattern rule with stem `makefile.mod'.
    Trying implicit prerequisite `s.makefile.mod'.
    Trying pattern rule with stem `makefile.mod'.
    Trying implicit prerequisite `SCCS/s.makefile.mod'.
  Trying pattern rule with stem `makefile'.
  Rejecting impossible implicit prerequisite `makefile.c'.
  Trying pattern rule with stem `makefile'.
  Rejecting impossible implicit prerequisite `makefile.cc'.
  Trying pattern rule with stem `makefile'.
  Rejecting impossible implicit prerequisite `makefile.cpp'.
  Trying pattern rule with stem `makefile'.
  Rejecting impossible implicit prerequisite `makefile.p'.
  Trying pattern rule with stem `makefile'.
  Rejecting impossible implicit prerequisite `makefile.f'.
  Trying pattern rule with stem `makefile'.
  Rejecting impossible implicit prerequisite `makefile.r'.
  Trying pattern rule with stem `makefile'.
  Rejecting impossible implicit prerequisite `makefile.s'.
  Trying pattern rule with stem `makefile'.
  Rejecting impossible implicit prerequisite `makefile.mod'.
  Trying pattern rule with stem `makefile'.
  Trying implicit prerequisite `makefile.sh'.
  Looking for a rule with intermediate file `makefile.sh'.
   Avoiding implicit rule recursion.
   Trying pattern rule with stem `makefile.sh'.
   Trying implicit prerequisite `makefile.sh,v'.
   Trying pattern rule with stem `makefile.sh'.
   Trying implicit prerequisite `RCS/makefile.sh,v'.
   Trying pattern rule with stem `makefile.sh'.
   Trying implicit prerequisite `RCS/makefile.sh'.
   Trying pattern rule with stem `makefile.sh'.
   Trying implicit prerequisite `s.makefile.sh'.
   Trying pattern rule with stem `makefile.sh'.
   Trying implicit prerequisite `SCCS/s.makefile.sh'.
  No implicit rule found for `makefile'.
  Finished prerequisites of target file `makefile'.
 No need to remake target `makefile'.
Updating goal targets....
Considering target file `all'.
 File `all' does not exist.
 Finished prerequisites of target file `all'.
Must remake target `all'.
Successfully remade target file `all'.
make: Nothing to be done for `all'.
recursion
makefile
asked on Stack Overflow Apr 24, 2015 by TheCrafter • edited Apr 27, 2015 by TheCrafter

3 Answers

1

Considering your edit, you basically have 2 solutions :

  1. Use a linux shell under Windows and use $(shell find $(BASE_DIR) -type d).

  2. Use a condition on the OS you're running on :

    BASE_DIR := .
    
    ifeq ($(OS),Windows_NT)
    DIRS := $(patsubst $(shell CHDIR )\\%,%,$(shell DIR /A:D /B /S $(BASE_DIR)))
    else
    DIRS := $(shell find $(BASE_DIR) -type d)
    endif
    
    $(info $(DIRS)) # print the variable
    
    .PHONY: all
    
    all:
    

Note that the space after CHDIR in $(shell CHDIR ) is mandatory.

answered on Stack Overflow Apr 25, 2015 by Chnossos • edited Apr 27, 2015 by Chnossos
0

John Graham-Cunning wrote this neat recursive wildcard function for make:

rwildcard=$(foreach d,$(wildcard $1*),$(call rwildcard,$d/,$2)
  $(filter $(subst *,%,$2),$d))

But I don't think that can do files vs. directories.

The only other solution I have is to shell out to find for this.

dirs := $(shell find '$(BASE_DIR)' -type d)

As Marc Fraioli points out if you want just the bare directory names in the variable then you want:

dirs := $(notdir $(shell find '$(BASE_DIR)' -type d))

For Windows this might work. I tested the dir command but not how make handles it.

dirs := $(notdir $(shell dir /s /b /ad $(BASE_DIR)))

How you determine which platform you are on to control which you use is a different question but there are a number of ways to do that.

answered on Stack Overflow Apr 24, 2015 by Etan Reisner • edited Apr 24, 2015 by Etan Reisner
0

Yes, try this:

BASE_DIR = src
DIRS = $(shell find $(BASE_DIR) -type d -exec basename {} \;)

all:
    @echo dirs: $(DIRS)

running:

$ ls -lR src
src:
total 8
drwxrwxr-x. 2 mfraioli mfraioli 4096 Apr 24 07:41 subdir1
drwxrwxr-x. 3 mfraioli mfraioli 4096 Apr 24 07:41 subdir2

src/subdir1:
total 0

src/subdir2:
total 4
drwxrwxr-x. 2 mfraioli mfraioli 4096 Apr 24 07:41 subdir3

src/subdir2/subdir3:
total 0
$ make
dirs: src subdir1 subdir2 subdir3
answered on Stack Overflow Apr 24, 2015 by Moldova

User contributions licensed under CC BY-SA 3.0