Makefile

1. 简单例子

target=main

$(target): main.o 
	gcc -o $(target) $^

%.o:%.c
	gcc -c -o $@ $<
  1. 我想生成一个目标文件 main,但是它依赖 main.o ,而 main.o 依赖 $^,“$^”的意思是当前规则编译出目标文件所有需要依赖的文件 例如编译 gcc -o main main.o test.o d 等文件

  2. .o 文件不存在, 则需要获取

    %.o:%.c
    	gcc -c -o $@ $<
    

    %.o 是目标,%.c 是依赖文件, 例如 main.o 编译出来需要 main.c 需要命令为

    • 目标:main.o​($@​)
    • 依赖:main.c​($<​)
    • 执行命令:gcc -c -o main.o main.c
  3. 变量 含义 示例(规则:test: a.o b.o​)
    $@ 目标文件名称 main
    $< 第一个依赖文件 main.o
    $^ 所有依赖文件(去重) main.o test.o
    $+ 所有依赖文件(保留重复) main.o test.o test.o
    $? 比目标新的依赖文件 test.o​ 较新:test.o

    $^:所有依赖文件

    生成目标文件 需要连接多个 o 文件

    $<:第一个依赖文件

    生成 o 文件 只需要一个 c 文件

  4. 既然 $@ 代表目标文件,那么修改为

    target=main
    
    $(target): main.o 
    	gcc -o $@ $^
    
    %.o:%.c
    	gcc -c $< -o $@
    
  5. 同时因为因为一些编译需要条件再次添加

    1. 编译阶段的 Flags(如 -Wall -O2

    编译阶段将 .c​ 源文件转换为 .o​ 目标文件,此时的 flags 主要控制:

    • 语法检查:如 -Wall​(开启所有常见警告)
    • 优化级别:如 -O2​(二级优化)
    • 调试信息:如 -g​(生成调试符号)
    • 宏定义:如 -DDEBUG​(定义 DEBUG 宏)

    2. 链接阶段的 Flags(如 -lm -lpthread

    链接阶段将多个 .o​ 文件合并为可执行程序,此时的 flags 主要控制:

    • 库文件路径:如 -L/path/to/lib
    • 链接特定库:如 -lm​(数学库)、-lpthread​(线程库)
    • 链接选项:如 -static​(静态链接)
    CC = gcc
    CFLAGS = -Wall -O2 -g      # 编译选项(警告、优化、调试)
    LDFLAGS = -L/usr/local/lib # 链接器搜索路径
    LDLIBS = -lm -lpthread     # 需要链接的库
    
    $(target): main.o utils.o
        $(CC) $(LDFLAGS) -o $@ $^ $(LDLIBS)  # 链接阶段
    
    %.o: %.c
        $(CC) $(CFLAGS) -c -o $@ $<          # 编译阶段
    
    clean:
        rm -f *.o $(target)
    

    gcc -c -o main.o main.c
    gcc -o main main.o

  6. 伪目标 .PHONY

    makefile 执行的条件有两条

    1. 目标文件不存在

    2. 目标依赖的文件比目标新

    3. 如果在同级目录中 clean 名称的文件,这个 make clean 不会执行

      因为目标存在,也找不到依赖文件

    4. 所以添加伪目标关键字如下

      target=main
      
      $(target): main.o 
      	gcc -o $(target) $^
      
      %.o:%.c
      	gcc -c -o $@ $<
      
      .PHONY clean:
      clean:
      	rm -rf $(target) *.o
      
  7. 变量

    1. 立即变量:A:=XXX.定义时确定值
    2. 延迟变量 B=XXX 使用时确定值

    引用变量 用“$”,不想看到命令的执行结果“@”

    := # 即时变量
    = # 延时变量
    ?= # 延时变量, 如果是第1次定义才起效, 如果在前面该变量已定义则忽略这句
    += # 附加, 它是即时变量还是延时变量取决于前面的定义
    ?=: 如果这个变量在前面已经被定义了,这句话就会不会起效果,
    
    A := $(C)
    B = $(C)
    C = abc
    
    #D = ljgh666
    D ?= luojunguang
    
    all:
    	@echo A = $(A)
    	@echo B = $(B)
    	@echo D = $(D)
    
    C += 123
    
    

    A =
    B = abc 123
    D = luojunguang

    1. makefile 执行分为两个阶段

      解析阶段 读取整个文件 收集变量和规则

    2. 执行阶段

      根据规则执行命令

    3. 所以此处 B 为 abc 123

函数

  1. $(foreach var, list,text)

    • var​:循环变量,依次代表列表中的每个元素。
    • list​:要遍历的列表,元素之间用空格分隔。
    • text​:对每个元素执行的操作,可以包含对 $(var)​ 的引用。

    SRCS := main.c utils.c test.c

    OBJS := $(foreach var, $(SRCS), $(var).o)

    结构为 OBJS = main.c.o utils.c.o test.c.o

    对列表中的每个元素执行相同的操作并返回结果列表

  2. filter

    $(filter patten ..., text) # 在text中取出符合patten格式的值

    $(filter-out patten ..., text) # 在text中取出不符合patten格式的值

    C = src/ inc/ main.c lib/ func.h ./docs/
    D = $(filter %/, $(C))  # 筛选以 / 结尾的元素
    
    all:
        @echo "原始列表 C: $(C)"
        @echo "筛选结果 D: $(D)"
    

    原始列表 C: src/ inc/ main.c lib/ func.h ./docs/ 筛选结果 D: src/ inc/ lib/ ./docs/

  3. wildcard

    $(wildcard pattern) wildcard 会以 pattern 这个格式,去寻找存在的文件,返回存在文件的名字

    files = $(wildcard *.c)
    
    all:
            @echo files = $(files)
    
    

    files = a.c b.c c.c

  4. patsubst

    $(patsubst patten,replacement, $(var))

    var 变量里面取出每一个值,如果这个符合 pattern 格式,把它替换成 replacement 格式

    在函数 foreach 中做过这样测试

    SRCS := main.c utils.c test.c

    OBJS := $(foreach var, $(SRCS), $(var).o)

    结构为 OBJS = main.c.o utils.c.o test.c.o

    对列表中的每个元素执行相同的操作并返回结果列表

    每一个文件中都有.c 存在,这时候使用 patsubst 使用

    SRCS := main.c utils.c test.c
    OBJS := $(foreach var, $(SRCS), $(var).o) 改成
    OBJS := $(foreach var, $(SRCS), $(patsubst %.c, %.o, $(var)))
    
  • Makefile
    5 引用 • 6 回帖
  • C

    C 语言是一门通用计算机编程语言,应用广泛。C 语言的设计目标是提供一种能以简易的方式编译、处理低级存储器、产生少量的机器码以及不需要任何运行环境支持便能运行的编程语言。

    90 引用 • 165 回帖

相关帖子

回帖

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...

推荐标签 标签

  • 支付宝

    支付宝是全球领先的独立第三方支付平台,致力于为广大用户提供安全快速的电子支付/网上支付/安全支付/手机支付体验,及转账收款/水电煤缴费/信用卡还款/AA 收款等生活服务应用。

    29 引用 • 347 回帖 • 2 关注
  • Firefox

    Mozilla Firefox 中文俗称“火狐”(正式缩写为 Fx 或 fx,非正式缩写为 FF),是一个开源的网页浏览器,使用 Gecko 排版引擎,支持多种操作系统,如 Windows、OSX 及 Linux 等。

    7 引用 • 30 回帖 • 367 关注
  • flomo

    flomo 是新一代 「卡片笔记」 ,专注在碎片化时代,促进你的记录,帮你积累更多知识资产。

    6 引用 • 144 回帖
  • 一些有用的避坑指南。

    69 引用 • 93 回帖
  • Vue.js

    Vue.js(读音 /vju ː/,类似于 view)是一个构建数据驱动的 Web 界面库。Vue.js 的目标是通过尽可能简单的 API 实现响应的数据绑定和组合的视图组件。

    269 引用 • 666 回帖 • 1 关注
  • AWS
    11 引用 • 28 回帖 • 2 关注
  • 安装

    你若安好,便是晴天。

    134 引用 • 1184 回帖 • 2 关注
  • MySQL

    MySQL 是一个关系型数据库管理系统,由瑞典 MySQL AB 公司开发,目前属于 Oracle 公司。MySQL 是最流行的关系型数据库管理系统之一。

    695 引用 • 538 回帖 • 1 关注
  • Kafka

    Kafka 是一种高吞吐量的分布式发布订阅消息系统,它可以处理消费者规模的网站中的所有动作流数据。 这种动作(网页浏览,搜索和其他用户的行动)是现代系统中许多功能的基础。 这些数据通常是由于吞吐量的要求而通过处理日志和日志聚合来解决。

    36 引用 • 35 回帖
  • 钉钉

    钉钉,专为中国企业打造的免费沟通协同多端平台, 阿里巴巴出品。

    15 引用 • 67 回帖 • 236 关注
  • RabbitMQ

    RabbitMQ 是一个开源的 AMQP 实现,服务器端用 Erlang 语言编写,支持多种语言客户端,如:Python、Ruby、.NET、Java、C、PHP、ActionScript 等。用于在分布式系统中存储转发消息,在易用性、扩展性、高可用性等方面表现不俗。

    49 引用 • 60 回帖 • 342 关注
  • 创业

    你比 99% 的人都优秀么?

    81 引用 • 1396 回帖 • 1 关注
  • Netty

    Netty 是一个基于 NIO 的客户端-服务器编程框架,使用 Netty 可以让你快速、简单地开发出一个可维护、高性能的网络应用,例如实现了某种协议的客户、服务端应用。

    49 引用 • 33 回帖 • 63 关注
  • FreeMarker

    FreeMarker 是一款好用且功能强大的 Java 模版引擎。

    23 引用 • 20 回帖 • 475 关注
  • 黑曜石

    黑曜石是一款强大的知识库工具,支持本地 Markdown 文件编辑,支持双向链接和关系图。

    A second brain, for you, forever.

    34 引用 • 333 回帖
  • jsDelivr

    jsDelivr 是一个开源的 CDN 服务,可为 npm 包、GitHub 仓库提供免费、快速并且可靠的全球 CDN 加速服务。

    5 引用 • 31 回帖 • 121 关注
  • Elasticsearch

    Elasticsearch 是一个基于 Lucene 的搜索服务器。它提供了一个分布式多用户能力的全文搜索引擎,基于 RESTful 接口。Elasticsearch 是用 Java 开发的,并作为 Apache 许可条款下的开放源码发布,是当前流行的企业级搜索引擎。设计用于云计算中,能够达到实时搜索,稳定,可靠,快速,安装使用方便。

    117 引用 • 99 回帖 • 191 关注
  • 百度

    百度(Nasdaq:BIDU)是全球最大的中文搜索引擎、最大的中文网站。2000 年 1 月由李彦宏创立于北京中关村,致力于向人们提供“简单,可依赖”的信息获取方式。“百度”二字源于中国宋朝词人辛弃疾的《青玉案·元夕》词句“众里寻他千百度”,象征着百度对中文信息检索技术的执著追求。

    63 引用 • 785 回帖 • 46 关注
  • IDEA

    IDEA 全称 IntelliJ IDEA,是一款 Java 语言开发的集成环境,在业界被公认为最好的 Java 开发工具之一。IDEA 是 JetBrains 公司的产品,这家公司总部位于捷克共和国的首都布拉格,开发人员以严谨著称的东欧程序员为主。

    182 引用 • 400 回帖
  • webpack

    webpack 是一个用于前端开发的模块加载器和打包工具,它能把各种资源,例如 JS、CSS(less/sass)、图片等都作为模块来使用和处理。

    43 引用 • 130 回帖 • 259 关注
  • abitmean

    有点意思就行了

    44 关注
  • 新人

    让我们欢迎这对新人。哦,不好意思说错了,让我们欢迎这位新人!
    新手上路,请谨慎驾驶!

    52 引用 • 228 回帖
  • 电影

    这是一个不能说的秘密。

    125 引用 • 610 回帖
  • Swift

    Swift 是苹果于 2014 年 WWDC(苹果开发者大会)发布的开发语言,可与 Objective-C 共同运行于 Mac OS 和 iOS 平台,用于搭建基于苹果平台的应用程序。

    34 引用 • 37 回帖 • 565 关注
  • 音乐

    你听到信仰的声音了么?

    63 引用 • 513 回帖
  • TGIF

    Thank God It's Friday! 感谢老天,总算到星期五啦!

    293 引用 • 4496 回帖 • 687 关注
  • TensorFlow

    TensorFlow 是一个采用数据流图(data flow graphs),用于数值计算的开源软件库。节点(Nodes)在图中表示数学操作,图中的线(edges)则表示在节点间相互联系的多维数据数组,即张量(tensor)。

    20 引用 • 19 回帖