cmakefilecompilationcflagsldflags

How can I compile certain files and add flags in a Makefile only when a specific target is selected?


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.


Solution

  • 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:

    1. Build all object files with target_full CFLAGS. This way the object files can be shared between the targets.
    2. Build object files for target_light and target_full with different CFLAGS into different directories. In this case the object files aren't shared between the targets.