MakeFile
1.基础知识学习
1.编译基础
-
- 后缀含义
.a 文件是一种静态库文件,通常由编译器生成,并用于链接到其他程序中
.c C语言后缀文件
.h C语言头文件
.i 预处理文件
.o 目标文件
.s 汇编文件
.so 动态库
- 2.编译过程
C语言编译过程 源文件.c -> 预编译文件.i ->汇编语言文件.s -> 汇编文件.o -> 链接成可执行文件
- 3.编译
gcc -s tree.c -o tree.o 编译成汇编语言
gcc tree.c 生成tree.out文件
./tree.out 执行文件
- 3.静态库
gcc -c add.c tree.c
ar -r liboperation.a add.o tree.o
gcc main.c liboperation.a -0 exec
./exec
- 4.动态库
gcc -c -fpic add.c tree.c
gcc -shared add.o tree.o -o liboperation.so
gcc tree.c -o exec -loperation -L/home/sun/code/C/datastruct/tree
2.MakeFile
1.基本语法
- 1.make使用
make <任务名称> 例如 make hello
hello :
@echo hello
make 自动执行Makefile第一个任务
- 2.缩写
src : obj i
@echo $^
@echo $<
@echo $@
obj :
i :
# $@ 代表":"前面字符串 如:src
# $< 代表":" 后面第一个字符串 如:obj
# $^ 代表“:” 后面所有字符串 如:obj i
- 3.赋值
:= 赋值后不能修改
+= 累加
\续行符
2.常用函数
- 1.shell
以find为例
pp := $(shell find . -name '*.c')
pip :
@echo ${pp}
- 2.subst方法 替换字符串
substtest := $(subst o,l,oive)
substtask :
@echo ${substtest}
# subst 替换前字符,替换后字符,目标字符
打印:live
- 3.foreach遍历
path := /home/sun/code/C/datastruct/tree/day01/add.c \
/home/sun/code/C/datastruct/tree/day01/tree.c
fortest := $(foreach item,${path},${item})
fortesttask :
@echo ${fortest}
# foreach 第三个参数${item}可以随意拼接 如 $(foreach item,${path},-I${item})
打印:-I/home/sun/code/C/datastruct/tree/day01/add.c
-I/home/sun/code/C/datastruct/tree/day01/tree.c
- 4.dir 获取目录
cpp := day02/main.cpp
src := $(dir ${cpp})
path :
@echo ${cpp}
@echo ${src}
# 打印
day02/main.cpp
day02/
- 5.patsubst 替换文本
obj=$(patsubst %.cpp, %.o, 11.cpp 22.cpp 33.cpp)
objtask:
@echo $(obj)
打印:
11.o 22.o 33.o
# 参数一 替代文字
# 参数二 替代后文字
# 参数三 输入文本
- 6.notdir 去处目录
lib := $(shell find /usr/lib -name 'lib*')
dirtask :
@echo ${lib}
打印:
/usr/lib/xorg/modules/libvgahw.so
libs := $(notdir $(shell find /usr/lib -name 'lib*'))
notdirtask :
@echo ${libs}
# 打印:libvgahw.so
# 可以看到:notdir去掉了目录,只保留文件名
- 7.filter
libs := $(notdir $(shell find /usr/lib -name 'lib*'))
a_libs := $(filter %.a,${libs})
notdirtask :
@echo ${a_libs}
# filter 从libs字符串中过滤带有.a后缀的文件
- 8.basename
name :=libfile.so
libname := $(basename ${name})
nametask:
@echo ${libname}
# 打印:libfile
# 取出文件后缀
3.编译选项
- -m64:指定编译为64位应用程序
- -std=:制定编译标准,例如:-std=c++11、-std=c++14
- -g:包含调试信息
- -w:不显示警告
- -O:优化等级,通常使用:-O3
- -I:加在头文件路径前
- fPIC:
4.链接选项
- -l : 加在库名前面
- -L :加在库路径前面
- -Wl,<选项> :将逗号分割的<选项>传递给链接器
- -rpath= : 运行时候,去找目录。运行时候要找.so文件,会从这个选项里指定地方去找。
5.举例
- 例一
使用Makefile编译day02/main.cpp。如下文件:
#include<stdio.h>
int main(){
printf("Hello Word\n");
return 0;
}
Makefile配置
cpp_srcs := $(shell find day02 -name *.cpp)
cpp_i := $(patsubst day02/%.cpp,day02/%.o,$(cpp_srcs))
day02/%.o : day02/%.cpp
@echo build -o
@mkdir -p ${dir $@}
@g++ -c $< -o $@
clean :
@rm -f day02/*.i day02/*.o day02/*.s
workspace/exec : ${cpp_i}
@echo build workspace/exec
@mkdir -p ${dir $@}
@g++ $< -o $@
#编译C语言并执行
run : workspace/exec
@./$<
debug :
@echo $(cpp_i)
.PHONY : debug
目录供参考
- 例二
c文件:src目录下:add.cpp main.cpp minus.cpp
/*main.cpp代码*/
#include<stdio.h>
#include<add.hpp>
#include<minus.hpp>
int main(){
int a =10;
int b = 5;
int result = add(a,b);
int result1 = minus(a,b);
printf("a + b =%d\n",result);
printf("a - b =%d\n",result1);
}
/*add.cpp代码*/
#include<add.hpp>
int add(int a,int b){
return a+b;
}
/*minus.cpp代码*/
#include<minus.hpp>
int minus(int a,int b){
return a-b;
}
- include目录下:add.hpp minus.hpp
/*add.hpp代码*/
#ifndef A496740A_676F_441B_9149_5097BEBC7124
#define A496740A_676F_441B_9149_5097BEBC7124
int add(int a,int b);
#endif /* A496740A_676F_441B_9149_5097BEBC7124 */
/*minus.hpp代码*/
#ifndef E5A7F71C_6DC0_4C53_806D_12818A214AC8
#define E5A7F71C_6DC0_4C53_806D_12818A214AC8
int minus(int a,int b);
#endif /* E5A7F71C_6DC0_4C53_806D_12818A214AC8 */
Makefile 使用make run
cpp_srcs :=$(shell find src -name '*.cpp')
cpp_object := $(patsubst src/%.cpp,objes/%.o,$(cpp_srcs))
include_paths := /home/sun/code/C/datastruct/tree/day03/include
I_flags := $(include_paths:%=-I%)
comile_option := -m64 -g -O3 -w $(I_flags)
objes/%.o : src/%.cpp
@mkdir -p $(dir $@)
@g++ -c $< -o $@ $(comile_option)
workspace/exec : $(cpp_object)
@mkdir -p $(dir $@)
@g++ $< -o $@
run : workspace/exec
@./$<
debug :
@echo $(I_flags)
@echo $(comile_option)
@echo Build Ok!
目录: