The Makefile below throws the following error when compiled.
Error:
make: *** No rule to make target 'libfoo.so.0.1', needed by 'all'. Stop.
Makefile:
LIBNAME = libfoo
SOLIBNAME = $(LIBNAME).so.0.1
BINNAME = bar
SRC_DIR := exe/src
SRCS := $(shell find $(SRC_DIR) -name '*.cpp')
OBJS := $(SRCS:.cpp=.o)
CXXFLAGS += $(INCLUDES) -std=c++17 -Wall -Wextra -fPIC
LIB_LDFLAGS += \
-L../dir1 \
-lads
all: foobuild barbuild
.PHONY: foobuild barbuild all clean
$(LIBNAME).a: lib/src/abc.o
$(AR) -crs $@ $^
foobuild: lib/src/abc.o
g++ -shared -o $(SOLIBNAME) $^ $(LIB_LDFLAGS)
ln -srf $(SOLIBNAME) $(LIBNAME).so
ln -srf $(SOLIBNAME) $(LIBNAME).so.0
BIN_LDFLAGS += \
-L. \
-lfoo
barbuild: $(OBJS) foobuild
g++ -o $(BINNAME) $(OBJS) $(BIN_LDFLAGS)
clean:
rm -f $(LIBNAME)* $(BINNAME) exe/src/*.o lib/src/*.o
If I replace .PHONY with $(SOLIBNAME) $(BINNAME) all clean, it builds without any error, which I do not understand.
In typical use, the Make target on the left-hand side of a rule should be the name of the file the rule generates. Don't use a .PHONY: target if you're building a file; use the name of the file as the target name. In your setup you're creating three file targets (one shared library and two symlinks) and so this can usefully be three rules.
$(SOLIBNAME): lib/src/abc.o
g++ -shared -o $(SOLIBNAME) $^ $(LIB_LDFLAGS)
$(LIBNAME).so: $(SOLIBNAME)
ln -srf $(SOLIBNAME) $(LIBNAME).so
$(LIBNAME).so.0: $(SOLIBNAME)
ln -srf $(SOLIBNAME) $(LIBNAME).so.0
In a comment you ask about still having a consistent name for the command line, even if the library version changes. Here a .PHONY target makes sense.
.PHONY: foobuild
foobuild: $(LIBNAME).so $(LIBNAME).so.0
Now even if you change the build metadata, you'll have a fixed name you can use at the command line.
LIBNAME := libfoo
LIBFOO_MAJOR := 0
LIBFOO_MINOR := 0
LIBFOO_PATCH := 1
LIBFOO_SO_SHORT := $(LIBNAME).so.$(LIBFOO_MAJOR)
LIBFOO_SO_FULL := $(LIBNAME).so.$(LIBFOO_MAJOR).$(LIBFOO_MINOR).$(LIBFOO_PATCH)
.PHONY: foobuild
foobuild: $(LIBFOO_SO_SHORT) $(LIBFOO_SO_FULL)
make foobuild LIBFOO_MAJOR=1 LIBFOO_MINOR=0 LIBFOO_PATCH=0
# same as
# make libfoo.so.1 libfoo.so.1.0.0 LIBFOO_MAJOR=1 LIBFOO_MINOR=0 LIBFOO_PATCH=0