Make:提取跟随已知路径的目标路径段
Make: extract the target path segment that follows a known one
我正在尝试优化我们的构建目标。在我们当前的流程中,我们有针对 32 位和 64 位构建的单独目标。由于目标不同,我们的构建流程中有数百个目标。我们尝试使其成为全球性的地方,即 32 位和 64 位构建的一个目标。我正在尝试使用以下代码实现此目的。
Target/Output 32 位构建目录应该是这样的:
/test/scratch/<client_name>/Linux/...
Target/Output 64 位构建目录应该是这样的:
/test/scratch/<client_name>/Linux-64bit/...
因此,基于上述目标目录路径,我正在使用 $(findstring)
函数搜索字符串 Linux
,然后继续使用 32 位命令 运行。否则它将 运行 64 位命令如下所示。
RELEASE_FILES := $(TARGET_DIR)/build/test/csimtime.c
$(RELEASE_FILES): $(TGTDIRFILES)/%: %
ifneq (Linux,$(findstring $(OS),$@))
$(test_lib_32)
else
$(test_lib_64)
endif
$(TARGET_DIR)
变量作为参数传递给 make 命令
make TARGET_DIR=$(TGT32) all32
对于 64 位,我们将传递 TARGET_DIR=$(TGT64)
。
注意:test_lib_32/64以上是我们在当前make文件中包含的其他make文件中的宏定义。
按预期工作正常,但我不确定这是否是最好的方法?我注意到这里有一个问题,通常我们传递的 TGT32
/TGT64
变量有值:
/test/scratch/<client_name>/Linux/ (for 32bit)
或
/test/scratch/<client_name>/Linux-64bit/... (for 64bit)
如果有人用 client_name 'Linux' 字符串创建客户端,它将无法工作。它总是会转到 if
块并尝试 运行 32 位命令,即使我们 运行 64 位构建也是如此。我该如何处理?
我正在寻找上述路径中 'client_name' 之后的字符串。请帮忙?
如果我正确理解你的问题,那么你会遇到以下 $(TARGET_DIR)
值的问题:
/.../Linux/.../Linux-64bit
问题是您正在测试 $@
:
的值
/.../Linux/.../Linux-64bit/some/other/file
如您所见,这使得无法决定路径中的哪个 Linux
应该用于决策。
我建议试试这个:
# if $(TARGET_DIR) ends with /Linux -> 32-bit build
$(RELEASE_FILES): $(TGTDIRFILES)/%: %
ifneq ($(filter %/Linux,$(TARGET_DIR)),)
$(test_lib_32)
else
$(test_lib_64)
endif
如果您的目标目录名称总是类似于:
/test/scratch/<client_name>/Linux/...
并且 <client-name>
中没有 /
字符和 space ,您可以根据 Linux
(或 Linux-64bit
) 在路径中:
TYPE := $(word 4,$(subst /, ,$(TARGET_DIR)))
ifeq ($(TYPE),Linux)
<something>
else ifeq ($(TYPE),Linux-64bit)
<something-else>
else
$(error Unknown type: $(TYPE))
endif
EDIT 如果位置不是常数但你知道 <client-name>
是什么,并且没有 /
字符也没有 space s in <client-name>
,你可以像这样提取$(TARGET_DIR)
中<client-name>
后面的目录名:
TAIL := $(subst /, ,$(TARGET_DIR))
$(foreach w,$(TAIL),$(eval TAIL := $(wordlist 2,$(words $(TAIL)),$(TAIL)))$(if $(patsubst $(CLIENT_NAME),,$(w)),,$(eval TYPE := $(word 1,$(TAIL)))))
all:
@printf 'TYPE = $(TYPE)\n'
演示:
$ make TARGET_DIR=/a/b/test-client/Linux/c/d CLIENT_NAME=test-client
TYPE = Linux
$ make TARGET_DIR=/a/b/c/d/test-client/Linux-64bit/e/f/g CLIENT_NAME=test-client
TYPE = Linux-64bit
解释:
TAIL := $(subst /, ,$(TARGET_DIR))
用一个 space 替换 $(TARGET_DIR)
中的 /
个字符,这样它就变成了一个单词列表(路径中每个目录一个),并且将结果分配给变量 TAIL
.
$(foreach w,$(TAIL),...)
使用变量 w
对 $(TAIL)
. 的每个单词连续设置的 ...
求值
$(eval TAIL := $(wordlist 2,$(words $(TAIL)),$(TAIL)))
通过删除前导词重新分配变量 TAIL
。
如果 $(w)
等于 $(CLIENT_NAME)
.,$(if $(patsubst $(CLIENT_NAME),,$(w)),,...)
计算 ...
$(eval TYPE := $(word 1,$(TAIL)))
将 $(TAIL)
的第一个单词赋值给变量 TYPE
.
可能有更简单的方法来做同样的事情...
我正在尝试优化我们的构建目标。在我们当前的流程中,我们有针对 32 位和 64 位构建的单独目标。由于目标不同,我们的构建流程中有数百个目标。我们尝试使其成为全球性的地方,即 32 位和 64 位构建的一个目标。我正在尝试使用以下代码实现此目的。
Target/Output 32 位构建目录应该是这样的:
/test/scratch/<client_name>/Linux/...
Target/Output 64 位构建目录应该是这样的:
/test/scratch/<client_name>/Linux-64bit/...
因此,基于上述目标目录路径,我正在使用 $(findstring)
函数搜索字符串 Linux
,然后继续使用 32 位命令 运行。否则它将 运行 64 位命令如下所示。
RELEASE_FILES := $(TARGET_DIR)/build/test/csimtime.c
$(RELEASE_FILES): $(TGTDIRFILES)/%: %
ifneq (Linux,$(findstring $(OS),$@))
$(test_lib_32)
else
$(test_lib_64)
endif
$(TARGET_DIR)
变量作为参数传递给 make 命令
make TARGET_DIR=$(TGT32) all32
对于 64 位,我们将传递 TARGET_DIR=$(TGT64)
。
注意:test_lib_32/64以上是我们在当前make文件中包含的其他make文件中的宏定义。
按预期工作正常,但我不确定这是否是最好的方法?我注意到这里有一个问题,通常我们传递的 TGT32
/TGT64
变量有值:
/test/scratch/<client_name>/Linux/ (for 32bit)
或
/test/scratch/<client_name>/Linux-64bit/... (for 64bit)
如果有人用 client_name 'Linux' 字符串创建客户端,它将无法工作。它总是会转到 if
块并尝试 运行 32 位命令,即使我们 运行 64 位构建也是如此。我该如何处理?
我正在寻找上述路径中 'client_name' 之后的字符串。请帮忙?
如果我正确理解你的问题,那么你会遇到以下 $(TARGET_DIR)
值的问题:
/.../Linux/.../Linux-64bit
问题是您正在测试 $@
:
/.../Linux/.../Linux-64bit/some/other/file
如您所见,这使得无法决定路径中的哪个 Linux
应该用于决策。
我建议试试这个:
# if $(TARGET_DIR) ends with /Linux -> 32-bit build
$(RELEASE_FILES): $(TGTDIRFILES)/%: %
ifneq ($(filter %/Linux,$(TARGET_DIR)),)
$(test_lib_32)
else
$(test_lib_64)
endif
如果您的目标目录名称总是类似于:
/test/scratch/<client_name>/Linux/...
并且 <client-name>
中没有 /
字符和 space ,您可以根据 Linux
(或 Linux-64bit
) 在路径中:
TYPE := $(word 4,$(subst /, ,$(TARGET_DIR)))
ifeq ($(TYPE),Linux)
<something>
else ifeq ($(TYPE),Linux-64bit)
<something-else>
else
$(error Unknown type: $(TYPE))
endif
EDIT 如果位置不是常数但你知道 <client-name>
是什么,并且没有 /
字符也没有 space s in <client-name>
,你可以像这样提取$(TARGET_DIR)
中<client-name>
后面的目录名:
TAIL := $(subst /, ,$(TARGET_DIR))
$(foreach w,$(TAIL),$(eval TAIL := $(wordlist 2,$(words $(TAIL)),$(TAIL)))$(if $(patsubst $(CLIENT_NAME),,$(w)),,$(eval TYPE := $(word 1,$(TAIL)))))
all:
@printf 'TYPE = $(TYPE)\n'
演示:
$ make TARGET_DIR=/a/b/test-client/Linux/c/d CLIENT_NAME=test-client
TYPE = Linux
$ make TARGET_DIR=/a/b/c/d/test-client/Linux-64bit/e/f/g CLIENT_NAME=test-client
TYPE = Linux-64bit
解释:
TAIL := $(subst /, ,$(TARGET_DIR))
用一个 space 替换$(TARGET_DIR)
中的/
个字符,这样它就变成了一个单词列表(路径中每个目录一个),并且将结果分配给变量TAIL
.$(foreach w,$(TAIL),...)
使用变量w
对$(TAIL)
. 的每个单词连续设置的 $(eval TAIL := $(wordlist 2,$(words $(TAIL)),$(TAIL)))
通过删除前导词重新分配变量TAIL
。
如果 $(if $(patsubst $(CLIENT_NAME),,$(w)),,...)
计算...
$(eval TYPE := $(word 1,$(TAIL)))
将$(TAIL)
的第一个单词赋值给变量TYPE
.
...
求值
$(w)
等于 $(CLIENT_NAME)
.,可能有更简单的方法来做同样的事情...