• GNU make学习,入门与技巧


    1. make文件语法的基本结构:
      目标:依赖的文件
      <Tab>编译规则
      目标,是要生成的文件的名字。如,main.o, input.o, myapp.exe等
      依赖的文件,是生成目标时使用到的一些目标文件,和头文件,如iput.o input.h, ……
      编译规则,就是生成目标是使用的编译命令,如gcc –c intput.c

    2. 规则所在的行要以Tab开头;

    3. 注释以#开头到行尾;

    4. 宏(变量)的设定:MACRONAME=value。
         使用:$(MACRONAME)或者${MACRONAME},有些还支持$MACRONAME,使用时可以写入makefile文件中,也可以在命令中使用,
          如:make CC=c89;还有内置  宏:

       $?, 列出当前目标所依赖的文件列表中比当前的目标文件还要新的文件

       $@, 当前目标的名字

       $<, 当前依赖文件的名字

      $*, 不包括后缀名的当前依赖文件的名字

    5. make –p 打印make命令的内置规则

    6. gcc –MM filename,用来生成与文件filename有依赖关系的文件;

    7. 多行使用(\)来续行;

    8. 如果目标文件的名字和源文件的名字相同(correspondingly ),就可以简化规则。
        如: main.o : main.c defs.h
                        cc -c main.c
         可以改为:main.o : defs.h

    9. 进一步简化规则,在每个头文件前面加入和头文件有关的目标文件,如:
                     kbd.o command.o files.o : command.h

    10. 文件搜索功能,特殊变量VPATH用来指定搜索路径,
            如:VPATH = src:../headers 。表示在src和../headers中搜索(以冒号分隔)。
            还可以使用vpath(小写)用来实现功能,方法有:
            1、vpath<pattern><directories>, 为符合模式<pattern>的文件指定搜索目录<directories>,
                如: vpath %.h ../headers, 头文件在../headers 中搜索(如果当前目录没有的话)
           2、vpath <pattern>用来清除符合模式<pattern>的文件搜索目录
           3、vpath, 清除所有已设置的文件搜索目录

    11. 清除功能:
        .PHONY : clean
        clean :
         -rm edit $(objects)
          this rule will not run at all if we give the command ‘make’ with no arguments. In order to make the rule run, we have to type ‘make clean’.,
          (正常情况下不会使用清除功能,只有我们明确使用make clean,时会清除)。

    12. 未指定makefile的文件,默认的搜索次序:GNUmakefile, makefile and Makefile。推荐使用Makefile,因为可以在文件列表的前面,
          自己指定Makefile文件可以用:-f’ or ‘--file’.如:【-f mkfile.mk】。

    13. 同时make中还可以使用函数,如:subst,dir等;使用控制语句,ifeq,foreach等。

    一个简单实例:

    === makefile 开始 ===
    OBJS = file1.o file2.o
    CC = gcc
    CFLAGS = -Wall -O -g
    helloworld : $(OBJS)
    $(CC) $(OBJS) -o helloworld
    file1.o : file1.c file2.h
    $(CC) $(CFLAGS) -c file1.c -o file1.o
    file2.o : file2.c file2.h
    $(CC) $(CFLAGS) -c file2.c -o file2.o

    clean:

    rm -rf *.o helloworld
    === makefile 结束 ===

    14. 一个经典的例子:
    === makefile 开始 ===
    ######################################
    #
    # Generic makefile
    #
    # by George Foot
    # email: george.foot@merton.ox.ac.uk
    #
    # Copyright (c) 1997 George Foot
    # 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.
    # 你可以随便更改和散发这个文件
    # 而不需要给原作者什么荣誉。
    # (你好意思?)
    #
    ######################################
    ### Customising
    # 用户设定
    #
    # Adjust the following if necessary; EXECUTABLE is the target
    # executable's filename, and LIBS is a list of libraries to link in
    # (e.g. alleg, stdcx, iostr, etc). You can override these on make's
    # command line of course, if you prefer to do it that way.
    #
    # 如果需要,调整下面的东西。 EXECUTABLE 是目标的可执行文件名, LIBS
    # 是一个需要连接的程序包列表(例如 alleg, stdcx, iostr 等等)。当然你
    # 可以在 make 的命令行覆盖它们,你愿意就没问题。
    #
    EXECUTABLE := mushroom.exe
    LIBS := alleg
    # Now alter any implicit rules' variables if you like, e.g.:
    #
    # 现在来改变任何你想改动的隐含规则中的变量,例如
    CFLAGS := -g -Wall -O3 -m486
    CXXFLAGS := $(CFLAGS)
    # The next bit checks to see whether rm is in your djgpp bin
    # directory; if not it uses del instead, but this can cause (harmless)
    # `File not found' error messages. If you are not using DOS at all,
    # set the variable to something which will unquestioningly remove
    # files.
    #
    # 下面先检查你的 djgpp 命令目录下有没有 rm 命令,如果没有,我们使用
    # del 命令来代替,但有可能给我们 'File not found' 这个错误信息,这没
    # 什么大碍。如果你不是用 DOS ,把它设定成一个删文件而不废话的命令。
    # (其实这一步在 UNIX 类的系统上是多余的,只是方便 DOS 用户。 UNIX
    # 用户可以删除这5行命令。)
    ifneq ($(wildcard $(DJDIR)/bin/rm.exe),)
    RM-F := rm -f
    else
    RM-F := del
    endif
    # You shouldn't need to change anything below this point.
    #
    # 从这里开始,你应该不需要改动任何东西。(我是不太相信,太NB了!)
    SOURCE := $(wildcard *.c) $(wildcard *.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)))
    CPPFLAGS += -MD
    .PHONY : everything deps objs clean veryclean rebuild
    everything : $(EXECUTABLE)
    deps : $(DEPS)
    objs : $(OBJS)
    clean :
      @$(RM-F) *.o
      @$(RM-F) *.d
    veryclean: clean
      @$(RM-F) $(EXECUTABLE)
    rebuild: veryclean everything
    ifneq ($(MISSING_DEPS),)
    $(MISSING_DEPS) :
      @$(RM-F) $(patsubst %.d,%.o,$@)
    endif
    -include $(DEPS)
    $(EXECUTABLE) : $(OBJS)
      gcc -o $(EXECUTABLE) $(OBJS) $(addprefix -l,$(LIBS))
    === makefile 结束 ===
    有几个地方值得解释一下的。首先,我在定义大部分变量的时候使 用的是 := 而不是 = 符号。它的作用是立即把定义中参考到的函 数和变量都展开了。如果使用 = 的话,函数和变量参考会留在那 儿,就是说改变一个变量的值会导致其它变量的值也被改变。例 如:
    A = foo
    B = $(A)
    # 现在 B 是 $(A) ,而 $(A) 是 'foo' 。
    A = bar
    # 现在 B 仍然是 $(A) ,但它的值已随着变成 'bar' 了。
    B := $(A)
    # 现在 B 的值是 'bar' 。
    A = foo
    # B 的值仍然是 'bar' 。
    make 会忽略在 # 符号后面直到那一行结束的所有文字。
    ifneg...else...endif 系统是 makefile 里让某一部分码有条件的 失效/有效的工具。 ifeq 使用两个参数,如果它们相同,它把直 到 else (或者 endif ,如果没有 else 的话)的一段码加进 makefile 里;如果不同,把 else 到 endif 间的一段码加入 makefile (如果有 else )。 ifneq 的用法刚好相反。
    'filter-out' 函数使用两个用空格分开的列表,它把第二列表中所 有的存在于第一列表中的项目删除。我用它来处理 DEPS 列表,把所 有已经存在的项目都删除,而只保留缺少的那些。
    我前面说过, CPPFLAGS 存有用于隐含规则中传给预处理器的一些 旗标。而 -MD 开关类似 -M 开关,但是从源码文件 .c 或 .cc 中 形成的文件名是使用后缀 .d 的(这就解释了我形成 DEPS 变量的 步骤)。DEPS 里提到的文件后来用 '-include' 加进了 makefile 里,它隐藏了所有因文件不存在而产生的错误信息。
    如果任何依靠文件不存在, makefile 会把相应的 .o 文件从磁碟 上删除,从而使得 make 重建它。因为 CPPFLAGS 指定了 -MD , 它的 .d 文件也被重新产生。
    最后, 'addprefix' 函数把第二个参数列表的每一项前缀上第一 个参数值。
    这个 makefile 的那些目的是(这些目的可以传给 make 的命令行 来直接选用):
    everything:(预设) 更新主要的可执行程序,并且为每一个 源码文件生成或更新一个 '.d' 文件和一个 '.o' 文件。
    deps: 只是为每一个源码程序产生或更新一个 '.d' 文件。
    objs: 为每一个源码程序生成或更新 '.d' 文件和目标文件。
    clean: 删除所有中介/依靠文件( *.d 和 *.o )。
    veryclean: 做 `clean' 和删除可执行文件。
    rebuild: 先做 `veryclean' 然后 `everything' ;既完全重建。
    除了预设的 everything 以外,这里头只有 clean , veryclean , 和 rebuild 对用户是有意义的。
    我还没有发现当给出一个源码文件的目录,这个 makefile 会失败的 情况,除非依靠文件被弄乱。如果这种弄乱的情况发生了,只要输入 `make clean' ,所有的目标文件和依靠文件会被删除,问题就应该 被解决了。当然,最好不要把它们弄乱。如果你发现在某种情况下这 个 makefile 文件不能完成它的工作,请告诉我,我会把它整好的。

     

    参考:

    http://www.linuxsir.org/main/doc/gnumake/GNUmake_v3.80-zh_CN_html/index.html

    http://www.gnu.org/software/make/manual/make.html

    http://www.huihoo.org/gnu/linux/gmake.html

    http://hi.baidu.com/cui1206/blog/item/54826ba45e16cef29152ee67.html

    http://www.cnblogs.com/goodcandle/archive/2005/11/17/278702.html

    http://www.cnblogs.com/skyivben/archive/2009/12/27/1633524.html

  • 相关阅读:
    (一)linux 系统命令与文件
    python(1)- 初识python
    四、计算机硬件知识整理
    三、计算机硬件历史
    二、网络基础之网络协议
    jmeter while循环使用
    gitlab分支管理
    gitlab基本操作
    JAVA多种向influxDB中插入数据方式
    JAVA类变量和实例变量
  • 原文地址:https://www.cnblogs.com/hustlijian/p/2072836.html
Copyright © 2020-2023  润新知