FreeBSD Porter's Handbook
Prev | Chapter 12 Dos and Don'ts | Next

# 12.4 Differentiating operating systems and OS versions

You may come across code that needs modifications or conditional compilation based upon what version of Unix it is running under. If you need to make such changes to the code for conditional compilation, make sure you make the changes as general as possible so that we can back-port code to older FreeBSD systems and cross-port to other BSD systems such as 4.4BSD from CSRG, BSD/386, 386BSD, NetBSD, and OpenBSD.

The preferred way to tell 4.3BSD/Reno (1990) and newer versions of the BSD code apart is by using the `BSD` macro defined in sys/param.h. Hopefully that file is already included; if not, add the code:

    #if (defined(__unix__) || defined(unix)) && !defined(USG)
    #include <sys/param.h>
    #endif

to the proper place in the `.c` file. We believe that every system that defines these two symbols has `sys/param.h`. If you find a system that does not, we would like to know. Please send mail to the FreeBSD ports 郵遞論壇.

Another way is to use the GNU Autoconf style of doing this:

    #ifdef HAVE_SYS_PARAM_H
    #include <sys/param.h>
    #endif

Do not forget to add `-DHAVE_SYS_PARAM_H` to the `CFLAGS` in the `Makefile` for this method.

Once you have `sys/param.h` included, you may use:

    #if (defined(BSD) && (BSD >= 199103))

to detect if the code is being compiled on a 4.3 Net2 code base or newer (e.g. FreeBSD 1.x, 4.3/Reno, NetBSD 0.9, 386BSD, BSD/386 1.1 and below).

Use:

    #if (defined(BSD) && (BSD >= 199306))

to detect if the code is being compiled on a 4.4 code base or newer (e.g. FreeBSD 2.x, 4.4, NetBSD 1.0, BSD/386 2.0 or above).

The value of the `BSD` macro is `199506` for the 4.4BSD-Lite2 code base. This is stated for informational purposes only. It should not be used to distinguish between versions of FreeBSD based only on 4.4-Lite vs. versions that have merged in changes from 4.4-Lite2. The `__FreeBSD__` macro should be used instead.

Use sparingly:

- `__FreeBSD__` is defined in all versions of FreeBSD. Use it if the change you are making only affects FreeBSD. Porting gotchas like the use of `sys_errlist[]` vs `strerror()` are Berkeley-isms, not FreeBSD changes.

- In FreeBSD 2.x, `__FreeBSD__` is defined to be `2`. In earlier versions, it is `1`. Later versions always bump it to match their major version number.

- If you need to tell the difference between a FreeBSD 1.x system and a FreeBSD 2.x or above system, usually the right answer is to use the `BSD` macros described above. If there actually is a FreeBSD specific change (such as special shared library options when using `ld`) then it is OK to use `__FreeBSD__` and `#if __FreeBSD__ > 1` to detect a FreeBSD 2.x and later system. If you need more granularity in detecting FreeBSD systems since 2.0-RELEASE you can use the following:

      #if __FreeBSD__ >= 2
      #include <osreldate.h>
      #    if __FreeBSD_version >= 199504
           /* 2.0.5+ release specific code here */
      #    endif
      #endif

In the hundreds of ports that have been done, there have only been one or two cases where `__FreeBSD__` should have been used. Just because an earlier port screwed up and used it in the wrong place does not mean you should do so too.

Prev | Home | Next
`WRKDIRPREFIX` | Up | FreeBSD 版本速查表(__FreeBSD_version)

For questions about the FreeBSD ports system, e-mail <ports@FreeBSD.org>.
For questions about this documentation, e-mail <doc@FreeBSD.org>.