Reputation: 62848
I'm currently writing a Haskell package. I want it to behave differently on Windows and Unix. What is the most "correct" way to detect what OS my code is being compiled on?
I did try using CPP and #ifdef _WIN32
, but that doesn't appear to work at all.
Is there another macro? Can I get Cabal to tell me? Do I need to try something else entirely?
Upvotes: 22
Views: 3421
Reputation: 15121
You could use System.Info
as defined in the base package here:
> :m + System.Info
> os
"darwin"
> arch
"i386"
Upvotes: 40
Reputation: 2775
Cabal's Distribution.System module has an OS data type and an Arch data type, so you can pattern-match against named constructors instead of stringy data.
For example, you can use buildOS
:
case buildOS of
Windows -> -- do something
_ -> -- do something else
Upvotes: 6
Reputation: 15058
Quoting the GHC manual:
The symbols defined by GHC are listed below.
[...]
os_HOST_OS=1
- This define allows conditional compilation based on the Operating System, whereos
is the name of the current Operating System (eg.linux
,mingw32
for Windows,solaris
, etc.).
So to detect whether your code is being compiled on Windows you should use
#ifdef mingw32_HOST_OS
Obviously, you need to have CPP enabled for that to work.
For those who are wondering - mingw32_HOST_OS
is also defined on 64-bit Windows:
C:\ghc-7.8.2\bin>ghc --info
...
,("Build platform","x86_64-unknown-mingw32")
,("Host platform","x86_64-unknown-mingw32")
,("Target platform","x86_64-unknown-mingw32")
...
C:\ghc-7.8.2\bin>ghc -E -optP-dM -cpp foo.hs
C:\ghc-7.8.2\bin>cat foo.hspp
{-# LINE 1 "foo.hs" #-}
#define __ASSEMBLER__ 1
#define mingw32_HOST_OS 1
#define __GLASGOW_HASKELL__ 708
#define __STDC_HOSTED__ 1
#define TABLES_NEXT_TO_CODE 1
#define x86_64_HOST_ARCH 1
#define x86_64_BUILD_ARCH 1
#define mingw32_BUILD_OS 1
#define __SSE2__ 1
#define __SSE__ 1
Confusingly, mingw64_HOST_OS
is not - use x86_64_HOST_ARCH
to detect 64-bit Windows specifically.
Upvotes: 19
Reputation: 62848
These are all good answers. For completeness, it seems Cabal also has a hook for this:
http://www.haskell.org/ghc/docs/7.0.3/html/Cabal/authors.html#conditions
In particular, it's slightly sad that "Windows" is identified as "mingw32". I hate to think what would happen if I went and installed the 64-bit GHC! (Would that then be "mingw64"?) And what if one day GHC is built with some other compiler? Or, dare we dream, there exist Haskell compilers that aren't GHC? (OK, that sounds fairly far-fetched right now, but it could plausibly happen...)
It seems that Cabal has special-case logic to deal with this, such that os(windows)
is supposed to work all the time. It seems to me that by getting Cabal to do the work, if Wild Things happen in the future, it will be Cabal's job to sort that out, not mine.
Upvotes: 5