Q:

Makefile for many subfolders

I have the following folder structure:
├── build
├── external
│   ├── build
│   ├── lib1
│   │   ├── lib1Classes.cc
│   │   └── lib1Classes.h
│   ├── lib2
│   │   ├── lib2Classes.cc
│   │   └── lib2Classes.h
│   ├── lib3
│   │   ├── lib3Classes.cc
│   │   └── lib3Classes.h
│   └── Makefile
├── include
│   ├── SomeClass.h
│   └── SomeOtherClass.h
├── Makefile
└── src
    ├── main.cpp
    ├── SomeClass.cc
    └── SomeOtherClass.cc

I am trying to first compile libXClasses.cc and libXClasses.h into ./external/build/libX.o, then combine all libX.o into an ./external/build/external.so. 
In step 2 I'd like to compile SomeClass.h and SomeClass.cc into ./build/SomeClass.o and SomeOtherClass.h, SomeOtherClass.cc into ./build/SomeOtherClass.o. Finally I want to link ./external/build/external.o and ./build/*.o into a binary in ./build.
I am however already failing in step 1. My idea for ./external/Makefile was something like this:
CXX = g++ -std=c++11

TARGET ?= external.so
BUILD_DIR ?= ./build

# get all source files
SRCS = $(shell find . -name *.cc -or -name *.cpp -or -name *.h)
# get the name of all directories that contain at least one source file
SRC_DIRS ?= $(foreach src,$(SRCS),$(shell dirname $(src)))
# remove duplicate directories
SRC_DIRS := $(shell echo $(SRC_DIRS) | xargs -n1 | sort -u | xargs)
# define one target object file foreach .cc source file
OBJS := $(foreach srcd,$(SRC_DIRS),$(BUILD_DIR)/$(patsubst %.cc,%.o,$(shell find $(srcd) -name *.cc -printf "%f\n")))

# rule to build ./external/build/external.so
$(BUILD_DIR)/$(TARGET): $(OBJS)
    $(CXX) -shared $(OBJS) -o $@

# no idea how to build libX.o in one rule
$(BUILD_DIR)/%.o: %.cc %.h
    $(CXX) -c -fpic $< -o $@

This does not work as in the last rule I am not specifying where the correct .cc and .h come from. But I don't know how I could do that at all. Do I have to write a rule for each libX directory separately? What if I have 10 or 20 libX directories?
Cheers!

A:

Step 1: create a list of the libX directories (because no one wants to maintain a list like that by hand):
LIBS := $(wildcard external/lib*)

Step 2: create a list of the source files:
LIB_SRCS := $(notdir $(wildcard $(addsuffix /*.cc, $(LIBS))))

(I've removed the paths because they're a pain; there's more than one way to do this.)
Step 3: create a list of desired object files:
OBJS := $(patsubst lib%Classes.cc, external/build/lib%.o, $(LIB_SRCS))

Step 4: write a rule to build these files:
vpath %.cc $(LIBS)

$(OBJS): external/build/lib%.o: lib%Classes.cc
    $(CXX) -c -fPIC -I$(dir $<) $< -o $@

(Step 5: write a rule to build the library, but you already have that.)
One could do more. This makefile does not detect the fact that libN.o depends on libNClasses.h. It is possible to set that up, but it's a little complicated, and this is enough for one day.

