Makefile,从看懂开始 --eins

写在前面

从大三学编译开始,第一次接触makefile,觉得超级方便,基本语法样例中老师给好了,都是基础性makefile
到了自己源码编译什么东西时,看人家的makefile,根本摸不到头脑,只知道make modules,make, make install…
又是之前绕过的拦路虎,现在再一次避不过去了。近期目标是看懂,远期目标是会写。

Makefile基础

这里 二次整理而来

  1. 一些不明所以的符号: $@, $^, $<
# hello由hello.o生成,所以hello依赖于hello.o及多个hellox.o文件;
# 依赖关系用冒号(:)隔开
# 冒号左边的叫做目标(target);
# 冒号右边称为依赖(prerequisites)
# `$@`是指所有的编译目标;
# `$<`是指第一个依赖文件;
# `$^`是指多个依赖文件;
SRC_DIR     := .
SUB_SRC_DIR := ./sub
# patsubst 模式匹配文本并替换。第一个参数,匹配模式;第二个参数,替换字符串;第三个参数,要替换的文本字符串
# wildcard 列举符合通配符表达式的所有源文件,输出以空格为分隔符的列表 
OBJS        +=  $(patsubst %.c,%.o, $(wildcard $(SRC_DIR)/*.c $(SUB_SRC_DIR)/*.c))

hello: $(OBJS)
    gcc -o $@ $^
# $@即hello,$^即$(OBJS)中,所有的.o目标文件
# 如果此处只有一个依赖文件,比如hello.o,也可以用$<替代$^

# 伪目标的意义就是,无论如何都执行下面的命令
# 防止Makefile中定义的目标和工作目录的实际文件出现名字冲突,导致命令无法执行
# 伪目标,只是一个标签,不会生成文件,当然就不会有冲突啦  
.PHONY: clean       
clean:
    rm -f hello $(OBJS)
  1. 如何指定编译目录
    可以通过BUILD_DIR指定build目录,作为编译过程中间文件的存放位置
    makefile文件变成了这样
SRC_DIR     := .
SUB_SRC_DIR := ./sub
BUILD_DIR   := ./build

# 目标文件
SRCS    := $(wildcard $(SRC_DIR)/*.c $(SUB_SRC_DIR)/*.c)
OBJS    += $(addprefix $(BUILD_DIR)/,$(patsubst %.c,%.o,$(notdir $(wildcard $(SRC_DIR)/*.c $(SUB_SRC_DIR)/*.c))))

hello: $(OBJS)
    gcc -o $@ $^

# 这时候因为目标文件已经脱离了源文件的环境,
# 用makefile隐含规则自动编译已经不可行了。
# 需要显式执行编译
$(BUILD_DIR)/%.o:$(SRC_DIR)/%.c
    gcc -c -o $@ $^
$(BUILD_DIR)/%.o:$(SUB_SRC_DIR)/%.c
    gcc -c -o $@ $^

.PHONY: clean       
clean:
    rm -f hello $(OBJS)

Makefile手册

来自这里

Makefile概述

  • 在makefile中可以使用变量 (类似于C语言中的宏)
    • 然后可以以 $(objects) 的方式来使用它
  • 显式规则
  • 隐式规则:makefile的自动推导功能
  • 变量定义
  • 文件指示:可以引用其他makefile(include <filename>);可以实现#if
  • 注释
  • 命令要以 tab 键开始(绝对不能是空格),与之对应的include这些关键字前边一定不能有Tab键
  • 两条命令:在同一行时可用分号(;)分隔,或者是放在两行。以此保证前后依赖关系
  • 另外,Makefile以/bin/sh执行命令

关于语法

  • 支持通配符 *,?, ~
  • vpath 关键字
    • vpath <pattern> <directories> 为符合pattern的文件指定搜索目录
    • vpath <pattern> 清除符合pattern的文件的搜索目录
    • vpath 清除所有设置好的文件搜索目录
    • ps, 这里的pattern用%匹配符,举个例子,vpath %.h …/headers
  • 自动化变量 $@
    • $@表示 目标的集合
  • 静态模式
    • 基本语法,为啥叫这个名字我还没弄明白
 <targets ...> : <target-pattern> : <prereq-patterns ...>
    <commands>
  • 看个栗子就明白了这个语法了
objects = foo.o bar.o
all: $(objects)
$(objects): %.o: %.c
    $(CC) -c $(CFLAGS) $< -o $@

关于Makefile的书写和调试

怎么知道自己写的Makefile对不对呢,插装哈哈哈哈哈

  • @echo something_to_tell
  • make -n 或 make --just-print
    • 与之相对的就是 make -s 或 make --silent 或 make --quiet
  • 看到这里突然有了新的想法,鸽了暂时
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值