On Thu, Jul 21, 2011 at 12:53 PM, Patsy <open...@ethernull.org> wrote:
> I'm a little confused by the .PATH.o target in makefiles. For
> the record I'm running on a snapshot from the 29th of June
> (amd64).
>
> I have the following file structure:
>
> ./Makefile
> ./port.c
> ./cheese.c
> ./Makefile
> ./objects/
> ./include/
> ./include/port.h
>
> I have the following makefile:
>
> =========================================
> .SUFFIXES: .o .c .h
> .INCLUDES: .h
>
> .PATH.h: include
> .PATH.o: objects
>
> OBJ_DIR=objects
> CFLAGS=-Iinclude
>
> happiness:      cheese.o \
>                port.o
>        gcc $(CFLAGS) -o happiness \
>                $(OBJ_DIR)/cheese.o \
>                $(OBJ_DIR)/port.o
>
> port.o:         port.c  port.h
>        gcc -c $(CFLAGS) -o $(OBJ_DIR)/port.o port.c
>
> cheese.o:       cheese.c port.h
>        gcc -c $(CFLAGS) -o $(OBJ_DIR)/cheese.o cheese.c
>
> ========================================
>
> If I run make, I get the following output:
>
> gcc -c -Iinclude -o objects/cheese.o cheese.c
> gcc -c -Iinclude -o objects/port.o port.c
> gcc -Iinclude -o happiness  objects/cheese.o  objects/port.o
>
> which is fine, dandy and what I expect. If I run make again
> however, I get the same result. running "make -d m" indicates
> that it isn't finding port.o or cheese.o in the objects
> directory, it is only looking in the current directory.
>
> Prefixing port.o/cheese.o with $(OBJ_DIR) results in their
> targets not being found. Adding $(OBJ_DIR) as a prefix to all
> .o files seem a little verbose.
>
> I thought that specifying .PATH.o in the manner above would
> mean that make would interpret port.o as $(.PATH.o)/port.o
> whether it be a dependency or a target. I have read the man
> page (hence I know that .PATH.o exists) but I can't see why
> what I have shouldn't work.
>
> It seems obvious to me that I'm missing something, but I can't
> see what it is. Could somebody explain it to me, or suggest
> how I could patch the above makefile to make use of .PATH.o?

(Where to start...)

On success, A rule *MUST* create the file named by $@.  Telling make
that you'll create port.o and then creating ${OBJ_DIR}/port.o results
in *exactly* the behavior you describe: every build regenerates the
involved file because make doesn't see the file where it's looking.

In general, 'make' really doesn't like placing objects for suffix
rules in other than the current directory.  The specific exception is
the .OBJDIR logic in BSD make.  Go read the make(1) manpage's
description of the .OBJDIR variable.  You have the choice of using
that logic (and, for example, using the directory named 'obj' instead
of 'objects') or just give up and include full paths in the rules you
write.

If you choose the former, then your Makefile should reduce to
something like this:
-----
.INCLUDES: .h
.PATH.h: ${.CURDIR}/include
CPPFLAGS= ${.INCLUDES}
OBJ = cheese.o port.o
TARGET = ${.CURDIR}/happiness

${TARGET}: ${OBJ}
        ${LINK.c} -o ${TARGET} ${.ALLSRC}

port.o cheese.o: port.h

clean:
        rm -f ${OBJ} ${TARGET}
----

That's assuming you have a hard requirement to place the object file
in the source directory instead of the object directory.  That's
usually the Wrong Thing.  The reasons for moving object files
generally apply to the binaries as well; if you check the OpenBSD
source tree you'll find that output files are *never* placed in the
source directory, for example.  If you drop that perceived
requirement, then simply change the 'TARGET' variable assignment to
'TARGET=happiness'


If you have a hard requirement for naming the subdirectory "objects"
instead of "obj", then you've turned your back on the built-in support
of make for placement of object files, so all their paths will have to
be specified in the makefile, both in targets and prerequisites.  You
can't use suffix rules in that case.  I have written such makefiles in
a large build system using GNU make, which supports the more powerful
[than suffix rules] concept of pattern rules, but I can't generally
recommend it and will not waste my time writing makefiles to do that
in BSD make.


Philip Guenther

Reply via email to