old Makefile for building library no longer works under FreeBSD

105 Views Asked by At

I haven't been doing a lot of C programming lately, but recently I revisited an old project and found the old Makefile to build a library under FreeBSD no longer works. Here's a much simplified version of the Makefile that used to work:

TEST    = Test
LIBTEST = lib$(TEST).a

CC      = cc

.PRECIOUS: $(LIBTEST)

all: $(LIBTEST)

LIBSRC  = test.c

# Do not automatically delete library source files
.SECONDARY: $(LIBSRC)

LIBOBJ  = $(LIBSRC:%.c=%.o)

$(LIBTEST): $(LIBTEST)($(LIBOBJ))
        $(AR) $(ARFLAGS) $@ $?
        rm -f $?

clean:
        @rm -f *.o $(LIBTEST)

And here's a trivial C program to go with it:

/* test.c */
#include <stdio.h>

int
test(char const *text)
{
    printf("%s\n", text);
    return 1;
}

It looks like the Makefile directive dependency:

$(LIBTEST): $(LIBTEST)($(LIBOBJ))

no longer works. It results in:

 ar -crD libTest.a
 rm -f

I've been perusing 'man make' without success.

One thing that puzzles me is that 'man make' says "For a more thorough description of make and makefiles, please refer to PMake - A Tutorial."

Is this accurate? I was under the impression that pmake was replaced by bsdmake in recent versions of FreeBSD - is this the source of my problems?

Note: I am not interested in answers that boil down to "you can do this just fine using GNU make" - this is a question for FreeBSD make.

1

There are 1 best solutions below

3
On
$(LIBTEST): $(LIBTEST)($(LIBOBJ))

suggests that prerequisite of $(LIBTEST) (here libTest.a) is a $(LIBOBJ) (here test.o) member of that archive, which I am not really sure what make would be supposed to conclude from, but for me (FreeBSD 11.0) it comes up with all (which really means libTest.a) is already up to date (see also an example below the ruler). Changing the line to:

$(LIBTEST): $(LIBOBJ)

Would seem to make sense (and unless I've missed something, should be what you want), an object file is prerequisite of the library target and rule updates the library with all prerequisites newer then the target ($?).

Which leads me to one more comment. That rm seems not only unnecessary, but actually harmful, because it means test.o always gets recompiled on invocation of make all and library always gets updated even there is no source (test.c) change as the intermediate prerequisite target is not there (i.e. out of date).


I'd really get that behavior even if I resolve all the stuff around and strip that Makefile to a bare minimum:

$ ls
Makefile        test.c
$ cat Makefile 
libTest.a: libTest.a(test.o)
        $(AR) $(ARFLAGS) $@ $?
$ make
`libTest.a' is up to date.
$ ls
Makefile        test.c