欢迎光临
我们一直在努力

de风——【从零开始学习Linux】(六):自动化构建 make与Makefile

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */
#content_views .toc,
/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */
#content_views.markdown_views > p:empty:has(+ .toc),
#content_views.markdown_views > .toc + p:empty,
/* 富文本旧版目录标记 */
#content_views.htmledit_views #main-toc,
#content_views.htmledit_views #hr-toc,
#content_views.htmledit_views p[id*=\”-toc\”] {
display: none !important;
}
/* 目录去掉后,紧跟的首个标题不再多出一块上边距 */
#content_views.markdown_views > .toc + h1,
#content_views.markdown_views > .toc + h2,
#content_views.markdown_views > .toc + h3,
#content_views.markdown_views > .toc + h4,
#content_views.markdown_views > .toc + p:empty + h1,
#content_views.markdown_views > .toc + p:empty + h2,
#content_views.markdown_views > .toc + p:empty + h3,
#content_views.markdown_views > .toc + p:empty + h4 {
margin-top: 0 !important;
}

环境说明:本系列使用 Xshell 7 连接 腾讯云服务器 Ubuntu 22.04 进行操作演示。如果你还没有搭建好环境,请先阅读本系列前面的文章。


前言

在上一篇文章中,我们学会了使用 GCC 编译器编译代码。但那个例子只用了一个源文件,几行命令就能搞定。可是真实的项目是什么样的呢?

一个真实的 C/C++ 项目,源文件可能有几百甚至上千个,它们分散在不同的目录里,相互之间还存在依赖关系。如果每次都手动敲 gcc xxx.c yyy.c zzz.c -o app,不仅麻烦,而且——

  • 改一个文件要重新编译全部文件:浪费时间
  • 文件多了根本记不住依赖关系:容易出错
  • 每次编译都要手敲一长串命令:效率极低

幸好,Linux 世界早就有了解决方案——make 和 Makefile。它们能让整个项目"一键编译",是每个 Linux 程序员必须掌握的技能。

一句话总结:会不会写 Makefile,从侧面反映了一个人是否具备完成大型工程的能力。


思维导图

下面是本文内容的完整思维导图,建议先整体浏览一遍,建立全局认知后再逐节学习。


一、make 与 Makefile 简介

1.1 什么是 make 和 Makefile?

语法形式

make # 执行 Makefile 中的第一个目标
make 目标名 # 执行指定的目标

功能

这里要先区分两个东西:

名称

是什么

作用

make

一个命令工具

解释并执行 Makefile 中的指令

Makefile

一个文件

定义项目的编译规则

它们是搭配使用的:make 是命令,Makefile 是规则文件。你在终端敲 make,make 工具就会去读当前目录下的 Makefile 文件,然后按照里面定义的规则自动编译项目。

类比理解:把 Makefile 想象成一份"菜谱",make 就是"厨师"。菜谱(Makefile)写清楚每道菜需要什么食材、怎么做;厨师(make)照着菜谱一步步操作,最后端出成品(可执行程序)。

Makefile 带来的好处:

  • 自动化编译:一旦写好,只需一个 make 命令,整个工程完全自动编译2.
  • 增量编译:只重新编译修改过的文件,未修改的文件不重复编译,大大节省时间
  • 依赖管理:自动维护文件之间的依赖关系,指定谁先编译、谁后编译
  • 跨平台:几乎所有 IDE 都支持 make,Linux 下的 GNU make 更是标配
  • 示例

    ——演示 make 的基本使用流程

    # 1. 先创建一个简单的 C 程序
    vim myproc.c

    // myproc.c
    #include <stdio.h>

    int main()
    {
    printf("hello Makefile!\\n");
    return 0;
    }

    # 2. 创建 Makefile 文件(注意:文件名必须是 Makefile 或 makefile)
    vim Makefile

    myproc:myproc.c
    gcc -o myproc myproc.c

    # 3. 直接执行 make 命令
    make
    # 输出:
    # gcc -o myproc myproc.c

    # 4. 运行生成的可执行文件
    ./myproc
    # 输出:hello Makefile!

    新手注意:make 会自动在当前目录找名为 Makefile(首字母大写)或 makefile(全小写)的文件。文件名千万别写错,否则 make 会报错 make: *** No targets specified and no makefile found. Stop.


    二、Makefile 的基本语法规则

    Makefile 的核心就是一条条规则(Rule)。每条规则告诉 make:"要生成什么,需要什么,怎么生成"。

    2.1 规则的三要素

    语法形式

    目标(target): 依赖(dependency)
    命令(command)

    注意:命令前面必须是 Tab 键缩进(不能用空格),这是新手最容易踩的坑!

    功能

    一条 Makefile 规则由三部分组成:

    组成部分

    英文

    含义

    目标

    target

    要生成的文件(冒号左边)

    依赖

    dependency

    生成目标所需要的文件(冒号右边)

    命令

    command

    具体的生成动作(下一行 Tab 缩进)

    规则的含义:目标 依赖于 依赖,如果 依赖 比 目标 新,就执行 命令 来生成 目标。

    一句话理解:规则格式可以读作——"目标 由 依赖 生成,生成方法是执行 命令"。

    示例

    ——演示最基本的 Makefile 规则:依赖关系与依赖方法

    # Makefile 内容
    myproc:myproc.c
    gcc -o myproc myproc.c
    # 逐行理解这条规则:

    # 【目标】myproc —— 要生成的可执行文件
    # 【依赖】myproc.c —— 生成 myproc 需要 myproc.c 这个源文件
    # 【命令】gcc -o myproc myproc.c —— 用这条命令从 myproc.c 生成 myproc

    # 执行 make
    make
    # make 发现 myproc 不存在(或 myproc.c 比 myproc 新),于是执行命令
    # 输出:gcc -o myproc myproc.c

    # 再次执行 make(此时 myproc 已经是最新的)
    make
    # 输出:make: 'myproc' is up to date.
    # make 发现 myproc 比 myproc.c 新,不需要重新编译!

    关键概念:

    • 依赖关系:myproc 依赖 myproc.c
    • 依赖方法:gcc -o myproc myproc.c 一进一出的对应关系,就是 Makefile 的最小单元。

    ——演示 Tab 缩进的坑(新手必看)

    # 错误示范:命令前面用的是空格而不是 Tab
    vim Makefile

    myproc:myproc.c
    gcc -o myproc myproc.c # 这行用的是 4 个空格,不是 Tab!

    make
    # 报错:
    # Makefile:2: *** missing separator. Stop.
    # ↑ 缺少分隔符,就是因为你用了空格而不是 Tab
    # 正确做法:命令前面必须是 Tab 键
    # 在 Vim 中,先按 Tab 键,再输入命令
    # 可以用 cat -A Makefile 查看缩进(Tab 会显示为 ^I)
    cat -A Makefile
    # myproc:myproc.c$
    # ^Igcc -o myproc myproc.c$ ← ^I 就是 Tab

    新手避坑:"missing separator" 是新手最常遇到的 Makefile 报错,99% 的原因是命令前用了空格而不是 Tab。记住:Makefile 中命令必须用 Tab 缩进!在 Vim 里如果 Tab 键被设置成了空格,可以先去设置里确认,或者用 cat -A 检查一下。


    2.2 多规则与依赖链

    语法形式

    目标1: 依赖1
    命令1

    目标2: 依赖2
    命令2

    功能

    一个 Makefile 可以包含多条规则。当目标的依赖本身又是另一条规则的目标时,就形成了依赖链,make 会一层层递归地处理。

    示例

    ——演示完整编译流程的 Makefile(从 .c 到可执行文件)

    还记得上一篇文章讲的 GCC 编译四大步骤吗?我们用 Makefile 把每一步都写进规则里:

    # 完整版 Makefile
    myproc: myproc.o
    gcc myproc.o -o myproc

    myproc.o: myproc.s
    gcc -c myproc.s -o myproc.o

    myproc.s: myproc.i
    gcc -S myproc.i -o myproc.s

    myproc.i: myproc.c
    gcc -E myproc.c -o myproc.i
    # 执行 make
    make
    # 输出:
    # gcc -E myproc.c -o myproc.i ← 先生成 .i
    # gcc -S myproc.i -o myproc.s ← 再生成 .s
    # gcc -c myproc.s -o myproc.o ← 再生成 .o
    # gcc myproc.o -o myproc ← 最后链接成可执行文件

    理解依赖链:make 从第一个目标 myproc 开始,发现它依赖 myproc.o;而 myproc.o 又依赖 myproc.s……于是一层层往下找,直到找到最底层的 myproc.c,然后反过来一层层生成。这就像一个"堆栈"过程:先压栈找依赖,再出栈执行命令。


    三、make 的工作原理

    理解 make 的工作机制,是写好 Makefile 的关键。我们分点来讲。

    3.1 make 的执行流程

    功能

    当你直接输入 make(不带参数)时,make 会按照以下步骤工作:

  • 找文件:在当前目录下找名为 Makefile 或 makefile 的文件
  • 找目标:找到文件后,把第一个目标作为最终目标(默认目标)
  • 查依赖:检查这个目标的依赖文件是否存在、是否比目标更新
  • 递归生成:如果依赖文件不存在,就在 Makefile 中寻找生成该依赖的规则,递归处理
  • 执行命令:所有依赖都就绪后,执行命令生成目标
  • 出错退出:如果被依赖的文件找不到,make 会直接退出并报错
  • 示例

    ——演示 make 的依赖查找与增量编译

    # 假设 Makefile 内容是规则链版本(上面 2.2 的完整版)

    # 第一次 make:所有文件都不存在,从头生成
    make
    # 输出:执行了 4 条 gcc 命令

    # 文件都在了,再次 make
    make
    # 输出:make: 'myproc' is up to date.
    # 什么都不做,因为都是最新的

    # 只修改 myproc.c 文件
    touch myproc.c # 用 touch 更新 myproc.c 的时间戳

    # 再次 make
    make
    # 输出:
    # gcc -E myproc.c -o myproc.i
    # gcc -S myproc.i -o myproc.s
    # gcc -c myproc.s -o myproc.o
    # gcc myproc.o -o myproc
    # 因为 myproc.c 更新了,所有依赖它的文件都要重新生成

    # 只修改中间文件 myproc.s
    touch myproc.s

    make
    # 输出:
    # gcc -c myproc.s -o myproc.o ← 只重新生成 myproc.o 及之后
    # gcc myproc.o -o myproc
    # myproc.i 不用重新生成,因为 myproc.c 没变!

    这就是增量编译的威力:make 会智能判断哪些文件需要重新编译,只做必要的操作,绝不做无用功。这就是它比手敲命令高效的核心原因。


    3.2 文件时间戳:理解"是否需要更新"

    功能

    make 判断"是否需要重新编译"的依据是文件的时间戳(时间戳)。这里的核心是一个知识点:文件的三个时间。

    时间

    全称

    含义

    何时更新

    Access

    访问时间

    文件最近一次被读取的时间

    文件被访问时

    Modify

    修改时间

    文件内容被修改的时间

    内容变更时

    Change

    状态时间

    文件属性(如权限)变更的时间

    属性变更时

    公式:文件 = 内容 + 属性。Modify 管内容变更,Change 管属性变更。

    示例

    ——演示 stat 命令查看文件的时间戳

    # 用 stat 命令查看文件的详细时间信息
    stat myproc.c
    # 输出示例:
    # File: myproc.c
    # Size: 89 Blocks: 8 IO Block: 4096 regular file
    # Device: fd01h/64769d Inode: 1321125 Links: 1
    # Access: (0664/-rw-rw-r–) Uid: ( 1000/ user) Gid: ( 1000/ user)
    # Access: 2026-10-07 17:05:30.430619002 +0800 ← 访问时间
    # Modify: 2026-10-07 17:05:25.940595116 +0800 ← 修改时间
    # Change: 2026-10-07 17:05:25.940595116 +0800 ← 状态时间

    # make 判断需要更新的核心:比较依赖文件和目标文件的 Modify 时间
    # 如果 依赖的Modify时间 > 目标的Modify时间 → 需要重新生成

    ——演示用 touch 修改时间戳来触发重新编译

    # 假设 myproc 已是最新,make 不会做任何事
    make
    # make: 'myproc' is up to date.

    # touch 命令可以"更新文件时间"(不改内容,只改时间戳)
    touch myproc.c

    # 现在 myproc.c 的 Modify 时间比 myproc 新了
    make
    # 会重新编译!因为 make 发现依赖比目标新

    实用技巧:touch filename 可以不改动文件内容,只更新时间戳,常用于"强制触发重新编译"。


    3.3 .PHONY 伪目标

    语法形式

    .PHONY: 目标名
    目标名:
    命令

    功能

    clean 这类目标很特殊——它不生成任何文件,只是执行一些清理命令。这类目标叫伪目标(Phony Target)。

    为什么需要 .PHONY?

    如果目录里恰好有个叫 clean 的文件,make 会认为 clean 目标"已经存在且是最新的",于是不执行清理命令!用 .PHONY:clean 声明后,make 就会忽略文件比对,每次都执行这个目标。

    .PHONY 的作用:让 make 忽略"源文件和目标文件的 Modify 时间对比",让该目标总是被执行。

    示例

    ——演示 clean 目标:项目清理

    # Makefile
    myproc:myproc.c
    gcc -o myproc myproc.c

    .PHONY:clean
    clean:
    rm -f myproc
    # 编译
    make
    # gcc -o myproc myproc.c

    # 查看目录
    ls
    # Makefile myproc myproc.c

    # 清理项目(删除可执行文件)
    make clean
    # 输出:rm -f myproc

    # 再次查看
    ls
    # Makefile myproc.c
    # myproc 被删除了

    ——演示 .PHONY 的必要性(有同名文件时)

    # 假设当前目录下有个叫 clean 的文件
    touch clean

    # 如果 Makefile 中没有 .PHONY:clean
    ls
    # Makefile clean myproc.c

    make clean
    # 输出:make: 'clean' is up to date.
    # !清理命令根本没执行,因为 make 看到有个叫 clean 的文件,以为它是最新的

    # 加上 .PHONY:clean 之后
    # Makefile 内容:.PHONY:clean
    make clean
    # 输出:rm -f myproc
    # 正常执行清理,因为 .PHONY 让 make 忽略文件比对

    结论:像 clean 这种不生成文件的目标,一定要用 .PHONY 声明,否则一旦目录中存在同名文件就会失效。

    ——演示 .PHONY 让目标总是被执行

    # 把普通目标也声明成伪目标测试效果
    .PHONY:myproc
    myproc:myproc.c
    gcc -o myproc myproc.c
    make
    # gcc -o myproc myproc.c

    make
    # gcc -o myproc myproc.c ← 注意:即使已是最新,也会重新执行!
    # 因为 .PHONY:myproc 让它忽略时间比对,总是执行

    # 这验证了"伪目标的特性是总是被执行"


    四、Makefile 变量与自动化

    当项目变大时,重复写 gcc、myproc 这些字符串会很啰嗦。Makefile 提供了变量和自动化变量来简化写法,让 Makefile 更简洁、更好维护。

    4.1 自定义变量

    语法形式

    变量名 = 值 # 定义变量
    $(变量名) # 使用变量

    功能

    Makefile 中的变量和 Shell 变量类似,用于存储字符串。用 $(变量名) 的方式引用。使用变量能让 Makefile 更容易修改(改一处即可全局生效)。

    示例

    ——演示变量的定义与使用

    # 定义变量
    CC = gcc
    BIN = myproc
    SRC = myproc.c

    # 使用变量
    $(BIN):$(SRC)
    $(CC) -o $(BIN) $(SRC)

    .PHONY:clean
    clean:
    rm -f $(BIN)

    好处:使用变量后,要修改编译器、目标名等信息,只需改定义那一行,不用在每条命令里查找替换。这在大型项目中非常重要。


    4.2 wildcard 函数与替换

    语法形式

    $(wildcard 模式) # 获取匹配模式的所有文件名
    $(变量:.旧后缀=.新后缀) # 将变量中所有旧后缀替换为新后缀

    功能
    • wildcard:自动获取当前目录下符合模式的所有文件(比如所有 .c 文件),不用手动一个个列。
    • 后缀替换:把文件列表中的后缀统一替换(比如把 .c 列表替换成 .o 列表)。
    示例

    ——演示 wildcard 获取所有 .c 文件,并替换为 .o 文件

    # Makefile
    CC = gcc
    BIN = myproc
    SRC = $(wildcard *.c) # 获取当前目录所有 .c 文件
    OBJ = $(SRC:.c=.o) # 把所有 .c 替换成 .o

    $(BIN):$(OBJ)
    $(CC) -o $@ $^

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

    .PHONY:clean
    clean:
    rm -f $(OBJ) $(BIN)

    .PHONY:test
    test:
    @echo $(SRC)
    @echo $(OBJ)
    # 用 test 目标查看变量展开后的内容
    make test
    # 输出:
    # myproc.c ← $(SRC) 自动获取了所有 .c 文件
    # myproc.o ← $(OBJ) 自动把 .c 换成了 .o

    # 如果目录里有多个 .c 文件
    # SRC 会自动变成:a.c b.c c.c
    # OBJ 会自动变成:a.o b.o c.o
    # 完全不用手动修改 Makefile!

    $(wildcard *.c) 的妙用:项目里新增一个 .c 文件,Makefile 不用改,重新 make 就会自动把它纳入编译。这是大型项目 Makefile 的常见写法。


    4.3 自动化变量 $@ $^ $<

    语法形式

    变量

    含义

    $@

    目标文件名(target)

    $^

    所有依赖文件列表(dependencies)

    $<

    第一个依赖文件(first dependency)

    功能

    自动化变量是 Makefile 的"语法糖",能自动替换成当前规则中的目标名、依赖名,避免重复书写。

    示例

    ——演示 $@ / $^ / $< 的含义与效果

    # 不使用自动化变量(啰嗦写法)
    myproc:myproc.o
    gcc myproc.o -o myproc
    # 这里的 myproc 写了两遍,myproc.o 也写了两遍

    # 使用自动化变量(简洁写法)
    myproc:myproc.o
    gcc $^ -o $@
    # $^ 自动替换为 myproc.o(所有依赖)
    # $@ 自动替换为 myproc(目标)
    # 展开后等价于:gcc myproc.o -o myproc

    # $< 表示第一个依赖
    myproc.o:myproc.c myproc.h
    gcc -c $< -o $@
    # $< 自动替换为 myproc.c(第一个依赖)
    # $@ 自动替换为 myproc.o(目标)
    # 展开后:gcc -c myproc.c -o myproc.o
    make
    # 输出:gcc -c myproc.c -o myproc.o
    # gcc myproc.o -o myproc

    ——演示 @ 符号:不回显命令

    # 命令前加 @ 可以"静默执行",不显示命令本身
    test:
    @echo "这条命令不会回显"
    echo "这条命令会回显"

    # 对比:
    .PHONY:test
    test:
    @echo "只显示这行输出"
    echo "命令和执行结果都显示"
    make test
    # 输出:
    # 只显示这行输出
    # echo "命令和执行结果都显示"
    # 命令和执行结果都显示
    # ↑ 加了 @ 的那行,命令本身不显示;没加的会显示命令

    自动化变量记忆法:

    • $@ → @ 像"目标靶心",代表目标
    • $^ → ^ 像"一堆东西堆起来",代表所有依赖
    • $< → < 像"箭头指向第一个",代表第一个依赖

    4.4 模式规则 %.o:%.c

    语法形式

    %.o:%.c
    命令

    功能

    % 是通配符(相当于"任意名字")。%.o:%.c 表示:"任意一个 .o 文件,都可以由同名的 .c 文件生成"。这样一条规则就能自动处理所有 .c → .o 的转换,不用为每个文件单独写规则。

    示例

    ——演示模式规则自动处理多个文件

    # Makefile
    CC = gcc
    BIN = myproc
    SRC = $(wildcard *.c)
    OBJ = $(SRC:.c=.o)

    # 链接规则
    $(BIN):$(OBJ)
    $(CC) -o $@ $^
    @echo "linking … $^ to $@"

    # 模式规则:任意 .o 由同名 .c 生成
    %.o:%.c
    $(CC) -c $<
    @echo "compiling … $< to $@"

    .PHONY:clean
    clean:
    rm -f $(OBJ) $(BIN)
    make
    # 输出:
    # compiling … a.c to a.o
    # compiling … b.c to b.o
    # linking … a.o b.o to myproc
    # 一条 %.o:%.c 规则,自动处理了所有 .c 文件的编译!

    总结:%.o:%.c + $(wildcard *.c) + 自动化变量,是 Makefile 的"黄金三件套"。掌握它们,你的 Makefile 就能自动适应项目文件的增减,无需手动维护。


    五、完整实战:一个通用的 Makefile

    把前面学的知识串起来,这里给出一份经典的"通用 Makefile",可以直接用于大多数小型 C 项目:

    # ===== 通用 Makefile 模板 =====

    # 1. 定义变量
    BIN = proc.exe # 目标可执行文件名
    CC = gcc # 编译器
    SRC = $(wildcard *.c) # 自动获取所有 .c 文件
    OBJ = $(SRC:.c=.o) # 把 .c 列表替换成 .o 列表
    LFLAGS = -o # 链接选项
    FLAGS = -c # 编译选项
    RM = rm -f # 删除命令

    # 2. 链接规则(最终目标)
    $(BIN):$(OBJ)
    @$(CC) $(LFLAGS) $@ $^
    @echo "linking … $^ to $@"

    # 3. 模式规则(编译 .c 到 .o)
    %.o:%.c
    @$(CC) $(FLAGS) $<
    @echo "compiling … $< to $@"

    # 4. 清理
    .PHONY:clean
    clean:
    $(RM) $(OBJ) $(BIN)

    # 5. 测试(查看变量)
    .PHONY:test
    test:
    @echo $(SRC)
    @echo $(OBJ)

    模板说明:

    • @ 让命令静默执行,只显示自定制的 echo 信息,界面更清爽
    • $(wildcard *.c) 自动获取源文件,新增文件无需改 Makefile
    • $@、$^、$< 自动化变量减少重复输入

    六、常用命令与语法速查表

    make 命令速查

    命令

    功能

    make

    执行第一个目标(默认目标)

    make 目标名

    执行指定的目标

    make clean

    清理生成的文件

    make -f 文件名

    指定 Makefile 文件名(默认是 Makefile)

    make -n

    只显示要执行的命令,不实际执行(预演)

    Makefile 语法速查

    语法

    说明

    目标:依赖

    定义一条规则

    Tab + 命令

    命令必须用 Tab 缩进

    .PHONY:目标

    声明伪目标,总是被执行

    变量 = 值

    定义变量

    $(变量)

    引用变量

    $(wildcard *.c)

    获取所有 .c 文件

    $(SRC:.c=.o)

    后缀替换

    %.o:%.c

    模式规则

    $@

    目标文件名

    $^

    所有依赖文件

    $<

    第一个依赖文件

    @命令

    不回显该命令

    文件时间戳速查

    时间

    含义

    Access

    访问时间

    Modify

    内容修改时间(make 判断依据)

    Change

    属性变更时间

    stat 文件

    查看文件详细时间信息

    touch 文件

    更新时间戳(不改内容)


    七、总结

    本篇我们学习了 make 和 Makefile 的自动化构建,核心内容回顾:

  • make 与 Makefile 简介:make 是命令工具,Makefile 是规则文件,二者搭配实现自动化编译
  • 基本语法规则:目标:依赖 + Tab 缩进的命令,构成一条规则
  • 工作原理:找第一个目标 → 比较时间戳 → 递归查找依赖 → 增量编译
  • 伪目标 .PHONY:让 clean 等目标总是被执行,避免同名文件干扰
  • 变量与自动化:自定义变量(CC、BIN)、wildcard 函数、自动化变量($@、$^、$<)、模式规则(%.o:%.c)
  • 学习建议:

    • 理解"依赖关系 + 依赖方法"是 Makefile 的灵魂,多动手写几遍
    • Tab 缩进是第一大坑,遇到 "missing separator" 先检查缩进
    • make clean 和 .PHONY 是项目管理的标配,务必掌握
    • 熟练后试试 $(wildcard *.c) + 模式规则 + 自动化变量 这套组合,你的 Makefile 就能"以不变应万变"

    下一篇我们将开始动手写 Linux 的第一个真正意义上的程序——进度条,把 GCC 和 Makefile 的知识真正用起来,敬请期待!


    专栏目录:

    • 第一篇:Xshell 连接腾讯云服务器
    • 第二篇:Linux 基本指令入门
    • 第三篇:Linux 文件与目录管理
    • 第四篇:Vim 编辑器的基本使用
    • 第五篇:GCC 编译器的基本使用
    • 第六篇(本篇):make 与 Makefile 自动化构建
    • 第七篇:Linux 第一个系统程序——进度条(敬请期待)
    • …

    如果本文对你有帮助,欢迎点赞收藏关注,你的支持是我持续创作的动力!

    赞(0)
    未经允许不得转载:171主机测评 » de风——【从零开始学习Linux】(六):自动化构建 make与Makefile
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址