[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: VPATH and prerequisites
From: |
Joost Leeuwesteijn |
Subject: |
Re: VPATH and prerequisites |
Date: |
Sun, 30 Apr 2006 19:29:02 +0200 |
User-agent: |
Thunderbird 1.5.0.2 (Windows/20060308) |
Hi Rares,
I have a problem with VPATH and prerequisites.
Imagine the following structure:
- file1.cpp
- dir1
- file2.cpp
"Makefile" in the root directory looks like this:
VPATH = dir1
file: file1.o file2.o
file1.o: file1.cpp
"Makefile" in the "dir1" directory looks like this:
file2.o: file2.cpp
After I run "make" in "dir1", I will have "file2.o" file in "dir1".
When I run "make" in the root dirctory, "make" creates the "file2.o"
also in the root directory (it recompiles "file2").
This happends because "make" considers the "file2.o" rule from
"dir1/Makefile".
As far as I can tell this makes sense, which is good when it comes to
computers. Unexplainable output is spooky :-)
I can't tell if you're using any includes but if your not then you just
have two separate makefiles. When you run the makefile in dir1 it tries
to make file2.o in the current (dir1) directory as specified in the
makefile. It's also the first rule in this example, which is the
default. That's scenario one/makefile in dir1 explained.
As for scenario two, the root directory makefile also specifies that
file2.o should be made (part of the file rule), in the current directory
since there's no (output) directory given. The VPATH finds the source
file, in dir1. So it also builds file2.o, but in the current directory
(root). I expect that you have some recipe in the root makefile how the
.cpp file should be compiled. Or perhaps a builtin rule, I'm not sure.
I tried to change "file" rule in "Makefile" of the root directory to:
file: file1.o dir1/file2.o
but "make" returns an error:
No rule to make target 'dir1/file2.o', needed by 'file1'
That's because you're running two different make's. The makefile in dir1
just does it's work. The makefile in the root now contains dir1/file2.o.
But -that- makefile doesn't know how to build dir1/file2.o. If you have
a builtin rule or something in the root makefile, that's what caused
file2.o (without the dir1/ prefix) to be built. If you are using an
include (of dir1/makefile), you now have a prerequisite of dir1/file2.o
but the rule only specifies how to build file2.o, in the current
directory, not dir1/file2.o
I hope this make sense? I guess you're including dir1/makefile in the
root makefile? You didn't really mention this.
BTW, the VPATH in the root makefile is used to find the -source- of the
prerequisite! Not the .o file. file requires file2.o, file2.o requires
file2.cpp, it can't find it in the root directory -> use VPATH -> found
it in dir1 -> build it and put output in current directory (root).
I'm still perfecting my own build environment so I'm not sure if this is
the best solution but you could try:
root makefile contains:
----------------------------------------
PROJECT.TARGET := file
PROJECT.ALLMODULES := MODULE1
MODULE1.MAKEFILE := dir1/makefile
# include module(s)
# (not sure about the foreach syntax, check the manual :-)
# I'm not that fluent in make-speak yet)
include $(foreach m,$(ALLMODULES),$$(m.MAKEFILE))
$(PROJECT.TARGET) : file1.o $(MODULE1.TARGET)
file1.o: file1.cpp
----------------------------------------
dir1/makefile contains:
----------------------------------------
MODULE1.ROOTDIR := dir1
MODULE1.TARGET := $(MODULE1.ROOTDIR)/file2.o
$(MODULE1.TARGET) : $(MODULE1.ROOTDIR)/file2.cpp
----------------------------------------
And (always) run make from the root directory. file now requires
dir1/file2.o, the second included (module) makefile knows how to build
it -> done. And look: no VPATH :-) file2.o is now (only!) put in dir1
because dir1 is part of both the prerequisite and the target/rule.
You can check if make is run from the root directory by including a
first/default rule in the dir1 makefile that stops the build. Something
like:
----------------------------------------
.PHONY : dir1_default_rule
dir1_default_rule :
echo "ERROR: only run the toplevel makefile"
<not sure what's the best way to bail out (exit 1?, $$(error ...)>
and/or check on a variable that must be set by the toplevel makefile and
call $(error ...)
----------------------------------------
Hmm, maybe I should include this in my own module makefiles, I just came
up with this :-)
An other solution: keep -your- example (and include dir1/makefile) and
don't run make in the subdirectories :-) The object files just end up in
the root directory. But beware of subdirectories with files that have
the same name. They could overwrite just created .o files.
You can also separate the MODULE1 source dir and output dir, which is
what I did to keep my source directories tidy.
Hope this helps a bit.
Groeten,
Joost