Make - 如何构建依赖关系,以及如何定义多个目标?
Make - How to build dependencies, and how to define multiple targets?
我是 makefile 的新手,我想执行几个操作。
我目前的makefile如下:
OBJECTS=radio_listener.o radio_app_comm_func.o
TARGET_EXECUTABLE=radio_listener
# Default target
all: ${TARGET_EXECUTABLE}
# Compile all required .o files this way
%.o: %.c
@echo "Compiling $<"
@gcc -c -g -m32 $< -o $@
# Compile target exe by combining all objects
${TARGET_EXECUTABLE}: ${OBJECTS}
@echo "Linking $@"
@gcc ${OBJECTS} -g -m32 -o $@
# Cleanup rule
clean:
@echo "Cleaning up..."
@rm -f *.o ${TARGET_EXECUTABLE}
@echo "Done."
.PHONY: clean all
1. 假设我执行 'make'。然后在 radio_app_comm_types.h.
中更改宏定义
radio_app_comm_types.h 包含在 radio_app_comm_func.h.
中
更改 MACRO 并再次执行 'make' 后,我得到 “Nothing to be done for 'all'.
显然我需要以某种方式告诉我的 Makefile,radio_app_comm_func.h 依赖于 radio_app_comm_types.h。
如何操作?
2. 我感兴趣的第二件事是如何在不同的可执行文件中使用相同的 Makefile。
目前我只有 radio_listener ,但我计划添加 radio_control,radio_server,他们的 h 文件 还将包括 radio_app_comm_func.h,也许还有一些其他 h文件(为了使用它们的相关.c文件。
我怎样才能做到这一点?
我希望实现如下流程:
a) 执行make,将为每个exe编译所有相关文件,最后将为我创建 3 个不同的可执行文件 - radio_listener、radio_control、radio_server
b) 执行make server(例如),将编译所有需要的相关文件only for radio_server(包括寻找变化,比如说,在radio_app_comm_types.h)最后只会为我创建 1 个可执行文件 - radio_server
c) 执行 make controller ...编译 radio_control 所需的所有内容,等等(我猜你明白我的意思)
我正在研究 Ubuntu x64 系统,如果相关的话。
任何帮助将不胜感激。
谢谢。
这里是一个生成依赖项的 makefile。
SHELL = /bin/sh
target1 := <first executable name>
target2 := <second executable name>
target3 := <third executable name>
#
# details for target1
#
SRC1 := <list of files for target1
OBJ1 := $(SRC1:.c=.o)
#
# details for target2
#
SRC2 := <list of files for target2
OBJ2 := $(SRC2:.c=.o)
#
# details for target3
#
SRC3 := <list of files for target3
OBJ3 := $(SRC3:.c=.o)
MAKE := /usr/bin/make
CC := /usr/bin/gcc
CP := cp
MV := mv
LDFLAGS :=
DEBUG := -ggdb3
CCFLAGS := $(DEBUG) -Wall -Wextra -pedantic -std=c99 -Wconversion
#CPPFLAGS += =MD
LIBDIRS := -L/usr/lib -L/usr/local/lib
LIBS := -l<library short name> ...
.PHONY: all
all : $(target1) $(target2) $(target3)
#
# link the .o files into the executable
# using the linker flags
# -- explicit rule
#
$(target1): $(OBJ1)
#
# ======= $@ Link Start =========
$(CC) $(LDFLAGS) -o $@ $(OBJ1) $(LIBDIRS) $(LIBS)
# ======= $@ Link Done ==========
#
$(target2): $(OBJ2)
#
# ======= $@ Link Start =========
$(CC) $(LDFLAGS) -o $@ $(OBJ2) $(LIBDIRS) $(LIBS)
# ======= $@ Link Done ==========
#
$(target3): $(OBJ3)
#
# ======= $@ Link Start =========
$(CC) $(LDFLAGS) -o $@ $(OBJ3) $(LIBDIRS) $(LIBS)
# ======= $@ Link Done ==========
#
#
#create dependancy files -- inference rule
#
%.d: %.c
#
# ========= START $< TO $@ =========
$(CC) -M $(CPPFLAGS) $< > $@.$$$$; \
sed 's,\($*\)\.o[ :]*,.o $@ : ,g' < $@.$$$$ > $@; \
rm -f $@.$$$$
# ========= END $< TO $@ =========
#
# compile the .c files into .o files using the compiler flags
# -- inference rule
#
%.o: %.c %.d
#
# ========= START $< TO $@ =========
$(CC) $(CCFLAGS) -c $< -o $@ -I.
# ========= END $< TO $@ =========
#
.PHONY: clean
clean:
# ========== CLEANING UP ==========
rm -f *.o
rm -f $(target1) $(target2) $(target3)
rm -f *.d
# ========== DONE ==========
# include the contents of all the .d files
# note: the .d files contain:
# <filename>.o:<filename>.c plus all the dependencies for that .c file
# I.E. the #include'd header files
# wrap with ifneg... so will not rebuild *.d files when goal is 'clean'
#
ifneq "$(MAKECMDGOALS)" "clean"
-include $(DEP)
endif
这是一个使用高级 auto-dependency 规则并允许构建多个目标的版本。更新顶部附近的标志并在 TARGETS
中创建新条目并创建新的 xxx_SRC
变量以添加新目标。
如果您想要当前目录中的依赖文件,您可以将 DEPDIR
更改为 .
或者通过 makefile 并删除对它的引用,无论哪种方式。
TARGETS := exe1 exe2 exe3
DEPDIR = .d
exe1_SRC := foo.c bar.c
exe2_SRC := biz.c boz.c
exe3_SRC := bling.c blang.c
CC := gcc
CFLAGS := -g -O2
CPPFLAGS := -DXXX -I../include
LDFLAGS := -L../lib
LDLIBS := -lfoo -lbar
# ----- Nothing below here needs to be changed
.PHONY: all
all : $(TARGETS)
.SECONDEXPANSION:
# For each target, depend on the .o files for its sources
$(TARGETS): $$(patsubst %.c,%.o,$$($$@_SRC))
$(LINK.c) $^ $(LDLIBS) -o $@
ALLSRC := $(foreach T,$(TARGETS),$($T_SRC))
.PHONY: clean
clean:
rm -f $(TARGETS) *.o $(DEPDIR)/*.d
# -----
# Advanced auto-dependency, from:
# http://make.mad-scientist.net/papers/advanced-auto-dependency-generation/
$(shell mkdir -p $(DEPDIR) >/dev/null)
DEPFLAGS = -MT $@ -MMD -MP -MF $(DEPDIR)/$*.Td
COMPILE.c = $(CC) $(DEPFLAGS) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c
POSTCOMPILE = mv -f $(DEPDIR)/$*.Td $(DEPDIR)/$*.d
%.o : %.c
%.o : %.c $(DEPDIR)/%.d
$(COMPILE.c) $(OUTPUT_OPTION) $<
$(POSTCOMPILE)
$(DEPDIR)/%.d: ;
.PRECIOUS: $(DEPDIR)/%.d
-include $(patsubst %,$(DEPDIR)/%.d,$(basename $(ALLSRC)))
我是 makefile 的新手,我想执行几个操作。
我目前的makefile如下:
OBJECTS=radio_listener.o radio_app_comm_func.o
TARGET_EXECUTABLE=radio_listener
# Default target
all: ${TARGET_EXECUTABLE}
# Compile all required .o files this way
%.o: %.c
@echo "Compiling $<"
@gcc -c -g -m32 $< -o $@
# Compile target exe by combining all objects
${TARGET_EXECUTABLE}: ${OBJECTS}
@echo "Linking $@"
@gcc ${OBJECTS} -g -m32 -o $@
# Cleanup rule
clean:
@echo "Cleaning up..."
@rm -f *.o ${TARGET_EXECUTABLE}
@echo "Done."
.PHONY: clean all
1. 假设我执行 'make'。然后在 radio_app_comm_types.h.
中更改宏定义radio_app_comm_types.h 包含在 radio_app_comm_func.h.
中更改 MACRO 并再次执行 'make' 后,我得到 “Nothing to be done for 'all'.
显然我需要以某种方式告诉我的 Makefile,radio_app_comm_func.h 依赖于 radio_app_comm_types.h。
如何操作?
2. 我感兴趣的第二件事是如何在不同的可执行文件中使用相同的 Makefile。
目前我只有 radio_listener ,但我计划添加 radio_control,radio_server,他们的 h 文件 还将包括 radio_app_comm_func.h,也许还有一些其他 h文件(为了使用它们的相关.c文件。
我怎样才能做到这一点? 我希望实现如下流程:
a) 执行make,将为每个exe编译所有相关文件,最后将为我创建 3 个不同的可执行文件 - radio_listener、radio_control、radio_server
b) 执行make server(例如),将编译所有需要的相关文件only for radio_server(包括寻找变化,比如说,在radio_app_comm_types.h)最后只会为我创建 1 个可执行文件 - radio_server
c) 执行 make controller ...编译 radio_control 所需的所有内容,等等(我猜你明白我的意思)
我正在研究 Ubuntu x64 系统,如果相关的话。
任何帮助将不胜感激。
谢谢。
这里是一个生成依赖项的 makefile。
SHELL = /bin/sh
target1 := <first executable name>
target2 := <second executable name>
target3 := <third executable name>
#
# details for target1
#
SRC1 := <list of files for target1
OBJ1 := $(SRC1:.c=.o)
#
# details for target2
#
SRC2 := <list of files for target2
OBJ2 := $(SRC2:.c=.o)
#
# details for target3
#
SRC3 := <list of files for target3
OBJ3 := $(SRC3:.c=.o)
MAKE := /usr/bin/make
CC := /usr/bin/gcc
CP := cp
MV := mv
LDFLAGS :=
DEBUG := -ggdb3
CCFLAGS := $(DEBUG) -Wall -Wextra -pedantic -std=c99 -Wconversion
#CPPFLAGS += =MD
LIBDIRS := -L/usr/lib -L/usr/local/lib
LIBS := -l<library short name> ...
.PHONY: all
all : $(target1) $(target2) $(target3)
#
# link the .o files into the executable
# using the linker flags
# -- explicit rule
#
$(target1): $(OBJ1)
#
# ======= $@ Link Start =========
$(CC) $(LDFLAGS) -o $@ $(OBJ1) $(LIBDIRS) $(LIBS)
# ======= $@ Link Done ==========
#
$(target2): $(OBJ2)
#
# ======= $@ Link Start =========
$(CC) $(LDFLAGS) -o $@ $(OBJ2) $(LIBDIRS) $(LIBS)
# ======= $@ Link Done ==========
#
$(target3): $(OBJ3)
#
# ======= $@ Link Start =========
$(CC) $(LDFLAGS) -o $@ $(OBJ3) $(LIBDIRS) $(LIBS)
# ======= $@ Link Done ==========
#
#
#create dependancy files -- inference rule
#
%.d: %.c
#
# ========= START $< TO $@ =========
$(CC) -M $(CPPFLAGS) $< > $@.$$$$; \
sed 's,\($*\)\.o[ :]*,.o $@ : ,g' < $@.$$$$ > $@; \
rm -f $@.$$$$
# ========= END $< TO $@ =========
#
# compile the .c files into .o files using the compiler flags
# -- inference rule
#
%.o: %.c %.d
#
# ========= START $< TO $@ =========
$(CC) $(CCFLAGS) -c $< -o $@ -I.
# ========= END $< TO $@ =========
#
.PHONY: clean
clean:
# ========== CLEANING UP ==========
rm -f *.o
rm -f $(target1) $(target2) $(target3)
rm -f *.d
# ========== DONE ==========
# include the contents of all the .d files
# note: the .d files contain:
# <filename>.o:<filename>.c plus all the dependencies for that .c file
# I.E. the #include'd header files
# wrap with ifneg... so will not rebuild *.d files when goal is 'clean'
#
ifneq "$(MAKECMDGOALS)" "clean"
-include $(DEP)
endif
这是一个使用高级 auto-dependency 规则并允许构建多个目标的版本。更新顶部附近的标志并在 TARGETS
中创建新条目并创建新的 xxx_SRC
变量以添加新目标。
如果您想要当前目录中的依赖文件,您可以将 DEPDIR
更改为 .
或者通过 makefile 并删除对它的引用,无论哪种方式。
TARGETS := exe1 exe2 exe3
DEPDIR = .d
exe1_SRC := foo.c bar.c
exe2_SRC := biz.c boz.c
exe3_SRC := bling.c blang.c
CC := gcc
CFLAGS := -g -O2
CPPFLAGS := -DXXX -I../include
LDFLAGS := -L../lib
LDLIBS := -lfoo -lbar
# ----- Nothing below here needs to be changed
.PHONY: all
all : $(TARGETS)
.SECONDEXPANSION:
# For each target, depend on the .o files for its sources
$(TARGETS): $$(patsubst %.c,%.o,$$($$@_SRC))
$(LINK.c) $^ $(LDLIBS) -o $@
ALLSRC := $(foreach T,$(TARGETS),$($T_SRC))
.PHONY: clean
clean:
rm -f $(TARGETS) *.o $(DEPDIR)/*.d
# -----
# Advanced auto-dependency, from:
# http://make.mad-scientist.net/papers/advanced-auto-dependency-generation/
$(shell mkdir -p $(DEPDIR) >/dev/null)
DEPFLAGS = -MT $@ -MMD -MP -MF $(DEPDIR)/$*.Td
COMPILE.c = $(CC) $(DEPFLAGS) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c
POSTCOMPILE = mv -f $(DEPDIR)/$*.Td $(DEPDIR)/$*.d
%.o : %.c
%.o : %.c $(DEPDIR)/%.d
$(COMPILE.c) $(OUTPUT_OPTION) $<
$(POSTCOMPILE)
$(DEPDIR)/%.d: ;
.PRECIOUS: $(DEPDIR)/%.d
-include $(patsubst %,$(DEPDIR)/%.d,$(basename $(ALLSRC)))