如何在Makefile(BSD + GNU)中有条件地为变量分配值?

9

我有一个(在我看来)相当复杂的Makefile。

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

无论如何,我现在有一个问题:

除了Linux之外,我现在还支持*BSD,因此我需要在几个地方检查正在使用的平台。在Makefile中是否可以进行条件变量赋值?例如:


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

当然,这并不起作用,但希望你能理解我的意思。


我需要一个既能在BSD的make上工作,也能在GNU的make上工作的解决方案。

2个回答

15

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

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函数
platform := $(if $(patsubst Linux,,$(shell uname -s)),BSD or other,Linux)

另一个方法是仅依赖于shell条件语句:

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

GNU make条件语句也可以使用:

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

3
注意:!= 是在 GNU make 4.0 版本中添加的。在旧版本中无法使用。 - MadScientist

3

使用此解决方案前请注意

来自Renaud Pacalet的一条建议:您正在分配给make变量的是shell命令,而不是它们由shell执行的结果。这将严重限制您可以对它们进行的使用(基本上只能用于recipes)。您将无法将它们用作目标、先决条件、其他变量定义、make条件的条件。

MadScientist的评论上进行拓展

我引用他的话:

请注意,在GNU make 4.0版本中添加了!=。它在旧版本中不起作用。

并简化了一堆不必要的if,我们可以通过以下方法获得一个可工作的版本,可能适用于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中正常工作,所以我还不能确认这个。


需要在这些系统的旧版本上进行进一步测试,因此如果您有其中一个旧得相当显著,请进行测试,谢谢。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接