makefile 基础

makefile 的核心其实只有3句话.

甲.  宏变量. 乙.依赖关系. 丙. 构建命令

不妨理解为宏语句,依赖语句,命令语句. 还有一个条件语句.

========================================
甲: makefile 的 变量赋值, 包含等号的语句为宏语句.
========================================
1、“=” 最后计算展开后赋值
      make会将整个makefile展开后,再决定变量的值。也就是说,变量的值将会是整个makefile中最后被指定的值。看例子:
            x = foo
            y = $(x) bar
            x = xyz
      在上例中,y的值将会是 xyz bar ,而不是 foo bar 。

2、“:=” 立即赋值
      “:=”表示变量的值决定于它在makefile中的位置,而不是整个makefile展开后的最终值。
            x := foo
            y := $(x) bar
            x := xyz
      在上例中,y的值将会是 foo bar ,而不是 xyz bar 了。

?= 是如果没有被赋值过就赋予等号后面的值
    TEMP ?= var
    ifeq($(TEMP),undefined)
        TEMP = var
        endif


+= 是添加等号后面的值

========================================
乙: makefile 依赖关系, 包含冒号":"的语句为依赖语句.
========================================

依赖关系是形如x:y, 则说y依赖与x, 当y比较新时,要执行构建命令.

依赖关系要构成一个完整的链.


----------------------------------------
有问题的最简单的Makefile
----------------------------------------
all:
    gcc  -o main main.o
main.o: main.c
    gcc -c -o main.o main.c
clean:
    rm *.o main

运行make, 提示如下错误:
gcc  -o main main.o
gcc: main.o: No such file or directory
gcc: no input files
make: *** [all] Error 1

我很奇怪,不是告诉它main.o 依赖main.c 吗,按定义的规则去生成。
而且我查看了make -d 的输出,发现其并没有继续检查main.o 的依赖关系。
后来我对比了正确的makefile 写法, 发现要把main.o 写在all 的右边才能作为依赖
才能使makefile继续检查它的生成关系。
如果你使用隐含规则,甚至不用写.c 生成.o 的规则。
----------------------------------------
下面是正确的写法:all 右边有依赖
----------------------------------------
all:main.o
    gcc  -o main main.o
clean:
    rm *.o main
运行make 的结果:
[root@hjj /home/samba/testapp]# make
cc    -c -o main.o main.c
gcc  -o main main.o

========================================
丙: make 命令语句.(以tab开始的bash命令)
========================================

命令就是bash 命令,所以你可以使用bash 语言的一些技巧而不仅仅是执行一条命令.

========================================
丁: 除了上边3类语句,makefile 还有条件语句,其功能类似于c语言的条件编译.
========================================

<conditional-directive>
<text-if-true>
else
<text-if-false>
endif

条件语句有ifeq, ifneq, ifdef, ifndef

条件是一个变量是否定义及值(字符串值)是否相等.
句法书写举例:
ifeq(argv1,argv2)          # 字符串不用加单引号或双引号
ifdef(variable-name)        # 不能加$, 是变量名字
举例:
如果 strip 函数返回值为空
ifeq($(strip $(foo)),)
xxx
endif


给个例子:
[~/test]$ cat Makefile
foo=abc
ifdef foo
$(warning foo defined)
endif

========================================
makefile 执行的两个阶段
========================================

第一阶段:读取所有的makefile文件(包括 include 项,命令行 选项)
   内建所有的变量、明确规则和隐含规则,
   并建立所有目标和依赖之间的依赖关系结构链表。

第二阶段:根据第一阶段已经建立的依赖关系结构链表决定哪些目标需要更新,并使用对应的规则来重建这些目标

========================================
makefile 调试
========================================

调试就是试图监视到make的执行过程, 保证它能够按我们预定的执行过程来运行.


$(warning)函数
它可以放在makefile 中的任何地方:
开始的位置、工作目标或必要条件列表中以及命令脚本中。
这让你能够在最方便的地方查看变量的输出值

实际上就两个地方, 宏语句中和命令语句中.

========================================
对make 的控制, make 命令的参数.
========================================

-n 或“--just-print”,那么其只是显示命令,但不会执行命令,
这个功能很有利于我们调试我们的Makefile,

-p 或(--print-data-base) 是另一个你常会用到的选项。显示make 所运行的命令, 然后输出它的内部数据库。
数据库里的数据将会依种类划分

    成以下几个部分:
    variables:  有4种, 环境变量(enviroment),自动变量(automatic),默认变量(default),makefile 中定义的变量.
    implicit rules. 默认的类型依赖关系及处理法则
    target . .default_goal 是默认的维护目标
 
-d 是另一个有用的选项。 大量的信息可能让人眼花。


“-s”或“--slient”则是全面禁止命令的显示。  控制命令回显。
makefile 以tab开头表示命令,

当我们用“@”字符在命令行前,那么,这个命令将不被make显示出来. 为了向屏幕少输出信息。

令makefile 不包含内部默认规则 make -r 即可.
********************************************************************************

linux makefile 的 V=1 起了什么作用?
makefile 可以在命令行为宏变量赋值, 这实际上是从命令行为宏变量V设置了值V=1,以后就可以用$V来引用了.
ifeq ("$(origin V)", "command line")
KBUILD_VERBOSE = $(V)
endif

ifndef KBUILD_VERBOSE
KBUILD_VERBOSE = 0
endif
********************************************************************************
--------------------------------

如何调试makefile变量

--------------------------------

网上看到的一段代码。编写如下一段show_vars.mak

%:
	$(warning '$*=$($*)')
d-%:
	$(warning '$*=$($*)')
	$(warning  origin = $(origin $*))
	$(warning  value = $(value  $*))
	$(warning  flavor = $(flavor $*))

这里% 就是来替换你的目标,就是命令行上你指定的变量,$* 为茎,对于不带.后缀的目标,$*就等于%, 就是变量, $($*) 就是变量引用,这样就显示了变量及变量定义。

d-% 将对变量有更详细的显示。 用户可搜索“如何调试makefile变量” 找到实验例子,这里就不赘述了。

用法: make -f <你的makefile> -f show_vars.mak <预显示的变量>

用remake 可以调试Makefile, 类似于gdb 操作,但需要慢慢熟悉起来.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值