1
votes

I have the following Makefile:

CC=gcc
CFLAGS=-Wall -g -Wextra -DNDEBUG $(OPTFLAGS)

VPATH=%.c src
VPATH=%.h src
VPATH=%.o obj
SOURCES=$(wildcard **/*.c *.c)
OBJECTS=$(patsubst %.c,obj/%.o,$(SOURCES))

TEST_SRC=$(wildcard tests/*_tests.c)
TESTS=$(patsubst,%.c,%o,$(TEST_SRC))

TARGET=bin/ex

$(OBJECTS):$(SOURCES)
    $(CC) -c $(CFLAGS) $< -o $@

# The target build
all:$(TARGET)

$(TARGET):CFLAGS+=-fPIC
$(TARGET):build $(OBJECTS)
    $(CC) -c $(CFLAGS) $< -o $@ $(OBJECTS)

What I am trying to achive is to have all *.o files in obj directory and the final executable in the bin directory.

Folder structure as follows:

project/
    src/
    obj/
    bin/

When I run make all I get the following error which I am not able to fix: can't create obj/src/ex.o: No such file or directory

Obviously its targeting the wrong path. any help would be appreciated.

EDIT

Based on first comment I got to my question I have cleaned up the Makefile and came with the following solution that does the job, except that it created the "src" sub-folder into "obj". One of my mistakes was that I was using -c flag when trying to build the exec.

CC=gcc
CFLAGS=-Wall -g -Wextra -DNDEBUG $(OPTFLAGS)
LIBS=-ldl $(OPTLIBS)
#PREFIX?=/usr/local

SOURCESDIR=src
OBJECTSDIR=obj
SOURCES=$(wildcard **/*.c *.c)
OBJECTS=$(patsubst %.c,obj/%.o,$(SOURCES))

TEST_SRC=$(wildcard tests/*_tests.c)
TESTS=$(patsubst,%.c,%o,$(TEST_SRC))

TARGET=bin/ex

$(OBJECTS):$(SOURCES)
    @$(call make-repo)
    $(CC) -c $(CFLAGS) $< -o $@

# The target build
all:$(TARGET) tests

dev:CFLAGS=-Wall -g -Isrc -Wextra $(OPTFLAGS)
dev:all


$(TARGET):CFLAGS+=-fPIC
$(TARGET):build $(OBJECTS)
    $(CC) $(OBJECTS) $(LDFLAGS) -o $@

build:
    @mkdir -p bin

define make-repo
   for dir in $(SOURCESDIR); \
   do \
    mkdir -p $(OBJECTSDIR)/$$dir; \
   done
endef
1
I'm afraid your makefile is broken by problems much more major than the one you are asking about and quite unrelated to it. I suggest you set aside that problem until you are able write a makefile that successfully builds the object files and executable in one directory, and when you have it come back with your question.Mike Kinghan

1 Answers

0
votes

You aren't handing the path substitution correctly, there's a shorthand for it anyway. Also your link rule is broken as it doesn't link (-c), but there's a builtin recipe for that you can just copy

CPPFLAGS := -DNDEBUG
CFLAGS   := -Wall -g -Wextra $(OPTFLAGS)

sources := $(wildcard src/*.c)
objects := $(sources:src/%.c=obj/%.o)

.PHONY: all
all: bin/ex
bin/ex: CFLAGS += -fPIC
bin/ex: $(objects)
    $(LINK.o) $^ $(LDLIBS) -o $@
$(objects): obj/%.o: src/%.c
    $(COMPILE.c) $(OUTPUT_OPTION) $<