makefile c++11_makefile编写规则

makefile c++11_makefile编写规则视频:https://www.bilibili.com/video/BV1dW411n7vk?from=search&seid=13869936161616988114makefile可以试想一下,有一个上百个文件的代

视频:https://www.bilibili.com/video/BV1dW411n7vk?from=search&seid=13869936161616988114

可以试想一下,有一个上百个文件的代码构成的项目,如果其中只有一个或几个文件进行修改,需要从头到尾将每一个文件都重新编译是一个比较繁琐的过程。
为此,引入了Make工程管理器的概念,工程管理器指管理较多文件,自动根据文件时间自动发现更新过的文件而减少编译的工作量,同时通过读入Makefile文件来执行大量的编译工作。

makefile规则

规则:用于说明如何生成一个或多个目标文件

makefile文件里面可以有很多规则,但是第一个规则是最终生成的文件规则。

规则格式:

target: dependency_files // 目标项:依赖项
<tab>command	// 必须以tab开头,command编译命令

规则就是为了生成某一个文件的。
目标项:这个就是你要生成的文件名
依赖项:要生成目标项需要的文件
编译命令:如果有依赖项生成目标项;必须以TAB开头

在mekefile中,规则的顺序是很重要的。因为,Makefile中只应该有一个最终目标,其他的目标都是被这个目标所连带出来的,所以一定要让make知道你的最终目标是什么。一般来说,定义在Makefile中的目标可能会有很多,但是第一条规则中的目标将被确立为最终的目标

归结:

  1. 目标文件不存在,执行命令
  2. 文件已经更新了,执行命令
  3. Makefile的第一条规则为最终的目标。

例1:单文件

#include <stdio.h>

int main(int argc, int **argv)
{ 
   
    printf("hello world\n");
    return 0;
}

在这里插入图片描述
写成makefile如下

  1. 创建名称为makefile或者Makefile的文档
  2. 在文档中输入相应的内容
    test:test.c
    	gcc -o test test.c
    
  3. 运行makefile文件
    命令行输入
    make
    

    在这里插入图片描述

    如果马上再执行make命令
    在这里插入图片描述
    这是因为,make命令会对比源文件的修改时间,如果早于目标文件,说明源文件没有修改,就不会帮你再次编译了。

例2:多文件

test.c

#include <stdio.h>

extern void sort(int *arr, int len);
extern void show(int *arr, int len);

int main(int argc, int **argv)
{ 
   
    int arr[] = { 
   3, 2, 1, 5, 9, 8, 7};
    int len = sizeof(arr) / sizeof(arr[0]);
    sort(arr, len);
    show(arr, len);
    return 0;
}

void show(int *arr, int len)
{ 
   
    for (int i = 0; i < len; i++)
    { 
   
        printf("%d ", arr[i]);
    }
    printf("\n");
}

sequence.c

void sort(int *arr, int len)
{ 
   
    for (int i = 0; i < len; i++)
    { 
   
        for (int j = i; j < len; j++)
        { 
   
            if (arr[i] > arr[j])
            { 
   
                int temp = arr[i];
                arr[i] = arr[j];
                arr[j] = temp;
            }
        }
    }
}

makefile

test:test.o sequence.o
	gcc -o test test.o sequence.o
test.o:test.c
	gcc -o test.o -c test.c
sequence.o:sequence.c
	gcc -o sequence.o -c sequence.c

在这里插入图片描述

Makefile中特殊处理与伪目标

在这里插入图片描述

.PHONY是makefile文件中的关键字,表示它后面列表中的目标均为伪目标。

如:

.PHONY:b
b:
	echo 'b' # 通常用@echo "hello"

伪目标通常用在清理文件强制重新编译等情况下。一般伪目标没有时间的检查,一旦指明了就会执行。
如:

.PHONY:clean	//".PHONY"将"clean"目标声明为伪目标
clean:
	rm -f hello main.c func1.o func2.o

例3

继续例子2

修改Makefile文件

test:test.o sequence.o
	gcc -o test test.o sequence.o
test.o:test.c
	gcc -o test.o -c test.c
sequence.o:sequence.c
	gcc -o sequence.o -c sequence.c
.PHONY:clean rebuild
clean:
	rm -f test.o sequence.o test
rebuild:clean test

在这里插入图片描述
在这里插入图片描述

注意文件创建时间

Makefile的变量、规则与内置函数

变量

随着软件项目的变大、变复杂,源文件也越来越多,如果采用前面的方式写makefile文件,将会使makefile也变得复杂而难于维护。
通过make支持的变量定义、规则和内置函数,可以写出通用性较强的makefile文件,使得同一个makefile文件能够适应不同的项目。

变量:用来代替一个文本字符串
定义变量的2种方法:
	变量名=变量值 递归变量展开(几个变量共享一个值) // 不常用
	变量名:=变量值 简单变量展开(类似与C++的赋值)	// 通常采用这种形式
使用变量的一般方法:
	$(变量名)=??? // 赋值
	???=$(变量名) // 引用

变量分为用户自定义变量自动变量预定义变量环境变量

用户自定义变量

如:

OBJS:=test.o add.o
EXE:=test.exe
$(EXE):$(OBJS)
	gcc -o $(EXE) $(OBJS)
test.o:test.c
	gccc -c test.c
add.o:add.c
	gcc -c add.c
.PHONY:rebuild clean 
rebuild:clean $(EXE)
clean:
	rm -rf $(EXE) $(OBJS)

上面的例子就是用户自定义变量。

自动变量

值在使用的时候,自动用特定的值替换。
在这里插入图片描述
如:

OBJS:=test.o add.o
EXE:=test.exe
$(EXE):$(OBJS)
	gcc -o $@ $^
test.o:test.c
	gcc -c $^
add.o:add.c
	gcc -c $^
.PHONY:rebuild clean
rebuild:clean $(EXE)
clean:
	rm -rf $(EXE) $(OBJS)

预定义变量、环境变量(查看环境变量export)

内部事先定义好的变量,但是它的值是固定的,并且有些值是为空的

在这里插入图片描述
根据内部变量,可以将makefile改写为:TEST_file3文件夹。

OBJS:=test.o add.
EXE:=test.exe
$(EXE):$(OBJS)
	$(CC) -o $@ $^
test.o:test.c
	$(CC) -c $^
add.o:add.c
	$(CC) -c $^
.PHONY:rebuild clean 
rebuild:clean $(EXE)
clean:
	$(RM) $(EXE) $(OBJS)

规则:普通规则,隐含规则,模式规则

1、 普通规则

普通规则即基本语法规则

另外

  1. makefile里面的注释使用#
  2. 命令如果不想显示到终端,加@

2、隐含规则

例如:*.o文件自动依赖*.c*.cc文件,所以可以忽略main.o:main.c

OBJS:=test.o add.o
EXE:=test.exe
$(EXE):$(OBJS)
	$(CC) -o $@ $^
.PHONY:rebuild clean
rebuild:clean $(EXE)
clean:
	$(RM) $(EXE) $(OBJS)

省略了
在这里插入图片描述

3、模式规则

通过匹配模式找字符串,%匹配1或多个任意字符串。
%.o:%.cpp表示任何目标文件的依赖文件是与目标文件同名的并且扩展名为.cpp的文件

OBJS:=main.o fun.o
main.exe:$(OBJS)
	gcc $^ -o $@
%.o:%.cpp
	gcc -o $@ -c $^

另外还可以指定将*.o*.exe*.a*.so等编译到指定目录中

DIR:=./Debug/
EXE:=main.exe
OBJS:=main.o
$(DIR)$(EXE):$(DIR)$(OBJS)
	gcc -o $@ $< -L ./ -1func
$(DIR)main.o:main.c
	gcc -o $@ -c $^
.PHONY:rebuild clean
rebuild:clean $(DIR)$(EXE)
clean:
	rm -rf $(DIR)*.0 $(DIR)*.exe

注意:
当OBJS里面有多项的时候,此时$(DIR)$(OBJS)只能影响到OBJS第一个,后面的全部无效,因此需要全部列出来

函数

wildcard(搜索文件函数)

搜索当前目录下文件名,展开成一列所有符合由其参数描述的文件名,文件间以空格隔开

SOURCES=$(wildcard *.cpp)
// 把当前目录下所有.cpp文件存入变量SOURCES里

patsubst(字符替换函数)

格式:$(patsubst 要查找的子串, 替换后的目标子串, 源字符串)
将源字符串(以空格分隔)中的所有要查找的子串替换成目标子串
如:

OBJS=$(patsubst %.cvpp,%.o,$(SOURCES))

把SOURCES中.cpp替换为.o然后把替换后的字符串存入变量OBJS中

addprefix(加前缀函数)

格式:$(addprefix 前缀, 源字符串)
该函数把第二个参数列表里的每一项前缀加上第一个参数值。

make的命令行选项

在这里插入图片描述

其他

《GNU make 中文手册.pdf》

在这里插入图片描述

DIR:=./build/
OBJS=tt.o ConfigFile.o
DEPENDENCES:=$(addprefix $(DIR), $(OBJS))
EXE:=main
RM:=rm -rf
$(EXE):$(DEPENDENCES)
	gcc -o $(EXE) $(DEPENDENCES)
$(DIR)%.o:%.c
	gcc -o $@ -g -c $^
.PHONY:rebuild clean
rebuild:clean $(EXE)
clean:
	$(RM) $(DIR)* $(EXE)

今天的文章makefile c++11_makefile编写规则分享到此就结束了,感谢您的阅读。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/63814.html

(0)
编程小号编程小号

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注