如何有条件地为 Makefile (BSD + GNU) 中的变量赋值?

How to conditionally assign value to a variable in a Makefile (BSD + GNU)?

我有一个(从我的角度来看)相当复杂的 Makefile。

那主要是因为我想要那里的颜色和其他不必要的东西。

无论如何,我可以直接进入我的问题:

除了Linux我最近支持*BSD,因此我需要在几个地方检查正在使用的平台。 Makefile 中是否可以进行条件变量赋值?类似于:


platform := [ $$(uname) = Linux ] && echo Linux || echo BSD or other

当然这行不通,但希望你明白我的意思。


我需要一个同时适用于 BSD make 和 GNU make 的解决方案。

BSD 和 GNU make 显然都支持 != shell 赋值运算符:

platform_id != uname -s

platform != if [ $(platform_id) = Linux ] || \
    [ $(platform_id) = FreeBSD ] || \
    [ $(platform_id) = OpenBSD ] || \
    [ $(platform_id) = NetBSD ]; then \
        echo $(platform_id); \
    else \
        echo Unrecognized; \
    fi

请注意,赋值实际上是由 shell 求值的:赋值给 make 变量的是求值结果,而不是 shell 命令。

需要 GNU make 的解决方案。它适用于 BSD 上的 GNU make,但不适用于 BSD make。

一种可能是使用 if GNU make function:

platform := $(if $(patsubst Linux,,$(shell uname -s)),BSD or other,Linux)

另一种是仅依赖 shell 条件:

platform := $(shell [ $$(uname) = Linux ] && echo Linux || echo BSD or other)

也可以用GNU make conditionals

ifeq ($(shell uname -s),Linux)
    platform := Linux
else
    platform := BSD or other
endif

使用此解决方案前请注意

Renaud Pacalet的赞美:你分配给make变量的是shell命令,而不是shell执行它们的结果。这将严重限制您对它们的使用(主要是食谱)。您将无法将它们用作目标、先决条件、其他变量定义、make conditionals 的条件。

扩展 MadScientist 的评论

我引用:

Note != was added to GNU make in version 4.0. It won't work in older versions.

并且还简化了一堆不必要的 ifs,我们可以在 可能是所有 版本的 GNU 和 BSD make 上得到一个工作版本,比如下面的方法。

通过 shell

的替代方法
platform_id = $$( uname -s )

platform = $$( \
    case $(platform_id) in \
        ( Linux | FreeBSD | OpenBSD | NetBSD ) echo $(platform_id) ;; \
        ( * ) echo Unrecognized ;; \
    esac )

重要提示:

  • 您需要在此处使用标准 = 惰性赋值。使用立即赋值运算符 :=,它在 BSD make 中不起作用。

  • 您需要在case语句中使用( ... )。否则,它将无法在 OpenBSD

  • 上运行

成功测试:

我仍在努力让 NetBSD 8.0 在 VirtualBox 中工作,所以我还不能确认这一点。


需要对这些系统的旧版本进行进一步测试,因此如果您有其中一个明显较旧的系统,请进行测试,谢谢。