Swift - Friday Pie
Swift - Friday Pie

Reputation: 14688

Make unable to find rule

Perhaps I missing something, but this make file fails, with error (paraphrasing due to localization is active):

there is no rule to build target ****.o

where **** is the name of existing .cpp file. Make version 3.81, gcc 4.7.5 (if that's relevant).

Here is the makefile.

program_name := librlsmatt.a
source_dirs  :=   ../src    
include_dirs := $(source_dirs)

CXX = g++
AR = ar 

WARNS := -Wall -Wno-deprecated -Wno-unused -Wno-unused-parameter
CFLAGS:= $(addprefix -I, $(include_dirs)) $(WARNS) -fstack-protector-all -g 
ARFLAGS := cru

source_files := $(wildcard $(addsuffix /*.cpp, $(source_dirs) ) )
object_files := $(notdir $(source_files:.cpp=.o) )
dep_files := $(object_files:%.o=%.d)

.PHONY :  clean

-include $(dep_files)

$(program_name): $(object_files)
    $(info Linking ...)
    @$(AR) $(ARFLAGS) $@ $(object_files)

%.o: %.cpp makefile
    $(info Compiling $< ...)
    @$(CXX) -c $(CFLAGS) $< -o $@ -MF $(@:%.o=%.d) -MT $@

clean:
    $(info Clean $(program_name)...)
    @$(RM) -f $(program_name) $(object_files) $(dep_files)

Upvotes: 0

Views: 39

Answers (1)

Kaz
Kaz

Reputation: 58627

Firstly, note that the default target in a Makefile is the first one; therefore if we the dependency files exist, and we include them before the main target, then the .o target in the first included dependency rule will be the default target. As a rule of thumb, include dependencies somewhere farther down, like the very end.

The pattern matching problem in this Makefile is caused by the fact that the .o files do not have a directory prefix, due to the use of $(notdir ...) in the expansion which generates them, but the .cpp files do.

make is trying to build some foo.o and the %.o: %.cpp rule tells it to look for foo.cpp. But there is no foo.cpp; what exists is is some src/dir/foo.cpp.

If you really want the .o files to be in one directory, the VPATH mechanism may be a possibility. If src/dir is in the VPATH, then when make looks for foo.cpp to update foo.o, it will find it in src/dir.

If you force all .o files from the tree into one directory, you have to be sure there are no two .cpp files with the same name.

If you want to deposit .o files outside of the source tree (which is useful, because you can then have a read-only source tree, for instance), it's probably best to mirror the structure of the source tree in the output tree, like this:

$(OUTPUT_DIR)/%.o: %.cpp:   # where the % stem is src/dir/whatever/foo

The idea is that the object file is $(OUTPUT_DIR)/src/whatever/foo.o, and the source file is src/whatever/foo.cpp.

The recipe has to make sure that the directory $(OUTPUT_DIR)/src/whatever exists; so a mkdir -p command will be needed in there somewhere:

$(OUTPUT_DIR)/%.o: %.cpp:
        $(info Compiling $< ...)
        @mkdir -p $(dir $@) 
        @$(CXX) -c $(CFLAGS) $< -o $@ -MF $(@:%.o=%.d) -MT $@

Upvotes: 1

Related Questions