The use of version(...) in D has the potential for some very elegant portable code design. However, from most of the libraries I have seen, it is abused and misused turning it into a portability nightmare.

http://dsource.org/projects/dmd/browser/trunk/src/mars.c#L313 defines the following versions: Windows, Posix, linux, OSX, darwin, FreeBSD and Solaris.

http://dgcc.svn.sourceforge.net/viewvc/dgcc/trunk/d/target-ver-syms.sh?view=markup defines aix, unix, cygwin, darwin, freebsd, Win32, skyos, solaris, freebsd (and others).

The problem I run into is the assumption that linux == unix/posix. This assumption is not correct.

The use of version(linux) should be limited to code that:

1. Declares externals from sys/*.h
2. Accesses /proc or /sys (or other Linux specific pseudo filesystems)
3. Things that interface directly with the dynamic linker (eg. linking against libdl)
4. Other things that are linux specific....

Anything that accesses standard libc functions, standard unix semantics (eg. signals, shm, etc) should use version(Posix) or version(unix).

Build systems and scripts that are designed to run on unix machines should not assume the locations of libraries and binaries, and refer to posix standards for their locations. For example, bash in /bin/bash or the assumption of the existence of bash at all. If you need a shell script, try writing it with plain bourne syntax without all of the bash extensions to the shell, and use /bin/sh. Also avoid using the GNU extensions to standard tools (sed and awk for example). If you really want to do something fancy, do it in D and use the appropriate {g,l}dmd -run command.

A few things to keep in mind about linux systems vs. pretty much all other unix systems:

Linux is a kernel. The userspace stuff you use (your shell, your libc, etc) is (typically) GNU, and not Linux. On other unix systems, the kernel is tightly linked to the libc and other standard libraries, and the other base applications (shell, login, sed, awk, etc) are often part of the base system and not GNU (this is not always true, as some systems use GNU tools as part of the base system as well).

If you are writing a wrapper around something, and it is a library in Linux, it most likely is also a library in other unix machines. This includes opengl, image libraries, X11 libraries, sound & media libraries, etc. If you require an external library, please state as much in the documentation and don't hide it in a version(linux) statement because you just abused the reason for version(...) to exist in the first place.

Other tips:
- Don't use the /proc filesystem unless you really must. If you do, abstract the interface and implement a Linux specific interface. This will ease porting (I'd be happy to come in and do FreeBSD stuff where possible). - If you are unsure, check http://www.freebsd.org/cgi/man.cgi This interface can look up the manual pages for multiple OSes, and the FreeBSD versions of the manuals are very consistent. Some of the other ones will also give hints on bugs and subtle differences for different implementations. - If you want to make something work under FreeBSD or other OSes, post on the NG (or for FreeBSD, bug me directly). - Linux programs need to be linked against libdl for access to dlopen() and family, most unix OSes have access to dlopen() from libc (I think this is partially due to the tight libc/kernel coupling in most unix OSes). - Darwin/OSX & FreeBSD all share alot of similar kernel interfaces, specifically most of the process model, network stack and virtual filesystem layers. OSX even has kqueue! (although slightly different then FreeBSD). - FreeBSD & Solaris share some common ancestry. Although the similarities are not very important to application developers, internal kernel interfaces and designs are similar. - The GNU tools typically conform to standards, but add extra extensions everywhere. If you write your scripts for a standard bourne shell rather then bash, bash will still be able to run it most of the time. Personally the GNU extensions to everything feels like a move Microsoft would do, just breaking enough compatibility to create vendor lock in.

Thanks,
Travis

Reply via email to