Reputation: 4508
My source is distributed across multiple directories which are not under the same root. I'm don't want to go into the reasons why this is the case and at the moment I just want to compile it. I've written a Makefile
to compile my code but it is telling me that it can't find a rule to create object (.o
) files. The code for Makefile
is below. What am I doing wrong?
TARGET=main
ROOT_DIR:=.
BUILD_DIR:=$(ROOT_DIR)/build
OBJ_DIR:=$(BUILD_DIR)/obj
TARGET_DIR:=$(BUILD_DIR)/bin
OBJ:= src/main.o \
../src/system.o \
../../LTC2947/src/LTC2947.o \
../../spi/src/my_spi.o
INC_DIR:=src ../src/ ../../LTC2947/src ../../spi/src/
CFLAGS := -O2 -g -Wall -Wextra -Werror -std=gnu99 -DDEBUG -L$(LIB_DIR)
#====================================================
TARGET_BIN:=$(TARGET_DIR)/$(TARGET)
_INC_DIR:=$(foreach _dir,$(INC_DIR), -I$(_dir))
# absolute paths for object files
_OBJ:=$(foreach _path, $(OBJ), $(abspath $(_path)))
# prepend $(OBJ_DIR) to the oejct full paths
_OBJ2:=$(patsubst %,$(OBJ_DIR)/%,$(_OBJ))
# Remove double slashes
_OBJ:=$(shell echo $(_OBJ2) | sed 's,//,/,g')
OBJ_DIRS:=$(dir $(_OBJ))
BUILD_DIRS:= $(OBJ_DIRS) $(TARGET_DIR)
_CFLAGS := $(CFLAGS) $(_INC_DIR)
all: create-build-dirs $(TARGET_BIN)
$(TARGET_BIN): $(_OBJ)
$(CC) -o $@ $^ $(_CFLAGS) $(LIBS)
%.o: %.c
$(CC) $(_CFLAGS) -c $< -o $@
.PHONY: clean
clean:
rm -rf $(BUILD_DIR)
find . -type f \( -name *~ -o -name core \) -exec rm -f {} \;
create-build-dirs:
mkdir -p $(BUILD_DIRS)
EDIT
This is the error that is generated
No rule to make target /home/user/projects/myproject/spi/src/my_spi.o
Upvotes: 0
Views: 931
Reputation: 100836
Please provide the exact error messages you're seeing (cut and paste), not an abstract description.
There are many issues here, but fundamentally this rule:
%.o: %.c
$(CC) $(_CFLAGS) -c $< -o $@
tells make how to build a file PATH.o from a file PATH.c. The values of PATH in both these files must be exactly identical strings. In your environment (if you provided the error message it would be more clear) it appears that you're creating object files in $(OBJ_DIR)
for source files that are not there, so there's no way that the these paths are identical. This means that you are asking make to build a target $(OBJ_DIR)/foo/bar.o
, and make will try to find a file $(OBJ_DIR)/foo/bar.c
and if it can't this rule doesn't match.
A few other notes:
foreach
with abspath
; it takes multiple names. You can just say $(abspath $(OBJ))
.sed
shell command to replace //
with /
; you can just use $(subst //,/,$(_OBJ2))
Upvotes: 1