我正在开发一个新的 Makefile 基础设施,到目前为止,我已经设法使它非常可移植,因为它可以工作(使用 GNU-make(:
- 在 Linux 上
- 在Windows上(仅适用于CMD shell + GnuWin32 CoreUtils + GnuWin32 Make(
- 在Windows上(使用MSYS2 shell(
我使用的是罐装食谱,食谱使用顶部提供的参数。这些参数通常是标头包含目录和库包含目录。
到目前为止,我假设提供给罐装食谱的所有路径都相对于 Makefile 所在的位置 - 在配方中,这些路径始终以以下前缀为前缀:
ROOT_DIR := $(dir $(abspath $(lastword $(MAKEFILE_LIST))))
最近,我遇到了一个例子,其中我需要指定的包含路径并不容易用相对术语指定。 如果coreutils的"realpath --relative-to"在Windows上工作,我会使用它,但它不是。同样在Windows上,相对路径并不总是可能的,例如,如果包含目录和makefile位于不同的驱动器上。
因此,我目前的首选方法是在罐装食谱中检测作为参数提供的路径是绝对路径还是相对路径。仅当它是相对的时,它才会以 ROOT_DIR 为前缀,否则按原样使用。
任何建议如何以强大和便携的方式做到这一点?
我们可以检查各种情况:
- 领先的
/
, - 领先的
~
, - 前导
X:
,其中X
是大写字母(Windows 驱动器(, - 领先的
\
(视窗网络驱动器(
对于每个设置一个变量yes
或空字符串:
IS_ROOT := $(if $(patsubst /%,,$(THE_PATH_TO_CHECK)),,yes)
IS_HOME := $(if $(patsubst ~%,,$(THE_PATH_TO_CHECK)),,yes)
IS_NETWORK := $(if $(patsubst \\%,,$(THE_PATH_TO_CHECK)),,yes)
IS_DRIVE := $(foreach d,A B C D E...Z,$(if $(patsubst $(d):/%,,$(THE_PATH_TO_CHECK)),,yes))
然后,我们可以测试这些变量的串联是否等于yes
:
ifeq ($(strip $(IS_ROOT)$(IS_HOME)$(IS_NETWORK)$(IS_DRIVE)),yes)
<absolute>
else
<relative>
endif
当然,如果您有其他情况,您可以使用类似的 make 函数组合来添加它们。