erlang.mk和makefile语法剖析

1. makefile 基本规则:

1. 所有的源文件没有被编译过,则对各个源文件进行编译并进行链接,生成最后的可执行程序;
2. 每一个在上次执行make之后修改过的源代码文件在本次执行make时将会 被重新编译;
3. 头文件在上一次执行make之后被修改。则所有包含此头文件的源文件在本次执行 make 时将会被重新编译。

2. 基本格式:

TARGET... : PREREQUISITES...
  COMMAND  ...

2.1 target(目标)通常是最后需要生成的文件名或者为了实现这个目的而必需的中间过程文件名。

也可以是一个make执行的动作的名称,如目标“clean”:伪目标(phony target)。

2.2 PREREQUISITES(依赖条件) 生成规则目标所需要的文件名列表。通常一个目标依赖于一个或者多个文件。

2.3 COMMAND(命令行) 任意的shell命令或者是可在shell下执行的程序。

  它限定了make执行这条规则时所需要的动作。可以有多个命令行,每一条命令占一行。

注意:每一个命令行必须以[Tab]字符开始,[Tab]字符告诉 make 此行是一个命令行,make程序本身并不关心命令是如何工作的,对目标文件的更新需要你在规则描述中提供正确的命令。

“make”程序所做的 就是当目标程序需要更新时执行规则所定义的命令。

建议:单目标,多依赖。就是说尽量要做到一个规则中只存在一 个目标文件,可有多个依赖文件。尽量避免使用多目标,单依赖的方式 。

最神奇的就是这三个元素都可以使用变量,变量又可以使用通配符展开。

下面通过erlang.mk这个项目自己的build过程来了解一下最基本makefile的工作步骤:

##makefile
BUILD_CONFIG_FILE ?= $(CURDIR)/build.config
BUILD_CONFIG = $(shell sed "s/\#.*//" $(BUILD_CONFIG_FILE))

ERLANG_MK = erlang.mk
ERLANG_MK_VERSION = $(shell git describe --tags --dirty)

.PHONY: all check

all:
awk ‘FNR==1 && NR!=1{print ""}1‘ $(patsubst %,%.mk,$(BUILD_CONFIG)) | sed ‘s/^ERLANG_MK_VERSION = .*/ERLANG_MK_VERSION = $(ERLANG_MK_VERSION)/‘ > $(ERLANG_MK)

ifeq ($(p),)
check:
$(MAKE) -C test
else
check:
$(MAKE) -C test pkg-$(p)
endif

以上是根据build.config生成给我们项目自己使用的erlang.mk文件 (注意这个并不在build自定义项目,而只是生成erlang.mk,然后用它来build我们自定义的项目),它包括了变量赋值.引用,特殊变量 伪目标,终极目标, 条件语句:

3.1 变量

1. Makefile 中变量和函数的展开(除规则命令行中的变量和函数以外),是在 make 读取 makefile 文件时进行的,这里的变量包括了使用“=”定义和使用指示符 “define”定义的。
2. 变量可以用来代表一个文件名列表、编译选项列表、程序运行的选项参数列表、 搜索源文件的目录列表、编译输出的目录列表和所有我们能够想到的事物。
3. 变量名是不包括“:”、“#”、“=”、前置空白和尾空白的任何字符串。
4. 变量名是大小写敏感的。
5. 另外有一些变量名只包含了一个或者很少的几个特殊的字符(符号)。称它们为 自动化变量。像“$<”、“[email protected]”、“$?”、“$*” 2. 变量的赋值

3.1.1 递归展开式变量

语法:VAR  = Value

BUILD_CONFIG = $(shell sed "s/\#.*//" $(BUILD_CONFIG_FILE))

使用此风格的变量定义,可能会由于出现变量的递归定义而导致make陷入到无限的变量展开过程中,最终使 make 执行失败。如下:

CFLAGS = $(CFLAGS) –O

这种风格的变量定义中如果使用了函数,那么包含在变量值中的 函数总会在变量被引用的地方执行(变量被展开时)。

3.1.2 直接展开式变量

语法  VAR := Value
变量值中对其他量或者函数的引用在定义变量时被展开(对变量进行替换)

x := foo
y := $(x) bar
x := later
# 就等价于:
y := foo bar
 x := later

3.1.3 ?= 操作符

 BUILD_CONFIG_FILE ?= $(CURDIR)/build.config 

只有此变量在之前没有赋值的情况下才会对这个变量进行赋值。

正因为变量只是简单的宏展开,且所有的makefile都是先从头到尾先计算好更新规则后,一次性从终极目标(第一个目标)开始执行的。所以在erlang.mk中才必须core的部分写在编译前面(因为core中定义了大量与编译erl相关的参数)。

3.2 变量的引用

$(BUILD_CONFIG)
#或
${BUILD_CONFIG}

3.3 特殊的变量
$(CURDIR) 此变量代表 make 的工 作目录。当使用“-C”选项进入一个子目录后,此变量将被重新赋值。总之,如果在 Makefile 中没有对此变量进行显式的赋值操作,那么它代表 make 的工作目录。
$(MAKE) 用于递归展开make时MAKE可以带不一样的参数,比如MAKE := /bin/make 在另一个目录就是MAKE := /bin/make -t
3.4 伪目标 
语法 :target不是一个真正的文件名
使用.phony:all check 的原因:避免 目录中有一个文件叫all或check,强制说明这个是伪目标。
3.5 命令行
在 Makefile 中书写在同一行中的多个命令属于一个完整的 shell 命令行,书写在独立行的一条命令是一个独立的 shell 命令行。
如果想在同一个shell中运行多条命令,应该用 \ 连接各个命令。让它成为一行命令。
3.6. 条件语句:

ifeq($(p),)
check:
$(MAKE) -C test
else
check:
$(MAKE) -C test pkg-$(p)
endif 

3.7 shell 命令:

#把BUILD_CONFIG_FILE里面的所有注释去掉。sed ‘s/pattern/replace_string‘ FileName
sed "s/\#.*//" $(BUILD_CONFIG_FILE) 

#表示在除了第一个文件croe/core.mk外,其它的文件第一行都要先加一个空行。1表示返回值为1awk ‘BEGIN{print "start"} pattern{ commands} END{print "end"} file
awk ‘FNR==1 && NR!=1{print ""}1‘ $(patsubst %,%.mk,$(BUILD_CONFIG))
#展开后:
awk ‘FNR==1 && NR!=1{print ""}1‘ core/core.mk index/*.mk core/index.mk core/deps.mk plugins/protobuffs.mk core/erlc.mk core/docs.mk core/test.mk plugins/asciidoc.mk plugins/bootstrap.mk plugins/c_src.mk plugins/ci.mk plugins/ct.mk plugins/dialyzer.mk plugins/edoc.mk plugins/elvis.mk plugins/erlydtl.mk plugins/escript.mk plugins/eunit.mk plugins/relx.mk plugins/shell.mk plugins/triq.mk plugins/xref.mk plugins/cover.mk

awk特殊变量:
 NR:表示记录数量,在执行过程中对应于当前行号
 FNR:表示单个文件的当前行号,在多个文件中不会累加,NR会累加。
3.8 make 内置函数

patsubst %, %.mk,$(BUILD_CONFIG))

把BUILD_CONFIG里面的第行都加上.mk结尾。patsubst是makefile的一个内部函数。

3.9 终极目标

默认的情况下,make执行的是Makefile中的第一个规则,此规则的第一个目标称 之为“最终目的”或者“终极目标”(就是一个Makefile最终需要更新或者创建的目标)。

摘抄博客:http://www.cnblogs.com/zhongwencool/p/erlang_mk.html

时间: 2024-11-05 14:39:24

erlang.mk和makefile语法剖析的相关文章

[Erlang_Question34]erlang.mk的源码阅读1-入门makefile

通过erlang.mk项目,掌握基本的makefile语法,可以自己定制makefile. 1. makefile 基本规则: 1. 所有的源文件没有被编译过,则对各个源文件进行编译并进行链接,生成最后的可执行程序; 2. 每一个在上次执行make之后修改过的源代码文件在本次执行make时将会 被重新编译; 3. 头文件在上一次执行make之后被修改.则所有包含此头文件的源文件在本次执行 make 时将会被重新编译. 2. 基本格式: TARGET... : PREREQUISITES... C

u-boot的Makefile语法教程分析

U-BOOT是一个LINUX下的工程,在编译之前必须已经安装对应体系结构的交叉编译环境,这里只针对ARM,编译器系列软件为arm-linux-*. U-BOOT的下载地址: http://sourceforge.net/projects/u-boot我下载的是1.1.6版本,一开始在FTP上下载了一个次新版,结果编译失败.1.1.6是没问题的. u-boot源码结构    解压就可以得到全部u-boot源程序.在顶层目录下有18个子目录,分别存放和管理不同的源程序.这些目录中所要存放的文件有其规

erlang 符号相关基本语法

http://blog.csdn.net/anghlq/article/details/6803332 ErLang语法约定: 大写字母开头的名字(比如Address),表示一个变量,包括参数.局部变量等: 小写字母开头的单词(比如ok),表示一个常量,叫做atom(原子的意思),包括常量名.函数名.模块名等. ErLang的注释用%开头.ErLang用下划线“_”表示任意变量,类似于Java的switch语法里面的default选项. 参数中没使用到的变量用下杠和首字母大写,如_Sample

Makefile语法基础介绍

在Linux下,make是一个命令工具,是一个解释Makefile中指令的命令工具.make命令执行时,需要一个Makefile文件,以告诉make命令需要怎么样去编译和链接程序. make如何工作:在默认的方式下,只输入make命令,那么: (1).make会在当前目录下找名字叫"Makefile"或"makefile"的文件: (2).如果找到,它会找文件中的第一个目标文件(target),并把这个文件作为最终的目标文件: (3).如果目标文件不存在,或是目标文

Android.mk文件的语法解析

这是RDA8810(Android4.2.2)的Browser模块的Android.mk文件 LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE_TAGS := optional LOCAL_STATIC_JAVA_LIBRARIES := \ android-common \ guava \ android-support-v13 \ android-support-v4 \ LOCAL_SRC_FILES := \

tiny210——uboot移植之Makefile剖析篇

这篇东东早就写好了,一直没时间发出来,现在终于有时间发一下了记录总结uboot的学习历程,好像够详细了,以后忘了也可以再温习回来嘛有些特殊字符显示得乱掉了 Makefile追踪技巧: 技巧1:可以先从编译目标开始顺藤摸瓜地分析,先不要关注具体细节,着重关注主要的代码结构和编译过程 技巧2:追踪分析时要通过文本或者其他途径暂时记录重要的线索 技巧3:将主要的Makefile文件中export出来的变量以及include的文件提取出来,看看include的文件大致是些什么文件,当看到一些来历不明的变

【转】Android.mk文件语法规范(Android.mk File)

原文网址:http://blog.csdn.net/smfwuxiao/article/details/8530742 1.Android.mk文件概述 Android.mk文件用来告诉NDK编译系统,应该如何编译这些源码.更确切地说,该文件其实就是一个小型的Makefile.该文件会被NDK的编译工具解析多次,所以要注意不要过多使用环境变量,以免第一次解析时产生的变量影响后面的解析.Android.mk把源码组织成不同的模块,每个模块可以是一个静态库也可以是一个动态库.动态库才会被拷贝到安装包

工程管理之makefile与自动创建makefile文件过程

(风雪之隅 http://www.laruence.com/2009/11/18/1154.html) Linux Makefile自动编译和链接使用的环境 想知道到Linux Makefile系统的真相么,想知道Linux Makefile系统中藏有的内在奥义么,只有我来给大家全面讲解介绍Linux Makefile系统作为Linux下的程序开发人员,大家一定都遇到过Linux Makefile,用make命令来编译自己写的程序确实是很方便.一般情况下,大家都是手工写一个简单Linux Mak

Erlang cowboy 入门参考

Erlang cowboy 入门参考 cheungmine,2014-10-28 本文翻译自: http://ninenines.eu/docs/en/cowboy/HEAD/guide/getting_started/ 我没有按原文逐句翻译.仅仅是我自己的理解,力求简单明了.本文程序在RHEL6.4上写成并运行,参考下面的文章,安装Erlang: erlang在redhat上的安装 1 引言 Erlang不仅仅是一门语言,更是一个操作平台.Erlang开发者很少写单独的模块,而是写库和程序,然