• markfile 讲解1


    Makefile

    GNU Make官方网站:https://www.gnu.org/software/make/
    GNU Make官方文档下载地址:https://www.gnu.org/software/make/manual/

    1 基本格式

    targets : prerequisties
        command
    
    • 1
    • 2
    • target:目标文件,可以是OjectFile,也可以是执行文件,还可以是一个标签(Label),对于标签这种特性,在后续的“伪目标”章节中会有叙述。
    • prerequisite:要生成那个target所需要的文件或是目标。
    • command:是make需要执行的命令,

    2 Makefile规则

    (1)make会在当前目录下找到一个名字叫“Makefile”或“makefile”的文件。
    (2)如果找到,它会找文件中第一个目标文件(target),并把这个文件作为最终的目标文件。
    (3)如果target文件不存在,或是target文件依赖的.o文件(prerequities)的文件修改时间要比target这个文件新,就会执行后面所定义的命令command来生成target这个文件
    (4)如果target依赖的.o文件(prerequisties)也存在,make会在当前文件中找到target为.o文件的依赖性,如果找到,再根据那个规则生成.o文件。

    3 Makefile的变量

      变量在声明时需要给予初值,而在使用时,需要给在变量名前加上“$”符号,并用小括号“()”把变量给包括起来。

    3.1 变量的定义和使用

    • 定义
    include_paths := /usr/local/cuda-10.1/include \
                     /datav/lean/opencv4.5.1/include/opencv4 \
                     /datav/lean/tensorRT6.0.1.5_cuda10.1_cudnn7.6.0.3/include/ \
                     src \
                     src/tensorRT \
                     src/tensorRT/common \
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 使用
    include_paths := $(foreach item,$(include_path),-I(item))
    
    • 1

    3.2 Makefile常用的预定义变量

    • $@  目标(target)的完整名称。
    • $<  第一个依赖文件(prerequisties)的名称。
    • $^  所有的依赖文件(prerequisties),以空格分开,不包含重复的依赖文件。

    4 Makefile的常用运算符

    4.1 赋值:=

      用于变量的定义、赋值

    link_library := cudart opencv_core opencv_imgcodecs opencv_imgproc \
                     gomp nvinfer protobuf cudnn pthread \
                     cublas nvcaffe_parser nvinfer_plugin python3.8
    
    • 1
    • 2
    • 3

    4.2 累加+=

    cpp_compile_flags := -m64 -fPIC -g -O0 -std=c++11 -w -fopenmp
    
    cpp_compile_flags += $(include_paths)
    
    • 1
    • 2
    • 3

    5 Makefile的常用函数

      函数调用,很像变量的使用,也是以“$”来标识的,其语法如下:

    $( )
    
    • 1
    • 就是函数名,make 支持的函数不多。
    • 是函数的参数,参数间以逗号“,”分隔,而函数名和参数之间以“空格”分隔。

    5.1 shell

    $(shell  )
    
    • 1
    • 名称:shell命令函数——subst。

    • 功能:调用shell命令command

    • 返回:函数返回shell命令command的执行结果

    • 示例:

    cpp_srcs := $(shell find src -name "*.cpp") 
    
    
    • 1
    • 2

    5.2 patsubst

    $(patsubst ,,)
    
    • 1
    • 名称:模式字符串替换函数——patsubst。
    • 功能:查看 中的单词是否符合模式,如果匹配的话,则以替换。这里,可以包括通配符“%”,表示任意长度的字串。如果中也包含“%”,那么,中的这个“%”将是中的那个“%”所代表的字串。
    • 返回:函数返回被替换过后的字符串。
    • 示例:
    cpp_srcs := $(shell find src -name "*.cpp") #shell指令,src文件夹下找到.cpp文件
    cpp_objs := $(patsubst %.cpp,%.o,$(cpp_srcs)) #cpp_srcs变量下cpp文件替换成 .o文件
    
    
    • 1
    • 2
    • 3

    5.3 subst

    $(subst ,,)
    
    • 1
    • 名称:字符串替换函数——subst。
    • 功能:把字串 中的字符串替换成。
    • 返回:函数返回被替换过后的字符串。
    • 示例:
    cpp_srcs := $(shell find src -name "*.cpp") #shell指令,src文件夹下找到.cpp文件
    cpp_objs := $(patsubst %.cpp,%.o,$(cpp_srcs)) #cpp_srcs变量下cpp文件替换成 .o文件
    cpp_objs := $(subst src/,objs/,$(cpp_objs)) #cpp_objs 变量下替换后的 .o文件 从src文件夹移植到objs文件夹
    
    
    • 1
    • 2
    • 3
    • 4

    5.4 foreach

    $(foreach ,,)
    
    • 1
    • 名称:循环函数——subst。
    • 功能:把字串中的元素逐一取出来,执行包含的表达式
    • 返回:所返回的每个字符串所组成的整个字符串(以空格分隔)
    • 示例:
    library_paths := /datav/shared/100_du/03.08/lean/protobuf-3.11.4/lib \
                     /usr/local/cuda-10.1/lib64 \
    
    library_paths := $(foreach item,$(library_paths),-L$(item))
    
    
    • 1
    • 2
    • 3
    • 4
    • 5

    5.5 dir

    $(dir )
    
    • 1
    • 名称:取目录函数——dir。
    • 功能:从文件名序列中取出目录部分。目录部分是指最后一个反斜杠(“/”)之前
      的部分。如果没有反斜杠,那么返回“./”。
    • 返回:返回文件名序列的目录部分。
    • 示例:
    $(dir src/foo.c hacks)    # 返回值是“src/ ./”。
    
    • 1

    6 伪目标

      “伪目标”不是一个文件,只是一个标签,。我们要显示地指明这个“目标”才能让其生效。“伪目标”的取名不能和文件名重名,不然其就失去了“伪目标”的意义了。

      为了避免和文件重名的这种情况,我们可以使用一个特殊的标记“.PHONY”来显示地指明一个目标是“伪目标”,向 make 说明,不管是否有这个文件,这个目标就是“伪目标”。

    .PHONY : clean
    
    • 1

      只要有这个声明,不管是否有“clean”文件,要运行“clean”这个目标,只有“make clean”。

    7 编译过程

    7.1 总览

    源文件[.c/cpp] -> 预处理成[.i/.ii] -> 编译成[.s] -> 汇编成[.o] -> 链接成可执行文件
    
    • 1

    7.2 包含静态库的编译过程

    步骤:

    (1)源文件[.c/cpp] -> Object文件[.o]

    g++ -c [.c/cpp][.c/cpp]... -o [.o][.o]... -I[.h/hpp] -g
    
    • 1

    (2)Object文件[.o] -> 静态库文件[lib库名.a]

    ar -r [lib库名.a] [.o][.o]...
    
    • 1

    (3)main文件[.c/cpp] -> Object文件[.o]

    g++ -c [main.c/cpp] -o [.o] -I[.h/hpp] -g
    
    • 1

    (4)链接 main的Object文件 与 静态库文件[lib库名.a]

    g++ [main.o] -o [可执行文件] -l[库名] -L[库路径]
    
    • 1

    7.3 包含动态库(共享库)的编译过程

    步骤:

    源文件[.c/cpp] -> Object文件[.o]

    g++ -c [.c/cpp][.c/cpp]... -o [.o][.o]... -I[.h/hpp] -g -fpic
    
    • 1

    Object文件[.o] -> 静态库文件[lib库名.a]

    g++ -shared [.o][.o]... -o [lib库名.so] 
    
    • 1

    main文件[.c/cpp] -> Object文件[.o]

    g++ -c [main.c/cpp] -o [.o] -I[.h/hpp] -g
    
    • 1

    链接 main的Object文件 与 静态库文件[lib库名.a]

    g++ [main.o] -o [可执行文件] -l[库名] -L[库路径] -Wl,-rpath=[库路径]
    
    • 1
  • 相关阅读:
    Python基础(一) | Python的基本语法
    flask基础3-蓝图-cookie-钩函数-flask上下文-异常处理
    泰裤辣!!!手摸手教学,如何训练一个你的专属AI歌姬~
    淘宝API接口:提高电商运营效率与用户体验的利器(淘宝API接口使用指南)
    算法设计与分析复习(一)
    非零基础自学Java (老师:韩顺平) 第14章 集合 14.4 List 接口和常用方法
    js控制手机蓝牙
    arcgis pro植被冠层分析及单木识别
    基于javaweb的鲜花商城系统(java+jsp+javascript+bootstrap+mysql)
    交换机和路由器技术-25-OSPF多区域配置
  • 原文地址:https://blog.csdn.net/weixin_38346042/article/details/128153578