On 2011-12-01 18:49, Dmitry Samersoff wrote:
We have at least three options:

1. #ifdef  -
        pro we can slowly migrate from
           #ifdef OpenBSD to #ifdef HAVE_MAD_LINKER
        cons it pollutes code and doesn't cover all cases.

2. Dir structure
      unix/generic
           bsd/generic
              /OpenBSD
       etc

       pro -  well understandable
       cons - still not cover all cases

It might be useful to combine the two techniques. For small differences, a few lines at most, #ifdefs can work fine. If the differences are larger it might warrant putting them in a separate, platform-specific file. One one hand, it means that there is no clear-cut way of deciding how to handle platform-dependent code, so we must rely on rules of thumb and some subjectivity in deciding how to handle each case. On the other hand, it gives us much more flexibility and is likely to improve both reading and writing code, instead of having to strictly follow a system, possibly resulting in either large portions of the code #ifdeffed away for different platforms, or creation of small and trivial files with possible code duplication.

And now for a slight disgression:

As for the #ifdef CAPABILITY idea that are popular every now and then, I'm a bit sceptical. The problem is: what is a good level to determine a "capability"? In one extreme, you can imagine designing an #ifdef for every possible function call or type definition that can (possibly) be different between platforms. That would be so unpractical that it would be unusable.

So, then you start thinking that you can group several different functions into a single category. Say, "if you have pthread_create then you also have pthread_exit, and a whole bunch of other functions -- let's call this the PTHREAD capability". I imagine this is what people think of when they say "capabilities".

There are two problems with this. First, it's not clear when to stop this grouping if you continue upwards. If you have pthread capabilities, then you most likely also have full posix capabilities. So why test on pthread and not on posix? And in the end, we'll probably end up with a few bunch of groups which are basically mapping to the major operation systems/architectures we support -- that is, the very same kind of grouping that capabilities advocates want to move away from.

The second problem is that many times the devil is in the details. Most unix-like OSes have "more or less" posix, but with certain, often quite small, idiosyncratic differences. Once again, we can add "capabilities" for these exceptions like SYSTEM_CALL_FOO_RETURNS_ZERO_ON_SUCCESS for each and everyone of them. Or, we can start grouping them, once again probably ending up with USE_LINUX_PECULIARITIES.

I appreciate that there are situations where a specific subset of unix-like OSes do things one way, and other subsets another way, leading to code like:
#if defined(SOLARIS) || defined(BSD)
#elif defined(LINUX) || defined(AIX)
#endif

... which is acceptable (but not nice) in #ifdefs, but hard to find a good solution to when using separate files.

It might be possible, in these cases, to find proper grouping of capabilities that fits these actual use cases and test for these capability groups instead. And it might be possible to actually agree on a name on those capability gorups that doesn't suck. :-) And the end result might get better than testing explicitely for platforms. But I'm not convinced. And I think this should be used only when it is really motivated, and not as part of a general effort to "replace OS testing with capabilities testing".

/Magnus

Reply via email to