make игнорирует правила сборки
Всем привет. Я решил основательно разобраться в make и для этого сделать «универсальную» систему сборки для С-проектов. И столкнулся с проблемой уже на этапе компиляции исходных кодов в объектные. Make переводит только первый файл указанный в SRCS, а остальные пропускает. Тестовый проект для системы сборки выглядит так:
├── compile.mk
├── config.mk
├── Makefile
└── src
├── main.c
├── Makefile
├── module1
│ ├── module1_bar.c
│ └── module1_foo.c
└── module2
├── module2_bar.c
└── module2_foo.c
Содержимое Makefile-ов следующее:
#Makefile верхнего уровня
include config.mk
MAKEFLAGS+=--no-print-directory
all:
@printf "\x1b[32mStart project compilation\x1b[0m\n"
@$(foreach target,$(TARGETS), \
printf "\x1b[32m%s\x1b[0m compilation\n" "$(target)" && \
$(MAKE) -C $(target) clean && \
$(MAKE) -C $(target); \
)
clean:
$(foreach target,$(TARGETS),$(MAKE) -C $(target) clean;)
#config.mk
export CC=clang
export PROJECT_DIR=$(shell realpath .)
export SRC_DIR=$(PROJECT_DIR)/src
export BUILD_DIR=$(PROJECT_DIR)/build
export INCLUDE_DIR=$(PROJECT_DIR)/include
export LIBS_DIR=$(shell realpath libs)
export LIBS_INCLUDE_DIRS_PATH=$(shell find $(LIBS_DIR) -type d -iname "include")
export TARGETS=$(shell find $(shell realpath .) -type f -iname "Makefile" | xargs dirname | tail -n +2)
export CFLAGS=-I$(INCLUDE_DIR) $(addprefix -I,$(LIBS_INCLUDE_DIRS_PATH))
# $(info CC $(CC))
# $(info SRC_DIR $(SRC_DIR))
# $(info BUILD_DIR $(BUILD_DIR))
# $(info INCLUDE_DIR $(INCLUDE_DIR))
# $(info CFLAGS $(CFLAGS))
#compile.mk
SRC_BASENAMES=$(notdir $(SRCS))
SRC_FULLPATH=$(realpath $(SRCS))
OBJS=$(addprefix $(BUILD_DIR)/,$(addsuffix .o,$(SRC_BASENAMES)))
# $(info SRC_FULLPATH: $(SRC_FULLPATH))
# $(info OBJS: $(OBJS))
define COMPILE_SOURCE_TO_OBJECT
$(1): $(2)
$(info $(2) > $(1))
$(CC) $(CFLAGS) -c $(2) -o $(1)
@echo -e "\x1b[33m$(2)\x1b[0m compiled to \x1b[33m$(1)\x1b[0m"
endef
$(foreach i, $(shell seq 1 $(words $(SRCS))), \
$(eval $(call COMPILE_SOURCE_TO_OBJECT, \
$(strip $(word $(i),$(OBJS))), \
$(strip $(word $(i),$(SRC_FULLPATH))) \
)); \
)
$(BUILD_DIR)/$(TARGET): $(OBJS)
printf "\x1b[32m%s\x1b[0m compiled to \x1b[32m%s\x1b[0m" "$^" "$@"
clean:
rm -rf $(OBJS)
#Makefile в src
TARGET = main
TYPE = application
LIBS = lib1 lib2
SRCS = main.c \
module1/module1_foo.c \
module1/module1_bar.c \
module2/module2_foo.c \
module2/module2_bar.c
include ../compile.mk
all: $(BUILD_DIR)/$(TARGET)
После запуска make из корневой директории проекта получаю следующий вывод:
Start project compilation
/home/ren4/Code/make-build-system/src compilation
/home/ren4/Code/make-build-system/src/main.c > /home/ren4/Code/make-build-system/build/main.c.o
/home/ren4/Code/make-build-system/src/module1/module1_foo.c > /home/ren4/Code/make-build-system/build/module1_foo.c.o
/home/ren4/Code/make-build-system/src/module1/module1_bar.c > /home/ren4/Code/make-build-system/build/module1_bar.c.o
/home/ren4/Code/make-build-system/src/module2/module2_foo.c > /home/ren4/Code/make-build-system/build/module2_foo.c.o
/home/ren4/Code/make-build-system/src/module2/module2_bar.c > /home/ren4/Code/make-build-system/build/module2_bar.c.o
rm -rf /home/ren4/Code/make-build-system/build/main.c.o /home/ren4/Code/make-build-system/build/module1_foo.c.o /home/ren4/Code/make-build-system/build/module1_bar.c.o /home/ren4/Code/make-build-system/build/module2_foo.c.o /home/ren4/Code/make-build-system/build/module2_bar.c.o
/home/ren4/Code/make-build-system/src/main.c > /home/ren4/Code/make-build-system/build/main.c.o
/home/ren4/Code/make-build-system/src/module1/module1_foo.c > /home/ren4/Code/make-build-system/build/module1_foo.c.o
/home/ren4/Code/make-build-system/src/module1/module1_bar.c > /home/ren4/Code/make-build-system/build/module1_bar.c.o
/home/ren4/Code/make-build-system/src/module2/module2_foo.c > /home/ren4/Code/make-build-system/build/module2_foo.c.o
/home/ren4/Code/make-build-system/src/module2/module2_bar.c > /home/ren4/Code/make-build-system/build/module2_bar.c.o
clang -I/home/ren4/Code/make-build-system/include -I/home/ren4/Code/make-build-system/libs/lib1/include -I/home/ren4/Code/make-build-system/libs/lib2/include -c /home/ren4/Code/make-build-system/src/main.c -o /home/ren4/Code/make-build-system/build/main.c.o
/home/ren4/Code/make-build-system/src/main.c compiled to /home/ren4/Code/make-build-system/build/main.c.
UPD: Это не тема для того чтобы размышлять зачем я сделал так, а не иначе и почему я написал такую штуку, а не другую. А почему я не использовал что-то что в 10 раз удобнее. У меня игнорируются правила сборки. Подскажите пожалуйста почему так происходит. Это все что я спрашиваю. Я не спрашиваю какие есть альтернативы, как правильно составлять make-файлы, как мне надо учить make.
UPD2: После того как я перенес содержимое compile.mk в src/Makefile make перестал игнорировать правила сборки. Щас буду разираться почему так. Первое предположение косак в путях или make не может обработать нормально относительные пути
UPD3: Проблема оказалась в том, что include ../compile.mk указан до правила all, а не после… :(