目录
首发于:
最近更新于:
分类: archived

简单了解下makefile

makefile一般只能在Linux环境下运行,更确切来说要有gnu make这个工具去运行Makefile这个文件。

makefile里面内容其实很丰富的,实际上甚至有点过于复杂了。不过有的时候只是简单使用其基本功能还是很便利的。

project=helloworld
cflags=-g -Wall  ${CCFLAGS}

${project}: 
    ${CC}  helloworld.c -o $@ ${cflags}

clean:
    rm ${project}

install:
    cp ${project} /usr/local/bin

uninstall:
    rm /usr/local/bin/${project}

.PHONY:
    clean uninstall install

为了便于理解,上面这个makefile我有意采用了一种和bash shell接近的风格。前面 project= 就是一个定义变量的行为。这个project变量就是本脚本的名字。然后makefile下面的主体部分格式如下:

target: prerequisites
    the command

具体意思就是要生成target这个文件,首先要确保prerequisites这些依赖文件都在而且是最新的,不在或者不是最新的那么查找对应的目标生成规则继续生成。而对于这个target的生成就是执行下面的bash命令。下面是关于上面例子的一些讲解信息:

  • 特别要强调,命令前面请用 Tab键 隔开
  • 关于变量的使用读者看到上面的例子,我有意采用了类似bash脚本的语法。这么写也是支持的。
  • $@ 这个特殊的符号并不是什么神秘东西,其意思就是当前目标的文件名,上面例子中当前目标是 ${target} ,也就是helloworld,所以这里 $@ 就是 "helloworld" 。
  • .PHONY 这后面跟着一些生成目标,具体意思就是这些生成目标是伪目标,或者说其并没有生成文件,只是执行了某个命令。
  • 我们注意到上面的${CC}${CCFLAGS} 并没有为用户定义,其是make命令的一些默认变量。 $(CC) 就是调用系统默认的c编译器,一般为gcc。
  • make 命令不输入任何子命令时,默认执行输出第一个目标命令,一般是本项目目标。
  • makefile的每个命令都有一个独立的终端,也就是不同的终端不共享变量,所以最好多个命令连接成为一个命令,这样好在一个shell里面执行和共享变量。(export是可以共享的?)
  • makefile扫描两边,第一遍变量替换,第二遍依赖关系。变量声明最好跟着对应的规则,还有要保证不能被后面的变量声明改变。

强制某个目标更新

参考了 这个网页

大致如下面所示,设置一个 FORCE 目标,凡是依赖FORCE目标的都将强制没一次都再更新一遍,而原因就是因为这个FORCE目标不不依赖任何目标,这样makefile认为目标不存在,而每次都会再更新生成一遍。

${project}.org: FORCE
    python3 make_${project}org.py
FORCE: