在 makefile 中将 Windows 路径转换为 ​​Unix 路径

Geo*_*son 5 makefile gnu-make

这个问题与Convert Cygwin path to Windows path in a makefile有关,但并不相同。

我需要转换 Windows 路径,例如:

C:\src\bin
Run Code Online (Sandbox Code Playgroud)

进入 Unix 路径,例如:

/c/src/bin
Run Code Online (Sandbox Code Playgroud)

在 makefile 中,我可以使用以下代码来转换此类路径:

slashedpath = $(subst \\,\/,$(windowspath))
unixpath = $(shell cygpath -u $(slashedpath))
Run Code Online (Sandbox Code Playgroud)

当cygpath函数不可用时,如何在 GNU Make 正在处理的 makefile 中执行相同的转换?

ps 如果$(windowspath)包含多个路径怎么办?如何将它们全部转换?

Jos*_*sey 0

生成文件:

windowspath=C:\src\bin
unixpath=$(subst \,/,$(subst C:\,/c/,$(windowspath)))
all:
    @echo "$(windowspath)"
    @echo "$(unixpath)"
Run Code Online (Sandbox Code Playgroud)

给出输出:

C:\src\bin
/c/src/bin
Run Code Online (Sandbox Code Playgroud)

$(windowspath)如果包含多个路径,这也将起作用。在i686-pc-cygwin的 GNU Make 4.2.1以及为i686-redhat-linux-gnu构建的 GNU Make 3.81 上进行了测试。

我很惊讶这竟然有效。


更新:第二个版本将处理各种驱动器,例如C:D:等。其中一些想法来自 Eric Melski 对In GNU Make, how do I conversion a variable to lower case? 的回答。。如果Makefile是:

DRIVE = $(subst \
  A:,/a,$(subst B:,/b,$(subst C:,/c,$(subst D:,/d,$(subst \
  E:,/e,$(subst F:,/f,$(subst G:,/g,$(subst H:,/h,$(subst \
  I:,/i,$(subst J:,/j,$(subst K:,/k,$(subst L:,/l,$(subst \
  M:,/m,$(subst N:,/n,$(subst O:,/o,$(subst P:,/p,$(subst \
  Q:,/q,$(subst R:,/r,$(subst S:,/s,$(subst T:,/t,$(subst \
  U:,/u,$(subst V:,/v,$(subst W:,/w,$(subst X:,/x,$(subst \
  Y:,/y,$(subst Z:,/z,$1))))))))))))))))))))))))))

drive = $(subst \
  a:,/a,$(subst b:,/b,$(subst c:,/c,$(subst d:,/d,$(subst \
  e:,/e,$(subst f:,/f,$(subst g:,/g,$(subst h:,/h,$(subst \
  i:,/i,$(subst j:,/j,$(subst k:,/k,$(subst l:,/l,$(subst \
  m:,/m,$(subst n:,/n,$(subst o:,/o,$(subst p:,/p,$(subst \
  q:,/q,$(subst r:,/r,$(subst s:,/s,$(subst t:,/t,$(subst \
  u:,/u,$(subst v:,/v,$(subst w:,/w,$(subst x:,/x,$(subst \
  y:,/y,$(subst z:,/z,$1))))))))))))))))))))))))))

windowspath = c:\src\bin D:\FOO\BAR
unixpath = $(subst \,/,$(call DRIVE,$(call drive,$(windowspath))))

all:
    @echo Original: "$(windowspath)"
    @echo Modified: "$(unixpath)"
Run Code Online (Sandbox Code Playgroud)

那么输出是make

Original: c:\src\bin D:\FOO\BAR
Modified: /c/src/bin /d/FOO/BAR
Run Code Online (Sandbox Code Playgroud)

更新 2:最直接、最灵活的方法是使用标准正则表达式处理程序,例如perlsed,如果可用的话。例如,使用 GNU sed,此 Makefile 将按要求工作:

windowspath = c:\src\bin D:\FOO\BAR
unixpath = $(shell echo '$(windowspath)' | \
           sed -E 's_\<(.):_/\l\1_g; s_\\_/_g')

all:
    @echo Original: "$(windowspath)"
    @echo Modified: "$(unixpath)"
Run Code Online (Sandbox Code Playgroud)

的解释sed

  • s_\<(.):_/\l\1_gA:对于每个以or开头的单词a:,请将开头替换为/a
  • s_\\_/_g将所有反斜杠替换为正斜杠。

  • 有一个比 Update2 更优雅的解决方案:`unixpath=/$(subst \,/,$(subst :\,/,$(windowspath)))`。这会在前面放置一个“/”,并首先将“:\”替换为“/”。每个程序员的通用经验法则是:复制粘贴会产生糟糕的代码。使用包含函数或子例程的通用代码以及模板(如果可用)。 (2认同)