9-makefile学习

 

 

一般的 ./configure --enable-static ,这里的 --enable-static 仅控制自身 是否生成静态库,不影响它的依赖库的链接方式
没有特殊指定那就优先链接依赖库的动态库,如 -lts,  # 特殊指定 -l:libts.a
也可以使用参数优先链接依赖库的静态库:-Wl,-Bstatic  # -Wl,-Bdynamic:恢复默认的动态链接

 

 

实例1
 SHELL := /bin/bash

# \
1. ifneq 只能在规则里使用,不能在函数里使用 \
2. 函数和依赖的方式哪个更好:\
  1. 函数:$(call func, args...),无论 all 是否需要构建 都会立即执行;\
  2. 依赖:all: a1 a2 , Make 决定是否需要重新构建,取决于 a1 和 a2 是否比 all 更新


TARGET:=a b c d

FILE = $(foreach v, $(TARGET),$v.txt) # 全局变量 在Make解析阶段被计算,结果赋值给变量,不会去执行结果; 内部变量会导致 shell 尝试执行结果,如执行 a.txt、b.txt 结果没有这个命令就报错了,所以全局变量要加双引号

GREEN = "\e[32;1m"
GREEN_END    = "\033[0m"

.PHONY: clean # 伪目标表示这里 clean 只是一个标签,防止有文件名称也叫 clean

# 给其它函数调用,用于测试
define func0
	echo " 进入 func0 函数"
endef

# 变量、循环、判断
define func1

	echo "进入 func1 函数"

	echo $(0) $(1) # $(0)是函数名,这里是:func1、 $(1)是传过来的第1个参数,这里是:a b c d

	echo "FILE=$(FILE)" # 访问全局变量没有问题

	# 定义一个局部变量。 注意1:等于号两边不能有空格 2:要在同一行执行
	VAR="Hello, World!";\
	echo $$VAR

	# 定义一个全局变量。 出了这个函数也可以被使用
	$(eval VAR2 := Hello, World2!)
	echo $(VAR2)

	# 循环 1
	# 内部变量 会导致 shell 尝试执行展开后的文本,如执行展开后的文本 a.txt、b.txt 结果没有这个命令就报错了,所以扩展变量要加双引号
	VAR3="$(foreach v,$(TARGET),$v.txt)"; \
	echo $$VAR3

	# 循环2
	for v in $(TARGET); do\
		echo $$v.txt; \
	done

	# 变量有空格的情况下,两边要加 双引号
	if [ "$(VAR2)" != "Hello, World2!" ]; then \
		echo "error"; \
		exit 1; \
	else \
		echo "ok"; \
	fi

	# -e 可以判断文件或目录
	if [ -e ./bl31.bin ] && [ -e ./webs ]; then \
		echo "yes"; \
	fi

endef

# 调用 sell
define func2
	echo "进入 func2 函数"

	$(call func3)

	echo `pwd`
	echo $(shell pwd)

	# 不等于:-ne、等于:-eq、大于:-gt、小于:-lt、大于等于: -ge、小于等于: -le
	var=1;var2=2;var3=$$[$$var+$$var2]; var3=$$[$$var3+2];\
	echo var3=$$var3 ;\
	if [ $$var -ne 2 ]; then \
		echo "var 不等于2"; \
	fi; \
	if [ $$var -eq 1 ]; then \
		echo "var 等于1"; \
	fi; 


	# $(shell ...) 不适合用于交互式命令
	echo "请输入数字:"
	read num; \
	case $$num in \
		1) echo "You entered 1";; \
		2) echo "You entered 2";; \
		*) echo "Invalid input";; \
	esac

	# 不是数字也可以
	echo "请输入:"
	read num; \
	case $$num in \
		aa) echo "You entered aa";; \
		bb) echo "You entered bb";; \
		*) echo "Invalid input";; \
	esac

endef

# 输出绿色的一段话
define func3
	echo -e $(GREEN) "进入 func3 函数" $(GREEN_END)
endef

all: a1 a2
#	$(call func1,$(TARGET) ) # 调用函数,并传一个参数
#	$(call func2)
	$(call func3)
	echo "end"

a1:
	echo "a1"

a2:
	echo "a2"
	echo "$(wildcard ./webs)" # 找到了就返回 ./webs, 不然什么都不返回,所以可以这样:ifneq ($(wildcard ./webs),) 判断
ifeq (./webs, $(wildcard ./webs))
	echo "webs 目录存在"
endif
ifneq (./webs2, $(wildcard ./webs))
	echo "webs2 目录不存在"
endif
ifeq ($(wildcard ./webs2),)
	echo "webs2 目录不存在"
endif
	pushd webs; echo "当前目录:$$(pwd) 或者 `pwd`; 执行make的目录:$(CURDIR) 或者 $(PWD)"; popd
	pushd webs; \
		pushd images; echo "当前目录1:`pwd`" ; popd;\
		echo "当前目录2:`pwd`"; \
	popd
	# 当前目录1:/home/fx/share/temp/webs/images
	# 当前目录2:/home/fx/share/temp/webs
	

 

 

[ -f Makefile ] && make clean || true  # 如果 Makefile 文件存在,执行 make clean

 

存根(stub)库 就只是让你测试代码的时候不报错就简单定义了一下,没有实际的实现代码,所以  -Wl,-rpath 实际引用的时候别引用到 stub 库了

 

静态库打包
# 静态库打包(总之不能直接将动态库(.so)打包到静态库中)

1. 先生成 .o
g++ -c -I/xxx main.cpp -o main.o

2. 打包 main.o 到静态库
    方案1:ar rcs libmain.a main.o // 这样的话以后的程序需要连接 main.a 之前的依赖库如:g++ -o ts ts.o libmain.a -L/opencv/lib -lopencv_core -l...
    方案2:ar rcs libmylib.a main.o /path/to/opencv/lib/*.a

 

# 将空格替换为冒号: $(subst <old>,<new>,<text>)
LIB_DIR_PATHS_WITH_COLONS := $(subst ,:,$(LIB_DIR_PATHS))

 

# 移除-L前缀:$(patsubst <pattern>,<replacement>,<text>)
  # <pattern> 是你要匹配的模式。它通常包含通配符%,%代表任意长度的文本。
  # <replacement> 是用来替换匹配到的模式的文本。它也可以包含%,表示保留被匹配的文本部分
  # <text> 是要进行模式匹配和替换的文本或变量
LIB_DIR_PATHS := $(patsubst -L%,%,$(LIB_DIRS))
  # <pattern> 是-L%,意味着任何以-L开头的文本串
  # <replacement> 是%,意味着保留被匹配文本中-L之后的部分
  
  # 因此,patsubst -L%,%,$(LIB_DIRS)将遍历LIB_DIRS变量中的所有项,如果某一项以-L开始,那么这部分将被移除,只保留-L后面的部分



c:  -lpthread  // 链接器选项,如果你只是需要链接pthread库,而不关心编译器是否做额外的处理,你可以使用-lpthread

c++: -pthread // 是一个编译器和链接器的组合选项,对于编译器,它可能会定义一些宏或启用某些特性,以便更好地支持pthreads

posted @ 2024-12-11 14:15  封兴旺  阅读(44)  评论(0)    收藏  举报

联系方式: 18274305123(微信同号)