I have a project with the following directory structure:
Root directory
bin/ (for final executable)
Mod1/
build/ (for *.o / *.d files)
inc/
src/
Mod2/
build/
inc/
src/
Mod.../ (future module directories)
build/
inc/
src/
makefile
My current makefile contains this:
# Directory naming conventions
SRC_DIR_NAME = src
BUILD_DIR_NAME = build
# Parallel source/object/dependency file lists
SRCS = $(shell find -name *.cpp)
OBJS = $(subst $(SRC_DIR_NAME),$(BUILD_DIR_NAME),$(SRCS:%.cpp=%.o))
# Final executable
APP = bin/app
build: $(APP)
$(APP): $(OBJS)
# link objects and compile app
%.o: %.cpp
# compile sources into objects
My file lists work as expected and produce:
SRCS=./mod1/src/file.cpp ./mod2/src/file.cpp
OBJS=./mod1/build/file.o ./mod2/build/file.o
DEPS=./mod1/build/file.d ./mod2/build/file.d
However when I run make I get the following error:
make: *** No rule to make target `mod1/build/file.o', needed by `/bin/app'. Stop.
My assumption is that:
%.o: %.cpp
Doesn't work with a input like
mod1/build/file.o
Is there a way to make a generic target that takes a module directory and creates targets for that module's object files that require that module's source files in their respective sub-directories?
I know using recursive make can solve this issue but I want to avoid having to use that solution if possible.
There is no way to express such sophisticated target in GNU Make. Although there is a way to generate the set of targets (and corresponding rules). Except an obvious way to use some tool to generate Makefile, we can use eval feature of GNU Make to create rules programmatically. Example code is following.
# Directory naming conventions
SRC_DIR_NAME := src
BUILD_DIR_NAME := build
# source files list
SRCS := $(shell find -name '*.cpp')
# function to get obj file name from src file name
OBJ_FROM_SRC = $(subst /$(SRC_DIR_NAME)/,/$(BUILD_DIR_NAME)/,$(1:%.cpp=%.o))
# Final executable
APP := bin/app
.PHONY: build
.DEFAULT_GOAL := build
# rule template for obj
define obj_rule_by_src =
src := $(1)
obj := $$(call OBJ_FROM_SRC,$$(src))
OBJS := $$(OBJS) $$(obj)
$$(obj): $$(src)
# compile source into object
echo build $$@ from $$<
endef
# generate rules for OBJS
$(foreach src,$(SRCS),$(eval $(call obj_rule_by_src,$(src))))
$(APP): $(OBJS)
# link objects and compile app
echo create $@ from $^
build: $(APP)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.