Nested Make
Problem
Assume that we have the following directory structure in a project:
/
├── db/
│ └── gen/
│ ├── customer_table.go
│ └── product_table.go
└── Makefile
Where you might have some targets defined in the Makefile
, and you also need to run a specific command that generates some code (in this case the contents of /db/gen/
directory). Also, one limitation you have with the generator command is that is must be executed in the /db/
directory. How to solve this?
Solution
There are some common solutions for this:
Write a script inside
/db/
directory, e.g.,/db/generate.sh
, that executes the command. And, when you’d want to run it, you have to manuallycd
into/db/
, run this script, andcd
back to where you were in the first place (usually project’s root directory). Something similar to:cd ./db bash ./generate.sh cd ..
Add a target to Makefile such that it includes
cd
command before executing the actual generator command.Add a target that executes the generator command in
/db/Makefile
, and a similar target in the rootMakefile
that simply forwards the target command execution to theMakefile
inside/db/
directory.
The last solution, I think, makes intentions clearer, compared to the 1st solution, which at some point might cause confusions about who is going to execute that shell script, the application itself, or developers? What if a developer executes the script directly from project’s root directory? How is the platform support for that shell script format? When compared to the 2nd option, it doesn’t require any explicit cd
instructions, which might become a problem when it comes to cross-platform development support. Of course there are some drawbacks to this solution, but let’s have a demonstration of it.
Content of /Makefile
:
.PHONY: gen
gen:
$(MAKE) -C ./db gen
And, /db/Makefile
:
.PHONY: gen
gen:
somescript that --generates files
This way, all you need to do, is to run make gen
in the root directory, and it will run the gen
target defined in the nested Makefile
.