makefile学习(一)

GNU Make简介

make是Unix和其他操作系统上最持久的工具之一。自1970年问世以来,make至今仍旧是大多数项目开发的核心工具,它甚至被用来编译Linux内核。 简单是make的设计理念,在你变更源代码文件之后,想重新编译你的程序或者其他输出文件之际,make会检查时间戳,找出被变更的文件并进行必要的重 编译动作。 GNU make这一版本已经成为make程序的行业标准。本文将介绍GNU make的用法和使用技巧。首先介绍一下GNU make的基本用法,接着介绍通配符的使用,最后介绍一下如何利用make组织你的项目文件目录。

基本语法

make描述文件的文件名为makefile、Makefile、GNUMakefile。为了简单起见,我们统一使用makefile。 makefile的文件一般采用“从上到下”的结构,下层工作目标用来让上层工作目标保持在最新的状态。下面是makefile的基本语法结构:

target1 target2 target3 : prerequisite1 prerequisite2
command1
command2
command3

冒号左边可以是一个或者多个工作目标,右边可以是零个或者多个必要条件。更新工作目标会执行一条或者多条命令,且每个命令必须以TAB开头。需要注意的是不能在非命令行的第一个字符前输入一个TAB,否则make会将其后的文字作为命令来解释。 另外如果一行文本太长,可以使用标准的反斜线分隔为多行。

规则

假想工作目标

假想工作目标就是贴上标签的工作目标,它把一个或者多个工作目标归类,几乎成为makefile里面的必备元素。表1是一些常用的假想工作目标。

表1 常用的假想工作目标

工作目标功能
all执行编译应用程序的所有工作
install从已编译的二进制文件进行应用程序的安装
clean将编译产生的二进制文件删除
check执行与应用程序相关的任何测试
info从Texinfo源代码来创建GNU info文件
变量

make的变量来自以下几个来源:

  • 文件,直接在makefile里面定义
  • 命令行参数传入
  • 环境变量
  • make自动创建的变量

简单变量的具体语法:

$(variable-name)

表2是GNU make的核心自动变量列表:

表2 核心自动变量

自动变量含义
$@工作目标的文件名
$%档案文件成员结构中的文件名
$<第一个必要条件的文件名
$^所有必要条件的文件名,用空格隔开
$+所有必要条件的文件名,用空格隔开,包括重复的文件名
$*工作目标的主文件名
模式规则

许多程序在读取文件以及输出文件时都会有惯例。比如,所有的C编译器都会假设:文件以.c为扩展名,目标文件以.o为扩展名。我们可以利用GNU make提供的模式规则来简化规则的建立。例如,从一个.c文件编译出一个.o文件,下面的模式规则实现这一功能:

%.o: %.c
$(CC) -c $<
指令

在makefile开始复杂起来的时候,一些实用的指令是必须的,下面介绍二个常用的指令:

  • 条件指令

    下面是基本语法的样例:

    libtools.a: $(tools_objects)
    $(AR) $(ARFLAGS) $@ $<
    ifdef GUILIB
    $(GUILIB)
    endif

    在样例中,ifdef可以替换为以下的几个指令:

    • ifndef
    • ifeq
    • ifneq
  • 引入指令

    在多个makefile里面都要使用的变量、函数、语句,我们可以使用引入指令include来组织。 下面是引入指令的基本语法样例:

    include makefile.common

函数

内置函数

表3 GNU make内置函数

函数原型功能描述样例
$(filter pattern..., text)filter将text视为一系列被空格隔开的单词,与pattern比较之后,接着会返回符合的单词列表$(gui_objects): $(filter gui/%.o, $(objects))
$(filter pattern...,text)filter-out函数用来选出与模式不相符合的单词to_compile := $(filter-out %.h, $(all_source))
$(findstring string..., text)此函数将会在text搜索string。如果该字符串被找到了,此函数就会返回string;否则,返回空值。$(findstring /tom/book/zeuux, $(PWD))
$(subst search-string, replace-string, text)常用来在文件名列表中将一个名换成另外一个扩展名,不带通配符功能objects := $(subst .c, .o, $(sources))
$(patsubst search-pattern, replace-pattern, text)replace-pattern中的%被扩展成与模式相符的文字,且search-pattern必须与text的整个值进行匹配strip-trailing-flash = $(patsub %/,%,%(directory-path))
$(words n, text)返回text中第n个单词$(words 2, $(version_list))
$(sort list)排序list参数并移出重复的项目d-prefix = $(sort dbase db2 mysql)
$(shell command)执行command命令stdout := $(shell echo normal message)
$(wildcard pattern...)wildcard函数的参数是一份模式列表,它会对列表中的每个模式进行扩展的动作。如果找不到相符的文件,返回空字符串source := $(wildcard *.c *.h)
$(suffix name...)返回参数中每个单词的后缀same-suffix = $(filter 1 $(words $(sort $(suffix $1))))
$(basename name...)返回文件名称中不含后缀的部分$(basename $1)
自定义函数

如何应用make到项目中

前面介绍了如何使用make的基本用法,下面我们介绍一下使用make来进行项目开发的步骤:

  1. 需求

    每个项目的需求是不一样的,如何在项目中使用make的功能也是仁者见仁、智者见智。 下面是一些常见的项目需求:

    • 源代码和二进制码分开
    • 需要管理不同版本的二进制发布文件
    • 需要不同平台的版本
    • 需要一个完整的安装文件
    在开始项目之前,最后考虑一下你使用make的需求是什么。
  2. 文件系统布局

    当你进入二进制文件树的时候,你需要考虑二进制文件的文件系统布局问题。常见的文件系统布局有一下几种:

    • 版本号
    • 平台依赖
  3. 自动编译和测试

    自动编译可以在晚上无人看守的情况下编译,从而节省开发人员白天的时间。以后的一些工具可以帮助开发人员完成这一任务,比如cron。 自动测试可以验证编译程序的正确性,同时会把结果反馈给开发人员。开发人员可以直接构建这样的自动测试工具,也有一些现成的工具可选,比如 GNU工具dejaGnu就可以用来测试需要交互的非图形实用程序。

总结

本文介绍了GNU Make的用法和使用技巧,我们可以看到make很强大,可以节省开发人员的时间,享受开发的乐趣。动起手来,使用make来管理你的项目吧!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值