C源文件的Makefile

时间:2015-09-04 19:54:29

标签: c makefile directory-structure

在为源代码树编写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中声明的函数提供“未定义的引用”错误消息。它可以解决在debug.h,file1.h或file4.h中声明的函数,但是不应该为utils.h中的函数提供错误消息

请帮我找出Makefile的错误。

2 个答案:

答案 0 :(得分:2)

首先让我们修复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,那么那些标题应该是规则的先决条件(这样如果你修改标题,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

你得到“未定义的引用”错误并不奇怪; debug.hutils.hfile1.hfile4.h中声明 的函数已定义(我推测){{ 1}},debug.cutils.cfile1.c,这个makefile从未提及过。 在您理解之前不要继续。

处理此问题的方法是将file4.c规则链接到所有相关目标文件:

myexec

当然,您必须拥有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.outils.ofile1.o的规则,类似于file4.o的规则。

一旦完成,你就有了一个可以工作的makefile,但这个文件是不必要的冗长冗余。 “有效但粗暴”。它可以做得更短更优雅,但这个答案越来越长;只是让它工作,然后我们可以努力使它更清洁。

答案 1 :(得分:0)

这是一个很长的例子:它适用于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[ :]*,\1.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[ :]*,\1.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