-1

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.

ninadepina
1,33713 silver badges20 bronze badges
asked Dec 22, 2025 at 11:42
4
  • 6
    Your target named foobuild should be named $(SOLIBNAME) – the name of the file the rule generates – and it shouldn't be phony. Maybe break this up into three separate targets to build the library itself and the related symlinks. Commented Dec 22, 2025 at 13:39
  • 1
    I can't reproduce your error, which is what I expected from analyzing the makefile presented. I created dummy sources lib/src/abc.cpp and exe/src/main.cpp, each containing exactly one function, the latter's being a main(). I used your makefile unmodified except for changing the value of LIB_LDFLAGS to empty to avoid dealing with whatever your libads is. make successfully built a working bar executable, issuing the usual echo of the commands it was running but no diagnostic messages. Commented Dec 22, 2025 at 15:31
  • The modification of LIB_LDFLAGS is not relevant to your particular diagnostic, which is about dependencies between rules, because LIB_LDFLAGS is used only in recipes, not in the target or prerequisite list of any rule. Commented Dec 22, 2025 at 15:33
  • @DavidMaze After changing to all: $(SOLIBNAME) $(BINNAME) and .PHONY: all clean, the build is successful. In case, I only want to build the shared library I need to issue the command make libfoo.so.0.1 right? Or Is there a more idiomatic way since library version keeps changing. Commented Dec 22, 2025 at 16:14

1 Answer 1

1

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
answered Dec 22, 2025 at 18:22
Sign up to request clarification or add additional context in comments.

1 Comment

This is all good advice, but it does not explain the error described in the question. Which would be hard, given that the error is not reproducible with the makefile presented.

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.