help-make
[Top][All Lists]
Advanced

[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





reply via email to

[Prev in Thread] Current Thread [Next in Thread]