MathematicalOrchid
MathematicalOrchid

Reputation: 62848

Haskell: Detect current OS

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

Answers (4)

Lee Duhem
Lee Duhem

Reputation: 15121

You could use System.Info as defined in the base package here:

> :m + System.Info
> os
"darwin"
> arch
"i386"

Upvotes: 40

typesanitizer
typesanitizer

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

Mikhail Glushenkov
Mikhail Glushenkov

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, where os 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

MathematicalOrchid
MathematicalOrchid

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

Related Questions