Makefile 简易教程

本文深入探讨了编译流程的自动化过程,从传统命令行编译到引入Makefile实现高效编译,再到利用Shell脚本与函数简化编译流程,最终达到自动化编译的共产主义阶段。详细介绍了不同历史阶段的编译规则、Makefile语法、Shell函数应用及变量替换技巧,旨在提升开发效率与生产力。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. 定义

target: dependencies
[tab] command

NOTE: [tab] 不能为四个空格。

2. 使用规则

2.1 测试文件

       func.h                     func.cpp                      main.cpp
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
void PrintHello();   |   void PrintHello()             |   int main()
                     |   {                             |   {
                     |       cout << "Hello World!";   |       PrintHello();
                     |   }                             |   }

2.2 原始社会

g++ func.cpp main.cpp -o prog

当有多个文件的时候,每次都需要g++ 一串cpp文件,繁琐低效。

2.3 奴隶社会

compile.sh
-----------------
#!/bin/sh
g++ func.cpp main.cpp -o prog

事先写好脚本,编译操作一键式完成,./compile.sh。同样,文件数量急剧上涨的时候,问题显现出来。
无论源文件是否改动,每次都需要将所有的cpp编译成.o 目标文件,耗时低效。

2.4 封建社会

通过makefile的依赖关系,只需要编译修改的文件即可,没有修改的源文件,没有必要重新编译。省时,但不省力。

prog: func.o main.o
    g++ func.o main.o -o prog

func.o: func.cpp
    g++ -c func.cpp -o func.o

main.o: main.cpp
    g++ -c main.cpp -o main.o

2.5 社会主义

在封建社会中,只要存在一个cpp文件,就要为这个cpp文件写规则,一旦源文件数量上升,makefile将成为瓶颈。

CC = g++
RM = rm -rf
CFLAGS = -g -WALL

OBJS = main.o func.o
EXEC = main

$(EXEC): $(OBJS)
    $(CC) $^ $(CFLAGS) -o $@ 

%.o : %.cpp
    $(CC) -c $< -o $@

clean:
    $(RM) $(OBJS) $(EXEC)
变量
  • 自定义变量
    = 使用等号给自定义变量赋值
    # 注释

  • 内建变量
    $^ 依赖关系列表
    $< 依赖关系列表中第一个
    $@ target 名字

prog: main.o func.o
  g++ $^ -o $@

$^   => main.o func.o
$@ => prog
$<  => main.o

模式规则

target目标中包含%,即为一个模式规则。
%.o : %.cpp 指导任何一个cpp文件编译成对应的.o文件

2.5 共产主义

社会主义中,工作效率已经得到了极大的提升,但是,仍需要手动将每个.cpp文件对应为.o文件。共产主义社会中,通过引入函数,自动完成这一繁琐工作。

CC = g++
RM = rm -rf
CFLAGS = -g -WALL

SRCS = $(wildcard *.cpp)
OBJS = $(SRCS:.cpp=.o)
EXEC = main

$(EXEC): $(OBJS)
    $(CC) $^ $(CFLAGS) -o $@ 

%.o : %.cpp
    $(CC) -c $< -o $@

clean:
    $(RM) $(OBJS) $(EXEC)
函数

语法
$(function arguments)
- function 函数名
- arguments 函数参数

Makefile 手册: Functions for Transforming Text

wildcard 函数
wildcard 为通配符函数,类似于通配符 %

(wildcard *.cpp) 得到当前目录下,所有的cpp文件

变量替换
foo = test.c main.c
bar = $(foo:**.**c=**.**o)

prog :
    echo $(bar)

-------------------
输出: test.o main.o

MakeFile 手册:Substitution References

替换规则:
- 针对单词进行替换, foo 变量单词直接以空格隔开
- 后缀替换,仅仅替换匹配的后缀

foo = test.o oppo.o
bar = $(foo: o = x)

bar => test.x oppo.x

3. Shell 语法

脚本语法
- 每行一个进程进行处理,因而每个命令单元不能断行
- makefile中变量以$开头,所有为了避免冲突,shell变量获取以$$开头

    DIRS = common logic middle_tier bootstrap
    all:
        @for dir in $(DIRS); do make -C $$dir; done
        rm -rf prog/conf/*
        mkdir -p prog/conf
        cp -r bootstrap/conf/* prog/conf

Note:
@ 执行此条命令,但不要输出任何信息
make -C 嵌套调用子目录中的Makefile

Shell 函数
files = $(shell echo *.c)

DIRS = $(shell ls -F | grep /$)
all:
  @for dir in $(DIRS); do make -C $$dir; done
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值