实例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"
# 给其它函数调用,用于测试
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
.PHONY: clean # 伪目标表示这里 clean 只是一个标签,防止有文件名称也叫 clean
[ -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
标签:main,LIB,makefile,echo,学习,webs,var,txt From: https://www.cnblogs.com/fxw1/p/17809617.html