makefile 完美教程

2023-05-16

简介

Makefile 是和 make 命令一起配合使用的,很多大型项目的编译都是通过 Makefile 来组织的,。
我建立工程的方法有以下三点:
1.makefile:
优点:使用非常广泛,通用性强,可跨平台。
缺点:语法比较蛋疼。要写出一个通用,便于管理,且兼容性强的makefile比较困难。

2.cmake:
优点:简单易用,使用较广泛,方便管理,可跨平台。
缺点:自动生成的makefile太臃肿。

3.sh脚本:
优点:自由,高度定制。简单易用,可操作性强。方便维护。(甚至还可以生成makefile)
缺点:sh建的工程太少了(估计没人这么搞吧)

但我考虑到方便移植和管理其他人的工程还是选择了第一种,以makefile建立管理工程。(其实我的内心是比较向往第三种sh脚本建工程的)。下面来介绍下makefile的规则以及语法

PS:我本意是想写短一点的,只是想写点常用的东西,方便大家查阅。精炼了这么久,可还有这么多内容(15000字)。所以,大家还是耐心的学习吧,想学好linux这是必不可少的一步。


规则

说明

<target1 > <target2>.... : <prerequisites1> <prerequisites2>...
[TAB] <command1>
[TAB] <command2>
...

target可以是一个object file(目标文件),也可以是一个执行文件,还可以是一个标签(label)。对于标签这种特性,在后续的“伪目标”章节中会有叙述。

<prerequisites>就是,要生成那个target所需要的文件或是目标。

<command>也就是make需要执行的命令。(任意的shell命令)

这是一个文件的依赖关系,也就是说,<target>这一个或多个的目标文件依赖于<prerequisites>中的文件,其生成规则定义在 <command>中。说白一点就是说,<prerequisites>中如果有一个以上的文件比<target>文件要新的话,<command>所定义的命令就会被执行。这就是makefile的规则。也就是makefile中最核心的内容。

经典示例

原始版本

objects = main.o kbd.o command.o display.o \
		insert.o search.o files.o utils.o

edit : $(objects)
	cc -o edit $(objects)
main.o : main.c defs.h
	cc -c main.c
kbd.o : kbd.c defs.h command.h
	cc -c kbd.c
command.o : command.c defs.h command.h
	cc -c command.c
display.o : display.c defs.h buffer.h
	cc -c display.c
insert.o : insert.c defs.h buffer.h
	cc -c insert.c
search.o : search.c defs.h buffer.h
	cc -c search.c
files.o : files.c defs.h buffer.h command.h
	cc -c files.c
utils.o : utils.c defs.h
	cc -c utils.c
clean :
	rm edit $(objects)

自动推导版本

objects = main.o kbd.o command.o display.o \
		insert.o search.o files.o utils.o
 cc = gcc

edit : $(objects)
	cc -o edit $(objects)

main.o : defs.h
kbd.o : defs.h command.h
command.o : defs.h command.h
display.o : defs.h buffer.h
insert.o : defs.h buffer.h
search.o : defs.h buffer.h
files.o : defs.h buffer.h command.h
utils.o : defs.h

.PHONY : clean
clean :
	rm edit $(objects)

理解

1.内容展开

list_a = 1.a 2.a
list_b = 1.b 2.b 3.b

#list_a中的元素每次单个展开连接list_b中的所有元素
#结果如下
test:list_a
%.a:list_b	#展开:
	1.a:1.b 2.b 3.b		#此时&@=1.a  $<=1.b 2.b 3.b
	2.a:1.b 2.b 3.b		#此时&@=2.a  $<=1.b 2.b 3.b

#内容还可以继续展开
%.b:%.x		#自动推导展开
	1.b:1.x
	2.b:2.x
	3.b:3.x

2.include 相当于将内容复制展开,export可以共享全局变量。

3.用make遍历子目录makefile时相当于,用新进程开启make。因此export不能共享全局变量。

注意

1.注意空格与TAB(有些编辑器会自动将TAB转换成4个空格,难以发现)

2.注意 = 与 := 的区别


语法

1.符号

1) 命令前缀

[不用前缀 ]输出执行的命令以及命令执行的结果, 出错的话停止执行
[前缀 @]只输出命令执行的结果, 出错的话停止执行
[前缀 -]命令执行有错的话, 忽略错误, 继续执行

2) 通配符

*表示任意一个或多个字符
? 表示任意一个字符
[...] [abcd] 表示a,b,c,d中任意一个字符, [^abcd]表示除a,b,c,d以外的字符, [0-9]表示 0~9中任意一个数字

3) 自动变量

在下文的 自动变量

4) 赋值

与 :=

相同点:都是给内容赋值;
区别:与Verilog的=和<=类似。
其中 = 和 := 的区别在于 :

= 只能使用前面定义好的变量,
= 可以使用后面定义的变量

赋值符号 [=]

最后再赋值

# Makefile内容
OBJS2 = $(OBJS1) programC.o
OBJS1 = programA.o programB.o

all:
    @echo $(OBJS2)

# bash中执行 make, 可以看出虽然 OBJS1 是在 OBJS2 之后定义的, 但在 OBJS2中可以提前使用
$ make
programA.o programB.o programC.o

赋值符号 [:=]

:= 立即赋值

# Makefile内容
OBJS2 := $(OBJS1) programC.o
OBJS1 := programA.o programB.o

all:
    @echo $(OBJS2)

# bash中执行 make, 可以看出 OBJS2 中的 $(OBJS1) 为空
$ make
programC.o

赋值符号 [+=]

+= 变量追加值

# Makefile内容
SRCS := programA.c programB.c programC.c
SRCS += programD.c

all:
    @echo "SRCS: " $(SRCS)

# bash中运行make
$ make
SRCS:  programA.c programB.c programC.c programD.c

5) 伪目标

.PHONY

.PHONY : clean
clean :
	-rm edit $(objects)

2. 隐含规则

1) 自动推倒命名:

编译C时,*.o 的目标会自动推导为 *.c

2) 隐含变量

[RM] rm -f
[AR] ar
[CC] cc
[CXX] g++
[ARFLAGS] AR命令的参数
[CFLAGS] 语言编译器的参数
[CXXFLAGS] C++语言编译器的参数

3) 自动变量

[$@] 目标集合
[$%] 当目标是函数库文件时, 表示其中的目标文件名
[$<] 第一个依赖目标. 如果依赖目标是多个, 逐个表示依赖目标
[$?] 比目标新的依赖目标的集合
[$^] 所有依赖目标的集合, 会去除重复的依赖目标
[$+] 所有依赖目标的集合, 不会去除重复的依赖目标
[$*] 这个是GNU make特有的, 其它的make不一定支持

1.o: 1.c
	@echo $@ : $< 
	
# bash中执行 make:
1.o : 1.c

3.定义

不限于makefile还有部分shell指令

1) 查看依赖关系

gcc -MM

$ gcc -MM kvm_main.c 
kvm_main.o: kvm_main.c iodev.h coalesced_mmio.hasync_pf.h  

#这句就可以加到 Makefile 中作为编译 kvm_main.o 的依赖关系

2) 定义命令包

define <command-name> 
command 
... 
endef

# Makefile 内容
define run-hello-makefile
@echo -n "Hello"
@echo " Makefile!"
@echo "这里可以执行多条 Shell 命令!"
endef

all:
    $(run-hello-makefile)


# bash 中运行make
$ make
Hello Makefile!
这里可以执行多条 Shell 命令!

3) 条件判断

# Makefile 内容
all:
ifeq ("aa", "bb")
    @echo "equal"
else
    @echo "not equal"
endif

# bash 中执行 make
$ make
not equal

4) 自定义函数

$(call <expression>,<parm1>,<parm2>,<parm3>...)

# Makefile 内容
hello = "hello " $(1) " world"

all:
    @echo $(call hello,"我是参数1")

# bash 中执行 make
$ make
hello 我是参数1 world

5) 执行shell指令

$(shell <shell command>) 与 `<shell command>`
作用:执行一个shell命令, 并将shell命令的结果作为返回.
注意:` 是反引号(英文状态下,键盘的ESC下面那个键)

4.函数

不限于makefile还有部分shell指令

1) 传参(同一个进程)

export

export EX_VAR = value
export EX_VAR := value
export EX_VAR += value
#=  :=  +=  与上面的描述基本相同

注意:是同一个进程下的make才有用。当多级遍历make时是无法全局的。

2) 字符串处理

(1) 字符串替换函数

$( subst<source>,<new>,<text>)

功能: 把字符串<text> 中的<source> 替换为<new>
返回: 替换过的字符串

# Makefile 内容
all:
    @echo $(subst t,e,maktfilt)  <-- 将t替换为e

# bash 中执行 make
$ make
makefile

(2) 字符串中每个元素替换函数

$( patsubst <source>,<new>,<text>)

功能: 把字符串 <text> 中的的每个元素 <source> 替换为<new>
返回: 替换过的字符串

# Makefile 内容
all:
    @echo $(patsubst %.c,%.o,programA.c programB.c)

# bash 中执行 make
$ make
programA.o programB.o

(3) 去空格函数

$(strip <text>)

功能: 去掉 <string> 字符串中开头和结尾的空字符
返回: 被去掉空格的字符串值

# Makefile 内容
VAL := "       aa  bb  cc "

all:
    @echo "去除空格前: " $(VAL)
    @echo "去除空格后: " $(strip $(VAL))

# bash 中执行 make
$ make
去除空格前:         aa  bb  cc 
去除空格后:   aa bb cc

(4) 判断字符串内是否存在特定字符串

$(findstring<text>,<elem>)

功能: 在字符串 <text> 中查找 <elem> 字符串是否存在
返回: 如果找到, 返回 <elem> 字符串, 否则返回空字符串

# Makefile 内容
VAL := "       aa  bb  cc "

all:
    @echo $(findstring aa,$(VAL))
    @echo $(findstring ab,$(VAL))

# bash 中执行 make
$ make
aa

3) 文件元素相关

(1) 取文件函数

保留符合条件的元素

$(filter <elem1 elem2...>,<text>)

# Makefile 内容
all:
    @echo $(filter %.o %.a,program.c program.o program.a)
	
# bash 中执行 make
$ make
program.o program.a
program.c

去掉符合条件的元素

$(filter-out <elem1 elem2...>,<text>)

# Makefile 内容
all:
    @echo $(filter-out %.o %.a,program.c program.o program.a)

# bash 中执行 make
$ make
program.c

获取该目录下所有文件

获取该目录下所有.x文件
$(wildcard *.x)

# Makefile 内容
all:
    @echo $(wildcard *.c)

# bash 中执行 make
$ make
a.x b.x c.x

(2) 路径函数

去掉路径

$(notdir <elem elem...>)

功能: 去掉序列的路径
返回: 文件名序列 <elem> 中的非目录部分

# Makefile 内容
all:
    @echo $(notdir /home/a.c ./bb.c ../c.c d.c)

# bash 中执行 make
$ make
a.c bb.c c.c d.c

取路径

$(dir <elem1 elem2...>)

功能: 从文件名序列 <elem> 中取出目录部分
返回: 文件名序列 <elem> 中的目录部分

# Makefile 内容
all:
    @echo $(dir /home/a.c ./bb.c ../c.c d.c)


# bash 中执行 make
$ make
/home/ ./ ../ ./

(3) 取前后缀

取后缀函数

$(suffix <elem1 elem2...>)

功能: 从文件名序列 <elem> 中取出各个文件名的后缀
返回: 文件名序列 <elem> 中各个文件名的后缀, 没有后缀则返回空字符串

# Makefile 内容
all:
    @echo $(suffix /home/a.c ./b.o ../c.a d)

# bash 中执行 make
$ make
.c .o .a

取前缀函数

$(basename <elem1 elem2...>)

功能: 从文件名序列 <elem> 中取出各个文件名的前缀
返回: 文件名序列 <elem> 中各个文件名的前缀, 没有前缀则返回空字符串

# Makefile 内容
all:
    @echo $(basename /home/a.c ./b.o ../c.a /home/.d .e)


# bash 中执行 make
$ make
/home/a ./b ../c /home/

(3) 增添前后缀

增添后缀函数

$(addsuffix <suffix>,<elem1 elem2...>)

功能: 把后缀 <suffix> 加到 <elem> 中的每个单词后面
返回: 加过后缀的文件名序列

# Makefile 内容
all:
    @echo $(addsuffix .c,/home/a b ./c.o ../d.c)


# bash 中执行 make
$ make
/home/a.c b.c ./c.o.c ../d.c.c

增添前缀函数

$(addprefix <prefix>, <elem1 elem2...>)

功能: 把前缀 <prefix> 加到 <elem> 中的每个单词前面
返回: 加过前缀的文件名序列

# Makefile 内容
all:
    @echo $(addprefix test_,/home/a.c b.c ./d.c)

# bash 中执行 make
$ make
test_/home/a.c test_b.c test_./d.c

我写的管理大型项目的makefile

以下内容为基础版本。可以混编C和C++。
但没有加入平台兼容性验证等功能。
在ubuntu16.04下测试通过。

tree
.
├── app
│   ├── app1
│   │   ├── main.c
│   │   └── makefile
│   └── makefile
├── make_conf.mk
├── makefile
├── make_fun.mk
├── module
│   ├── makefile
│   └── test
│       ├── drive
│       │   ├── cpp_test.cpp
│       │   ├── cpp_test.h
│       │   ├── test.c
│       │   └── test.h
│       ├── hal
│       │   ├── test_hal.c
│       │   └── test_hal.h
│       └── makefile
└── output
    ├── bin
    │   ├── app1.bin
    │   └── app2.bin
    ├── lib
    │   └── libobj.a
    └── obj
        ├── app
        │   ├── app1
        │   │   └── main.o
        │   └── app2
        │       └── main.o
        └── module
            └── test
                ├── drive
                │   ├── cpp_test.o
                │   └── test.o
                └── hal
                    └── test_hal.o

17 directories, 22 files

顶层 makefile

# -------------------------------------------
# FileName      :makefile
# Author        :wind 
# Date          :2018-1-16
# Description 
#
# Top makefile.
#
# ------------------------------------------- 

# 设置当前路径
DIR_ROOT:=.

# 设置递归子目录
DIR_LIST_SUB :=module app


include $(DIR_ROOT)/make_conf.mk
all:make_root
clean:make_clean
include $(DIR_ROOT)/make_fun.mk

中间遍历层 makefile

# -------------------------------------------
# FileName      :xx/makefile
# Author        :wind 
# Date          :2018-1-16
# Description 
#
# Level1 makefile.
#
# ------------------------------------------- 

# 设置当前路径
DIR_ROOT:=..

# 添加递归子目录
DIR_LIST_SUB :=\
app1\
app2\


# 添加源文件
FILE_LIST_C +=\


FILE_LIST_CPP +=\


FILE_LIST_S +=\



# 添加头文件路径
DIR_LIST_INCLUDE+=\




include $(DIR_ROOT)/make_conf.mk 
all:make_show make_subdir
clean:make_clean
include $(DIR_ROOT)/make_fun.mk

app的makefile

# -------------------------------------------
# FileName      :xx/xx/makefile
# Author        :wind 
# Date          :2018-1-16
# Description 
#
# Level2 makefile.
#
# ------------------------------------------- 

# 设置当前路径
DIR_ROOT:=../..

# 添加递归子目录
DIR_LIST_SUB :=\

# 添加源文件
FILE_LIST_C +=\
main.c\


FILE_LIST_CPP +=\


FILE_LIST_S +=\



# 添加头文件路径
DIR_LIST_INCLUDE+=\
$(DIR_ROOT)/module/test/hal\
$(DIR_ROOT)/module/test/drive\



include $(DIR_ROOT)/make_conf.mk 
all:make_show make_app
clean:make_clean
include $(DIR_ROOT)/make_fun.mk

drive的makefile

# -------------------------------------------
# FileName      :xx/xx/makefile
# Author        :wind 
# Date          :2018-1-16
# Description 
#
# Level2 makefile.
#
# ------------------------------------------- 

# 设置当前路径
DIR_ROOT:=../..

# 添加递归子目录
DIR_LIST_SUB :=\

# 添加源文件
FILE_LIST_C +=\
drive/test.c\
hal/test_hal.c\

FILE_LIST_CPP +=\
drive/cpp_test.cpp\

FILE_LIST_S +=\


# 添加头文件路径
DIR_LIST_INCLUDE+=\
hal\
drive\



include $(DIR_ROOT)/make_conf.mk 
all:make_show make_lib_a
clean:make_clean
include $(DIR_ROOT)/make_fun.mk

配置文件 make_conf.mk

# -------------------------------------------
# FileName      :make_set.inc
# Author        :wind 
# Date          :2018-1-16
# Description 
#
# 工程相关设置。
#
# -------------------------------------------

# 设置常用指令
# -------------------------------------------
RM = rm -f
MV = mv -f
MKDIR = mkdir -p
RMDIR = rm -rf   


# 颜色输出
# -------------------------------------------
ECHO_END:=\033[0m"
ECHO_GREEN:=echo "\033[32m
ECHO_RED:=echo "\033[31m
ECHO_YELLOW:=echo "\033[33m
ECHO_BLUE:=echo "\033[34m
ECHO_GREEN_YELLOW:=echo "\033[42;30m

# 编译缺省设置
# -------------------------------------------

# 默认编译
CXX:=g++

#编译选项
COMPILE_C ?= $(CXX)
COMPILE_CXX ?= $(CXX)
COMPILE_ASM ?= $(CXX)
COMPILE_AR ?= ar

# 设置优化等级
OPT ?=0

# 设置警告开关
COMPILE_WARN ?= -Wall  

# 设置静态编译
COMPILE_STATIC ?= -s

# 在环境基础下添加设置
CFLAGS+= $(DIR_LIST_INCLUDE_I) $(COMPILE_WARN) -O$(OPT) $(COMPILE_STATIC)
CXXFLAGS+= $(DIR_LIST_INCLUDE_I) $(COMPILE_WARN) -O$(OPT) $(COMPILE_STATIC)
ASFLAGS+= -Wa,-adhlns=$(<:.S=.lst),-gstabs $(DIR_LIST_INCLUDE_I)

# 编译设置汇总 
COMPILE_CFLAGS = $(CFLAGS)
COMPILE_CXXFLAGS = $(CXXFLAGS)
COMPILE_ASFLAGS = $(ASFLAGS)

#链接选项
LDFLAGS+= -lstdc++#编译C++
LDFLAGS+= -lpthread#使用了线程
LDFLAGS+= -fPIC#编译为位置独立的代码
LDFLAGS+= -ldl#引用动态库
LDFLAGS+= $(DIR_LIST_INCLUDE_I)

#引用其他静态库
FILE_LIST_LIB_A+=\

功能文件 make_fun.mk

# -------------------------------------------
# FileName      :make_fun.mk
# Author        :wind 
# Date          :2018-1-16
# Description 
#
# 实际编译过程。
#s
# ------------------------------------------- 

# 路径关系
# -------------------------------------------
DIR_ROOT_REAL=$(realpath $(DIR_ROOT))
NAME_MODULE := $(notdir $(CURDIR))#所在的文件夹名称
DIR_OUTPUT:=$(DIR_ROOT)/output
DIR_BIN:=$(DIR_OUTPUT)/bin
DIR_OBJ:=$(DIR_OUTPUT)/obj
DIR_LIB:=$(DIR_OUTPUT)/lib


# 路径处理成可用参数
# -------------------------------------------
DIR_LIST_INCLUDE_I:=$(addprefix -I,$(DIR_LIST_INCLUDE))#添加编译选项-I
DIR_LIST_SUB:=$(addprefix  $(CURDIR)/,$(DIR_LIST_SUB))#转换成绝对路径
DIR_CURDIR:=$(subst $(DIR_ROOT_REAL),,$(CURDIR))#相对路径
DIR_OBJ_OUT:=$(DIR_OBJ)$(DIR_CURDIR)


#文件处理
FILE_LIST_OBJ:=$(FILE_LIST_C:%.c=%.o)
FILE_LIST_OBJ+=$(FILE_LIST_CPP:%.cpp=%.o)
FILE_LIST_OBJ+=$(FILE_LIST_S:%.s=%.o)

FILE_LIST_OBJ:=$(addprefix  $(DIR_OBJ_OUT)/,$(FILE_LIST_OBJ))#转换成带绝对路径的中间文件
FILE_LIB_A:=$(DIR_LIB)/libobj.a
FILE_LIST_LIB_APP:=$(DIR_BIN)/$(NAME_MODULE).bin

# 函数库
# ------------------------------------------- 
make_root:make_start make_subdir make_end

# 工程开始
make_start:
	@$(ECHO_BLUE)\t-----------------------------$(ECHO_END)
	@$(ECHO_BLUE)\t-\t [编译开始]  \t    -$(ECHO_END)
	@$(ECHO_BLUE)\t-----------------------------$(ECHO_END)
	@$(ECHO_BLUE)[COMPILE_C]$(COMPILE_C) 	 	[COMPILE_CFLAGS]$(COMPILE_CFLAGS)$(ECHO_END)
	@$(ECHO_BLUE)[COMPILE_CXX]$(COMPILE_CXX) 	[COMPILE_CXXFLAGS]$(COMPILE_CXXFLAGS)$(ECHO_END)
	@$(ECHO_BLUE)[COMPILE_ASM]$(COMPILE_ASM) 	[COMPILE_ASFLAGS]$(COMPILE_ASFLAGS)$(ECHO_END)
	@$(ECHO_BLUE)[COMPILE_AR]$(COMPILE_AR)   	[LDFLAGS]$(LDFLAGS)$(ECHO_END)
	@$(ECHO_BLUE)[OPT]$(OPT)  $(ECHO_END)
	@$(ECHO_BLUE)[COMPILE_STATIC]$(COMPILE_STATIC)  $(ECHO_END)
	@$(ECHO_BLUE)[FILE_LIST_LIB_A]$(FILE_LIST_LIB_A)  $(ECHO_END)


# 工程完成
make_end: 
	@$(ECHO_BLUE)[编译完成]$(ECHO_END)         

# 递归子目录
make_subdir:
	@for list in $(DIR_LIST_SUB);\
	do\
		cd $$list && make all|| exit 1;\
	done

# 生成可执行文件
make_app:make_lib_a make_bin

# 生成静态链接库
make_lib_a:make_obj
	@$(MKDIR) `dirname $(FILE_LIB_A)`
	@$(ECHO_YELLOW)[$(COMPILE_AR)]-rcs $(FILE_LIB_A) $(FILE_LIST_OBJ)$(ECHO_END)
	$(COMPILE_AR) -rcs $(FILE_LIB_A) $(FILE_LIST_OBJ)

# 链接
make_bin:$(FILE_LIST_LIB_APP)

# 编译
make_obj:$(FILE_LIST_OBJ)

# 清除
make_clean:
	$(RMDIR) $(DIR_OUTPUT)
	
# 显示参数,方便调试
make_show:
	@$(ECHO_GREEN_YELLOW)[DIR_CURDIR] $(DIR_CURDIR) $(ECHO_END)
	@$(ECHO_GREEN)[FILE_LIST_C] $(FILE_LIST_C) $(ECHO_END)
	@$(ECHO_GREEN)[DIR_LIST_INCLUDE] $(subst $(DIR_ROOT)/,[DIR_ROOT]/,$(DIR_LIST_INCLUDE)) $(ECHO_END)
	
	
# 文件操作过程
# ------------------------------------------- 

# 编译过程成中间文件
$(DIR_OBJ_OUT)/%.o: %.c
	@$(MKDIR) `dirname $@`
	@$(ECHO_YELLOW)[$(COMPILE_C)]$< -o $@ $(ECHO_END)
	$(COMPILE_C) -c $(COMPILE_CFLAGS) $< -o $@

$(DIR_OBJ_OUT)/%.o: %.cpp
	@$(MKDIR) `dirname $@`
	@$(ECHO_YELLOW)[$(COMPILE_CXX)]$< -o $@ $(ECHO_END)
	$(COMPILE_CXX) -c $(COMPILE_CXXFLAGS) $< -o $@

$(DIR_OBJ_OUT)/%.o: %.s
	@$(MKDIR) `dirname $@`
	@$(ECHO_YELLOW)[$(COMPILE_C)]$< -o $@ $(ECHO_END)
	$(COMPILE_ASM) -c $(COMPILE_ASFLAGS) $< -o $@

 
# 链接成二进制文件
$(FILE_LIST_LIB_APP): $(FILE_LIB_A)
	@$(MKDIR) `dirname $@`
	@$(ECHO_YELLOW)[$(COMPILE_C)]$< -o $@ $(ECHO_END)
	$(COMPILE_C) $(LDFLAGS) -L$(DIR_LIB) -lobj $< $(FILE_LIST_LIB_A) -o $@



内容推荐

跟我一起写Makefile
Makefile 使用总结
项目实用makefile
Makefile之大型工程项目子目录Makefile的一种通用写法

引用本地址

http://blog.csdn.net/a7232799/article/details/79111935

下载PDF版本以及工程文件:大型工程的makefile.rar(密码:wind)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

makefile 完美教程 的相关文章

  • SSM框架整合

    整合思路 主要分为Controller xff0c service层 xff0c dao层 整合dao mybatis和spring的整合 xff0c 通过spring来管理mapper接口 xff0c 数据源 xff0c 使用mapper
  • SSM框架实战-搭建自己的个人博客1-基础架构搭建

    前言 本系列文章主要通过从零开始搭建自己的个人博客 xff0c 来加深对SSM框架的学习与使用 xff0c 了解一个系统从提出到设计 到开发 到测试 部署运行的过程 xff0c 并记录在搭建过程中的学习心得 遇见的错误及解决方式 代码放在g
  • SSM框架实战-搭建自己的个人博客2-UEditor编辑器的使用

    目录 UEditor 博客内容提交与展示功能测试 Controller开发 新增博客页面add ueditor jsp 博客详情界面detail jsp 博客新增和展示详情功能开发 博客存储 博客标题开发 标签POJO类 TagMapper
  • SSM框架实战-搭建自己的个人博客3-登录实现及前端界面设计

    目录 后台登录功能 前端页面 后端开发 前端界面设计 详情首页 js脚本 SSM整体设计 Dao层 Service层 Mapper xml Controller 子博文界面 部署至服务器 后台登录功能 登录页面 xff1a 用户名和密码 通
  • 超分辨率重建-PNSR与SSIM的计算(RGB、YUV和YCbCr互转)

    RGB YUV和YCbCr 自己复现的网络跑出来的模型进行预测的时候 xff0c 不知道为啥算出来的结果比论文中要低好多 不论scale factor为多少 xff0c 我算出来的结果均普遍低于论文中给出的 xff0c PSNR大概低个1
  • 如何写简历

    注意点 xff1a 篇幅 校招一页 社招二页 谨慎使用精通 精通 gt 熟悉 xff08 推荐使用 xff09 gt 掌握 xff08 推荐使用 xff09 gt 了解 xff08 推荐使用 xff09 拿不准的不要写在简历上 突出自己技能
  • SSM框架实战-搭建自己的个人博客4-文章管理与展示

    实现功能 主要实现上图所示的功能 xff0c 从数据库中查询到所有文章数据 xff0c 并进行显示如标题 xff0c 栏目等信息 xff0c 可以通过分类查询文章 xff0c 通过标签查询文章 xff0c 也可以通过搜索进行模糊查询 xff
  • Pytorch加载与保存模型(利用pth的参数更新h5预训练模型)

    前言 以前用Keras用惯了 xff0c fit和fit generator真的太好使了 xff0c 模型断电保存搞个checkpoint回调函数就行了 近期使用pytorch进行训练 xff0c 苦于没有类似的回调函数 xff0c 写完网
  • 如何用pyplot优雅的绘制loss,acc,miou,psnr变化曲线

    前言 TensorFlowBoard过于强大 xff0c 导致我对它依赖性很强 xff0c 今年转手使用pytorch进行开发 xff0c 本以为没了TensorFlowBoard xff0c 后来发现人家Tensorflow封装了个Ten
  • Pytorch实现CA,SA,SE注意力机制

    通道注意力CA class ChannelAttention nn Module def init self in planes ratio 61 16 super ChannelAttention self init self avg p
  • Python使用OpenCV按自定义帧率提取视频帧并保存

    在做室外语义分割 视觉导航与定位的时候 xff0c 通常会用对一个连续的视频帧进行测试 xff0c 除去常用数据集外 xff0c 也经常会自己制作一些数据集 xff0c 这个工具类可以按需求对视频进行分帧提取 xff0c 封装好了直接可以使
  • 悲观锁与乐观锁详解

    悲观锁 悲观锁顾名思义是从悲观的角度去思考问题 xff0c 解决问题 它总是会假设当前情况是最坏的情况 xff0c 在每次去拿数据的时候 xff0c 都会认为数据会被别人改变 xff0c 因此在每次进行拿数据操作的时候都会加锁 xff0c
  • 亚像素卷积网络(ESPCN)学习与Pytorch复现

    论文内容 论文地址 xff1a Real Time Single Image and Video Super Resolution Using an Efficient Sub Pixel Convolutional Neural Netw
  • Lock锁和ReentrantLock锁

    前言 JDK 1 5中提供的锁的接口java util concurrent locks Lock xff0c 其提供了一些ReentrantLock ReentrantReadWriteLock实现类 参考JDK文档 xff1a Java
  • 面试题--JVM垃圾回收及内存管理

    选择题 1 以下哪些内存区域属于 JVM 规范 xff1f xff08 xff09 A 方法区 B 实例变量 C 静态变量 D 程序计数器 E 虚拟机栈 正确答案 xff1a A D E 解析 xff1a Java虚拟机规范划分了七个内存区
  • Pytorch维度操作-unsqueeze、squeeze、view与permute

    view 在pytorch中view函数的作用为重构张量的维度 相当于numpy中resize 的功能 a 61 1 2 3 b 61 2 3 4 c 61 3 5 5 d 61 4 5 6 e 61 np array a b c d e
  • 长假余额为零!我用Python做了个中秋国庆双节拼图游戏

    点击上方 菜鸟学Python xff0c 选择 星标 公众号 重磅干货 xff0c 第一时间送达 今年的国庆长假非常长 xff0c 不知不觉已经余额为零 xff01 朋友圈很多晒出游的照片 xff0c 聚会的照片 xff0c 吃吃喝喝真舒服
  • Redis系列学习1-Redis安装启动与基础概念

    Remote Dictionary Server Redis 是一个由 Salvatore Sanfilippo 写的 key value 存储系统 xff0c 是跨平台的非关系型数据库 Redis 是一个开源的使用 ANSI C 语言编写
  • Redis系列学习2-五大类型(String,List,Hash,Set,ZSet)及其常规操作

    Redis的基本操作 Redis默认是有16个数据库 xff0c 默认使用的是第0个数据库 xff0c 可以通过select 切换数据库 xff0c Redis的命令大小写不敏感的 切换数据库 切换数据库 格式 xff1a select i
  • Redis系列学习3-geospatial地理空间

    geospatial 地理空间 可以用来实现定位 附近的人 打车APP上距离计算 距离的实现主要基于经纬度 xff0c 城市的经纬度查询 xff1a http www jsons cn lngcode geoadd 添加地址位置 格式 xf

随机推荐

  • 遗传算法求解TSP旅行商问题

    旅行商问题 旅行商问题 traveling salesman problem TSP 可描述为 已知N个城市之间的相互距离 现有一个商人必须遍访这N个城市 并且每个城市只能访问一次 最后又必须返回出发城市 如何安排他对这些城市的访问次序 使
  • 剑指Offer-面试算法题

    1 二分查找 xff08 递归与非递归实现 xff09 基本算法 xff0c 掌握好循环条件 package com company Description 二分查找 xff08 递归与非递归实现 xff09 Created by Wanb
  • Python爬虫-抓取PC端网易云音乐评论(GUI界面)

    歌曲搜素 网易云音乐网址为 xff1a https music 163 com 思路是进入后输入一个歌曲名 xff0c 点击搜索按钮 xff0c 通过开发者调试工具捕获搜索请求 xff0c 捕获到的数据信息如下 xff1a 所有的歌曲相关信
  • Package cmake is not available, but is referred to by another package.

    inux环境下安装Cmake报错 xff1a Package cmake is not available but is referred to by another package This may mean that the packa
  • 完美数问题

    题目描述 对于一个十进制正整数 xff0c 如果z的每一位数字只可能是1 2 3中的其中一个 xff0c 则称 是完美数 如 123 1 3321都是完美数而5 1234则不是 牛牛想写一个函数f n xff0c 使得其返回最大的不大于n的
  • 围圈抽牌报数问题

    问题描述 米免参加公司司建 xff0c 100个同事围坐圈 xff0c 裁判开始顺时针从头发牌 xff0c 每发3张白牌就会发出1张黑 牌 xff0c 抽到黑牌的人出局 xff0c 每局第N个抽到黑牌的将获得奖励 问如果米免想获得奖品 xf
  • RTX30系列-Ubuntu系统配置与深度学习环境Pytorch配置

    本文完成RTX3090Windows 43 Ubuntu双系统配置 xff0c 并配置深度学习环境 硬件环境为RTX3090 43 Z590主板 xff0c 64GB RAM xff0c 2TB固态 xff0c 8TB存储 Ubuntu系统
  • 【rotors】多旋翼无人机仿真(一)——搭建rotors仿真环境

    rotors 多旋翼无人机仿真 xff08 一 xff09 搭建rotors仿真环境 rotors 多旋翼无人机仿真 xff08 二 xff09 设置飞行轨迹 rotors 多旋翼无人机仿真 xff08 三 xff09 SE3控制 roto
  • JVM内存管理

    JVM内存管理 Java 虚拟机在执行 Java 程序的过程中会把它管理的内存划分成若干个不同的数据区域 xff0c JDK 1 8 和之前的版本的数据区域有所差异 xff0c JDK1 6如下图所示 图片来源 xff1a JavaGuid
  • AQS、Semaphore、CountDownLatch与CyclicBarrier原理及使用方法

    AQS AQS 的全称为 AbstractQueuedSynchronizer xff0c 翻译过来的意思就是抽象队列同步器 这个类在 java util concurrent locks 包下面 xff0c AQS 就是一个抽象类 xff
  • 滑动窗口框架算法

    最长覆盖子串 xff0c 异位词 xff0c 最长无重复子串等等许多子串问题用常规暴力法费时费力 xff0c 一些大佬的解法虽然很强效率很高 xff0c 但是太难想到了 xff0c 这类问题用滑动窗口算法解决非常的快捷简便 滑动窗口算法思想
  • Python-深度学习常用脚本

    记录一些因为在网络训练 xff0c 测试过程中经常用到的一些脚本 1 视频按帧提取 可以从一段视频中截取不同帧的图片 xff0c 并保存至文件夹 需要自己更改视频路径和图片保存路径 import os import cv2 import s
  • Java面试基础(一)

    1 重载与重写 重载就是同样的一个方法能够根据输入数据的不同 xff0c 做出不同的处理 重写就是当子类继承自父类的相同方法 xff0c 输入数据一样 xff0c 但要做出有别于父类的响应时 xff0c 你就要覆盖父类方法不同类型的对象 x
  • 网络篇-传输控制协议TCP

    TCP协议 传输控制协议 xff08 TCP xff0c Transmission Control Protocol xff09 用一句话概括的话 xff0c 它是一种面向连接的 可靠的 基于字节流的传输层通信协议 TCP xff08 传输
  • 阻塞队列-BlockingQueue

    对于Queue而言 xff0c BlockingQueue是主要的线程安全的版本 xff0c 具有阻塞功能 xff0c 可以允许添加 删除元素被阻塞 xff0c 直到成功为止 xff0c blockingqueue相对于Queue而言增加了
  • 线程池-ThreadPoolExecutor

    如果并发的线程数量很多 xff0c 并且每个线程都是执行一个时间很短的任务就结束了 xff0c 这样频繁创建线程就会大大降低系统的效率 xff0c 因为频繁创建线程和销毁线程需要时间 那么有没有一种办法使得线程可以复用 xff0c 就是执行
  • MySQL索引

    基础知识 索引是创建在表上的 xff0c 对数据库表中一列或多列的值进行排序的一种结构 xff0c 可以提高查询的速度 通俗的来说 xff0c 数据库中存储的数据比作字典的话 xff0c 索引就相当于是字典中的目录 如果没有索引 xff0c
  • ThreadPoolExecutor任务提交与停止流程及底层实现

    ThreadPoolExecutor任务提交 executor任务提交流程 通过查看源码可知 xff0c JUC下的Excutor接口仅提供了一个可执行方法executor public interface Executor Execute
  • RoboMaster步兵机器人简介

    RoboMaster步兵机器人简介 湖北工业大学 蔡饶 如下图所示 xff0c 设计的是一个基于麦克纳姆轮的四轮全向越障平台 xff0c 纵臂式独立悬挂 xff0c 搭载两轴云台和弹丸发射机构 xff0c 是大疆承办的RoboMaster机
  • makefile 完美教程

    简介 Makefile 是和 make 命令一起配合使用的 xff0c 很多大型项目的编译都是通过 Makefile 来组织的 我建立工程的方法有以下三点 xff1a 1 makefile xff1a 优点 xff1a 使用非常广泛 xff