Makefile 检查生成文件中路径是绝对路径还是相对路径的可移植方法

Makefile 检查生成文件中路径是绝对路径还是相对路径的可移植方法,makefile,gnu-make,Makefile,Gnu Make,我正在开发一个新的Makefile结构,到目前为止,我已经设法使它非常可移植(与GNU make一起使用): 在Linux上 在Windows上(仅使用CMD shell+GnuWin32 CoreUtils+GnuWin32 Make) 在Windows上(使用MSYS2外壳) 我使用的是罐装配方,配方使用的是顶部提供的参数。这些参数通常是header include dirs和library include dirs 到目前为止,我假设提供给罐装配方的所有路径都与Makefile所在的位

我正在开发一个新的Makefile结构,到目前为止,我已经设法使它非常可移植(与GNU make一起使用):

  • 在Linux上
  • 在Windows上(仅使用CMD shell+GnuWin32 CoreUtils+GnuWin32 Make)
  • 在Windows上(使用MSYS2外壳)
我使用的是罐装配方,配方使用的是顶部提供的参数。这些参数通常是header include dirs和library include dirs

到目前为止,我假设提供给罐装配方的所有路径都与Makefile所在的位置相关——在配方中,这些路径始终以以下前缀为前缀:

ROOT_DIR := $(dir $(abspath $(lastword $(MAKEFILE_LIST))))
最近,我遇到了一个示例,其中我需要指定的include路径不容易用相对术语指定。 如果coreutils“realpath--relative”在Windows上工作,我会使用它,但它不是。此外,在Windows上,相对路径也不总是可能的,例如,如果include dir和makefile位于不同的驱动器上

因此,目前我首选的方法是在罐装配方中检测作为参数提供的路径是绝对的还是相对的。只有当它是相对的时,才会以ROOT_DIR作为前缀,否则就按原样使用


如何以一种健壮、便携的方式做到这一点,有什么建议吗?

我们可以检查各种情况:

  • 前导
    /
  • 前导
    ~
  • 前导
    X:
    其中
    X
    是大写字母(Windows驱动器)
  • 领先的
    \\
    (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
    
    ifeq($(strip$(IS\u ROOT)$(IS\u HOME)$(IS\u NETWORK)$(IS\u DRIVE)),是)
    其他的
    恩迪夫
    

    当然,如果您考虑了其他情况,可以使用类似的make函数组合来添加它们。

    欢迎使用堆栈溢出。您将在一个工作目录中运行Make,该目录通常不是makefile所在的目录,对吗?与这里讨论的问题没有直接关系,我想我会分享一些我发现的关于两个绝对路径的好想法:-我没有尝试过,我想知道当两个绝对路径不在同一个驱动器上时,它在Windows上的行为如何。。。它会抛出错误吗?-谢谢,这是一个很好的开始!我想说两点:1)这应该在Linux和MSYS上都能正常工作,除非检查路径以~。对如何处理这个案子也有什么建议吗?你能想到其他例外情况吗
    2)Windows CMD外壳的情况如何?如何检查路径是否以驱动器号开头?(我的个人习惯是在窗户上也使用前向缝板,以避免任何问题)?本例中的例外情况可能是以\\开头的网络路径。我不使用Windows,因此无法测试,但我们可以单独测试这些情况,并使用
    ifeq
    条件将它们合并。查看我的更新答案。它看起来像是
    $(abspath/)
    给出了文件系统的根目录。我在Msys2中用
    mingw32 make
    对它进行了测试,结果是
    C:///code>。也许只要检查一下它给出的前缀就足够了。