zoukankan      html  css  js  c++  java
  • Makefile基础(二)

    上一章:C语言之Makefile基础(一)

    上一章的Makefile写的中规中矩,比较繁琐,是为了讲清楚基本概念,其实Makefile有很多灵活的写法,可以写的更简洁,同时减少出错的可能

    一个目标依赖的所有条件不一定非得写在一个规则中,也可以拆开来写,例如:

    main.o: main.h stack.h maze.h
    main.o: main.c
    	gcc -c main.c
    

      

    就相当于:

    main.o: main.c main.h stack.h maze.h
    	gcc -c main.c
    

        

    如果一个目标拆开写多条规则,其中只有一条规则允许有命令列表,其他规则应该没有命令列表,否则make会报警告并采用最后一条规则的命令列表。

    于是,之前的Makefile文件我们还可以写成这样:

    main: main.o stack.o maze.o
    	gcc main.o stack.o maze.o -o main
    main.o: main.h stack.h maze.h
    stack.o: stack.h main.h
    maze.o: maze.h main.h
    main.o: main.c
    	gcc -c main.c
    stack.o: stack.c
    	gcc -c stack.c
    maze.o: maze.c
    	gcc -c maze.c
    clean:
    	-rm main *.o
    .PHONY: clean
    

      

    这样虽然也允许执行,但相比以前更繁琐了些,于是我们把提出来的三条规则删去,写成:

    main: main.o stack.o maze.o
    	gcc main.o stack.o maze.o -o main
    main.o: main.h stack.h maze.h
    stack.o: stack.h main.h
    maze.o: maze.h main.h
    clean:
    	-rm main *.o
    .PHONY: clean
    

      

    这样就比原来简单多了,可是现在main.o、stack.o和maze.o这三个目标连编译命令都没有了,怎么编译呢?试试看:

    [root@localhost linux_c]# make
    cc    -c -o main.o main.c
    cc    -c -o stack.o stack.c
    cc    -c -o maze.o maze.c
    gcc main.o stack.o maze.o -o main
    

      

    现在解释一下前三条编译命令怎么来的。如果一个目标在Makefile中的所有规则都没有命令列表,make会尝试在内建的隐含规则数据库中查找适用的规则。make的隐含规则数据库可以用make -p命令来打印,打印出来的格式也是Makefile的格式,包含很多变量和规则,其中和我们这个例子有关的隐含规则有:

    # default
    OUTPUT_OPTION = -o $@
    # default
    CC = cc
    # default
    COMPILE.c = $(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c
    %.o: %.c
    # commands to execute (built-in):
    	$(COMPILE.c) $(OUTPUT_OPTION) $<
    

      

    #号在Makefile中表示单行注释。CC是一个Makefile变量,用CC = cc定义和赋值,用$(CC)取它的值,其值应该是cc。Makefile变量像C的宏定义一样,代表一串字符,在取值的地方展开。cc是一个符号链接,通常指向gcc,在有些Unix系统上可能指向另外一种C编译器

    [root@localhost linux_c]# which cc
    /usr/bin/cc
    [root@localhost linux_c]# ls -l /usr/bin/cc 
    lrwxrwxrwx. 1 root root 3 Feb 13 11:13 /usr/bin/cc -> gcc
    

      

    在make -p中包含这一段定义:

    # default
    COMPILE.c = $(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c
    %.o: %.c
    # commands to execute (built-in):
    	$(COMPILE.c) $(OUTPUT_OPTION) $<
    

        

    CFLAGS这个变量没有定义,$(CFLAGS)展开是空,CPPFLAGS和TARGET_ARCH也是如此,这样,$(COMPILE.c)展开应该是cc 空 空 空 -c,去掉“空”就得到cc -c。所以,%.o: %.c规则的命令 $(COMPILE.c) $(OUTPUT_OPTION) $<展开之后为cc -c -o $@ $<,和上面的编译命令很接近了

    $@和$<是两个特殊的变量,$@的取值为规则中的目标,$<的取值为规则中的第一个条件。 %.o:%.c是一种特殊的规则,称为模式规则,我们再来回顾一下整个过程,在我们的Makefile中,以main.o为目标的规则都没有命令列表,所以make会查找隐含规则,发现隐含规则中有一条模式规则适用main.o符合%.o模式,%代表main,以.o结尾的文件,再替换到%.c中就是main.c,所以,这条规则相当于:

    main.o: main.c
    	cc -c -o main.o main.c
    

      

    同理:

    stack.o: stack.c
    	cc -c -o stack.o stack.c
    

      

    maze.o也同样处理。这三条规则可以由make的隐含规则推导出来,所以就不必写在Makefile中了

    先前我们写Makefile都是以目标为中心,一个目标依赖若干条件,现在换个角度,以条件为中心,Makefile还可以这么写:

    main: main.o stack.o maze.o
    	gcc main.o stack.o maze.o -o main
    main.o stack.o: main.h
    main.o maze.o: maze.h
    main.o stack.o: stack.h
    clean:
    	-rm main *.o
    .PHONY: clean
    

        

    写规则的目的是让make建立依赖关系图,不管怎么写,只要把所有的依赖关系描述清楚就行,对于多目标的规则,make会拆成几条单目标的规则来处理,例如:

    target1 target2: prerequisite1 prerequisite2
    	command $< -o $@
    

      

    这样的规则相当于:

    target1: prerequisite1 prerequisite2
    	command prerequisite1 -o target1
    target2: prerequisite1 prerequisite2
    	command prerequisite1 -o target2
    

      

    注意这两条规则的命令列表是一样的,但$@的取值不同

  • 相关阅读:
    6-8 Percolate Up and Down (20分)
    6-7 Isomorphic (20分)
    6-5 Evaluate Postfix Expression (25分)
    服务器磁盘满无法释放空间解析及解决
    必会的MySQL操作方法
    Tomcat基本安装和优化方法
    Nginx常用配置及优化安全
    Redis笔记整理(三):进阶操作与高级部分
    Redis笔记整理(二):Java API使用与Redis分布式集群环境搭建
    Redis笔记整理(一):Redis安装配置与数据类型操作
  • 原文地址:https://www.cnblogs.com/beiluowuzheng/p/9266463.html
Copyright © 2011-2022 走看看