C Using make to install header.h files.

I am using the FreeBSD make environment to build a local library that I now want to install and make available to other projects. I can build, link and install the library.a but need to install a set of header files from the local build directories as well. Here is what I believe is the closest I got:

Code:
HEADERS =    a.h \
             b.h

INCDIR = /tmp

TARGETS =  ${HEADERS:S/^/$(INCDIR)\//g}

install: $(TARGETS)

$(INCDIR)/%.h: %.h
    echo $(INSTALL) -m 444 ${_INSTALLFLAGS} ${.IMPSRC} $(.TARGET)

It seems $(INCDIR)/%.h: %.h doesn't match correctly. If I change to the following rules it all works but this is not sustainable.
Code:
/tmp/a.h : a.h
    $(INSTALL) -m 444 ${_INSTALLFLAGS} ${.IMPSRC} $(.TARGET)

/tmp/b.h : b.h
    $(INSTALL) -m 444 ${_INSTALLFLAGS} ${.IMPSRC} $(.TARGET)

I can force a copy each time by using the following and even use the options to the install program like -C or -p but its not quite the same as it doesn't check 'out of date' timestamps.

Code:
HEADERS = a.h \
        b.h

INCLDIR = /tmp

install:
.for H in ${HEADERS}
    @$(INSTALL) -v -m 444 ${_INSTALLFLAGS} ${H} $(INCLDIR)/${H}
.endfor


Is there a way of getting make to copy a set of header files from a source to destination.
 
Unless you use a makefile generator like CMake then I think your second method is the way to go.

You can use 'install -C' to avoid copies if the destination exists and the files are the same.
 
I am using the FreeBSD make environment to build a local library that I now want to install and make available to other projects.
If it's really FreeBSD specific, the easiest way is to just use FreeBSD's make framework like e.g. this:
Code:
PREFIX?=        /usr/local

LIB=            foo
LIBDIR=         ${PREFIX}/lib
SHLIB_MAJOR=    1

INCS=           foo.h
INCSDIR=        ${PREFIX}/include

.include <bsd.lib.mk>
Note there's no need to write any rules at all, they're provided by the framework just based on the variables you set.

BTW, pattern matching rules with % is GNU-make specific syntax. BSD make has other features, I recommend to read the manpage: make(1).

Edit: If you want to understand how this framework is implemented, you find it in /usr/share/mk. Unfortunately it isn't very well documented, but you find lots of usage examples in FreeBSD's source tree.

Edit2: In case this is not FreeBSD-specific, my recommendation would be to either use a tool that generates portable makefiles (like GNU autotools, cmake, ...) or require GNU make (devel/gmake) for your hand-written Makefile. The latter not because GNU make is "more powerful" (it's just very different), but because it's available on almost any platform.
 
I can force a copy each time by using the following and even use the options to the install program like -C or -p but its not quite the same as it doesn't check 'out of date' timestamps.
A remark about this: You normally don't WANT that for install targets, it's fragile because you reach out of the area you control, so you don't know about any timestamp tampering and whatnot. Rules for install therefore typically always install everything, I'd strongly recommend to follow this practice.

Nevertheless, you can easily do the "correct" dependencies in BSD make without repeating yourself, e.g. like this:
Code:
INCS=           a.h b.h
INCSDIR=        /tmp

.for h in ${INCS}
install: ${INCSDIR}/${h}

${INCSDIR}/${h}: ${h}
        install -m 444 ${h} ${INCSDIR}
.endfor
 
This is called pattern rule and it's sadly not yet supported by bmake.
Arguably, there's no need for it, as bmake offers powerful and simple loops to compensate for that (while in GNU make, you only have something like "looped evaluation" which is often cumbersome to use).

But, what is sad: Portable make (the common denominator of all make utilities) is so limited, you'll never want to hand-write it.
 
Arguably, there's no need for it
I have some other project I'm working on that uses pattern rules extensively, and I would really love to use bmake as a drop-in replacement for its ancient make, and then convert the build system piece by piece. Other than that, I do agree.
 
I have some other project I'm working on that uses pattern rules extensively, and I would really love to use bmake as a drop-in replacement for its ancient make, and then convert the build system piece by piece. Other than that, I do agree.
And a suffix rule won't suffice as a replacement?

Code:
.c.o:
    $(CC) -c $< ...



Seeing GNU make say suffix rules are "obsolete" instantly loses all credibility and confidence from me. It is like saying int main() is obsolete compared to the "modern" winmain stuff. Instead they should be presented as the original way with pattern rules being the extension. GNU can be a little scummy when it comes to this stuff.

Yes pattern rules do allow for use of relative directories and a lot more flexibility (making the papers relating to "recursive makefiles are bad" actually feasible to implement) but I do notice that suffix rules are at least the lowest common denominator for nmake, wmake, etc. Even though in practice you will want different common Makefile libs for these.
 
Many thanks for all the suggestions.

I think zirias@ hit the nail dead center.

Yes its really FreeBSD specific but I asked the question with a generic tone. We use .include <bsd.lib.mk> from a modified copy of a FreeBSD 9 version of /usr/share/mk (Using FreeBSD 13 OS). I was not aware of the use of INCS/INCSDIR so I will do some tests but this would be my preferred solution if it works. The alternative of putting the install: inside the for loop also fits the bill. As mentioned I am aware of the install -C option but I would really like make to decide if it should install or not.
 
Back
Top