如何仅在选择特定目标时编译某些文件并在 Makefile 中添加标志?

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

我目前在为 C 项目编写 Makefile 时遇到问题。

特别是,我的项目应该至少有两个 Makefile 目标(target_lighttarget_full),target_light 默认目标。

target_light 应该编译我所有的源文件,除了少数需要在系统上安装外部库的文件(保存在 src/extra 中,对于 .c 文件,include/extra,对于 .h 文件)。 target_full 应该编译所有文件,包括那些需要外部库的文件。它还应该向 CFLAGSLDLIBS 添加一些标志。

我目前有一个类似于下面的 Makefile:

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)

我目前正在努力寻找一种方法将 target_full 添加到此 Makefile 中,这也应该考虑到 SRC_DIR_EXTERNAL_FILES OBJ_DIR_EXTERNAL_FILES SRC_EXTERNAL_FILES OBJ_EXTERNAL_FILES,以便仅在请求时编译附加文件。

如何执行此操作?在 Makefile 中有这样做的好方法吗?

我的第二个问题是:只有在选择 target_full 时,如何才能同时向 CFLAGSLDLIBS 添加标志? 我试着写:

target_full: CFLAGS += -DENABLE_CODE_EXTERNAL_LIB -Iinclude/extra
    LDLIBS += -lext_lib

然后更改 $(EXECNAME) 行:

target_light target_light_debug target_light_embedded target_full: $(EXECNAME)

但是附加的 LDLIBS 标志似乎总是被考虑,即使选择了 target_light

我应该做类似下面几行的事情,重复两次吗target_full

target_full: CFLAGS += -DENABLE_CODE_EXTERNAL_LIB -Iinclude/extra
target_full: LDLIBS += -lext_lib

非常感谢您。

如果 target_lighttarget_full 共享目标文件,那么当您构建 target_light 时,它会编译没有 target_full CFLAGS 的源代码。当您随后构建 target_full 时,它不会用额外的 CFLAGS.

重建现有的目标文件

可能的解决方案:

  1. 使用 target_full CFLAGS 构建所有目标文件。这样目标文件就可以在目标之间共享。
  2. 将具有不同 CFLAGStarget_lighttarget_full 的目标文件构建到不同的目录中。在这种情况下,目标文件不会在目标之间共享。