MakeFile学习

110 阅读2分钟

MakeFile

1.基础知识学习

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

目录供参考

Screenshot-1.png

  • 例二

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!

目录:

image.png