Pete
Pete

Reputation: 23

Struggling with general makefile

I've been recently been turned from the Windows and VisualStudio darkside to Linux and am struggling to get my generic makefile to work. I know it's probably an easy fix, but I've been reading around this and watching youtube videos for hours and can't seem to spot/fix the issue - please help!

I had all my code in the same directory (and it worked fine!), but it was becoming a bit of a handful so moved it to a src directory, with all the object files to go to a build directory. That way, only the makefile and the final executable would sit in the top level. I get an error saying:

    make: *** No ruke to make target 'build/main.o', needed by 'testProg'. Stop.  

My makefile is below. Any help would be much appreciated! Thanks in advance!

    #Program Name:
    PROG = testProg

    CC = g++
    CPPFLAGS = -c -g -Wall
    LINKER = $(CC) -o

    SRC_DIR = ./src
    BUILD_DIR = ./build

    # All source cpp files
    SRCS = $(shell find $(SRC_DIR) -name *.cpp -or -name *.CPP)

    # Substitute the .cpp for a .o for all entries in the $SRCS list.
    OBJS_NAMES = $(subst .cpp,.o,$(SRCS))
    OBJS = $(subst $(SRC_DIR),$(BUILD_DIR),$(OBJS_NAMES))

    all: $(PROG)

    $(PROG): $(OBJS)
        $(CC) $(OBJS) -o $(PROG)

    # Create object files
    %.o: %.cpp
        $(CC) $(CPPFLAGS) $< -o $@

    clean: 
        rm -f $(PROG) $(OBJS)


    #for debugging
    show: 
        @echo 'Source files: ' $(SRCS)
        @echo 'Object files: ' $(OBJS)

When doing make show I get the output:

    Source files: ./src/main.cpp ./src/func1.cpp ...
    Object files: ./build/main.o ./build/func1.o ... 

Upvotes: 0

Views: 425

Answers (1)

MadScientist
MadScientist

Reputation: 101081

This rule:

%.o: %.cpp
        $(CC) $(CPPFLAGS) $< -o $@

tells make how to build a file XXX.o from a file XXX.cpp. The XXX (the part that matches the %) must be identical.

In your new makefile you're trying to build build/foo.o, so that rule will only match if make can find a build/foo.cpp to compile. Since it can't, that rule doesn't match, and make doesn't know how to build your build/foo.o files.

If you want the source file and the target file in different directories you have to write the rule such that the non-identical parts are spelled out, like this:

$(BUILD_DIR)/%.o: $(SRC_DIR)/%.cpp
        $(CC) $(CPPFLAGS) $< -o $@

BTW, I recommend you don't use subst above because that replaces all occurrences even if they appear in the middle of a word which is unlikely but, won't be what you want. I'd use:

OBJS = $(patsubst $(SRC_DIR)/%.c,$(BUILD_DIR)/%.o,$(SRCS))

No need for OBJS_NAMES at all.

Upvotes: 3

Related Questions