I am currently facing a problem when writing a Makefile for a C project.
In particular, my project should have at least two Makefile targets (target_light
and target_full
), being target_light
the default one.
target_light
should compile all my source files, except few ones which require the installation of an external library on the system (which are saved in src/extra
, for .c files, and include/extra
, for .h files).
target_full
should instead compile all the files, including the ones which need the external library. It should also add some flags to CFLAGS
and LDLIBS
.
I currently have a Makefile similar to the following one:
EXECNAME=MyExecutable
CC=gcc
SRC_DIR=src
OBJ_DIR=obj
SRC_DIR_EXTERNAL_FILES=src/extra
OBJ_DIR_EXTERNAL_FILES=obj/extra
SRC=$(wildcard $(SRC_DIR)/*.c)
OBJ=$(SRC:$(SRC_DIR)/%.c=$(OBJ_DIR)/%.o)
SRC_EXTERNAL_FILES=$(wildcard $(SRC_DIR_EXTERNAL_FILES)/*.c)
OBJ_EXTERNAL_FILES=$(SRC_EXTERNAL_FILES:$(SRC_DIR_EXTERNAL_FILES)/%.c=$(OBJ_DIR_EXTERNAL_FILES)/%.o)
CFLAGS += -Wall -O2 -Iinclude
LDLIBS += -lpthread -lm
.PHONY: all clean
all: target_light
target_light: CC=gcc
target_light_embedded: CC=x86_64-openwrt-linux-musl-gcc
target_light_debug: CFLAGS += -g
target_light_debug: target_light
target_light target_light_debug target_light_embedded: $(EXECNAME)
$(EXECNAME): $(OBJ_CC)
$(CC) $(LDFLAGS) $^ $(LDLIBS) -o $@
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c
$(CC) $(CFLAGS) -c $< -o $@
clean:
$(RM) $(OBJ_DIR)/*.o $(OBJ_DIR_EXTERNAL_FILES)/*.o
$(RM) $(EXECNAME)
-rm -rf $(OBJ_DIR)
I'm currently struggling to find a way to add target_full
to this Makefile, which should also take into account SRC_DIR_EXTERNAL_FILES
OBJ_DIR_EXTERNAL_FILES
SRC_EXTERNAL_FILES
OBJ_EXTERNAL_FILES
, in order to compile the additional files only when requested.
How can I perform this operation? Is there a good way to do so within the Makefile?
My second question is: how can I add, at the same time, flags to both CFLAGS
and LDLIBS
only when target_full
is selected?
I tried writing:
target_full: CFLAGS += -DENABLE_CODE_EXTERNAL_LIB -Iinclude/extra
LDLIBS += -lext_lib
And then changing the $(EXECNAME)
line in:
target_light target_light_debug target_light_embedded target_full: $(EXECNAME)
But the additional LDLIBS
flag seems to be always considered, even when target_light
is selected.
Should I do something like the following lines, repeating two times target_full
?
target_full: CFLAGS += -DENABLE_CODE_EXTERNAL_LIB -Iinclude/extra
target_full: LDLIBS += -lext_lib
Thank you very much in advance.
If target_light
and target_full
share object files, then when you build target_light
it compiles the sources without target_full
CFLAGS
. When you then build target_full
it won't rebuild the existing object files with extra CFLAGS
.
Possible solutions:
target_full
CFLAGS
. This way the object files can be shared between the targets.target_light
and target_full
with different CFLAGS
into different directories. In this case the object files aren't shared between the targets.