通用Makefile實現

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

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




本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/383321.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/383321.shtml
英文地址,請注明出處:http://en.pswp.cn/news/383321.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

c++中空指針訪問成員函數

如果成員函數沒有用到this &#xff0c;那么空指針可以直接訪問 如果成員函數用到this 指針&#xff0c;就要注意&#xff0c;要判斷是否為空&#xff0c;防止程序崩潰 #include<iostream>using namespace std;class Person{public:void show(){//沒有 用到this指針&am…

從0開始python學習-35.allure報告企業定制

目錄 1. 搭建allure環境 2. 生成報告 3. logo定制 4. 企業級報告內容或層級定制 5. allure局域網查看 1. 搭建allure環境 1.1 JDK&#xff0c;使用PyCharm 找到pycharm安裝目錄找到java.exe記下jbr目錄的完整路徑&#xff0c;eg: C:\Program Files\JetBrains\PyCharm Com…

grep 常用命令

這個--include選項,可以這樣使用: grep -rn --include*.c --include*.h re . 可以指定多次, 如果真是上面的這種情況, 其實可以用 grep -rn --include*.[ch] re . 但是, 如果源文件中含有C源代碼,上面的方法就不湊效了, 因為[]中只能放一個字符. grep -rn --include*.{cp…

c++中友元函數詳解

友元 友元分為&#xff1a;友元函數和友元類 友元提供了一種突破封裝的方式&#xff0c;有時提供了便利。但是友元會增加耦合度&#xff0c;破壞了封裝&#xff0c;所以友元不宜多 用。 全局函數做友元函數 全局函數寫到類中做聲明 并且最前面寫關鍵字 friend 友元函數可訪問…

Linux時間函數札記

關于gmtime、gmtime_r、localtime、localtime_r 測試環境&#xff1a;vmware 7 Redhat5.5&#xff0c;系統時間使用UTC&#xff0c;時區為上海。 1、函數功能介紹 使用man gmtime或man localtime都可以的得到這幾個函數的介紹。原型如下&#xff1a; struct tm *gmtime(const …

c++實現順序表的相關操作

Myarray.h文件 #pragma once#include<iostream>using namespace std;class MyArray { public:MyArray();//默認構造 默認100容量MyArray(int capacity);MyArray(const MyArray& array);~MyArray();//尾插法void Push_Back(int val);//根據索引獲取值int getData(int…

系統架構札記

什么是高內聚、低耦合&#xff1f; 起因&#xff1a;模塊獨立性指每個模塊只完成系統要求的獨立子功能&#xff0c;并且與其他模塊的聯系最少且接口簡單&#xff0c;兩個定性的度量標準――耦合性和內聚性。 耦合性也稱塊間聯系。指軟件系統結構中各模塊間相互聯系緊密程度的一…

c++中運算符重載(加號運算,左移運算,前置后置++運算符,賦值運算,關系運算,函數運算)

運算符重載注意 重載的運算符要易讀內置的數據類型的表達式的運算符是不可以改變的不要重載&& 和 | | 運算符&#xff0c;[]和->運算符只能通過成員函數進行重載<<和>>只能通過全局函數配合友元函數進行重載 加號運算符重載 如果想讓自定義數據類型 進…

linux fstab解讀

fstab這個文件挺有用的。 從左到右&#xff1a; /dev/device mount-point type rules dump fsck 1. /dev/device: 不用說了吧&#xff1f;例如&#xff0c;/dev/hda1為M$-Win9x下的c:盤。 2. mount-point: 掛載點。例如&#xff0c;把/dev/hda1掛到/mnt/mywinc下。 3. type: ex…

c++實現字符串類的封裝

MyString.h文件 #define _CRT_SECURE_NO_WARNINGS#pragma once#include<iostream>#include<string>using namespace std;class MyString{friend ostream & operator<<(ostream & cout, MyString & str);friend istream & operator>>(…

c++中的繼承--1(引出,繼承方式,繼承的對象模型)

繼承的引出 概念&#xff1a; 繼承(inheritance)機制是面向對象程序設計使代碼可以復用的最重要的手段&#xff0c;它允許程序員在保持原有類特 性的基礎上進行擴展&#xff0c;增加功能&#xff0c;這樣產生新的類&#xff0c;稱派生類。繼承呈現了面向對象程序設計的層次結構…

Makefile經典教程(掌握這些足夠)

makefile很重要 什么是makefile&#xff1f;或許很多Winodws的程序員都不知道這個東西&#xff0c;因為那些Windows的IDE都為你做了這個工作&#xff0c;但我覺得要作一個好的和professional的程序員&#xff0c;makefile還是要懂。這就好像現在有這么多的HTML的編輯器&#xf…

c++中的繼承--2(繼承中的析構函數和構造函數,繼承中同名成員,繼承中靜態成員)

繼承中的構造函數和析構函數 繼承中的構造和析構順序 子類創建對象時&#xff0c;先調用父類的構造&#xff0c;然后調用自身構造析構順序與構造順序相反子類不會繼承父類的構造函數和析構函數如果父類中沒有合適默認構造&#xff0c;那么子類可以利用初始化列表的方式顯示的…

Linux鎖機制和線程安全

鎖機制是多線程編程中最常用的同步機制&#xff0c;用來對多線程間共享的臨界區進行保護。 1. 互斥鎖&#xff1a;pthread_mutex&#xff0c;屬于sleep-waiting類型的鎖 pthread_mutex_t *mutex; int pthread_mutex_int(mutex, attr) //以動態方式創建互斥鎖&#xff0c;參…

c++中的繼承--3(多繼承問題,菱形繼承)

繼承中的多繼承 #include<iostream>using namespace std;class Base1 { public:Base1(){m_A 10;} public:int m_A;};class Base2 { public:Base2(){m_A 10;} public:int m_B;int m_A;};class Son :public Base1, public Base2 {public:int m_C;int m_D; };void test01…

c++中的多態---1(多態概念,靜態聯編和動態聯編,多態原理解析,重載,重寫,重定義的對比)

多態的基本概念 多態是面向對象設計語言數據抽象和繼承之外的第三個基本特征多態性(polymorphism)提供接口與具體實現之間的另一層隔膜&#xff0c;從而將“what”和“how”分離開來&#xff0c;多態性改善了代碼的可讀和組織性&#xff0c;同時也使創建的程序具有可擴展性&am…

Ubuntu下各種服務搭建及操作技巧

Ubuntu下搭建TFTP 1、安裝軟件包 sudo apt-get install tftpd tftp xinetd 2、建立配置文件 在/etc/xinetd.d/下建立一個配置文件tftp sudo vi /etc/xinetd.d/tftp 內容如下 service tftp { socket_type dgram protocol udp wait yes user root …

c++多態--2(計算器,純虛函數和抽象類)

為什么要用多態 早期方法不利于擴展開閉原則 開閉原則 對擴展開放 對修改關閉利用多態實現—利于后期擴展&#xff0c;結構性非常好&#xff0c;可讀性高&#xff0c;效率稍微低&#xff0c;發生多態內部結構復雜 多態成立的條件 又繼承 子類重寫父類虛函數的函數&#xff1…

使用Automake和Autoconf生成Makefile

automake 所產生的 Makefile 除了可以做到程序的自動編譯和鏈接 外&#xff0c;還可以用來生成各種文檔&#xff08;如manual page、info文件&#xff09;&#xff0c;可以將源代碼文件包裝起來以供發布。所以程序源代碼所存放的目錄 結構最好符合GNU的標準慣例。下面以hello.…

c++中多態---3(虛析構和純虛析構,向上類型轉化和向下類型轉化)

虛析構和純虛析構 虛析構virtual ~類名(){}類內聲明&#xff0c;類內實現解決問題&#xff1a;通過父類指針指向子類對象釋放時候不干凈的問題 純虛析構 寫法 virtual ~類名(){}0; 類內聲明 類外實現 如果出現了純虛析構函數&#xff0c;這個類也算是抽象類&#xff0c;不可…