[cs631apue] Cross-OS compatibility question

Jan Schaumann jschauma at stevens.edu
Mon Sep 2 15:24:44 EDT 2019


Elliot Wasem <ewasem at stevens.edu> wrote:
 
> I've been playing around with writing code that is
> trivially portable between Linux and NetBSD.

That's a useful exercise, and we will discuss some of
those aspects in future lectures.

Portability may require accomodating not just
different headers or conditionally include code in
your sources, but may also require you to account for
the difference in the compiler or the build chain (as
you noticed here).

As noted earlier, the reference platform will be
NetBSD, so adding support for other platforms is
something that you may, but do not need to do.

Having said that...

> I realized that 'setprogname(...)' is only available
> in BSD's <stdlib.h>, and so on Linux, I needed to
> include <bsd/stdlib.h> in my code iff on a Linux
> system.

To conditionally include code in your source files,
use the '#ifdef' macro.  Different constants are
defined for you by default on the platform on which
you're building your code.  You can view the default
values by e.g., running

cc -E -dM - </dev/null | more

To conditionally include code only on Linux systems,
you'd then use

#ifdef __linux__
#include <bsd/stdlib.h>
#endif

> Now, it seems that NetBSD's Make does not play well
> with the GNU way of creating makefiles (i.e.
> conditional blocks in the makefile), however 'gmake'
> on NetBSD works fine.

Well, 'gmake' works fine on NetBSD if it was
installed.  Out of the box, your reference system
should not have a 'gmake' installed anywhere.  So your
Makefile will need to be made to work with the default
BSD make.

Like other tools, 'make' has diverged over the years
as well, and as so often, the GNU tools support
options either that are not supported on other
platforms at all or are supported differently.

BSD make(1) does have support for conditional variable
assignment, but it uses a different syntax from GNU
make(1) ('.if' vs. e.g. 'ifeq').  But creating a
platform-specific Makefile then doesn't provide real
portability, and you'd have to ship different Makefile
for the different target platforms etc.

Instead, it'd be best to write a Makefile that works
on all of your target platforms.  To do that, you can
use shell-conditionals in the variable assignment.

The following Makefile snippet should help get you on
the right track:

---- 8< ----- 8< -----

UNAME = $$(uname -s)

EXTRA_LDFLAGS = $$(if [ x"${UNAME}" = x"Linux" ]; then echo "-lbsd"; fi)

all:
        @echo "Platform is: ${UNAME}"
        @echo "${CC} ${CFLAGS} ${EXTRA_LDFLAGS}"

---- 8< ----- 8< -----

(There are other ways to do this as well.  Play around
with some of the ways that variables might be assigned
and how commands might be executed and see whether
there are functional differences or performance
reasons why one might want to do things one way over
the other.)

As I said, we'll discuss make(1) and portability of
code in more detail in future lectures, but hopefully
the above is enough to answer your question.

-Jan


More information about the cs631apue mailing list