Andrew Cowie | 15 Feb 15:05 2013

ifdef based on which OS you're on

I've got a piece of code that looks like this:

        baselineContextSSL :: IO SSLContext
        baselineContextSSL = do
            ctx <- SSL.context
            SSL.contextSetDefaultCiphers ctx
        #if defined __MACOSX__
            SSL.contextSetVerificationMode ctx SSL.VerifyNone
        #elif defined __WIN32__
            SSL.contextSetVerificationMode ctx SSL.VerifyNone
        #else
            SSL.contextSetCADirectory ctx "/etc/ssl/certs"
            SSL.contextSetVerificationMode ctx $
                SSL.VerifyPeer True True Nothing
        #endif
            return ctx

all very nice (this being necessary because apparently the non-free
operating systems don't store their certs in a reliably discoverable
place; bummer).

That, however, is not the problem. After all, this sort of thing is what
#ifdefs are for. The problem is needing to get an appropriate symbol
based on what OS you're using defined.

I naively assumed there would be __LINUX__ and __MACOSX__ and __WIN32__
defined by GHC because, well, that's just the sort of wishful thinking
that powers the universe.

So my question is: what's an appropriate Haskell mechanism for building
(Continue reading)

Artyom Kazak | 15 Feb 15:15 2013
Picon

Re: ifdef based on which OS you're on

Andrew Cowie <andrew <at> operationaldynamics.com> писал(а) в своём письме Fri,  
15 Feb 2013 17:05:13 +0300:

> So my question is: what's an appropriate Haskell mechanism for building
> code that is OS / arch  / distro specific? It's not like I have autoconf
> running generating me a config.h I could #include, right?

You can know the OS and arch without even resorting to CPP; see  
System.Info  
(http://hackage.haskell.org/packages/archive/base/latest/doc/html/System-Info.html),  
which defines `os` and `arch`.

_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe <at> haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe
Andrew Cowie | 15 Feb 15:50 2013

Re: ifdef based on which OS you're on

That's interesting. But are there standard values for those functions? I'm guessing not, seeing a how
they're String and not an ADT.

AfC
Sydney

Artyom Kazak <artyom.kazak <at> gmail.com> wrote:

>You can know the OS and arch without even resorting to CPP; see  
>System.Info  which defines `os` and `arch`.

--

-- 
Andrew Frederik Cowie
Operational Dynamics
Krzysztof Skrzętnicki | 15 Feb 15:16 2013
Picon

Re: ifdef based on which OS you're on

Well, for sure you can in define that in .cabal file:

    if !os(windows)
      CC-Options: "-DWINDOWS"

or something. See: http://www.haskell.org/cabal/users-guide/developing-packages.html#configurations




On Fri, Feb 15, 2013 at 3:05 PM, Andrew Cowie <andrew <at> operationaldynamics.com> wrote:
I've got a piece of code that looks like this:

        baselineContextSSL :: IO SSLContext
        baselineContextSSL = do
            ctx <- SSL.context
            SSL.contextSetDefaultCiphers ctx
        #if defined __MACOSX__
            SSL.contextSetVerificationMode ctx SSL.VerifyNone
        #elif defined __WIN32__
            SSL.contextSetVerificationMode ctx SSL.VerifyNone
        #else
            SSL.contextSetCADirectory ctx "/etc/ssl/certs"
            SSL.contextSetVerificationMode ctx $
                SSL.VerifyPeer True True Nothing
        #endif
            return ctx

all very nice (this being necessary because apparently the non-free
operating systems don't store their certs in a reliably discoverable
place; bummer).

That, however, is not the problem. After all, this sort of thing is what
#ifdefs are for. The problem is needing to get an appropriate symbol
based on what OS you're using defined.

I naively assumed there would be __LINUX__ and __MACOSX__ and __WIN32__
defined by GHC because, well, that's just the sort of wishful thinking
that powers the universe.

So my question is: what's an appropriate Haskell mechanism for building
code that is OS / arch  / distro specific? It's not like I have autoconf
running generating me a config.h I could #include, right?

This feels simple and an appropriate use of CPP; even the symbol names
look just about like what I would have expected; stackoverflow said so,
must be true. Just need to get the right symbol defined at build time.

Any suggestions?

AfC
Sydney


_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe <at> haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe <at> haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe
Andrew Cowie | 16 Feb 01:57 2013

Re: ifdef based on which OS you're on

On Fri, 2013-02-15 at 15:16 +0100, Krzysztof Skrzętnicki wrote:

> See:
> http://www.haskell.org/cabal/users-guide/developing-packages.html#configurations

That link says os():

        "Tests if the current operating system is name. The argument is
        tested against System.Info.os on the target system. There is
        unfortunately some disagreement between Haskell implementations
        about the standard values of System.Info.os. Cabal canonicalises
        it so that in particular os(windows) works on all
        implementations. If the canonicalised os names match, this test
        evaluates to true, otherwise false. The match is
        case-insensitive."

So this approach is back to relying on System.Info.os either way. What
worries me is the "Cabal canonicalises it", which seems to indicate that
there are actually many values that show up in 'os' that need to be
regularized. Anyone have any idea if the Cabal library exposes this
somewhere?

AfC
Sydney

_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe <at> haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe
Henk-Jan van Tuyl | 16 Feb 08:18 2013
Picon

Re: ifdef based on which OS you're on

On Sat, 16 Feb 2013 01:57:14 +0100, Andrew Cowie  
<andrew <at> operationaldynamics.com> wrote:

> Anyone have any idea if the Cabal library exposes this
> somewhere?

See:
http://hackage.haskell.org/packages/archive/Cabal/1.16.0.3/doc/html/Distribution-System.html

Regards,
Henk-Jan van Tuyl

--

-- 
http://Van.Tuyl.eu/
http://members.chello.nl/hjgtuyl/tourdemonad.html
Haskell programming
--
Andrew Cowie | 24 Feb 23:28 2013

Re: ifdef based on which OS you're on

On Sat, 2013-02-16 at 08:18 +0100, Henk-Jan van Tuyl wrote:
> > Anyone have any idea if the Cabal library exposes this
> > somewhere?
> 
> See...

I blogged about my solution using Krzysztof and Henk's suggestions here:
http://blogs.operationaldynamics.com/andrew/software/haskell/config-dot-h-and-ifdef

Cheers everyone,

AfC
Sydney

_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe <at> haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe
Dan Cross | 25 Feb 06:28 2013
Picon

Re: ifdef based on which OS you're on

On Sun, Feb 24, 2013 at 5:28 PM, Andrew Cowie <andrew <at> operationaldynamics.com> wrote:
On Sat, 2013-02-16 at 08:18 +0100, Henk-Jan van Tuyl wrote:
> > Anyone have any idea if the Cabal library exposes this
> > somewhere?
>
> See...

I blogged about my solution using Krzysztof and Henk's suggestions here:
http://blogs.operationaldynamics.com/andrew/software/haskell/config-dot-h-and-ifdef

Cheers everyone,

I read your blog post and I'm afraid I don't see the point: you write some code to tap into a pre-existing library that figures out what platform you are on so that you can write out a 'config.h' that #define's the platform you are on so that you can then use the C preprocessor to pick a particular code path via conditional compilation.  Why go to all that bother?  Why not just write code that writes out the path you want to take and link against it?

        - Dan C.
_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe <at> haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe
Andrew Cowie | 26 Feb 02:38 2013

Re: ifdef based on which OS you're on

On Mon, 2013-02-25 at 00:28 -0500, Dan Cross wrote:
> 
> Why go to all that bother?  Why not just write code that writes out
> the path you want to take and link against it?
> 

{shrug} You could do that too. 

I spent a decade doing work in Java-land, a language where by design we
*didn't* have #ifdefs. Write once, run everywhere, they said. Yeah,
right. It was a royal pain in the ass, especially when writing language
bindings to native libraries. Portability is part of it, but including
coverage (or not) of features based on whether dependencies were present
was a biggie, too. So I'm a fan.

To your point about generating code and then having only one version at
compile time, that's a fair approach too. I would choose against it only
because I'd prefer (as in this example) the relevant lines be in the
source file where they belong, rather than having three definitions of
that function somewhere else (or worse, meta).

In the case I showed it's only one #define and one code block. But in a
case where you had to make decisions across a code base, then I think
#include "config.h" would be a workable choice.

Anyway, I thought it was cool, and as figuring it out took a bit of
doing I wanted to write it up.

AfC
Sydney
Dan Cross | 15 Feb 15:18 2013
Picon

Re: ifdef based on which OS you're on

On Fri, Feb 15, 2013 at 9:05 AM, Andrew Cowie <andrew <at> operationaldynamics.com> wrote:
I've got a piece of code that looks like this:

        baselineContextSSL :: IO SSLContext
        baselineContextSSL = do
            ctx <- SSL.context
            SSL.contextSetDefaultCiphers ctx
        #if defined __MACOSX__
            SSL.contextSetVerificationMode ctx SSL.VerifyNone
        #elif defined __WIN32__
            SSL.contextSetVerificationMode ctx SSL.VerifyNone
        #else
            SSL.contextSetCADirectory ctx "/etc/ssl/certs"
            SSL.contextSetVerificationMode ctx $
                SSL.VerifyPeer True True Nothing
        #endif
            return ctx

all very nice (this being necessary because apparently the non-free
operating systems don't store their certs in a reliably discoverable
place; bummer).

That, however, is not the problem. After all, this sort of thing is what
#ifdefs are for. The problem is needing to get an appropriate symbol
based on what OS you're using defined.

I naively assumed there would be __LINUX__ and __MACOSX__ and __WIN32__
defined by GHC because, well, that's just the sort of wishful thinking
that powers the universe.

So my question is: what's an appropriate Haskell mechanism for building
code that is OS / arch  / distro specific? It's not like I have autoconf
running generating me a config.h I could #include, right?

This feels simple and an appropriate use of CPP; even the symbol names
look just about like what I would have expected; stackoverflow said so,
must be true. Just need to get the right symbol defined at build time.

Any suggestions?

Things like this have been the bane of Unix programmers for decades; the C pre-processor has always been kind of a hack, mostly because of things like #ifdef and the huge messes they create.  For more on why this is so bad from the Unix side of the house, see: http://static.usenix.org/publications/library/proceedings/sa92/spencer.pdf

A better solution is to define a standard interface called by your code and a per-system module that implements that interface and does the things you need, then simply include one for the appropriate system at compile time.  E.g., a Darwin and Win32 modules that provide a function that calls 'SSL.contextSetVerificationMode ctx SSL.VerifyNone', and some kind of Generic module that provides a function that does the rest.

        - Dan C.


_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe <at> haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe
Vincent Hanquez | 15 Feb 16:12 2013

Re: ifdef based on which OS you're on

On 02/15/2013 02:05 PM, Andrew Cowie wrote:
> all very nice (this being necessary because apparently the non-free
> operating systems don't store their certs in a reliably discoverable
> place; bummer).
>
Sorry the answer is out of topic, but this is not true.

Windows certificate and macos X certificate are stored in a reliably 
discoverable place. That openssl provide no way to get to it is a 
different story and one reason to have tls.

--

-- 
Vincent
Andrew Cowie | 16 Feb 01:51 2013

tls talking to certificate stores (was Re: ...)

On Fri, 2013-02-15 at 15:12 +0000, Vincent Hanquez wrote:

> Sorry the answer is out of topic

That's ok.

> Windows certificate and macos X certificate are stored in a reliably 
> discoverable place. That openssl provide no way to get to it is a 
> different story and one reason to have tls.

Is talking to the Windows and Mac OS certificate stores something that
you wrote for the tls library [in Haskell]? If so, is it something that
could be ported for other people to use?

[I assume we can "just look at tls's source" but I'd certainly welcome a
pointer as to where to look]

AfC
Sydney

_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe <at> haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe
Vincent Hanquez | 16 Feb 17:55 2013

Re: tls talking to certificate stores (was Re: ...)

On 02/16/2013 12:51 AM, Andrew Cowie wrote:
>
>> Windows certificate and macos X certificate are stored in a reliably
>> discoverable place. That openssl provide no way to get to it is a
>> different story and one reason to have tls.
> Is talking to the Windows and Mac OS certificate stores something that
> you wrote for the tls library [in Haskell]? If so, is it something that
> could be ported for other people to use?

It's not much but it's available in the certificate package. 
https://github.com/vincenthz/hs-certificate/tree/master/System/Certificate/X509

The mac os certificates are trivially available throught the "security" 
executable, but there's also documentation on the keychain format 
readily available.
The windows certificate implementation is not finished. The certificate 
are easy to find, however the format is slightly complicated (basically 
a dump of C like structure with ASN1 marshalled data in the dump). The 
windows certificate is sadly not finished, as no windows user of tls (if 
any) is {interested-in/know-how-to} implementing it, and as I boot 
windows once every moon ... if someone want to sponsor the feature, come 
talk to me ;)

That remind me that i've got pending patches to win32 to send ..

--

-- 
Vincent
kudah | 16 Feb 14:46 2013
Picon

Re: ifdef based on which OS you're on

> __WIN32__

use mingw32_HOST_OS
> __MACOSX__

darwin_HOST_OS

On Sat, 16 Feb 2013 01:05:13 +1100 Andrew Cowie
<andrew <at> operationaldynamics.com> wrote:

> I've got a piece of code that looks like this:
> 
>         baselineContextSSL :: IO SSLContext
>         baselineContextSSL = do
>             ctx <- SSL.context
>             SSL.contextSetDefaultCiphers ctx
>         #if defined __MACOSX__
>             SSL.contextSetVerificationMode ctx SSL.VerifyNone
>         #elif defined __WIN32__
>             SSL.contextSetVerificationMode ctx SSL.VerifyNone
>         #else
>             SSL.contextSetCADirectory ctx "/etc/ssl/certs"
>             SSL.contextSetVerificationMode ctx $
>                 SSL.VerifyPeer True True Nothing
>         #endif
>             return ctx
> 
> all very nice (this being necessary because apparently the non-free
> operating systems don't store their certs in a reliably discoverable
> place; bummer).
> 
> That, however, is not the problem. After all, this sort of thing is
> what #ifdefs are for. The problem is needing to get an appropriate
> symbol based on what OS you're using defined.
> 
> I naively assumed there would be __LINUX__ and __MACOSX__ and
> __WIN32__ defined by GHC because, well, that's just the sort of
> wishful thinking that powers the universe.
> 
> So my question is: what's an appropriate Haskell mechanism for
> building code that is OS / arch  / distro specific? It's not like I
> have autoconf running generating me a config.h I could #include,
> right?
> 
> This feels simple and an appropriate use of CPP; even the symbol names
> look just about like what I would have expected; stackoverflow said
> so, must be true. Just need to get the right symbol defined at build
> time.
> 
> Any suggestions?
> 
> AfC
> Sydney
> 
Donn Cave | 16 Feb 16:29 2013

Re: ifdef based on which OS you're on

As counterpoint to Vincent Hanquez' note about the certificate store
on MacOS & Windows, I'd like to cast some doubt on the notion that
you can reliably find the cert store here on Linux or the *BSDs.

So, if my experience with platforms like that is any guide, you'd
rather not "hard code" this value in any case.  I suppose that means
application needs a configuration file.

>>         #else
>>             SSL.contextSetCADirectory ctx "/etc/ssl/certs"
>>             SSL.contextSetVerificationMode ctx $
>>                 SSL.VerifyPeer True True Nothing
>>         #endif

On the bright side, a configuration file makes operational parameters
like this very transparent for a sys admin who needs to work with
it but wasn't in on the original install.  Assuming the config file
is easy to find in the first place.

	Donn
Doug McIlroy | 17 Feb 21:20 2013

Re: ifdef based on which OS you're on

With apologies for prolonging a tangential topic, I'd like to
sharpen anti-ifdef comments that have been posted already.

1. An ifdef for portability is an admission of nonportability.

    What it does is point out a nonportability--a useful crutch
    for maintainers, but a crutch nonetheless.

2. Ifdefs violate program structure.

    All ifdefs appear at top level. Yet, save for those that control
    top-level declarations, they embody conditionals at inner levels
    of structure.

Doug McIlroy

Gmane