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.

可能有更简单的方法来做同样的事情...