5makefile
makefile编译多个可执行文件
1: 多个 C 文件编译成不同的目标文件
2: 多个 C 文件编译成 一个目标文件
注意:makefile的文件名的三种形式(优先级排序)
makefile>Makefile>GNUMakefile
简单说,makefile类似快捷键。
如:创建主函数文件mian.c 函数文件func.c
编译二进制:
gcc -g -Wall -c main.c -o mian.o
gcc -g -Wall -c func.c -o func.o
链接并生成可执行文件:
gcc -Wall main.o func.o -o main
此时可以看到只用两个文件都如此麻烦,一旦许多文件呢?或对mian.c进行修改后,还要再一次编译
解决方式:
创建一个makefile的文件:
main:main.o func.o
gcc -g -Wall mainn.o func.o -o main
main.o:main.c
gcc -g -Wall -c mainn.c func.o -o main.o
func.o:func.c
gcc -g -Wall -c func.c func.o -o func.o
执行:make
解析:
main依赖于main.o func.o,一定要就此句在第一个。因此makefile只编译第一个语句。main.o,func.o将会向下寻找。即使重新修改文件内容,只需再一次make就自动编译
如果:
main.o:main.c
gcc -g -Wall -c mainn.c func.o -o main.o
main:main.o func.o
gcc -g -Wall mainn.o func.o -o main
func.o:func.c
gcc -g -Wall -c func.c func.o -o func.o
此时,只编译
main.o:main.c
gcc -g -Wall -c mainn.c func.o -o main.o
后面两个不进行编译。
make工具
自动完成编译工作
1:修改某个文件后,只重新编译修改的文件
2:修改某个头文件后,重新编译所有包含该头文件的文件
makefile 描述了整个工程编译,链接的规则
make工具通过makefile文件来完成、维护编译工作
makefile基本规则
Target ... : dependencies ...
[ Tab ] command
...
Target: 程序生成的文件,或者要指向的动作,如clean
dependencies:目标文件依赖的文件
command:make执行的动作(以 TAB字符开始!!!)
dependencies 中文件更新时候,执行command
例子:
main:main.o add.o sub.o
gcc -Wall -g main.o sub.o add.o -o main
main.o:main.c
gcc -Wall -g -c main.c -o main.o
add.o:add.c add.h
gcc -Wall -g -c add.c -o add.o
sub.o:sub.c sub.h
gcc -Wall -g -c sub.c -o sub.o
clean:
rm -f main main.o add.o sub.o
make ==》按需生成文件
make ==》修改时间未改变,则不会重新编译
make ... 生成某个目标(或者伪目标clean),不加则默认生成第一个模板
显式指定伪目标
上面的makefile文件,如果目录下存在clean文件
结果: make clean失效
解决办法:需要显示指定 clean 是伪目标, 文件开头加上:.PHONY:clean
.PHONY: 表示这是一个伪目标
定义变量
makefile自动化变量
$@: 规则的目标文件名
$< : 规则的第一个依赖文件名
$^ : 规则的所有依赖文件列表
举例 add.o:add.c add.h
$@ 为 add.o
$< 为 add.c
$^ 为 add.c add.h
自定义变量
var=....... ? 使用变量 $(var)
使用变量的例子:
.PHONY:clean
OBJ=main.o add.o sub.o
main:$(OBJ)
gcc -Wall -g $^ -o $@
main.o:main.c
gcc -Wall -g -c $< -o $@
add.o:add.c add.h
gcc -Wall -g -c $< -o $@
sub.o:sub.c sub.h
gcc -Wall -g -c $< -o $@
clean:
rm -rf $(OBJ)
改进:
.PHONY:clean
BIN=main
CC=gcc
CFLAGS=-Wall -g
OBJ=main.o add.o sub.o
$(BIN):$(OBJ)
$(CC) $(CFLAGS) $^ -o $@
main.o:main.c
$(CC) $(CFLAGS) -c $< -o $@
add.o:add.c add.h
$(CC) $(CFLAGS)-c $< -o $@
sub.o:sub.c sub.h
$(CC) $(CFLAGS) -c $< -o $@
clean:
rm -rf *.o $(BIN)
自定义的变量一般使用大写。
注意:通过 –f 参数,指定需要用到的makefile文件make –f makefile.1 自定义使用的makefile文件
自动推导
编译器会自动推导,
同名的 .c 文件生成同名目标文件
默认使用隐含方式生成,不想使用自动推导则自行添加生成方式
cc –c –o xxx.o xxx.c
模式匹配
规则 1:
%.o:%.c
gcc -Wall -g -c $< -o $@
规则2:
.c.o:
gcc -Wall -g -c $< -o $@
规则2注意 .c.o之间不能由空格
编译目录下所有.c 文件
$(BIN):%:%.o
所有的 $(BIN) 文件生成规则:
$(BIN)中没有扩展名的文件依赖于对应扩展名为.o 的文件
编译多个可执行文件
makefile 默认生成第一个对象
要生成对个对象的话,可以使用自定义变量
.PHONY:clean all
OBJ=test1 test2
all:$(OBJ)
...
这里: all 是一个伪目标,makefile 要生成 all, 也就是 test1, test2
make常用内嵌函数
函数调用
$(function arguments)
$(wildcard 模式)
当前目录下匹配模式的文件:
获取所有.c文件
src = $(wildcard *.c)
把src的 .c替换为.o
$(src :%.c=%.o)
obj = $(src:%.c=%.o)
shell函数
执行shell命令: $(shell ls –d */) 获取所有子目录
例子改进:
.PHONY:clean all
SRC=$(wildcard *.c)
OBJ=$(SRC:%.c=%.o)
BIN=$(SRC:$.c=%)
CC=gcc
CFLAGS=-Wall -g
all:$(BIN)
%.o:%.c
$(CC) $(SFLAGS) $^ -o %@
clean:
rm -f $(BIN) $(OBJ)
多级目录makefile
SUBDIRS=test1 test2
.PHONY:default all clean $(SUBDIRS)
default:all #无参数,则生成all
all clean: #all 和 clean都依赖下面语句
$(MAKE) $(SUBDIRS) TARGET=$@ #make test1 test2 ;赋值 TARGET=all
$(SBUDIRS):
$(MAKE) -C $@ $(TARGET)
#make –C test1 all: 调用test1中make,并以all为入参。 make test1/makefile all
注意-C大写
C语言版
makefile万能模板:
.PHONY:clean all
SRC=$(wildcard *.c)
BIN=$(SRC:%.c=%)
CC=gcc
CFLAGS=-g -Wall
all:$(BIN)
clean:
rm -rf $(BIN)
~
C++版
.PHONY:all clean
SRC=$(wildcard *.c)
BIN=$(SRC:%.c=%)
CPPSRC=$(wildcard *.cpp)
CPPBIN=$(CPPSRC:%.cpp=%)
CC=gcc
CXX=g++
CFLAGS=-g -Wall
CXXFLAGS=-g -Wall -std=c++11
all:$(BIN) //$(CPPBIN)
clean:
rm -rf $(BIN) //$(CPPBIN)
5makefile的更多相关文章
- 【Makefile】5-Makefile变量的基础
目录 前言 概念 Chapter 5:变量的基础 5.1 变量的基础 * 空格的定义 ** 一些赋值 一些特殊的符号 5.2 变量中的变量 * 5.3 变量高级用法 变量值替换 把变量的值再当成变量 ...
- 嵌入式Linux-GNU Make 使用手册(中译版)
GNU Make 使用手册(中译版) 翻译:于凤昌 译者注:本人在阅读Linux源代码过程中发现如果要全面了解Linux的结构.理解Linux的编程总体设计及思想必须首先全部读通Linux源代码中各级 ...
- PostgreSQL杂记页
磨砺技术珠矶,践行数据之道,追求卓越价值 luckyjackgao@gmail.com 返回顶级页:PostgreSQL索引页 此页,记录其他数据库,linux以及各种点滴事项 1--数据库设计 1 ...
随机推荐
- MySQL开启预编译环境
Mysql是默认 没有开启预编译的,需要在配置中加上 jdbc:mysql://xxx.22.11.31:3306/dbname?useServerPrepStmts=true
- mySQL数据库二:命令行的使用
在做整理的时候,上一篇刚开始只是简单的做了个数据类型的开头,在这里简单说一下mySQL的使用以及它的命令行 1.准备工作 有一个好的开发工具可以几何倍数的增加我们的工作效率,所以,工具是必不可少的,首 ...
- JS控制元素可见(显示)与不可见(隐藏)
方法一: document.getElementById("id").style.visibility="hidden"; document.getElemen ...
- 实现类似printf这样的函数
来源:http://www.vimer.cn/2009/12/cc%E5%AE%9E%E7%8E%B0%E5%A4%9A%E5%8F%82%E6%95%B0%E5%87%BD%E6%95%B0%E7% ...
- Android英文文档翻译系列(1)——AlarmManager
原文:个人翻译,水平有限,欢迎看官指正. public class Ala ...
- bigpipe&bigrender
bigpipe: 先输出页面的整体布局,在按块输出输出页面的每个部分.这样可以让服务器的运算.网络的传输和浏览器的渲染并行.适用于服务器运算较慢的时候. bigrender: 主要在浏览器端,先将字符 ...
- 【BZOJ2157】旅游 树链剖分+线段树
[BZOJ2157]旅游 Description Ray 乐忠于旅游,这次他来到了T 城.T 城是一个水上城市,一共有 N 个景点,有些景点之间会用一座桥连接.为了方便游客到达每个景点但又为了节约成本 ...
- 【JavaScript算法】---希尔排序
一.什么是希尔排序 希尔排序(Shell's Sort)是插入排序的一种又称“缩小增量排序”,是直接插入排序算法的一种更高效的改进版本. 思路: 希尔排序是把记录按下标的一定增量分组,对 ...
- MySQL实现根据当前ID读取上一条和下一条记录
以下为MySQL语句演示: SELECT * FROM t_news AS n ORDER BY n.`News_ID` 当前ID为4,读取上一条记录: ,; 当前ID为4,读取下一条记录: ,; 其 ...
- jenkins之jenkins与gitlab集成
实现当git代码使用push的时候自动构建 安装gitlab钩子插件 安装令牌认证插件 在主机上面生产token(其实随便弄一个简单的字符串也可以) openssl rand -hex 10 修改任务 ...