简单工程Makefile的编写

转载 2015年11月20日 15:54:17
工程Makefile的编写,对于初始Makefile的菜鸟们来说,还是比较头疼的一件事情,如何做到整个工程结构清晰,各个模块相对独立,模块的添加 删除等都比较方便,各个层次的的Makefile风格一致,便于移植,这些并不容易。这里,就自己学习的一些体会,和大家分享一下。

    本例工程,实现几种排序算法的具体代码实现和性能比较。工程结构如下:
sort
|-- Makefile
|-- Makefile.rule
|-- main
|   |-- Makefile
|   |-- include
|   |   |-- heap_sort.h
|   |   |-- quick_sort.h
|   |   `-- shell_sort.h
|   |-- libs
|   `-- src
|       `-- sort.c
|-- heap_sort
|   |-- Makefile
|   |-- include
|   `-- src
|       `-- heap_sort.c
|-- quick_sort
|   |-- Makefile
|   |-- include
|   `-- src
|       `-- quick_sort.c
`-- shell_sort
    |-- Makefile
    |-- include
    `-- src
        `-- shell_sort.c
    工程名:sort,根目录下的一级子目录包括main,heap_sort,quick_sort,shell_sort,每级目录中,有include 和 src目录,include中,包含该模块用到的相关头文件,src中是源代码。在main目录中,另有libs文件夹,工程需要引入的库可以放在该文件 夹中。

Makefile.rule
    该文件为工程Makefile的通用规则定义,在各个模块的Makefile中被include。

    该文件具体内容如下:

CC := gcc

AR := ar
ARFLAGS := -rcs
SRC := src
INCLUDES := include
LIBS := libs
CFLAGS := -g -Wall -O3  $(addprefix -I,$(INCLUDES)) /
    $(addprefix -L,$(LIBS))
CXXFLAGS := $(CFLAGS)
CPPFLAGS += -MD
RM_F := rm -rf


HIDE_PREFIX := .
EXPORT_ODIR := $(HIDE_PREFIX)o
IMPORT_IDIR := $(HIDE_PREFIX)i

SOURCE := $(wildcard $(SRC)/*.c) $(wildcard $(SRC)/*.cc)
OBJS := $(patsubst %.c,%.o,$(patsubst %.cc,%.o,$(SOURCE)))
DEPS := $(patsubst %.o,%.d,$(OBJS))
MISSING_DEPS := $(filter-out $(wildcard $(DEPS)),$(DEPS))
MISSING_DEPS_SOURCES := $(wildcard $(patsubst %.d,%.c,$(MISSING_DEPS)) /
    $(patsubst %.d,%.cc,$(MISSING_DEPS)))



    该文件主要定义了工程的编译工具,编译链接的参数等。 EXPORT_ODIR和IMPORT_IDIR是编译之后模块的输入输出,编译生成.i和.o文件夹,.i中为模块需要引入的文件的软链接,.o中是该模块输出的文件的软链接。

工程总Makefile

    根目录下的Makefile,内容如下:


TOPDIR := .
MODDIR := .
TARGET := $(notdir $(shell cd $(MODDIR) && pwd))
MODULES += quick_sort /
           heap_sort /
           shell_sort /
           main

-include $(TOPDIR)/Makefile.rule

submodule_make = $(MAKE) -C $(TOPDIR)/$(1);
submodule_clean = $(MAKE) clean -C $(TOPDIR)/$(1);

.PHONY : all deps objs clean cleanall rebuild modules cleanmodules

all : $(TARGET)

deps : $(DEPS)

objs : $(OBJS)

modules :
    @ $(foreach n,$(MODULES),$(call submodule_make,$(n)))

cleanmodules :
    @ $(foreach n,$(MODULES),$(call submodule_clean,$(n)))

clean :
    @ $(RM_F) *.o
    @ $(RM_F) *.d
    @ $(RM_F) *.a
    @ $(RM_F) $(wildcard $(SRC)/*.o)
    @ $(RM_F) $(wildcard $(SRC)/*.d)
    @ $(RM_F) $(wildcard $(MODIR)/*.d)
    @ $(RM_F) $(EXPORT_ODIR)
    @ $(RM_F) $(IMPORT_IDIR)
    @ echo CLEAN DONE

cleanall: cleanmodules clean
    @ $(RM_F) $(wildcard $(TOPDIR)/*.d)
    @ $(RM_F) $(TARGET)
    @ echo CLEANALL DONE

rebuild: clean all

ifneq ($(MISSING_DEPS),)
$(MISSING_DEPS) :
    @ $(RM_F) $(patsubst %.d,%.o,$@)
endif

-include $(DEPS)

$(TARGET) : $(OBJS) modules
    @ echo MAKE $(TARGET) START
    @ mkdir -p $(EXPORT_ODIR)
    @ mkdir -p $(IMPORT_IDIR)
    @ echo MAKE $(TARGET) DONE


    在这个Makefile中,变量MODULES 定义了各个子模块,quick_sort,heap_sort,shell_sort,  main。

main模块中Makefile

    main模块下的Makefile,内容如下:


TOPDIR := ..
MODDIR := .
MODNAME := $(notdir $(shell cd $(MODDIR) && pwd))
TARGET := $(notdir $(shell cd $(TOPDIR) && pwd))
ALIBS = $(addprefix ../, $(wildcard $(TOPDIR)/$(IMPORT_IDIR)/*.a))
LDFLAGS += $(addprefix -L,$(IMPORT_IDIR))
LDFLAGS += $(foreach n,$(MODULES),$(addprefix -l,$(n)))

MODULES += quick_sort /
           heap_sort  /
           shell_sort

-include $(TOPDIR)/Makefile.rule

submodule_make = $(MAKE) -C $(TOPDIR)/$(1);
submodule_clean = $(MAKE) clean -C $(TOPDIR)/$(1);

.PHONY : all deps objs clean cleanall rebuild modules cleanmodules

all : $(TARGET)

deps : $(DEPS)

objs : $(OBJS)

modules :
    @ $(foreach n,$(MODULES),$(call submodule_make,$(n)))

cleanmodules :
    @ $(foreach n,$(MODULES),$(call submodule_clean,$(n)))

clean :
    @ $(RM_F) *.o
    @ $(RM_F) *.d
    @ $(RM_F) $(wildcard $(SRC)/*.o)
    @ $(RM_F) $(wildcard $(SRC)/*.d)
    @ $(RM_F) $(EXPORT_ODIR)
    @ $(RM_F) $(IMPORT_IDIR)
    @ echo CLEAN DONE

cleanall: cleanmodules clean
    @ $(RM_F) $(TARGET)
    @ echo CLEANALL DONE

rebuild: clean all

ifneq ($(MISSING_DEPS),)
$(MISSING_DEPS) :
    @ $(RM_F) $(patsubst %.d,%.o,$@)
endif

-include $(DEPS)

$(TARGET) : $(OBJS) modules
    @ echo MAKE $(TARGET) START
    @ mkdir -p $(EXPORT_ODIR)
    @ mkdir -p $(IMPORT_IDIR)
    @ ln -sft $(IMPORT_IDIR) $(ALIBS)
    $(CC) $(CFLAGS) -o $(TARGET) $(OBJS) $(LDFLAGS)
    @ cp -f $@ $(TOPDIR) 
    @ echo MAKE $(TARGET) DONE


    在此模块中,变量MODULES定义了其依赖的子模块。首先编译子模块,然后编译本模块。

其他模块中Makefile

    其他模块下的Makefile,内容如下:


TOPDIR := ..
MODDIR := .
MODNAME := $(notdir $(shell cd $(MODDIR) && pwd))
TARGET := $(addprefix lib,$(addsuffix .a,$(MODNAME)))
EXPORT_HEADERS += $(INCLUDES)/*.h
MODULES +=

-include $(TOPDIR)/Makefile.rule

submodule_make = $(MAKE) -C $(TOPDIR)/$(1);
submodule_clean = $(MAKE) clean -C $(TOPDIR)/$(1);

.PHONY : all deps objs clean cleanall rebuild

all : $(TARGET)

deps : $(DEPS)

objs : $(OBJS)

modules :
    @ $(foreach n,$(MODULES),$(call submodule_make,$(n)))

cleanmodules :
    @ $(foreach n,$(MODULES),$(call submodule_clean,$(n)))

clean :
    @ $(RM_F) *.o
    @ $(RM_F) *.d
    @ $(RM_F) $(wildcard $(SRC)/*.o)
    @ $(RM_F) $(wildcard $(SRC)/*.d)
    @ $(RM_F) $(EXPORT_ODIR)
    @ $(RM_F) $(IMPORT_IDIR)
    @ echo CLEAN DONE

cleanall: cleanmodules clean
    @ $(RM_F) $(TARGET)
    @ echo CLEANALL DONE

rebuild: clean all

ifneq ($(MISSING_DEPS),)
$(MISSING_DEPS) :
    @ $(RM_F) $(patsubst %.d,%.o,$@)
endif

-include $(DEPS)

$(TARGET) : $(OBJS) modules
    @ echo MAKE $(TARGET) START
    @ mkdir -p $(EXPORT_ODIR)
    @ mkdir -p $(IMPORT_IDIR)
    @ mkdir -p $(TOPDIR)/$(IMPORT_IDIR)
    @ $(AR) $(ARFLAGS) -o $(TARGET) $(OBJS) 
    @ ln -sft $(TOPDIR)/$(IMPORT_IDIR) $(TOPDIR)/$(MODNAME)/$(TARGET) 
    @ echo MAKE $(TARGET) DONE


    此Makefile不依赖于模块名及模块具体内容,具有较好的移植性。添加新的模块,只需直接将该Makefile复制到新模块目录下就可以了,然后在main模块Makefile和根Makefile中添加新的模块名。直接编译就可以了。

    准备好了Makefile,就可以进行编译了。

    在sort根目录下运行make:

root@mygirl:/study/sort# make
root@mygirl:/study/sort# ls
heap_sort  sort  main  Makefile  Makefile.rule  quick_sort  shell_sort

    看到的新出现的文件sort,就是编译后的可之执行文件。

    在sort根目录下运行make cleanall:

root@mygirl:/study/sort# make cleanall
root@mygirl:/study/sort# ls
heap_sort main  Makefile  Makefile.rule  quick_sort  shell_sort

    这样,就可以清除编译生成的各个文件了。

至此一切OK! 希望对Makefile初学者有所帮助!


http://blog.csdn.net/yf210yf/article/details/7638542

相关文章推荐

Linux相关-------简单工程Makefile的编写

工程Makefile的编写,对于初始Makefile的菜鸟们来说,还是比较头疼的一件事情,如何做到整个工程结构清晰,各个模块相对独立,模块的添加 删除等都比较方便,各个层次的的Makefile风格一致...
  • yf210yf
  • yf210yf
  • 2012年06月06日 15:40
  • 782

简单工程Makefile的编写

原文链接:     工程Makefile的编写,对于初始Makefile的菜鸟们来说,还是比较头疼的一件事情,如何做到整个工程结构清晰,各个模块相对独立,模块的添加删除等都比较方便,各个...

简单通用Makefile使用示例工程

  • 2017年07月05日 14:32
  • 2KB
  • 下载

简单的裸机makefile工程

makefile工程的基本思想:把子目录下的所有的源文件都编成库,然后再由顶层的makefile来包含这些库,然后再编译成核心文件...

工程管理器makefile的解释及简单模型

工程管理器makefile

快速实现工程makefile的简单通用模板

以前刚开始接触linux开发的时候,发现makefile真麻烦,我学C/C++开发已经花了不少时间了,现在还要花这个时间类搞这玩意,真是麻烦。真希望能出现一个模板,我只需要填下我需要编译的文件,以及相...
  • ErvinX
  • ErvinX
  • 2016年12月08日 19:43
  • 377

简单工程Makefile模版 及资料

模版: ######################################################## #程序文件夹下包含 src,obj,inc文件夹,分别放c源文件,obj文...

简单工程Makefile的自动生成

工程Makefile的编写,可以自己动手来写,也可以使用automake等工具来自动生成。下面还是以sort工程为例,对自动生成Makefle进行示例说明。 预备知识:     运用GNU A...
  • fzs333
  • fzs333
  • 2015年11月20日 15:56
  • 527

linux下C工程层级目录的Makefile编写

以前在ubuntu的gcc写小型的测试程序,都是直接调用gcc命令及其选项,突然有想完成稍大的工程的冲动,于是用了下makefile,果然强大。 目录包含 bin src inc lib obj ,...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:简单工程Makefile的编写
举报原因:
原因补充:

(最多只允许输入30个字)