I have following simple Makefile that almost does what I want.
This compiles .c
files from directories listed in SRC_DIRS
into a single executable.
The source files are in ./src
and ../pmlin/master
and the intermediate files are supposed to be in directory ./build
The problem is that this compiles files from ./src
to ./build
correctly,
but files from ./pmlin/master
end up in ./pmlin/master
and not ./build/pmlin/master
.
I've tried various things like removing the ../
from the paths in OBJS
with pathsubst
but at the end of the day after hours of googling and experimenting I've not been able to make this work.
TARGET_EXEC = aslac-calibrator
BUILD_DIR = ./build
SRC_DIRS = ./src ../pmlin/src/master
SRCS := $(foreach dir, $(SRC_DIRS), $(wildcard $(dir)/*.c))
OBJS := $(SRCS:%=$(BUILD_DIR)/%.o)
DEPS := $(OBJS:.o=.d)
INC_DIRS := $(shell find $(SRC_DIRS) -type d) ../pmlin/src ../pmlin/src/devices
INC_FLAGS := $(addprefix -I,$(INC_DIRS))
CPPFLAGS ?= $(INC_FLAGS) -MMD -MP
$(TARGET_EXEC): $(OBJS)
$(CC) $(OBJS) -o $@ $(LDFLAGS)
$(BUILD_DIR)/%.c.o: %.c
$(MKDIR_P) $(dir $@)
$(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $@
.PHONY: clean
clean:
$(RM) -r $(BUILD_DIR)
-include $(DEPS)
MKDIR_P ?= mkdir -p
I actually ended up with this solution where I turn the relative path to the other source trees into absolute paths with $(abspath). In this way everything is compiled into the build directory and there no chance of a name conflict.
TARGET_EXEC = pmlin-demo
BUILD_DIR = ./build
PMLIN_DIR = $(abspath ../pmlin)
SRC_DIRS = ./src $(PMLIN_DIR)/src/master $(PMLIN_DIR)/src/slave
SRCS := $(foreach dir, $(SRC_DIRS), $(wildcard $(dir)/*.c))
OBJS := $(SRCS:%=$(BUILD_DIR)/%.o)
DEPS := $(OBJS:.o=.d)
INC_DIRS := $(shell find $(SRC_DIRS) -type d) ../pmlin/src ../pmlin/src/devices
INC_FLAGS := $(addprefix -I,$(INC_DIRS))
CFLAGS += -target macos-x86_64
CPPFLAGS ?= $(INC_FLAGS) -MMD -MP
LDFLAGS += -target macos-x86_64
$(TARGET_EXEC): $(OBJS)
$(CC) $(OBJS) -o $@ $(LDFLAGS)
$(BUILD_DIR)/%.c.o: %.c
$(MKDIR_P) $(dir $@)
$(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $@
.PHONY: clean
clean:
$(RM) -r $(BUILD_DIR)
-include $(DEPS)
MKDIR_P ?= mkdir -p
all: pmlin-demo