栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

C语言-Makefile-学习笔记12

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

C语言-Makefile-学习笔记12

文章目录
  • 1. Make简介
  • 2. Makefile基本结构
  • 3. 创建和使用变量
  • 4. Make使用
  • 5. Makefile的VPATH
  • 6. Makefile综合实战

1. Make简介
  • 工程管理器,顾名思义,是指管理较多的文件
  • Make工程管理器也就是个“自动编译管理器”,这里的“自动”是指他能根据文件时间戳自动发现更新过的文件而减少编译工作量,同时,他通过读入Makefile文件的内容来执行大量的编译工作
  • Make将只编译改动的代码,而不是完全编译
2. Makefile基本结构
  • Makefile是Make读入的唯一配置文件
  • 由make工具创建的目标体(target),通常是目标文件或可执行文件
  • 要创建的目标体所依赖的文件(dependency_file)
  • 创建每个目标体时需要运行的命令(command)
  • 注意:命令行前面必须是一个TAB键,否则编译错误
  • 用法:新建一个Makefile文档,完成后在终端make一下就编译好了
target: dependency_files
	command
  • 例1:
hello.o: hello.c hello.h
	gcc -c hello.c -o hello.o
  • 例2:
test: f1.o f2.o main.o
	gcc f1.o f2.o main.o -o test
f1.o: f1.c
	gcc -c f1.c -o f1.o
f2.o: f2.c
	gcc -c f2.o -o f2.o
main.o: main.c -o main.o
	gcc -c main.c -o main.o
  • 如果想要删除生成相关的*.o文件可以用clear,见下面这个例子,在终端输入make clear就好了
test: f1.o f2.o main.o
	gcc f1.o f2.o main.o -o test
f1.o: f1.c
	gcc -c f1.c -o f1.o
f2.o: f2.c
	gcc -c f2.o -o f2.o
main.o: main.c -o main.o
	gcc -c main.c -o main.o
PHONY: clean
	rm *.o test
3. 创建和使用变量
  • 定义变量的两种方式

    • :=:直接赋值,常规赋值方式,一赋值马上有效。在没赋值是为空字符。
    • ?=:仅仅在变量还没赋值的情况下才有效,所有一般用在第一次赋值
    • +=:在变量后加上字符
    • VAR=var:递归展开方式,赋值后并不马上生效,等到使用时才真正的赋值,此时通过递归找出当前的值,所有在使用是很有可并不是开始赋的值
  • 使用变量:$(VAR),如果要用$符号则需要$$来表示

  • 举例

OBJS = kang.o yul.o
CC = gcc
CFLAGS = -Wall -O -g
sunq: $(OBJS)
	$(CC) $(OBJS) -o sunq
kang.o: kang.c kang.h
	$(CC) $(CFLAGS) -c kang.c -o kang.o
yul.o: yul.c yul.h
	$(CC) $(CFLAGS) -c yul.c -o yul.o
  • 注意:不能CFLAGS = $(CFLAGS) -O进行扩展,会造成死循环
  • 预定义变量
预定义变量解释
AR库文件维护程序的名称,默认值为ar
AS汇编程序的名称,默认值为as
CCC编译器的名称,默认值为cc
CPPC预编译器的名称,默认值为$(CC) -E
CXXC++编译器的名称,默认值为g++
FCFORTRAN编译器的名称,默认值为f77
RM文件删除程序的名称,默认值为rm -f
ARFLAGS库文件维护程序的选项,无默认值
ASFLAGS汇编程序的选项,无默认值
CFLAGSC编译器的选项,无默认值
CPPFLAGSC预编译的选项,无默认值
CXXFLAGSC++编译器的选项,无默认值
FFLAGSFORTRAN编译器的选项,无默认值
  • 举例
Hello: main.c main.h
	$(CC) -o hello main.c
clean
	$(RM) hello
  • 自动变量
自动变量解释举例
test: f1.o f2.o main.o
$*不包括扩展名的目标文件名称hello.c->hello.o,我们可以用$*.o
$+所有的依赖文件,以空格分开,并以出现的先后为序,可能包含重复的依赖文件
$<第一个依赖文件的名称f1.0
$?所有时间戳比目标文件晚的依赖文件,并以空格分开
$@目标文件的完整名称test
$^所有不重复的目标依赖文件,以空格分开f1.o f2.o main.o
$%如果目标是归档成员,则该变量表示目标归档成员名称
  • 举例
OBJS = f1.o f2.o
OBJS += main.o
CC = gcc
CFLAGS = -Wall -O -g
test: $(OBJS)
	gcc $(CFLAGS) $(OBJS) -o $@
f1.o: f1.c
	gcc -c $^ -o $@
f2.o: f2.c
	gcc -c $< -o $@
main.o: main.c
	gcc -c main.c -o main.o
.PHONY: clean
clean:
	$(RM) *.o test
  • 环境变量
    • make在启动时会自动读取系统当前已经定义了的环境变量,并且会创建与之具有相同名称和数值的变量
    • 如果用户在Makefile中定义了相同名称的变量,那么用户自定义变量会覆盖同名的环境变量
4. Make使用
  • 用法:make [option] [param]
  • 选项
选项解释
-C dir读入指定目录下的Makefile
-f file读入当前目录下的file文件作为Makefile
-i忽略所有的命令执行错误
-l dir指定被包含的Makefile所在目录
-n只打印要执行的命令,但不执行这些命令
-p显示make变量数据库和隐含规则
-s在执行命令时不显示命令
-w如果make在执行过程中改变目录,打印当前目录名
  • 隐含规则1:.o的目标的依赖目标会自动推导为.c,并且其生成命令是$(CC) -c $(CPPFLAGS) $(CFLAGS),下面的代码运用了隐含规则,因此也可以正常执行
OBJS = f1.o f2.o
OBJS += main.o
CC = gcc
CFLAGS = -Wall -O -g
test: $(OBJS)
	gcc $(CFLAGS) $(OBJS) -o $@
f1.o: f1.c
f2.o: f2.c
main.o: main.c
.PHONY: clean
clean:
	$(RM) *.o test
  • 隐含规则2:链接Object文件的隐含规则 ,通过运行C的编译器来运行链接程序生成(一般是ld),其生成命令是:$(CC) $(LDFLAGS) .o $(LOADLIBES) $(LDLIBS),这个规则对一个或多个Object文件都生效。
    用法: 文件*: 文件1.o 文件2.o 文件3.o ...,需要注意生成文件名必须是文件1、文件2或文件3中的一个
    举例:最终我们的Makefile可以简化成下面的代码
f1: f1.o f2.o main.o
.PHONY: clean
clean:
	$(RM) *.o main
5. Makefile的VPATH
  • 通常在项目中会把文件放在不同的目录下进行分类。我们可以告诉make我们文件的路径,让make自己找
  • VPATH完成了这个功能,如果没有指明这个变量,make只会在当前目录下找,如果定义里VPATH,make会在当前目录找不到的情况下,到指定目录下寻找。
  • 用法:VPATH = 路径1: 路径2: ...
  • 举例:VPATH = src: ../headers,make会按照这个顺序进行搜索
  • 举例:
    首先,先介绍下我们现在文件的位置
    ├── makefile
    │   ├── include
    │   │   └── head.h
    │   ├── main
    │   │   └── main.c
    │   ├── Makefile
    │   ├── src1
    │   │   └── f1.c
    │   └── src2
    │       └── f2.c
    
    如果不用VPATH,我们的Makefile如下所示
    CC = gcc
    CFLAGS = -Wall -I include
    f1: src1/f1.o src2/f2.o main/main.o
    	$(CC) $(CFLAGS) $^ -o $@
    .PHONY: clean
    clean:
    	find ./ -name "*.o" -exec rm {} ;;rm f1
    
    如果用VPATH,我们的代码如下所示
    CC = gcc
    CFLAGS = -Wall -I include
    VPATH = src1:src2:main
    f1: f1.o f2.o main.o
    	$(CC) $(CFLAGS) $^ -o $@
    .PHONY: clean
    clean:
    	find ./ -name "*.o" -exec rm {} ;;rm f1
    
6. Makefile综合实战
  • 文件结构如下图所示
  • ./f1目录下的Makefile代码如下所示
../$(OBJS_DIR)/f1.o: f1.c
	$(CC) -c $^ -o $@
  • ./f2目录下的Makefile代码如下所示
../$(OBJS_DIR)/f2.o: f2.c
	$(CC) -c $^ -o $@
  • ./main目录下的Makefile代码如下所示
../$(OBJS_DIR)/main.o: main.c
	$(CC) -c $^ -o $@
  • 主目录下的Makefile
CC = gcc
SUBDIRS = f1 
  		  f2 
  		  main 
  		  obj 
OBJS = f1.o f2.o main.o
BIN = myapp
OBJS_DIR = obj
BIN_DIR = bin
export CC OBJS BIN OBJS_DIR BIN_DIR #把变量传给子目录makefile

all: CHECK_DIR $(SUBDIRS)
CHECK_DIR:
	mkdir -p $(BIN_DIR) #生成一个bin目录
$(SUBDIRS): ECHO #ECHO是打印
	make -C $@
ECHO:
	@echo $(SUBDIRS) #加@是打印不提示
	@echo begin compile
clean:
	@$(RM) $(OBJS_DIR)/*.o
	@rm -rf $(BIN_DIR)
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/931675.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号