如何写一个makefile

功能

一个工程中源代码不计其数,其按类型、功能、模块分别放在若干个目录中。

如src:.c/.cpp源代码

include:.h头文件

lib:libxx.so/libxx.a库

bin:生成的二进制文件

obj:生成的.o文件,用于下一步的动态链接

makefile制定了一系列规则来指定 哪些文件需要编译,怎么编译的,先后顺序是怎么样的。

makefile就像shell脚本一样,可以执行操作系统的命令,只需要make,make clean指令即可实现自动化编译和自动化删除构建的文件,极大提高了开发效率。

一般来说,大多数的IDE都有这个命令,比如:Delphi的make,Visual C++的nmake,Linux下GNU的make。可见,makefile都成为了一种在工程方面的编译方法。

Cmake(Cmakelist.txt)也是一种自动化编译的工具,其编写更复杂,底层还是通过自动生成makefile文件再执行make命令的。

configure脚本也是一种自动化编译的工具,执行./configure后根据脚本生成makefile,再执行make命令。

make规则

target: prerequisites

command

#target是生成的文件

#prerequisites是需要的文件

#command是这个过程中需要执行的命令

其实就是根据makefile文件定义的编译流程,不断倒推执行,知道编译出最终的target,如下是一个简单的例子

main:file1.o file2.o
gcc -o main  file1.o file2.o

file1.o:file1.c
gcc file1.c -o file1.o

file2.o:file2.c
gcc file2.c -o file2.o

如果编译需要指定编译选项,文件不在同一目录,编译过程需要指定头文件路径,编译后的结果也应该跟源文件分开放,编译器需要能方便同时管理,接下来看下面的例子

假设项目目录是

project/

├── Makefile

├── src/

│ ├── main.c

│ ├── foo.c

│ ├── foo.h

│ ├── bar.c

│ └── bar.h

├── include/

│ └── common.h

├── lib/

│ └── libmylib.a

├── test/

│ ├── test_foo.c

│ └── test_bar.c

└── build/

# 指定编译器和链接器
CC = gcc
CXX = g++
AR = ar

# 编译选项
CFLAGS = -Wall -Wextra -Iinclude -g
LDFLAGS = -Llib -lmylib

# 目标可执行文件名称
TARGET = build/myprogram

# 源文件和对象文件
SRCS = src/main.c src/foo.c src/bar.c
OBJS = $(SRCS:%.c=build/%.o)

# 单元测试
TEST_SRCS = test/test_foo.c test/test_bar.c
TEST_OBJS = $(TEST_SRCS:%.c=build/%.o)
TEST_TARGET = build/tests

# 默认目标
all: $(TARGET)

# 链接目标可执行文件
$(TARGET): $(OBJS)
	$(CC) $(LDFLAGS) -o $@ $^

# 编译对象文件
build/%.o: %.c
	@mkdir -p $(dir $@)
	$(CC) $(CFLAGS) -c -o $@ $<

# 单元测试目标
tests: $(TEST_TARGET)
	$(TEST_TARGET)

# 链接单元测试可执行文件
$(TEST_TARGET): $(OBJS) $(TEST_OBJS)
	$(CC) $(CFLAGS) -o $@ $^

# 静态库生成
lib/libmylib.a: $(OBJS)
	$(AR) rcs $@ $^

# 清理
clean:
	rm -rf build

# 伪目标
.PHONY: all clean tests

想要看懂以上代码需要以下知识:

  • 使用“=”,进行变量定义,类似于宏,当想改变全局的某一变量,如编译器,只需要改变定义
  • OBJS = $(SRCS:%.c=build/%.o)表示源文件对应的对象文件,这里指build/main.o build/foo.o build/bar.o
  • 为了方便指代target和prerequisites,使用$@、$^、$<分别代表target、所有依赖文件列表、第一个依赖文件名

以上是本人学习过程中的认识,如有错误,请指正批评

  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值