源代码树的 C Makefile
C Makefile for a source tree
在为以下源代码树编写 Makefile 时需要帮助。
我已经尝试了 Makefile 的简单示例,并且效果很好。但无法弄清楚如何为以下类型的源代码树编写 Makefile。
我正在组织我的代码如下
root_dir:
Makefile
component1:
dir1:
file1.c file1.h
dir2:
file2.c file2.h
dir3:
file3.c file3.h
component2:
dir4:
file4.c file4.h
dir5:
file5.c file5.h
common:
debug.c debug.h
utils.c utils.h
main.c main.h
这里,main.c使用了debug.h、utils.h、file1.h和file4.h中声明的一些函数。这些 file1.c 和 file4.c 使用 debug.h 和 utils.h。我已经开始编写如下 Makefile 规则。
CC=gcc
CFlags=-c -g3 -Wall
myexec: main.o
$(CC) main.o -o myexec
main.o: common/main.c common/main.h common/utils.h
$(CC) $(CFLAGS) common/main.c
此 Makefile 为 utils.h 中声明的函数提供 "undefined reference" 错误消息。它可以对 debug.h、file1.h 或 file4.h 中声明的函数进行抄袭,但不应该为 utils.h
中的函数给出错误消息
请帮我找出这里的 Makefile 有什么问题。
这里有一个很长的例子:它是针对 linux 嵌入式系统的,但只需对您的应用程序进行微小的改动就可以工作
这两个 makefile 将在每个子目录中创建一个可执行文件
它有一个类似下面的目录树:
top
utility .h and .c files
makefile.top
makefile.bot
/executable1
exec1 .h and .c files
/executable2
exec2 .h and .c files
makefile.mak
的内容
SHELL = /bin/sh
# note: this makefile.mak needs to be run from the ./src directory
# of the GOT4 directory tree
SRC := $(wildcard *.c)
OBJ := $(SRC:.c=.o)
DEP := $(SRC:.c=.d)
INC := $(SRC:.c=.h)
MAKE := /usr/bin/make
CC := /usr/bin/gcc
CP := cp
MV := mv
LDFLAGS := -L/usr/local/lib -L/usr/lib -L/lib
DEBUG := -ggdb3
CCFLAGS := $(DEBUG) -Wall -Wextra -pedantic
#CPPFLAGS += =MD
LIBS := -lssl -ldl -lrt -lz -lc -lm
.PHONY: AllDirectories
AllDirectories := \
executable1 \
executable2
.PHONY: all
all: $(OBJ) $(AllDirectories)
$(foreach d,$(AllDirectories), \
( cd $d && $(MAKE) -f ../makefile.bot name=Tsk_$d all ); )
#
# create dependancy files
#
%.d: %.c
#
# ========= START $< TO $@ =========
$(CC) -M $(CPPFLAGS) $< > $@.$$$$; \
sed 's,\($*\)\.o[ :]*,.o $@ : ,g' < $@.$$$$ > $@; \
rm -f $@.$$$$
# ========= END $< TO $@ =========
#
# compile the .c file into .o files using the compiler flags
#
%.o: %.c %.d
#
# ========= START $< TO $@ =========
$(CC) $(CCFLAGS) -c $< -o $@ -I.
# ========= END $< TO $@ =========
#
.PHONY: clean
#clean: $(AllDirectories)
# # ========== start clean activities ==========
# rm -f *.o
# rm -f $(name).map
# rm -f $(name)
# rm -f *.d
# $(foreach d,$(AllDirectories), \
# ( cd $d && $(MAKE) -f makefile.mak clean ); )
# # ========== end clean activities ==========
clean: $(AllDirectories)
# ========== start clean activities ==========
rm -f *.o
rm -f $(name).map
rm -f $(name)
rm -f *.d
rm -f ../bin/Tsk_*
$(foreach d,$(AllDirectories), \
( cd $d && $(MAKE) -f ../makefile.bot name=Tsk_$d clean ); )
# ========== end clean activities ==========
.PHONY: install
#install: $(AllDirectories)
# # ========== start install activities ==========
# $(foreach d,$(AllDirectories), \
# ( cd $d && $(MAKE) -f makefile.mak clean ); )
# # ========== end install activities ==========
install: $(AllDirectories)
# ========== start install activities ==========
$(foreach d,$(AllDirectories), \
( cd $d && $(MAKE) -f ../makefile.bot name=Tsk_$d install ); )
# ========== end install activities ==========
# include the contents of all the .d files
# note: the .d files contain:
# <filename>.o:<filename>.c plus all the dependancies for that 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
和makefile.bot
SHELL = /bin/sh
BINDIR := /home/user/bin
.PHONY: all
all : $(BINDIR)/$(name) ../makefile.mak ../makefile.bot
#
# macro of all *.c files
# (NOTE:
# (the following 'wildcard' will pick up ALL .c files
# (like FileHeader.c and FunctionHeader.c
# (which should not be part of the build
# (so be sure no unwanted .c files in directory
# (or change the extension
#
SRC := $(wildcard *.c)
OBJ := $(SRC:.c=.o)
DEP := $(SRC:.c=.d)
INC := $(SRC:.c=.h)
COMMON_OBJ := $(wildcard ../*.o)
#COMMON_SRC := $(wildcard ../*.c)
#COMMON_OBJ := $(COMMON_SRC:.c=.o)
#COMMON_DEP := $(COMMON_SRC:.c=.d)
#COMMON_INC := $(COMMON_SRC:.c=.h)
MAKE := /usr/bin/make
CC := /usr/bin/gcc
CP := cp
MV := mv
LDFLAGS := -L/usr/local/lib
DEBUG := -ggdb3
CCFLAGS := $(DEBUG) -Wall -Wextra -pedantic -std=c99
#CPPFLAGS += =MD
LIBS := -lssl -ldl -lrt -lz -lc -lm
#
# link the .o files into the executable
# using the linker flags
# -- explicit rule
#
$(name): $(OBJ) $(COMMON_OBJ) ../makefile.mak ../makefile.bot
#
# ======= $(name) Link Start =========
$(CC) $(LDFLAGS) -o $@ $(OBJ) $(COMMON_OBJ) $(LIBS)
# ======= $(name) Link Done ==========
#
# note:
# using MV rather than CP results in all executables being re-made everytime
$(BINDIR)/$(name): $(name)
#
# ======= $(name) Copy Start =========
sudo $(CP) $(name) $(BINDIR)/.
# ======= $(name) Copy Done ==========
#
#
#create dependancy files -- inference rule
# list makefile.mak as dependancy so changing makfile forces rebuild
#
%.d: %.c
#
# ========= START $< TO $@ =========
$(CC) -M $(CPPFLAGS) $< > $@.$$$$; \
sed 's,\($*\)\.o[ :]*,.o $@ : ,g' < $@.$$$$ > $@; \
rm -f $@.$$$$
# ========= END $< TO $@ =========
#
# compile the .c file 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 $(name).map
rm -f $(name)
rm -f *.d
# ========== DONE ==========
.PHONY: install
install: all
# include the contents of all the .d files
# note: the .d files contain:
# <filename>.o:<filename>.c plus all the dependancies 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
首先让我们修正main.o
规则:
main.o: common/main.c common/main.h common/utils.h
$(CC) $(CFLAGS) common/main.c
如果,如你所说main.c uses some functions declared in debug.h, utils.h, file1.h and file4.h
,那么那些header应该是规则的先决条件(这样如果你修改一个header,Make将重建main.o
):
main.o: common/main.c common/main.h common/debug.h common/utils.h component1/dir1/file1.h component2/dir4/file4.h
$(CC) $(CFLAGS) common/main.c
现在看myexec
规则:
myexec: main.o
$(CC) main.o -o myexec
出现 "undefined reference" 错误并不奇怪;在debug.h
、utils.h
、file1.h
和file4.h
中声明的函数在定义 (我假设)debug.c
、utils.c
、file1.c
和 file4.c
,这个 makefile 从未提及。 在你理解这一点之前不要继续。
处理此问题的方法是拥有 myexec
规则 link 所有相关的 object 文件:
myexec: main.o debug.o utils.o file1.o file4.o
$(CC) main.o debug.o utils.o file1.o file4.o -o myexec
当然你必须有 debug.o
、utils.o
、file1.o
和 file4.o
的规则,类似于 main.o
.
一旦完成,您就有了一个可以工作但不必要的长和冗余的 makefile。 "Effective but crude"。它可以变得更短更优雅,但这个答案越来越长;让它工作,然后我们可以努力让它更干净。
在为以下源代码树编写 Makefile 时需要帮助。 我已经尝试了 Makefile 的简单示例,并且效果很好。但无法弄清楚如何为以下类型的源代码树编写 Makefile。
我正在组织我的代码如下
root_dir:
Makefile
component1:
dir1:
file1.c file1.h
dir2:
file2.c file2.h
dir3:
file3.c file3.h
component2:
dir4:
file4.c file4.h
dir5:
file5.c file5.h
common:
debug.c debug.h
utils.c utils.h
main.c main.h
这里,main.c使用了debug.h、utils.h、file1.h和file4.h中声明的一些函数。这些 file1.c 和 file4.c 使用 debug.h 和 utils.h。我已经开始编写如下 Makefile 规则。
CC=gcc
CFlags=-c -g3 -Wall
myexec: main.o
$(CC) main.o -o myexec
main.o: common/main.c common/main.h common/utils.h
$(CC) $(CFLAGS) common/main.c
此 Makefile 为 utils.h 中声明的函数提供 "undefined reference" 错误消息。它可以对 debug.h、file1.h 或 file4.h 中声明的函数进行抄袭,但不应该为 utils.h
中的函数给出错误消息请帮我找出这里的 Makefile 有什么问题。
这里有一个很长的例子:它是针对 linux 嵌入式系统的,但只需对您的应用程序进行微小的改动就可以工作
这两个 makefile 将在每个子目录中创建一个可执行文件
它有一个类似下面的目录树:
top
utility .h and .c files
makefile.top
makefile.bot
/executable1
exec1 .h and .c files
/executable2
exec2 .h and .c files
makefile.mak
的内容SHELL = /bin/sh
# note: this makefile.mak needs to be run from the ./src directory
# of the GOT4 directory tree
SRC := $(wildcard *.c)
OBJ := $(SRC:.c=.o)
DEP := $(SRC:.c=.d)
INC := $(SRC:.c=.h)
MAKE := /usr/bin/make
CC := /usr/bin/gcc
CP := cp
MV := mv
LDFLAGS := -L/usr/local/lib -L/usr/lib -L/lib
DEBUG := -ggdb3
CCFLAGS := $(DEBUG) -Wall -Wextra -pedantic
#CPPFLAGS += =MD
LIBS := -lssl -ldl -lrt -lz -lc -lm
.PHONY: AllDirectories
AllDirectories := \
executable1 \
executable2
.PHONY: all
all: $(OBJ) $(AllDirectories)
$(foreach d,$(AllDirectories), \
( cd $d && $(MAKE) -f ../makefile.bot name=Tsk_$d all ); )
#
# create dependancy files
#
%.d: %.c
#
# ========= START $< TO $@ =========
$(CC) -M $(CPPFLAGS) $< > $@.$$$$; \
sed 's,\($*\)\.o[ :]*,.o $@ : ,g' < $@.$$$$ > $@; \
rm -f $@.$$$$
# ========= END $< TO $@ =========
#
# compile the .c file into .o files using the compiler flags
#
%.o: %.c %.d
#
# ========= START $< TO $@ =========
$(CC) $(CCFLAGS) -c $< -o $@ -I.
# ========= END $< TO $@ =========
#
.PHONY: clean
#clean: $(AllDirectories)
# # ========== start clean activities ==========
# rm -f *.o
# rm -f $(name).map
# rm -f $(name)
# rm -f *.d
# $(foreach d,$(AllDirectories), \
# ( cd $d && $(MAKE) -f makefile.mak clean ); )
# # ========== end clean activities ==========
clean: $(AllDirectories)
# ========== start clean activities ==========
rm -f *.o
rm -f $(name).map
rm -f $(name)
rm -f *.d
rm -f ../bin/Tsk_*
$(foreach d,$(AllDirectories), \
( cd $d && $(MAKE) -f ../makefile.bot name=Tsk_$d clean ); )
# ========== end clean activities ==========
.PHONY: install
#install: $(AllDirectories)
# # ========== start install activities ==========
# $(foreach d,$(AllDirectories), \
# ( cd $d && $(MAKE) -f makefile.mak clean ); )
# # ========== end install activities ==========
install: $(AllDirectories)
# ========== start install activities ==========
$(foreach d,$(AllDirectories), \
( cd $d && $(MAKE) -f ../makefile.bot name=Tsk_$d install ); )
# ========== end install activities ==========
# include the contents of all the .d files
# note: the .d files contain:
# <filename>.o:<filename>.c plus all the dependancies for that 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
和makefile.bot
SHELL = /bin/sh
BINDIR := /home/user/bin
.PHONY: all
all : $(BINDIR)/$(name) ../makefile.mak ../makefile.bot
#
# macro of all *.c files
# (NOTE:
# (the following 'wildcard' will pick up ALL .c files
# (like FileHeader.c and FunctionHeader.c
# (which should not be part of the build
# (so be sure no unwanted .c files in directory
# (or change the extension
#
SRC := $(wildcard *.c)
OBJ := $(SRC:.c=.o)
DEP := $(SRC:.c=.d)
INC := $(SRC:.c=.h)
COMMON_OBJ := $(wildcard ../*.o)
#COMMON_SRC := $(wildcard ../*.c)
#COMMON_OBJ := $(COMMON_SRC:.c=.o)
#COMMON_DEP := $(COMMON_SRC:.c=.d)
#COMMON_INC := $(COMMON_SRC:.c=.h)
MAKE := /usr/bin/make
CC := /usr/bin/gcc
CP := cp
MV := mv
LDFLAGS := -L/usr/local/lib
DEBUG := -ggdb3
CCFLAGS := $(DEBUG) -Wall -Wextra -pedantic -std=c99
#CPPFLAGS += =MD
LIBS := -lssl -ldl -lrt -lz -lc -lm
#
# link the .o files into the executable
# using the linker flags
# -- explicit rule
#
$(name): $(OBJ) $(COMMON_OBJ) ../makefile.mak ../makefile.bot
#
# ======= $(name) Link Start =========
$(CC) $(LDFLAGS) -o $@ $(OBJ) $(COMMON_OBJ) $(LIBS)
# ======= $(name) Link Done ==========
#
# note:
# using MV rather than CP results in all executables being re-made everytime
$(BINDIR)/$(name): $(name)
#
# ======= $(name) Copy Start =========
sudo $(CP) $(name) $(BINDIR)/.
# ======= $(name) Copy Done ==========
#
#
#create dependancy files -- inference rule
# list makefile.mak as dependancy so changing makfile forces rebuild
#
%.d: %.c
#
# ========= START $< TO $@ =========
$(CC) -M $(CPPFLAGS) $< > $@.$$$$; \
sed 's,\($*\)\.o[ :]*,.o $@ : ,g' < $@.$$$$ > $@; \
rm -f $@.$$$$
# ========= END $< TO $@ =========
#
# compile the .c file 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 $(name).map
rm -f $(name)
rm -f *.d
# ========== DONE ==========
.PHONY: install
install: all
# include the contents of all the .d files
# note: the .d files contain:
# <filename>.o:<filename>.c plus all the dependancies 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
首先让我们修正main.o
规则:
main.o: common/main.c common/main.h common/utils.h
$(CC) $(CFLAGS) common/main.c
如果,如你所说main.c uses some functions declared in debug.h, utils.h, file1.h and file4.h
,那么那些header应该是规则的先决条件(这样如果你修改一个header,Make将重建main.o
):
main.o: common/main.c common/main.h common/debug.h common/utils.h component1/dir1/file1.h component2/dir4/file4.h
$(CC) $(CFLAGS) common/main.c
现在看myexec
规则:
myexec: main.o
$(CC) main.o -o myexec
出现 "undefined reference" 错误并不奇怪;在debug.h
、utils.h
、file1.h
和file4.h
中声明的函数在定义 (我假设)debug.c
、utils.c
、file1.c
和 file4.c
,这个 makefile 从未提及。 在你理解这一点之前不要继续。
处理此问题的方法是拥有 myexec
规则 link 所有相关的 object 文件:
myexec: main.o debug.o utils.o file1.o file4.o
$(CC) main.o debug.o utils.o file1.o file4.o -o myexec
当然你必须有 debug.o
、utils.o
、file1.o
和 file4.o
的规则,类似于 main.o
.
一旦完成,您就有了一个可以工作但不必要的长和冗余的 makefile。 "Effective but crude"。它可以变得更短更优雅,但这个答案越来越长;让它工作,然后我们可以努力让它更干净。