如何在makefile目标中将“ $ *”值大写?

时间:2019-03-28 17:34:23

标签: makefile pattern-matching uppercase variable-names

我有一堆目标,每个目标都针对不同的外壳,如下所示:

BASH_VERSION := 4.4
FISH_VERSION := 3.0.0
…
ZSH_VERSION := 5.4.2-r1

.PHONY: dev-pure-on-bash
dev-pure-on-bash:
    $(MAKE) dev-pure-on TARGET=bash VERSION="${BASH_VERSION}" ARGS="VERSION=${BASH_VERSION}"

.PHONY: dev-pure-on-elvish
dev-pure-on-elvish:
    $(MAKE) dev-pure-on TARGET=elvish VERSION="${ELVISH_VERSION}" ARGS="VERSION=${ELVISH_VERSION}"

.PHONY: dev-pure-on-fish
dev-pure-on-fish:
    $(MAKE) dev-pure-on TARGET=fish VERSION="${FISH_VERSION}" ARGS="VERSION=${FISH_VERSION}"

…

.PHONY: dev-pure-on-xonsh
dev-pure-on-xonsh:
    $(MAKE) dev-pure-on TARGET=xonsh VERSION="${XONSH_VERSION}" ARGS="VERSION=${XONSH_VERSION}"

.PHONY: dev-pure-on-zsh
dev-pure-on-zsh:
    $(MAKE) dev-pure-on TARGET=zsh VERSION="${ZSH_VERSION}" ARGS="VERSION=${ZSH_VERSION}"

.PHONY: dev-pure-on
dev-pure-on:
    docker run \
        --name run-pure-on-${TARGET} \
        --rm \
        --interactive \
        --tty \
        --volume=$$PWD:/home/pure/.pure/ \
        pure-on-${TARGET}-${VERSION}

尝试

我尝试使用pattern rule失败了:

dev-pure-on-%:
    $(MAKE) dev-pure-on TARGET=$* VERSION="${$*_VERSION}" ARGS="VERSION=${$*_VERSION}"

但是我需要$*中的${$*_VERSION}大写

问题

如何在内部将$*的值大写并在另一个变量中使用它?

2 个答案:

答案 0 :(得分:2)

正如马特(Matt)所建议的,为什么不使用以下内容:

struct MySum : Sum<std::vector<int>>
{
    MySum(int t0, int t1, int t2, int t3) : Sum<std::vector<int>>{t0, t1, t2, t3} { }
};

struct MySum4 : Sum<std::array<int, 4>>
{
    MySum4(int t0, int t1, int t2, int t3) : Sum<std::array<int, 4>>{t0, t1, t2, t3} { }
};

struct MySumSet : Sum<std::set<int>>
{
    MySumSet(int t0, int t1, int t2, int t3) : Sum<std::set<int>>{t0, t1, t2, t3} { }
};

struct MySumList : Sum<std::list<int>>
{
    MySumList(int t0, int t1, int t2, int t3) : Sum<std::list<int>>{t0, t1, t2, t3} { }
};

int main()
{  
    MySum s(1, 2, 3, 4);
    s.print();

    MySum4 s4(1, 2, 3, 4);
    s4.print();
    static_assert(s4.m_terms.size() == 4);

    MySumSet ss(1, 2, 3, 4);
    ss.print();

    MySumList sl(1, 2, 3, 4);
    sl.print();
}

然后使用UC = $(shell echo '$*' | tr '[:lower:]' '[:upper:]') 代替$(UC)。或者,如果您想更通用地做到这一点:

$*

然后使用UC = $(shell echo '$1' | tr '[:lower:]' '[:upper:]') (或使用其他任何方式代替$(call UC,$*))。

使用递归尝试使用特殊的shell设施似乎只是将字符串大写而产生的大量开销。

答案 1 :(得分:0)

请赞成@MadScientist's answer,这使我得以全面实施。


在我第一次尝试使用tr时,我错误地将代码放在目标主体中,而不是在目标之前(如make代码)。

解决方案

BASH_VERSION := 4.4
ZSH_VERSION := 5.4.2-r1

shell = $*
shell_name = $(shell echo '$*' | tr '[:lower:]' '[:upper:]')
shell_version = ${${shell_name}_VERSION}

.PHONY: dev-pure-on-%
dev-pure-on-%:
    @echo ${shell} ${shell_version}
    docker run \
        --name run-pure-on-${shell} \
        --rm \
        --interactive \
        --tty \
        --volume=$$PWD:/home/pure/.pure/ \
        pure-on-${shell}-${shell_version}
  • shell不是必需的,但提供的含义比$*
  • shell_name是大写的shell名称
  • shell_version展开shell_name,然后展开结果变量(例如ZSH_VERSIONBASH_VERSION等)

用法

make dev-pure-on-bash
make dev-pure-on-zsh