通用Makefile实现

来源:互联网 发布:11.3非农数据最新消息 编辑:程序博客网 时间:2024/05/29 18:20

MakefileLinux下程序开发的自动化编译工具,一个好的Makefile应该准确的识别编译目标与源文件的依赖关系,并且有着高效的编译效率,即每次重新make时只需要处理那些修改过的文件即可。Makefile拥有很多复杂的功能,这里不可能也没必要一一介绍,为了简化问题的复杂性,本文仅和大家讨论针对单目录下的C/C++项目开发,如何写一个通用的Makefile

首先,我们假设当前工程目录为prj/,该目录下有6个文件,分别是:main.cabc.cxyz.cabc.hxyz.hMakefile。其中main.c包含头文件abc.hxyz.habc.c包含头文件abc.hxyz.c包含头文件xyz.h,而abc.h又包含了xyz.h。它们的依赖关系如图1


1 文件依赖关系

第一次使用Makefile应该写成这个样子(假设生成目标main):

main:main.o abc.o xyz.o

    gcc main.o abc.o xyz.o -o main

main.o:main.c abc.h xyz.h

    gcc -c main.c –o main.o -g

abc.o:abc.c abc.h xyz.h

    gcc -c abc.c –o abc.o -g

xyz.o:xyz.c xyz.h

    gcc -c xyz.c -o xyz.o -g

clean:

    rm main main.o abc.o xyz.o -f

虽然这样Makefile完全符合Makefile的书写规则,但是当代码文件再增加几倍后,再管理这些命令将会是一个噩梦!!!因此Makefile提供了默认规则和自动推导帮我们完成一些常用功能。然后,我们将Makefile修改如下:

EXE=main

CC=gcc

OBJ=main.o abc.o xyz.o

CFLAGS=-g

(EXE):

(EXE):

(OBJ)

   

(CC)

(CC)

^ -o $@

clean:

    rm

(EXE)

(EXE)

(OBJ) -f

变量EXECCOBJ分别代指目标程序名,编译器名,目标文件名。CFLAGSMakefile的预定义变量,它会附加在每条编译命令(gcc -c)之后。

$(EXE)是对变量的引用,$^代指所有的依赖项——$(OBJ)$@代指目标项——$(EXE)。该命令等价于:

(CC)

(CC)

(OBJ) -o $(EXE)

这个Makefile只有目标文件链接的命令,源文件的编译命令都被忽略了!这正是Makefile的自动推导功能——它可以将目标文件自动依赖于同名的源文件,即:

main.o:main.c

    gcc -c main.c -o main.o

abc.o:abc.c

    gcc -c abc.c -o abc.o

xyz.o:xyz.c

    gcc -c xyz.c -o xyz.o


按照上述方式,只要工程下增加了源文件后,只需要在OBJ初始化处增加一个*.o即可。但是这种方式是有问题的,Makefile的自动推导功能只会推导出目标文件对源文件的依赖关系,而不会增加头文件的依赖关系!!!这导致的直接问题就是修改项目的头文件,不会导致make的自动更新!除非修改头文件后运行一次make clean,再运行make…… :-)

为了能让make自动包含头文件的依赖关系,我们需要做一点额外的工作。幸运的是gcc为我们提供了一个编译选项(gcc -M,对于g++-MM),能输出目标文件的依赖关系!比如:

$gcc -M main.c

main.o:main.c abc.h xyz.h

如果将每个源文件的依赖关系包含到Makefile里,就可以使得目标文件自动依赖于头文件了!再次修改原先的Makefile

EXE=main

CC=gcc

SRC=$(wildcard *.c)

OBJ=$(SRC:.c=.o)

CFLAGS=-g

all:depend $(EXE)

depend:

@

(CC)−MM

(CC)−MM

(SRC) > .depend

-include .depend

(EXE):

(EXE):

(OBJ)

(CC)

(CC)

(OBJ) -o $(EXE)

clean:

@rm

(EXE)

(EXE)

(OBJ) .depend -f

我们虚设了一个目标all,它依赖于depend和实际的目标EXE。而depend正式将所有的源文件对应的目标文件的依赖关系输入到.depend文件,并包含在Makefile内!这里有几个细节需要说明:

1.depend文件是隐藏文件,避免和工程的文件混淆。

2include命令之前增加符号‘-’,避免第一次make时由于.depend文件不存在报告错误信息。

3SRC初始化为wildcard *.c表示当前目录下的所有.c源文件,这就省去了我们手动输入新增的源文件。

4OBJ初始化为SRC:.c=.o,表示将SRC中所有.c结尾的文件名替换为.o结尾的,这样就自动生成了源文件的目标文件序列。

5cleanrm命令钱@符号表示执行该命令时不输出任何信息。

这样,每次执行make时都会重新计算目标文件的依赖关系,并输出到.depend文件,然后包含到Makefile后进行编译工作,这样目标文件的依赖关系就不会出错了!而我们得到了一个能自动包含源文件和识别头文件依赖关系的Makefile,将该文件应用于任何单目录的C/C++工程(C++需要修改部分细节,不作赘述)都能正常工作。

但是,这种方式也有一定的不足,当头文件的依赖关系不发生变化时,每次make也会重新生成.depend文件。如果这样使得工程的编译变得不尽人意,那么我们可以尝试将依赖文件拆分,使得每个源文件独立拥有一个依赖文件,这样每次make时变化的只是一小部分文件的依赖关系。

EXE=main

CC=gcc

SRC=$(wildcard *.c)

OBJ=$(SRC:.c=.o)

DEP=

(patsubst

(patsubst

(SRC))

CFLAGS=-g

(EXE):

(EXE):

(OBJ)

(CC)

(CC)

^ -o $@

$(DEP):.%.d:%.c

@set -e;\

rm -f $@;\

(CC)−M

(CC)−M

< >

@.

@.

$$$;\

sed 's,

$

$

\.o[ :]*,\1.o

@:,

g

<

@:,g′<

@.



> $@;\

rm -f

@.

@.

$$$

-include $(DEP)

clean:

@rm

(EXE)

(EXE)

(OBJ) $(DEP) -f

Makefile增加了一个变量DEP,初始化为patsubst %.c,.%.d,$(SRC),表示将SRC中的以*.c结尾的源文件名替换为.*.d的形式,比如main.c对应着文件.main.d,这就是main.c的依赖关系文件,且是隐藏的。

为了生成每个源文件的依赖文件,建立了目标依赖关系$(DEP):.%.d:%.c,该关系表示,对于目标DEP,通过$@可以访问一个依赖文件,通过$>则访问对应的同名源文件。命令部分使用\连接,表示当前命令作为一个整体在一个进程内执行。该组命令的含义是:将gcc -M生成的信息输出到一个临时文件,然后在:之前加上当前的文件名输出到依赖文件。比如对于main.c生成的临时文件信息为:

main.o:main.c abc.h xyz.h

处理后依赖文件信息是:

main.o .main.d:main.c abc.h xyz.h

这样的依赖关系表示main.o和它的依赖关系文件的依赖项是一致的,只要相关的源文件或头文件发生了改变,才会重新生成目标文件和依赖关系文件,也就达到了依赖关系文件单独更新的目的了。

虽然如此,但是这样的Makefile也不是完美的。现假设工程目录内新增一个源文件lmn.c,按照Makefile的指令make后会产生.lmn.d依赖关系文件。而如果我们再删除lmn.c源文件后,重新make.lmn.d依然存在!尤其是当重复增删很多源文件后,工程目录下可能会存在很多无用的依赖文件,当然这些问题可以通过make clean解决。

通过前边的讨论,我们得到一个能在单目录工程下工作的通用Makefile,至于是实现为单独一个依赖文件的形式,还是每个源文件产生一个独立的依赖文件,要根据程序作者自己的喜恶来选择。虽然每种方法都有一些细微的瑕疵,但是不影响这个通用的Makefile的实用性,试想一下在工程目录下拷贝一份当前的Makefile,稍加修改便可以正确的编译开发,一定会令人心情大好。希望本文对你学习Linux写的程序开发有所帮助!




Makfile相关函数说明:

1wildcard : 扩展通配符
2notdir 去除路径
3patsubst :替换通配符

例子:
建立一个测试目录,在测试目录下建立一个名为sub的子目录
$ mkdir test
$ cd test
$ mkdir sub

test下,建立a.cb.c2个文件,在sub目录下,建立sa.csb.c2个文件

建立一个简单的Makefile
src=$(wildcard *.c ./sub/*.c)
dir=$(notdir $(src))
obj=$(patsubst %.c,%.o,$(dir) )

all:
 @echo $(src)
 @echo $(dir)
 @echo $(obj)
 @echo "end"
 
执行结果分析:
第一行输出:
a.c b.c ./sub/sa.c ./sub/sb.c

wildcard 指定目录 ./ ./sub/下的所有后缀是c的文件全部展开。

第二行输出:
a.c b.c sa.c sb.c
notdir把展开的文件去除掉路径信息

第三行输出:
a.o b.o sa.o sb.o

$(patsubst %.c,%.o,$(dir) )中,patsubst$(dir)中的变量符合后缀是.c的全部替换成.o

任何输出。
或者可以使用
obj=$(dir:%.c=%.o)
效果也是一样的。

这里用到makefile里的替换引用规则,即用您指定的变量替换另一个变量。

它的标准格式是

$(var:a=b) ${var:a=b}

它的含义是把变量var中的每一个值结尾用b替换掉a








linux makefile模板

 

sg_trans.gif

 (2013-05-12 17:39:38)

sg_trans.gif

转载▼

分类:linux

转载:http://bbs.chinaunix.net/thread-3553668-1-1.html

本文提供一个在GNU/Linux环境下通用的智能Makefile模板,用户可以将其引入到自己的工程当中。即使用户对此
Makefile
的工作原理不甚了解,但是只需要修改少数几个关键变量,就可以满足不同的应用需求。


1.
使用环境
GNU make 3.8.1
或者以上版本
sed
gcc/binutils
cygwin
或者Linux

2.
关键变量
CROSS_COMPILE
:交叉编译器前缀
OPTIMIZE
:关于优化的编译参数
WARNINGS
:关于warning的编译参数
DEFS
    关于宏定义的编译参数
EXTRA_CFLAGS
:其它的编译参数
$(OPTIMIZE) $(WARNINGS) $(DEFS) $(EXTRA_CFLAGS)
共同构成了传给gcc的编译参数。

INC_DIR
:头文件目录
SRC_DIR
:源文件目录(当前目录.是被默认包含的)
OBJ_DIR
object文件的输出目录
EXTRA_SRC
:源文件列表
EXCLUDE_FILES
exclude文件列表

SUFFIX
:源文件的后缀名
TARGET
:最终的目标程序名
TARGET_TYPE
:目标程序的类型。
可以定义的类型为:arstatic library),soshared library)和appapplication)。

最终Makefile的行为是:
$(SRC_DIR)定义的每个目录中查找后缀为$(SUFFIX)的文件,并加上$(EXTRA_SRC)中的文件,然后排除掉
$(EXCLUDE_FILES)
中的文件,获得本工程定义的源文件列表。对于每一个源文件,编译生成的一个.o文件和一个.d文件
(依赖文件),放在$(OBJ_DIR)目录下。最终生成的目标文件为$(TARGET)
Makefile已经充分考虑到文件之间的依赖关系,即,如果某个头文件发生改变,当运行make的时候,所有依赖于它的
源文件都将被重新编译。

附件是一个例子,演示了如何处理不同目录,如何处理不同目标类型,以及如何exclude文件。

rar.gif

 example.rar

实例:

makefile

###############################################################################
#
# A smart Makefile template for GNU/LINUX programming
#
# Author: PRC (ijkxyz AT msn DOT com)
# Date:   2011/06/17
#
# Usage:
#   $ make           Compile and link (or archive)
#   $ make clean     Clean the objectives and target.
###############################################################################

CROSS_COMPILE =
OPTIMIZE := -O2
WARNINGS := -Wall -Wno-unused -Wno-format
DEFS     := -DMYDEF=1 -UMYDEF2
EXTRA_CFLAGS :=

INC_DIR   = include
SRC_DIR   = src1 src2/a src2/b
OBJ_DIR   = out/target
EXTRA_SRC = src3/z3.c src4/z4.cpp
EXCLUDE_FILES = src1/skipme1.c src2/a/skipme2.c

SUFFIX       = c cpp cc cxx
TARGET       := out/go.exe
#TARGET_TYPE  := ar
TARGET_TYPE  := app
#TARGET_TYPE  := so


#####################################################################################
#  Do not change any part of them unless you have understood this script very well  #
#  This is a kind remind.                                                           #
#####################################################################################

#FUNC#  Add a new line to the input stream.
define add_newline
$1

endef

#FUNC# set the variable `src-x' according to the input $1
define set_src_x
src-$1 = $(filter-out $4,$(foreach d,$2,$(wildcard $d/*.$1)) $(filter %.$1,$3))

endef

#FUNC# set the variable `obj-x' according to the input $1
define set_obj_x
obj-$1 = $(patsubst %.$1,$3%.o,$(notdir $2))

endef

#VAR# Get the uniform representation of the object directory path name
ifneq ($(OBJ_DIR),)
prefix_objdir  = $(shell echo $(OBJ_DIR)|sed 's:\(\./*\)*::')
prefix_objdir := $(filter-out /,$(prefix_objdir)/)
endif

GCC      := $(CROSS_COMPILE)gcc
G++      := $(CROSS_COMPILE)g++
SRC_DIR := $(sort . $(SRC_DIR))
inc_dir = $(foreach d,$(sort $(INC_DIR) $(SRC_DIR)),-I$d)

#--# Do smart deduction automatically
$(eval $(foreach i,$(SUFFIX),$(call set_src_x,$i,$(SRC_DIR),$(EXTRA_SRC),$(EXCLUDE_FILES))))
$(eval $(foreach i,$(SUFFIX),$(call set_obj_x,$i,$(src-$i),$(prefix_objdir))))
$(eval $(foreach f,$(EXTRA_SRC),$(call add_newline,vpath $(notdir $f) $(dir $f))))
$(eval $(foreach d,$(SRC_DIR),$(foreach i,$(SUFFIX),$(call add_newline,vpath %.$i $d))))

all_objs = $(foreach i,$(SUFFIX),$(obj-$i))
all_srcs = $(foreach i,$(SUFFIX),$(src-$i))

CFLAGS       = $(EXTRA_CFLAGS) $(WARNINGS) $(OPTIMIZE) $(DEFS)
TARGET_TYPE := $(strip $(TARGET_TYPE))

ifeq ($(filter $(TARGET_TYPE),so ar app),)
$(error Unexpected TARGET_TYPE `$(TARGET_TYPE)')
endif

ifeq ($(TARGET_TYPE),so)
 CFLAGS  += -fpic -shared
 LDFLAGS += -shared
endif

PHONY = all .mkdir clean

all: .mkdir $(TARGET)

define cmd_o
$$(obj-$1): $2%.o: %.$1  $(MAKEFILE_LIST)
 $(GCC) $(inc_dir) -Wp,-MT,$$@ -Wp,-MMD,$$@.d $(CFLAGS) -c -o $$@ $$<

endef
$(eval $(foreach i,$(SUFFIX),$(call cmd_o,$i,$(prefix_objdir))))

ifeq ($(TARGET_TYPE),ar)
$(TARGET): AR := $(CROSS_COMPILE)ar
$(TARGET): $(all_objs)
 rm -f $@
 $(AR) rcvs $@ $(all_objs)
else
$(TARGET): LD = $(if $(strip $(src-cpp) $(src-cc) $(src-cxx)),$(G++),$(GCC))
$(TARGET): $(all_objs)
 $(LD) $(LDFLAGS) $(all_objs) -o $@
endif

.mkdir:
 @if [ ! -d $(OBJ_DIR) ]; then mkdir -p $(OBJ_DIR); fi

clean:
 rm -f $(prefix_objdir)*.o $(TARGET)

-include $(patsubst %.o,%.o.d,$(all_objs))

.PHONY: $(PHONY)






   1 、生成可执行文件的 makefile

######################################

#

# Generic makefile

#

# by Coon Xu

# email: coonxu@126.com

#

# Copyright (c) 2005 Coon Xu

# All rights reserved.

# No warranty, no liability;

# you use this at your own risk.

#

# You are free to modify and

# distribute this without giving

# credit to the original author.

#

######################################

 

 

#source file

# 源文件,自动找所有 .c .cpp文件,并将目标定义为同名 .o文件

SOURCE  := $(wildcard *.c) $(wildcard *.cpp)

OBJS    := $(patsubst %.c,%.o,$(patsubst %.cpp,%.o,$(SOURCE)))

 

#target you can change test to what you want

# 目标文件名,输入任意你想要的执行文件名

TARGET  := test

 

#compile and lib parameter

# 编译参数

CC      := gcc

LIBS    :=

LDFLAGS:= 

DEFINES:=

INCLUDE:= -I.

CFLAGS  := -g -Wall -O3 $(DEFINES) $(INCLUDE)

CXXFLAGS:= $(CFLAGS) -DHAVE_CONFIG_H

 

 

#i think you should do anything here

# 下面的基本上不需要做任何改动了

.PHONY : everything objs clean veryclean rebuild

 

everything : $(TARGET)

 

all : $(TARGET)

 

objs : $(OBJS)

 

rebuild: veryclean everything

               

clean :

    rm -fr *.so

    rm -fr *.o

   

veryclean : clean

    rm -fr $(TARGET)

 

$(TARGET) : $(OBJS) 

    $(CC) $(CXXFLAGS) -o $@ $(OBJS) $(LDFLAGS) $(LIBS)




2 、生成静态链接库的 makefile


######################################

#

# Generic Static Library makefile

#

# by Coon Xu

# email: coonxu@126.com

#

# Copyright (c) 2005 Coon Xu

# All rights reserved.

# No warranty, no liability;

# you use this at your own risk.

#

# You are free to modify and

# distribute this without giving

# credit to the original author.

#

######################################

 

#target you can change test to what you want

# 共享库文件名, lib*.a

TARGET  := libtest.a

 

#compile and lib parameter

# 编译参数

CC      := gcc

AR      = ar

RANLIB  = ranlib

LIBS    :=

LDFLAGS:= 

DEFINES:=

INCLUDE:= -I.

CFLAGS  := -g -Wall -O3 $(DEFINES) $(INCLUDE)

CXXFLAGS:= $(CFLAGS) -DHAVE_CONFIG_H

 

#i think you should do anything here

# 下面的基本上不需要做任何改动了

 

#source file

# 源文件,自动找所有 .c .cpp文件,并将目标定义为同名 .o文件

SOURCE  := $(wildcard *.c) $(wildcard *.cpp)

OBJS    := $(patsubst %.c,%.o,$(patsubst %.cpp,%.o,$(SOURCE)))

 

.PHONY : everything objs clean veryclean rebuild

 

everything : $(TARGET)

 

all : $(TARGET)

 

objs : $(OBJS)

 

rebuild: veryclean everything

               

clean :

    rm -fr *.o

   

veryclean : clean

    rm -fr $(TARGET)

 

$(TARGET) : $(OBJS) 

    $(AR) cru $(TARGET) $(OBJS)

    $(RANLIB) $(TARGET)




3 、生成动态链接库的 makefile


######################################

#

# Generic Share Library makefile

#

# by Coon Xu

# email: coonxu@126.com

#

# Copyright (c) 2005 Coon Xu

# All rights reserved.

# No warranty, no liability;

# you use this at your own risk.

#

# You are free to modify and

# distribute this without giving

# credit to the original author.

#

######################################

 

#target you can change test to what you want

# 共享库文件名, lib*.so

TARGET  := libtest.so

 

#compile and lib parameter

# 编译参数

CC      := gcc

LIBS    :=

LDFLAGS:= 

DEFINES:=

INCLUDE:= -I.

CFLAGS  := -g -Wall -O3 $(DEFINES) $(INCLUDE)

CXXFLAGS:= $(CFLAGS) -DHAVE_CONFIG_H

SHARE   := -fPIC -shared -o

 

#i think you should do anything here

# 下面的基本上不需要做任何改动了

 

#source file

# 源文件,自动找所有 .c .cpp文件,并将目标定义为同名 .o文件

SOURCE  := $(wildcard *.c) $(wildcard *.cpp)

OBJS    := $(patsubst %.c,%.o,$(patsubst %.cpp,%.o,$(SOURCE)))

 

.PHONY : everything objs clean veryclean rebuild

 

everything : $(TARGET)

 

all : $(TARGET)

 

objs : $(OBJS)

 

rebuild: veryclean everything

               

clean :

    rm -fr *.o

   

veryclean : clean

    rm -fr $(TARGET)

 

$(TARGET) : $(OBJS) 

    $(CC) $(CXXFLAGS) $(SHARE) $@ $(OBJS) $(LDFLAGS) $(LIBS)





uClinux makefile


来源: ChinaUnix博客 日期: 2007.03.23 10:41 (共有条评论)我要评论

 

今天开始学习uClinux下的makefile啦,应该对马上要开始的移植有帮助

——————从现在起,记录点点滴滴。。。。。

(刚刚起步,只是自己的了解,注释也是一点点的加上去的,不对的地方请见谅,提出以修改)

DE2 开发板下uClinux下的主Makedile源代码:

############################################################################

#

# Makefile -- Top level uClinux makefile.

#

# Copyright (c) 2001-2004, SnapGear (

www.snapgear.com

)

# Copyright (c) 2001, Lineo

#

VERSIONPKG = 3.2.0                        *目标系统版本序列号

VERSIONSTR = $(CONFIG_VENDOR)/$(CONFIG_PRODUCT) Version $(VERSIONPKG)

############################################################################

#

# Lets work out what the user wants, and if they have configured us yet

#

ifeq (.config,$(wildcard .config))   *wildcrad用于通配符.config的扩展,如果存在

include .config                      *.config,则运行该与系统配置依赖关系的.config

all: ucfront cksum subdirs romfs image  *all为最终目标,最终目标为多个程序,如输入     

else                         *make image则编译产生iamge内核

all: config_error        *不存在.config则运行config_erro                            

endif

############################################################################

#

# Get the core stuff worked out

#

LINUXDIR = $(CONFIG_LINUXDIR)      

LIBCDIR  = $(CONFIG_LIBCDIR)

ROOTDIR  = $(shell pwd)

PATH  := $(PATH):$(ROOTDIR)/tools

HOSTCC   = cc

IMAGEDIR = $(ROOTDIR)/images

RELDIR   = $(ROOTDIR)/release

ROMFSDIR = $(ROOTDIR)/romfs

ROMFSINST= romfs-inst.sh

SCRIPTSDIR = $(ROOTDIR)/config/scripts

TFTPDIR    = /tftpboot                     **路径说明

BUILD_START_STRING ?= $(shell date "+%a, %d %b %Y %T %z")  

ifndef NON_SMP_BUILD

HOST_NCPU := $(shell if [ -f /proc/cpuinfo ]; then n=`grep -c processor /proc/cpuinfo`; if [ $$n -gt 1 ];then expr $$n \* 2; else echo $$n; fi; else echo 1; fi)

else

HOST_NCPU := 1

endif

LINUX_CONFIG  = $(ROOTDIR)/$(LINUXDIR)/.config

CONFIG_CONFIG = $(ROOTDIR)/config/.config

MODULES_CONFIG = $(ROOTDIR)/modules/.config

CONFIG_SHELL := $(shell if [ -x "$$BASH" ]; then echo $$BASH; \

   else if [ -x /bin/bash ]; then echo /bin/bash; \

   else echo sh; fi ; fi)

ifeq (config.arch,$(wildcard config.arch))

ifeq ($(filter %_default, $(MAKECMDGOALS)),)

include config.arch

ARCH_CONFIG = $(ROOTDIR)/config.arch

export ARCH_CONFIG

endif

endif

# May use a different compiler for the kernel

KERNEL_CROSS_COMPILE ?= $(CROSS_COMPILE)

ifneq ($(SUBARCH),)

# Using UML, so make the kernel and non-kernel with different ARCHs

MAKEARCH = $(MAKE) ARCH=$(SUBARCH) CROSS_COMPILE=$(CROSS_COMPILE)

MAKEARCH_KERNEL = $(MAKE) ARCH=$(ARCH) SUBARCH=$(SUBARCH) CROSS_COMPILE=$(KERNEL_CROSS_COMPILE)

else

MAKEARCH = $(MAKE) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE)

MAKEARCH_KERNEL = $(MAKEARCH)  ARCH=$(ARCH) CROSS_COMPILE=$(KERNEL_CROSS_COMPILE)

endif

DIRS    = $(VENDOR_TOPDIRS) include lib include user

export VENDOR PRODUCT ROOTDIR LINUXDIR HOSTCC CONFIG_SHELL

export CONFIG_CONFIG LINUX_CONFIG MODULES_CONFIG ROMFSDIR SCRIPTSDIR

export VERSIONPKG VERSIONSTR ROMFSINST PATH IMAGEDIR RELDIR RELFILES TFTPDIR

export BUILD_START_STRING

export HOST_NCPU

.PHONY: ucfront

ucfront: tools/ucfront/*.c

$(MAKE) -C tools/ucfront

ln -sf $(ROOTDIR)/tools/ucfront/ucfront tools/ucfront-gcc

ln -sf $(ROOTDIR)/tools/ucfront/ucfront tools/ucfront-g++

ln -sf $(ROOTDIR)/tools/ucfront/ucfront-ld tools/ucfront-ld

.PHONY: cksum

cksum: tools/sg-cksum/*.c

$(MAKE) -C tools/sg-cksum

ln -sf $(ROOTDIR)/tools/sg-cksum/cksum tools/cksum

############################################################################

#

# Config stuff,  we recall ourselves to load the new config.arch before

# running the kernel and other config scripts

#

.PHONY: config.tk config.in

config.in:

@chmod u+x config/mkconfig

config/mkconfig > config.in

config.tk: config.in

$(MAKE) -C $(SCRIPTSDIR) tkparse

ARCH=dummy $(SCRIPTSDIR)/tkparse  config.tmp

@if [ -f /usr/local/bin/wish ]; then \

  echo '#!'"/usr/local/bin/wish -f" > config.tk; \

else \

  echo '#!'"/usr/bin/wish -f" > config.tk; \

fi

cat $(SCRIPTSDIR)/header.tk >> ./config.tk

cat config.tmp >> config.tk

rm -f config.tmp

echo "set defaults \"/dev/null\"" >> config.tk

echo "set help_file \"config/Configure.help\"" >> config.tk

cat $(SCRIPTSDIR)/tail.tk >> config.tk

chmod 755 config.tk

.PHONY: xconfig

xconfig: config.tk

@wish -f config.tk

@if [ ! -f .config ]; then \

  echo; \

  echo "You have not saved your config, please re-run make config"; \

  echo; \

  exit 1; \

  fi

@chmod u+x config/setconfig

@config/setconfig defaults

@if egrep "^CONFIG_DEFAULTS_KERNEL=y" .config > /dev/null; then \

  $(MAKE) linux_xconfig; \

  fi

@if egrep "^CONFIG_DEFAULTS_MODULES=y" .config > /dev/null; then \

  $(MAKE) modules_xconfig; \

  fi

@if egrep "^CONFIG_DEFAULTS_VENDOR=y" .config > /dev/null; then \

  $(MAKE) config_xconfig; \

  fi

@config/setconfig final

.PHONY: config

config: config.in

@HELP_FILE=config/Configure.help \

  $(CONFIG_SHELL) $(SCRIPTSDIR)/Configure config.in

@chmod u+x config/setconfig

@config/setconfig defaults

@if egrep "^CONFIG_DEFAULTS_KERNEL=y" .config > /dev/null; then \

  $(MAKE) linux_config; \

  fi

@if egrep "^CONFIG_DEFAULTS_MODULES=y" .config > /dev/null; then \

  $(MAKE) modules_config; \

  fi

@if egrep "^CONFIG_DEFAULTS_VENDOR=y" .config > /dev/null; then \

  $(MAKE) config_config; \

  fi

@config/setconfig final

.PHONY: menuconfig

menuconfig: config.in

$(MAKE) -C $(SCRIPTSDIR)/lxdialog all

@HELP_FILE=config/Configure.help \

  $(CONFIG_SHELL) $(SCRIPTSDIR)/Menuconfig config.in

@if [ ! -f .config ]; then \

  echo; \

  echo "You have not saved your config, please re-run make config"; \

  echo; \

  exit 1; \

  fi

@chmod u+x config/setconfig

@config/setconfig defaults

@if egrep "^CONFIG_DEFAULTS_KERNEL=y" .config > /dev/null; then \

  $(MAKE) linux_menuconfig; \

  fi

@if egrep "^CONFIG_DEFAULTS_MODULES=y" .config > /dev/null; then \

  $(MAKE) modules_menuconfig; \

  fi

@if egrep "^CONFIG_DEFAULTS_VENDOR=y" .config > /dev/null; then \

  $(MAKE) config_menuconfig; \

  fi

@config/setconfig final

.PHONY: oldconfig

oldconfig: config.in

@HELP_FILE=config/Configure.help \

  $(CONFIG_SHELL) $(SCRIPTSDIR)/Configure -d config.in

@$(MAKE) oldconfig_linux

@$(MAKE) oldconfig_modules

@$(MAKE) oldconfig_config

@$(MAKE) oldconfig_uClibc

@chmod u+x config/setconfig

@config/setconfig final

.PHONY: modules

modules:

. $(LINUXDIR)/.config; if [ "$$CONFIG_MODULES" = "y" ]; then \

  [ -d $(LINUXDIR)/modules ] || mkdir $(LINUXDIR)/modules; \

  $(MAKEARCH_KERNEL) -C $(LINUXDIR) modules; \

fi

.PHONY: modules_install

modules_install:

. $(LINUXDIR)/.config; if [ "$$CONFIG_MODULES" = "y" ]; then \

  [ -d $(ROMFSDIR)/lib/modules ] || mkdir -p $(ROMFSDIR)/lib/modules; \

  $(MAKEARCH_KERNEL) -C $(LINUXDIR) INSTALL_MOD_PATH=$(ROMFSDIR) DEPMOD="../user/busybox/examples/depmod.pl -k vmlinux" modules_install; \

  rm -f $(ROMFSDIR)/lib/modules/*/build; \

  rm -f $(ROMFSDIR)/lib/modules/*/source; \

  find $(ROMFSDIR)/lib/modules -type f -name "*o" | xargs -r $(STRIP) -R .comment -R .note -g --strip-unneeded; \

fi

linux_xconfig:

KCONFIG_NOTIMESTAMP=1 $(MAKEARCH_KERNEL) -C $(LINUXDIR) xconfig

linux_menuconfig:

KCONFIG_NOTIMESTAMP=1 $(MAKEARCH_KERNEL) -C $(LINUXDIR) menuconfig

linux_config:

KCONFIG_NOTIMESTAMP=1 $(MAKEARCH_KERNEL) -C $(LINUXDIR) config

modules_xconfig:

[ ! -d modules ] || $(MAKEARCH) -C modules xconfig

modules_menuconfig:

[ ! -d modules ] || $(MAKEARCH) -C modules menuconfig

modules_config:

[ ! -d modules ] || $(MAKEARCH) -C modules config

modules_clean:

-[ ! -d modules ] || $(MAKEARCH) -C modules clean

config_xconfig:

$(MAKEARCH) -C config xconfig

config_menuconfig:

$(MAKEARCH) -C config menuconfig

config_config:

$(MAKEARCH) -C config config

oldconfig_config:

$(MAKEARCH) -C config oldconfig

oldconfig_modules:

[ ! -d modules ] || $(MAKEARCH) -C modules oldconfig

oldconfig_linux:

KCONFIG_NOTIMESTAMP=1 $(MAKEARCH_KERNEL) -C $(LINUXDIR) oldconfig

oldconfig_uClibc:

[ -z "$(findstring uClibc,$(LIBCDIR))" ] || $(MAKEARCH) -C $(LIBCDIR) oldconfig

############################################################################

#

# normal make targets

#

.PHONY: romfs

romfs: romfs.subdirs modules_install romfs.post

.PHONY: romfs.subdirs

romfs.subdirs:

for dir in vendors $(DIRS) ; do [ ! -d $$dir ] || $(MAKEARCH) -C $$dir romfs || exit 1 ; done

.PHONY: romfs.post

romfs.post:

$(MAKEARCH) -C vendors romfs.post

-find $(ROMFSDIR)/. -name CVS | xargs -r rm -rf

.PHONY: image

image:

[ -d $(IMAGEDIR) ] || mkdir $(IMAGEDIR)

$(MAKEARCH) -C vendors image

.PHONY: release

release:

make -C release release

%_fullrelease:

@echo "This target no longer works"

@echo "Do a make -C release $@"

exit 1

#

# fancy target that allows a vendor to have other top level

# make targets,  for example "make vendor_flash" will run the

# vendor_flash target in the vendors directory

#

vendor_%:

$(MAKEARCH) -C vendors $@

.PHONY: linux

linux linux%_only:

@if [ $(LINUXDIR) != linux-2.5.x -a $(LINUXDIR) != linux-2.6.x -a ! -f $(LINUXDIR)/.depend ] ; then \

  echo "ERROR: you need to do a 'make dep' first" ; \

  exit 1 ; \

fi

$(MAKEARCH_KERNEL) -j$(HOST_NCPU) -C $(LINUXDIR) $(LINUXTARGET) || exit 1

if [ -f $(LINUXDIR)/vmlinux ]; then \

  ln -f $(LINUXDIR)/vmlinux $(LINUXDIR)/linux ; \

fi

.PHONY: sparse

sparse:

$(MAKEARCH_KERNEL) -C $(LINUXDIR) C=1 $(LINUXTARGET) || exit 1

.PHONY: sparseall

sparseall:

$(MAKEARCH_KERNEL) -C $(LINUXDIR) C=2 $(LINUXTARGET) || exit 1

.PHONY: subdirs

subdirs: linux modules

for dir in $(DIRS) ; do [ ! -d $$dir ] || $(MAKEARCH) -C $$dir || exit 1 ; done

dep:

@if [ ! -f $(LINUXDIR)/.config ] ; then \

  echo "ERROR: you need to do a 'make config' first" ; \

  exit 1 ; \

fi

$(MAKEARCH_KERNEL) -C $(LINUXDIR) dep

# This one removes all executables from the tree and forces their relinking

.PHONY: relink

relink:

find user prop vendors -type f -name '*.gdb' | sed 's/^\(.*\)\.gdb/\1 \1.gdb/' | xargs rm -f

clean: modules_clean

for dir in $(LINUXDIR) $(DIRS); do [ ! -d $$dir ] || $(MAKEARCH) -C $$dir clean ; done

rm -rf $(ROMFSDIR)/*

rm -f $(IMAGEDIR)/*

rm -f config.tk

rm -f $(LINUXDIR)/linux

rm -f $(LINUXDIR)/include/asm

rm -rf $(LINUXDIR)/net/ipsec/alg/libaes $(LINUXDIR)/net/ipsec/alg/perlasm

real_clean mrproper: clean

-$(MAKEARCH_KERNEL) -C $(LINUXDIR) mrproper

-$(MAKEARCH) -C config clean

-$(MAKEARCH) -C uClibc distclean

-$(MAKEARCH) -C $(RELDIR) clean

rm -rf romfs config.in config.arch config.tk images

rm -f modules/config.tk

rm -rf .config .config.old .oldconfig autoconf.h

distclean: mrproper

-$(MAKEARCH_KERNEL) -C $(LINUXDIR) distclean

-rm -f user/tinylogin/applet_source_list user/tinylogin/config.h

%_only:

@case "$(@)" in \

*/*) d=`expr $(@) : '\([^/]*\)/.*'`; \

      t=`expr $(@) : '[^/]*/\(.*\)'`; \

      $(MAKEARCH) -C $$d $$t;; \

*)   $(MAKEARCH) -C $(@:_only=);; \

esac

%_clean:

@case "$(@)" in \

*/*) d=`expr $(@) : '\([^/]*\)/.*'`; \

      t=`expr $(@) : '[^/]*/\(.*\)'`; \

      $(MAKEARCH) -C $$d $$t;; \

*)   $(MAKEARCH) -C $(@:_clean=) clean;; \

esac

%_default:

@if [ ! -f "vendors/$(@:_default=)/config.device" ]; then \

  echo "vendors/$(@:_default=)/config.device must exist first"; \

  exit 1; \

  fi

-make clean > /dev/null 2>&1

cp vendors/$(@:_default=)/config.device .config

chmod u+x config/setconfig

yes "" | config/setconfig defaults

config/setconfig final

make dep

make

config_error:

@echo "*************************************************"

@echo "You have not run make config."

@echo "The build sequence for this source tree is:"

@echo "1. 'make config' or 'make xconfig'"

@echo "2. 'make dep'"

@echo "3. 'make'"

@echo "*************************************************"

@exit 1

prune: ucfront

@for i in `ls -d linux-* | grep -v $(LINUXDIR)`; do \

  rm -fr $$i; \

done

$(MAKE) -C lib prune

$(MAKE) -C user prune

$(MAKE) -C vendors prune

dist-prep:

-find $(ROOTDIR) -name 'Makefile*.bin' | while read t; do \

  $(MAKEARCH) -C `dirname $$t` -f `basename $$t` $@; \

  done

############################################################################




0 0
原创粉丝点击