Pattern rules behave differently in GNU Make and BSD Make

958 Views Asked by At

I have a single Makefile.
On a FreeBSD machine with both gmake and make installed, I run the same Makefile using both tools.
The output log for make and gmake is not the same. Why is this? And how can I "fix" this?

The logs are below:

$ gmake

compile main.cpp
linking myout

$ make

c++  -O2 -pipe -c main.cpp -o main.o
linking myout

$ cat Makefile

TARGET = myout

default: $(TARGET)

SRCS = main.cpp

OBJS = $(SRCS:%.cpp=%.o)

default: $(BIN)

%.o: %.cpp
    @echo compile $<
    @$(CXX) -c $< -o $@

$(TARGET): $(OBJS)
    @echo linking $@

    @$(CXX) $(OBJS) -o $@

clean:
    @rm -f $(OBJS) $(TARGET)
2

There are 2 best solutions below

3
On

The default build utilities are different. FreeBSD uses a different implementation of make than GNU/Linux. The respective man pages outline differences.

https://forums.freebsd.org/threads/difference-gmake-gnu-and-freebsd-make.28784/

0
On

According to the FreeBSD make documentation, it doesn't support pattern rules. So your rule here:

%.o: %.cpp
        @echo compile $<
        @$(CXX) -c $< -o $@

in FreeBSD make is just an explicit rule telling make how to build the literal file %.o from the literal file %.cpp. Since you don't try to build a file named %.o (you're trying to build main.o), this rule is ignored / never used.

It looks like if you want something that will work the same way between both versions of make you'll have to restrict yourself to the POSIX standard suffix rules format, like this:

.SUFFIXES: .cpp .o
.cpp.o:
        @echo compile $<
        @$(CXX) -c $< -o $@