mekefile 编写

mekefile 编写

参考

Linux下使用 autoconf和automake 自动构建 项目 make file文件

makefile 中加入shell语句 if shell

参考

foo.bak: foo.barecho "foo"if [ -d "~/Dropbox" ]; then echo "Dir exists"; fi
Or
foo.bak: foo.barecho "foo"if [ -d "~/Dropbox" ]; then \echo "Dir exists"; \fi

Makefile中的wildcard用法 获取所有源文件

在Makefile规则中,通配符会被自动展开。但在变量的定义和函数引用时,通配符将失效。这种情况下如果需要通配符有效,就需要使用函数“wildcard”,它的用法是:$(wildcard PATTERN...) 。在Makefile中,它被展开为已经存在的、使用空格分开的、匹配此模式的所有文件列表。如果不存在任何符合此模式的文件,函数会忽略模式字符并返回空。需要注意的是:这种情况下规则中通配符的展开和上一小节匹配通配符的区别。一般我们可以使用“$(wildcard *.c)”来获取工作目录下的所有的.c文件列表。复杂一些用法;可以使用“$(patsubst %.c,%.o,$(wildcard *.c))”,首先使用“wildcard”函数获取工作目录下的.c文件列表;之后将列表中所有文件名的后缀.c替换为.o。这样我们就可以得到在当前目录可生成的.o文件列表。因此在一个目录下可以使用如下内容的Makefile来将工作目录下的所有的.c文件进行编译并最后连接成为一个可执行文件:#sample Makefileobjects := $(patsubst %.c,%.o,$(wildcard *.c))foo : $(objects)cc -o foo $(objects)这里我们使用了make的隐含规则来编译.c的源文件。对变量的赋值也用到了一个特殊的符号(:=)。1、wildcard : 扩展通配符
2、notdir : 去除路径
3、patsubst :替换通配符例子:
建立一个测试目录,在测试目录下建立一个名为sub的子目录
$ mkdir test
$ cd test
$ mkdir sub在test下,建立a.c和b.c2个文件,在sub目录下,建立sa.c和sb.c2 个文件建立一个简单的Makefile
src=$(wildcard *.c ./sub/*.c)
dir=$(notdir $(src))
obj=$(patsubst %.c,%.o,$(dir) )all:
@echo $(src)
@echo $(dir)
@echo $(obj)
@echo "end"执行结果分析:
第一行输出:
a.c b.c ./sub/sa.c ./sub/sb.cwildcard把 指定目录 ./ 和 ./sub/ 下的所有后缀是c的文件全部展开。第二行输出:
a.c b.c sa.c sb.c
notdir把展开的文件去除掉路径信息第三行输出:
a.o b.o sa.o sb.o在$(patsubst %.c,%.o,$(dir) )中,patsubst把$(dir)中的变量符合后缀是.c的全部替换成.o,
任何输出。
或者可以使用
obj=$(dir:%.c=%.o)
效果也是一样的。这里用到makefile里的替换引用规则,即用您指定的变量替换另一个变量。
它的标准格式是
$(var:a=b) 或 ${var:a=b}
它的含义是把变量var中的每一个值结尾用b替换掉a今天在研究makefile时在网上看到一篇文章,介绍了使用函数wildcard得到指定目录下所有的C语言源程序文件名的方法,这下好了,不用手工一个一个指定需要编译的.c文件了,方法如下:SRC = $(wildcard *.c)等于指定编译当前目录下所有.c文件,如果还有子目录,比如子目录为inc,则再增加一个wildcard函数,象这样:SRC = $(wildcard *.c) $(wildcard inc/*.c)也可以指定汇编源程序:
ASRC = $(wildcard *.S) 

示例

# 变量定义 ( = or := )
# 其中 = 和 := 的区别在于, 
# := 只能使用前面定义好的变量, = 可以使用后面定义的变量
# +=变量追加值 SRCS += programD.c# 工程名
# 定义变量PROJ为 challenge ,在后面 handin 中使用了这个变量,将其插入生成的压缩包名字中
# 可能是用来让同学改为学号等信息对提交的作业进行区分
PROJ	:= challenge
# 生成空格
EMPTY	:=
SPACE	:= $(EMPTY) $(EMPTY)
# 斜杠 /   反斜杠\ back slash
SLASH	:= /# 后面没有使用上面的3个变量# @放在行首,表示不打印此行信息, at符号
V       := @
# 显示信息
#V       :=
# 为了显示所有执行的命令,我一开始是把Line6的“V:=@”改为“V:=”,然后make。
# 不过后来在网上看到,可以通过执行make "V=" 来达到目的。
# make qemu "V="
#变量V=@,后面大量使用了V
#@的作用是不输出后面的命令,只输出结果
#在这里修改V即可调整输出的内容
#也可以 make "V=" 来完整输出# 不输出警告信息
W:=
# 输出警告信息
# W:= -Wall
#为了不输出warning,我自己加的# 编译器=========================#need llvm/clang-3.5+
#USELLVM := 1
#若要使用LLVM则去掉前面一行的#即可
#LLVM 是LLVM基金会开发的编译器架构,Clang是其开发的C++,C,ObjectiveC,Ojc++编译器。# 这里是在选择交叉编译器。
# try to infer the correct GCCPREFX
# 检查环境变量 GCCPREFIX 是否被设置(通常是没有的)
ifndef GCCPREFIX
# 如果没有被设置(if not define),那么判断运行环境,自行定义变量 GCCPREFIX
# grep 在文本信息中查找 
# 0 是一个文件描述符,表示标准输入(stdin) == keyboard 键盘输入,并返回在前端 =========
# 1 是一个文件描述符,表示标准输出(stdout)== monitor 正确返回值 输出到前端  ====
# 2 是一个文件描述符,表示标准错误(stderr)== monitor 错误返回值 输出到前端  ====
# >和>> 都是重定向输出=== > 会覆盖已有的文件内容,而 >> 会附加到已有内容之后====
# 1>   指 标准信息输出路径(也就是默认的输出方式)   "1>" 通常可以省略成 ">". 
# 2>   指 错误信息输出路径                      
# 2>&1 指将 标准错误 指定 为标准输出(错误合并到输出) &1 表示 标准输出通道
# 1>&2 正确返回值传递给 2输出通道 &2表示 输出错误通道 (正确合并到错误)
# 如果此处错写成 1>2, 就表示把1输出重定向到文件2中. 
# <和<<都是重定向输入===========
# <0指标准输入路径
# 4<&0 指的是将文件描述符4指定为标准输入(实际可选4到9之间任意一个数字)GCCPREFIX := $(shell if i386-elf-objdump -i 2>&1 | grep '^elf32-i386$$' >/dev/null 2>&1; \then echo 'i386-elf-'; \elif objdump -i 2>&1 | grep 'elf32-i386' >/dev/null 2>&1; \then echo ''; \else echo "***" 1>&2; \echo "*** Error: Couldn't find an i386-elf version of GCC/binutils." 1>&2; \echo "*** Is the directory with i386-elf-gcc in your PATH?" 1>&2; \echo "*** If your i386-elf toolchain is installed with a command" 1>&2; \echo "*** prefix other than 'i386-elf-', set your GCCPREFIX" 1>&2; \echo "*** environment variable to that prefix and run 'make' again." 1>&2; \echo "*** To turn off this error, run 'gmake GCCPREFIX= ...'." 1>&2; \echo "***" 1>&2; exit 1; fi)
endif# 硬件模拟环境====================
# QEMU是一款优秀的模拟处理器,使用方便,比virtualbox更适合进行实验。
# try to infer the correct QEMU
# 检查环境变量 QEMU 是否被设置(通常是没有的)
ifndef QEMU
# 如果没有被设置(if not define),那么自行定义变量 QEMU
# /dev/null 哑型设备  无用信息收集器 (不会打印信息,哑巴)
# which 查找 并 显示 给定 命令 的绝对路径
QEMU := $(shell if which qemu-system-i386 > /dev/null; \then echo 'qemu-system-i386'; exit; \elif which i386-elf-qemu > /dev/null; \then echo 'i386-elf-qemu'; exit; \elif which qemu > /dev/null; \then echo 'qemu'; exit; \else \echo "***" 1>&2; \echo "*** Error: Couldn't find a working QEMU executable." 1>&2; \echo "*** Is the directory containing the qemu binary in your PATH" 1>&2; \echo "***" 1>&2; exit 1; fi)
endif# 使用伪目标.SUFFIXES 定义自己的后缀列表
# 当前makefile内 支持 文件后缀 的类型列表
# eliminate default suffix rules
.SUFFIXES: .c .S .h# 如果编译出错,或者编译中断,删除已经生成的目标文件
# delete target files if there is an error (or make is interrupted)
.DELETE_ON_ERROR:# 设置编译器选项
# define compiler and flags 编译器和编译选项
ifndef  USELLVM
# 未定义 USELLVM 则使用 gcc编译器
# /dev/null 哑型设备  无用信息收集器 (不会打印信息,哑巴)# hostcc是给主机用的编译器,按照主机格式。HOSTCC		:= gcc# -g 是为了gdb能够对程序进行调试  GNU  debug
# -Wall 生成警告信息
# -O2 优化处理(0,1,2,3表示不同的优化程度,O0为不优化)
HOSTCFLAGS	:= -g -Wall -O2# cc 是 i386、elf32 格式的编译器 (交叉编译器)。CC		:= $(GCCPREFIX)gcc# -fno-builtin 不接受非“__”开头的 内建函数 buildin function
# -Wall 生成警告信息
# -ggdb 让 gcc 为 gdb 生成 比较丰富 的 调试信息
# -m32  编译32位程序 
# -gstabs 此选项以 stabs 格式声称调试信息, 但是不包括gdb调试信息
# -nostdinc 不在 标准系统 目录中搜索头文件, 只在-I指定的目录中搜索   no standard include
# DEFS是未定义量。可用来对CFLAGS进行扩展。
CFLAGS	:= -fno-builtin -Wall -ggdb -m32 -gstabs -nostdinc  $(DEFS)# 这句话的意思是,如果-fno-stack-protector(无堆栈保护??)选项存在,就添加它。过程蛮复杂的。
# -fstack-protector-all 启用 堆栈保护, 为所有函数 插入保护代码
# -E 仅作预处理,不进行编译、汇编和链接
# -x c 指明使用的语言为 c语言
# 前一个 /dev/null 用来指定 目标文件
# >/dev/null 2>&1 将标准输出与错误输出重定向到 /dev/null(哑型设备  无用信息收集器 (不会打印信息,哑巴))
# /dev/null是一个 垃圾桶 一样的东西
# ‘&&’之前的半句表示,试着对一个垃圾 跑一下这个命令,所有的 输出 都作为垃圾,为了快一点,开了-E。
# 如果不能运行,那么&&前面的条件不成立,后面的就被忽视。======================s
# 如果可以运行,那么&&后面的句子得到执行,于是 CFLAGS += -fno-stack-protector
CFLAGS	+= $(shell $(CC) -fno-stack-protector -E -x c /dev/null >/dev/null 2>&1 && echo -fno-stack-protector)else
# 如果定义了 USELLVM 则使用 clang编译器
# LLVM 是LLVM基金会开发的编译器架构,Clang是其开发的 C++,C,ObjectiveC, Ojc++编译器。HOSTCC		:= clang
HOSTCFLAGS	:= -g -Wall -O2
CC		:= clang
CFLAGS	:= -fno-builtin -Wall -g -m32 -mno-sse -nostdinc $(DEFS)
CFLAGS	+= $(shell $(CC) -fno-stack-protector -E -x c /dev/null >/dev/null 2>&1 && echo -fno-stack-protector)
endif# 源文件类型为 c 和 S=======
# .c文件 .S汇编文件
CTYPE	:= c S# 一些链接选项========
LD      := $(GCCPREFIX)ld
# #ld -V命令会输出连接器的版本与支持的模拟器。在其中搜索grep elf_i386, 错误信息到 哑型设备
# 若支持,则LDFLAGS := -m elf_i386
LDFLAGS	:= -m $(shell $(LD) -V | grep elf_i386 2>/dev/null)# -nostdinc 不在 标准系统 目录中搜索头文件, no standard include
# 只把指定的文件传递给连接器
LDFLAGS	+= -nostdlib# objcopy把一种目标文件中的内容复制到另一种类型的目标文件中. 
OBJCOPY := $(GCCPREFIX)objcopy
# objdump命令是Linux下的反汇编目标文件或者可执行文件的命令
OBJDUMP := $(GCCPREFIX)objdump
# shell 指令
COPY	:= cp#复制
MKDIR   := mkdir -p#创建文件夹  make directory
MV	:= mv      #移动文件    move 
RM	:= rm -f   #删除文件    remove 
AWK	:= awk     #逐行逐列处理      字符串解析
SED	:= sed     #sed常常一整行处理 
SH	:= sh      #bash解析命令      
TR	:= tr      #对来自标准输入的字符进行替换、压缩和删除
TOUCH	:= touch -c#-c 如果文件不存在,则不要进行创建OBJDIR	:= obj# 目标地址目标
BINDIR	:= bin# 二进制文件地址# 可执行文件
ALLOBJS	:=
# 依赖
ALLDEPS	:=
# 目标
TARGETS	:=#包含另外一个Makefile文件
#function.mk中定义了大量的函数。
#.mk中每个函数都有注释。
include tools/function.mk#call函数:call func,变量1,变量2,...
#listf函数在function.mk中定义,列出某地址(变量1)下某些类型(变量2)文件
#listf_cc函数即列出某地址(变量1)下.c与.S文件
listf_cc = $(call listf,$(1),$(CTYPE))# for cc
# add_files:(#files, cc[, flags, packet, dir])
# add_files_cc:(#files, packet, flags, dir) flags已添加,这个变量仅用以扩展
# 添加文件到目标
add_files_cc = $(call add_files,$(1),$(CC),$(CFLAGS) $(3),$(2),$(4))
create_target_cc = $(call create_target,$(1),$(2),$(3),$(CC),$(CFLAGS))# for hostcc
add_files_host = $(call add_files,$(1),$(HOSTCC),$(HOSTCFLAGS),$(2),$(3))
create_target_host = $(call create_target,$(1),$(2),$(3),$(HOSTCC),$(HOSTCFLAGS))#patsubst替换通配符
#cgtype(filenames,type1,type2)
#把文件名中 后缀是 type 1的改为 type2, 如*.c改为*.o
cgtype = $(patsubst %.$(2),%.$(3),$(1))# 列出所有.o文件
objfile = $(call toobj,$(1))
# .o改为.asm
asmfile = $(call cgtype,$(call toobj,$(1)),o,asm)
# .o改为.out
outfile = $(call cgtype,$(call toobj,$(1)),o,out)
# .o改为.sym
symfile = $(call cgtype,$(call toobj,$(1)),o,sym)# for match pattern
match = $(shell echo $(2) | $(AWK) '{for(i=1;i<=NF;i++){if(match("$(1)","^"$$(i)"$$")){exit 1;}}}'; echo $$?)# >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
# include kernel/user
#库文件 
# +=变量追加值
INCLUDE	+= libs/CFLAGS	+= $(addprefix -I,$(INCLUDE))LIBDIR	+= libs$(call add_files_cc,$(call listf_cc,$(LIBDIR)),libs,)# -------------------------------------------------------------------
# kernel  内核源文件
# 生成 bin/kernel
# 头文件
KINCLUDE	+= kern/debug/ \kern/driver/ \kern/trap/ \kern/mm/
# 源文件
KSRCDIR		+= kern/init \kern/libs \kern/debug \kern/driver \kern/trap \kern/mmKCFLAGS		+= $(addprefix -I,$(KINCLUDE))$(call add_files_cc,$(call listf_cc,$(KSRCDIR)),kernel,$(KCFLAGS))#应为所有的编译后的目标文件路径都保存在__temp_packet中,则该函数直接引用,用来最后的链接工作
KOBJS	= $(call read_packet,kernel libs)# create kernel target  系统内核目标文件 obj/kernel
kernel = $(call totarget,kernel)# 最终的目标文件的规则
$(kernel): tools/kernel.ld
# 命令前缀 
# 前缀 @   :: 只输出命令执行的结果, 出错的话停止执行
# 前缀 -   :: 命令执行有错的话, 忽略错误, 继续执行
$(kernel): $(KOBJS)@echo + ld $@
# 链接 obj/libs/* 和 obj/kernel/init/* ... 所有的目标文件生成 elf-i386 的内核文件,并且使用kernel.ld链接器脚本$(V)$(LD) $(LDFLAGS) -T tools/kernel.ld -o $@ $(KOBJS)
# 最终的内核文件应该去除符号表等信息,并输出符号表信息,汇编文件信息,和输出信息@$(OBJDUMP) -S $@ > $(call asmfile,kernel)@$(OBJDUMP) -t $@ | $(SED) '1,/SYMBOL TABLE/d; s/ .* / /; /^$$/d' > $(call symfile,kernel)$(call create_target,kernel)# -------------------------------------------------------------------# create bootblock 引导区
# 生成 bin/bootblock
# 启动扇区的编译,过程与内核差不多唯一的区别是需要对编译后的启动扇区进行签名,即有效启动扇区,最后字节为0x55aa。
bootfiles = $(call listf_cc,boot)# boot 下的文件 
$(foreach f,$(bootfiles),$(call cc_compile,$(f),$(CC),$(CFLAGS) -Os -nostdinc))bootblock = $(call totarget,bootblock)$(bootblock): $(call toobj,$(bootfiles)) | $(call totarget,sign)@echo + ld $@$(V)$(LD) $(LDFLAGS) -N -e start -Ttext 0x7C00 $^ -o $(call toobj,bootblock)@$(OBJDUMP) -S $(call objfile,bootblock) > $(call asmfile,bootblock)@$(OBJCOPY) -S -O binary $(call objfile,bootblock) $(call outfile,bootblock)@$(call totarget,sign) $(call outfile,bootblock) $(bootblock)
# boot/bootasm.S  ----> bootasm.o
# boot/bootmain.c ----> bootmain.o
# bootasm.o + bootmain.o ------> bootblock
$(call create_target,bootblock)# -------------------------------------------------------------------
# 生成 tools/sign.c ----> bin/sign
# create 'sign' tools 创建符合规定的硬盘引导扇区  bootblock.out + 0x55AA -> bootblock (512字节)
# 在内核工具目录中,sign.c, 用来给扇区签名的小工具, 为什么这而使用host呢,
# 是因为该工具是在特定操作系统下的工具,所以编译过程跟内核编译过程完全不同,
# 最显著的就是 nostdlibc 内核是必须的编译选项,
# 而应用软件一般都是依赖C库,并且内核代码为了精简,
# 也没有栈溢出保护 --no-stack-protector
$(call add_files_host,tools/sign.c,sign,sign)
$(call create_target_host,sign,sign)
# 生成 一个被系统认为是符合规范的硬盘主引导扇区
# 主引导区大小为512字节且最后两个字节为 0x55 和 0xAA,只要达到这两个条件即符合规范。
# buf[510] = 0x55
# buf[511] = 0xAA# -------------------------------------------------------------------
# 生成 bin/ucore.img
#最后把编译出的二进制文件和bootloader都写进一个大文件中,用来模拟硬盘。使用linux下dd块命令
# create ucore.img  创建虚拟硬盘文件
# 引导扇区bootblock + 系统内核kernel -> ucore.img
UCOREIMG	:= $(call totarget,ucore.img)$(UCOREIMG): $(kernel) $(bootblock)$(V)dd if=/dev/zero of=$@ count=10000$(V)dd if=$(bootblock) of=$@ conv=notrunc$(V)dd if=$(kernel) of=$@ seek=1 conv=notrunc$(call create_target,ucore.img)# >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
# 收尾工作/定义变量
$(call finish_all)IGNORE_ALLDEPS	= clean \dist-clean \grade \touch \print-.+ \handinifeq ($(call match,$(MAKECMDGOALS),$(IGNORE_ALLDEPS)),0)
-include $(ALLDEPS)
endif# files for grade script
# 定义各种make目标
TARGETS: $(TARGETS).DEFAULT_GOAL := TARGETS.PHONY: qemu qemu-nox debug debug-nox
#下面的很多命令是qemu的参数,其中一些网上不太好查,有兴趣的话可以去 http://wiki.qemu.org/Manual 查阅#终端模式打开qemu   -monitor
qemu-mon: $(UCOREIMG)$(V)$(QEMU)  -no-reboot -monitor stdio -hda $< -serial null#新窗口下打开qemu   -parallel
qemu: $(UCOREIMG)$(V)$(QEMU) -no-reboot -parallel stdio -hda $< -serial null#运行并生成log文件
log: $(UCOREIMG)$(V)$(QEMU) -no-reboot -d int,cpu_reset  -D q.log -parallel stdio -hda $< -serial null#禁止图形界面,转到终端
qemu-nox: $(UCOREIMG)$(V)$(QEMU)   -no-reboot -serial mon:stdio -hda $< -nographic
TERMINAL        :=gnome-terminal#调试
# 利用make debug来观察BIOS的单步执行
# 首先是对qemu进行的操作
# sleep 2 等待一段时间
# 针对 gdbinit 文件进行的调试
debug: $(UCOREIMG)$(V)$(QEMU) -S -s -parallel stdio -hda $< -serial null &$(V)sleep 2$(V)$(TERMINAL) -e "gdb -q -tui -x tools/gdbinit"#在终端打开qemu进行调试,现在终端会陷入死循环QAQ
debug-nox: $(UCOREIMG)$(V)$(QEMU) -S -s -serial mon:stdio -hda $< -nographic &$(V)sleep 2$(V)$(TERMINAL) -e "gdb -q -x tools/gdbinit".PHONY: grade touchGRADE_GDB_IN	:= .gdb.in
GRADE_QEMU_OUT	:= .qemu.out
HANDIN			:= proj$(PROJ)-handin.tar.gzTOUCH_FILES		:= kern/trap/trap.cMAKEOPTS		:= --quiet --no-print-directorygrade:$(V)$(MAKE) $(MAKEOPTS) clean$(V)$(SH) tools/grade.shtouch:$(V)$(foreach f,$(TOUCH_FILES),$(TOUCH) $(f))print-%:@echo $($(shell echo $(patsubst print-%,%,$@) | $(TR) [a-z] [A-Z])).PHONY: clean dist-clean handin packall tags
# 清理
clean:$(V)$(RM) $(GRADE_GDB_IN) $(GRADE_QEMU_OUT) cscope* tags-$(RM) -r $(OBJDIR) $(BINDIR)
#把压缩包也删除
dist-clean: clean-$(RM) $(HANDIN)#打包并输出一句话
handin: packall@echo Please visit http://learn.tsinghua.edu.cn and upload $(HANDIN). Thanks!#打包
packall: clean@$(RM) -f $(HANDIN)@tar -czf $(HANDIN) `find . -type f -o -type d | grep -v '^\.*$$' | grep -vF '$(HANDIN)'`#可能是输出所有tags,要cscope工具
tags:@echo TAGS ALL$(V)rm -f cscope.files cscope.in.out cscope.out cscope.po.out tags$(V)find . -type f -name "*.[chS]" >cscope.files$(V)cscope -bq $(V)ctags -L cscope.files

通用makefile

#########################################################################
######################## Configuration Area #############################
CC = gcc
CXX = g++
OBJDUMP = objdumpINCLUDES +=
CFLAGS += -g
CXXFLAGS += -g
LDFLAGS +=
LIBS +=
DUMP_FLAGS = -DTARGET_OUTPUT_DIR = bin
DUMP_OUTPUT_DIR = ${TARGET_OUTPUT_DIR}
#########################################################################ifneq (${INCLUDES}, )CFLAGS += -I${INCLUDES}CXXFLAGS += -I${INCLUDES}
endifC_SRC = $(wildcard *.c)
C_TARGET = $(patsubst %.c, ${TARGET_OUTPUT_DIR}/%, ${C_SRC})
C_DUMP= $(patsubst %.c, ${DUMP_OUTPUT_DIR}/%.dump, ${C_SRC})
CXX_SRC = $(wildcard *.cpp)
CXX_TARGET = $(patsubst %.cpp, ${TARGET_OUTPUT_DIR}/%, ${CXX_SRC})
CXX_DUMP= $(patsubst %.cpp, ${DUMP_OUTPUT_DIR}/%.dump, ${CXX_SRC})
TARGET = ${C_TARGET} ${CXX_TARGET}
DUMP = ${C_DUMP} ${CXX_DUMP}all: ${TARGET}dump: ${DUMP} ${TARGET}clean:@rm -f ${TARGET} ${DUMP}${C_TARGET}: ${TARGET_OUTPUT_DIR}/%: %.c@mkdir -p `dirname $@`${CC} -o $@ $< ${CFLAGS} ${LDFLAGS} ${LIBS}${CXX_TARGET}: ${TARGET_OUTPUT_DIR}/%: %.cpp@mkdir -p `dirname $@`${CXX} -o $@ $< ${CXXFLAGS} ${LDFLAGS} ${LIBS}${DUMP}: ${DUMP_OUTPUT_DIR}/%.dump: ${TARGET_OUTPUT_DIR}/%@mkdir -p `dirname $@`${OBJDUMP} ${DUMP_FLAGS} $< > $@

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/43174.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

文心一言 VS 讯飞星火 VS chatgpt (76)-- 算法导论7.3 1题

一、如果用go语言&#xff0c;为什么我们分析随机化算法的期望运行时间&#xff0c;而不是其最坏运行时间呢? 文心一言&#xff1a; 在分析算法的性能时&#xff0c;期望运行时间是一个重要的指标&#xff0c;它描述了算法在平均情况下的表现。期望运行时间考虑了所有可能的…

管理类联考——逻辑——真题篇——按知识分类——汇总篇——二、论证逻辑——支持加强——第二节——分类2——正面支持

文章目录 第二节 支持加强-分类2-正面支持题-支持加强-分类2-正面支持-表达“确实如此”题-支持加强-分类2-正面支持-表达“确实如此”-正面支持不直观:转为削弱反面更直观真题(2010-38)-支持加强-分类2-正面支持真题(2018-29)-支持加强-分类2-正面支持-支持关键词真题(…

musl libc ldso 动态加载研究笔记:02

前言 本篇继续研究 musl libc ldso 的动态加载过程中遇到的关键性的概念&#xff1a;到底要加载ELF 文件的哪些内容到 内存 当前如果遇到 ELF 动态加载&#xff0c;当前系统需要有【文件系统】&#xff0c;并且有较大的内存&#xff0c;因为 ELF 文件是无法直接运行的&#xf…

IDEA两种方法修改生成的jar包名字

方法一&#xff1a; 直接修改pom文件中的如下部分 <artifactId>excelreport</artifactId> <version>0.0.1-SNAPSHOT</version> <name>excelreport</name> <description>excelreport</description> 修改完成后&#xff0c;点…

SpringBoot3集成Kafka

标签&#xff1a;Kafka3.Kafka-eagle3&#xff1b; 一、简介 Kafka是一个开源的分布式事件流平台&#xff0c;常被用于高性能数据管道、流分析、数据集成和关键任务应用&#xff0c;基于Zookeeper协调的处理平台&#xff0c;也是一种消息系统&#xff0c;具有更好的吞吐量、内…

跟着美团学设计模式(感处)

读了着篇文章之后发现真的是&#xff0c;你的思想&#xff0c;你的思维是真的比比你拥有什么技术要强的。 注 开闭原则 开闭原则&#xff08;Open-Closed Principle&#xff09;是面向对象设计中的基本原则之一&#xff0c;它的定义是&#xff1a;一个软件实体应该对扩展开放…

python生成旗帜--比如美国国旗生成

目录 1、解释说明&#xff1a; 2、使用示例&#xff1a; 3、注意事项&#xff1a; 1、解释说明&#xff1a; 在Python中&#xff0c;生成国旗可以通过使用第三方库或者自定义函数来实现。通常&#xff0c;我们可以使用Pillow库来处理图像&#xff0c;以及使用matplotlib库来…

python爬虫7:实战1

python爬虫7&#xff1a;实战1 前言 ​ python实现网络爬虫非常简单&#xff0c;只需要掌握一定的基础知识和一定的库使用技巧即可。本系列目标旨在梳理相关知识点&#xff0c;方便以后复习。 申明 ​ 本系列所涉及的代码仅用于个人研究与讨论&#xff0c;并不会对网站产生不好…

carla中lka实现(二)

前言&#xff1a; 首先计算之前检测出来的车道线的中线与输入图像的中线进行计算距离&#xff0c;&#xff0c;并设置不同的阈值对于不同的方向进行相关的调整。 一、车辆中心线 一般而言将摄像头架设在车辆的正中心轴上&#xff0c;所获得的图像的中间线极为车辆的中心。 …

QGraphicsView 实例3地图浏览器

主要介绍Graphics View框架&#xff0c;实现地图的浏览、放大、缩小&#xff0c;以及显示各个位置的视图、场景和地图坐标 效果图: mapwidget.h #ifndef MAPWIDGET_H #define MAPWIDGET_H #include <QLabel> #include <QMouseEvent> #include <QGraphicsView&…

WSL2 ubuntu子系统OpenCV调用本机摄像头的RTSP视频流做开发测试

文章目录 前言一、Ubuntu安装opencv库二、启动 Windows 本机的 RTSP 视频流下载解压 EasyDarwin查看本机摄像头设备开始推流 三、在ubuntu 终端编写代码创建目录及文件创建CMakeLists.txt文件启动 cmake 配置并构建 四、结果展示启动图形界面在图形界面打开终端找到 rtsp_demo运…

linux系统服务学习(二)linux下yum源配置实战

文章目录 Linux下yum源配置实战一、Linux下软件包的管理1、软件安装方式2、源码安装的配置过程3、详解源码安装的配置过程&#xff08;定制&#xff09;4、详解编译过程5、安装过程6、axel多线程下载软件源码安装7、使用软链接解决command not found8、使用环境变量解决command…

软考A计划-系统集成项目管理工程师-收尾管理

点击跳转专栏>Unity3D特效百例点击跳转专栏>案例项目实战源码点击跳转专栏>游戏脚本-辅助自动化点击跳转专栏>Android控件全解手册点击跳转专栏>Scratch编程案例点击跳转>软考全系列点击跳转>蓝桥系列 &#x1f449;关于作者 专注于Android/Unity和各种游…

字符串的无重复排列组合

题目描述&#xff1a; 无重复字符串的排列组合。编写一种方法&#xff0c;计算某字符串的所有排列组合&#xff0c;字符串每个字符均不相同。 示例1: 输入&#xff1a;S "qwe" 输出&#xff1a;["qwe", "qew", "wqe", "weq&q…

中间件(二)dubbo负载均衡介绍

一、负载均衡概述 支持轮询、随机、一致性hash和最小活跃数等。 1、轮询 ① sequences&#xff1a;内部的序列计数器 ② 服务器接口方法权重一样&#xff1a;&#xff08;sequences1&#xff09;%服务器的数量&#xff08;决定调用&#xff09;哪个服务器的服务。 ③ 服务器…

opencv直方图与模板匹配

import cv2 #opencv读取的格式是BGR import numpy as np import matplotlib.pyplot as plt#Matplotlib是RGB %matplotlib inline def cv_show(img,name):cv2.imshow(name,img)cv2.waitKey()cv2.destroyAllWindows() 直方图 cv2.calcHist(images,channels,mask,histSize,ran…

Spring中Bean的生命周期以及Bean的单例与多例模式

一. Bean的生命周期 bean的生命周期可以表达为&#xff1a;bean的定义➡bean的初始化➡bean的使用➡bean的销毁 Bean的初始化过程 1&#xff09;通过XML、Java annotation&#xff08;注解&#xff09;以及Java Configuration&#xff08;配置类&#xff09; 等方式加载Bea…

2023+HuggingGPT: Solving AI Tasks with ChatGPT and itsFriends in Hugging Face

摘要&#xff1a; 语言是llm(例如ChatGPT)连接众多AI模型(例如hugs Face)的接口&#xff0c;用于解决复杂的AI任务。在这个概念中&#xff0c;llms作为一个控制器&#xff0c;管理和组织专家模型的合作。LLM首先根据用户请求规划任务列表&#xff0c;然后为每个任务分配专家模…

Unity 鼠标实现对物体的移动、缩放、旋转

文章目录 1. 代码2. 测试场景 1. 代码 using UnityEngine;public class ObjectManipulation : MonoBehaviour {// 缩放比例限制public float MinScale 0.2f;public float MaxScale 3.0f;// 缩放速率private float scaleRate 1f;// 新尺寸private float newScale;// 射线pri…

【Windows系统编程】03.远线程注入ShellCode

shellcode&#xff1a;本质上也是一段普通的代码&#xff0c;只不过特殊的编程手法&#xff0c;可以在任意环境下&#xff0c;不依赖于原有的依赖库执行。 远程线程 #include <iostream> #include <windows.h> #include <TlHelp32.h>int main(){HANDLE hPr…