Reputation: 741
Suppose I have the following setup
CPPSRC+=path1/foo.cpp
CPPSRC+=path2/main.cpp
CSRC+=path3/zoo.c
CSRC+=path4/bar.c
I want to produce all object files .o
into build/
folder (so I supposingly need both pathsubst and pattern matching).
I also need the .cpp
to be compiled with g++
and related CXXFLAGS
, whereas the .c
need to be compiled with gcc
and simplier CFLAGS
.
I've come this far:
CPPOBJ := $(CPPSRC:%.cpp=%.o)
COBJ := $(CSRC:%.c=%.o)
OBJ := $(COBJ) $(CPPOBJ)
BUILTOBJ := $(addprefix $(BUILD_PATH)/,$(notdir $(OBJ)))
$(APP): $(OBJ)
[...]
$(CPPOBJ): %.o: %.cpp
@echo "[g++" $(BUILD_PATH)$(notdir $@)"]"
$(SILENT)$(GPP) $(CXXFLAGS) $(INCLUDES) -c $< -o $(BUILD_PATH)$(notdir $@)
$(COBJ): %.o: %.c
@echo "[gcc " $(BUILD_PATH)$(notdir $@)"]"
$(SILENT)$(CC) $(CFLAGS) $(INCLUDES) -c $< -o $(BUILD_PATH)$(notdir $@)
but cannot get to reach $(COBJ): %.o: %.c
prerequisite (in short the .c
sources do not get compiled).
How to?
Upvotes: 0
Views: 3073
Reputation: 741
How naive of me.. because I did have the .o files in the original path (not in build/
) and my clean:
only removed the build/
path, the .c
prerequisites where never invoked and .o
where not generated nor placed in the build/
folder.
Indeed my trick tried to fool make by making it produce the .o
file in a position different than what prerequisites defined.
Minor addon: I don't need to land to the makefile with separated C/C++ sources lists; I can achieve separation with the following:
CPPSRC:=$(filter %.cpp,$(SRC))
CSRC:=$(filter %.c,$(SRC))
CPPOBJ:= $(CPPSRC:%.cpp=%.opp)
COBJ:= $(CSRC:%.c=%.o)
OBJ:= $(COBJ) $(CPPOBJ)
BUILTOBJ:= $(addprefix $(BUILD_PATH)/,$(notdir $(OBJ)))
Upvotes: 0
Reputation: 85341
What you're trying to achieve using gmake's pattern rules is impossible because you're losing path information when you strip the source subdirectory from the object file.
So a generic pattern rule like %.o: %.cpp
won't ever know that to compile build/foo.o
it needs to look in path1/foo.cpp
.
Not to mention the increased possibility of a naming conflict.
You can solve it by recreating the subdirectory structure under build/
, i.e. compile path1/foo.cpp
to build/path1/foo.o
, etc.
Once that's sorted, gmake is smart enough to resolve seemingly ambiguous rules, i.e. it will have no problem at all compiling a mix of .c
and .cpp
files, like in the example below:
APP = app
BUILD_PATH = build
CPPOBJ := $(CPPSRC:%.cpp=%.o)
COBJ := $(CSRC:%.c=%.o)
OBJ := $(COBJ) $(CPPOBJ)
BUILTOBJ := $(addprefix $(BUILD_PATH)/,$(OBJ))
$(APP): $(BUILTOBJ)
$(CXX) $(CPPFLAGS) -o $@ $(BUILTOBJ) $(LDLIBS)
$(BUILD_PATH)/%.o: %.cpp
mkdir -p $(@D)
$(CXX) $(CXXFLAGS) $(INCLUDES) -c $< -o $@
$(BUILD_PATH)/%.o: %.c
mkdir -p $(@D)
$(CC) $(CFLAGS) $(INCLUDES) -c $< -o $@
Upvotes: 1