Makefile that distinguishes between Windows and Unix-like systems
Asked Answered
H

5

63

I would like to have the same Makefile for building on Linux and on Windows. I use the default GNU make on Linux and the mingw32-make (also GNU make) on Windows.

I want the Makefile to detect whether it operates on Windows or Linux.


For example make clean command on Windows looks like:

clean:
    del $(DESTDIR_TARGET)

But on Linux:

clean:
    rm $(DESTDIR_TARGET)

Also I would like to use different directory separator on Windows (\) and Linux (/).


It is possible to detect Windows operating system in Makefile?

PS: I do not want to emulate Linux on Windows (cygwin etc.)

There is similiar question: OS detecting makefile, but I didn't find the answer here.

Harding answered 30/10, 2010 at 13:13 Comment(5)
Windows is able to handle both slashes "/" and "\" are equivalent.Mer
If this is for a substantial project, I wonder if it'd be worth letting autotools handle some of the portability stuff?Impetrate
@Jefromi: autotools assumes a basic UNIX toolset (sh, m4, sed, rm, ...). @tomp: Might as well install them on windows (from MSYS or GnuWin) and spend your efforts on the more challenging portability issues.Bountiful
@ephemient: Ah, right, my bad. I'm not really a windows person. (But now I'm confused - can't the mingw toolchain provide that too? I know, the OP said no linux emulation.)Impetrate
@Ency, the "del" command on Windows doesn't like to be given a "/".Spurgeon
J
70

I solved this by looking for an env variable that will only be set on 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/*)

Because %OS% is the type of windows, it should be set on all Windows computers but not on Linux.

The blocks then setups up variables for the different programs as well as a function for converting the forward slashes into backslashes.

You to have to use $(call FixPath,path) when you call an outside command (internal commands work fine). You could also use something like:

/ := /

and then

objs$(/)*

if you like that format better.

Johore answered 22/12, 2010 at 16:15 Comment(8)
Thanks for this. I switch between MinGW on Windows and GCC on Linux, this works great.Spurgeon
In mingw it should be SYSTEMROOT in uppercaseHalfcocked
You can also check for ComSpec, that is only defined on WindowsAdrial
If you're running COMMAND.COM for some reason, you should also be checking for SYSTEMROOT in uppercase: "SystemRoot" won't be defined with that capitalisation (whereas it will in CMD.EXE).Haemocyte
Updated example to use the upper case version of SYSTEMROOTJohore
System root is sensitive in mingw32-make and it doesn't work after either.Underling
There is already $(RM) in make environments, already depending on OS.Qualified
In GnuWin32's make the predefined variable $(RM) expands to rm -f in CMD.EXESpohr
P
52

The SystemRoot trick didn't work for me on Windows XP but this did:

ifeq ($(OS),Windows_NT)
    #Windows stuff
    ...
else
    #Linux stuff
    ....
endif
Paratyphoid answered 16/6, 2011 at 12:19 Comment(1)
this might be tricky if you have cygwin installed and make executable comes from cygwin. You will get OS=Windows_NT but you can use Linux commands like mkdir -p. The direction of the directory separator is also importantTocantins
R
10

You should probably use the $(RM) variable to remove some files.

Rephrase answered 30/10, 2010 at 13:23 Comment(0)
S
2

Checking WINDIR or COMSPEC is case-sensitive. Instead, I came up with the following solution, hope that helps someone someday:

# 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
Splint answered 25/8, 2018 at 10:58 Comment(1)
If using cygwin or in a mingw shell, you'd have rm in path and still be in windows.Milreis
T
-2

I would like to have the same Makefile for building on Linux and on Windows.

Maybe you will like CMake

Tapir answered 30/10, 2010 at 15:36 Comment(1)
Please put the explanation how to use toolDecretory

© 2022 - 2024 — McMap. All rights reserved.