zoukankan      html  css  js  c++  java
  • makefile示例

    一、Makefile 基本结构

      Makefile 是make读入的唯一配置文件,

    i:由make工具创建的目标体(target),通常是目标文件或可执行文件

    ii:要创建的目标体所依赖的文件(dependency_file)

    iii:要创建每个目标体时需要运行的命令(command)

    注意命令行前面必须是一个“TAB键”,否则编译错误为:*** missing separator.    Stop.

    Makefile格式

    target: dependency file
    <TAB>command

    例子:

    hello.o: hello.c hello.h
        gcc -c hello.c -o hello.o

    二:Makefile变量

     下面有一个例子:

    temp:f1.o f2.o main.o
      gcc f1.o f2.o main.o -o temp
    f1.o:f1.c f1.h
      gcc -Wall -O -g -c f1.c -o f1.o
    f2.o:f2.c f2.h
      gcc -Wall -O -g -c f2.c -o f2.o
    main.o:main.c
      gcc -Wall -O -g -c main.c -o main.o
    .PHONY : clean
    clean:
      rm *.o temp

    注释:-Wall:表示允许发出gcc所有有用的报警信息

          -c:只是编译不链接,生成目标文件“ .o”

       -o file:表示把输出文件输出到file里

      更多的用man工具

    1、变量定义

    变量定义的方式: VAR=var       VAR:=var
    
    变量使用: $(VAR)

    类似于编程语言的宏;
    如果你要使用真实的“$”字符,那么你需要写成“$$”
    OBJS = f1.o f2.0 main.o
    CC = gcc
    CFLAGS = -Wall -O -g
    
    temp:$(OBJS)
      $(CC) $(OBJS) -o temp
    f1.o:f1.c f1.h
      $(CC) $(CFLAGS) -c f1.c -o f1.o
    f2.o:f2.c f2.h
      $(CC) $(CFLAGS) -c $< -o $@
    main.o:main.c
      $(CC) $(CFLAGS) -c main.c -o main.o
    .PHONY : clean
    clean:
      rm *.o temp


    .PHONY : clean  
      比如“clean”这个目标,一个“伪目标”,我们并不生成“clean”这个文件。“伪目标”并不是一个文件,只是一个标签,由于“伪目标”

    不是文件,所以make无法生成它的依赖关系和决定它是否要执行。我们只有通过显式地指明这个“目标”才能让其生效。

    当然,“伪目标”的取名不能和文件名重名,不然其就失去了“伪目标”的意义了。

      当然,为了避免和文件重名的这种情况,我们可以使用一个特殊的标记“.PHONY”来显式地指明一个目标是“伪目标”,向make说明,

    不管是否有这个文件,这个目标就是“伪目标”。

    2、追加变量值

    追加变量值:我们可以使用“+=”操作符给变量追加值
    如果变量之前没有定义过,那么,“+=”会自动变成“=”,如果前面有变量定义,那么“+=”会继承于前次操作的赋值符。

    OBJS = f1.o f2.0 main.o
    OBJS += f3.o

    3、自动化变量

    $@   表示规则中的目标文件集。在模式规则中,如果有多个目标,那么,"$@"就是匹配于目标中模式定义的集合。
    $<   依赖目标中的第一个目标名字。如果依赖目标是以模式(即"%")定义的,那么"$<"将是符合模式的一系列的文件集。注意,其是一个一个取出来的。
    $%   仅当目标是函数库文件中,表示规则中的目标成员名。例如,如果一个目标是"foo.a(bar.o)",那么,"$%"就是 "bar.o""$@"就是"foo.a"。如果目标
         不是函数库文件(Unix下是[.a],Windows下是[.lib]),那么,其值为空。
    $?   所有比目标新的依赖目标的集合。以空格分隔。
    $^   所有的依赖目标的集合。以空格分隔。如果在依赖目标中有多个重复的,那个这个变量会去除重复的依赖目标,只保留一份。
    $+   这个变量很像"$^",也是所有依赖目标的集合。只是它不去除重复的依赖目标。

    4、变量中的变量

    foo = $(bar)
    bar = $(ugh)
    ugh = Huh?
    $(foo)的值为Huh?
    echo $(foo)来进行查看 

    5、条件变量

    还有一个比较有用的操作符是“?=”,先看示例: 

     FOO ?= bar

    其含义是,如果FOO没有被定义过,那么变量FOO的值就是“bar”,如果FOO先前被定义过,那么这条语句将什么也不做,其等价于:

    ifeq ($(origin FOO), undefined)
      FOO = bar
    endif

    6、关于命令的变量

    AR    函数库打包程序。默认命令是“ar”。
    AS    汇编语言编译程序。默认命令是“as”。
    CC    C语言编译程序。默认命令是“cc”。
    CXX   C++语言编译程序。默认命令是“g++”。
    CO    从 RCS文件中扩展文件程序。默认命令是“co”。
    CPP   C程序的预处理器(输出是标准输出设备)。默认命令是“$(CC) –E”。
    RM   删除文件命令。默认命令是“rm –f”

    7、关于命令参数的变量

    ARFLAGS    函数库打包程序AR命令的参数。默认值是“rv”。
    ASFLAGS    汇编语言编译器参数。(当明显地调用“.s”或“.S”文件时)。
    CFLAGS     C语言编译器参数。
    CXXFLAGS   C++语言编译器参数。
    COFLAGS    RCS命令参数。
    CPPFLAGS   C预处理器参数。( C 和 Fortran 编译器也会用到)
    LDFLAGS   链接器参数。(如:“ld”)

    如下面的例子:

    CROSS_COMPILE =                             #指定编译器种类,为空,使用的就是gcc;类似于arm_linux_gnu_
    LDFLAGS := -lm -lfreetype -lvga                         #指定编译器链接(根据实际项目手动修改)
    TARGET := show_file #编译后的程序名(根据实际项目手动修改)
    CFLAGS = -Wall -O -g

    CC = $(CROSS_COMPILE)gcc
    STRIP = $(CROSS_COMPILE)strip #优化工具
    OBJCOPY = $(CROSS_COMPILE)objcopy
    OBJDUMP = $(CROSS_COMPILE)objdump
    OBJS:= $(patsubst %.c, %.o, $(SRC))
    all :$(OBJS)
      $(CC) $(OBJS) -o $(TARGET) $(LDFLAGS)  #将编译好的 .o文件链接生成我们的目标文件
    %.o: %.c
      $(CC) $(CFLAGS) -c $< -o $@
    .PHONY : clean
    clean:
      rm *.o temp

    目标中的"%"定义表示对文件名的匹配,"%"表示长度任意的非空字符串。例如:"%.c"表示以".c"结尾的文件名

    三、make参数

    “-I <dir>” 指定一个被包含 makefile 的搜索目标。可以使用多个“-I”参数来指定多个目录

    CFLAGS += -I include

    Makefile里面获取相对路径必须在pwd前面加shell,然后把shell pwd当一个变量来引用,书写形式是:$(shell pwd),比如说:

    CFLAGS  += -I$(shell pwd)/include

     

    四、关键字

     1、模式字符串替换函数——patsubst

    $(patsubst <pattern>,<replacement>,<text>) 
    • 功能:查找<text>中的单词(单词以“空格”、“Tab”或“回车”“换行”分隔)是否符合模式< pattern>,如果匹配的话,则以<replacement>替换。这里,<pattern>可以包括通配符 “%”,表示任意长度的字串。如果<replacement>中也包含“%”,那么,<replacement>中的这个 “%”将是<pattern>中的那个“%”所代表的字串。(可以用“”来转义,以“\%”来表示真实含义的“%”字符)
    • 返回:函数返回被替换过后的字符串
    $(patsubst %.c,%.o,x.c bar.c)

    把字串“x.c bar.c”符合模式 %.c 的单词替换成 %.o ,返回结果是“x.o bar.o”

     2、扩展通配符------wildcard

    在Makefile规则中,通配符会被自动展开。但在变量的定义和函数引用时,通配符将失效。这种情况下如果需要通配符有效,就需要使用函数“wildcard”

    一般我们可以使用“$(wildcard *.c)”来获取工作目录下的所有的.c文件列表。

    可以使用“$(patsubst%.c,%.o,$(wildcard *.c))”,首先使用“wildcard”函数获取工作目录下的.c文件列表;之后将列表中所有文件名的后缀.c替换为.o

    这样我们就可以得到在当前目录可生成的.o文件列表。

    SRC = $(wildcard *.c)  $(wildcard app/*.c)
    OBJS:= $(patsubst %.c, %.o, $(SRC))

    推荐好文:跟我一起写Makefile

  • 相关阅读:
    Zookeeper搭建集群及协同
    无限可能,Elasticsearch(一)
    如何打造一款m3u8视频爬虫
    垃圾如何进行自救
    必知必会的JavaJDK工具
    如何在局域网内开一家电影院
    谈谈网络游戏中的延迟解决方案
    简述一致性哈希算法
    Python网络爬虫实战(五)批量下载B站收藏夹视频
    Python网络爬虫实战(四)模拟登录
  • 原文地址:https://www.cnblogs.com/listxue/p/12826708.html
Copyright © 2011-2022 走看看