printf("Hello Wor|

c3n1g

园龄:1年6个月粉丝:2关注:0

2024-10-14 21:52阅读: 18评论: 0推荐: 0

Makefile

Makefile是由target和命令构成的,最简单的Makefile:

build:
	gcc test.c -o test

然后执行 make build 就会执行gcc这条命令,但是一般推荐先将源文件构建为对象文件,然后再统一编译为可执行文件

build: test.o
	gcc test.o -o test

test.o:
	gcc test.c -c

文件目标test.o是build伪目标依赖的文件,当执行build是会首先去执行文件目标的操作,所以:后面的称为目标的依赖

这种对多文件来说会更合适

build: test.o lib.o
	gcc test.o lib.o -o test

test.o:
	gcc test.c -c
	
lib.o:
	gcc lib.c -c

除此之外,make编译时候可以指定很多Flags,例如

  • CC:指定C语言编译器
  • CXX:指定CPP语言编译器
  • CFLAGS:指定C选项
  • CXXFLAGS:指定CPP选项
  • CPPFLAGS:指定编译过程中预处理选项
  • LDFLAGS:指定链接器选项

make -p可以查看所有预设的变量

除此之外也可以定义一些自定义变量,使用变量直接用$()即可。变量还可以使用?=,这个表示只有make时没有指定时才生效,否则不会执行到

有点值得注意,就是变量的值永远都是字符串,不需要用双引号括起来

DEBUG = 1
EXECUTABLE_NAME = test

CC = gcc
CFLAGS = -g -O0

COMPILER_CALL = $(CC) $(CFLAGS)

build: test.o lib.o
	$(COMPILER_CALL) test.o lib.o -o $(EXECUTABLE_NAME)

test.o:
	$(COMPILER_CALL) test.c -c
	
lib.o:
	$(COMPILER_CALL) lib.c -c

makefile也支持条件语句,关键字有 ifeqifneqifdefifndefelseendif

DEBUG = 1
ifeq ($(DEBUG), 1)
	CFLAGS = -g -O0
else
	CFLAGS = -O3
endif

如果源文件很多的话,一个一个指定文件目标会很麻烦,所以就要通配符来简化操作

  • $<:第一个依赖
  • $@:文件目标名
  • $^:所有依赖名

然后可以通过%来匹配文件名

EXECUTABLE_NAME = test

CC = gcc
CFLAGS = -g -O0

COMPILER_CALL = $(CC) $(CFLAGS)
C_OBJECTS = test.o lib.o

build: $(C_OBJECTS)
	$(COMPILER_CALL) $(C_OBJECTS) -o $(EXECUTABLE_NAME)

%.o: %.c
	$(COMPILER_CALL) $< -c -o $@

我们还可以更进一步,因为C_OBJECTS还不够自动化,没有自动识别.o文件自动添加,所以可以通过内置函数去实现

  • $(wildcard <pattern...>):获取指定格式化的文件列表
  • $(dir <names...>):获取文件所在目录
  • $(suffix <names...>):获取文件后缀
  • $(basename <names...>:去除文件后缀
  • $(subst ,,:替换字符
  • $(patsubst <src_pattern>,<dst_pattern>,):按格式替换字符
  • $(strip ):去除开头和结尾的空白字符
EXECUTABLE_NAME = test

CC = gcc
CFLAGS = -g -O0

COMPILER_CALL = $(CC) $(CFLAGS)
C_SOURCES = $(wildcard *.c)
C_OBJECTS = $(patsubst %.c, %.o, $(C_SOURCES))

build: $(C_OBJECTS)
	$(COMPILER_CALL) $(C_OBJECTS) -o $(EXECUTABLE_NAME)

%.o: %.c
	$(COMPILER_CALL) $< -c -o $@

在makefile有两种目标,一种是文件目标,比如test.o,还有一种是伪目标,例如build,对于伪目标最好通过.PHONY标记

.PHONY: build

如果需要创建目录,需要额外创建一个目标来处理

create:
	@mkdir -p build

@会隐藏命令回显,而-p指的是如果目录不存在则创建,还有点值得注意的是,每行命令其实是拥有单独的shell环境,所以以下代码

create:
	@mkdir -p build
	@cd build
	@touch test

这个create不会在build目录下创建文件,因为对于touch来说,当前目录并没有进入build,可以如下执行

create:
	@mkdir -p build && cd build && touch test

本文作者:c3n1g

本文链接:https://www.cnblogs.com/musing/p/18463119

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   c3n1g  阅读(18)  评论(0编辑  收藏  举报
(评论功能已被禁用)
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起