如何仅在选择特定目标时编译某些文件并在 Makefile 中添加标志?
How can I compile certain files and add flags in a Makefile only when a specific target is selected?
我目前在为 C 项目编写 Makefile 时遇到问题。
特别是,我的项目应该至少有两个 Makefile 目标(target_light
和 target_full
),target_light
默认目标。
target_light
应该编译我所有的源文件,除了少数需要在系统上安装外部库的文件(保存在 src/extra
中,对于 .c 文件,include/extra
,对于 .h 文件)。
target_full
应该编译所有文件,包括那些需要外部库的文件。它还应该向 CFLAGS
和 LDLIBS
添加一些标志。
我目前有一个类似于下面的 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
时,如何才能同时向 CFLAGS
和 LDLIBS
添加标志?
我试着写:
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_light
和 target_full
共享目标文件,那么当您构建 target_light
时,它会编译没有 target_full
CFLAGS
的源代码。当您随后构建 target_full
时,它不会用额外的 CFLAGS
.
重建现有的目标文件
可能的解决方案:
- 使用
target_full
CFLAGS
构建所有目标文件。这样目标文件就可以在目标之间共享。
- 将具有不同
CFLAGS
的 target_light
和 target_full
的目标文件构建到不同的目录中。在这种情况下,目标文件不会在目标之间共享。
我目前在为 C 项目编写 Makefile 时遇到问题。
特别是,我的项目应该至少有两个 Makefile 目标(target_light
和 target_full
),target_light
默认目标。
target_light
应该编译我所有的源文件,除了少数需要在系统上安装外部库的文件(保存在 src/extra
中,对于 .c 文件,include/extra
,对于 .h 文件)。
target_full
应该编译所有文件,包括那些需要外部库的文件。它还应该向 CFLAGS
和 LDLIBS
添加一些标志。
我目前有一个类似于下面的 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
时,如何才能同时向 CFLAGS
和 LDLIBS
添加标志?
我试着写:
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_light
和 target_full
共享目标文件,那么当您构建 target_light
时,它会编译没有 target_full
CFLAGS
的源代码。当您随后构建 target_full
时,它不会用额外的 CFLAGS
.
可能的解决方案:
- 使用
target_full
CFLAGS
构建所有目标文件。这样目标文件就可以在目标之间共享。 - 将具有不同
CFLAGS
的target_light
和target_full
的目标文件构建到不同的目录中。在这种情况下,目标文件不会在目标之间共享。