如何从一组模板中为源设置多个目标? [英] How do I make multiple targets from a set of templates for the source?

查看:66
本文介绍了如何从一组模板中为源设置多个目标?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有由版本号(7.0 7.1 7.2)标识的目标

I have targets identified by a version number (7.0 7.1 7.2)

我有一些模板,每个模板都需要替换一个占位符,这样我最终得到每个版本的目录,并且每个目录中的所有文件都有适当的替换.

I have some templates that have a placeholder that needs to be replaced for each version such that I end up with a directory for each version with all the files in each directory having the appropriate replacements.

因此,如果模板目录为:

So, if the template directory is :

template\Dockerfile

我想结束:

7.0\Dockerfile
7.1\Dockerfile
7.2\Dockerfile

,其中template\Dockerfile中的标签已替换为版本号.

with the the tag in the template\Dockerfile being replaced with the version number.

这是一个简化的示例.模板文件夹中实际上有4个文件(其中2个在子目录中).

This is a simplified example. There are actually 4 files in the template folder (and 2 are in a subdirectory).

管道将运行make build-targets,然后运行适当的docker命令来构建容器并将其推送到存储库-这就是目标.

A pipeline will run make build-targets and then the appropriate docker commands to build the containers and push them to the repository - that's the goal.

虽然对所有这些问题都有一个答案是很高兴的,但我想学习,但是我找不到关于如何处理源和目标集的任何信息.

Whilst it would be nice to have an answer to all of this, I would like to learn, but I can't find anything about how to deal with sets of sources and sets of targets.

任何建议将不胜感激.

当前版本仅在Makefile中的1行:VERSIONS := 7.0 7.1 7.2 latest

The versions are currently just 1 line in the Makefile: VERSIONS := 7.0 7.1 7.2 latest

要运行的代码将是一系列sed命令,以获取模板并将文件中的#version#标签替换为版本号(latest除外,在这种情况下,它将删除标签).

The code to run will be a series of sed commands to take a template and replace a #version# tag in the file with the version number (except for latest in which case it will just remove the tag.

模板源全部在templates目录中.作为sed命令的一部分,生成的文件名会将templates部分替换为版本(包括latest).

The template sources are all in the templates directory. As part of the sed command, the resulting filename will have the part templates replaced with the version (including latest).

开始...(不知道这是否好-还在学习)

A start ... (no idea if this is good or not - still learning)

VERSIONS  := 7.0 7.1 7.2 latest
SOURCEDIR := ./templates
DESTDIR   := ./
TEMPLATES := $(shell find $(SOURCEDIR) -type f)

# For each file in $(TEMPLATES) for each version in $(VERSIONS), create a corresponding file in $(DEST_DIR)/$(VERSION)
# Replace `#version#` with $(VERSION) in each file, except for the `latest` target where the `#version#` removed.

根据下面提供的解决方案,我的最终代码是:

Based upon solutions provide below, my final code is:

VERSIONS := 7.0 7.1 7.2 latest
SOURCE_DIR := ./templates
TEMPLATES := $(shell find $(SOURCE_DIR) -type f)
TEMPLATES := $(patsubst $(SOURCE_DIR)/%,%,$(TEMPLATES))
DEST_DIR := ./

.DEFAULT_GOAL := all
.PHONY: all

# $(1): version
# $(2): template file (without the $(SOURCE_DIR)/ stem)
define generate_target_file
$(DEST_DIR)/$(1)/$(2): $(SOURCE_DIR)/$(2)
    @echo "Making $$@"
    @mkdir -p $$(dir $$@)
    @if [ "$(1)" == "latest" ]; then \
        sed 's/#version#//g' $$< > $$@; \
    else \
        sed 's/#version#/$(1)-/g' $$< > $$@; \
    fi

all: $(DEST_DIR)/$(1)/$(2)
endef

$(foreach version,$(VERSIONS),$(foreach template,$(TEMPLATES),$(eval $(call generate_target_file,$(version),$(template)))))

list:
    @echo 'The following targets are available :'
    @$(MAKE) -pRrq -f $(lastword $(MAKEFILE_LIST)) : 2>/dev/null | \
        awk -v RS= -F: '/^# File/,/^# Finished Make data base/ {if ($$1 !~ "^[#.]") {print $$1}}' | \
        sort | \
        egrep -v -e '^[^[:alnum:]]' -e '^$@$$' | \
        xargs -0

推荐答案

如果使用的是GNU-make,则可以使用make的foreach函数轻松创建循环.您可以嵌套它们. eval函数可用于以编程方式实例化make构造,而call函数可用于创建某种宏:

If you are using GNU-make, you can easily create loops with make's foreach function. And you can nest them. The eval function can be used to programmatically instantiate make constructs and the call function allows you to create kind of macros:

V := 7.0 7.1 7.2 latest
S := ./templates
T := $(shell find $(S) -type f)
T := $(patsubst $(S)/%,%,$(T))
D := ./destdir

.DEFAULT_GOAL := all
.PHONY: all

# $(1): version
# $(2): template file (without the $(S)/ stem)
# $(3): replacement string
define MY_rule
$(D)/$(1)/$(2): $(S)/$(2)
    mkdir -p $$(dir $$@)
    sed 's/#version#/$(3)/g' $$< > $$@

all: $(D)/$(1)/$(2)
endef

$(foreach v,$(V),\
  $(foreach t,$(T),\
    $(eval $(call MY_rule,$(v),$(t),$(patsubst latest,,$(v))))))

GNU制作手册解释了此内容作品.请注意MY_rule宏的双扩展,这是为什么某些$符号必须加倍的原因.

The GNU make manual explains how this works. Beware the double expansion of the MY_rule macro, reason why some $ signs must be doubled.

这篇关于如何从一组模板中为源设置多个目标?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆