I have a project that I would like to convert from recursive to non recursive make. The structure looks like the following
+--app
| +-- Makefile
+--lib1
| +-- Makefile
| +-- x.c
| +-- y.c
|
+--lib2
| +-- Makefile
| +-- x.c
What I am trying to do is after a build is have a structure like this
+--app
| +-- build/
| | +-- debug(or release or test)/
| | | +-- lib1/
| | | | +-- *.o
| | | | +-- *.d
| | | +-- lib2/
| | | | +-- *.o
| | | | +-- *.d
| |
| +-- target/
| | +-- main.bin
| |
| +-- Makefile
|
+--lib1
| +-- module.mk
| +-- x.c
| +-- y.c
|
+--lib2
| +-- module.mk
| +-- x.c
The main idea is that the build folder contains all object and dependency files and and target has the program file that should be loaded.
The issue that I am having is that make will never want to create this structure. When I define my rules make will only run implicit rules and not my defined rules.
I have read every resource on non-recursive make and right now it just has not clicked yet. Any help is much appreciated.
For build results to have the same directory structure like that of the sources, the pattern rules must be in the form of:
${obj_dir}/%.o : ${src_dir}/%.c
Where %
part includes all the subdirectories. The object file must also depend on its directory for make
to build the directory first:
.SECONDEXPANSION:
${obj_dir}/%.o : ${src_dir}/%.c | $$(dir $$@)
${obj_dir}/% : mkdir -p $@
Depending on the target, one source file can be compiled with/without multi-threading, as position-independent/non-position-independent code, etc.. One way to cope with that is to have separate top-level object file directories (in addition to debug/release top-level directory), e.g.:
${obj_dir}/obj
${obj_dir}/obj-pic
${obj_dir}/obj-mt
${obj_dir}/obj-mt-pic
Once you have these rules working correctly and try a parallel build you will notice that mkdir -p
fails when two of them race to create /a/b/a
and /a/b/b
. The fix is:
${obj_dir}/% : while ! mkdir -p $@; do echo -n ""; done