Makefile pattern rules

tatteredpotato

Diamond Member
Jul 23, 2006
3,934
0
76
I'm having issues coaxing my makefile into doing what I need. I have a source tree that looks something like:

kern/
| -> .c Files
arch/x86
| -> .c Files
| -> .S Files

Then I have basic pattern rules like:
build/%.o : %.c

The first thing that my makefile does is symlink arch/$(ARCH) to kern/arch, and my platform-specific object-file dependencies are listed like in a variale like "build/arch/somefile.o", and the symlink is created by another make target. This method works file for a single job, however if I try to run with "make -j", then the any files in "build/arch/*" don't get compiled on the first try, and the linker will fail for one of the later targets since it doesn't have all the .o files it needs. My guess is that make is sending a thread off to calculate what the list of .c and .S files are that go to my pattern rules while another thread is creating the symlinks, however the pattern thread is resolving before the symlinks are created.

I was thinking of using a static pattern rule like:
$(KOBJS): build/%.o : %.c
However this doesn't behave correctly because if any .S files will cause problems since it will try to find .c versions of .S files and vice versa.
 

degibson

Golden Member
Mar 21, 2008
1,389
0
0
Try:
Code:
$(SYMLINK):
  -ln -s build/arch arch

build/%o: %.c $(SYMLINK)
  [gcc goes here]

(remember commands in Makefiles start with tabs, but I can't insert tabs in code segments so I used double-space)
 

tatteredpotato

Diamond Member
Jul 23, 2006
3,934
0
76
Try:
Code:
$(SYMLINK):
  -ln -s build/arch arch

build/%o: %.c $(SYMLINK)
  [gcc goes here]

I've tried that before but that doesn't work either. With the above rule, will make not expand the target until the $(SYMLINK) rule has been satisfied?
 

degibson

Golden Member
Mar 21, 2008
1,389
0
0
I've tried that before but that doesn't work either. With the above rule, will make not expand the target until the $(SYMLINK) rule has been satisfied?

The above rule states that, in order to build any build/%.o, you must already have satisfied presence of %.c and $(SYMLINK).

You should define SYMLINK to be the actual link path, i.e.,
Code:
SYMLINK := arch

$(SYMLINK):
  -ln -s build/arch $(SYMLINK)
 

tatteredpotato

Diamond Member
Jul 23, 2006
3,934
0
76
The above rule states that, in order to build any build/%.o, you must already have satisfied presence of %.c and $(SYMLINK).

You should define SYMLINK to be the actual link path, i.e.,
Code:
SYMLINK := arch

$(SYMLINK):
  -ln -s build/arch $(SYMLINK)

II think I've figured out my issue, here is the full makefile for reference: http://codepad.org/7NvQ4bQn

When I invoke make with multiple threads, it eventually tries to find a rule to build my object files. Now I can define that build/%.o:%.c, however the thread that is looking for a rule to match build/someobject.o to someobject.c will be unable to do so because the symlinks are not in place yet (since these operations are in parallel). Likewise, it won't match to the default rule, since I'm doing an out of tree build.

So I guess I have a clearer picture of WHY make is failing to resolve this, essentially what I need is for the symlink rule to be run to completion before any other rule can run (regardless of how many threads make wants to use).

EDIT:
Seems kind of obvious in hindsight:
Code:
%.o: $(SYMLINKS)

build/%.o: %.c
  @$(CC)...etc...
 
Last edited: