LV012-变量与shell命令
在Makefile中,变量可以使用shell命令的结果进行赋值。这种功能非常有用,因为它允许我们在Makefile中动态地获取系统信息,如当前目录、文件列表、系统版本等,而无需在命令行中手动指定。
一、基本语法
1. $(shell command)
这是最常用的通过shell命令为变量赋值的方式。语法格式如下:
makefile
variable := $(shell command)2. 反引号
也可以使用反引号来执行shell命令:
makefile
variable := `command`二、常用示例
1. 获取文件列表
makefile
# 获取文件列表
SOURCE_FILES := $(shell find . -name "*.c")
HEADER_FILES := $(shell find . -name "*.h")
# 获取目录列表
INC_DIR += $(shell find ./inc ../../include -type d )
# 获取静态库和动态库
LD_FLAGS += $(shell find ./lib -type f|grep \.a\$$)
LD_FLAGS += $(shell find ./lib -type f|grep \.so\$$)其实这里的几个示例还是很常用的,他们其实用的都是find命令的用法。前面几个都很好理解,这里主要看一些后面获取动态库和静态库的命令:
find ./lib -type f:在./lib目录下递归查找所有类型为普通文件(file)的文件。grep \.a\$$:使用grep命令筛选出以.a结尾的文件(静态库文件)。这里的正则表达式解释如下:.是正则表达式中的特殊字符,匹配任意字符。为了匹配字面意思的点号,需要使用反斜杠\进行转义。a匹配字母a。$$是正则表达式中的锚点符号,表示字符串结尾。在Makefile中,因为$是特殊字符,所以需要使用$$来表示字面意思的$。- 所以
\.a$$表示匹配以.a结尾的文件名,例如libfoo.a、libc.a等。
2. 获取信息
makefile
# 获取当前目录名
CURDIR_NAME := $(shell basename $(CURDIR))
# 获取系统信息
HOST_OS := $(shell uname -s)
CURRENT_USER := $(shell whoami)
CURRENT_DATE := $(shell date +%Y-%m-%d)
# 获取git信息
GIT_COMMIT := $(shell git rev-parse HEAD)
GIT_BRANCH := $(shell git rev-parse --abbrev-ref HEAD)
GIT_STATUS := $(shell git status --porcelain)
# 检查是否安装了某个命令
CHECK_CMD := $(shell which gcc 2>/dev/null || echo "not found")
# 检查文件是否存在
FILE_EXISTS := $(shell [ -f "config.txt" ] && echo "exists" || echo "missing")三、注意事项
1. 错误处理
使用shell命令时要注意错误处理:
makefile
# 安全的方式执行可能失败的命令
VERSION := $(shell git describe --tags 2>/dev/null || echo "unknown")2. 性能考虑
shell命令在makefile解析时执行,如果命令比较耗时,会影响makefile的解析速度。
3. 输出格式
shell命令的输出会被自动处理,多余的空白符会被删除。如果需要保留空格,可以使用以下方式:
makefile
# 保留原始输出格式
RAW_OUTPUT := $(shell command)
# 或者使用管道处理
PROCESSED_OUTPUT := $(shell command | tr '\n' ' ')