区分Windows和类Unix系统的Makefile

61
我希望在Linux和Windows上使用同一个Makefile进行构建。我在Linux上使用默认的GNU make,在Windows上使用mingw32-make(也是GNU make)。
我想要Makefile检测它是在Windows还是Linux上运行。
例如,在Windows上,"make clean"命令看起来像:
clean:
    del $(DESTDIR_TARGET)

但在 Linux 上:

clean:
    rm $(DESTDIR_TARGET)

我想在Windows(\)和Linux(/)上使用不同的目录分隔符。


能否在Makefile中检测Windows操作系统?

PS:我不想在Windows上模拟Linux(例如cygwin等)

这里有一个类似的问题:OS detecting makefile,但我在那里没有找到答案。


5
Windows可以处理正斜杠"/"和反斜杠"",它们是等效的。 - Ency
如果这是一个重要的项目,我想知道是否值得让autotools处理一些可移植性问题? - Cascabel
@Jefromi:autotools假定有基本的UNIX工具集(sh,m4,sed,rm,...)。@tomp:最好在Windows上安装它们(从MSYS或GnuWin),并将精力集中于更具挑战性的可移植性问题上。 - ephemient
@ephemient:啊,对了,我的错。我不是一个Windows人。(但现在我有点困惑——mingw工具链不能提供这个吗?我知道,OP说不要Linux仿真。) - Cascabel
12
@Ency,在Windows上,“del”命令不喜欢带有“/”。请注意。 - Imbue
5个回答

67

我通过寻找一个只在Windows上被设置的环境变量来解决了这个问题。

ifdef OS
   RM = del /Q
   FixPath = $(subst /,\,$1)
else
   ifeq ($(shell uname), Linux)
      RM = rm -f
      FixPath = $1
   endif
endif

clean:
    $(RM) $(call FixPath,objs/*)

因为%OS%是Windows的一种类型,所以应该在所有Windows计算机上设置它,但不用在Linux上设置。

然后这些代码块设置了不同程序的变量,并设置了将正斜杠转换为反斜杠的函数。

当您调用外部命令时(内部命令可以正常工作),您必须使用$(call FixPath,path)。您也可以使用类似以下的内容:

/ := /

然后

objs$(/)*

如果你更喜欢那种格式。


2
谢谢。我在Windows上使用MinGW和在Linux上使用GCC之间切换,这运行得很好。 - Imbue
1
在mingw中,应该使用大写的SYSTEMROOT - SystemParadox
1
你也可以检查ComSpec,它只在Windows上定义。 - kebs
如果您因某种原因正在运行COMMAND.COM,则还应检查大写的SYSTEMROOT:“SystemRoot”不会以该大小写定义(而在CMD.EXE中会定义)。 - user458541
系统根目录在mingw32-make中非常敏感,而且在此之后它无法正常工作。 - Tomáš Zato
显示剩余3条评论

50

SystemRoot 技巧在我的Windows XP上不起作用,但这个方法可以:

ifeq ($(OS),Windows_NT)
    #Windows stuff
    ...
else
    #Linux stuff
    ....
endif

如果您安装了Cygwin并且可执行文件来自Cygwin,则可能会出现一些棘手的问题。您将获得OS = Windows_NT,但是您可以使用Linux命令,例如mkdir -p。目录分隔符的方向也很重要。 - sagi

10
你应该使用$(RM)变量来删除一些文件。

2

检查WINDIR或COMSPEC是区分大小写的。相反,我想出了以下解决方案,希望能对某些人有所帮助:

# detect if running under unix by finding 'rm' in $PATH :
ifeq ($(wildcard $(addsuffix /rm,$(subst :, ,$(PATH)))),)
WINMODE=1
else
WINMODE=0
endif

ifeq ($(WINMODE),1)
# native windows setup :
UNLINK = del $(subst /,\,$(1))
CAT = type $(subst /,\,$(1))
else
# cross-compile setup :
UNLINK = $(RM) $(1)
CAT = cat $(1)
endif

如果使用cygwin或mingw shell,你的路径中会有rm命令,并且仍然在Windows系统中。 - undefined

0
我想要在Linux和Windows上使用相同的Makefile进行构建。
也许你会喜欢CMake

请提供如何使用工具的说明。 - Vlad

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