Makefile

来源:互联网 发布:收银软件免费版 编辑:程序博客网 时间:2024/06/06 03:56

今天看到了Makefile这个新东西,之前从没了解过,这就记录下来


Makefile基础 :

关于基础,有个人写的很好,我这个博客转载了他的文章,你可以翻翻看。



make命令会自动读取当前目录下的Makefile文件,完成相应的编译步骤。

Makefile由一组规则(Rule)组成,每条规则的格式是:

  1. target ... : prerequisites ...   
  2.     command1  
  3.     command2  
  4.     ... 
例如:

  1. main: main.o stack.o maze.o  
  2.     gcc main.o stack.o maze.o -o main 

main是这条规则的目标(Target),main.ostack.omaze.o是这条规则的条件(Prerequisite)。

目标和条件之间的关系是:欲更新目标,必须首先更新它的所有条件;所有条件中只要有一个条件被更新了,目标也必须随之被更新。所谓“更新”就是执行一遍规则中的命令列表,命令列表中的每条命令必须以一个Tab开头,

注意不能是空格,Makefile的格式不像C语言的缩进那么随意,对于Makefile中的每个以Tab开头的命令,make会创建一个Shell进程去执行它。

 

通常Makefile都会有一个clean规则,用于清除编译过程中产生的二进制文件,保留源文件:

  1. clean:  
  2.     @echo "cleanning project"  
  3.     -rm main *.o  
  4.     @echo "clean completed"  
把这条规则添加到我们的Makefile末尾,然后执行这条规则:

  1. $ make clean   
  2. cleanning project  
  3. rm main *.o  
  4. clean completed  
 如果在make的命令行中指定一个目标(例如clean),则更新这个目标,如果不指定目标则更新Makefile中第一条规则的目标(缺省目标)。

命令前面加@-字符的效果:

        如果make执行的命令前面加了@字符,则不显示命令本身而只显示它的结果;

       通常make执行的命令如果出错(该命令的退出状态非0)就立刻终止,不再执行后续命令,但如果命令前面加了-号,即使这条命令出错,make也会继续执行后续命令。

通常rm命令和mkdir命令前面要加-号,因为rm要删除的文件可能不存在,mkdir要创建的目录可能已存在,这两个命令都有可能出错,但这种错误是应该忽略的。

 

     文件名则不一定是Makefile。事实上,执行make命令时,是按照GNUmakefilemakefileMakefile的顺序找到第一个存在的文件并执行它,不过还是建议使用Makefile做文件名。除了GNU make,有些UNIX系统的make命令不是GNU make,不会查找GNUmakefile这个文件名,如果你写的Makefile包含GNU make的特殊语法,可以起名GNUmakefile,否则不建议用这个文件名。

 

隐含规则和模式规则:

make的隐含规则数据库可以用make -p命令打印,打印出来的格式也是Makefile的格式,包括很多变量和规则。

#号在Makefile中表示单行注释,就像C语言的//注释一样。CC是一个Makefile变量,用CC = cc定义和赋值,用$(CC)取它的值,其值应该是cc

$@和$<是两个特殊的变量,$@的取值为规则中的目标,$<的取值为规则中的第一个条件。%.o: %.c是一种特殊的规则,称为模式规则(Pattern Rule)。

 

一个目标依赖于若干条件,现在换个角度,以条件为中心,Makefile还可以这么写:

  1. main: main.o stack.o maze.o  
  2.     gcc main.o stack.o maze.o -o main  
  3.   
  4. main.o stack.o maze.o: main.h  
  5. main.o maze.o: maze.h  
  6. main.o stack.o: stack.h  
  7.   
  8. clean:  
  9.     -rm main *.o  
  10.   
  11. .PHONY: clean  


对于多目标的规则,make会拆成几条单目标的规则来处理,例如

  1. target1 target2: prerequisite1 prerequisite2  
  2.     command $< -o $@  
这样一条规则相当于:

  1. target1: prerequisite1 prerequisite2  
  2.     command prerequisite1 -o target1  
  3.   
  4. target2: prerequisite1 prerequisite2  
  5.     command prerequisite1 -o target2  
注意两条规则的命令列表是一样的,但$@的取值不同。

变量:

  1. foo = $(bar)   
  2. bar = Huh?   
  3.   
  4. all:   
  5.     @echo $(foo)  

 我们执行make将会打出Huh?。当make读到foo = $(bar)时,确定foo的值是$(bar),但并不立即展开$(bar),然后读到bar = Huh?,确定bar的值是Huh?,然后在执行规则all:的命令列表时才需要展开$(foo),得到$(bar),再展开$(bar),得到Huh?。因此,虽然bar的定义写在foo之后,$(foo)展开还是能够取到$(bar)的值。

 

有时候我们希望make在遇到变量定义时立即展开,可以用:=运算符,例如:

  1. x := foo  
  2. y := $(x) bar  
  3.   
  4. all:   
  5.     @echo "-$(y)-" 

运算符是?=,例如foo ?= $(bar)的意思是:如果foo没有定义过,那么?=相当于=,定义foo的值是$(bar),但不立即展开;如果先前已经定义了foo,则什么也不做,不会给foo重新赋值。

 

 

常用的特殊变量有:

  • $@,表示规则中的目标。

  • $<,表示规则中的第一个条件。

  • $?,表示规则中所有比目标新的条件,组成一个列表,以空格分隔。

  • $^,表示规则中的所有条件,组成一个列表,以空格分隔。


    1. main: main.o stack.o maze.o  
    2.     gcc main.o stack.o maze.o -o mainv  
    可以改写成:

    1. main: main.o stack.o maze.o  
    2.     gcc $^ -o $@  

    常用的make命令行选项

    -n选项只打印要执行的命令,而不会真的执行命令,这个选项有助于我们检查Makefile写得是否正确,由于Makefile不是顺序执行的,用这个选项可以先看看命令的执行顺序,确认无误了再真正执行命令。

    -C选项可以切换到另一个目录执行那个目录下的Makefile,

    make命令行也可以用=:=定义变量,如果这次编译我想加调试选项-g,但我不想每次编译都加-g选项,可以在命令行定义CFLAGS变量,而不必修改Makefile编译完了再改回来:

    $ make CFLAGS=-gcc -g   -c -o main.o main.ccc -g   -c -o stack.o stack.ccc -g   -c -o maze.o maze.cgcc main.o stack.o maze.o -o main

    如果在Makefile中也定义了CFLAGS变量,则命令行的值覆盖Makefile中的值。


    模板很多,可以在网上搜索下看看。

    下面附一个makefile 典型模板:

    1. # Makefile for iPhone Application for Xcode gcc compiler (SDK Headers)  
    2.   
    3. IPHONE_IP=192.168.1.115  
    4.   
    5. DARWINVERSION=10  
    6. GCCVERSION=4.2.1  
    7. SDKVERSION=3.1  
    8. ENVP=IPHONEOS_DEPLOYMENT_TARGET=3.0  
    9.   
    10. PROJECTNAME=iColorCall  
    11. APPFOLDER=$(PROJECTNAME).app  
    12. INSTALLFOLDER=$(PROJECTNAME).app  
    13.   
    14. SDK=/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS$(SDKVERSION).sdk  
    15.   
    16. CC=/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/arm-apple-darwin$(DARWINVERSION)-gcc-$(GCCVERSION)  
    17. CPP=/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/arm-apple-darwin$(DARWINVERSION)-g++-$(GCCVERSION)  
    18. LD=$(CC)  
    19.   
    20. LDFLAGS += -lobjc \  
    21.             -ObjC++ \  
    22.             -fobjc-exceptions \  
    23.             -march=armv6 \  
    24.             -mcpu=arm1176jzf-s \  
    25.             -fobjc-call-cxx-cdtors \  
    26.             -multiply_defined suppress \  
    27.             -framework CoreFoundation \  
    28.             -framework Foundation \  
    29.             -framework UIKit \  
    30.             -framework CoreGraphics \  
    31.             -framework AddressBookUI \  
    32.             -framework AddressBook \  
    33.             -framework QuartzCore \  
    34.             -framework OpenGLES \  
    35.             -framework CoreTelephony \  
    36.             -L"$(SDK)/usr/lib" \  
    37.             -F"$(SDK)/System/Library/Frameworks" \  
    38.             -F"$(SDK)/System/Library/PrivateFrameworks"  
    39.   
    40.   
    41. CFLAGS += -I"/Developer/Platforms/iPhoneOS.platform/Developer/usr/lib/gcc/arm-apple-darwin$(DARWINVERSION)/(GCCVERSION)/include/" \  
    42.             -I"$(SDK)/usr/include" \  
    43.             -I"/Developer/Platforms/iPhoneOS.platform/Developer/usr/include/" \  
    44.             -F"$(SDK)/System/Library/Frameworks" \  
    45.             -F"$(SDK)/System/Library/PrivateFrameworks" \  
    46.             -I./Classes \  
    47.             -I./Classes/Glgif \  
    48.             -I./Classes/Engine \  
    49.             -march=armv6 \  
    50.             -mcpu=arm1176jzf-s \  
    51.             -DDEBUG -std=c99 \  
    52.             -Diphoneos_version_min=3.0 \  
    53.             -DTARGET_OS_IPHONE \  
    54.             -DSP3 \  
    55.             -DLOG_APP_DEBUG_ENABLE \  
    56.             -DHEX_OUT_ENABLE  
    57.             #-DWINKS_LONG_SOCKET  
    58.             #-DWINKS_SOCKET_WRITE_CATCH  
    59.             #-DIPHONE_GIF_PREVIEW_TEST  
    60.             #-DTEST_STATIC_IMG_PREVIEW  
    61.   
    62. CPPFLAGS=$CFLAGS  
    63.   
    64. BUILDDIR=./build/$(SDKVERSION)  
    65. SRCDIR=./Classes  
    66. SRCDIR2=./Classes/Engine  
    67. SRCDIR3=./Classes/Glgif  
    68. RESDIR=./Resources  
    69.   
    70. OBJS=$(patsubst %.m,%.o,$(wildcard $(SRCDIR2)/*.m)) \  
    71.     $(patsubst %.c,%.o,$(wildcard $(SRCDIR2)/*.c)) \  
    72.     $(patsubst %.cpp,%.o,$(wildcard $(SRCDIR2)/*.cpp)) \  
    73.     $(patsubst %.m,%.o,$(wildcard $(SRCDIR)/*.m)) \  
    74.     $(patsubst %.c,%.o,$(wildcard $(SRCDIR)/*.c)) \  
    75.     $(patsubst %.cpp,%.o,$(wildcard $(SRCDIR)/*.cpp)) \  
    76.     $(patsubst %.mm,%.o,$(wildcard $(SRCDIR)/*.mm)) \  
    77.     $(patsubst %.m,%.o,$(wildcard $(SRCDIR3)/*.m)) \  
    78.     $(patsubst %.c,%.o,$(wildcard $(SRCDIR3)/*.c)) \  
    79.     $(patsubst %.cpp,%.o,$(wildcard $(SRCDIR3)/*.cpp)) \  
    80.     $(patsubst %.m,%.o,$(wildcard *.m))  
    81.   
    82. PCH=$(wildcard *.pch)  
    83. RESOURCES=$(wildcard $(RESDIR)/*)  
    84. NIBS=$(patsubst %.xib,%.nib,$(wildcard *.xib))  
    85.   
    86. all:    dist  
    87.   
    88. $(PROJECTNAME): $(OBJS)  
    89.     $(LD) $(LDFLAGS) -o $@ $^   
    90.   
    91. %.o:    %.m  
    92.     $(ENVP) $(CC) -c $(CFLAGS) $< -o $@  
    93.   
    94. %.o:    %.c  
    95.     $(ENVP) $(CC) -c $(CFLAGS) $< -o $@  
    96.   
    97. %.o:    %.cpp  
    98.     $(ENVP) $(CPP) -c $(CPPFLAGS) $< -o $@  
    99.   
    100. %.o:    %.mm  
    101.     $(ENVP) $(CC) -c $(CFLAGS) $< -o $@  
    102.   
    103. %.nib:  %.xib  
    104.     ibtool $< --compile $@  
    105.   
    106. dist:   $(PROJECTNAME) $(NIBS)  
    107.     rm -rf $(BUILDDIR)  
    108.     mkdir -p $(BUILDDIR)/$(APPFOLDER)  
    109.     cp -r $(RESOURCES) $(BUILDDIR)/$(APPFOLDER)  
    110.     cp Info.plist $(BUILDDIR)/$(APPFOLDER)/Info.plist  
    111.     @echo "APPL????" > $(BUILDDIR)/$(APPFOLDER)/PkgInfo  
    112.     cp -r English.lproj $(BUILDDIR)/$(APPFOLDER)/English.lproj/  
    113.     cp -r zh_CN.lproj $(BUILDDIR)/$(APPFOLDER)/zh_CN.lproj/  
    114.     cp -r zh_HK.lproj $(BUILDDIR)/$(APPFOLDER)/zh_HK.lproj/  
    115.     rm -rf $(BUILDDIR)/$(APPFOLDER)/English.lproj/.svn  
    116.     rm -rf $(BUILDDIR)/$(APPFOLDER)/zh_CN.lproj/.svn  
    117.     rm -rf $(BUILDDIR)/$(APPFOLDER)/zh_HK.lproj/.svn  
    118.     mv $(NIBS) $(BUILDDIR)/$(APPFOLDER)  
    119.     export CODESIGN_ALLOCATE=/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/codesign_allocate; ./ldid_intel -S $(PROJECTNAME)  
    120.     mv $(PROJECTNAME) $(BUILDDIR)/$(APPFOLDER)  
    121.   
    122. installapp: uninstallapp  
    123.     #只上传程序不上传资源, 节省安装时间  
    124.     scp -r $(BUILDDIR)/$(APPFOLDER)/$(PROJECTNAME) root@$(IPHONE_IP):/Applications/$(INSTALLFOLDER)/$(PROJECTNAME)  
    125.     ssh root@$(IPHONE_IP) 'killall SpringBoard'  
    126.   
    127. uninstallapp:   
    128.     #只删除程序  
    129.     ssh root@$(IPHONE_IP) 'rm -fr /Applications/$(INSTALLFOLDER)/$(PROJECTNAME)'  
    130.   
    131. install: uninstall    
    132.     #ssh root@$(IPHONE_IP) 'rm -f /private/var/mobile/Library/Caches/com.apple.mobile.installation.plist'  
    133.     #上传程序及资源  
    134.     scp -r $(BUILDDIR)/$(APPFOLDER) root@$(IPHONE_IP):/Applications/$(INSTALLFOLDER)  
    135.     ssh root@$(IPHONE_IP) 'killall SpringBoard'  
    136.   
    137. uninstall:    
    138.     #删除程序及资源  
    139.     ssh root@$(IPHONE_IP) 'rm -fr /Applications/$(INSTALLFOLDER)'  
    140.   
    141. install_respring:  
    142.     scp respring_arm root@$(IPHONE_IP):/usr/bin/respring  
    143.   
    144. clean:  
    145.     @rm -f $(SRCDIR)/*.o *.o  
    146.     @rm -f $(SRCDIR2)/*.o *.o  
    147.     @rm -f $(SRCDIR3)/*.o *.o  
    148.     @rm -rf $(BUILDDIR)  
    149.     @rm -f $(PROJECTNAME)  
    150.       
    151. log:  
    152.     scp root@$(IPHONE_IP):/var/mobile/appLog ~/Desktop/appLog/appLog  
    153.   
    154. clearlog:  
    155.     ssh root@$(IPHONE_IP) 'rm -fr /var/mobile/appLog'  


  • 0 0
    原创粉丝点击